yann300
10 years ago
193 changed files with 9740 additions and 6433 deletions
@ -1,36 +1,31 @@ |
|||
FROM ubuntu:14.04 |
|||
FROM ubuntu:utopic |
|||
MAINTAINER caktux |
|||
|
|||
ENV DEBIAN_FRONTEND noninteractive |
|||
|
|||
# Usual update / upgrade |
|||
RUN apt-get update |
|||
RUN apt-get upgrade -y |
|||
RUN apt-get upgrade -q -y |
|||
RUN apt-get dist-upgrade -q -y |
|||
|
|||
# Ethereum dependencies |
|||
RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget |
|||
RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons |
|||
RUN apt-get install -qy libjsoncpp-dev libargtable2-dev |
|||
RUN apt-get install -qy libncurses5-dev libcurl4-openssl-dev wget |
|||
RUN apt-get install -qy libjsoncpp-dev libargtable2-dev libmicrohttpd-dev |
|||
# Let our containers upgrade themselves |
|||
RUN apt-get install -q -y unattended-upgrades |
|||
|
|||
# Ethereum PPA |
|||
RUN apt-get install -qy software-properties-common |
|||
# Install Ethereum |
|||
RUN apt-get install -q -y software-properties-common |
|||
RUN add-apt-repository ppa:ethereum/ethereum |
|||
RUN add-apt-repository ppa:ethereum/ethereum-dev |
|||
RUN apt-get update |
|||
RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev |
|||
RUN apt-get install -q -y eth |
|||
|
|||
# LLVM-3.5 |
|||
RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add - |
|||
RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main\ndeb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main" > /etc/apt/sources.list.d/llvm-trusty.list |
|||
RUN apt-get update |
|||
RUN apt-get install -qy llvm-3.5 libedit-dev |
|||
# Install supervisor |
|||
RUN apt-get install -q -y supervisor |
|||
|
|||
# Fix llvm-3.5 cmake paths |
|||
RUN mkdir -p /usr/lib/llvm-3.5/share/llvm && ln -s /usr/share/llvm-3.5/cmake /usr/lib/llvm-3.5/share/llvm/cmake |
|||
# Add supervisor configs |
|||
ADD supervisord.conf supervisord.conf |
|||
|
|||
# Build Ethereum (HEADLESS) |
|||
RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum |
|||
RUN mkdir -p cpp-ethereum/build |
|||
RUN cd cpp-ethereum/build && cmake .. -DHEADLESS=1 -DLLVM_DIR=/usr/share/llvm-3.5/cmake -DEVMJIT=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install |
|||
RUN ldconfig |
|||
EXPOSE 8080 |
|||
EXPOSE 30303 |
|||
|
|||
ENTRYPOINT ["/usr/local/bin/eth"] |
|||
CMD ["-n", "-c", "/supervisord.conf"] |
|||
ENTRYPOINT ["/usr/bin/supervisord"] |
|||
|
@ -1,17 +1,30 @@ |
|||
# Dockerfile for cpp-ethereum |
|||
Dockerfile to build a bleeding edge cpp-ethereum docker image from source |
|||
|
|||
docker build -t cppeth < Dockerfile |
|||
### Quick usage |
|||
|
|||
Run a simple peer server |
|||
docker run -d ethereum/client-cpp |
|||
|
|||
docker run -i cppeth -m off -o peer -x 256 |
|||
### Building |
|||
|
|||
GUI is compiled but not exposed. You can mount /cpp-ethereum/build to access binaries: |
|||
Dockerfile to build a cpp-ethereum docker image from source |
|||
|
|||
cid = $(docker run -i -v /cpp-ethereum/build cppeth -m off -o peer -x 256) |
|||
docker inspect $cid # <-- Find volume path in JSON output |
|||
docker build -t cpp-ethereum . |
|||
|
|||
You may also modify the Docker image to run the GUI and expose a |
|||
ssh/VNC server in order to tunnel an X11 or VNC session. |
|||
### Running |
|||
|
|||
docker run -d cpp-ethereum |
|||
|
|||
### Usage |
|||
|
|||
First enter the container: |
|||
|
|||
docker exec -it <container name> bash |
|||
|
|||
Inspect logs: |
|||
|
|||
cat /var/log/cpp-ethereum.log |
|||
cat /var/log/cpp-ethereum.err |
|||
|
|||
Restart supervisor service: |
|||
|
|||
supervisorctl restart cpp-ethereum |
|||
|
@ -0,0 +1,23 @@ |
|||
[supervisord] |
|||
nodaemon=false |
|||
|
|||
[program:eth] |
|||
priority=30 |
|||
directory=/ |
|||
command=eth --bootstrap --json-rpc |
|||
user=root |
|||
autostart=true |
|||
autorestart=true |
|||
startsecs=10 |
|||
stopsignal=QUIT |
|||
stdout_logfile=/var/log/eth.log |
|||
stderr_logfile=/var/log/eth.err |
|||
|
|||
[unix_http_server] |
|||
file=%(here)s/supervisor.sock |
|||
|
|||
[supervisorctl] |
|||
serverurl=unix://%(here)s/supervisor.sock |
|||
|
|||
[rpcinterface:supervisor] |
|||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface |
@ -0,0 +1,41 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
set(CMAKE_AUTOMOC OFF) |
|||
|
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(BEFORE ..) |
|||
include_directories(${Boost_INCLUDE_DIRS}) |
|||
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) |
|||
|
|||
set(EXECUTABLE ethminer) |
|||
|
|||
file(GLOB HEADERS "*.h") |
|||
|
|||
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) |
|||
|
|||
add_dependencies(${EXECUTABLE} BuildInfo.h) |
|||
|
|||
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) |
|||
|
|||
if (READLINE_FOUND) |
|||
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) |
|||
endif() |
|||
|
|||
if (JSONRPC) |
|||
target_link_libraries(${EXECUTABLE} web3jsonrpc) |
|||
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES}) |
|||
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) |
|||
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) |
|||
eth_copy_dlls(${EXECUTABLE} CURL_DLLS) |
|||
endif() |
|||
endif() |
|||
|
|||
target_link_libraries(${EXECUTABLE} webthree) |
|||
target_link_libraries(${EXECUTABLE} ethash) |
|||
|
|||
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) |
|||
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) |
|||
endif() |
|||
|
|||
install( TARGETS ${EXECUTABLE} DESTINATION bin ) |
|||
|
@ -0,0 +1,39 @@ |
|||
/**
|
|||
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! |
|||
*/ |
|||
|
|||
#ifndef JSONRPC_CPP_STUB_FARM_H_ |
|||
#define JSONRPC_CPP_STUB_FARM_H_ |
|||
|
|||
#include <jsonrpccpp/client.h> |
|||
|
|||
class Farm : public jsonrpc::Client |
|||
{ |
|||
public: |
|||
Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} |
|||
|
|||
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException) |
|||
{ |
|||
Json::Value p; |
|||
p = Json::nullValue; |
|||
Json::Value result = this->CallMethod("eth_getWork",p); |
|||
if (result.isArray()) |
|||
return result; |
|||
else |
|||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
|||
} |
|||
bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) |
|||
{ |
|||
Json::Value p; |
|||
p.append(param1); |
|||
p.append(param2); |
|||
p.append(param3); |
|||
Json::Value result = this->CallMethod("eth_submitWork",p); |
|||
if (result.isBool()) |
|||
return result.asBool(); |
|||
else |
|||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
|||
} |
|||
}; |
|||
|
|||
#endif //JSONRPC_CPP_STUB_FARM_H_
|
@ -0,0 +1,28 @@ |
|||
/**
|
|||
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! |
|||
*/ |
|||
|
|||
#ifndef JSONRPC_CPP_STUB_PHONEHOME_H_ |
|||
#define JSONRPC_CPP_STUB_PHONEHOME_H_ |
|||
|
|||
#include <jsonrpccpp/client.h> |
|||
|
|||
class PhoneHome : public jsonrpc::Client |
|||
{ |
|||
public: |
|||
PhoneHome(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} |
|||
|
|||
int report_benchmark(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException) |
|||
{ |
|||
Json::Value p; |
|||
p.append(param1); |
|||
p.append(param2); |
|||
Json::Value result = this->CallMethod("report_benchmark",p); |
|||
if (result.isInt()) |
|||
return result.asInt(); |
|||
else |
|||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
|||
} |
|||
}; |
|||
|
|||
#endif //JSONRPC_CPP_STUB_PHONEHOME_H_
|
@ -0,0 +1,4 @@ |
|||
[ |
|||
{ "name": "eth_getWork", "params": [], "order": [], "returns": []}, |
|||
{ "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true} |
|||
] |
@ -0,0 +1,483 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file main.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
* Ethereum client. |
|||
*/ |
|||
|
|||
#include <thread> |
|||
#include <chrono> |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <signal.h> |
|||
|
|||
#include <boost/algorithm/string.hpp> |
|||
#include <boost/algorithm/string/trim_all.hpp> |
|||
|
|||
#include <libdevcrypto/FileSystem.h> |
|||
#include <libevmcore/Instruction.h> |
|||
#include <libdevcore/StructuredLogger.h> |
|||
#include <libethcore/ProofOfWork.h> |
|||
#include <libethcore/EthashAux.h> |
|||
#include <libevm/VM.h> |
|||
#include <libevm/VMFactory.h> |
|||
#include <libethereum/All.h> |
|||
#include <libwebthree/WebThree.h> |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
#include <libweb3jsonrpc/WebThreeStubServer.h> |
|||
#include <jsonrpccpp/server/connectors/httpserver.h> |
|||
#include <jsonrpccpp/client/connectors/httpclient.h> |
|||
#endif |
|||
#include "BuildInfo.h" |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
#include "PhoneHome.h" |
|||
#include "Farm.h" |
|||
#endif |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::p2p; |
|||
using namespace dev::eth; |
|||
using namespace boost::algorithm; |
|||
using dev::eth::Instruction; |
|||
|
|||
#undef RETURN |
|||
|
|||
bool isTrue(std::string const& _m) |
|||
{ |
|||
return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; |
|||
} |
|||
|
|||
bool isFalse(std::string const& _m) |
|||
{ |
|||
return _m == "off" || _m == "no" || _m == "false" || _m == "0"; |
|||
} |
|||
|
|||
void help() |
|||
{ |
|||
cout |
|||
<< "Usage ethminer [OPTIONS]" << endl |
|||
<< "Options:" << endl << endl |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
<< "Work farming mode:" << endl |
|||
<< " -F,--farm <url> Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8080)" << endl |
|||
<< " --farm-recheck <n> Leave n ms between checks for changed work (default: 500)." << endl |
|||
#endif |
|||
<< "Benchmarking mode:" << endl |
|||
<< " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl |
|||
<< " --benchmark-warmup <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl |
|||
<< " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl |
|||
<< " --benchmark-trials <n> Set the duration of warmup for the benchmark tests (default: 5)." << endl |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
<< " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl |
|||
#endif |
|||
<< "DAG creation mode:" << endl |
|||
<< " -D,--create-dag <number> Create the DAG in preparation for mining on given block and exit." << endl |
|||
<< "General Options:" << endl |
|||
<< " -C,--cpu When mining, use the CPU." << endl |
|||
<< " -G,--opencl When mining use the GPU via OpenCL." << endl |
|||
<< " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl |
|||
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl |
|||
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl |
|||
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl |
|||
<< " -V,--version Show the version and exit." << endl |
|||
<< " -h,--help Show this help message and exit." << endl |
|||
; |
|||
exit(0); |
|||
} |
|||
|
|||
string credits() |
|||
{ |
|||
std::ostringstream cout; |
|||
cout |
|||
<< "Ethereum (++) " << dev::Version << endl |
|||
<< " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl |
|||
<< " Based on a design by Vitalik Buterin." << endl << endl; |
|||
return cout.str(); |
|||
} |
|||
|
|||
void version() |
|||
{ |
|||
cout << "eth version " << dev::Version << endl; |
|||
cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl; |
|||
cout << "Client database version: " << dev::eth::c_databaseVersion << endl; |
|||
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; |
|||
exit(0); |
|||
} |
|||
|
|||
void doInitDAG(unsigned _n) |
|||
{ |
|||
BlockInfo bi; |
|||
bi.number = _n; |
|||
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; |
|||
Ethash::prep(bi); |
|||
exit(0); |
|||
} |
|||
|
|||
enum class OperationMode |
|||
{ |
|||
DAGInit, |
|||
Benchmark, |
|||
Farm |
|||
}; |
|||
|
|||
enum class MinerType |
|||
{ |
|||
CPU, |
|||
GPU |
|||
}; |
|||
|
|||
void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) |
|||
{ |
|||
BlockInfo genesis = CanonBlockChain::genesis(); |
|||
genesis.difficulty = 1 << 18; |
|||
cdebug << genesis.boundary(); |
|||
|
|||
GenericFarm<Ethash> f; |
|||
f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); |
|||
|
|||
string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; |
|||
cout << "Benchmarking on platform: " << platformInfo << endl; |
|||
|
|||
cout << "Preparing DAG..." << endl; |
|||
Ethash::prep(genesis); |
|||
|
|||
genesis.difficulty = u256(1) << 63; |
|||
genesis.noteDirty(); |
|||
f.setWork(genesis); |
|||
if (_m == MinerType::CPU) |
|||
f.startCPU(); |
|||
else if (_m == MinerType::GPU) |
|||
f.startGPU(); |
|||
|
|||
map<uint64_t, MiningProgress> results; |
|||
uint64_t mean = 0; |
|||
uint64_t innerMean = 0; |
|||
for (unsigned i = 0; i <= _trials; ++i) |
|||
{ |
|||
if (!i) |
|||
cout << "Warming up..." << endl; |
|||
else |
|||
cout << "Trial " << i << "... " << flush; |
|||
this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); |
|||
|
|||
auto mp = f.miningProgress(); |
|||
f.resetMiningProgress(); |
|||
if (!i) |
|||
continue; |
|||
auto rate = mp.rate(); |
|||
|
|||
cout << rate << endl; |
|||
results[rate] = mp; |
|||
mean += rate; |
|||
if (i > 1 && i < 5) |
|||
innerMean += rate; |
|||
} |
|||
f.stop(); |
|||
cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; |
|||
cout << "inner mean: " << (innerMean / (_trials - 2)) << " H/s" << endl; |
|||
|
|||
(void)_phoneHome; |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
if (_phoneHome) |
|||
{ |
|||
cout << "Phoning home to find world ranking..." << endl; |
|||
jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); |
|||
PhoneHome rpc(client); |
|||
try |
|||
{ |
|||
unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); |
|||
cout << "Ranked: " << ranking << " of all benchmarks." << endl; |
|||
} |
|||
catch (...) |
|||
{ |
|||
cout << "Error phoning home. ET is sad." << endl; |
|||
} |
|||
} |
|||
#endif |
|||
exit(0); |
|||
} |
|||
|
|||
struct HappyChannel: public LogChannel { static const char* name() { return ":-D"; } static const int verbosity = 1; }; |
|||
struct SadChannel: public LogChannel { static const char* name() { return ":-("; } static const int verbosity = 1; }; |
|||
|
|||
void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) |
|||
{ |
|||
(void)_m; |
|||
(void)_remote; |
|||
(void)_recheckPeriod; |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
jsonrpc::HttpClient client(_remote); |
|||
Farm rpc(client); |
|||
GenericFarm<Ethash> f; |
|||
if (_m == MinerType::CPU) |
|||
f.startCPU(); |
|||
else if (_m == MinerType::GPU) |
|||
f.startGPU(); |
|||
|
|||
ProofOfWork::WorkPackage current; |
|||
while (true) |
|||
try |
|||
{ |
|||
bool completed = false; |
|||
ProofOfWork::Solution solution; |
|||
f.onSolutionFound([&](ProofOfWork::Solution sol) |
|||
{ |
|||
solution = sol; |
|||
return completed = true; |
|||
}); |
|||
for (unsigned i = 0; !completed; ++i) |
|||
{ |
|||
if (current) |
|||
cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); |
|||
else |
|||
cnote << "Getting work package..."; |
|||
Json::Value v = rpc.eth_getWork(); |
|||
h256 hh(v[0].asString()); |
|||
if (hh != current.headerHash) |
|||
{ |
|||
current.headerHash = hh; |
|||
current.seedHash = h256(v[1].asString()); |
|||
current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); |
|||
cnote << "Got work package:" << current.headerHash << " < " << current.boundary; |
|||
f.setWork(current); |
|||
} |
|||
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); |
|||
} |
|||
cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "..."; |
|||
bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); |
|||
if (ok) |
|||
clog(HappyChannel) << "Submitted and accepted."; |
|||
else |
|||
clog(SadChannel) << "Not accepted."; |
|||
current.reset(); |
|||
} |
|||
catch (jsonrpc::JsonRpcException&) |
|||
{ |
|||
for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) |
|||
cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; |
|||
cerr << endl; |
|||
} |
|||
#endif |
|||
exit(0); |
|||
} |
|||
|
|||
int main(int argc, char** argv) |
|||
{ |
|||
// Init defaults
|
|||
Defaults::get(); |
|||
|
|||
/// Operating mode.
|
|||
OperationMode mode = OperationMode::Farm; |
|||
|
|||
/// Mining options
|
|||
MinerType minerType = MinerType::CPU; |
|||
unsigned openclPlatform = 0; |
|||
unsigned openclDevice = 0; |
|||
unsigned miningThreads = UINT_MAX; |
|||
|
|||
/// DAG initialisation param.
|
|||
unsigned initDAG = 0; |
|||
|
|||
/// Benchmarking params
|
|||
bool phoneHome = true; |
|||
unsigned benchmarkWarmup = 3; |
|||
unsigned benchmarkTrial = 3; |
|||
unsigned benchmarkTrials = 5; |
|||
|
|||
/// Farm params
|
|||
string farmURL = "http://127.0.0.1:8080"; |
|||
unsigned farmRecheckPeriod = 500; |
|||
|
|||
for (int i = 1; i < argc; ++i) |
|||
{ |
|||
string arg = argv[i]; |
|||
if ((arg == "-F" || arg == "--farm") && i + 1 < argc) |
|||
{ |
|||
mode = OperationMode::Farm; |
|||
farmURL = argv[++i]; |
|||
} |
|||
else if (arg == "--farm-recheck" && i + 1 < argc) |
|||
try { |
|||
farmRecheckPeriod = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
else if (arg == "--opencl-platform" && i + 1 < argc) |
|||
try { |
|||
openclPlatform = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
else if (arg == "--opencl-device" && i + 1 < argc) |
|||
try { |
|||
openclDevice = stol(argv[++i]); |
|||
miningThreads = 1; |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
else if (arg == "--phone-home" && i + 1 < argc) |
|||
{ |
|||
string m = argv[++i]; |
|||
if (isTrue(m)) |
|||
phoneHome = true; |
|||
else if (isFalse(m)) |
|||
phoneHome = false; |
|||
else |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << m << endl; |
|||
return -1; |
|||
} |
|||
} |
|||
else if (arg == "--benchmark-warmup" && i + 1 < argc) |
|||
try { |
|||
benchmarkWarmup = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
else if (arg == "--benchmark-trial" && i + 1 < argc) |
|||
try { |
|||
benchmarkTrial = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
else if (arg == "--benchmark-trials" && i + 1 < argc) |
|||
try { |
|||
benchmarkTrials = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
else if (arg == "-C" || arg == "--cpu") |
|||
minerType = MinerType::CPU; |
|||
else if (arg == "-G" || arg == "--opencl") |
|||
minerType = MinerType::GPU; |
|||
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) |
|||
{ |
|||
string m = boost::to_lower_copy(string(argv[++i])); |
|||
mode = OperationMode::DAGInit; |
|||
try |
|||
{ |
|||
initDAG = stol(m); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << m << endl; |
|||
return -1; |
|||
} |
|||
} |
|||
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) |
|||
{ |
|||
string m; |
|||
try |
|||
{ |
|||
BlockInfo bi; |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
h256 powHash(m); |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
h256 seedHash; |
|||
if (m.size() == 64 || m.size() == 66) |
|||
seedHash = h256(m); |
|||
else |
|||
seedHash = EthashAux::seedHash(stol(m)); |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
bi.difficulty = u256(m); |
|||
auto boundary = bi.boundary(); |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
bi.nonce = h64(m); |
|||
auto r = EthashAux::eval(seedHash, powHash, bi.nonce); |
|||
bool valid = r.value < boundary; |
|||
cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; |
|||
cout << r.value << (valid ? " < " : " >= ") << boundary << endl; |
|||
cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; |
|||
cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; |
|||
cout << " with seed as " << seedHash << endl; |
|||
if (valid) |
|||
cout << "(mixHash = " << r.mixHash << ")" << endl; |
|||
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl; |
|||
exit(0); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << m << endl; |
|||
return -1; |
|||
} |
|||
} |
|||
else if (arg == "-M" || arg == "--benchmark") |
|||
mode = OperationMode::Benchmark; |
|||
else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) |
|||
{ |
|||
try { |
|||
miningThreads = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
return -1; |
|||
} |
|||
} |
|||
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) |
|||
g_logVerbosity = atoi(argv[++i]); |
|||
else if (arg == "-h" || arg == "--help") |
|||
help(); |
|||
else if (arg == "-V" || arg == "--version") |
|||
version(); |
|||
else |
|||
{ |
|||
cerr << "Invalid argument: " << arg << endl; |
|||
exit(-1); |
|||
} |
|||
} |
|||
|
|||
if (minerType == MinerType::CPU) |
|||
ProofOfWork::CPUMiner::setNumInstances(miningThreads); |
|||
else if (minerType == MinerType::GPU) |
|||
{ |
|||
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); |
|||
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); |
|||
ProofOfWork::GPUMiner::setNumInstances(miningThreads); |
|||
} |
|||
|
|||
if (mode == OperationMode::DAGInit) |
|||
doInitDAG(initDAG); |
|||
|
|||
if (mode == OperationMode::Benchmark) |
|||
doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); |
|||
|
|||
if (mode == OperationMode::Farm) |
|||
doFarm(minerType, farmURL, farmRecheckPeriod); |
|||
|
|||
return 0; |
|||
} |
|||
|
@ -0,0 +1,3 @@ |
|||
[ |
|||
{ "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 } |
|||
] |
@ -0,0 +1,158 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file ICAP.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "ICAP.h" |
|||
#include <boost/algorithm/string/case_conv.hpp> |
|||
#include <boost/algorithm/string.hpp> |
|||
#include <libdevcore/Base64.h> |
|||
#include <libdevcrypto/SHA3.h> |
|||
#include "Exceptions.h" |
|||
#include "ABI.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
string ICAP::iban(std::string _c, std::string _d) |
|||
{ |
|||
boost::to_upper(_c); |
|||
boost::to_upper(_d); |
|||
auto totStr = _d + _c + "00"; |
|||
bigint tot = 0; |
|||
for (char x: totStr) |
|||
if (x >= 'A') |
|||
tot = tot * 100 + x - 'A' + 10; |
|||
else |
|||
tot = tot * 10 + x - '0'; |
|||
unsigned check = (unsigned)(u256)(98 - tot % 97); |
|||
ostringstream out; |
|||
out << _c << setfill('0') << setw(2) << check << _d; |
|||
return out.str(); |
|||
} |
|||
|
|||
std::pair<string, string> ICAP::fromIBAN(std::string _iban) |
|||
{ |
|||
if (_iban.size() < 4) |
|||
return std::make_pair(string(), string()); |
|||
boost::to_upper(_iban); |
|||
std::string c = _iban.substr(0, 2); |
|||
std::string d = _iban.substr(4); |
|||
if (iban(c, d) != _iban) |
|||
return std::make_pair(string(), string()); |
|||
return make_pair(c, d); |
|||
} |
|||
|
|||
ICAP ICAP::decoded(std::string const& _encoded) |
|||
{ |
|||
ICAP ret; |
|||
std::string country; |
|||
std::string data; |
|||
std::tie(country, data) = fromIBAN(_encoded); |
|||
if (country != "XE") |
|||
throw InvalidICAP(); |
|||
if (data.size() == 30) |
|||
{ |
|||
ret.m_type = Direct; |
|||
// Direct ICAP
|
|||
ret.m_direct = fromBase36<Address::size>(data); |
|||
} |
|||
else if (data.size() == 16) |
|||
{ |
|||
ret.m_type = Indirect; |
|||
ret.m_asset = data.substr(0, 3); |
|||
if (ret.m_asset == "XET" || ret.m_asset == "ETH") |
|||
{ |
|||
ret.m_institution = data.substr(3, 4); |
|||
ret.m_client = data.substr(7); |
|||
} |
|||
else |
|||
throw InvalidICAP(); |
|||
} |
|||
else |
|||
throw InvalidICAP(); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
std::string ICAP::encoded() const |
|||
{ |
|||
if (m_type == Direct) |
|||
{ |
|||
if (!!m_direct[0]) |
|||
throw InvalidICAP(); |
|||
std::string d = toBase36<Address::size>(m_direct); |
|||
while (d.size() < 30) |
|||
d = "0" + d; |
|||
return iban("XE", d); |
|||
} |
|||
else if (m_type == Indirect) |
|||
{ |
|||
if ( |
|||
m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || |
|||
m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || |
|||
m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || |
|||
m_asset.size() != 3 || |
|||
(boost::to_upper_copy(m_asset) != "XET" && boost::to_upper_copy(m_asset) != "ETH") || |
|||
m_institution.size() != 4 || |
|||
m_client.size() != 9 |
|||
) |
|||
throw InvalidICAP(); |
|||
return iban("XE", m_asset + m_institution + m_client); |
|||
} |
|||
else |
|||
throw InvalidICAP(); |
|||
} |
|||
|
|||
pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const |
|||
{ |
|||
auto resolve = [&](string const& s) |
|||
{ |
|||
vector<string> ss; |
|||
boost::algorithm::split(ss, s, boost::is_any_of("/")); |
|||
Address r = _reg; |
|||
for (unsigned i = 0; i < ss.size() - 1; ++i) |
|||
r = abiOut<Address>(_call(r, abiIn("subRegistrar(bytes32)", toString32(ss[i])))); |
|||
return abiOut<Address>(_call(r, abiIn("addr(bytes32)", toString32(ss.back())))); |
|||
}; |
|||
if (m_asset == "XET") |
|||
{ |
|||
Address a = resolve(m_institution); |
|||
bytes d = abiIn("deposit(uint64)", fromBase36<8>(m_client)); |
|||
return make_pair(a, d); |
|||
} |
|||
else if (m_asset == "ETH") |
|||
{ |
|||
if (m_institution == "XREG") |
|||
return make_pair(resolve(m_client), bytes()); |
|||
else if (m_institution[0] != 'X') |
|||
return make_pair(resolve(m_institution + "/" + m_client), bytes()); |
|||
else |
|||
throw InterfaceNotSupported("ICAP::lookup(), bad institution"); |
|||
} |
|||
throw InterfaceNotSupported("ICAP::lookup(), bad asset"); |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,107 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file ICAP.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
* |
|||
* Ethereum-specific data structures & algorithms. |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <string> |
|||
#include <functional> |
|||
#include <boost/algorithm/string/case_conv.hpp> |
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/Exceptions.h> |
|||
#include <libdevcore/FixedHash.h> |
|||
#include "Common.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
struct InvalidICAP: virtual public dev::Exception {}; |
|||
|
|||
static const std::string EmptyString; |
|||
|
|||
/**
|
|||
* @brief Encapsulation of an ICAP address. |
|||
* Can be encoded, decoded, looked-up and inspected. |
|||
*/ |
|||
class ICAP |
|||
{ |
|||
public: |
|||
/// Construct null ICAP object.
|
|||
ICAP() = default; |
|||
/// Construct a direct ICAP object for given target address. Must have a zero first byte.
|
|||
ICAP(Address const& _target): m_type(Direct), m_direct(_target) {} |
|||
/// Construct an indirect ICAP object for given target name.
|
|||
ICAP(std::string const& _target): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_target)), m_asset("ETH") {} |
|||
/// Construct an indirect ICAP object for given client and institution names.
|
|||
ICAP(std::string const& _client, std::string const& _inst): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_client)), m_institution(boost::algorithm::to_upper_copy(_inst)), m_asset("XET") {} |
|||
/// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this.
|
|||
ICAP(std::string const& _c, std::string const& _i, std::string const& _a): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_c)), m_institution(boost::algorithm::to_upper_copy(_i)), m_asset(boost::algorithm::to_upper_copy(_a)) {} |
|||
|
|||
/// Type of ICAP address.
|
|||
enum Type |
|||
{ |
|||
Invalid, |
|||
Direct, |
|||
Indirect |
|||
}; |
|||
|
|||
/// @returns IBAN encoding of client and data.
|
|||
static std::string iban(std::string _c, std::string _d); |
|||
/// @returns Client and data from given IBAN address.
|
|||
static std::pair<std::string, std::string> fromIBAN(std::string _iban); |
|||
|
|||
/// @returns the ICAP object for the ICAP address given.
|
|||
static ICAP decoded(std::string const& _encoded); |
|||
|
|||
/// @returns the encoded ICAP address.
|
|||
std::string encoded() const; |
|||
/// @returns type of ICAP.
|
|||
Type type() const { return m_type; } |
|||
/// @returns target address. Only valid when type() == Direct.
|
|||
Address const& direct() const { return m_type == Direct ? m_direct : ZeroAddress; } |
|||
/// @returns asset. Only valid when type() == Indirect.
|
|||
std::string const& asset() const { return m_type == Indirect ? m_asset : EmptyString; } |
|||
/// @returns target name. Only valid when type() == Indirect and asset() == "ETH".
|
|||
std::string const& target() const { return m_type == Indirect && m_asset == "ETH" ? m_client : EmptyString; } |
|||
/// @returns institution name. Only valid when type() == Indirect and asset() == "XET".
|
|||
std::string const& institution() const { return m_type == Indirect && m_asset == "XET" ? m_institution : EmptyString; } |
|||
/// @returns client name. Only valid when type() == Indirect and asset() == "XET".
|
|||
std::string const& client() const { return m_type == Indirect && m_asset == "XET" ? m_client : EmptyString; } |
|||
/// @returns target address. Always valid, but requires the Registry address and a function to make calls.
|
|||
std::pair<Address, bytes> address(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const { return m_type == Direct ? make_pair(direct(), bytes()) : m_type == Indirect ? lookup(_call, _reg) : make_pair(Address(), bytes()); } |
|||
|
|||
/// @returns target address. Looks up through the given Registry and call function. Only valid when type() == Indirect.
|
|||
std::pair<Address, bytes> lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const; |
|||
|
|||
private: |
|||
Type m_type = Invalid; |
|||
Address m_direct; |
|||
std::string m_client; |
|||
std::string m_institution; |
|||
std::string m_asset; |
|||
}; |
|||
|
|||
|
|||
} |
|||
} |
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,77 +0,0 @@ |
|||
<!doctype> |
|||
<html> |
|||
|
|||
<head> |
|||
<script type="text/javascript" src="../dist/web3.js"></script> |
|||
<script type="text/javascript"> |
|||
|
|||
var web3 = require('web3'); |
|||
web3.setProvider(new web3.providers.HttpProvider()); |
|||
|
|||
// solidity source code |
|||
var source = "" + |
|||
"contract test {\n" + |
|||
" function multiply(uint[] a) returns(uint d) {\n" + |
|||
" return a[0] + a[1];\n" + |
|||
" }\n" + |
|||
"}\n"; |
|||
|
|||
// contract description, this will be autogenerated somehow |
|||
var desc = [{ |
|||
"name": "multiply(uint256[])", |
|||
"type": "function", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256[]" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}]; |
|||
|
|||
var myContract; |
|||
|
|||
function createExampleContract() { |
|||
// hide create button |
|||
document.getElementById('create').style.visibility = 'hidden'; |
|||
document.getElementById('source').innerText = source; |
|||
|
|||
// create contract |
|||
var address = web3.eth.sendTransaction({data: web3.eth.compile.solidity(source)}), |
|||
Contract = web3.eth.contract(desc); |
|||
|
|||
myContract = new Contract(address); |
|||
document.getElementById('call').style.visibility = 'visible'; |
|||
} |
|||
|
|||
function callExampleContract() { |
|||
// this should be generated by ethereum |
|||
var param = parseInt(document.getElementById('value').value); |
|||
var param2 = parseInt(document.getElementById('value2').value); |
|||
|
|||
// call the contract |
|||
var res = myContract.call().multiply([param, param2]); |
|||
document.getElementById('result').innerText = res.toString(10); |
|||
} |
|||
|
|||
</script> |
|||
</head> |
|||
<body> |
|||
<h1>contract</h1> |
|||
<div id="source"></div> |
|||
<div id='create'> |
|||
<button type="button" onClick="createExampleContract();">create example contract</button> |
|||
</div> |
|||
<div id='call' style='visibility: hidden;'> |
|||
<input type="number" id="value" onkeyup='callExampleContract()'></input> |
|||
<input type="number" id="value2" onkeyup='callExampleContract()'></input> |
|||
</div> |
|||
<div id="result"></div> |
|||
</body> |
|||
</html> |
|||
|
@ -1,119 +0,0 @@ |
|||
<!doctype> |
|||
<html> |
|||
<head> |
|||
<script type="text/javascript" src="../dist/web3.js"></script> |
|||
<script type="text/javascript"> |
|||
var web3 = require('web3'); |
|||
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080')); |
|||
|
|||
var desc = [{ |
|||
"type":"event", |
|||
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}], |
|||
"name":"Event" |
|||
}, { |
|||
"type":"event", |
|||
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}], |
|||
"name":"Event2" |
|||
}, { |
|||
"type":"function", |
|||
"inputs": [{"name":"a","type":"uint256"}], |
|||
"name":"foo", |
|||
"outputs": [] |
|||
}]; |
|||
|
|||
var address = '0x01'; |
|||
|
|||
var contract = web3.eth.contract(address, desc); |
|||
|
|||
function test1() { |
|||
// "{"topic":["0x83c9849c","0xc4d76332"],"address":"0x01"}" |
|||
web3.eth.watch(contract).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test2() { |
|||
// "{"topic":["0x83c9849c"],"address":"0x01"}" |
|||
web3.eth.watch(contract.Event).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test3() { |
|||
// "{"topic":["0x83c9849c"],"address":"0x01"}" |
|||
contract.Event().changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test4() { |
|||
// "{"topic":["0x83c9849c","0000000000000000000000000000000000000000000000000000000000000045"],"address":"0x01"}" |
|||
contract.Event({a: 69}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test5() { |
|||
// "{"topic":["0x83c9849c",["0000000000000000000000000000000000000000000000000000000000000045","000000000000000000000000000000000000000000000000000000000000002a"]],"address":"0x01"}" |
|||
contract.Event({a: [69, 42]}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test6() { |
|||
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}" |
|||
contract.Event({a: 30}, {max: 100}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test7() { |
|||
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"address":"0x01"}" |
|||
web3.eth.watch(contract.Event, {a: 30}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test8() { |
|||
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}" |
|||
web3.eth.watch(contract.Event, {a: 30}, {max: 100}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
// not valid |
|||
// function testX() { |
|||
// web3.eth.watch([contract.Event, contract.Event2]).changed(function (res) { |
|||
// }); |
|||
// }; |
|||
|
|||
</script> |
|||
</head> |
|||
|
|||
<body> |
|||
<div> |
|||
<button type="button" onClick="test1();">test1</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test2();">test2</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test3();">test3</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test4();">test4</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test5();">test5</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test6();">test6</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test7();">test7</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test8();">test8</button> |
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,329 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** |
|||
* @file coder.js |
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var BigNumber = require('bignumber.js'); |
|||
var utils = require('../utils/utils'); |
|||
var f = require('./formatters'); |
|||
var SolidityParam = require('./param'); |
|||
|
|||
/** |
|||
* Should be used to check if a type is an array type |
|||
* |
|||
* @method isArrayType |
|||
* @param {String} type |
|||
* @return {Bool} true is the type is an array, otherwise false |
|||
*/ |
|||
var isArrayType = function (type) { |
|||
return type.slice(-2) === '[]'; |
|||
}; |
|||
|
|||
/** |
|||
* SolidityType prototype is used to encode/decode solidity params of certain type |
|||
*/ |
|||
var SolidityType = function (config) { |
|||
this._name = config.name; |
|||
this._match = config.match; |
|||
this._mode = config.mode; |
|||
this._inputFormatter = config.inputFormatter; |
|||
this._outputFormatter = config.outputFormatter; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to determine if this SolidityType do match given type |
|||
* |
|||
* @method isType |
|||
* @param {String} name |
|||
* @return {Bool} true if type match this SolidityType, otherwise false |
|||
*/ |
|||
SolidityType.prototype.isType = function (name) { |
|||
if (this._match === 'strict') { |
|||
return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]'); |
|||
} else if (this._match === 'prefix') { |
|||
// TODO better type detection!
|
|||
return name.indexOf(this._name) === 0; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform plain param to SolidityParam object |
|||
* |
|||
* @method formatInput |
|||
* @param {Object} param - plain object, or an array of objects |
|||
* @param {Bool} arrayType - true if a param should be encoded as an array |
|||
* @return {SolidityParam} encoded param wrapped in SolidityParam object |
|||
*/ |
|||
SolidityType.prototype.formatInput = function (param, arrayType) { |
|||
if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same
|
|||
var self = this; |
|||
return param.map(function (p) { |
|||
return self._inputFormatter(p); |
|||
}).reduce(function (acc, current) { |
|||
acc.appendArrayElement(current); |
|||
return acc; |
|||
}, new SolidityParam('', f.formatInputInt(param.length).value)); |
|||
} |
|||
return this._inputFormatter(param); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transoform SolidityParam to plain param |
|||
* |
|||
* @method formatOutput |
|||
* @param {SolidityParam} byteArray |
|||
* @param {Bool} arrayType - true if a param should be decoded as an array |
|||
* @return {Object} plain decoded param |
|||
*/ |
|||
SolidityType.prototype.formatOutput = function (param, arrayType) { |
|||
if (arrayType) { |
|||
// let's assume, that we solidity will never return long arrays :P
|
|||
var result = []; |
|||
var length = new BigNumber(param.prefix, 16); |
|||
for (var i = 0; i < length * 64; i += 64) { |
|||
result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64)))); |
|||
} |
|||
return result; |
|||
} |
|||
return this._outputFormatter(param); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to check if a type is variadic |
|||
* |
|||
* @method isVariadicType |
|||
* @param {String} type |
|||
* @returns {Bool} true if the type is variadic |
|||
*/ |
|||
SolidityType.prototype.isVariadicType = function (type) { |
|||
return isArrayType(type) || this._mode === 'bytes'; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to shift param from params group |
|||
* |
|||
* @method shiftParam |
|||
* @param {String} type |
|||
* @returns {SolidityParam} shifted param |
|||
*/ |
|||
SolidityType.prototype.shiftParam = function (type, param) { |
|||
if (this._mode === 'bytes') { |
|||
return param.shiftBytes(); |
|||
} else if (isArrayType(type)) { |
|||
var length = new BigNumber(param.prefix.slice(0, 64), 16); |
|||
return param.shiftArray(length); |
|||
} |
|||
return param.shiftValue(); |
|||
}; |
|||
|
|||
/** |
|||
* SolidityCoder prototype should be used to encode/decode solidity params of any type |
|||
*/ |
|||
var SolidityCoder = function (types) { |
|||
this._types = types; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to transform type to SolidityType |
|||
* |
|||
* @method _requireType |
|||
* @param {String} type |
|||
* @returns {SolidityType} |
|||
* @throws {Error} throws if no matching type is found |
|||
*/ |
|||
SolidityCoder.prototype._requireType = function (type) { |
|||
var solidityType = this._types.filter(function (t) { |
|||
return t.isType(type); |
|||
})[0]; |
|||
|
|||
if (!solidityType) { |
|||
throw Error('invalid solidity type!: ' + type); |
|||
} |
|||
|
|||
return solidityType; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform plain bytes to SolidityParam object |
|||
* |
|||
* @method _bytesToParam |
|||
* @param {Array} types of params |
|||
* @param {String} bytes to be transformed to SolidityParam |
|||
* @return {SolidityParam} SolidityParam for this group of params |
|||
*/ |
|||
SolidityCoder.prototype._bytesToParam = function (types, bytes) { |
|||
var self = this; |
|||
var prefixTypes = types.reduce(function (acc, type) { |
|||
return self._requireType(type).isVariadicType(type) ? acc + 1 : acc; |
|||
}, 0); |
|||
var valueTypes = types.length - prefixTypes; |
|||
|
|||
var prefix = bytes.slice(0, prefixTypes * 64); |
|||
bytes = bytes.slice(prefixTypes * 64); |
|||
var value = bytes.slice(0, valueTypes * 64); |
|||
var suffix = bytes.slice(valueTypes * 64); |
|||
return new SolidityParam(value, prefix, suffix); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform plain param of given type to SolidityParam |
|||
* |
|||
* @method _formatInput |
|||
* @param {String} type of param |
|||
* @param {Object} plain param |
|||
* @return {SolidityParam} |
|||
*/ |
|||
SolidityCoder.prototype._formatInput = function (type, param) { |
|||
return this._requireType(type).formatInput(param, isArrayType(type)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to encode plain param |
|||
* |
|||
* @method encodeParam |
|||
* @param {String} type |
|||
* @param {Object} plain param |
|||
* @return {String} encoded plain param |
|||
*/ |
|||
SolidityCoder.prototype.encodeParam = function (type, param) { |
|||
return this._formatInput(type, param).encode(); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to encode list of params |
|||
* |
|||
* @method encodeParams |
|||
* @param {Array} types |
|||
* @param {Array} params |
|||
* @return {String} encoded list of params |
|||
*/ |
|||
SolidityCoder.prototype.encodeParams = function (types, params) { |
|||
var self = this; |
|||
return types.map(function (type, index) { |
|||
return self._formatInput(type, params[index]); |
|||
}).reduce(function (acc, solidityParam) { |
|||
acc.append(solidityParam); |
|||
return acc; |
|||
}, new SolidityParam()).encode(); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform SolidityParam to plain param |
|||
* |
|||
* @method _formatOutput |
|||
* @param {String} type |
|||
* @param {SolidityParam} param |
|||
* @return {Object} plain param |
|||
*/ |
|||
SolidityCoder.prototype._formatOutput = function (type, param) { |
|||
return this._requireType(type).formatOutput(param, isArrayType(type)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to decode bytes to plain param |
|||
* |
|||
* @method decodeParam |
|||
* @param {String} type |
|||
* @param {String} bytes |
|||
* @return {Object} plain param |
|||
*/ |
|||
SolidityCoder.prototype.decodeParam = function (type, bytes) { |
|||
return this._formatOutput(type, this._bytesToParam([type], bytes)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to decode list of params |
|||
* |
|||
* @method decodeParam |
|||
* @param {Array} types |
|||
* @param {String} bytes |
|||
* @return {Array} array of plain params |
|||
*/ |
|||
SolidityCoder.prototype.decodeParams = function (types, bytes) { |
|||
var self = this; |
|||
var param = this._bytesToParam(types, bytes); |
|||
return types.map(function (type) { |
|||
var solidityType = self._requireType(type); |
|||
var p = solidityType.shiftParam(type, param); |
|||
return solidityType.formatOutput(p, isArrayType(type)); |
|||
}); |
|||
}; |
|||
|
|||
var coder = new SolidityCoder([ |
|||
new SolidityType({ |
|||
name: 'address', |
|||
match: 'strict', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputInt, |
|||
outputFormatter: f.formatOutputAddress |
|||
}), |
|||
new SolidityType({ |
|||
name: 'bool', |
|||
match: 'strict', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputBool, |
|||
outputFormatter: f.formatOutputBool |
|||
}), |
|||
new SolidityType({ |
|||
name: 'int', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputInt, |
|||
outputFormatter: f.formatOutputInt, |
|||
}), |
|||
new SolidityType({ |
|||
name: 'uint', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputInt, |
|||
outputFormatter: f.formatOutputUInt |
|||
}), |
|||
new SolidityType({ |
|||
name: 'bytes', |
|||
match: 'strict', |
|||
mode: 'bytes', |
|||
inputFormatter: f.formatInputDynamicBytes, |
|||
outputFormatter: f.formatOutputDynamicBytes |
|||
}), |
|||
new SolidityType({ |
|||
name: 'bytes', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputBytes, |
|||
outputFormatter: f.formatOutputBytes |
|||
}), |
|||
new SolidityType({ |
|||
name: 'real', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputReal, |
|||
outputFormatter: f.formatOutputReal |
|||
}), |
|||
new SolidityType({ |
|||
name: 'ureal', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputReal, |
|||
outputFormatter: f.formatOutputUReal |
|||
}) |
|||
]); |
|||
|
|||
module.exports = coder; |
|||
|
@ -0,0 +1,105 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** |
|||
* @file param.js |
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
/** |
|||
* SolidityParam object prototype. |
|||
* Should be used when encoding, decoding solidity bytes |
|||
*/ |
|||
var SolidityParam = function (value, prefix, suffix) { |
|||
this.prefix = prefix || ''; |
|||
this.value = value || ''; |
|||
this.suffix = suffix || ''; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to encode two params one after another |
|||
* |
|||
* @method append |
|||
* @param {SolidityParam} param that it appended after this |
|||
*/ |
|||
SolidityParam.prototype.append = function (param) { |
|||
this.prefix += param.prefix; |
|||
this.value += param.value; |
|||
this.suffix += param.suffix; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to encode next param in an array |
|||
* |
|||
* @method appendArrayElement |
|||
* @param {SolidityParam} param that is appended to an array |
|||
*/ |
|||
SolidityParam.prototype.appendArrayElement = function (param) { |
|||
this.suffix += param.value; |
|||
this.prefix += param.prefix; |
|||
// TODO: suffix not supported = it's required for nested arrays;
|
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to create bytearrays from param |
|||
* |
|||
* @method encode |
|||
* @return {String} encoded param(s) |
|||
*/ |
|||
SolidityParam.prototype.encode = function () { |
|||
return this.prefix + this.value + this.suffix; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to shift first param from group of params |
|||
* |
|||
* @method shiftValue |
|||
* @return {SolidityParam} first value param |
|||
*/ |
|||
SolidityParam.prototype.shiftValue = function () { |
|||
var value = this.value.slice(0, 64); |
|||
this.value = this.value.slice(64); |
|||
return new SolidityParam(value); |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to first bytes param from group of params |
|||
* |
|||
* @method shiftBytes |
|||
* @return {SolidityParam} first bytes param |
|||
*/ |
|||
SolidityParam.prototype.shiftBytes = function () { |
|||
return this.shiftArray(1); |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to shift an array from group of params |
|||
* |
|||
* @method shiftArray |
|||
* @param {Number} size of an array to shift |
|||
* @return {SolidityParam} first array param |
|||
*/ |
|||
SolidityParam.prototype.shiftArray = function (length) { |
|||
var prefix = this.prefix.slice(0, 64); |
|||
this.prefix = this.value.slice(64); |
|||
var suffix = this.suffix.slice(0, 64 * length); |
|||
this.suffix = this.suffix.slice(64 * length); |
|||
return new SolidityParam('', prefix, suffix); |
|||
}; |
|||
|
|||
module.exports = SolidityParam; |
|||
|
@ -1,77 +0,0 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file types.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var f = require('./formatters'); |
|||
|
|||
/// @param expected type prefix (string)
|
|||
/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false
|
|||
var prefixedType = function (prefix) { |
|||
return function (type) { |
|||
return type.indexOf(prefix) === 0; |
|||
}; |
|||
}; |
|||
|
|||
/// @param expected type name (string)
|
|||
/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false
|
|||
var namedType = function (name) { |
|||
return function (type) { |
|||
return name === type; |
|||
}; |
|||
}; |
|||
|
|||
/// Setups input formatters for solidity types
|
|||
/// @returns an array of input formatters
|
|||
var inputTypes = function () { |
|||
|
|||
return [ |
|||
{ type: prefixedType('uint'), format: f.formatInputInt }, |
|||
{ type: prefixedType('int'), format: f.formatInputInt }, |
|||
{ type: prefixedType('bytes'), format: f.formatInputString }, |
|||
{ type: prefixedType('real'), format: f.formatInputReal }, |
|||
{ type: prefixedType('ureal'), format: f.formatInputReal }, |
|||
{ type: namedType('address'), format: f.formatInputInt }, |
|||
{ type: namedType('bool'), format: f.formatInputBool } |
|||
]; |
|||
}; |
|||
|
|||
/// Setups output formaters for solidity types
|
|||
/// @returns an array of output formatters
|
|||
var outputTypes = function () { |
|||
|
|||
return [ |
|||
{ type: prefixedType('uint'), format: f.formatOutputUInt }, |
|||
{ type: prefixedType('int'), format: f.formatOutputInt }, |
|||
{ type: prefixedType('bytes'), format: f.formatOutputString }, |
|||
{ type: prefixedType('real'), format: f.formatOutputReal }, |
|||
{ type: prefixedType('ureal'), format: f.formatOutputUReal }, |
|||
{ type: namedType('address'), format: f.formatOutputAddress }, |
|||
{ type: namedType('bool'), format: f.formatOutputBool } |
|||
]; |
|||
}; |
|||
|
|||
module.exports = { |
|||
prefixedType: prefixedType, |
|||
namedType: namedType, |
|||
inputTypes: inputTypes, |
|||
outputTypes: outputTypes |
|||
}; |
|||
|
@ -1,3 +1,3 @@ |
|||
{ |
|||
"version": "0.2.6" |
|||
"version": "0.3.3" |
|||
} |
|||
|
@ -0,0 +1,151 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** |
|||
* @file function.js |
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var web3 = require('../web3'); |
|||
var coder = require('../solidity/coder'); |
|||
var utils = require('../utils/utils'); |
|||
|
|||
/** |
|||
* This prototype should be used to call/sendTransaction to solidity functions |
|||
*/ |
|||
var SolidityFunction = function (json, address) { |
|||
this._inputTypes = json.inputs.map(function (i) { |
|||
return i.type; |
|||
}); |
|||
this._outputTypes = json.outputs.map(function (i) { |
|||
return i.type; |
|||
}); |
|||
this._constant = json.constant; |
|||
this._name = utils.transformToFullName(json); |
|||
this._address = address; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to create payload from arguments |
|||
* |
|||
* @method toPayload |
|||
* @param {...} solidity function params |
|||
* @param {Object} optional payload options |
|||
*/ |
|||
SolidityFunction.prototype.toPayload = function () { |
|||
var args = Array.prototype.slice.call(arguments); |
|||
var options = {}; |
|||
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { |
|||
options = args.pop(); |
|||
} |
|||
options.to = this._address; |
|||
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); |
|||
return options; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to get function signature |
|||
* |
|||
* @method signature |
|||
* @return {String} function signature |
|||
*/ |
|||
SolidityFunction.prototype.signature = function () { |
|||
return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to call function |
|||
* |
|||
* @method call |
|||
* @param {Object} options |
|||
* @return {String} output bytes |
|||
*/ |
|||
SolidityFunction.prototype.call = function () { |
|||
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); |
|||
var output = web3.eth.call(payload); |
|||
output = output.length >= 2 ? output.slice(2) : output; |
|||
var result = coder.decodeParams(this._outputTypes, output); |
|||
return result.length === 1 ? result[0] : result; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to sendTransaction to solidity function |
|||
* |
|||
* @method sendTransaction |
|||
* @param {Object} options |
|||
*/ |
|||
SolidityFunction.prototype.sendTransaction = function () { |
|||
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); |
|||
web3.eth.sendTransaction(payload); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to get function display name |
|||
* |
|||
* @method displayName |
|||
* @return {String} display name of the function |
|||
*/ |
|||
SolidityFunction.prototype.displayName = function () { |
|||
return utils.extractDisplayName(this._name); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to get function type name |
|||
* |
|||
* @method typeName |
|||
* @return {String} type name of the function |
|||
*/ |
|||
SolidityFunction.prototype.typeName = function () { |
|||
return utils.extractTypeName(this._name); |
|||
}; |
|||
|
|||
/** |
|||
* Should be called to execute function |
|||
* |
|||
* @method execute |
|||
*/ |
|||
SolidityFunction.prototype.execute = function () { |
|||
var transaction = !this._constant; |
|||
|
|||
// send transaction
|
|||
if (transaction) { |
|||
return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments)); |
|||
} |
|||
|
|||
// call
|
|||
return this.call.apply(this, Array.prototype.slice.call(arguments)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be called to attach function to contract |
|||
* |
|||
* @method attachToContract |
|||
* @param {Contract} |
|||
*/ |
|||
SolidityFunction.prototype.attachToContract = function (contract) { |
|||
var execute = this.execute.bind(this); |
|||
execute.call = this.call.bind(this); |
|||
execute.sendTransaction = this.sendTransaction.bind(this); |
|||
var displayName = this.displayName(); |
|||
if (!contract[displayName]) { |
|||
contract[displayName] = execute; |
|||
} |
|||
contract[displayName][this.typeName()] = execute; // circular!!!!
|
|||
}; |
|||
|
|||
module.exports = SolidityFunction; |
|||
|
@ -1,42 +0,0 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file signature.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var web3 = require('../web3'); |
|||
var c = require('../utils/config'); |
|||
|
|||
/// @param function name for which we want to get signature
|
|||
/// @returns signature of function with given name
|
|||
var functionSignatureFromAscii = function (name) { |
|||
return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2); |
|||
}; |
|||
|
|||
/// @param event name for which we want to get signature
|
|||
/// @returns signature of event with given name
|
|||
var eventSignatureFromAscii = function (name) { |
|||
return web3.sha3(web3.fromAscii(name)); |
|||
}; |
|||
|
|||
module.exports = { |
|||
functionSignatureFromAscii: functionSignatureFromAscii, |
|||
eventSignatureFromAscii: eventSignatureFromAscii |
|||
}; |
|||
|
@ -1,7 +1,7 @@ |
|||
/* jshint ignore:start */ |
|||
|
|||
if(typeof web3 === 'undefined') { |
|||
web3 = require('ethereum.js'); |
|||
web3 = require('web3'); |
|||
BigNumber = require('bignumber.js'); |
|||
} |
|||
|
|||
|
@ -0,0 +1,68 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var coder = require('../lib/solidity/coder'); |
|||
var BigNumber = require('bignumber.js'); |
|||
var bn = BigNumber; |
|||
|
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('decodeParam', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.value + ' to ' + t.expected, function () { |
|||
assert.deepEqual(coder.decodeParam(t.type, t.value), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ type: 'int', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'int256', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int256', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int256', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'bytes32', expected: 'gavofyork', value: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'bytes', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'int[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int256[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int[]', expected: [new bn(1), new bn(2), new bn(3)], |
|||
value: '0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
}); |
|||
}); |
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('decodeParams', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.values + ' to ' + t.expected, function () { |
|||
assert.deepEqual(coder.decodeParams(t.types, t.values), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ types: ['int'], expected: [new bn(1)], values: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ types: ['bytes32', 'int'], expected: ['gavofyork', new bn(5)], |
|||
values: '6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005'}); |
|||
test({ types: ['int', 'bytes32'], expected: [new bn(5), 'gavofyork'], |
|||
values: '0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], expected: [new bn(1), 'gavofyork', new bn(2), new bn(3), new bn(4), |
|||
[new bn(5), new bn(6), new bn(7)]], |
|||
values: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'0000000000000000000000000000000000000000000000000000000000000006' + |
|||
'0000000000000000000000000000000000000000000000000000000000000007'}); |
|||
}); |
|||
}); |
|||
|
@ -0,0 +1,91 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var coder = require('../lib/solidity/coder'); |
|||
|
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('encodeParam', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.value + ' to ' + t.expected, function () { |
|||
assert.equal(coder.encodeParam(t.type, t.value), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ type: 'int', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'int256', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int256', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int256', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'bytes32', value: 'gavofyork', expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'bytes', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'int[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int256[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int[]', value: [1,2,3], expected: '0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
}); |
|||
}); |
|||
|
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('encodeParams', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.values + ' to ' + t.expected, function () { |
|||
assert.equal(coder.encodeParams(t.types, t.values), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ types: ['int'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ types: ['int'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ types: ['int'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ types: ['int256'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ types: ['int256'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ types: ['int256'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ types: ['bytes32'], values: ['gavofyork'], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['bytes'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ types: ['int256[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ types: ['int256[]'], values: [[1,2,3]], expected: '0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ types: ['bytes32', 'int'], values: ['gavofyork', 5], |
|||
expected: '6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005'}); |
|||
test({ types: ['int', 'bytes32'], values: [5, 'gavofyork'], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['bytes', 'int'], values: ['gavofyork', 5], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int', 'bytes'], values: [5, 'gavofyork'], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], values: [1, 'gavofyork', 2, 3, 4, [5, 6, 7]], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'0000000000000000000000000000000000000000000000000000000000000006' + |
|||
'0000000000000000000000000000000000000000000000000000000000000007'}); |
|||
|
|||
}); |
|||
}); |
|||
|
|||
|
@ -0,0 +1,180 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var BigNumber = require('bignumber.js'); |
|||
var SolidityEvent = require('../lib/web3/event'); |
|||
|
|||
var name = 'event1'; |
|||
var address = '0x1234567890123456789012345678901234567890'; |
|||
|
|||
var tests = [{ |
|||
abi: { |
|||
name: name, |
|||
inputs: [] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1' |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: {}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: name, |
|||
inputs: [{ |
|||
name: 'a', |
|||
type: 'int', |
|||
indexed: false |
|||
}] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1', |
|||
data: '0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: { |
|||
a: new BigNumber(1) |
|||
}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: name, |
|||
inputs: [{ |
|||
name: 'a', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'b', |
|||
type: 'int', |
|||
indexed: true |
|||
}, { |
|||
name: 'c', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'd', |
|||
type: 'int', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1', |
|||
data: '0x' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004', |
|||
topics: [ |
|||
address, |
|||
'0x000000000000000000000000000000000000000000000000000000000000000a', |
|||
'0x0000000000000000000000000000000000000000000000000000000000000010' |
|||
] |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: { |
|||
a: new BigNumber(1), |
|||
b: new BigNumber(10), |
|||
c: new BigNumber(4), |
|||
d: new BigNumber(16) |
|||
}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: name, |
|||
anonymous: true, |
|||
inputs: [{ |
|||
name: 'a', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'b', |
|||
type: 'int', |
|||
indexed: true |
|||
}, { |
|||
name: 'c', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'd', |
|||
type: 'int', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1', |
|||
data: '0x' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004', |
|||
topics: [ |
|||
'0x000000000000000000000000000000000000000000000000000000000000000a', |
|||
'0x0000000000000000000000000000000000000000000000000000000000000010' |
|||
] |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: { |
|||
a: new BigNumber(1), |
|||
b: new BigNumber(10), |
|||
c: new BigNumber(4), |
|||
d: new BigNumber(16) |
|||
}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}]; |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('decode', function () { |
|||
tests.forEach(function (test, index) { |
|||
it('test no: ' + index, function () { |
|||
var event = new SolidityEvent(test.abi, address); |
|||
|
|||
var result = event.decode(test.data); |
|||
assert.deepEqual(result, test.expected); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -0,0 +1,206 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var SolidityEvent = require('../lib/web3/event'); |
|||
|
|||
var address = '0x1234567890123456789012345678901234567890'; |
|||
var signature = '0xffff'; |
|||
|
|||
var tests = [{ |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [] |
|||
}, |
|||
indexed: {}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: 16 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, |
|||
'0x0000000000000000000000000000000000000000000000000000000000000010' |
|||
] |
|||
} |
|||
},{ |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'b', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'c', |
|||
indexed: false |
|||
}, { |
|||
type: 'int', |
|||
name: 'd', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
b: 4 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, // signature
|
|||
null, // a
|
|||
'0x0000000000000000000000000000000000000000000000000000000000000004', // b
|
|||
null // d
|
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'b', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: [16, 1], |
|||
b: 2 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, |
|||
['0x0000000000000000000000000000000000000000000000000000000000000010', '0x0000000000000000000000000000000000000000000000000000000000000001'], |
|||
'0x0000000000000000000000000000000000000000000000000000000000000002' |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: null |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, |
|||
null |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: 1 |
|||
}, |
|||
options: { |
|||
fromBlock: 4, |
|||
toBlock: 10 |
|||
}, |
|||
expected: { |
|||
address: address, |
|||
fromBlock: '0x4', |
|||
toBlock: '0xa', |
|||
topics: [ |
|||
signature, |
|||
'0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}], |
|||
anonymous: true |
|||
}, |
|||
indexed: { |
|||
a: 1 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
topics: [ |
|||
'0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'b', |
|||
indexed: true |
|||
}], |
|||
anonymous: true |
|||
}, |
|||
indexed: { |
|||
b: 1 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
topics: [ |
|||
null, |
|||
'0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
] |
|||
} |
|||
}]; |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('encode', function () { |
|||
tests.forEach(function (test, index) { |
|||
it('test no: ' + index, function () { |
|||
var event = new SolidityEvent(test.abi, address); |
|||
event.signature = function () { // inject signature
|
|||
return signature.slice(2); |
|||
}; |
|||
|
|||
var result = event.encode(test.indexed, test.options); |
|||
assert.deepEqual(result, test.expected); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -1,113 +0,0 @@ |
|||
var assert = require('assert'); |
|||
var event = require('../lib/web3/event.js'); |
|||
var f = require('../lib/solidity/formatters.js'); |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('inputParser', function () { |
|||
it('should create basic filter input object', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl(); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 1); |
|||
assert.equal(result.topics[0], signature); |
|||
|
|||
}); |
|||
|
|||
it('should create filter input object with options', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var options = { |
|||
fromBlock: 1, |
|||
toBlock: 2, |
|||
}; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl({}, options); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 1); |
|||
assert.equal(result.topics[0], signature); |
|||
assert.equal(result.fromBlock, options.fromBlock); |
|||
assert.equal(result.toBlock, options.toBlock); |
|||
|
|||
}); |
|||
|
|||
it('should create filter input object with indexed params', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var options = { |
|||
fromBlock: 1, |
|||
toBlock: 2 |
|||
}; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl({a: 4}, options); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 2); |
|||
assert.equal(result.topics[0], signature); |
|||
assert.equal(result.topics[1], '0x' + f.formatInputInt(4)); |
|||
assert.equal(result.fromBlock, options.fromBlock); |
|||
assert.equal(result.toBlock, options.toBlock); |
|||
|
|||
}); |
|||
|
|||
it('should create filter input object with an array of indexed params', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var options = { |
|||
fromBlock: 1, |
|||
toBlock: 2, |
|||
}; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl({a: [4, 69]}, options); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 2); |
|||
assert.equal(result.topics[0], signature); |
|||
assert.equal(result.topics[1][0], f.formatInputInt(4)); |
|||
assert.equal(result.topics[1][1], f.formatInputInt(69)); |
|||
assert.equal(result.fromBlock, options.fromBlock); |
|||
assert.equal(result.toBlock, options.toBlock); |
|||
|
|||
}); |
|||
}); |
|||
}); |
|||
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue