josephnicholas
6 years ago
42 changed files with 7605 additions and 2 deletions
@ -1 +1,16 @@ |
|||
# Equihash |
|||
# equihashverify |
|||
nodejs native binding to check for valid Equihash solutions |
|||
|
|||
##usage: |
|||
````javascript |
|||
var ev = require('bindings')('equihashverify.node'); |
|||
|
|||
var header = new Buffer(..., 'hex'); |
|||
var solution = new Buffer(..., 'hex'); //do not include byte size preamble "fd4005" |
|||
|
|||
ev.verify(header, solution); |
|||
//returns boolean |
|||
```` |
|||
|
|||
##help |
|||
https://zclassic.herokuapp.com |
|||
|
@ -0,0 +1,47 @@ |
|||
{ |
|||
"targets": [ |
|||
{ |
|||
"target_name": "equihashverify", |
|||
"dependencies": [ |
|||
|
|||
], |
|||
"sources": [ |
|||
"support/cleanse.cpp", |
|||
"uint256.cpp", |
|||
"random.cpp", |
|||
"util.cpp", |
|||
"utiltime.cpp", |
|||
"utilstrencodings.cpp", |
|||
"crypto/equihash.cpp", |
|||
"crypto/hmac_sha256.cpp", |
|||
"crypto/hmac_sha512.cpp", |
|||
"crypto/ripemd160.cpp", |
|||
"crypto/sha1.cpp", |
|||
"crypto/sha256.cpp", |
|||
"crypto/sha512.cpp", |
|||
"equihashverify.cc" |
|||
], |
|||
"include_dirs": [ |
|||
"<!(node -e \"require('nan')\")", |
|||
".", |
|||
"/usr/include" |
|||
], |
|||
"defines": [ |
|||
"HAVE_DECL_STRNLEN=1", |
|||
"HAVE_BYTESWAP_H=1" |
|||
], |
|||
"cflags_cc": [ |
|||
"-std=c++11", |
|||
"-Wl,--whole-archive", |
|||
"-fPIC", |
|||
"-fexceptions" |
|||
], |
|||
"link_settings": { |
|||
"libraries": [ |
|||
"-Wl,-rpath,./build/Release/", |
|||
] |
|||
}, |
|||
} |
|||
] |
|||
} |
|||
|
@ -0,0 +1,324 @@ |
|||
# We borrow heavily from the kernel build setup, though we are simpler since
|
|||
# we don't have Kconfig tweaking settings on us.
|
|||
|
|||
# The implicit make rules have it looking for RCS files, among other things.
|
|||
# We instead explicitly write all the rules we care about.
|
|||
# It's even quicker (saves ~200ms) to pass -r on the command line.
|
|||
MAKEFLAGS=-r |
|||
|
|||
# The source directory tree.
|
|||
srcdir := .. |
|||
abs_srcdir := $(abspath $(srcdir)) |
|||
|
|||
# The name of the builddir.
|
|||
builddir_name ?= . |
|||
|
|||
# The V=1 flag on command line makes us verbosely print command lines.
|
|||
ifdef V |
|||
quiet= |
|||
else |
|||
quiet=quiet_ |
|||
endif |
|||
|
|||
# Specify BUILDTYPE=Release on the command line for a release build.
|
|||
BUILDTYPE ?= Release |
|||
|
|||
# Directory all our build output goes into.
|
|||
# Note that this must be two directories beneath src/ for unit tests to pass,
|
|||
# as they reach into the src/ directory for data with relative paths.
|
|||
builddir ?= $(builddir_name)/$(BUILDTYPE) |
|||
abs_builddir := $(abspath $(builddir)) |
|||
depsdir := $(builddir)/.deps |
|||
|
|||
# Object output directory.
|
|||
obj := $(builddir)/obj |
|||
abs_obj := $(abspath $(obj)) |
|||
|
|||
# We build up a list of every single one of the targets so we can slurp in the
|
|||
# generated dependency rule Makefiles in one pass.
|
|||
all_deps := |
|||
|
|||
|
|||
|
|||
CC.target ?= $(CC) |
|||
CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS) |
|||
CXX.target ?= $(CXX) |
|||
CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS) |
|||
LINK.target ?= $(LINK) |
|||
LDFLAGS.target ?= $(LDFLAGS) |
|||
AR.target ?= $(AR) |
|||
|
|||
# C++ apps need to be linked with g++.
|
|||
LINK ?= $(CXX.target) |
|||
|
|||
# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
|
|||
# to replicate this environment fallback in make as well.
|
|||
CC.host ?= gcc |
|||
CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host) |
|||
CXX.host ?= g++ |
|||
CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host) |
|||
LINK.host ?= $(CXX.host) |
|||
LDFLAGS.host ?= |
|||
AR.host ?= ar |
|||
|
|||
# Define a dir function that can handle spaces.
|
|||
# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
|
|||
# "leading spaces cannot appear in the text of the first argument as written.
|
|||
# These characters can be put into the argument value by variable substitution."
|
|||
empty := |
|||
space := $(empty) $(empty) |
|||
|
|||
# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
|
|||
replace_spaces = $(subst $(space),?,$1) |
|||
unreplace_spaces = $(subst ?,$(space),$1) |
|||
dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) |
|||
|
|||
# Flags to make gcc output dependency info. Note that you need to be
|
|||
# careful here to use the flags that ccache and distcc can understand.
|
|||
# We write to a dep file on the side first and then rename at the end
|
|||
# so we can't end up with a broken dep file.
|
|||
depfile = $(depsdir)/$(call replace_spaces,$@).d |
|||
DEPFLAGS = -MMD -MF $(depfile).raw |
|||
|
|||
# We have to fixup the deps output in a few ways.
|
|||
# (1) the file output should mention the proper .o file.
|
|||
# ccache or distcc lose the path to the target, so we convert a rule of
|
|||
# the form:
|
|||
# foobar.o: DEP1 DEP2
|
|||
# into
|
|||
# path/to/foobar.o: DEP1 DEP2
|
|||
# (2) we want missing files not to cause us to fail to build.
|
|||
# We want to rewrite
|
|||
# foobar.o: DEP1 DEP2 \
|
|||
# DEP3
|
|||
# to
|
|||
# DEP1:
|
|||
# DEP2:
|
|||
# DEP3:
|
|||
# so if the files are missing, they're just considered phony rules.
|
|||
# We have to do some pretty insane escaping to get those backslashes
|
|||
# and dollar signs past make, the shell, and sed at the same time.
|
|||
# Doesn't work with spaces, but that's fine: .d files have spaces in
|
|||
# their names replaced with other characters.
|
|||
define fixup_dep |
|||
# The depfile may not exist if the input file didn't have any #includes.
|
|||
touch $(depfile).raw |
|||
# Fixup path as in (1).
|
|||
sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) |
|||
# Add extra rules as in (2).
|
|||
# We remove slashes and replace spaces with new lines;
|
|||
# remove blank lines;
|
|||
# delete the first line and append a colon to the remaining lines.
|
|||
sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ |
|||
grep -v '^$$' |\
|
|||
sed -e 1d -e 's|$$|:|' \
|
|||
>> $(depfile) |
|||
rm $(depfile).raw |
|||
endef |
|||
|
|||
# Command definitions:
|
|||
# - cmd_foo is the actual command to run;
|
|||
# - quiet_cmd_foo is the brief-output summary of the command.
|
|||
|
|||
quiet_cmd_cc = CC($(TOOLSET)) $@ |
|||
cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< |
|||
|
|||
quiet_cmd_cxx = CXX($(TOOLSET)) $@ |
|||
cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< |
|||
|
|||
quiet_cmd_touch = TOUCH $@ |
|||
cmd_touch = touch $@ |
|||
|
|||
quiet_cmd_copy = COPY $@ |
|||
# send stderr to /dev/null to ignore messages when linking directories.
|
|||
cmd_copy = rm -rf "$@" && cp -af "$<" "$@" |
|||
|
|||
quiet_cmd_alink = AR($(TOOLSET)) $@ |
|||
cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) |
|||
|
|||
quiet_cmd_alink_thin = AR($(TOOLSET)) $@ |
|||
cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) |
|||
|
|||
# Due to circular dependencies between libraries :(, we wrap the
|
|||
# special "figure out circular dependencies" flags around the entire
|
|||
# input list during linking.
|
|||
quiet_cmd_link = LINK($(TOOLSET)) $@ |
|||
cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) |
|||
|
|||
# We support two kinds of shared objects (.so):
|
|||
# 1) shared_library, which is just bundling together many dependent libraries
|
|||
# into a link line.
|
|||
# 2) loadable_module, which is generating a module intended for dlopen().
|
|||
#
|
|||
# They differ only slightly:
|
|||
# In the former case, we want to package all dependent code into the .so.
|
|||
# In the latter case, we want to package just the API exposed by the
|
|||
# outermost module.
|
|||
# This means shared_library uses --whole-archive, while loadable_module doesn't.
|
|||
# (Note that --whole-archive is incompatible with the --start-group used in
|
|||
# normal linking.)
|
|||
|
|||
# Other shared-object link notes:
|
|||
# - Set SONAME to the library filename so our binaries don't reference
|
|||
# the local, absolute paths used on the link command-line.
|
|||
quiet_cmd_solink = SOLINK($(TOOLSET)) $@ |
|||
cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) |
|||
|
|||
quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ |
|||
cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) |
|||
|
|||
|
|||
# Define an escape_quotes function to escape single quotes.
|
|||
# This allows us to handle quotes properly as long as we always use
|
|||
# use single quotes and escape_quotes.
|
|||
escape_quotes = $(subst ','\'',$(1)) |
|||
# This comment is here just to include a ' to unconfuse syntax highlighting.
|
|||
# Define an escape_vars function to escape '$' variable syntax.
|
|||
# This allows us to read/write command lines with shell variables (e.g.
|
|||
# $LD_LIBRARY_PATH), without triggering make substitution.
|
|||
escape_vars = $(subst $$,$$$$,$(1)) |
|||
# Helper that expands to a shell command to echo a string exactly as it is in
|
|||
# make. This uses printf instead of echo because printf's behaviour with respect
|
|||
# to escape sequences is more portable than echo's across different shells
|
|||
# (e.g., dash, bash).
|
|||
exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' |
|||
|
|||
# Helper to compare the command we're about to run against the command
|
|||
# we logged the last time we ran the command. Produces an empty
|
|||
# string (false) when the commands match.
|
|||
# Tricky point: Make has no string-equality test function.
|
|||
# The kernel uses the following, but it seems like it would have false
|
|||
# positives, where one string reordered its arguments.
|
|||
# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
|
|||
# $(filter-out $(cmd_$@), $(cmd_$(1))))
|
|||
# We instead substitute each for the empty string into the other, and
|
|||
# say they're equal if both substitutions produce the empty string.
|
|||
# .d files contain ? instead of spaces, take that into account.
|
|||
command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
|
|||
$(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) |
|||
|
|||
# Helper that is non-empty when a prerequisite changes.
|
|||
# Normally make does this implicitly, but we force rules to always run
|
|||
# so we can check their command lines.
|
|||
# $? -- new prerequisites
|
|||
# $| -- order-only dependencies
|
|||
prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) |
|||
|
|||
# Helper that executes all postbuilds until one fails.
|
|||
define do_postbuilds |
|||
@E=0;\
|
|||
for p in $(POSTBUILDS); do\
|
|||
eval $$p;\
|
|||
E=$$?;\
|
|||
if [ $$E -ne 0 ]; then\
|
|||
break;\
|
|||
fi;\
|
|||
done;\
|
|||
if [ $$E -ne 0 ]; then\
|
|||
rm -rf "$@";\
|
|||
exit $$E;\
|
|||
fi |
|||
endef |
|||
|
|||
# do_cmd: run a command via the above cmd_foo names, if necessary.
|
|||
# Should always run for a given target to handle command-line changes.
|
|||
# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
|
|||
# Third argument, if non-zero, makes it do POSTBUILDS processing.
|
|||
# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
|
|||
# spaces already and dirx strips the ? characters.
|
|||
define do_cmd |
|||
$(if $(or $(command_changed),$(prereq_changed)), |
|||
@$(call exact_echo, $($(quiet)cmd_$(1))) |
|||
@mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" |
|||
$(if $(findstring flock,$(word 1,$(cmd_$1))), |
|||
@$(cmd_$(1)) |
|||
@echo " $(quiet_cmd_$(1)): Finished", |
|||
@$(cmd_$(1)) |
|||
) |
|||
@$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) |
|||
@$(if $(2),$(fixup_dep)) |
|||
$(if $(and $(3), $(POSTBUILDS)), |
|||
$(call do_postbuilds) |
|||
) |
|||
) |
|||
endef |
|||
|
|||
# Declare the "all" target first so it is the default,
|
|||
# even though we don't have the deps yet.
|
|||
.PHONY: all |
|||
all: |
|||
|
|||
# make looks for ways to re-generate included makefiles, but in our case, we
|
|||
# don't have a direct way. Explicitly telling make that it has nothing to do
|
|||
# for them makes it go faster.
|
|||
%.d: ; |
|||
|
|||
# Use FORCE_DO_CMD to force a target to run. Should be coupled with
|
|||
# do_cmd.
|
|||
.PHONY: FORCE_DO_CMD |
|||
FORCE_DO_CMD: |
|||
|
|||
TOOLSET := target |
|||
# Suffix rules, putting all outputs into $(obj).
|
|||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
|
|||
# Try building from generated source, too.
|
|||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
|
|||
$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD |
|||
@$(call do_cmd,cc,1) |
|||
|
|||
|
|||
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ |
|||
$(findstring $(join ^,$(prefix)),\
|
|||
$(join ^,equihashverify.target.mk)))),) |
|||
include equihashverify.target.mk |
|||
endif |
|||
|
|||
quiet_cmd_regen_makefile = ACTION Regenerating $@ |
|||
cmd_regen_makefile = cd $(srcdir); /usr/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/home/osboxes/Documents/equihashverify/build/config.gypi -I/usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/home/osboxes/.node-gyp/9.8.0/include/node/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/osboxes/.node-gyp/9.8.0" "-Dnode_gyp_dir=/usr/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/home/osboxes/.node-gyp/9.8.0/<(target_arch)/node.lib" "-Dmodule_root_dir=/home/osboxes/Documents/equihashverify" "-Dnode_engine=v8" binding.gyp |
|||
Makefile: $(srcdir)/../../.node-gyp/9.8.0/include/node/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi |
|||
$(call do_cmd,regen_makefile) |
|||
|
|||
# "all" is a concatenation of the "all" targets from all the included
|
|||
# sub-makefiles. This is just here to clarify.
|
|||
all: |
|||
|
|||
# Add in dependency-tracking rules. $(all_deps) is the list of every single
|
|||
# target in our tree. Only consider the ones with .d (dependency) info:
|
|||
d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) |
|||
ifneq ($(d_files),) |
|||
include $(d_files) |
|||
endif |
@ -0,0 +1,6 @@ |
|||
# This file is generated by gyp; do not edit. |
|||
|
|||
export builddir_name ?= ./build/. |
|||
.PHONY: all |
|||
all: |
|||
$(MAKE) equihashverify |
@ -0,0 +1,181 @@ |
|||
# Do not edit. File was generated by node-gyp's "configure" step |
|||
{ |
|||
"target_defaults": { |
|||
"cflags": [], |
|||
"default_configuration": "Release", |
|||
"defines": [], |
|||
"include_dirs": [], |
|||
"libraries": [] |
|||
}, |
|||
"variables": { |
|||
"asan": 0, |
|||
"coverage": "false", |
|||
"debug_http2": "false", |
|||
"debug_nghttp2": "false", |
|||
"force_dynamic_crt": 0, |
|||
"gas_version": "2.23", |
|||
"host_arch": "x64", |
|||
"icu_data_in": "../../deps/icu-small/source/data/in/icudt60l.dat", |
|||
"icu_endianness": "l", |
|||
"icu_gyp_path": "tools/icu/icu-generic.gyp", |
|||
"icu_locales": "en,root", |
|||
"icu_path": "deps/icu-small", |
|||
"icu_small": "true", |
|||
"icu_ver_major": "60", |
|||
"llvm_version": 0, |
|||
"node_byteorder": "little", |
|||
"node_enable_d8": "false", |
|||
"node_enable_v8_vtunejit": "false", |
|||
"node_install_npm": "true", |
|||
"node_module_version": 59, |
|||
"node_no_browser_globals": "false", |
|||
"node_prefix": "/", |
|||
"node_release_urlbase": "https://nodejs.org/download/release/", |
|||
"node_shared": "false", |
|||
"node_shared_cares": "false", |
|||
"node_shared_http_parser": "false", |
|||
"node_shared_libuv": "false", |
|||
"node_shared_nghttp2": "false", |
|||
"node_shared_openssl": "false", |
|||
"node_shared_zlib": "false", |
|||
"node_tag": "", |
|||
"node_target_type": "executable", |
|||
"node_use_bundled_v8": "true", |
|||
"node_use_dtrace": "false", |
|||
"node_use_etw": "false", |
|||
"node_use_lttng": "false", |
|||
"node_use_openssl": "true", |
|||
"node_use_perfctr": "false", |
|||
"node_use_v8_platform": "true", |
|||
"node_without_node_options": "false", |
|||
"openssl_fips": "", |
|||
"openssl_no_asm": 0, |
|||
"shlib_suffix": "so.59", |
|||
"target_arch": "x64", |
|||
"v8_enable_gdbjit": 0, |
|||
"v8_enable_i18n_support": 1, |
|||
"v8_enable_inspector": 1, |
|||
"v8_no_strict_aliasing": 1, |
|||
"v8_optimized_debug": 0, |
|||
"v8_promise_internal_field_count": 1, |
|||
"v8_random_seed": 0, |
|||
"v8_trace_maps": 0, |
|||
"v8_use_snapshot": "true", |
|||
"want_separate_host_toolset": 0, |
|||
"nodedir": "/home/osboxes/.node-gyp/9.8.0", |
|||
"standalone_static_library": 1, |
|||
"cache_lock_stale": "60000", |
|||
"ham_it_up": "", |
|||
"legacy_bundling": "", |
|||
"sign_git_tag": "", |
|||
"user_agent": "npm/5.6.0 node/v9.8.0 linux x64", |
|||
"always_auth": "", |
|||
"bin_links": "true", |
|||
"key": "", |
|||
"allow_same_version": "", |
|||
"description": "true", |
|||
"fetch_retries": "2", |
|||
"heading": "npm", |
|||
"if_present": "", |
|||
"init_version": "1.0.0", |
|||
"user": "", |
|||
"prefer_online": "", |
|||
"force": "", |
|||
"only": "", |
|||
"read_only": "", |
|||
"cache_min": "10", |
|||
"init_license": "ISC", |
|||
"editor": "vi", |
|||
"rollback": "true", |
|||
"tag_version_prefix": "v", |
|||
"cache_max": "Infinity", |
|||
"timing": "", |
|||
"userconfig": "/home/osboxes/.npmrc", |
|||
"engine_strict": "", |
|||
"init_author_name": "", |
|||
"init_author_url": "", |
|||
"tmp": "/tmp", |
|||
"depth": "Infinity", |
|||
"package_lock_only": "", |
|||
"save_dev": "", |
|||
"usage": "", |
|||
"metrics_registry": "https://registry.npmjs.org/", |
|||
"otp": "", |
|||
"package_lock": "true", |
|||
"progress": "true", |
|||
"https_proxy": "", |
|||
"save_prod": "", |
|||
"cidr": "", |
|||
"onload_script": "", |
|||
"sso_type": "oauth", |
|||
"rebuild_bundle": "true", |
|||
"save_bundle": "", |
|||
"shell": "/bin/bash", |
|||
"dry_run": "", |
|||
"prefix": "/usr", |
|||
"scope": "", |
|||
"browser": "", |
|||
"cache_lock_wait": "10000", |
|||
"ignore_prepublish": "", |
|||
"registry": "https://registry.npmjs.org/", |
|||
"save_optional": "", |
|||
"searchopts": "", |
|||
"versions": "", |
|||
"cache": "/home/osboxes/.npm", |
|||
"send_metrics": "", |
|||
"global_style": "", |
|||
"ignore_scripts": "", |
|||
"version": "", |
|||
"local_address": "", |
|||
"viewer": "man", |
|||
"node_gyp": "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js", |
|||
"prefer_offline": "", |
|||
"color": "true", |
|||
"fetch_retry_mintimeout": "10000", |
|||
"maxsockets": "50", |
|||
"offline": "", |
|||
"sso_poll_frequency": "500", |
|||
"umask": "0022", |
|||
"fetch_retry_maxtimeout": "60000", |
|||
"logs_max": "10", |
|||
"message": "%s", |
|||
"ca": "", |
|||
"cert": "", |
|||
"global": "", |
|||
"link": "", |
|||
"access": "", |
|||
"also": "", |
|||
"save": "true", |
|||
"unicode": "true", |
|||
"long": "", |
|||
"production": "", |
|||
"searchlimit": "20", |
|||
"unsafe_perm": "true", |
|||
"auth_type": "legacy", |
|||
"node_version": "9.8.0", |
|||
"tag": "latest", |
|||
"git_tag_version": "true", |
|||
"commit_hooks": "true", |
|||
"script_shell": "", |
|||
"shrinkwrap": "true", |
|||
"fetch_retry_factor": "10", |
|||
"save_exact": "", |
|||
"strict_ssl": "true", |
|||
"dev": "", |
|||
"globalconfig": "/usr/etc/npmrc", |
|||
"init_module": "/home/osboxes/.npm-init.js", |
|||
"parseable": "", |
|||
"globalignorefile": "/usr/etc/npmignore", |
|||
"cache_lock_retries": "10", |
|||
"searchstaleness": "900", |
|||
"node_options": "", |
|||
"save_prefix": "^", |
|||
"scripts_prepend_node_path": "warn-only", |
|||
"group": "1000", |
|||
"init_author_email": "", |
|||
"searchexclude": "", |
|||
"git": "git", |
|||
"optional": "true", |
|||
"json": "" |
|||
} |
|||
} |
@ -0,0 +1,182 @@ |
|||
# This file is generated by gyp; do not edit.
|
|||
|
|||
TOOLSET := target |
|||
TARGET := equihashverify |
|||
DEFS_Debug := \
|
|||
'-DNODE_GYP_MODULE_NAME=equihashverify' \
|
|||
'-DUSING_UV_SHARED=1' \
|
|||
'-DUSING_V8_SHARED=1' \
|
|||
'-DV8_DEPRECATION_WARNINGS=1' \
|
|||
'-D_LARGEFILE_SOURCE' \
|
|||
'-D_FILE_OFFSET_BITS=64' \
|
|||
'-DHAVE_DECL_STRNLEN=1' \
|
|||
'-DHAVE_BYTESWAP_H=1' \
|
|||
'-DBUILDING_NODE_EXTENSION' \
|
|||
'-DDEBUG' \
|
|||
'-D_DEBUG' \
|
|||
'-DV8_ENABLE_CHECKS' |
|||
|
|||
# Flags passed to all source files.
|
|||
CFLAGS_Debug := \
|
|||
-fPIC \
|
|||
-pthread \
|
|||
-Wall \
|
|||
-Wextra \
|
|||
-Wno-unused-parameter \
|
|||
-m64 \
|
|||
-g \
|
|||
-O0 |
|||
|
|||
# Flags passed to only C files.
|
|||
CFLAGS_C_Debug := |
|||
|
|||
# Flags passed to only C++ files.
|
|||
CFLAGS_CC_Debug := \
|
|||
-fno-rtti \
|
|||
-fno-exceptions \
|
|||
-std=gnu++0x \
|
|||
-std=c++11 \
|
|||
-Wl,--whole-archive \
|
|||
-fPIC \
|
|||
-fexceptions |
|||
|
|||
INCS_Debug := \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/include/node \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/src \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/deps/uv/include \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/deps/v8/include \
|
|||
-I$(srcdir)/node_modules/nan \
|
|||
-I$(srcdir)/. \
|
|||
-I/usr/include |
|||
|
|||
DEFS_Release := \
|
|||
'-DNODE_GYP_MODULE_NAME=equihashverify' \
|
|||
'-DUSING_UV_SHARED=1' \
|
|||
'-DUSING_V8_SHARED=1' \
|
|||
'-DV8_DEPRECATION_WARNINGS=1' \
|
|||
'-D_LARGEFILE_SOURCE' \
|
|||
'-D_FILE_OFFSET_BITS=64' \
|
|||
'-DHAVE_DECL_STRNLEN=1' \
|
|||
'-DHAVE_BYTESWAP_H=1' \
|
|||
'-DBUILDING_NODE_EXTENSION' |
|||
|
|||
# Flags passed to all source files.
|
|||
CFLAGS_Release := \
|
|||
-fPIC \
|
|||
-pthread \
|
|||
-Wall \
|
|||
-Wextra \
|
|||
-Wno-unused-parameter \
|
|||
-m64 \
|
|||
-O3 \
|
|||
-fno-omit-frame-pointer |
|||
|
|||
# Flags passed to only C files.
|
|||
CFLAGS_C_Release := |
|||
|
|||
# Flags passed to only C++ files.
|
|||
CFLAGS_CC_Release := \
|
|||
-fno-rtti \
|
|||
-fno-exceptions \
|
|||
-std=gnu++0x \
|
|||
-std=c++11 \
|
|||
-Wl,--whole-archive \
|
|||
-fPIC \
|
|||
-fexceptions |
|||
|
|||
INCS_Release := \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/include/node \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/src \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/deps/uv/include \
|
|||
-I/home/osboxes/.node-gyp/9.8.0/deps/v8/include \
|
|||
-I$(srcdir)/node_modules/nan \
|
|||
-I$(srcdir)/. \
|
|||
-I/usr/include |
|||
|
|||
OBJS := \
|
|||
$(obj).target/$(TARGET)/support/cleanse.o \
|
|||
$(obj).target/$(TARGET)/uint256.o \
|
|||
$(obj).target/$(TARGET)/random.o \
|
|||
$(obj).target/$(TARGET)/util.o \
|
|||
$(obj).target/$(TARGET)/utiltime.o \
|
|||
$(obj).target/$(TARGET)/utilstrencodings.o \
|
|||
$(obj).target/$(TARGET)/crypto/equihash.o \
|
|||
$(obj).target/$(TARGET)/crypto/hmac_sha256.o \
|
|||
$(obj).target/$(TARGET)/crypto/hmac_sha512.o \
|
|||
$(obj).target/$(TARGET)/crypto/ripemd160.o \
|
|||
$(obj).target/$(TARGET)/crypto/sha1.o \
|
|||
$(obj).target/$(TARGET)/crypto/sha256.o \
|
|||
$(obj).target/$(TARGET)/crypto/sha512.o \
|
|||
$(obj).target/$(TARGET)/equihashverify.o |
|||
|
|||
# Add to the list of files we specially track dependencies for.
|
|||
all_deps += $(OBJS) |
|||
|
|||
# CFLAGS et al overrides must be target-local.
|
|||
# See "Target-specific Variable Values" in the GNU Make manual.
|
|||
$(OBJS): TOOLSET := $(TOOLSET) |
|||
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) |
|||
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) |
|||
|
|||
# Suffix rules, putting all outputs into $(obj).
|
|||
|
|||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
|
|||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
|
|||
# Try building from generated source, too.
|
|||
|
|||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
|
|||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
|
|||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
|
|||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cpp FORCE_DO_CMD |
|||
@$(call do_cmd,cxx,1) |
|||
|
|||
# End of this set of suffix rules
|
|||
### Rules for final target.
|
|||
LDFLAGS_Debug := \
|
|||
-pthread \
|
|||
-rdynamic \
|
|||
-m64 |
|||
|
|||
LDFLAGS_Release := \
|
|||
-pthread \
|
|||
-rdynamic \
|
|||
-m64 |
|||
|
|||
LIBS := \
|
|||
-Wl,-rpath,./build/Release/ |
|||
|
|||
$(obj).target/equihashverify.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) |
|||
$(obj).target/equihashverify.node: LIBS := $(LIBS) |
|||
$(obj).target/equihashverify.node: TOOLSET := $(TOOLSET) |
|||
$(obj).target/equihashverify.node: $(OBJS) FORCE_DO_CMD |
|||
$(call do_cmd,solink_module) |
|||
|
|||
all_deps += $(obj).target/equihashverify.node |
|||
# Add target alias
|
|||
.PHONY: equihashverify |
|||
equihashverify: $(builddir)/equihashverify.node |
|||
|
|||
# Copy this to the executable output path.
|
|||
$(builddir)/equihashverify.node: TOOLSET := $(TOOLSET) |
|||
$(builddir)/equihashverify.node: $(obj).target/equihashverify.node FORCE_DO_CMD |
|||
$(call do_cmd,copy) |
|||
|
|||
all_deps += $(builddir)/equihashverify.node |
|||
# Short alias for building this executable.
|
|||
.PHONY: equihashverify.node |
|||
equihashverify.node: $(obj).target/equihashverify.node $(builddir)/equihashverify.node |
|||
|
|||
# Add executable to "all" target.
|
|||
.PHONY: all |
|||
all: $(builddir)/equihashverify.node |
|||
|
@ -0,0 +1,110 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_COMMON_H |
|||
#define BITCOIN_CRYPTO_COMMON_H |
|||
|
|||
#if defined(HAVE_CONFIG_H) |
|||
#include "bitcoin-config.h" |
|||
#endif |
|||
|
|||
#include <stdint.h> |
|||
#include <assert.h> |
|||
|
|||
#include "sodium.h" |
|||
#include <endian.h> |
|||
|
|||
#if defined(NDEBUG) |
|||
# error "Zcash cannot be compiled without assertions." |
|||
#endif |
|||
|
|||
uint16_t static inline ReadLE16(const unsigned char* ptr) |
|||
{ |
|||
return le16toh(*((uint16_t*)ptr)); |
|||
} |
|||
|
|||
uint32_t static inline ReadLE32(const unsigned char* ptr) |
|||
{ |
|||
return le32toh(*((uint32_t*)ptr)); |
|||
} |
|||
|
|||
uint64_t static inline ReadLE64(const unsigned char* ptr) |
|||
{ |
|||
return le64toh(*((uint64_t*)ptr)); |
|||
} |
|||
|
|||
void static inline WriteLE16(unsigned char* ptr, uint16_t x) |
|||
{ |
|||
*((uint16_t*)ptr) = htole16(x); |
|||
} |
|||
|
|||
void static inline WriteLE32(unsigned char* ptr, uint32_t x) |
|||
{ |
|||
*((uint32_t*)ptr) = htole32(x); |
|||
} |
|||
|
|||
void static inline WriteLE64(unsigned char* ptr, uint64_t x) |
|||
{ |
|||
*((uint64_t*)ptr) = htole64(x); |
|||
} |
|||
|
|||
uint32_t static inline ReadBE32(const unsigned char* ptr) |
|||
{ |
|||
return be32toh(*((uint32_t*)ptr)); |
|||
} |
|||
|
|||
uint64_t static inline ReadBE64(const unsigned char* ptr) |
|||
{ |
|||
return be64toh(*((uint64_t*)ptr)); |
|||
} |
|||
|
|||
void static inline WriteBE32(unsigned char* ptr, uint32_t x) |
|||
{ |
|||
*((uint32_t*)ptr) = htobe32(x); |
|||
} |
|||
|
|||
void static inline WriteBE64(unsigned char* ptr, uint64_t x) |
|||
{ |
|||
*((uint64_t*)ptr) = htobe64(x); |
|||
} |
|||
|
|||
int inline init_and_check_sodium() |
|||
{ |
|||
if (sodium_init() == -1) { |
|||
return -1; |
|||
} |
|||
|
|||
// What follows is a runtime test that ensures the version of libsodium
|
|||
// we're linked against checks that signatures are canonical (s < L).
|
|||
const unsigned char message[1] = { 0 }; |
|||
|
|||
unsigned char pk[crypto_sign_PUBLICKEYBYTES]; |
|||
unsigned char sk[crypto_sign_SECRETKEYBYTES]; |
|||
unsigned char sig[crypto_sign_BYTES]; |
|||
|
|||
crypto_sign_keypair(pk, sk); |
|||
crypto_sign_detached(sig, NULL, message, sizeof(message), sk); |
|||
|
|||
assert(crypto_sign_verify_detached(sig, message, sizeof(message), pk) == 0); |
|||
|
|||
// Copied from libsodium/crypto_sign/ed25519/ref10/open.c
|
|||
static const unsigned char L[32] = |
|||
{ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, |
|||
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, |
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; |
|||
|
|||
// Add L to S, which starts at sig[32].
|
|||
unsigned int s = 0; |
|||
for (size_t i = 0; i < 32; i++) { |
|||
s = sig[32 + i] + L[i] + (s >> 8); |
|||
sig[32 + i] = s & 0xff; |
|||
} |
|||
|
|||
assert(crypto_sign_verify_detached(sig, message, sizeof(message), pk) != 0); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
#endif // BITCOIN_CRYPTO_COMMON_H
|
@ -0,0 +1,818 @@ |
|||
// Copyright (c) 2016 Jack Grigg
|
|||
// Copyright (c) 2016 The Zcash developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
// Implementation of the Equihash Proof-of-Work algorithm.
|
|||
//
|
|||
// Reference
|
|||
// =========
|
|||
// Alex Biryukov and Dmitry Khovratovich
|
|||
// Equihash: Asymmetric Proof-of-Work Based on the Generalized Birthday Problem
|
|||
// NDSS ’16, 21-24 February 2016, San Diego, CA, USA
|
|||
// https://www.internetsociety.org/sites/default/files/blogs-media/equihash-asymmetric-proof-of-work-based-generalized-birthday-problem.pdf
|
|||
|
|||
#if defined(HAVE_CONFIG_H) |
|||
#include "config/bitcoin-config.h" |
|||
#endif |
|||
|
|||
#include <endian.h> |
|||
#include "crypto/equihash.h" |
|||
#include <algorithm> |
|||
#include <iostream> |
|||
#include <stdexcept> |
|||
|
|||
#include <boost/optional.hpp> |
|||
#include "../util.h" |
|||
|
|||
EhSolverCancelledException solver_cancelled; |
|||
|
|||
template<unsigned int N, unsigned int K> |
|||
int Equihash<N,K>::InitialiseState(eh_HashState& base_state) |
|||
{ |
|||
uint32_t le_N = htole32(N); |
|||
uint32_t le_K = htole32(K); |
|||
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {}; |
|||
memcpy(personalization, "ZcashPoW", 8); |
|||
memcpy(personalization+8, &le_N, 4); |
|||
memcpy(personalization+12, &le_K, 4); |
|||
return crypto_generichash_blake2b_init_salt_personal(&base_state, |
|||
NULL, 0, // No key.
|
|||
(512/N)*N/8, |
|||
NULL, // No salt.
|
|||
personalization); |
|||
} |
|||
|
|||
void GenerateHash(const eh_HashState& base_state, eh_index g, |
|||
unsigned char* hash, size_t hLen) |
|||
{ |
|||
eh_HashState state; |
|||
state = base_state; |
|||
eh_index lei = htole32(g); |
|||
crypto_generichash_blake2b_update(&state, (const unsigned char*) &lei, |
|||
sizeof(eh_index)); |
|||
crypto_generichash_blake2b_final(&state, hash, hLen); |
|||
} |
|||
|
|||
void ExpandArray(const unsigned char* in, size_t in_len, |
|||
unsigned char* out, size_t out_len, |
|||
size_t bit_len, size_t byte_pad) |
|||
{ |
|||
assert(bit_len >= 8); |
|||
assert(8*sizeof(uint32_t) >= 7+bit_len); |
|||
|
|||
size_t out_width { (bit_len+7)/8 + byte_pad }; |
|||
assert(out_len == 8*out_width*in_len/bit_len); |
|||
|
|||
uint32_t bit_len_mask { ((uint32_t)1 << bit_len) - 1 }; |
|||
|
|||
// The acc_bits least-significant bits of acc_value represent a bit sequence
|
|||
// in big-endian order.
|
|||
size_t acc_bits = 0; |
|||
uint32_t acc_value = 0; |
|||
|
|||
size_t j = 0; |
|||
for (size_t i = 0; i < in_len; i++) { |
|||
acc_value = (acc_value << 8) | in[i]; |
|||
acc_bits += 8; |
|||
|
|||
// When we have bit_len or more bits in the accumulator, write the next
|
|||
// output element.
|
|||
if (acc_bits >= bit_len) { |
|||
acc_bits -= bit_len; |
|||
for (size_t x = 0; x < byte_pad; x++) { |
|||
out[j+x] = 0; |
|||
} |
|||
for (size_t x = byte_pad; x < out_width; x++) { |
|||
out[j+x] = ( |
|||
// Big-endian
|
|||
acc_value >> (acc_bits+(8*(out_width-x-1))) |
|||
) & ( |
|||
// Apply bit_len_mask across byte boundaries
|
|||
(bit_len_mask >> (8*(out_width-x-1))) & 0xFF |
|||
); |
|||
} |
|||
j += out_width; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void CompressArray(const unsigned char* in, size_t in_len, |
|||
unsigned char* out, size_t out_len, |
|||
size_t bit_len, size_t byte_pad) |
|||
{ |
|||
assert(bit_len >= 8); |
|||
assert(8*sizeof(uint32_t) >= 7+bit_len); |
|||
|
|||
size_t in_width { (bit_len+7)/8 + byte_pad }; |
|||
assert(out_len == bit_len*in_len/(8*in_width)); |
|||
|
|||
uint32_t bit_len_mask { ((uint32_t)1 << bit_len) - 1 }; |
|||
|
|||
// The acc_bits least-significant bits of acc_value represent a bit sequence
|
|||
// in big-endian order.
|
|||
size_t acc_bits = 0; |
|||
uint32_t acc_value = 0; |
|||
|
|||
size_t j = 0; |
|||
for (size_t i = 0; i < out_len; i++) { |
|||
// When we have fewer than 8 bits left in the accumulator, read the next
|
|||
// input element.
|
|||
if (acc_bits < 8) { |
|||
acc_value = acc_value << bit_len; |
|||
for (size_t x = byte_pad; x < in_width; x++) { |
|||
acc_value = acc_value | ( |
|||
( |
|||
// Apply bit_len_mask across byte boundaries
|
|||
in[j+x] & ((bit_len_mask >> (8*(in_width-x-1))) & 0xFF) |
|||
) << (8*(in_width-x-1))); // Big-endian
|
|||
} |
|||
j += in_width; |
|||
acc_bits += bit_len; |
|||
} |
|||
|
|||
acc_bits -= 8; |
|||
out[i] = (acc_value >> acc_bits) & 0xFF; |
|||
} |
|||
} |
|||
|
|||
// Big-endian so that lexicographic array comparison is equivalent to integer
|
|||
// comparison
|
|||
void EhIndexToArray(const eh_index i, unsigned char* array) |
|||
{ |
|||
BOOST_STATIC_ASSERT(sizeof(eh_index) == 4); |
|||
eh_index bei = htobe32(i); |
|||
memcpy(array, &bei, sizeof(eh_index)); |
|||
} |
|||
|
|||
// Big-endian so that lexicographic array comparison is equivalent to integer
|
|||
// comparison
|
|||
eh_index ArrayToEhIndex(const unsigned char* array) |
|||
{ |
|||
BOOST_STATIC_ASSERT(sizeof(eh_index) == 4); |
|||
eh_index bei; |
|||
memcpy(&bei, array, sizeof(eh_index)); |
|||
return be32toh(bei); |
|||
} |
|||
|
|||
eh_trunc TruncateIndex(const eh_index i, const unsigned int ilen) |
|||
{ |
|||
// Truncate to 8 bits
|
|||
BOOST_STATIC_ASSERT(sizeof(eh_trunc) == 1); |
|||
return (i >> (ilen - 8)) & 0xff; |
|||
} |
|||
|
|||
eh_index UntruncateIndex(const eh_trunc t, const eh_index r, const unsigned int ilen) |
|||
{ |
|||
eh_index i{t}; |
|||
return (i << (ilen - 8)) | r; |
|||
} |
|||
|
|||
std::vector<eh_index> GetIndicesFromMinimal(std::vector<unsigned char> minimal, |
|||
size_t cBitLen) |
|||
{ |
|||
assert(((cBitLen+1)+7)/8 <= sizeof(eh_index)); |
|||
size_t lenIndices { 8*sizeof(eh_index)*minimal.size()/(cBitLen+1) }; |
|||
size_t bytePad { sizeof(eh_index) - ((cBitLen+1)+7)/8 }; |
|||
std::vector<unsigned char> array(lenIndices); |
|||
ExpandArray(minimal.data(), minimal.size(), |
|||
array.data(), lenIndices, cBitLen+1, bytePad); |
|||
std::vector<eh_index> ret; |
|||
for (int i = 0; i < lenIndices; i += sizeof(eh_index)) { |
|||
ret.push_back(ArrayToEhIndex(array.data()+i)); |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
std::vector<unsigned char> GetMinimalFromIndices(std::vector<eh_index> indices, |
|||
size_t cBitLen) |
|||
{ |
|||
assert(((cBitLen+1)+7)/8 <= sizeof(eh_index)); |
|||
size_t lenIndices { indices.size()*sizeof(eh_index) }; |
|||
size_t minLen { (cBitLen+1)*lenIndices/(8*sizeof(eh_index)) }; |
|||
size_t bytePad { sizeof(eh_index) - ((cBitLen+1)+7)/8 }; |
|||
std::vector<unsigned char> array(lenIndices); |
|||
for (int i = 0; i < indices.size(); i++) { |
|||
EhIndexToArray(indices[i], array.data()+(i*sizeof(eh_index))); |
|||
} |
|||
std::vector<unsigned char> ret(minLen); |
|||
CompressArray(array.data(), lenIndices, |
|||
ret.data(), minLen, cBitLen+1, bytePad); |
|||
return ret; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
StepRow<WIDTH>::StepRow(const unsigned char* hashIn, size_t hInLen, |
|||
size_t hLen, size_t cBitLen) |
|||
{ |
|||
assert(hLen <= WIDTH); |
|||
ExpandArray(hashIn, hInLen, hash, hLen, cBitLen); |
|||
} |
|||
|
|||
template<size_t WIDTH> template<size_t W> |
|||
StepRow<WIDTH>::StepRow(const StepRow<W>& a) |
|||
{ |
|||
BOOST_STATIC_ASSERT(W <= WIDTH); |
|||
std::copy(a.hash, a.hash+W, hash); |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
FullStepRow<WIDTH>::FullStepRow(const unsigned char* hashIn, size_t hInLen, |
|||
size_t hLen, size_t cBitLen, eh_index i) : |
|||
StepRow<WIDTH> {hashIn, hInLen, hLen, cBitLen} |
|||
{ |
|||
EhIndexToArray(i, hash+hLen); |
|||
} |
|||
|
|||
template<size_t WIDTH> template<size_t W> |
|||
FullStepRow<WIDTH>::FullStepRow(const FullStepRow<W>& a, const FullStepRow<W>& b, size_t len, size_t lenIndices, int trim) : |
|||
StepRow<WIDTH> {a} |
|||
{ |
|||
assert(len+lenIndices <= W); |
|||
assert(len-trim+(2*lenIndices) <= WIDTH); |
|||
for (int i = trim; i < len; i++) |
|||
hash[i-trim] = a.hash[i] ^ b.hash[i]; |
|||
if (a.IndicesBefore(b, len, lenIndices)) { |
|||
std::copy(a.hash+len, a.hash+len+lenIndices, hash+len-trim); |
|||
std::copy(b.hash+len, b.hash+len+lenIndices, hash+len-trim+lenIndices); |
|||
} else { |
|||
std::copy(b.hash+len, b.hash+len+lenIndices, hash+len-trim); |
|||
std::copy(a.hash+len, a.hash+len+lenIndices, hash+len-trim+lenIndices); |
|||
} |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
FullStepRow<WIDTH>& FullStepRow<WIDTH>::operator=(const FullStepRow<WIDTH>& a) |
|||
{ |
|||
std::copy(a.hash, a.hash+WIDTH, hash); |
|||
return *this; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
bool StepRow<WIDTH>::IsZero(size_t len) |
|||
{ |
|||
// This doesn't need to be constant time.
|
|||
for (int i = 0; i < len; i++) { |
|||
if (hash[i] != 0) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
std::vector<unsigned char> FullStepRow<WIDTH>::GetIndices(size_t len, size_t lenIndices, |
|||
size_t cBitLen) const |
|||
{ |
|||
assert(((cBitLen+1)+7)/8 <= sizeof(eh_index)); |
|||
size_t minLen { (cBitLen+1)*lenIndices/(8*sizeof(eh_index)) }; |
|||
size_t bytePad { sizeof(eh_index) - ((cBitLen+1)+7)/8 }; |
|||
std::vector<unsigned char> ret(minLen); |
|||
CompressArray(hash+len, lenIndices, ret.data(), minLen, cBitLen+1, bytePad); |
|||
return ret; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
bool HasCollision(StepRow<WIDTH>& a, StepRow<WIDTH>& b, int l) |
|||
{ |
|||
// This doesn't need to be constant time.
|
|||
for (int j = 0; j < l; j++) { |
|||
if (a.hash[j] != b.hash[j]) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
TruncatedStepRow<WIDTH>::TruncatedStepRow(const unsigned char* hashIn, size_t hInLen, |
|||
size_t hLen, size_t cBitLen, |
|||
eh_index i, unsigned int ilen) : |
|||
StepRow<WIDTH> {hashIn, hInLen, hLen, cBitLen} |
|||
{ |
|||
hash[hLen] = TruncateIndex(i, ilen); |
|||
} |
|||
|
|||
template<size_t WIDTH> template<size_t W> |
|||
TruncatedStepRow<WIDTH>::TruncatedStepRow(const TruncatedStepRow<W>& a, const TruncatedStepRow<W>& b, size_t len, size_t lenIndices, int trim) : |
|||
StepRow<WIDTH> {a} |
|||
{ |
|||
assert(len+lenIndices <= W); |
|||
assert(len-trim+(2*lenIndices) <= WIDTH); |
|||
for (int i = trim; i < len; i++) |
|||
hash[i-trim] = a.hash[i] ^ b.hash[i]; |
|||
if (a.IndicesBefore(b, len, lenIndices)) { |
|||
std::copy(a.hash+len, a.hash+len+lenIndices, hash+len-trim); |
|||
std::copy(b.hash+len, b.hash+len+lenIndices, hash+len-trim+lenIndices); |
|||
} else { |
|||
std::copy(b.hash+len, b.hash+len+lenIndices, hash+len-trim); |
|||
std::copy(a.hash+len, a.hash+len+lenIndices, hash+len-trim+lenIndices); |
|||
} |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
TruncatedStepRow<WIDTH>& TruncatedStepRow<WIDTH>::operator=(const TruncatedStepRow<WIDTH>& a) |
|||
{ |
|||
std::copy(a.hash, a.hash+WIDTH, hash); |
|||
return *this; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
std::shared_ptr<eh_trunc> TruncatedStepRow<WIDTH>::GetTruncatedIndices(size_t len, size_t lenIndices) const |
|||
{ |
|||
std::shared_ptr<eh_trunc> p (new eh_trunc[lenIndices], std::default_delete<eh_trunc[]>()); |
|||
std::copy(hash+len, hash+len+lenIndices, p.get()); |
|||
return p; |
|||
} |
|||
|
|||
#ifdef ENABLE_MINING |
|||
template<unsigned int N, unsigned int K> |
|||
bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled) |
|||
{ |
|||
eh_index init_size { 1 << (CollisionBitLength + 1) }; |
|||
|
|||
// 1) Generate first list
|
|||
LogPrint("pow", "Generating first list\n"); |
|||
size_t hashLen = HashLength; |
|||
size_t lenIndices = sizeof(eh_index); |
|||
std::vector<FullStepRow<FullWidth>> X; |
|||
X.reserve(init_size); |
|||
unsigned char tmpHash[HashOutput]; |
|||
for (eh_index g = 0; X.size() < init_size; g++) { |
|||
GenerateHash(base_state, g, tmpHash, HashOutput); |
|||
for (eh_index i = 0; i < IndicesPerHashOutput && X.size() < init_size; i++) { |
|||
X.emplace_back(tmpHash+(i*N/8), N/8, HashLength, |
|||
CollisionBitLength, (g*IndicesPerHashOutput)+i); |
|||
} |
|||
if (cancelled(ListGeneration)) throw solver_cancelled; |
|||
} |
|||
|
|||
// 3) Repeat step 2 until 2n/(k+1) bits remain
|
|||
for (int r = 1; r < K && X.size() > 0; r++) { |
|||
LogPrint("pow", "Round %d:\n", r); |
|||
// 2a) Sort the list
|
|||
LogPrint("pow", "- Sorting list\n"); |
|||
std::sort(X.begin(), X.end(), CompareSR(CollisionByteLength)); |
|||
if (cancelled(ListSorting)) throw solver_cancelled; |
|||
|
|||
LogPrint("pow", "- Finding collisions\n"); |
|||
int i = 0; |
|||
int posFree = 0; |
|||
std::vector<FullStepRow<FullWidth>> Xc; |
|||
while (i < X.size() - 1) { |
|||
// 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits
|
|||
int j = 1; |
|||
while (i+j < X.size() && |
|||
HasCollision(X[i], X[i+j], CollisionByteLength)) { |
|||
j++; |
|||
} |
|||
|
|||
// 2c) Calculate tuples (X_i ^ X_j, (i, j))
|
|||
for (int l = 0; l < j - 1; l++) { |
|||
for (int m = l + 1; m < j; m++) { |
|||
if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices)) { |
|||
Xc.emplace_back(X[i+l], X[i+m], hashLen, lenIndices, CollisionByteLength); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 2d) Store tuples on the table in-place if possible
|
|||
while (posFree < i+j && Xc.size() > 0) { |
|||
X[posFree++] = Xc.back(); |
|||
Xc.pop_back(); |
|||
} |
|||
|
|||
i += j; |
|||
if (cancelled(ListColliding)) throw solver_cancelled; |
|||
} |
|||
|
|||
// 2e) Handle edge case where final table entry has no collision
|
|||
while (posFree < X.size() && Xc.size() > 0) { |
|||
X[posFree++] = Xc.back(); |
|||
Xc.pop_back(); |
|||
} |
|||
|
|||
if (Xc.size() > 0) { |
|||
// 2f) Add overflow to end of table
|
|||
X.insert(X.end(), Xc.begin(), Xc.end()); |
|||
} else if (posFree < X.size()) { |
|||
// 2g) Remove empty space at the end
|
|||
X.erase(X.begin()+posFree, X.end()); |
|||
X.shrink_to_fit(); |
|||
} |
|||
|
|||
hashLen -= CollisionByteLength; |
|||
lenIndices *= 2; |
|||
if (cancelled(RoundEnd)) throw solver_cancelled; |
|||
} |
|||
|
|||
// k+1) Find a collision on last 2n(k+1) bits
|
|||
LogPrint("pow", "Final round:\n"); |
|||
if (X.size() > 1) { |
|||
LogPrint("pow", "- Sorting list\n"); |
|||
std::sort(X.begin(), X.end(), CompareSR(hashLen)); |
|||
if (cancelled(FinalSorting)) throw solver_cancelled; |
|||
LogPrint("pow", "- Finding collisions\n"); |
|||
int i = 0; |
|||
while (i < X.size() - 1) { |
|||
int j = 1; |
|||
while (i+j < X.size() && |
|||
HasCollision(X[i], X[i+j], hashLen)) { |
|||
j++; |
|||
} |
|||
|
|||
for (int l = 0; l < j - 1; l++) { |
|||
for (int m = l + 1; m < j; m++) { |
|||
FullStepRow<FinalFullWidth> res(X[i+l], X[i+m], hashLen, lenIndices, 0); |
|||
if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices)) { |
|||
auto soln = res.GetIndices(hashLen, 2*lenIndices, CollisionBitLength); |
|||
assert(soln.size() == equihash_solution_size(N, K)); |
|||
if (validBlock(soln)) { |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
i += j; |
|||
if (cancelled(FinalColliding)) throw solver_cancelled; |
|||
} |
|||
} else |
|||
LogPrint("pow", "- List is empty\n"); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
void CollideBranches(std::vector<FullStepRow<WIDTH>>& X, const size_t hlen, const size_t lenIndices, const unsigned int clen, const unsigned int ilen, const eh_trunc lt, const eh_trunc rt) |
|||
{ |
|||
int i = 0; |
|||
int posFree = 0; |
|||
std::vector<FullStepRow<WIDTH>> Xc; |
|||
while (i < X.size() - 1) { |
|||
// 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits
|
|||
int j = 1; |
|||
while (i+j < X.size() && |
|||
HasCollision(X[i], X[i+j], clen)) { |
|||
j++; |
|||
} |
|||
|
|||
// 2c) Calculate tuples (X_i ^ X_j, (i, j))
|
|||
for (int l = 0; l < j - 1; l++) { |
|||
for (int m = l + 1; m < j; m++) { |
|||
if (DistinctIndices(X[i+l], X[i+m], hlen, lenIndices)) { |
|||
if (IsValidBranch(X[i+l], hlen, ilen, lt) && IsValidBranch(X[i+m], hlen, ilen, rt)) { |
|||
Xc.emplace_back(X[i+l], X[i+m], hlen, lenIndices, clen); |
|||
} else if (IsValidBranch(X[i+m], hlen, ilen, lt) && IsValidBranch(X[i+l], hlen, ilen, rt)) { |
|||
Xc.emplace_back(X[i+m], X[i+l], hlen, lenIndices, clen); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 2d) Store tuples on the table in-place if possible
|
|||
while (posFree < i+j && Xc.size() > 0) { |
|||
X[posFree++] = Xc.back(); |
|||
Xc.pop_back(); |
|||
} |
|||
|
|||
i += j; |
|||
} |
|||
|
|||
// 2e) Handle edge case where final table entry has no collision
|
|||
while (posFree < X.size() && Xc.size() > 0) { |
|||
X[posFree++] = Xc.back(); |
|||
Xc.pop_back(); |
|||
} |
|||
|
|||
if (Xc.size() > 0) { |
|||
// 2f) Add overflow to end of table
|
|||
X.insert(X.end(), Xc.begin(), Xc.end()); |
|||
} else if (posFree < X.size()) { |
|||
// 2g) Remove empty space at the end
|
|||
X.erase(X.begin()+posFree, X.end()); |
|||
X.shrink_to_fit(); |
|||
} |
|||
} |
|||
|
|||
template<unsigned int N, unsigned int K> |
|||
bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled) |
|||
{ |
|||
eh_index init_size { 1 << (CollisionBitLength + 1) }; |
|||
eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength + 1) }; |
|||
|
|||
// First run the algorithm with truncated indices
|
|||
|
|||
const eh_index soln_size { 1 << K }; |
|||
std::vector<std::shared_ptr<eh_trunc>> partialSolns; |
|||
int invalidCount = 0; |
|||
{ |
|||
|
|||
// 1) Generate first list
|
|||
LogPrint("pow", "Generating first list\n"); |
|||
size_t hashLen = HashLength; |
|||
size_t lenIndices = sizeof(eh_trunc); |
|||
std::vector<TruncatedStepRow<TruncatedWidth>> Xt; |
|||
Xt.reserve(init_size); |
|||
unsigned char tmpHash[HashOutput]; |
|||
for (eh_index g = 0; Xt.size() < init_size; g++) { |
|||
GenerateHash(base_state, g, tmpHash, HashOutput); |
|||
for (eh_index i = 0; i < IndicesPerHashOutput && Xt.size() < init_size; i++) { |
|||
Xt.emplace_back(tmpHash+(i*N/8), N/8, HashLength, CollisionBitLength, |
|||
(g*IndicesPerHashOutput)+i, CollisionBitLength + 1); |
|||
} |
|||
if (cancelled(ListGeneration)) throw solver_cancelled; |
|||
} |
|||
|
|||
// 3) Repeat step 2 until 2n/(k+1) bits remain
|
|||
for (int r = 1; r < K && Xt.size() > 0; r++) { |
|||
LogPrint("pow", "Round %d:\n", r); |
|||
// 2a) Sort the list
|
|||
LogPrint("pow", "- Sorting list\n"); |
|||
std::sort(Xt.begin(), Xt.end(), CompareSR(CollisionByteLength)); |
|||
if (cancelled(ListSorting)) throw solver_cancelled; |
|||
|
|||
LogPrint("pow", "- Finding collisions\n"); |
|||
int i = 0; |
|||
int posFree = 0; |
|||
std::vector<TruncatedStepRow<TruncatedWidth>> Xc; |
|||
while (i < Xt.size() - 1) { |
|||
// 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits
|
|||
int j = 1; |
|||
while (i+j < Xt.size() && |
|||
HasCollision(Xt[i], Xt[i+j], CollisionByteLength)) { |
|||
j++; |
|||
} |
|||
|
|||
// 2c) Calculate tuples (X_i ^ X_j, (i, j))
|
|||
bool checking_for_zero = (i == 0 && Xt[0].IsZero(hashLen)); |
|||
for (int l = 0; l < j - 1; l++) { |
|||
for (int m = l + 1; m < j; m++) { |
|||
// We truncated, so don't check for distinct indices here
|
|||
TruncatedStepRow<TruncatedWidth> Xi {Xt[i+l], Xt[i+m], |
|||
hashLen, lenIndices, |
|||
CollisionByteLength}; |
|||
if (!(Xi.IsZero(hashLen-CollisionByteLength) && |
|||
IsProbablyDuplicate<soln_size>(Xi.GetTruncatedIndices(hashLen-CollisionByteLength, 2*lenIndices), |
|||
2*lenIndices))) { |
|||
Xc.emplace_back(Xi); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 2d) Store tuples on the table in-place if possible
|
|||
while (posFree < i+j && Xc.size() > 0) { |
|||
Xt[posFree++] = Xc.back(); |
|||
Xc.pop_back(); |
|||
} |
|||
|
|||
i += j; |
|||
if (cancelled(ListColliding)) throw solver_cancelled; |
|||
} |
|||
|
|||
// 2e) Handle edge case where final table entry has no collision
|
|||
while (posFree < Xt.size() && Xc.size() > 0) { |
|||
Xt[posFree++] = Xc.back(); |
|||
Xc.pop_back(); |
|||
} |
|||
|
|||
if (Xc.size() > 0) { |
|||
// 2f) Add overflow to end of table
|
|||
Xt.insert(Xt.end(), Xc.begin(), Xc.end()); |
|||
} else if (posFree < Xt.size()) { |
|||
// 2g) Remove empty space at the end
|
|||
Xt.erase(Xt.begin()+posFree, Xt.end()); |
|||
Xt.shrink_to_fit(); |
|||
} |
|||
|
|||
hashLen -= CollisionByteLength; |
|||
lenIndices *= 2; |
|||
if (cancelled(RoundEnd)) throw solver_cancelled; |
|||
} |
|||
|
|||
// k+1) Find a collision on last 2n(k+1) bits
|
|||
LogPrint("pow", "Final round:\n"); |
|||
if (Xt.size() > 1) { |
|||
LogPrint("pow", "- Sorting list\n"); |
|||
std::sort(Xt.begin(), Xt.end(), CompareSR(hashLen)); |
|||
if (cancelled(FinalSorting)) throw solver_cancelled; |
|||
LogPrint("pow", "- Finding collisions\n"); |
|||
int i = 0; |
|||
while (i < Xt.size() - 1) { |
|||
int j = 1; |
|||
while (i+j < Xt.size() && |
|||
HasCollision(Xt[i], Xt[i+j], hashLen)) { |
|||
j++; |
|||
} |
|||
|
|||
for (int l = 0; l < j - 1; l++) { |
|||
for (int m = l + 1; m < j; m++) { |
|||
TruncatedStepRow<FinalTruncatedWidth> res(Xt[i+l], Xt[i+m], |
|||
hashLen, lenIndices, 0); |
|||
auto soln = res.GetTruncatedIndices(hashLen, 2*lenIndices); |
|||
if (!IsProbablyDuplicate<soln_size>(soln, 2*lenIndices)) { |
|||
partialSolns.push_back(soln); |
|||
} |
|||
} |
|||
} |
|||
|
|||
i += j; |
|||
if (cancelled(FinalColliding)) throw solver_cancelled; |
|||
} |
|||
} else |
|||
LogPrint("pow", "- List is empty\n"); |
|||
|
|||
} // Ensure Xt goes out of scope and is destroyed
|
|||
|
|||
LogPrint("pow", "Found %d partial solutions\n", partialSolns.size()); |
|||
|
|||
// Now for each solution run the algorithm again to recreate the indices
|
|||
LogPrint("pow", "Culling solutions\n"); |
|||
for (std::shared_ptr<eh_trunc> partialSoln : partialSolns) { |
|||
std::set<std::vector<unsigned char>> solns; |
|||
size_t hashLen; |
|||
size_t lenIndices; |
|||
unsigned char tmpHash[HashOutput]; |
|||
std::vector<boost::optional<std::vector<FullStepRow<FinalFullWidth>>>> X; |
|||
X.reserve(K+1); |
|||
|
|||
// 3) Repeat steps 1 and 2 for each partial index
|
|||
for (eh_index i = 0; i < soln_size; i++) { |
|||
// 1) Generate first list of possibilities
|
|||
std::vector<FullStepRow<FinalFullWidth>> icv; |
|||
icv.reserve(recreate_size); |
|||
for (eh_index j = 0; j < recreate_size; j++) { |
|||
eh_index newIndex { UntruncateIndex(partialSoln.get()[i], j, CollisionBitLength + 1) }; |
|||
if (j == 0 || newIndex % IndicesPerHashOutput == 0) { |
|||
GenerateHash(base_state, newIndex/IndicesPerHashOutput, |
|||
tmpHash, HashOutput); |
|||
} |
|||
icv.emplace_back(tmpHash+((newIndex % IndicesPerHashOutput) * N/8), |
|||
N/8, HashLength, CollisionBitLength, newIndex); |
|||
if (cancelled(PartialGeneration)) throw solver_cancelled; |
|||
} |
|||
boost::optional<std::vector<FullStepRow<FinalFullWidth>>> ic = icv; |
|||
|
|||
// 2a) For each pair of lists:
|
|||
hashLen = HashLength; |
|||
lenIndices = sizeof(eh_index); |
|||
size_t rti = i; |
|||
for (size_t r = 0; r <= K; r++) { |
|||
// 2b) Until we are at the top of a subtree:
|
|||
if (r < X.size()) { |
|||
if (X[r]) { |
|||
// 2c) Merge the lists
|
|||
ic->reserve(ic->size() + X[r]->size()); |
|||
ic->insert(ic->end(), X[r]->begin(), X[r]->end()); |
|||
std::sort(ic->begin(), ic->end(), CompareSR(hashLen)); |
|||
if (cancelled(PartialSorting)) throw solver_cancelled; |
|||
size_t lti = rti-(1<<r); |
|||
CollideBranches(*ic, hashLen, lenIndices, |
|||
CollisionByteLength, |
|||
CollisionBitLength + 1, |
|||
partialSoln.get()[lti], partialSoln.get()[rti]); |
|||
|
|||
// 2d) Check if this has become an invalid solution
|
|||
if (ic->size() == 0) |
|||
goto invalidsolution; |
|||
|
|||
X[r] = boost::none; |
|||
hashLen -= CollisionByteLength; |
|||
lenIndices *= 2; |
|||
rti = lti; |
|||
} else { |
|||
X[r] = *ic; |
|||
break; |
|||
} |
|||
} else { |
|||
X.push_back(ic); |
|||
break; |
|||
} |
|||
if (cancelled(PartialSubtreeEnd)) throw solver_cancelled; |
|||
} |
|||
if (cancelled(PartialIndexEnd)) throw solver_cancelled; |
|||
} |
|||
|
|||
// We are at the top of the tree
|
|||
assert(X.size() == K+1); |
|||
for (FullStepRow<FinalFullWidth> row : *X[K]) { |
|||
auto soln = row.GetIndices(hashLen, lenIndices, CollisionBitLength); |
|||
assert(soln.size() == equihash_solution_size(N, K)); |
|||
solns.insert(soln); |
|||
} |
|||
for (auto soln : solns) { |
|||
if (validBlock(soln)) |
|||
return true; |
|||
} |
|||
if (cancelled(PartialEnd)) throw solver_cancelled; |
|||
continue; |
|||
|
|||
invalidsolution: |
|||
invalidCount++; |
|||
} |
|||
LogPrint("pow", "- Number of invalid solutions found: %d\n", invalidCount); |
|||
|
|||
return false; |
|||
} |
|||
#endif // ENABLE_MINING
|
|||
|
|||
|
|||
|
|||
template<unsigned int N, unsigned int K> |
|||
bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln) |
|||
{ |
|||
|
|||
if (soln.size() != SolutionWidth) { |
|||
LogPrint("pow", "Invalid solution length: %d (expected %d)\n", |
|||
soln.size(), SolutionWidth); |
|||
return false; |
|||
} |
|||
|
|||
std::vector<FullStepRow<FinalFullWidth>> X; |
|||
X.reserve(1 << K); |
|||
unsigned char tmpHash[HashOutput]; |
|||
for (eh_index i : GetIndicesFromMinimal(soln, CollisionBitLength)) { |
|||
GenerateHash(base_state, i/IndicesPerHashOutput, tmpHash, HashOutput); |
|||
X.emplace_back(tmpHash+((i % IndicesPerHashOutput) * N/8), |
|||
N/8, HashLength, CollisionBitLength, i); |
|||
} |
|||
|
|||
size_t hashLen = HashLength; |
|||
size_t lenIndices = sizeof(eh_index); |
|||
while (X.size() > 1) { |
|||
std::vector<FullStepRow<FinalFullWidth>> Xc; |
|||
for (int i = 0; i < X.size(); i += 2) { |
|||
if (!HasCollision(X[i], X[i+1], CollisionByteLength)) { |
|||
LogPrint("pow", "Invalid solution: invalid collision length between StepRows\n"); |
|||
LogPrint("pow", "X[i] = %s\n", X[i].GetHex(hashLen)); |
|||
LogPrint("pow", "X[i+1] = %s\n", X[i+1].GetHex(hashLen)); |
|||
return false; |
|||
} |
|||
if (X[i+1].IndicesBefore(X[i], hashLen, lenIndices)) { |
|||
LogPrint("pow", "Invalid solution: Index tree incorrectly ordered\n"); |
|||
return false; |
|||
} |
|||
if (!DistinctIndices(X[i], X[i+1], hashLen, lenIndices)) { |
|||
LogPrint("pow", "Invalid solution: duplicate indices\n"); |
|||
return false; |
|||
} |
|||
Xc.emplace_back(X[i], X[i+1], hashLen, lenIndices, CollisionByteLength); |
|||
} |
|||
X = Xc; |
|||
hashLen -= CollisionByteLength; |
|||
lenIndices *= 2; |
|||
} |
|||
|
|||
assert(X.size() == 1); |
|||
return X[0].IsZero(hashLen); |
|||
} |
|||
|
|||
// Explicit instantiations for Equihash<96,3>
|
|||
template int Equihash<96,3>::InitialiseState(eh_HashState& base_state); |
|||
#ifdef ENABLE_MINING |
|||
template bool Equihash<96,3>::BasicSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
template bool Equihash<96,3>::OptimisedSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
#endif |
|||
template bool Equihash<96,3>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln); |
|||
|
|||
// Explicit instantiations for Equihash<200,9>
|
|||
template int Equihash<200,9>::InitialiseState(eh_HashState& base_state); |
|||
#ifdef ENABLE_MINING |
|||
template bool Equihash<200,9>::BasicSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
template bool Equihash<200,9>::OptimisedSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
#endif |
|||
template bool Equihash<200,9>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln); |
|||
|
|||
// Explicit instantiations for Equihash<96,5>
|
|||
template int Equihash<96,5>::InitialiseState(eh_HashState& base_state); |
|||
#ifdef ENABLE_MINING |
|||
template bool Equihash<96,5>::BasicSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
template bool Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
#endif |
|||
template bool Equihash<96,5>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln); |
|||
|
|||
// Explicit instantiations for Equihash<48,5>
|
|||
template int Equihash<48,5>::InitialiseState(eh_HashState& base_state); |
|||
#ifdef ENABLE_MINING |
|||
template bool Equihash<48,5>::BasicSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
template bool Equihash<48,5>::OptimisedSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
#endif |
|||
template bool Equihash<48,5>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln); |
@ -0,0 +1,282 @@ |
|||
// Copyright (c) 2016 Jack Grigg
|
|||
// Copyright (c) 2016 The Zcash developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_EQUIHASH_H |
|||
#define BITCOIN_EQUIHASH_H |
|||
|
|||
#include "crypto/sha256.h" |
|||
#include "utilstrencodings.h" |
|||
|
|||
#include "sodium.h" |
|||
|
|||
#include <cstring> |
|||
#include <exception> |
|||
#include <functional> |
|||
#include <memory> |
|||
#include <set> |
|||
#include <vector> |
|||
|
|||
#include <boost/static_assert.hpp> |
|||
|
|||
|
|||
typedef crypto_generichash_blake2b_state eh_HashState; |
|||
typedef uint32_t eh_index; |
|||
typedef uint8_t eh_trunc; |
|||
|
|||
void ExpandArray(const unsigned char* in, size_t in_len, |
|||
unsigned char* out, size_t out_len, |
|||
size_t bit_len, size_t byte_pad=0); |
|||
void CompressArray(const unsigned char* in, size_t in_len, |
|||
unsigned char* out, size_t out_len, |
|||
size_t bit_len, size_t byte_pad=0); |
|||
void GenerateHash(const eh_HashState& base_state, eh_index g, |
|||
unsigned char* hash, size_t hLen) |
|||
|
|||
eh_index ArrayToEhIndex(const unsigned char* array); |
|||
eh_trunc TruncateIndex(const eh_index i, const unsigned int ilen); |
|||
|
|||
std::vector<eh_index> GetIndicesFromMinimal(std::vector<unsigned char> minimal, |
|||
size_t cBitLen); |
|||
std::vector<unsigned char> GetMinimalFromIndices(std::vector<eh_index> indices, |
|||
size_t cBitLen); |
|||
|
|||
template<size_t WIDTH> |
|||
class StepRow |
|||
{ |
|||
template<size_t W> |
|||
friend class StepRow; |
|||
friend class CompareSR; |
|||
|
|||
protected: |
|||
unsigned char hash[WIDTH]; |
|||
|
|||
public: |
|||
StepRow(const unsigned char* hashIn, size_t hInLen, |
|||
size_t hLen, size_t cBitLen); |
|||
~StepRow() { } |
|||
|
|||
template<size_t W> |
|||
StepRow(const StepRow<W>& a); |
|||
|
|||
bool IsZero(size_t len); |
|||
std::string GetHex(size_t len) { return HexStr(hash, hash+len); } |
|||
|
|||
template<size_t W> |
|||
friend bool HasCollision(StepRow<W>& a, StepRow<W>& b, int l); |
|||
}; |
|||
|
|||
class CompareSR |
|||
{ |
|||
private: |
|||
size_t len; |
|||
|
|||
public: |
|||
CompareSR(size_t l) : len {l} { } |
|||
|
|||
template<size_t W> |
|||
inline bool operator()(const StepRow<W>& a, const StepRow<W>& b) { return memcmp(a.hash, b.hash, len) < 0; } |
|||
}; |
|||
|
|||
template<size_t WIDTH> |
|||
bool HasCollision(StepRow<WIDTH>& a, StepRow<WIDTH>& b, int l); |
|||
|
|||
template<size_t WIDTH> |
|||
class FullStepRow : public StepRow<WIDTH> |
|||
{ |
|||
template<size_t W> |
|||
friend class FullStepRow; |
|||
|
|||
using StepRow<WIDTH>::hash; |
|||
|
|||
public: |
|||
FullStepRow(const unsigned char* hashIn, size_t hInLen, |
|||
size_t hLen, size_t cBitLen, eh_index i); |
|||
~FullStepRow() { } |
|||
|
|||
FullStepRow(const FullStepRow<WIDTH>& a) : StepRow<WIDTH> {a} { } |
|||
template<size_t W> |
|||
FullStepRow(const FullStepRow<W>& a, const FullStepRow<W>& b, size_t len, size_t lenIndices, int trim); |
|||
FullStepRow& operator=(const FullStepRow<WIDTH>& a); |
|||
|
|||
inline bool IndicesBefore(const FullStepRow<WIDTH>& a, size_t len, size_t lenIndices) const { return memcmp(hash+len, a.hash+len, lenIndices) < 0; } |
|||
std::vector<unsigned char> GetIndices(size_t len, size_t lenIndices, |
|||
size_t cBitLen) const; |
|||
|
|||
template<size_t W> |
|||
friend bool DistinctIndices(const FullStepRow<W>& a, const FullStepRow<W>& b, |
|||
size_t len, size_t lenIndices); |
|||
template<size_t W> |
|||
friend bool IsValidBranch(const FullStepRow<W>& a, const size_t len, const unsigned int ilen, const eh_trunc t); |
|||
}; |
|||
|
|||
template<size_t WIDTH> |
|||
class TruncatedStepRow : public StepRow<WIDTH> |
|||
{ |
|||
template<size_t W> |
|||
friend class TruncatedStepRow; |
|||
|
|||
using StepRow<WIDTH>::hash; |
|||
|
|||
public: |
|||
TruncatedStepRow(const unsigned char* hashIn, size_t hInLen, |
|||
size_t hLen, size_t cBitLen, |
|||
eh_index i, unsigned int ilen); |
|||
~TruncatedStepRow() { } |
|||
|
|||
TruncatedStepRow(const TruncatedStepRow<WIDTH>& a) : StepRow<WIDTH> {a} { } |
|||
template<size_t W> |
|||
TruncatedStepRow(const TruncatedStepRow<W>& a, const TruncatedStepRow<W>& b, size_t len, size_t lenIndices, int trim); |
|||
TruncatedStepRow& operator=(const TruncatedStepRow<WIDTH>& a); |
|||
|
|||
inline bool IndicesBefore(const TruncatedStepRow<WIDTH>& a, size_t len, size_t lenIndices) const { return memcmp(hash+len, a.hash+len, lenIndices) < 0; } |
|||
std::shared_ptr<eh_trunc> GetTruncatedIndices(size_t len, size_t lenIndices) const; |
|||
}; |
|||
|
|||
enum EhSolverCancelCheck |
|||
{ |
|||
ListGeneration, |
|||
ListSorting, |
|||
ListColliding, |
|||
RoundEnd, |
|||
FinalSorting, |
|||
FinalColliding, |
|||
PartialGeneration, |
|||
PartialSorting, |
|||
PartialSubtreeEnd, |
|||
PartialIndexEnd, |
|||
PartialEnd |
|||
}; |
|||
|
|||
class EhSolverCancelledException : public std::exception |
|||
{ |
|||
virtual const char* what() const throw() { |
|||
return "Equihash solver was cancelled"; |
|||
} |
|||
}; |
|||
|
|||
inline constexpr const size_t max(const size_t A, const size_t B) { return A > B ? A : B; } |
|||
|
|||
inline constexpr size_t equihash_solution_size(unsigned int N, unsigned int K) { |
|||
return (1 << K)*(N/(K+1)+1)/8; |
|||
} |
|||
|
|||
template<unsigned int N, unsigned int K> |
|||
class Equihash |
|||
{ |
|||
private: |
|||
BOOST_STATIC_ASSERT(K < N); |
|||
BOOST_STATIC_ASSERT(N % 8 == 0); |
|||
BOOST_STATIC_ASSERT((N/(K+1)) + 1 < 8*sizeof(eh_index)); |
|||
|
|||
public: |
|||
enum : size_t { IndicesPerHashOutput=512/N }; |
|||
enum : size_t { HashOutput=IndicesPerHashOutput*N/8 }; |
|||
enum : size_t { CollisionBitLength=N/(K+1) }; |
|||
enum : size_t { CollisionByteLength=(CollisionBitLength+7)/8 }; |
|||
enum : size_t { HashLength=(K+1)*CollisionByteLength }; |
|||
enum : size_t { FullWidth=2*CollisionByteLength+sizeof(eh_index)*(1 << (K-1)) }; |
|||
enum : size_t { FinalFullWidth=2*CollisionByteLength+sizeof(eh_index)*(1 << (K)) }; |
|||
enum : size_t { TruncatedWidth=max(HashLength+sizeof(eh_trunc), 2*CollisionByteLength+sizeof(eh_trunc)*(1 << (K-1))) }; |
|||
enum : size_t { FinalTruncatedWidth=max(HashLength+sizeof(eh_trunc), 2*CollisionByteLength+sizeof(eh_trunc)*(1 << (K))) }; |
|||
enum : size_t { SolutionWidth=(1 << K)*(CollisionBitLength+1)/8 }; |
|||
|
|||
Equihash() { } |
|||
|
|||
int InitialiseState(eh_HashState& base_state); |
|||
#ifdef ENABLE_MINING |
|||
bool BasicSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
bool OptimisedSolve(const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled); |
|||
#endif |
|||
bool IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln); |
|||
}; |
|||
|
|||
#include "equihash.tcc" |
|||
|
|||
static Equihash<96,3> Eh96_3; |
|||
static Equihash<200,9> Eh200_9; |
|||
static Equihash<96,5> Eh96_5; |
|||
static Equihash<48,5> Eh48_5; |
|||
|
|||
#define EhInitialiseState(n, k, base_state) \ |
|||
if (n == 96 && k == 3) { \ |
|||
Eh96_3.InitialiseState(base_state); \ |
|||
} else if (n == 200 && k == 9) { \ |
|||
Eh200_9.InitialiseState(base_state); \ |
|||
} else if (n == 96 && k == 5) { \ |
|||
Eh96_5.InitialiseState(base_state); \ |
|||
} else if (n == 48 && k == 5) { \ |
|||
Eh48_5.InitialiseState(base_state); \ |
|||
} else { \ |
|||
throw std::invalid_argument("Unsupported Equihash parameters"); \ |
|||
} |
|||
|
|||
#ifdef ENABLE_MINING |
|||
inline bool EhBasicSolve(unsigned int n, unsigned int k, const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled) |
|||
{ |
|||
if (n == 96 && k == 3) { |
|||
return Eh96_3.BasicSolve(base_state, validBlock, cancelled); |
|||
} else if (n == 200 && k == 9) { |
|||
return Eh200_9.BasicSolve(base_state, validBlock, cancelled); |
|||
} else if (n == 96 && k == 5) { |
|||
return Eh96_5.BasicSolve(base_state, validBlock, cancelled); |
|||
} else if (n == 48 && k == 5) { |
|||
return Eh48_5.BasicSolve(base_state, validBlock, cancelled); |
|||
} else { |
|||
throw std::invalid_argument("Unsupported Equihash parameters"); |
|||
} |
|||
} |
|||
|
|||
inline bool EhBasicSolveUncancellable(unsigned int n, unsigned int k, const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock) |
|||
{ |
|||
return EhBasicSolve(n, k, base_state, validBlock, |
|||
[](EhSolverCancelCheck pos) { return false; }); |
|||
} |
|||
|
|||
inline bool EhOptimisedSolve(unsigned int n, unsigned int k, const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock, |
|||
const std::function<bool(EhSolverCancelCheck)> cancelled) |
|||
{ |
|||
if (n == 96 && k == 3) { |
|||
return Eh96_3.OptimisedSolve(base_state, validBlock, cancelled); |
|||
} else if (n == 200 && k == 9) { |
|||
return Eh200_9.OptimisedSolve(base_state, validBlock, cancelled); |
|||
} else if (n == 96 && k == 5) { |
|||
return Eh96_5.OptimisedSolve(base_state, validBlock, cancelled); |
|||
} else if (n == 48 && k == 5) { |
|||
return Eh48_5.OptimisedSolve(base_state, validBlock, cancelled); |
|||
} else { |
|||
throw std::invalid_argument("Unsupported Equihash parameters"); |
|||
} |
|||
} |
|||
|
|||
inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const eh_HashState& base_state, |
|||
const std::function<bool(std::vector<unsigned char>)> validBlock) |
|||
{ |
|||
return EhOptimisedSolve(n, k, base_state, validBlock, |
|||
[](EhSolverCancelCheck pos) { return false; }); |
|||
} |
|||
#endif // ENABLE_MINING
|
|||
|
|||
#define EhIsValidSolution(n, k, base_state, soln, ret) \ |
|||
if (n == 96 && k == 3) { \ |
|||
ret = Eh96_3.IsValidSolution(base_state, soln); \ |
|||
} else if (n == 200 && k == 9) { \ |
|||
ret = Eh200_9.IsValidSolution(base_state, soln); \ |
|||
} else if (n == 96 && k == 5) { \ |
|||
ret = Eh96_5.IsValidSolution(base_state, soln); \ |
|||
} else if (n == 48 && k == 5) { \ |
|||
ret = Eh48_5.IsValidSolution(base_state, soln); \ |
|||
} else { \ |
|||
throw std::invalid_argument("Unsupported Equihash parameters"); \ |
|||
} |
|||
|
|||
#endif // BITCOIN_EQUIHASH_H
|
@ -0,0 +1,49 @@ |
|||
// Copyright (c) 2016 Jack Grigg |
|||
// Copyright (c) 2016 The Zcash developers |
|||
// Distributed under the MIT software license, see the accompanying |
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
|||
|
|||
#include <algorithm> |
|||
#include <cassert> |
|||
|
|||
// Checks if the intersection of a.indices and b.indices is empty |
|||
template<size_t WIDTH> |
|||
bool DistinctIndices(const FullStepRow<WIDTH>& a, const FullStepRow<WIDTH>& b, size_t len, size_t lenIndices) |
|||
{ |
|||
for(size_t i = 0; i < lenIndices; i += sizeof(eh_index)) { |
|||
for(size_t j = 0; j < lenIndices; j += sizeof(eh_index)) { |
|||
if (memcmp(a.hash+len+i, b.hash+len+j, sizeof(eh_index)) == 0) { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
template<size_t MAX_INDICES> |
|||
bool IsProbablyDuplicate(std::shared_ptr<eh_trunc> indices, size_t lenIndices) |
|||
{ |
|||
assert(lenIndices <= MAX_INDICES); |
|||
bool checked_index[MAX_INDICES] = {false}; |
|||
int count_checked = 0; |
|||
for (int z = 0; z < lenIndices; z++) { |
|||
// Skip over indices we have already paired |
|||
if (!checked_index[z]) { |
|||
for (int y = z+1; y < lenIndices; y++) { |
|||
if (!checked_index[y] && indices.get()[z] == indices.get()[y]) { |
|||
// Pair found |
|||
checked_index[y] = true; |
|||
count_checked += 2; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return count_checked == lenIndices; |
|||
} |
|||
|
|||
template<size_t WIDTH> |
|||
bool IsValidBranch(const FullStepRow<WIDTH>& a, const size_t len, const unsigned int ilen, const eh_trunc t) |
|||
{ |
|||
return TruncateIndex(ArrayToEhIndex(a.hash+len), ilen) == t; |
|||
} |
@ -0,0 +1,34 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "crypto/hmac_sha256.h" |
|||
|
|||
#include <string.h> |
|||
|
|||
CHMAC_SHA256::CHMAC_SHA256(const unsigned char* key, size_t keylen) |
|||
{ |
|||
unsigned char rkey[64]; |
|||
if (keylen <= 64) { |
|||
memcpy(rkey, key, keylen); |
|||
memset(rkey + keylen, 0, 64 - keylen); |
|||
} else { |
|||
CSHA256().Write(key, keylen).Finalize(rkey); |
|||
memset(rkey + 32, 0, 32); |
|||
} |
|||
|
|||
for (int n = 0; n < 64; n++) |
|||
rkey[n] ^= 0x5c; |
|||
outer.Write(rkey, 64); |
|||
|
|||
for (int n = 0; n < 64; n++) |
|||
rkey[n] ^= 0x5c ^ 0x36; |
|||
inner.Write(rkey, 64); |
|||
} |
|||
|
|||
void CHMAC_SHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) |
|||
{ |
|||
unsigned char temp[32]; |
|||
inner.Finalize(temp); |
|||
outer.Write(temp, 32).Finalize(hash); |
|||
} |
@ -0,0 +1,32 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_HMAC_SHA256_H |
|||
#define BITCOIN_CRYPTO_HMAC_SHA256_H |
|||
|
|||
#include "crypto/sha256.h" |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/** A hasher class for HMAC-SHA-512. */ |
|||
class CHMAC_SHA256 |
|||
{ |
|||
private: |
|||
CSHA256 outer; |
|||
CSHA256 inner; |
|||
|
|||
public: |
|||
static const size_t OUTPUT_SIZE = 32; |
|||
|
|||
CHMAC_SHA256(const unsigned char* key, size_t keylen); |
|||
CHMAC_SHA256& Write(const unsigned char* data, size_t len) |
|||
{ |
|||
inner.Write(data, len); |
|||
return *this; |
|||
} |
|||
void Finalize(unsigned char hash[OUTPUT_SIZE]); |
|||
}; |
|||
|
|||
#endif // BITCOIN_CRYPTO_HMAC_SHA256_H
|
@ -0,0 +1,34 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "crypto/hmac_sha512.h" |
|||
|
|||
#include <string.h> |
|||
|
|||
CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen) |
|||
{ |
|||
unsigned char rkey[128]; |
|||
if (keylen <= 128) { |
|||
memcpy(rkey, key, keylen); |
|||
memset(rkey + keylen, 0, 128 - keylen); |
|||
} else { |
|||
CSHA512().Write(key, keylen).Finalize(rkey); |
|||
memset(rkey + 64, 0, 64); |
|||
} |
|||
|
|||
for (int n = 0; n < 128; n++) |
|||
rkey[n] ^= 0x5c; |
|||
outer.Write(rkey, 128); |
|||
|
|||
for (int n = 0; n < 128; n++) |
|||
rkey[n] ^= 0x5c ^ 0x36; |
|||
inner.Write(rkey, 128); |
|||
} |
|||
|
|||
void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) |
|||
{ |
|||
unsigned char temp[64]; |
|||
inner.Finalize(temp); |
|||
outer.Write(temp, 64).Finalize(hash); |
|||
} |
@ -0,0 +1,32 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_HMAC_SHA512_H |
|||
#define BITCOIN_CRYPTO_HMAC_SHA512_H |
|||
|
|||
#include "crypto/sha512.h" |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/** A hasher class for HMAC-SHA-512. */ |
|||
class CHMAC_SHA512 |
|||
{ |
|||
private: |
|||
CSHA512 outer; |
|||
CSHA512 inner; |
|||
|
|||
public: |
|||
static const size_t OUTPUT_SIZE = 64; |
|||
|
|||
CHMAC_SHA512(const unsigned char* key, size_t keylen); |
|||
CHMAC_SHA512& Write(const unsigned char* data, size_t len) |
|||
{ |
|||
inner.Write(data, len); |
|||
return *this; |
|||
} |
|||
void Finalize(unsigned char hash[OUTPUT_SIZE]); |
|||
}; |
|||
|
|||
#endif // BITCOIN_CRYPTO_HMAC_SHA512_H
|
@ -0,0 +1,292 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "crypto/ripemd160.h" |
|||
|
|||
#include "crypto/common.h" |
|||
|
|||
#include <string.h> |
|||
|
|||
// Internal implementation code.
|
|||
namespace |
|||
{ |
|||
/// Internal RIPEMD-160 implementation.
|
|||
namespace ripemd160 |
|||
{ |
|||
uint32_t inline f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; } |
|||
uint32_t inline f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); } |
|||
uint32_t inline f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; } |
|||
uint32_t inline f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); } |
|||
uint32_t inline f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); } |
|||
|
|||
/** Initialize RIPEMD-160 state. */ |
|||
void inline Initialize(uint32_t* s) |
|||
{ |
|||
s[0] = 0x67452301ul; |
|||
s[1] = 0xEFCDAB89ul; |
|||
s[2] = 0x98BADCFEul; |
|||
s[3] = 0x10325476ul; |
|||
s[4] = 0xC3D2E1F0ul; |
|||
} |
|||
|
|||
uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32 - i)); } |
|||
|
|||
void inline Round(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) |
|||
{ |
|||
a = rol(a + f + x + k, r) + e; |
|||
c = rol(c, 10); |
|||
} |
|||
|
|||
void inline R11(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } |
|||
void inline R21(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r); } |
|||
void inline R31(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r); } |
|||
void inline R41(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r); } |
|||
void inline R51(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r); } |
|||
|
|||
void inline R12(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r); } |
|||
void inline R22(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r); } |
|||
void inline R32(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r); } |
|||
void inline R42(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r); } |
|||
void inline R52(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } |
|||
|
|||
/** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */ |
|||
void Transform(uint32_t* s, const unsigned char* chunk) |
|||
{ |
|||
uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4]; |
|||
uint32_t a2 = a1, b2 = b1, c2 = c1, d2 = d1, e2 = e1; |
|||
uint32_t w0 = ReadLE32(chunk + 0), w1 = ReadLE32(chunk + 4), w2 = ReadLE32(chunk + 8), w3 = ReadLE32(chunk + 12); |
|||
uint32_t w4 = ReadLE32(chunk + 16), w5 = ReadLE32(chunk + 20), w6 = ReadLE32(chunk + 24), w7 = ReadLE32(chunk + 28); |
|||
uint32_t w8 = ReadLE32(chunk + 32), w9 = ReadLE32(chunk + 36), w10 = ReadLE32(chunk + 40), w11 = ReadLE32(chunk + 44); |
|||
uint32_t w12 = ReadLE32(chunk + 48), w13 = ReadLE32(chunk + 52), w14 = ReadLE32(chunk + 56), w15 = ReadLE32(chunk + 60); |
|||
|
|||
R11(a1, b1, c1, d1, e1, w0, 11); |
|||
R12(a2, b2, c2, d2, e2, w5, 8); |
|||
R11(e1, a1, b1, c1, d1, w1, 14); |
|||
R12(e2, a2, b2, c2, d2, w14, 9); |
|||
R11(d1, e1, a1, b1, c1, w2, 15); |
|||
R12(d2, e2, a2, b2, c2, w7, 9); |
|||
R11(c1, d1, e1, a1, b1, w3, 12); |
|||
R12(c2, d2, e2, a2, b2, w0, 11); |
|||
R11(b1, c1, d1, e1, a1, w4, 5); |
|||
R12(b2, c2, d2, e2, a2, w9, 13); |
|||
R11(a1, b1, c1, d1, e1, w5, 8); |
|||
R12(a2, b2, c2, d2, e2, w2, 15); |
|||
R11(e1, a1, b1, c1, d1, w6, 7); |
|||
R12(e2, a2, b2, c2, d2, w11, 15); |
|||
R11(d1, e1, a1, b1, c1, w7, 9); |
|||
R12(d2, e2, a2, b2, c2, w4, 5); |
|||
R11(c1, d1, e1, a1, b1, w8, 11); |
|||
R12(c2, d2, e2, a2, b2, w13, 7); |
|||
R11(b1, c1, d1, e1, a1, w9, 13); |
|||
R12(b2, c2, d2, e2, a2, w6, 7); |
|||
R11(a1, b1, c1, d1, e1, w10, 14); |
|||
R12(a2, b2, c2, d2, e2, w15, 8); |
|||
R11(e1, a1, b1, c1, d1, w11, 15); |
|||
R12(e2, a2, b2, c2, d2, w8, 11); |
|||
R11(d1, e1, a1, b1, c1, w12, 6); |
|||
R12(d2, e2, a2, b2, c2, w1, 14); |
|||
R11(c1, d1, e1, a1, b1, w13, 7); |
|||
R12(c2, d2, e2, a2, b2, w10, 14); |
|||
R11(b1, c1, d1, e1, a1, w14, 9); |
|||
R12(b2, c2, d2, e2, a2, w3, 12); |
|||
R11(a1, b1, c1, d1, e1, w15, 8); |
|||
R12(a2, b2, c2, d2, e2, w12, 6); |
|||
|
|||
R21(e1, a1, b1, c1, d1, w7, 7); |
|||
R22(e2, a2, b2, c2, d2, w6, 9); |
|||
R21(d1, e1, a1, b1, c1, w4, 6); |
|||
R22(d2, e2, a2, b2, c2, w11, 13); |
|||
R21(c1, d1, e1, a1, b1, w13, 8); |
|||
R22(c2, d2, e2, a2, b2, w3, 15); |
|||
R21(b1, c1, d1, e1, a1, w1, 13); |
|||
R22(b2, c2, d2, e2, a2, w7, 7); |
|||
R21(a1, b1, c1, d1, e1, w10, 11); |
|||
R22(a2, b2, c2, d2, e2, w0, 12); |
|||
R21(e1, a1, b1, c1, d1, w6, 9); |
|||
R22(e2, a2, b2, c2, d2, w13, 8); |
|||
R21(d1, e1, a1, b1, c1, w15, 7); |
|||
R22(d2, e2, a2, b2, c2, w5, 9); |
|||
R21(c1, d1, e1, a1, b1, w3, 15); |
|||
R22(c2, d2, e2, a2, b2, w10, 11); |
|||
R21(b1, c1, d1, e1, a1, w12, 7); |
|||
R22(b2, c2, d2, e2, a2, w14, 7); |
|||
R21(a1, b1, c1, d1, e1, w0, 12); |
|||
R22(a2, b2, c2, d2, e2, w15, 7); |
|||
R21(e1, a1, b1, c1, d1, w9, 15); |
|||
R22(e2, a2, b2, c2, d2, w8, 12); |
|||
R21(d1, e1, a1, b1, c1, w5, 9); |
|||
R22(d2, e2, a2, b2, c2, w12, 7); |
|||
R21(c1, d1, e1, a1, b1, w2, 11); |
|||
R22(c2, d2, e2, a2, b2, w4, 6); |
|||
R21(b1, c1, d1, e1, a1, w14, 7); |
|||
R22(b2, c2, d2, e2, a2, w9, 15); |
|||
R21(a1, b1, c1, d1, e1, w11, 13); |
|||
R22(a2, b2, c2, d2, e2, w1, 13); |
|||
R21(e1, a1, b1, c1, d1, w8, 12); |
|||
R22(e2, a2, b2, c2, d2, w2, 11); |
|||
|
|||
R31(d1, e1, a1, b1, c1, w3, 11); |
|||
R32(d2, e2, a2, b2, c2, w15, 9); |
|||
R31(c1, d1, e1, a1, b1, w10, 13); |
|||
R32(c2, d2, e2, a2, b2, w5, 7); |
|||
R31(b1, c1, d1, e1, a1, w14, 6); |
|||
R32(b2, c2, d2, e2, a2, w1, 15); |
|||
R31(a1, b1, c1, d1, e1, w4, 7); |
|||
R32(a2, b2, c2, d2, e2, w3, 11); |
|||
R31(e1, a1, b1, c1, d1, w9, 14); |
|||
R32(e2, a2, b2, c2, d2, w7, 8); |
|||
R31(d1, e1, a1, b1, c1, w15, 9); |
|||
R32(d2, e2, a2, b2, c2, w14, 6); |
|||
R31(c1, d1, e1, a1, b1, w8, 13); |
|||
R32(c2, d2, e2, a2, b2, w6, 6); |
|||
R31(b1, c1, d1, e1, a1, w1, 15); |
|||
R32(b2, c2, d2, e2, a2, w9, 14); |
|||
R31(a1, b1, c1, d1, e1, w2, 14); |
|||
R32(a2, b2, c2, d2, e2, w11, 12); |
|||
R31(e1, a1, b1, c1, d1, w7, 8); |
|||
R32(e2, a2, b2, c2, d2, w8, 13); |
|||
R31(d1, e1, a1, b1, c1, w0, 13); |
|||
R32(d2, e2, a2, b2, c2, w12, 5); |
|||
R31(c1, d1, e1, a1, b1, w6, 6); |
|||
R32(c2, d2, e2, a2, b2, w2, 14); |
|||
R31(b1, c1, d1, e1, a1, w13, 5); |
|||
R32(b2, c2, d2, e2, a2, w10, 13); |
|||
R31(a1, b1, c1, d1, e1, w11, 12); |
|||
R32(a2, b2, c2, d2, e2, w0, 13); |
|||
R31(e1, a1, b1, c1, d1, w5, 7); |
|||
R32(e2, a2, b2, c2, d2, w4, 7); |
|||
R31(d1, e1, a1, b1, c1, w12, 5); |
|||
R32(d2, e2, a2, b2, c2, w13, 5); |
|||
|
|||
R41(c1, d1, e1, a1, b1, w1, 11); |
|||
R42(c2, d2, e2, a2, b2, w8, 15); |
|||
R41(b1, c1, d1, e1, a1, w9, 12); |
|||
R42(b2, c2, d2, e2, a2, w6, 5); |
|||
R41(a1, b1, c1, d1, e1, w11, 14); |
|||
R42(a2, b2, c2, d2, e2, w4, 8); |
|||
R41(e1, a1, b1, c1, d1, w10, 15); |
|||
R42(e2, a2, b2, c2, d2, w1, 11); |
|||
R41(d1, e1, a1, b1, c1, w0, 14); |
|||
R42(d2, e2, a2, b2, c2, w3, 14); |
|||
R41(c1, d1, e1, a1, b1, w8, 15); |
|||
R42(c2, d2, e2, a2, b2, w11, 14); |
|||
R41(b1, c1, d1, e1, a1, w12, 9); |
|||
R42(b2, c2, d2, e2, a2, w15, 6); |
|||
R41(a1, b1, c1, d1, e1, w4, 8); |
|||
R42(a2, b2, c2, d2, e2, w0, 14); |
|||
R41(e1, a1, b1, c1, d1, w13, 9); |
|||
R42(e2, a2, b2, c2, d2, w5, 6); |
|||
R41(d1, e1, a1, b1, c1, w3, 14); |
|||
R42(d2, e2, a2, b2, c2, w12, 9); |
|||
R41(c1, d1, e1, a1, b1, w7, 5); |
|||
R42(c2, d2, e2, a2, b2, w2, 12); |
|||
R41(b1, c1, d1, e1, a1, w15, 6); |
|||
R42(b2, c2, d2, e2, a2, w13, 9); |
|||
R41(a1, b1, c1, d1, e1, w14, 8); |
|||
R42(a2, b2, c2, d2, e2, w9, 12); |
|||
R41(e1, a1, b1, c1, d1, w5, 6); |
|||
R42(e2, a2, b2, c2, d2, w7, 5); |
|||
R41(d1, e1, a1, b1, c1, w6, 5); |
|||
R42(d2, e2, a2, b2, c2, w10, 15); |
|||
R41(c1, d1, e1, a1, b1, w2, 12); |
|||
R42(c2, d2, e2, a2, b2, w14, 8); |
|||
|
|||
R51(b1, c1, d1, e1, a1, w4, 9); |
|||
R52(b2, c2, d2, e2, a2, w12, 8); |
|||
R51(a1, b1, c1, d1, e1, w0, 15); |
|||
R52(a2, b2, c2, d2, e2, w15, 5); |
|||
R51(e1, a1, b1, c1, d1, w5, 5); |
|||
R52(e2, a2, b2, c2, d2, w10, 12); |
|||
R51(d1, e1, a1, b1, c1, w9, 11); |
|||
R52(d2, e2, a2, b2, c2, w4, 9); |
|||
R51(c1, d1, e1, a1, b1, w7, 6); |
|||
R52(c2, d2, e2, a2, b2, w1, 12); |
|||
R51(b1, c1, d1, e1, a1, w12, 8); |
|||
R52(b2, c2, d2, e2, a2, w5, 5); |
|||
R51(a1, b1, c1, d1, e1, w2, 13); |
|||
R52(a2, b2, c2, d2, e2, w8, 14); |
|||
R51(e1, a1, b1, c1, d1, w10, 12); |
|||
R52(e2, a2, b2, c2, d2, w7, 6); |
|||
R51(d1, e1, a1, b1, c1, w14, 5); |
|||
R52(d2, e2, a2, b2, c2, w6, 8); |
|||
R51(c1, d1, e1, a1, b1, w1, 12); |
|||
R52(c2, d2, e2, a2, b2, w2, 13); |
|||
R51(b1, c1, d1, e1, a1, w3, 13); |
|||
R52(b2, c2, d2, e2, a2, w13, 6); |
|||
R51(a1, b1, c1, d1, e1, w8, 14); |
|||
R52(a2, b2, c2, d2, e2, w14, 5); |
|||
R51(e1, a1, b1, c1, d1, w11, 11); |
|||
R52(e2, a2, b2, c2, d2, w0, 15); |
|||
R51(d1, e1, a1, b1, c1, w6, 8); |
|||
R52(d2, e2, a2, b2, c2, w3, 13); |
|||
R51(c1, d1, e1, a1, b1, w15, 5); |
|||
R52(c2, d2, e2, a2, b2, w9, 11); |
|||
R51(b1, c1, d1, e1, a1, w13, 6); |
|||
R52(b2, c2, d2, e2, a2, w11, 11); |
|||
|
|||
uint32_t t = s[0]; |
|||
s[0] = s[1] + c1 + d2; |
|||
s[1] = s[2] + d1 + e2; |
|||
s[2] = s[3] + e1 + a2; |
|||
s[3] = s[4] + a1 + b2; |
|||
s[4] = t + b1 + c2; |
|||
} |
|||
|
|||
} // namespace ripemd160
|
|||
|
|||
} // namespace
|
|||
|
|||
////// RIPEMD160
|
|||
|
|||
CRIPEMD160::CRIPEMD160() : bytes(0) |
|||
{ |
|||
ripemd160::Initialize(s); |
|||
} |
|||
|
|||
CRIPEMD160& CRIPEMD160::Write(const unsigned char* data, size_t len) |
|||
{ |
|||
const unsigned char* end = data + len; |
|||
size_t bufsize = bytes % 64; |
|||
if (bufsize && bufsize + len >= 64) { |
|||
// Fill the buffer, and process it.
|
|||
memcpy(buf + bufsize, data, 64 - bufsize); |
|||
bytes += 64 - bufsize; |
|||
data += 64 - bufsize; |
|||
ripemd160::Transform(s, buf); |
|||
bufsize = 0; |
|||
} |
|||
while (end >= data + 64) { |
|||
// Process full chunks directly from the source.
|
|||
ripemd160::Transform(s, data); |
|||
bytes += 64; |
|||
data += 64; |
|||
} |
|||
if (end > data) { |
|||
// Fill the buffer with what remains.
|
|||
memcpy(buf + bufsize, data, end - data); |
|||
bytes += end - data; |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
void CRIPEMD160::Finalize(unsigned char hash[OUTPUT_SIZE]) |
|||
{ |
|||
static const unsigned char pad[64] = {0x80}; |
|||
unsigned char sizedesc[8]; |
|||
WriteLE64(sizedesc, bytes << 3); |
|||
Write(pad, 1 + ((119 - (bytes % 64)) % 64)); |
|||
Write(sizedesc, 8); |
|||
WriteLE32(hash, s[0]); |
|||
WriteLE32(hash + 4, s[1]); |
|||
WriteLE32(hash + 8, s[2]); |
|||
WriteLE32(hash + 12, s[3]); |
|||
WriteLE32(hash + 16, s[4]); |
|||
} |
|||
|
|||
CRIPEMD160& CRIPEMD160::Reset() |
|||
{ |
|||
bytes = 0; |
|||
ripemd160::Initialize(s); |
|||
return *this; |
|||
} |
@ -0,0 +1,28 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_RIPEMD160_H |
|||
#define BITCOIN_CRYPTO_RIPEMD160_H |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/** A hasher class for RIPEMD-160. */ |
|||
class CRIPEMD160 |
|||
{ |
|||
private: |
|||
uint32_t s[5]; |
|||
unsigned char buf[64]; |
|||
size_t bytes; |
|||
|
|||
public: |
|||
static const size_t OUTPUT_SIZE = 20; |
|||
|
|||
CRIPEMD160(); |
|||
CRIPEMD160& Write(const unsigned char* data, size_t len); |
|||
void Finalize(unsigned char hash[OUTPUT_SIZE]); |
|||
CRIPEMD160& Reset(); |
|||
}; |
|||
|
|||
#endif // BITCOIN_CRYPTO_RIPEMD160_H
|
@ -0,0 +1,199 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "crypto/sha1.h" |
|||
|
|||
#include "crypto/common.h" |
|||
|
|||
#include <string.h> |
|||
|
|||
// Internal implementation code.
|
|||
namespace |
|||
{ |
|||
/// Internal SHA-1 implementation.
|
|||
namespace sha1 |
|||
{ |
|||
/** One round of SHA-1. */ |
|||
void inline Round(uint32_t a, uint32_t& b, uint32_t c, uint32_t d, uint32_t& e, uint32_t f, uint32_t k, uint32_t w) |
|||
{ |
|||
e += ((a << 5) | (a >> 27)) + f + k + w; |
|||
b = (b << 30) | (b >> 2); |
|||
} |
|||
|
|||
uint32_t inline f1(uint32_t b, uint32_t c, uint32_t d) { return d ^ (b & (c ^ d)); } |
|||
uint32_t inline f2(uint32_t b, uint32_t c, uint32_t d) { return b ^ c ^ d; } |
|||
uint32_t inline f3(uint32_t b, uint32_t c, uint32_t d) { return (b & c) | (d & (b | c)); } |
|||
|
|||
uint32_t inline left(uint32_t x) { return (x << 1) | (x >> 31); } |
|||
|
|||
/** Initialize SHA-1 state. */ |
|||
void inline Initialize(uint32_t* s) |
|||
{ |
|||
s[0] = 0x67452301ul; |
|||
s[1] = 0xEFCDAB89ul; |
|||
s[2] = 0x98BADCFEul; |
|||
s[3] = 0x10325476ul; |
|||
s[4] = 0xC3D2E1F0ul; |
|||
} |
|||
|
|||
const uint32_t k1 = 0x5A827999ul; |
|||
const uint32_t k2 = 0x6ED9EBA1ul; |
|||
const uint32_t k3 = 0x8F1BBCDCul; |
|||
const uint32_t k4 = 0xCA62C1D6ul; |
|||
|
|||
/** Perform a SHA-1 transformation, processing a 64-byte chunk. */ |
|||
void Transform(uint32_t* s, const unsigned char* chunk) |
|||
{ |
|||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4]; |
|||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; |
|||
|
|||
Round(a, b, c, d, e, f1(b, c, d), k1, w0 = ReadBE32(chunk + 0)); |
|||
Round(e, a, b, c, d, f1(a, b, c), k1, w1 = ReadBE32(chunk + 4)); |
|||
Round(d, e, a, b, c, f1(e, a, b), k1, w2 = ReadBE32(chunk + 8)); |
|||
Round(c, d, e, a, b, f1(d, e, a), k1, w3 = ReadBE32(chunk + 12)); |
|||
Round(b, c, d, e, a, f1(c, d, e), k1, w4 = ReadBE32(chunk + 16)); |
|||
Round(a, b, c, d, e, f1(b, c, d), k1, w5 = ReadBE32(chunk + 20)); |
|||
Round(e, a, b, c, d, f1(a, b, c), k1, w6 = ReadBE32(chunk + 24)); |
|||
Round(d, e, a, b, c, f1(e, a, b), k1, w7 = ReadBE32(chunk + 28)); |
|||
Round(c, d, e, a, b, f1(d, e, a), k1, w8 = ReadBE32(chunk + 32)); |
|||
Round(b, c, d, e, a, f1(c, d, e), k1, w9 = ReadBE32(chunk + 36)); |
|||
Round(a, b, c, d, e, f1(b, c, d), k1, w10 = ReadBE32(chunk + 40)); |
|||
Round(e, a, b, c, d, f1(a, b, c), k1, w11 = ReadBE32(chunk + 44)); |
|||
Round(d, e, a, b, c, f1(e, a, b), k1, w12 = ReadBE32(chunk + 48)); |
|||
Round(c, d, e, a, b, f1(d, e, a), k1, w13 = ReadBE32(chunk + 52)); |
|||
Round(b, c, d, e, a, f1(c, d, e), k1, w14 = ReadBE32(chunk + 56)); |
|||
Round(a, b, c, d, e, f1(b, c, d), k1, w15 = ReadBE32(chunk + 60)); |
|||
|
|||
Round(e, a, b, c, d, f1(a, b, c), k1, w0 = left(w0 ^ w13 ^ w8 ^ w2)); |
|||
Round(d, e, a, b, c, f1(e, a, b), k1, w1 = left(w1 ^ w14 ^ w9 ^ w3)); |
|||
Round(c, d, e, a, b, f1(d, e, a), k1, w2 = left(w2 ^ w15 ^ w10 ^ w4)); |
|||
Round(b, c, d, e, a, f1(c, d, e), k1, w3 = left(w3 ^ w0 ^ w11 ^ w5)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k2, w8 = left(w8 ^ w5 ^ w0 ^ w10)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k2, w9 = left(w9 ^ w6 ^ w1 ^ w11)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k2, w10 = left(w10 ^ w7 ^ w2 ^ w12)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k2, w11 = left(w11 ^ w8 ^ w3 ^ w13)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k2, w12 = left(w12 ^ w9 ^ w4 ^ w14)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k2, w13 = left(w13 ^ w10 ^ w5 ^ w15)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k2, w14 = left(w14 ^ w11 ^ w6 ^ w0)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k2, w15 = left(w15 ^ w12 ^ w7 ^ w1)); |
|||
|
|||
Round(d, e, a, b, c, f2(e, a, b), k2, w0 = left(w0 ^ w13 ^ w8 ^ w2)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k2, w1 = left(w1 ^ w14 ^ w9 ^ w3)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k2, w2 = left(w2 ^ w15 ^ w10 ^ w4)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k2, w3 = left(w3 ^ w0 ^ w11 ^ w5)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9)); |
|||
Round(a, b, c, d, e, f3(b, c, d), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); |
|||
Round(e, a, b, c, d, f3(a, b, c), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); |
|||
Round(d, e, a, b, c, f3(e, a, b), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); |
|||
Round(c, d, e, a, b, f3(d, e, a), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); |
|||
Round(b, c, d, e, a, f3(c, d, e), k3, w12 = left(w12 ^ w9 ^ w4 ^ w14)); |
|||
Round(a, b, c, d, e, f3(b, c, d), k3, w13 = left(w13 ^ w10 ^ w5 ^ w15)); |
|||
Round(e, a, b, c, d, f3(a, b, c), k3, w14 = left(w14 ^ w11 ^ w6 ^ w0)); |
|||
Round(d, e, a, b, c, f3(e, a, b), k3, w15 = left(w15 ^ w12 ^ w7 ^ w1)); |
|||
|
|||
Round(c, d, e, a, b, f3(d, e, a), k3, w0 = left(w0 ^ w13 ^ w8 ^ w2)); |
|||
Round(b, c, d, e, a, f3(c, d, e), k3, w1 = left(w1 ^ w14 ^ w9 ^ w3)); |
|||
Round(a, b, c, d, e, f3(b, c, d), k3, w2 = left(w2 ^ w15 ^ w10 ^ w4)); |
|||
Round(e, a, b, c, d, f3(a, b, c), k3, w3 = left(w3 ^ w0 ^ w11 ^ w5)); |
|||
Round(d, e, a, b, c, f3(e, a, b), k3, w4 = left(w4 ^ w1 ^ w12 ^ w6)); |
|||
Round(c, d, e, a, b, f3(d, e, a), k3, w5 = left(w5 ^ w2 ^ w13 ^ w7)); |
|||
Round(b, c, d, e, a, f3(c, d, e), k3, w6 = left(w6 ^ w3 ^ w14 ^ w8)); |
|||
Round(a, b, c, d, e, f3(b, c, d), k3, w7 = left(w7 ^ w4 ^ w15 ^ w9)); |
|||
Round(e, a, b, c, d, f3(a, b, c), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); |
|||
Round(d, e, a, b, c, f3(e, a, b), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); |
|||
Round(c, d, e, a, b, f3(d, e, a), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); |
|||
Round(b, c, d, e, a, f3(c, d, e), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k4, w13 = left(w13 ^ w10 ^ w5 ^ w15)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k4, w14 = left(w14 ^ w11 ^ w6 ^ w0)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k4, w15 = left(w15 ^ w12 ^ w7 ^ w1)); |
|||
|
|||
Round(b, c, d, e, a, f2(c, d, e), k4, w0 = left(w0 ^ w13 ^ w8 ^ w2)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k4, w1 = left(w1 ^ w14 ^ w9 ^ w3)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k4, w2 = left(w2 ^ w15 ^ w10 ^ w4)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k4, w3 = left(w3 ^ w0 ^ w11 ^ w5)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k4, w4 = left(w4 ^ w1 ^ w12 ^ w6)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k4, w5 = left(w5 ^ w2 ^ w13 ^ w7)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k4, w6 = left(w6 ^ w3 ^ w14 ^ w8)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k4, w7 = left(w7 ^ w4 ^ w15 ^ w9)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k4, w8 = left(w8 ^ w5 ^ w0 ^ w10)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k4, w9 = left(w9 ^ w6 ^ w1 ^ w11)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k4, w10 = left(w10 ^ w7 ^ w2 ^ w12)); |
|||
Round(a, b, c, d, e, f2(b, c, d), k4, w11 = left(w11 ^ w8 ^ w3 ^ w13)); |
|||
Round(e, a, b, c, d, f2(a, b, c), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); |
|||
Round(d, e, a, b, c, f2(e, a, b), k4, left(w13 ^ w10 ^ w5 ^ w15)); |
|||
Round(c, d, e, a, b, f2(d, e, a), k4, left(w14 ^ w11 ^ w6 ^ w0)); |
|||
Round(b, c, d, e, a, f2(c, d, e), k4, left(w15 ^ w12 ^ w7 ^ w1)); |
|||
|
|||
s[0] += a; |
|||
s[1] += b; |
|||
s[2] += c; |
|||
s[3] += d; |
|||
s[4] += e; |
|||
} |
|||
|
|||
} // namespace sha1
|
|||
|
|||
} // namespace
|
|||
|
|||
////// SHA1
|
|||
|
|||
CSHA1::CSHA1() : bytes(0) |
|||
{ |
|||
sha1::Initialize(s); |
|||
} |
|||
|
|||
CSHA1& CSHA1::Write(const unsigned char* data, size_t len) |
|||
{ |
|||
const unsigned char* end = data + len; |
|||
size_t bufsize = bytes % 64; |
|||
if (bufsize && bufsize + len >= 64) { |
|||
// Fill the buffer, and process it.
|
|||
memcpy(buf + bufsize, data, 64 - bufsize); |
|||
bytes += 64 - bufsize; |
|||
data += 64 - bufsize; |
|||
sha1::Transform(s, buf); |
|||
bufsize = 0; |
|||
} |
|||
while (end >= data + 64) { |
|||
// Process full chunks directly from the source.
|
|||
sha1::Transform(s, data); |
|||
bytes += 64; |
|||
data += 64; |
|||
} |
|||
if (end > data) { |
|||
// Fill the buffer with what remains.
|
|||
memcpy(buf + bufsize, data, end - data); |
|||
bytes += end - data; |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
void CSHA1::Finalize(unsigned char hash[OUTPUT_SIZE]) |
|||
{ |
|||
static const unsigned char pad[64] = {0x80}; |
|||
unsigned char sizedesc[8]; |
|||
WriteBE64(sizedesc, bytes << 3); |
|||
Write(pad, 1 + ((119 - (bytes % 64)) % 64)); |
|||
Write(sizedesc, 8); |
|||
WriteBE32(hash, s[0]); |
|||
WriteBE32(hash + 4, s[1]); |
|||
WriteBE32(hash + 8, s[2]); |
|||
WriteBE32(hash + 12, s[3]); |
|||
WriteBE32(hash + 16, s[4]); |
|||
} |
|||
|
|||
CSHA1& CSHA1::Reset() |
|||
{ |
|||
bytes = 0; |
|||
sha1::Initialize(s); |
|||
return *this; |
|||
} |
@ -0,0 +1,28 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_SHA1_H |
|||
#define BITCOIN_CRYPTO_SHA1_H |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/** A hasher class for SHA1. */ |
|||
class CSHA1 |
|||
{ |
|||
private: |
|||
uint32_t s[5]; |
|||
unsigned char buf[64]; |
|||
size_t bytes; |
|||
|
|||
public: |
|||
static const size_t OUTPUT_SIZE = 20; |
|||
|
|||
CSHA1(); |
|||
CSHA1& Write(const unsigned char* data, size_t len); |
|||
void Finalize(unsigned char hash[OUTPUT_SIZE]); |
|||
CSHA1& Reset(); |
|||
}; |
|||
|
|||
#endif // BITCOIN_CRYPTO_SHA1_H
|
@ -0,0 +1,199 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "crypto/sha256.h" |
|||
|
|||
#include "crypto/common.h" |
|||
|
|||
#include <string.h> |
|||
#include <stdexcept> |
|||
|
|||
// Internal implementation code.
|
|||
namespace |
|||
{ |
|||
/// Internal SHA-256 implementation.
|
|||
namespace sha256 |
|||
{ |
|||
uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } |
|||
uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } |
|||
uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } |
|||
uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); } |
|||
uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); } |
|||
uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } |
|||
|
|||
/** One round of SHA-256. */ |
|||
void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w) |
|||
{ |
|||
uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; |
|||
uint32_t t2 = Sigma0(a) + Maj(a, b, c); |
|||
d += t1; |
|||
h = t1 + t2; |
|||
} |
|||
|
|||
/** Initialize SHA-256 state. */ |
|||
void inline Initialize(uint32_t* s) |
|||
{ |
|||
s[0] = 0x6a09e667ul; |
|||
s[1] = 0xbb67ae85ul; |
|||
s[2] = 0x3c6ef372ul; |
|||
s[3] = 0xa54ff53aul; |
|||
s[4] = 0x510e527ful; |
|||
s[5] = 0x9b05688cul; |
|||
s[6] = 0x1f83d9abul; |
|||
s[7] = 0x5be0cd19ul; |
|||
} |
|||
|
|||
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ |
|||
void Transform(uint32_t* s, const unsigned char* chunk) |
|||
{ |
|||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; |
|||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); |
|||
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); |
|||
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); |
|||
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); |
|||
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); |
|||
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); |
|||
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); |
|||
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); |
|||
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); |
|||
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); |
|||
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); |
|||
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); |
|||
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); |
|||
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); |
|||
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); |
|||
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
s[0] += a; |
|||
s[1] += b; |
|||
s[2] += c; |
|||
s[3] += d; |
|||
s[4] += e; |
|||
s[5] += f; |
|||
s[6] += g; |
|||
s[7] += h; |
|||
} |
|||
|
|||
} // namespace sha256
|
|||
} // namespace
|
|||
|
|||
|
|||
////// SHA-256
|
|||
|
|||
CSHA256::CSHA256() : bytes(0) |
|||
{ |
|||
sha256::Initialize(s); |
|||
} |
|||
|
|||
CSHA256& CSHA256::Write(const unsigned char* data, size_t len) |
|||
{ |
|||
const unsigned char* end = data + len; |
|||
size_t bufsize = bytes % 64; |
|||
if (bufsize && bufsize + len >= 64) { |
|||
// Fill the buffer, and process it.
|
|||
memcpy(buf + bufsize, data, 64 - bufsize); |
|||
bytes += 64 - bufsize; |
|||
data += 64 - bufsize; |
|||
sha256::Transform(s, buf); |
|||
bufsize = 0; |
|||
} |
|||
while (end >= data + 64) { |
|||
// Process full chunks directly from the source.
|
|||
sha256::Transform(s, data); |
|||
bytes += 64; |
|||
data += 64; |
|||
} |
|||
if (end > data) { |
|||
// Fill the buffer with what remains.
|
|||
memcpy(buf + bufsize, data, end - data); |
|||
bytes += end - data; |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) |
|||
{ |
|||
static const unsigned char pad[64] = {0x80}; |
|||
unsigned char sizedesc[8]; |
|||
WriteBE64(sizedesc, bytes << 3); |
|||
Write(pad, 1 + ((119 - (bytes % 64)) % 64)); |
|||
Write(sizedesc, 8); |
|||
FinalizeNoPadding(hash, false); |
|||
} |
|||
|
|||
void CSHA256::FinalizeNoPadding(unsigned char hash[OUTPUT_SIZE], bool enforce_compression) |
|||
{ |
|||
if (enforce_compression && bytes != 64) { |
|||
throw std::length_error("SHA256Compress should be invoked with a 512-bit block"); |
|||
} |
|||
|
|||
WriteBE32(hash, s[0]); |
|||
WriteBE32(hash + 4, s[1]); |
|||
WriteBE32(hash + 8, s[2]); |
|||
WriteBE32(hash + 12, s[3]); |
|||
WriteBE32(hash + 16, s[4]); |
|||
WriteBE32(hash + 20, s[5]); |
|||
WriteBE32(hash + 24, s[6]); |
|||
WriteBE32(hash + 28, s[7]); |
|||
} |
|||
|
|||
CSHA256& CSHA256::Reset() |
|||
{ |
|||
bytes = 0; |
|||
sha256::Initialize(s); |
|||
return *this; |
|||
} |
@ -0,0 +1,33 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_SHA256_H |
|||
#define BITCOIN_CRYPTO_SHA256_H |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
|
|||
/** A hasher class for SHA-256. */ |
|||
class CSHA256 |
|||
{ |
|||
public: |
|||
static const size_t OUTPUT_SIZE = 32; |
|||
|
|||
CSHA256(); |
|||
CSHA256& Write(const unsigned char* data, size_t len); |
|||
void Finalize(unsigned char hash[OUTPUT_SIZE]); |
|||
void FinalizeNoPadding(unsigned char hash[OUTPUT_SIZE]) { |
|||
FinalizeNoPadding(hash, true); |
|||
}; |
|||
CSHA256& Reset(); |
|||
|
|||
private: |
|||
uint32_t s[8]; |
|||
unsigned char buf[64]; |
|||
size_t bytes; |
|||
void FinalizeNoPadding(unsigned char hash[OUTPUT_SIZE], bool enforce_compression); |
|||
}; |
|||
|
|||
#endif // BITCOIN_CRYPTO_SHA256_H
|
@ -0,0 +1,207 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "crypto/sha512.h" |
|||
|
|||
#include "crypto/common.h" |
|||
|
|||
#include <string.h> |
|||
|
|||
// Internal implementation code.
|
|||
namespace |
|||
{ |
|||
/// Internal SHA-512 implementation.
|
|||
namespace sha512 |
|||
{ |
|||
uint64_t inline Ch(uint64_t x, uint64_t y, uint64_t z) { return z ^ (x & (y ^ z)); } |
|||
uint64_t inline Maj(uint64_t x, uint64_t y, uint64_t z) { return (x & y) | (z & (x | y)); } |
|||
uint64_t inline Sigma0(uint64_t x) { return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); } |
|||
uint64_t inline Sigma1(uint64_t x) { return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); } |
|||
uint64_t inline sigma0(uint64_t x) { return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); } |
|||
uint64_t inline sigma1(uint64_t x) { return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); } |
|||
|
|||
/** One round of SHA-512. */ |
|||
void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t& d, uint64_t e, uint64_t f, uint64_t g, uint64_t& h, uint64_t k, uint64_t w) |
|||
{ |
|||
uint64_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; |
|||
uint64_t t2 = Sigma0(a) + Maj(a, b, c); |
|||
d += t1; |
|||
h = t1 + t2; |
|||
} |
|||
|
|||
/** Initialize SHA-256 state. */ |
|||
void inline Initialize(uint64_t* s) |
|||
{ |
|||
s[0] = 0x6a09e667f3bcc908ull; |
|||
s[1] = 0xbb67ae8584caa73bull; |
|||
s[2] = 0x3c6ef372fe94f82bull; |
|||
s[3] = 0xa54ff53a5f1d36f1ull; |
|||
s[4] = 0x510e527fade682d1ull; |
|||
s[5] = 0x9b05688c2b3e6c1full; |
|||
s[6] = 0x1f83d9abfb41bd6bull; |
|||
s[7] = 0x5be0cd19137e2179ull; |
|||
} |
|||
|
|||
/** Perform one SHA-512 transformation, processing a 128-byte chunk. */ |
|||
void Transform(uint64_t* s, const unsigned char* chunk) |
|||
{ |
|||
uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; |
|||
uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0x428a2f98d728ae22ull, w0 = ReadBE64(chunk + 0)); |
|||
Round(h, a, b, c, d, e, f, g, 0x7137449123ef65cdull, w1 = ReadBE64(chunk + 8)); |
|||
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2full, w2 = ReadBE64(chunk + 16)); |
|||
Round(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbcull, w3 = ReadBE64(chunk + 24)); |
|||
Round(e, f, g, h, a, b, c, d, 0x3956c25bf348b538ull, w4 = ReadBE64(chunk + 32)); |
|||
Round(d, e, f, g, h, a, b, c, 0x59f111f1b605d019ull, w5 = ReadBE64(chunk + 40)); |
|||
Round(c, d, e, f, g, h, a, b, 0x923f82a4af194f9bull, w6 = ReadBE64(chunk + 48)); |
|||
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118ull, w7 = ReadBE64(chunk + 56)); |
|||
Round(a, b, c, d, e, f, g, h, 0xd807aa98a3030242ull, w8 = ReadBE64(chunk + 64)); |
|||
Round(h, a, b, c, d, e, f, g, 0x12835b0145706fbeull, w9 = ReadBE64(chunk + 72)); |
|||
Round(g, h, a, b, c, d, e, f, 0x243185be4ee4b28cull, w10 = ReadBE64(chunk + 80)); |
|||
Round(f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2ull, w11 = ReadBE64(chunk + 88)); |
|||
Round(e, f, g, h, a, b, c, d, 0x72be5d74f27b896full, w12 = ReadBE64(chunk + 96)); |
|||
Round(d, e, f, g, h, a, b, c, 0x80deb1fe3b1696b1ull, w13 = ReadBE64(chunk + 104)); |
|||
Round(c, d, e, f, g, h, a, b, 0x9bdc06a725c71235ull, w14 = ReadBE64(chunk + 112)); |
|||
Round(b, c, d, e, f, g, h, a, 0xc19bf174cf692694ull, w15 = ReadBE64(chunk + 120)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65ull, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275ull, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483ull, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x76f988da831153b5ull, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0x983e5152ee66dfabull, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0xa831c66d2db43210ull, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0xb00327c898fb213full, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4ull, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aedull, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0x53380d139d95b3dfull, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x650a73548baf63deull, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8ull, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6ull, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x92722c851482353bull, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364ull, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0xa81a664bbc423001ull, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791ull, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0xc76c51a30654be30ull, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99ull, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8ull, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63ull, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acbull, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373ull, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fcull, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0x78a5636f43172f60ull, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72ull, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0x8cc702081a6439ecull, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, d, e, f, g, h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1eull, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178ull, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, h, a, b, c, d, 0x06f067aa72176fbaull, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6ull, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, f, g, h, a, b, 0x113f9804bef90daeull, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, e, f, g, h, a, 0x1b710b35131c471bull, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, d, e, f, g, h, 0x28db77f523047d84ull, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, c, d, e, f, g, 0x32caab7b40c72493ull, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebcull, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
s[0] += a; |
|||
s[1] += b; |
|||
s[2] += c; |
|||
s[3] += d; |
|||
s[4] += e; |
|||
s[5] += f; |
|||
s[6] += g; |
|||
s[7] += h; |
|||
} |
|||
|
|||
} // namespace sha512
|
|||
|
|||
} // namespace
|
|||
|
|||
|
|||
////// SHA-512
|
|||
|
|||
CSHA512::CSHA512() : bytes(0) |
|||
{ |
|||
sha512::Initialize(s); |
|||
} |
|||
|
|||
CSHA512& CSHA512::Write(const unsigned char* data, size_t len) |
|||
{ |
|||
const unsigned char* end = data + len; |
|||
size_t bufsize = bytes % 128; |
|||
if (bufsize && bufsize + len >= 128) { |
|||
// Fill the buffer, and process it.
|
|||
memcpy(buf + bufsize, data, 128 - bufsize); |
|||
bytes += 128 - bufsize; |
|||
data += 128 - bufsize; |
|||
sha512::Transform(s, buf); |
|||
bufsize = 0; |
|||
} |
|||
while (end >= data + 128) { |
|||
// Process full chunks directly from the source.
|
|||
sha512::Transform(s, data); |
|||
data += 128; |
|||
bytes += 128; |
|||
} |
|||
if (end > data) { |
|||
// Fill the buffer with what remains.
|
|||
memcpy(buf + bufsize, data, end - data); |
|||
bytes += end - data; |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
void CSHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) |
|||
{ |
|||
static const unsigned char pad[128] = {0x80}; |
|||
unsigned char sizedesc[16] = {0x00}; |
|||
WriteBE64(sizedesc + 8, bytes << 3); |
|||
Write(pad, 1 + ((239 - (bytes % 128)) % 128)); |
|||
Write(sizedesc, 16); |
|||
WriteBE64(hash, s[0]); |
|||
WriteBE64(hash + 8, s[1]); |
|||
WriteBE64(hash + 16, s[2]); |
|||
WriteBE64(hash + 24, s[3]); |
|||
WriteBE64(hash + 32, s[4]); |
|||
WriteBE64(hash + 40, s[5]); |
|||
WriteBE64(hash + 48, s[6]); |
|||
WriteBE64(hash + 56, s[7]); |
|||
} |
|||
|
|||
CSHA512& CSHA512::Reset() |
|||
{ |
|||
bytes = 0; |
|||
sha512::Initialize(s); |
|||
return *this; |
|||
} |
@ -0,0 +1,28 @@ |
|||
// Copyright (c) 2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_CRYPTO_SHA512_H |
|||
#define BITCOIN_CRYPTO_SHA512_H |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/** A hasher class for SHA-512. */ |
|||
class CSHA512 |
|||
{ |
|||
private: |
|||
uint64_t s[8]; |
|||
unsigned char buf[128]; |
|||
size_t bytes; |
|||
|
|||
public: |
|||
static const size_t OUTPUT_SIZE = 64; |
|||
|
|||
CSHA512(); |
|||
CSHA512& Write(const unsigned char* data, size_t len); |
|||
void Finalize(unsigned char hash[OUTPUT_SIZE]); |
|||
CSHA512& Reset(); |
|||
}; |
|||
|
|||
#endif // BITCOIN_CRYPTO_SHA512_H
|
@ -0,0 +1,80 @@ |
|||
#include <nan.h> |
|||
#include <node.h> |
|||
#include <node_buffer.h> |
|||
#include <v8.h> |
|||
#include <stdint.h> |
|||
#include <sodium.h> |
|||
#include "crypto/equihash.h" |
|||
|
|||
/*extern "C" {
|
|||
#include "src/equi/equi.h" |
|||
}*/ |
|||
|
|||
using namespace v8; |
|||
|
|||
void verifyEH(const unsigned char *hdr, const unsigned char *soln){ |
|||
const int n = 200; |
|||
const int k = 9; |
|||
const int collisionBitLength = n / (k + 1); |
|||
const int collisionByteLength = (collisionBitLength + 7) / 8; |
|||
const int hashLength = (k + 1) * collisionByteLength; |
|||
const int indicesPerHashOutput = 512 / n; |
|||
const int hashOutput = indecesPerHashOutput * n / 8; |
|||
const int equihashSolutionSize = (1 << k) * (n / (k + 1) + 1) / 8; |
|||
const int solnr = 1 << k; |
|||
uint32_t indices[512]; |
|||
|
|||
crypto_generichash_blake2b_state state; |
|||
Eh200_9.InitialiseState(state); |
|||
crypto_generichash_blake2b_update(&state, hdr, 140); |
|||
|
|||
ExpandArray(soln, equihashSolutionSize, (unsigned char *)&indices, sizeof(indices), collisionBitLength + 1, 1); |
|||
|
|||
uint8_t vHash[hashLength]; |
|||
memset(vHash, 0 , sizeof(vHash)); |
|||
|
|||
for (int j = 0; j < solnr; j++) { |
|||
uint8_t tmpHash[hashOutput]; |
|||
uint8_t hash[hashLength]; |
|||
int i = be32toh(indices[j]); |
|||
GenerateHash(&state, i / indicesPerHashOutput, tmpHash, hashOutput); |
|||
ExpandArray(tmpHash + (i % indicesPerHashOutput * n / 8), n / 8, hash, hashLength, collisionBitLength, 0); |
|||
for (int k = 0; k < hashLength; ++k) |
|||
vHash[k] ^= hash[k]; |
|||
} |
|||
return IsZero(sizeof(vHash)); |
|||
} |
|||
|
|||
void Verify(const v8::FunctionCallbackInfo<Value>& args) { |
|||
Isolate* isolate = Isolate::GetCurrent(); |
|||
HandleScope scope(isolate); |
|||
|
|||
if (args.Length() < 2) { |
|||
isolate->ThrowException(Exception::TypeError( |
|||
String::NewFromUtf8(isolate, "Wrong number of arguments"))); |
|||
return; |
|||
} |
|||
|
|||
Local<Object> header = args[0]->ToObject(); |
|||
Local<Object> solution = args[1]->ToObject(); |
|||
|
|||
if(!node::Buffer::HasInstance(header) || !node::Buffer::HasInstance(solution)) { |
|||
isolate->ThrowException(Exception::TypeError( |
|||
String::NewFromUtf8(isolate, "Arguments should be buffer objects."))); |
|||
return; |
|||
} |
|||
|
|||
const char *hdr = node::Buffer::Data(header); |
|||
const char *soln = node::Buffer::Data(solution); |
|||
|
|||
bool result = verifyEH(hdr, soln); |
|||
args.GetReturnValue().Set(result); |
|||
|
|||
} |
|||
|
|||
|
|||
void Init(Handle<Object> exports) { |
|||
NODE_SET_METHOD(exports, "verify", Verify); |
|||
} |
|||
|
|||
NODE_MODULE(equihashverify, Init) |
@ -0,0 +1 @@ |
|||
module.exports = require('bindings')('equihashverify.node'); |
@ -0,0 +1,749 @@ |
|||
{ |
|||
"name": "equihashverify", |
|||
"version": "0.0.1", |
|||
"lockfileVersion": 1, |
|||
"requires": true, |
|||
"dependencies": { |
|||
"abbrev": { |
|||
"version": "1.1.1", |
|||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", |
|||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" |
|||
}, |
|||
"ajv": { |
|||
"version": "5.5.2", |
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", |
|||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", |
|||
"requires": { |
|||
"co": "4.6.0", |
|||
"fast-deep-equal": "1.1.0", |
|||
"fast-json-stable-stringify": "2.0.0", |
|||
"json-schema-traverse": "0.3.1" |
|||
} |
|||
}, |
|||
"ansi-regex": { |
|||
"version": "2.1.1", |
|||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", |
|||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" |
|||
}, |
|||
"aproba": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", |
|||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" |
|||
}, |
|||
"are-we-there-yet": { |
|||
"version": "1.1.4", |
|||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", |
|||
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", |
|||
"requires": { |
|||
"delegates": "1.0.0", |
|||
"readable-stream": "2.3.5" |
|||
} |
|||
}, |
|||
"asn1": { |
|||
"version": "0.2.3", |
|||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", |
|||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" |
|||
}, |
|||
"assert-plus": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
|||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" |
|||
}, |
|||
"asynckit": { |
|||
"version": "0.4.0", |
|||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", |
|||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" |
|||
}, |
|||
"aws-sign2": { |
|||
"version": "0.7.0", |
|||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", |
|||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" |
|||
}, |
|||
"aws4": { |
|||
"version": "1.6.0", |
|||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", |
|||
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" |
|||
}, |
|||
"balanced-match": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", |
|||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" |
|||
}, |
|||
"bcrypt-pbkdf": { |
|||
"version": "1.0.1", |
|||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", |
|||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", |
|||
"optional": true, |
|||
"requires": { |
|||
"tweetnacl": "0.14.5" |
|||
} |
|||
}, |
|||
"bindings": { |
|||
"version": "1.3.0", |
|||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", |
|||
"integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" |
|||
}, |
|||
"block-stream": { |
|||
"version": "0.0.9", |
|||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", |
|||
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", |
|||
"requires": { |
|||
"inherits": "2.0.3" |
|||
} |
|||
}, |
|||
"boom": { |
|||
"version": "4.3.1", |
|||
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", |
|||
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", |
|||
"requires": { |
|||
"hoek": "4.2.1" |
|||
} |
|||
}, |
|||
"brace-expansion": { |
|||
"version": "1.1.11", |
|||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", |
|||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", |
|||
"requires": { |
|||
"balanced-match": "1.0.0", |
|||
"concat-map": "0.0.1" |
|||
} |
|||
}, |
|||
"caseless": { |
|||
"version": "0.12.0", |
|||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", |
|||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" |
|||
}, |
|||
"co": { |
|||
"version": "4.6.0", |
|||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", |
|||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" |
|||
}, |
|||
"code-point-at": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", |
|||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" |
|||
}, |
|||
"combined-stream": { |
|||
"version": "1.0.6", |
|||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", |
|||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", |
|||
"requires": { |
|||
"delayed-stream": "1.0.0" |
|||
} |
|||
}, |
|||
"concat-map": { |
|||
"version": "0.0.1", |
|||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", |
|||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" |
|||
}, |
|||
"console-control-strings": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", |
|||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" |
|||
}, |
|||
"core-util-is": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", |
|||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" |
|||
}, |
|||
"cryptiles": { |
|||
"version": "3.1.2", |
|||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", |
|||
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", |
|||
"requires": { |
|||
"boom": "5.2.0" |
|||
}, |
|||
"dependencies": { |
|||
"boom": { |
|||
"version": "5.2.0", |
|||
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", |
|||
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", |
|||
"requires": { |
|||
"hoek": "4.2.1" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"dashdash": { |
|||
"version": "1.14.1", |
|||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", |
|||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", |
|||
"requires": { |
|||
"assert-plus": "1.0.0" |
|||
} |
|||
}, |
|||
"delayed-stream": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", |
|||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" |
|||
}, |
|||
"delegates": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", |
|||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" |
|||
}, |
|||
"ecc-jsbn": { |
|||
"version": "0.1.1", |
|||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", |
|||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", |
|||
"optional": true, |
|||
"requires": { |
|||
"jsbn": "0.1.1" |
|||
} |
|||
}, |
|||
"extend": { |
|||
"version": "3.0.1", |
|||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", |
|||
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" |
|||
}, |
|||
"extsprintf": { |
|||
"version": "1.3.0", |
|||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", |
|||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" |
|||
}, |
|||
"fast-deep-equal": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", |
|||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" |
|||
}, |
|||
"fast-json-stable-stringify": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", |
|||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" |
|||
}, |
|||
"forever-agent": { |
|||
"version": "0.6.1", |
|||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", |
|||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" |
|||
}, |
|||
"form-data": { |
|||
"version": "2.3.2", |
|||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", |
|||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", |
|||
"requires": { |
|||
"asynckit": "0.4.0", |
|||
"combined-stream": "1.0.6", |
|||
"mime-types": "2.1.18" |
|||
} |
|||
}, |
|||
"fs.realpath": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", |
|||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" |
|||
}, |
|||
"fstream": { |
|||
"version": "1.0.11", |
|||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", |
|||
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", |
|||
"requires": { |
|||
"graceful-fs": "4.1.11", |
|||
"inherits": "2.0.3", |
|||
"mkdirp": "0.5.1", |
|||
"rimraf": "2.6.2" |
|||
} |
|||
}, |
|||
"gauge": { |
|||
"version": "2.7.4", |
|||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", |
|||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", |
|||
"requires": { |
|||
"aproba": "1.2.0", |
|||
"console-control-strings": "1.1.0", |
|||
"has-unicode": "2.0.1", |
|||
"object-assign": "4.1.1", |
|||
"signal-exit": "3.0.2", |
|||
"string-width": "1.0.2", |
|||
"strip-ansi": "3.0.1", |
|||
"wide-align": "1.1.2" |
|||
} |
|||
}, |
|||
"getpass": { |
|||
"version": "0.1.7", |
|||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", |
|||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", |
|||
"requires": { |
|||
"assert-plus": "1.0.0" |
|||
} |
|||
}, |
|||
"glob": { |
|||
"version": "7.1.2", |
|||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", |
|||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", |
|||
"requires": { |
|||
"fs.realpath": "1.0.0", |
|||
"inflight": "1.0.6", |
|||
"inherits": "2.0.3", |
|||
"minimatch": "3.0.4", |
|||
"once": "1.4.0", |
|||
"path-is-absolute": "1.0.1" |
|||
} |
|||
}, |
|||
"graceful-fs": { |
|||
"version": "4.1.11", |
|||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", |
|||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" |
|||
}, |
|||
"har-schema": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", |
|||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" |
|||
}, |
|||
"har-validator": { |
|||
"version": "5.0.3", |
|||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", |
|||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", |
|||
"requires": { |
|||
"ajv": "5.5.2", |
|||
"har-schema": "2.0.0" |
|||
} |
|||
}, |
|||
"has-unicode": { |
|||
"version": "2.0.1", |
|||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", |
|||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" |
|||
}, |
|||
"hawk": { |
|||
"version": "6.0.2", |
|||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", |
|||
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", |
|||
"requires": { |
|||
"boom": "4.3.1", |
|||
"cryptiles": "3.1.2", |
|||
"hoek": "4.2.1", |
|||
"sntp": "2.1.0" |
|||
} |
|||
}, |
|||
"hoek": { |
|||
"version": "4.2.1", |
|||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", |
|||
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" |
|||
}, |
|||
"http-signature": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", |
|||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", |
|||
"requires": { |
|||
"assert-plus": "1.0.0", |
|||
"jsprim": "1.4.1", |
|||
"sshpk": "1.14.1" |
|||
} |
|||
}, |
|||
"inflight": { |
|||
"version": "1.0.6", |
|||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", |
|||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", |
|||
"requires": { |
|||
"once": "1.4.0", |
|||
"wrappy": "1.0.2" |
|||
} |
|||
}, |
|||
"inherits": { |
|||
"version": "2.0.3", |
|||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", |
|||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" |
|||
}, |
|||
"is-fullwidth-code-point": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", |
|||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", |
|||
"requires": { |
|||
"number-is-nan": "1.0.1" |
|||
} |
|||
}, |
|||
"is-typedarray": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", |
|||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" |
|||
}, |
|||
"isarray": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", |
|||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" |
|||
}, |
|||
"isexe": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", |
|||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" |
|||
}, |
|||
"isstream": { |
|||
"version": "0.1.2", |
|||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", |
|||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" |
|||
}, |
|||
"jsbn": { |
|||
"version": "0.1.1", |
|||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", |
|||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", |
|||
"optional": true |
|||
}, |
|||
"json-schema": { |
|||
"version": "0.2.3", |
|||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", |
|||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" |
|||
}, |
|||
"json-schema-traverse": { |
|||
"version": "0.3.1", |
|||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", |
|||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" |
|||
}, |
|||
"json-stringify-safe": { |
|||
"version": "5.0.1", |
|||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", |
|||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" |
|||
}, |
|||
"jsprim": { |
|||
"version": "1.4.1", |
|||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", |
|||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", |
|||
"requires": { |
|||
"assert-plus": "1.0.0", |
|||
"extsprintf": "1.3.0", |
|||
"json-schema": "0.2.3", |
|||
"verror": "1.10.0" |
|||
} |
|||
}, |
|||
"mime-db": { |
|||
"version": "1.33.0", |
|||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", |
|||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" |
|||
}, |
|||
"mime-types": { |
|||
"version": "2.1.18", |
|||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", |
|||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", |
|||
"requires": { |
|||
"mime-db": "1.33.0" |
|||
} |
|||
}, |
|||
"minimatch": { |
|||
"version": "3.0.4", |
|||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", |
|||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", |
|||
"requires": { |
|||
"brace-expansion": "1.1.11" |
|||
} |
|||
}, |
|||
"minimist": { |
|||
"version": "0.0.8", |
|||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", |
|||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" |
|||
}, |
|||
"mkdirp": { |
|||
"version": "0.5.1", |
|||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", |
|||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", |
|||
"requires": { |
|||
"minimist": "0.0.8" |
|||
} |
|||
}, |
|||
"nan": { |
|||
"version": "2.9.2", |
|||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.9.2.tgz", |
|||
"integrity": "sha512-ltW65co7f3PQWBDbqVvaU1WtFJUsNW7sWWm4HINhbMQIyVyzIeyZ8toX5TC5eeooE6piZoaEh4cZkueSKG3KYw==" |
|||
}, |
|||
"node-gyp": { |
|||
"version": "3.6.2", |
|||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", |
|||
"integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", |
|||
"requires": { |
|||
"fstream": "1.0.11", |
|||
"glob": "7.1.2", |
|||
"graceful-fs": "4.1.11", |
|||
"minimatch": "3.0.4", |
|||
"mkdirp": "0.5.1", |
|||
"nopt": "3.0.6", |
|||
"npmlog": "4.1.2", |
|||
"osenv": "0.1.5", |
|||
"request": "2.85.0", |
|||
"rimraf": "2.6.2", |
|||
"semver": "5.3.0", |
|||
"tar": "2.2.1", |
|||
"which": "1.3.0" |
|||
} |
|||
}, |
|||
"nopt": { |
|||
"version": "3.0.6", |
|||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", |
|||
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", |
|||
"requires": { |
|||
"abbrev": "1.1.1" |
|||
} |
|||
}, |
|||
"npmlog": { |
|||
"version": "4.1.2", |
|||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", |
|||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", |
|||
"requires": { |
|||
"are-we-there-yet": "1.1.4", |
|||
"console-control-strings": "1.1.0", |
|||
"gauge": "2.7.4", |
|||
"set-blocking": "2.0.0" |
|||
} |
|||
}, |
|||
"number-is-nan": { |
|||
"version": "1.0.1", |
|||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", |
|||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" |
|||
}, |
|||
"oauth-sign": { |
|||
"version": "0.8.2", |
|||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", |
|||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" |
|||
}, |
|||
"object-assign": { |
|||
"version": "4.1.1", |
|||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", |
|||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" |
|||
}, |
|||
"once": { |
|||
"version": "1.4.0", |
|||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", |
|||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", |
|||
"requires": { |
|||
"wrappy": "1.0.2" |
|||
} |
|||
}, |
|||
"os-homedir": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", |
|||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" |
|||
}, |
|||
"os-tmpdir": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", |
|||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" |
|||
}, |
|||
"osenv": { |
|||
"version": "0.1.5", |
|||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", |
|||
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", |
|||
"requires": { |
|||
"os-homedir": "1.0.2", |
|||
"os-tmpdir": "1.0.2" |
|||
} |
|||
}, |
|||
"path-is-absolute": { |
|||
"version": "1.0.1", |
|||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", |
|||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" |
|||
}, |
|||
"performance-now": { |
|||
"version": "2.1.0", |
|||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", |
|||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" |
|||
}, |
|||
"process-nextick-args": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", |
|||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" |
|||
}, |
|||
"punycode": { |
|||
"version": "1.4.1", |
|||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", |
|||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" |
|||
}, |
|||
"qs": { |
|||
"version": "6.5.1", |
|||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", |
|||
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" |
|||
}, |
|||
"readable-stream": { |
|||
"version": "2.3.5", |
|||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", |
|||
"integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", |
|||
"requires": { |
|||
"core-util-is": "1.0.2", |
|||
"inherits": "2.0.3", |
|||
"isarray": "1.0.0", |
|||
"process-nextick-args": "2.0.0", |
|||
"safe-buffer": "5.1.1", |
|||
"string_decoder": "1.0.3", |
|||
"util-deprecate": "1.0.2" |
|||
} |
|||
}, |
|||
"request": { |
|||
"version": "2.85.0", |
|||
"resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", |
|||
"integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", |
|||
"requires": { |
|||
"aws-sign2": "0.7.0", |
|||
"aws4": "1.6.0", |
|||
"caseless": "0.12.0", |
|||
"combined-stream": "1.0.6", |
|||
"extend": "3.0.1", |
|||
"forever-agent": "0.6.1", |
|||
"form-data": "2.3.2", |
|||
"har-validator": "5.0.3", |
|||
"hawk": "6.0.2", |
|||
"http-signature": "1.2.0", |
|||
"is-typedarray": "1.0.0", |
|||
"isstream": "0.1.2", |
|||
"json-stringify-safe": "5.0.1", |
|||
"mime-types": "2.1.18", |
|||
"oauth-sign": "0.8.2", |
|||
"performance-now": "2.1.0", |
|||
"qs": "6.5.1", |
|||
"safe-buffer": "5.1.1", |
|||
"stringstream": "0.0.5", |
|||
"tough-cookie": "2.3.4", |
|||
"tunnel-agent": "0.6.0", |
|||
"uuid": "3.2.1" |
|||
} |
|||
}, |
|||
"rimraf": { |
|||
"version": "2.6.2", |
|||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", |
|||
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", |
|||
"requires": { |
|||
"glob": "7.1.2" |
|||
} |
|||
}, |
|||
"safe-buffer": { |
|||
"version": "5.1.1", |
|||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", |
|||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" |
|||
}, |
|||
"semver": { |
|||
"version": "5.3.0", |
|||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", |
|||
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" |
|||
}, |
|||
"set-blocking": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", |
|||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" |
|||
}, |
|||
"signal-exit": { |
|||
"version": "3.0.2", |
|||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", |
|||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" |
|||
}, |
|||
"sntp": { |
|||
"version": "2.1.0", |
|||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", |
|||
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", |
|||
"requires": { |
|||
"hoek": "4.2.1" |
|||
} |
|||
}, |
|||
"sshpk": { |
|||
"version": "1.14.1", |
|||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", |
|||
"integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", |
|||
"requires": { |
|||
"asn1": "0.2.3", |
|||
"assert-plus": "1.0.0", |
|||
"bcrypt-pbkdf": "1.0.1", |
|||
"dashdash": "1.14.1", |
|||
"ecc-jsbn": "0.1.1", |
|||
"getpass": "0.1.7", |
|||
"jsbn": "0.1.1", |
|||
"tweetnacl": "0.14.5" |
|||
} |
|||
}, |
|||
"string-width": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", |
|||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", |
|||
"requires": { |
|||
"code-point-at": "1.1.0", |
|||
"is-fullwidth-code-point": "1.0.0", |
|||
"strip-ansi": "3.0.1" |
|||
} |
|||
}, |
|||
"string_decoder": { |
|||
"version": "1.0.3", |
|||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", |
|||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", |
|||
"requires": { |
|||
"safe-buffer": "5.1.1" |
|||
} |
|||
}, |
|||
"stringstream": { |
|||
"version": "0.0.5", |
|||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", |
|||
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" |
|||
}, |
|||
"strip-ansi": { |
|||
"version": "3.0.1", |
|||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", |
|||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", |
|||
"requires": { |
|||
"ansi-regex": "2.1.1" |
|||
} |
|||
}, |
|||
"tar": { |
|||
"version": "2.2.1", |
|||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", |
|||
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", |
|||
"requires": { |
|||
"block-stream": "0.0.9", |
|||
"fstream": "1.0.11", |
|||
"inherits": "2.0.3" |
|||
} |
|||
}, |
|||
"tough-cookie": { |
|||
"version": "2.3.4", |
|||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", |
|||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", |
|||
"requires": { |
|||
"punycode": "1.4.1" |
|||
} |
|||
}, |
|||
"tunnel-agent": { |
|||
"version": "0.6.0", |
|||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", |
|||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", |
|||
"requires": { |
|||
"safe-buffer": "5.1.1" |
|||
} |
|||
}, |
|||
"tweetnacl": { |
|||
"version": "0.14.5", |
|||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", |
|||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", |
|||
"optional": true |
|||
}, |
|||
"util-deprecate": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", |
|||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" |
|||
}, |
|||
"uuid": { |
|||
"version": "3.2.1", |
|||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", |
|||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" |
|||
}, |
|||
"verror": { |
|||
"version": "1.10.0", |
|||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", |
|||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", |
|||
"requires": { |
|||
"assert-plus": "1.0.0", |
|||
"core-util-is": "1.0.2", |
|||
"extsprintf": "1.3.0" |
|||
} |
|||
}, |
|||
"which": { |
|||
"version": "1.3.0", |
|||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", |
|||
"integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", |
|||
"requires": { |
|||
"isexe": "2.0.0" |
|||
} |
|||
}, |
|||
"wide-align": { |
|||
"version": "1.1.2", |
|||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", |
|||
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", |
|||
"requires": { |
|||
"string-width": "1.0.2" |
|||
} |
|||
}, |
|||
"wrappy": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", |
|||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
{ |
|||
"name": "equihashverify", |
|||
"version": "0.0.1", |
|||
"description": "function to check whether an Equihash solution is valid", |
|||
"main": "equihashverify", |
|||
"scripts": { |
|||
"install": "node-gyp rebuild", |
|||
"test": "echo \"Error: no test specified\" && exit 1" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "https://github.com/josephnicholas/equihashverify" |
|||
}, |
|||
"keywords": [ |
|||
"zclassic" |
|||
], |
|||
"author": "Joshua Yabut", |
|||
"contributors": [ |
|||
"Sammy Libre" |
|||
], |
|||
"license": "MIT", |
|||
"bugs": { |
|||
"url": "https://github.com/josephnicholas/equihashverify/issues" |
|||
}, |
|||
"homepage": "https://github.com/josephnicholas/equihashverify", |
|||
"dependencies": { |
|||
"bindings": "*", |
|||
"node-gyp": "*", |
|||
"nan": "*" |
|||
}, |
|||
"engines": { |
|||
"node": ">=0.12" |
|||
} |
|||
} |
@ -0,0 +1,89 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "random.h" |
|||
|
|||
#include "support/cleanse.h" |
|||
#include "serialize.h" // for begin_ptr(vec) |
|||
#include "util.h" // for LogPrint() |
|||
#include "utilstrencodings.h" // for GetTime() |
|||
|
|||
#include <limits> |
|||
|
|||
#ifndef WIN32 |
|||
#include <sys/time.h> |
|||
#endif |
|||
|
|||
#include "sodium.h" |
|||
|
|||
static inline int64_t GetPerformanceCounter() |
|||
{ |
|||
int64_t nCounter = 0; |
|||
#ifdef WIN32 |
|||
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); |
|||
#else |
|||
timeval t; |
|||
gettimeofday(&t, NULL); |
|||
nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec); |
|||
#endif |
|||
return nCounter; |
|||
} |
|||
|
|||
void GetRandBytes(unsigned char* buf, size_t num) |
|||
{ |
|||
randombytes_buf(buf, num); |
|||
} |
|||
|
|||
uint64_t GetRand(uint64_t nMax) |
|||
{ |
|||
if (nMax == 0) |
|||
return 0; |
|||
|
|||
// The range of the random source must be a multiple of the modulus
|
|||
// to give every possible output value an equal possibility
|
|||
uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax; |
|||
uint64_t nRand = 0; |
|||
do { |
|||
GetRandBytes((unsigned char*)&nRand, sizeof(nRand)); |
|||
} while (nRand >= nRange); |
|||
return (nRand % nMax); |
|||
} |
|||
|
|||
int GetRandInt(int nMax) |
|||
{ |
|||
return GetRand(nMax); |
|||
} |
|||
|
|||
uint256 GetRandHash() |
|||
{ |
|||
uint256 hash; |
|||
GetRandBytes((unsigned char*)&hash, sizeof(hash)); |
|||
return hash; |
|||
} |
|||
|
|||
uint32_t insecure_rand_Rz = 11; |
|||
uint32_t insecure_rand_Rw = 11; |
|||
void seed_insecure_rand(bool fDeterministic) |
|||
{ |
|||
// The seed values have some unlikely fixed points which we avoid.
|
|||
if (fDeterministic) { |
|||
insecure_rand_Rz = insecure_rand_Rw = 11; |
|||
} else { |
|||
uint32_t tmp; |
|||
do { |
|||
GetRandBytes((unsigned char*)&tmp, 4); |
|||
} while (tmp == 0 || tmp == 0x9068ffffU); |
|||
insecure_rand_Rz = tmp; |
|||
do { |
|||
GetRandBytes((unsigned char*)&tmp, 4); |
|||
} while (tmp == 0 || tmp == 0x464fffffU); |
|||
insecure_rand_Rw = tmp; |
|||
} |
|||
} |
|||
|
|||
int GenIdentity(int n) |
|||
{ |
|||
return n-1; |
|||
} |
@ -0,0 +1,74 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_RANDOM_H |
|||
#define BITCOIN_RANDOM_H |
|||
|
|||
#include "uint256.h" |
|||
|
|||
#include <functional> |
|||
#include <stdint.h> |
|||
|
|||
/**
|
|||
* Functions to gather random data via the libsodium CSPRNG |
|||
*/ |
|||
void GetRandBytes(unsigned char* buf, size_t num); |
|||
uint64_t GetRand(uint64_t nMax); |
|||
int GetRandInt(int nMax); |
|||
uint256 GetRandHash(); |
|||
|
|||
/**
|
|||
* Identity function for MappedShuffle, so that elements retain their original order. |
|||
*/ |
|||
int GenIdentity(int n); |
|||
|
|||
/**
|
|||
* Rearranges the elements in the range [first,first+len) randomly, assuming |
|||
* that gen is a uniform random number generator. Follows the same algorithm as |
|||
* std::shuffle in C++11 (a Durstenfeld shuffle). |
|||
* |
|||
* The elements in the range [mapFirst,mapFirst+len) are rearranged according to |
|||
* the same permutation, enabling the permutation to be tracked by the caller. |
|||
* |
|||
* gen takes an integer n and produces a uniform random output in [0,n). |
|||
*/ |
|||
template <typename RandomAccessIterator, typename MapRandomAccessIterator> |
|||
void MappedShuffle(RandomAccessIterator first, |
|||
MapRandomAccessIterator mapFirst, |
|||
size_t len, |
|||
std::function<int(int)> gen) |
|||
{ |
|||
for (size_t i = len-1; i > 0; --i) { |
|||
auto r = gen(i+1); |
|||
assert(r >= 0); |
|||
assert(r <= i); |
|||
std::swap(first[i], first[r]); |
|||
std::swap(mapFirst[i], mapFirst[r]); |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* Seed insecure_rand using the random pool. |
|||
* @param Deterministic Use a deterministic seed |
|||
*/ |
|||
void seed_insecure_rand(bool fDeterministic = false); |
|||
|
|||
/**
|
|||
* MWC RNG of George Marsaglia |
|||
* This is intended to be fast. It has a period of 2^59.3, though the |
|||
* least significant 16 bits only have a period of about 2^30.1. |
|||
* |
|||
* @return random value |
|||
*/ |
|||
extern uint32_t insecure_rand_Rz; |
|||
extern uint32_t insecure_rand_Rw; |
|||
static inline uint32_t insecure_rand(void) |
|||
{ |
|||
insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16); |
|||
insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16); |
|||
return (insecure_rand_Rw << 16) + insecure_rand_Rz; |
|||
} |
|||
|
|||
#endif // BITCOIN_RANDOM_H
|
@ -0,0 +1,996 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_SERIALIZE_H |
|||
#define BITCOIN_SERIALIZE_H |
|||
|
|||
#include <endian.h> |
|||
#include <algorithm> |
|||
#include <assert.h> |
|||
#include <ios> |
|||
#include <limits> |
|||
#include <list> |
|||
#include <map> |
|||
#include <set> |
|||
#include <stdint.h> |
|||
#include <string> |
|||
#include <string.h> |
|||
#include <utility> |
|||
#include <vector> |
|||
|
|||
#include <boost/array.hpp> |
|||
#include <boost/optional.hpp> |
|||
|
|||
class CScript; |
|||
|
|||
static const unsigned int MAX_SIZE = 0x02000000; |
|||
|
|||
/**
|
|||
* Used to bypass the rule against non-const reference to temporary |
|||
* where it makes sense with wrappers such as CFlatData or CTxDB |
|||
*/ |
|||
template<typename T> |
|||
inline T& REF(const T& val) |
|||
{ |
|||
return const_cast<T&>(val); |
|||
} |
|||
|
|||
/**
|
|||
* Used to acquire a non-const pointer "this" to generate bodies |
|||
* of const serialization operations from a template |
|||
*/ |
|||
template<typename T> |
|||
inline T* NCONST_PTR(const T* val) |
|||
{ |
|||
return const_cast<T*>(val); |
|||
} |
|||
|
|||
/**
|
|||
* Get begin pointer of vector (non-const version). |
|||
* @note These functions avoid the undefined case of indexing into an empty |
|||
* vector, as well as that of indexing after the end of the vector. |
|||
*/ |
|||
template <class T, class TAl> |
|||
inline T* begin_ptr(std::vector<T,TAl>& v) |
|||
{ |
|||
return v.empty() ? NULL : &v[0]; |
|||
} |
|||
/** Get begin pointer of vector (const version) */ |
|||
template <class T, class TAl> |
|||
inline const T* begin_ptr(const std::vector<T,TAl>& v) |
|||
{ |
|||
return v.empty() ? NULL : &v[0]; |
|||
} |
|||
/** Get end pointer of vector (non-const version) */ |
|||
template <class T, class TAl> |
|||
inline T* end_ptr(std::vector<T,TAl>& v) |
|||
{ |
|||
return v.empty() ? NULL : (&v[0] + v.size()); |
|||
} |
|||
/** Get end pointer of vector (const version) */ |
|||
template <class T, class TAl> |
|||
inline const T* end_ptr(const std::vector<T,TAl>& v) |
|||
{ |
|||
return v.empty() ? NULL : (&v[0] + v.size()); |
|||
} |
|||
|
|||
/*
|
|||
* Lowest-level serialization and conversion. |
|||
* @note Sizes of these types are verified in the tests |
|||
*/ |
|||
template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) |
|||
{ |
|||
s.write((char*)&obj, 1); |
|||
} |
|||
template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj) |
|||
{ |
|||
obj = htole16(obj); |
|||
s.write((char*)&obj, 2); |
|||
} |
|||
template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj) |
|||
{ |
|||
obj = htole32(obj); |
|||
s.write((char*)&obj, 4); |
|||
} |
|||
template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj) |
|||
{ |
|||
obj = htole64(obj); |
|||
s.write((char*)&obj, 8); |
|||
} |
|||
template<typename Stream> inline uint8_t ser_readdata8(Stream &s) |
|||
{ |
|||
uint8_t obj; |
|||
s.read((char*)&obj, 1); |
|||
return obj; |
|||
} |
|||
template<typename Stream> inline uint16_t ser_readdata16(Stream &s) |
|||
{ |
|||
uint16_t obj; |
|||
s.read((char*)&obj, 2); |
|||
return le16toh(obj); |
|||
} |
|||
template<typename Stream> inline uint32_t ser_readdata32(Stream &s) |
|||
{ |
|||
uint32_t obj; |
|||
s.read((char*)&obj, 4); |
|||
return le32toh(obj); |
|||
} |
|||
template<typename Stream> inline uint64_t ser_readdata64(Stream &s) |
|||
{ |
|||
uint64_t obj; |
|||
s.read((char*)&obj, 8); |
|||
return le64toh(obj); |
|||
} |
|||
inline uint64_t ser_double_to_uint64(double x) |
|||
{ |
|||
union { double x; uint64_t y; } tmp; |
|||
tmp.x = x; |
|||
return tmp.y; |
|||
} |
|||
inline uint32_t ser_float_to_uint32(float x) |
|||
{ |
|||
union { float x; uint32_t y; } tmp; |
|||
tmp.x = x; |
|||
return tmp.y; |
|||
} |
|||
inline double ser_uint64_to_double(uint64_t y) |
|||
{ |
|||
union { double x; uint64_t y; } tmp; |
|||
tmp.y = y; |
|||
return tmp.x; |
|||
} |
|||
inline float ser_uint32_to_float(uint32_t y) |
|||
{ |
|||
union { float x; uint32_t y; } tmp; |
|||
tmp.y = y; |
|||
return tmp.x; |
|||
} |
|||
|
|||
|
|||
/////////////////////////////////////////////////////////////////
|
|||
//
|
|||
// Templates for serializing to anything that looks like a stream,
|
|||
// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
|
|||
//
|
|||
|
|||
enum |
|||
{ |
|||
// primary actions
|
|||
SER_NETWORK = (1 << 0), |
|||
SER_DISK = (1 << 1), |
|||
SER_GETHASH = (1 << 2), |
|||
}; |
|||
|
|||
#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action)) |
|||
|
|||
/**
|
|||
* Implement three methods for serializable objects. These are actually wrappers over |
|||
* "SerializationOp" template, which implements the body of each class' serialization |
|||
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be |
|||
* added as members. |
|||
*/ |
|||
#define ADD_SERIALIZE_METHODS \ |
|||
size_t GetSerializeSize(int nType, int nVersion) const { \ |
|||
CSizeComputer s(nType, nVersion); \ |
|||
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\ |
|||
return s.size(); \ |
|||
} \ |
|||
template<typename Stream> \ |
|||
void Serialize(Stream& s, int nType, int nVersion) const { \ |
|||
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\ |
|||
} \ |
|||
template<typename Stream> \ |
|||
void Unserialize(Stream& s, int nType, int nVersion) { \ |
|||
SerializationOp(s, CSerActionUnserialize(), nType, nVersion); \ |
|||
} |
|||
|
|||
/*
|
|||
* Basic Types |
|||
*/ |
|||
inline unsigned int GetSerializeSize(char a, int, int=0) { return 1; } |
|||
inline unsigned int GetSerializeSize(int8_t a, int, int=0) { return 1; } |
|||
inline unsigned int GetSerializeSize(uint8_t a, int, int=0) { return 1; } |
|||
inline unsigned int GetSerializeSize(int16_t a, int, int=0) { return 2; } |
|||
inline unsigned int GetSerializeSize(uint16_t a, int, int=0) { return 2; } |
|||
inline unsigned int GetSerializeSize(int32_t a, int, int=0) { return 4; } |
|||
inline unsigned int GetSerializeSize(uint32_t a, int, int=0) { return 4; } |
|||
inline unsigned int GetSerializeSize(int64_t a, int, int=0) { return 8; } |
|||
inline unsigned int GetSerializeSize(uint64_t a, int, int=0) { return 8; } |
|||
inline unsigned int GetSerializeSize(float a, int, int=0) { return 4; } |
|||
inline unsigned int GetSerializeSize(double a, int, int=0) { return 8; } |
|||
|
|||
template<typename Stream> inline void Serialize(Stream& s, char a, int, int=0) { ser_writedata8(s, a); } // TODO Get rid of bare char
|
|||
template<typename Stream> inline void Serialize(Stream& s, int8_t a, int, int=0) { ser_writedata8(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, uint8_t a, int, int=0) { ser_writedata8(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, int16_t a, int, int=0) { ser_writedata16(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, uint16_t a, int, int=0) { ser_writedata16(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, int32_t a, int, int=0) { ser_writedata32(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, uint32_t a, int, int=0) { ser_writedata32(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, int64_t a, int, int=0) { ser_writedata64(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, uint64_t a, int, int=0) { ser_writedata64(s, a); } |
|||
template<typename Stream> inline void Serialize(Stream& s, float a, int, int=0) { ser_writedata32(s, ser_float_to_uint32(a)); } |
|||
template<typename Stream> inline void Serialize(Stream& s, double a, int, int=0) { ser_writedata64(s, ser_double_to_uint64(a)); } |
|||
|
|||
template<typename Stream> inline void Unserialize(Stream& s, char& a, int, int=0) { a = ser_readdata8(s); } // TODO Get rid of bare char
|
|||
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a, int, int=0) { a = ser_readdata8(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a, int, int=0) { a = ser_readdata8(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, int16_t& a, int, int=0) { a = ser_readdata16(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a, int, int=0) { a = ser_readdata16(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, int32_t& a, int, int=0) { a = ser_readdata32(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a, int, int=0) { a = ser_readdata32(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, int64_t& a, int, int=0) { a = ser_readdata64(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a, int, int=0) { a = ser_readdata64(s); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, float& a, int, int=0) { a = ser_uint32_to_float(ser_readdata32(s)); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, double& a, int, int=0) { a = ser_uint64_to_double(ser_readdata64(s)); } |
|||
|
|||
inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); } |
|||
template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; ser_writedata8(s, f); } |
|||
template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f=ser_readdata8(s); a=f; } |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/**
|
|||
* Compact Size |
|||
* size < 253 -- 1 byte |
|||
* size <= 0xFFFF -- 3 bytes (253 + 2 bytes) |
|||
* size <= 0xFFFFFFFF -- 5 bytes (254 + 4 bytes) |
|||
* size > 0xFFFFFFFF -- 9 bytes (255 + 8 bytes) |
|||
*/ |
|||
inline unsigned int GetSizeOfCompactSize(uint64_t nSize) |
|||
{ |
|||
if (nSize < 253) return 1; |
|||
else if (nSize <= 0xFFFFu) return 3; |
|||
else if (nSize <= 0xFFFFFFFFu) return 5; |
|||
else return 9; |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void WriteCompactSize(Stream& os, uint64_t nSize) |
|||
{ |
|||
if (nSize < 253) |
|||
{ |
|||
ser_writedata8(os, nSize); |
|||
} |
|||
else if (nSize <= 0xFFFFu) |
|||
{ |
|||
ser_writedata8(os, 253); |
|||
ser_writedata16(os, nSize); |
|||
} |
|||
else if (nSize <= 0xFFFFFFFFu) |
|||
{ |
|||
ser_writedata8(os, 254); |
|||
ser_writedata32(os, nSize); |
|||
} |
|||
else |
|||
{ |
|||
ser_writedata8(os, 255); |
|||
ser_writedata64(os, nSize); |
|||
} |
|||
} |
|||
|
|||
template<typename Stream> |
|||
uint64_t ReadCompactSize(Stream& is) |
|||
{ |
|||
uint8_t chSize = ser_readdata8(is); |
|||
uint64_t nSizeRet = 0; |
|||
if (chSize < 253) |
|||
{ |
|||
nSizeRet = chSize; |
|||
} |
|||
else if (chSize == 253) |
|||
{ |
|||
nSizeRet = ser_readdata16(is); |
|||
if (nSizeRet < 253) |
|||
throw std::ios_base::failure("non-canonical ReadCompactSize()"); |
|||
} |
|||
else if (chSize == 254) |
|||
{ |
|||
nSizeRet = ser_readdata32(is); |
|||
if (nSizeRet < 0x10000u) |
|||
throw std::ios_base::failure("non-canonical ReadCompactSize()"); |
|||
} |
|||
else |
|||
{ |
|||
nSizeRet = ser_readdata64(is); |
|||
if (nSizeRet < 0x100000000ULL) |
|||
throw std::ios_base::failure("non-canonical ReadCompactSize()"); |
|||
} |
|||
if (nSizeRet > (uint64_t)MAX_SIZE) |
|||
throw std::ios_base::failure("ReadCompactSize(): size too large"); |
|||
return nSizeRet; |
|||
} |
|||
|
|||
/**
|
|||
* Variable-length integers: bytes are a MSB base-128 encoding of the number. |
|||
* The high bit in each byte signifies whether another digit follows. To make |
|||
* sure the encoding is one-to-one, one is subtracted from all but the last digit. |
|||
* Thus, the byte sequence a[] with length len, where all but the last byte |
|||
* has bit 128 set, encodes the number: |
|||
* |
|||
* (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1)) |
|||
* |
|||
* Properties: |
|||
* * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes) |
|||
* * Every integer has exactly one encoding |
|||
* * Encoding does not depend on size of original integer type |
|||
* * No redundancy: every (infinite) byte sequence corresponds to a list |
|||
* of encoded integers. |
|||
* |
|||
* 0: [0x00] 256: [0x81 0x00] |
|||
* 1: [0x01] 16383: [0xFE 0x7F] |
|||
* 127: [0x7F] 16384: [0xFF 0x00] |
|||
* 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F] |
|||
* 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F] |
|||
* 2^32: [0x8E 0xFE 0xFE 0xFF 0x00] |
|||
*/ |
|||
|
|||
template<typename I> |
|||
inline unsigned int GetSizeOfVarInt(I n) |
|||
{ |
|||
int nRet = 0; |
|||
while(true) { |
|||
nRet++; |
|||
if (n <= 0x7F) |
|||
break; |
|||
n = (n >> 7) - 1; |
|||
} |
|||
return nRet; |
|||
} |
|||
|
|||
template<typename Stream, typename I> |
|||
void WriteVarInt(Stream& os, I n) |
|||
{ |
|||
unsigned char tmp[(sizeof(n)*8+6)/7]; |
|||
int len=0; |
|||
while(true) { |
|||
tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00); |
|||
if (n <= 0x7F) |
|||
break; |
|||
n = (n >> 7) - 1; |
|||
len++; |
|||
} |
|||
do { |
|||
ser_writedata8(os, tmp[len]); |
|||
} while(len--); |
|||
} |
|||
|
|||
template<typename Stream, typename I> |
|||
I ReadVarInt(Stream& is) |
|||
{ |
|||
I n = 0; |
|||
while(true) { |
|||
unsigned char chData = ser_readdata8(is); |
|||
n = (n << 7) | (chData & 0x7F); |
|||
if (chData & 0x80) |
|||
n++; |
|||
else |
|||
return n; |
|||
} |
|||
} |
|||
|
|||
#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) |
|||
#define VARINT(obj) REF(WrapVarInt(REF(obj))) |
|||
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj))) |
|||
|
|||
/**
|
|||
* Wrapper for serializing arrays and POD. |
|||
*/ |
|||
class CFlatData |
|||
{ |
|||
protected: |
|||
char* pbegin; |
|||
char* pend; |
|||
public: |
|||
CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } |
|||
template <class T, class TAl> |
|||
explicit CFlatData(std::vector<T,TAl> &v) |
|||
{ |
|||
pbegin = (char*)begin_ptr(v); |
|||
pend = (char*)end_ptr(v); |
|||
} |
|||
char* begin() { return pbegin; } |
|||
const char* begin() const { return pbegin; } |
|||
char* end() { return pend; } |
|||
const char* end() const { return pend; } |
|||
|
|||
unsigned int GetSerializeSize(int, int=0) const |
|||
{ |
|||
return pend - pbegin; |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Serialize(Stream& s, int, int=0) const |
|||
{ |
|||
s.write(pbegin, pend - pbegin); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Unserialize(Stream& s, int, int=0) |
|||
{ |
|||
s.read(pbegin, pend - pbegin); |
|||
} |
|||
}; |
|||
|
|||
template<typename I> |
|||
class CVarInt |
|||
{ |
|||
protected: |
|||
I &n; |
|||
public: |
|||
CVarInt(I& nIn) : n(nIn) { } |
|||
|
|||
unsigned int GetSerializeSize(int, int) const { |
|||
return GetSizeOfVarInt<I>(n); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Serialize(Stream &s, int, int) const { |
|||
WriteVarInt<Stream,I>(s, n); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Unserialize(Stream& s, int, int) { |
|||
n = ReadVarInt<Stream,I>(s); |
|||
} |
|||
}; |
|||
|
|||
template<size_t Limit> |
|||
class LimitedString |
|||
{ |
|||
protected: |
|||
std::string& string; |
|||
public: |
|||
LimitedString(std::string& string) : string(string) {} |
|||
|
|||
template<typename Stream> |
|||
void Unserialize(Stream& s, int, int=0) |
|||
{ |
|||
size_t size = ReadCompactSize(s); |
|||
if (size > Limit) { |
|||
throw std::ios_base::failure("String length limit exceeded"); |
|||
} |
|||
string.resize(size); |
|||
if (size != 0) |
|||
s.read((char*)&string[0], size); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Serialize(Stream& s, int, int=0) const |
|||
{ |
|||
WriteCompactSize(s, string.size()); |
|||
if (!string.empty()) |
|||
s.write((char*)&string[0], string.size()); |
|||
} |
|||
|
|||
unsigned int GetSerializeSize(int, int=0) const |
|||
{ |
|||
return GetSizeOfCompactSize(string.size()) + string.size(); |
|||
} |
|||
}; |
|||
|
|||
template<typename I> |
|||
CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); } |
|||
|
|||
/**
|
|||
* Forward declarations |
|||
*/ |
|||
|
|||
/**
|
|||
* string |
|||
*/ |
|||
template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0); |
|||
template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0); |
|||
template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0); |
|||
|
|||
/**
|
|||
* vector |
|||
* vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. |
|||
*/ |
|||
template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&); |
|||
template<typename T, typename A, typename V> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&); |
|||
template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion); |
|||
template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&); |
|||
template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const V&); |
|||
template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion); |
|||
template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const unsigned char&); |
|||
template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&); |
|||
template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* others derived from vector |
|||
*/ |
|||
extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion); |
|||
template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion); |
|||
template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* optional |
|||
*/ |
|||
template<typename T> unsigned int GetSerializeSize(const boost::optional<T> &item, int nType, int nVersion); |
|||
template<typename Stream, typename T> void Serialize(Stream& os, const boost::optional<T>& item, int nType, int nVersion); |
|||
template<typename Stream, typename T> void Unserialize(Stream& is, boost::optional<T>& item, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* array |
|||
*/ |
|||
template<typename T, std::size_t N> unsigned int GetSerializeSize(const boost::array<T, N> &item, int nType, int nVersion); |
|||
template<typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const boost::array<T, N>& item, int nType, int nVersion); |
|||
template<typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, boost::array<T, N>& item, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* pair |
|||
*/ |
|||
template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion); |
|||
template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion); |
|||
template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* map |
|||
*/ |
|||
template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion); |
|||
template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion); |
|||
template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* set |
|||
*/ |
|||
template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion); |
|||
template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion); |
|||
template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion); |
|||
|
|||
/**
|
|||
* list |
|||
*/ |
|||
template<typename T, typename A> unsigned int GetSerializeSize(const std::list<T, A>& m, int nType, int nVersion); |
|||
template<typename Stream, typename T, typename A> void Serialize(Stream& os, const std::list<T, A>& m, int nType, int nVersion); |
|||
template<typename Stream, typename T, typename A> void Unserialize(Stream& is, std::list<T, A>& m, int nType, int nVersion); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/**
|
|||
* If none of the specialized versions above matched, default to calling member function. |
|||
* "int nType" is changed to "long nType" to keep from getting an ambiguous overload error. |
|||
* The compiler will only cast int to long if none of the other templates matched. |
|||
* Thanks to Boost serialization for this idea. |
|||
*/ |
|||
template<typename T> |
|||
inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion) |
|||
{ |
|||
return a.GetSerializeSize((int)nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename T> |
|||
inline void Serialize(Stream& os, const T& a, long nType, int nVersion) |
|||
{ |
|||
a.Serialize(os, (int)nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename T> |
|||
inline void Unserialize(Stream& is, T& a, long nType, int nVersion) |
|||
{ |
|||
a.Unserialize(is, (int)nType, nVersion); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/**
|
|||
* string |
|||
*/ |
|||
template<typename C> |
|||
unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int) |
|||
{ |
|||
return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]); |
|||
} |
|||
|
|||
template<typename Stream, typename C> |
|||
void Serialize(Stream& os, const std::basic_string<C>& str, int, int) |
|||
{ |
|||
WriteCompactSize(os, str.size()); |
|||
if (!str.empty()) |
|||
os.write((char*)&str[0], str.size() * sizeof(str[0])); |
|||
} |
|||
|
|||
template<typename Stream, typename C> |
|||
void Unserialize(Stream& is, std::basic_string<C>& str, int, int) |
|||
{ |
|||
unsigned int nSize = ReadCompactSize(is); |
|||
str.resize(nSize); |
|||
if (nSize != 0) |
|||
is.read((char*)&str[0], nSize * sizeof(str[0])); |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* vector |
|||
*/ |
|||
template<typename T, typename A> |
|||
unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&) |
|||
{ |
|||
return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); |
|||
} |
|||
|
|||
template<typename T, typename A, typename V> |
|||
unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&) |
|||
{ |
|||
unsigned int nSize = GetSizeOfCompactSize(v.size()); |
|||
for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi) |
|||
nSize += GetSerializeSize((*vi), nType, nVersion); |
|||
return nSize; |
|||
} |
|||
|
|||
template<typename T, typename A> |
|||
inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion) |
|||
{ |
|||
return GetSerializeSize_impl(v, nType, nVersion, T()); |
|||
} |
|||
|
|||
|
|||
template<typename Stream, typename T, typename A> |
|||
void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&) |
|||
{ |
|||
WriteCompactSize(os, v.size()); |
|||
if (!v.empty()) |
|||
os.write((char*)&v[0], v.size() * sizeof(T)); |
|||
} |
|||
|
|||
template<typename Stream, typename T, typename A, typename V> |
|||
void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const V&) |
|||
{ |
|||
WriteCompactSize(os, v.size()); |
|||
for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi) |
|||
::Serialize(os, (*vi), nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename T, typename A> |
|||
inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion) |
|||
{ |
|||
Serialize_impl(os, v, nType, nVersion, T()); |
|||
} |
|||
|
|||
|
|||
template<typename Stream, typename T, typename A> |
|||
void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const unsigned char&) |
|||
{ |
|||
// Limit size per read so bogus size value won't cause out of memory
|
|||
v.clear(); |
|||
unsigned int nSize = ReadCompactSize(is); |
|||
unsigned int i = 0; |
|||
while (i < nSize) |
|||
{ |
|||
unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); |
|||
v.resize(i + blk); |
|||
is.read((char*)&v[i], blk * sizeof(T)); |
|||
i += blk; |
|||
} |
|||
} |
|||
|
|||
template<typename Stream, typename T, typename A, typename V> |
|||
void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&) |
|||
{ |
|||
v.clear(); |
|||
unsigned int nSize = ReadCompactSize(is); |
|||
unsigned int i = 0; |
|||
unsigned int nMid = 0; |
|||
while (nMid < nSize) |
|||
{ |
|||
nMid += 5000000 / sizeof(T); |
|||
if (nMid > nSize) |
|||
nMid = nSize; |
|||
v.resize(nMid); |
|||
for (; i < nMid; i++) |
|||
Unserialize(is, v[i], nType, nVersion); |
|||
} |
|||
} |
|||
|
|||
template<typename Stream, typename T, typename A> |
|||
inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion) |
|||
{ |
|||
Unserialize_impl(is, v, nType, nVersion, T()); |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* others derived from vector |
|||
*/ |
|||
inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion) |
|||
{ |
|||
return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Serialize(Stream& os, const CScript& v, int nType, int nVersion) |
|||
{ |
|||
Serialize(os, (const std::vector<unsigned char>&)v, nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Unserialize(Stream& is, CScript& v, int nType, int nVersion) |
|||
{ |
|||
Unserialize(is, (std::vector<unsigned char>&)v, nType, nVersion); |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* optional |
|||
*/ |
|||
template<typename T> |
|||
unsigned int GetSerializeSize(const boost::optional<T> &item, int nType, int nVersion) |
|||
{ |
|||
if (item) { |
|||
return 1 + GetSerializeSize(*item, nType, nVersion); |
|||
} else { |
|||
return 1; |
|||
} |
|||
} |
|||
|
|||
template<typename Stream, typename T> |
|||
void Serialize(Stream& os, const boost::optional<T>& item, int nType, int nVersion) |
|||
{ |
|||
// If the value is there, put 0x01 and then serialize the value.
|
|||
// If it's not, put 0x00.
|
|||
if (item) { |
|||
unsigned char discriminant = 0x01; |
|||
Serialize(os, discriminant, nType, nVersion); |
|||
Serialize(os, *item, nType, nVersion); |
|||
} else { |
|||
unsigned char discriminant = 0x00; |
|||
Serialize(os, discriminant, nType, nVersion); |
|||
} |
|||
} |
|||
|
|||
template<typename Stream, typename T> |
|||
void Unserialize(Stream& is, boost::optional<T>& item, int nType, int nVersion) |
|||
{ |
|||
unsigned char discriminant = 0x00; |
|||
Unserialize(is, discriminant, nType, nVersion); |
|||
|
|||
if (discriminant == 0x00) { |
|||
item = boost::none; |
|||
} else if (discriminant == 0x01) { |
|||
T object; |
|||
Unserialize(is, object, nType, nVersion); |
|||
item = object; |
|||
} else { |
|||
throw std::ios_base::failure("non-canonical optional discriminant"); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* array |
|||
*/ |
|||
template<typename T, std::size_t N> |
|||
unsigned int GetSerializeSize(const boost::array<T, N> &item, int nType, int nVersion) |
|||
{ |
|||
unsigned int size = 0; |
|||
for (size_t i = 0; i < N; i++) { |
|||
size += GetSerializeSize(item[0], nType, nVersion); |
|||
} |
|||
return size; |
|||
} |
|||
|
|||
template<typename Stream, typename T, std::size_t N> |
|||
void Serialize(Stream& os, const boost::array<T, N>& item, int nType, int nVersion) |
|||
{ |
|||
for (size_t i = 0; i < N; i++) { |
|||
Serialize(os, item[i], nType, nVersion); |
|||
} |
|||
} |
|||
|
|||
template<typename Stream, typename T, std::size_t N> |
|||
void Unserialize(Stream& is, boost::array<T, N>& item, int nType, int nVersion) |
|||
{ |
|||
for (size_t i = 0; i < N; i++) { |
|||
Unserialize(is, item[i], nType, nVersion); |
|||
} |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* pair |
|||
*/ |
|||
template<typename K, typename T> |
|||
unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion) |
|||
{ |
|||
return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename K, typename T> |
|||
void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion) |
|||
{ |
|||
Serialize(os, item.first, nType, nVersion); |
|||
Serialize(os, item.second, nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename K, typename T> |
|||
void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion) |
|||
{ |
|||
Unserialize(is, item.first, nType, nVersion); |
|||
Unserialize(is, item.second, nType, nVersion); |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* map |
|||
*/ |
|||
template<typename K, typename T, typename Pred, typename A> |
|||
unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion) |
|||
{ |
|||
unsigned int nSize = GetSizeOfCompactSize(m.size()); |
|||
for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi) |
|||
nSize += GetSerializeSize((*mi), nType, nVersion); |
|||
return nSize; |
|||
} |
|||
|
|||
template<typename Stream, typename K, typename T, typename Pred, typename A> |
|||
void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion) |
|||
{ |
|||
WriteCompactSize(os, m.size()); |
|||
for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi) |
|||
Serialize(os, (*mi), nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename K, typename T, typename Pred, typename A> |
|||
void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion) |
|||
{ |
|||
m.clear(); |
|||
unsigned int nSize = ReadCompactSize(is); |
|||
typename std::map<K, T, Pred, A>::iterator mi = m.begin(); |
|||
for (unsigned int i = 0; i < nSize; i++) |
|||
{ |
|||
std::pair<K, T> item; |
|||
Unserialize(is, item, nType, nVersion); |
|||
mi = m.insert(mi, item); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* set |
|||
*/ |
|||
template<typename K, typename Pred, typename A> |
|||
unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion) |
|||
{ |
|||
unsigned int nSize = GetSizeOfCompactSize(m.size()); |
|||
for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it) |
|||
nSize += GetSerializeSize((*it), nType, nVersion); |
|||
return nSize; |
|||
} |
|||
|
|||
template<typename Stream, typename K, typename Pred, typename A> |
|||
void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion) |
|||
{ |
|||
WriteCompactSize(os, m.size()); |
|||
for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it) |
|||
Serialize(os, (*it), nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename K, typename Pred, typename A> |
|||
void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion) |
|||
{ |
|||
m.clear(); |
|||
unsigned int nSize = ReadCompactSize(is); |
|||
typename std::set<K, Pred, A>::iterator it = m.begin(); |
|||
for (unsigned int i = 0; i < nSize; i++) |
|||
{ |
|||
K key; |
|||
Unserialize(is, key, nType, nVersion); |
|||
it = m.insert(it, key); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* list |
|||
*/ |
|||
template<typename T, typename A> |
|||
unsigned int GetSerializeSize(const std::list<T, A>& l, int nType, int nVersion) |
|||
{ |
|||
unsigned int nSize = GetSizeOfCompactSize(l.size()); |
|||
for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it) |
|||
nSize += GetSerializeSize((*it), nType, nVersion); |
|||
return nSize; |
|||
} |
|||
|
|||
template<typename Stream, typename T, typename A> |
|||
void Serialize(Stream& os, const std::list<T, A>& l, int nType, int nVersion) |
|||
{ |
|||
WriteCompactSize(os, l.size()); |
|||
for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it) |
|||
Serialize(os, (*it), nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename T, typename A> |
|||
void Unserialize(Stream& is, std::list<T, A>& l, int nType, int nVersion) |
|||
{ |
|||
l.clear(); |
|||
unsigned int nSize = ReadCompactSize(is); |
|||
typename std::list<T, A>::iterator it = l.begin(); |
|||
for (unsigned int i = 0; i < nSize; i++) |
|||
{ |
|||
T item; |
|||
Unserialize(is, item, nType, nVersion); |
|||
l.push_back(item); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/**
|
|||
* Support for ADD_SERIALIZE_METHODS and READWRITE macro |
|||
*/ |
|||
struct CSerActionSerialize |
|||
{ |
|||
bool ForRead() const { return false; } |
|||
}; |
|||
struct CSerActionUnserialize |
|||
{ |
|||
bool ForRead() const { return true; } |
|||
}; |
|||
|
|||
template<typename Stream, typename T> |
|||
inline void SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action) |
|||
{ |
|||
::Serialize(s, obj, nType, nVersion); |
|||
} |
|||
|
|||
template<typename Stream, typename T> |
|||
inline void SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action) |
|||
{ |
|||
::Unserialize(s, obj, nType, nVersion); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
class CSizeComputer |
|||
{ |
|||
protected: |
|||
size_t nSize; |
|||
|
|||
public: |
|||
int nType; |
|||
int nVersion; |
|||
|
|||
CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {} |
|||
|
|||
CSizeComputer& write(const char *psz, size_t nSize) |
|||
{ |
|||
this->nSize += nSize; |
|||
return *this; |
|||
} |
|||
|
|||
template<typename T> |
|||
CSizeComputer& operator<<(const T& obj) |
|||
{ |
|||
::Serialize(*this, obj, nType, nVersion); |
|||
return (*this); |
|||
} |
|||
|
|||
size_t size() const { |
|||
return nSize; |
|||
} |
|||
}; |
|||
|
|||
#endif // BITCOIN_SERIALIZE_H
|
@ -0,0 +1,13 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "cleanse.h" |
|||
|
|||
#include <openssl/crypto.h> |
|||
|
|||
void memory_cleanse(void *ptr, size_t len) |
|||
{ |
|||
OPENSSL_cleanse(ptr, len); |
|||
} |
@ -0,0 +1,13 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_SUPPORT_CLEANSE_H |
|||
#define BITCOIN_SUPPORT_CLEANSE_H |
|||
|
|||
#include <stdlib.h> |
|||
|
|||
void memory_cleanse(void *ptr, size_t len); |
|||
|
|||
#endif // BITCOIN_SUPPORT_CLEANSE_H
|
@ -0,0 +1,6 @@ |
|||
var ev = require('bindings')('equihashverify.node'); |
|||
|
|||
header = Buffer('0400000008e9694cc2120ec1b5733cc12687b609058eec4f7046a521ad1d1e3049b400003e7420ed6f40659de0305ef9b7ec037f4380ed9848bc1c015691c90aa16ff3930000000000000000000000000000000000000000000000000000000000000000c9310d5874e0001f000000000000000000000000000000010b000000000000000000000000000040', 'hex'); |
|||
soln = Buffer('00b43863a213bfe79f00337f5a729f09710abcc07035ef8ac34372abddecf2f82715f7223f075af96f0604fc124d6151fc8fb516d24a137faec123a89aa9a433f8a25a6bcfc554c28be556f6c878f96539186fab191505f278df48bf1ad2240e5bb39f372a143de1dd1b672312e00d52a3dd83f471b0239a7e8b30d4b9153027df87c8cd0b64de76749539fea376b4f39d08cf3d5e821495e52fdfa6f8085e59fc670656121c9d7c01388c8b4b4585aa7b9ac3f7ae796f9eb1fadba1730a1860eed797feabb18832b5e8f003c0adaf0788d1016e7a8969144018ecc86140aa4553962aa739a4850b509b505e158c5f9e2d5376374652e9e6d81b19fa0351be229af136efbce681463cc53d7880c1eeca3411154474ff8a7b2bac034a2026646776a517bf63921c31fbbd6be7c3ff42aab28230bfe81d33800b892b262f3579b7a41925a59f5cc1d4f523577c19ff9f92023146fa26486595bd89a1ba459eb0b5cec0578c3a071dbec73eca054c723ab30ce8e69de32e779cd2f1030e39878ac6ea3cdca743b43aedefe1a9b4f2da861038e2759defef0b8cad11d4179f2f08881b53ccc203e558c0571e049d998a257b3279016aad0d7999b609f6331a0d0f88e286a70432ca7f50a5bb8fafbbe9230b4ccb1fa57361c163d6b9f84579d61f41585a022d07dc8e55a8de4d8f87641dae777819458a2bf1bb02c438480ff11621ca8442ec2946875cce247c8877051359e9c822670d37bb00fa806e60e8e890ce62540fda2d5b1c790ca1e005030ac6d8e63db577bb98be111ee146828f9c48ee6257d7627b93ea3dd11aac3412e63dfc7ca132a73c4f51e7650f3f8ecf57bfc18716990b492d50e0a3e5fbf6136e771b91f7283ec3326209265b9531d157f8a07a4117fc8fb29ba1363afc6f9f0608251ea595256727a5bbe28f42a42edfbfa9017680e32980d4ad381612612b2bc7ad91e82eca693ea4fc27049a99636b50a576f1e55c72202d582b150ef194c1419f53177ecf315ea6b0e2f1aa8cd8f59b165aa0d89561c537fb6141f5813b7a4968fe16afc703326113f68508d88ff8d0aee1e88a84c0ae56c72f27511290ced48e93e8c95419d14aed1a5b2e9b2c9c1070c593e5eb50bb9a80e14e9f9fe501f56b1b3140159e8213b75d48d14af472a604484cd8e7e7abb6820245ed3ab29f9947463a033c586194be45eadec8392c8614d83a1e9ca0fe5655fa14f7a9c1d1f8f2185a06193ff4a3c3e9a96b02310033ceaa25894e7c56a6147e691597098054e285d39656d3d459ec5d13243c062b6eb44e19a13bdfc0b3c96bd3d1aeb75bb6b080322aea23555993cb529243958bb1a0e5d5027e6c78155437242d1d13c1d6e442a0e3783147a08bbfc0c2529fb705ad27713df40486fd58f001977f25dfd3c202451c07010a3880bca63959ca61f10ed3871f1152166fce2b52135718a8ceb239a0664a31c62defaad70be4b920dce70549c10d9138fbbad7f291c5b73fa21c3889929b143bc1576b72f70667ac11052b686891085290d871db528b5cfdc10a6d563925227609f10d1768a0e02dc7471ad424f94f737d4e7eb0fb167f1434fc4ae2d49e152f06f0845b6db0a44f0d6f5e7410420e6bd1f430b1af956005bf72b51405a04d9a5d9906ceca52c22c855785c3c3ac4c3e9bf532d31bab321e1db66f6a9f7dc9c017f2b7d8dfeb933cf5bbae71311ae318f6d187ebc5c843be342b08a9a0ff7c4b9c4b0f4fa74b13296afe84b6481440d58332e07b3d051ed55219d28e77af6612134da4431b797c63ef55bc53831e2f421db620fee51ba0967e4ed7009ef90af2204259bbfbb54537fd35c2132fa8e7f9c84bf9938d248862c6ca1cca9f48b0b33aa1589185c4eabc1c32', 'hex'); |
|||
|
|||
console.log(ev.verify(header, soln)); |
File diff suppressed because it is too large
@ -0,0 +1,146 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "uint256.h" |
|||
|
|||
#include "utilstrencodings.h" |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
template <unsigned int BITS> |
|||
base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch) |
|||
{ |
|||
assert(vch.size() == sizeof(data)); |
|||
memcpy(data, &vch[0], sizeof(data)); |
|||
} |
|||
|
|||
template <unsigned int BITS> |
|||
std::string base_blob<BITS>::GetHex() const |
|||
{ |
|||
char psz[sizeof(data) * 2 + 1]; |
|||
for (unsigned int i = 0; i < sizeof(data); i++) |
|||
sprintf(psz + i * 2, "%02x", data[sizeof(data) - i - 1]); |
|||
return std::string(psz, psz + sizeof(data) * 2); |
|||
} |
|||
|
|||
template <unsigned int BITS> |
|||
void base_blob<BITS>::SetHex(const char* psz) |
|||
{ |
|||
memset(data, 0, sizeof(data)); |
|||
|
|||
// skip leading spaces
|
|||
while (isspace(*psz)) |
|||
psz++; |
|||
|
|||
// skip 0x
|
|||
if (psz[0] == '0' && tolower(psz[1]) == 'x') |
|||
psz += 2; |
|||
|
|||
// hex string to uint
|
|||
const char* pbegin = psz; |
|||
while (::HexDigit(*psz) != -1) |
|||
psz++; |
|||
psz--; |
|||
unsigned char* p1 = (unsigned char*)data; |
|||
unsigned char* pend = p1 + WIDTH; |
|||
while (psz >= pbegin && p1 < pend) { |
|||
*p1 = ::HexDigit(*psz--); |
|||
if (psz >= pbegin) { |
|||
*p1 |= ((unsigned char)::HexDigit(*psz--) << 4); |
|||
p1++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
template <unsigned int BITS> |
|||
void base_blob<BITS>::SetHex(const std::string& str) |
|||
{ |
|||
SetHex(str.c_str()); |
|||
} |
|||
|
|||
template <unsigned int BITS> |
|||
std::string base_blob<BITS>::ToString() const |
|||
{ |
|||
return (GetHex()); |
|||
} |
|||
|
|||
// Explicit instantiations for base_blob<160>
|
|||
template base_blob<160>::base_blob(const std::vector<unsigned char>&); |
|||
template std::string base_blob<160>::GetHex() const; |
|||
template std::string base_blob<160>::ToString() const; |
|||
template void base_blob<160>::SetHex(const char*); |
|||
template void base_blob<160>::SetHex(const std::string&); |
|||
|
|||
// Explicit instantiations for base_blob<256>
|
|||
template base_blob<256>::base_blob(const std::vector<unsigned char>&); |
|||
template std::string base_blob<256>::GetHex() const; |
|||
template std::string base_blob<256>::ToString() const; |
|||
template void base_blob<256>::SetHex(const char*); |
|||
template void base_blob<256>::SetHex(const std::string&); |
|||
|
|||
static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c) |
|||
{ |
|||
// Taken from lookup3, by Bob Jenkins.
|
|||
a -= c; |
|||
a ^= ((c << 4) | (c >> 28)); |
|||
c += b; |
|||
b -= a; |
|||
b ^= ((a << 6) | (a >> 26)); |
|||
a += c; |
|||
c -= b; |
|||
c ^= ((b << 8) | (b >> 24)); |
|||
b += a; |
|||
a -= c; |
|||
a ^= ((c << 16) | (c >> 16)); |
|||
c += b; |
|||
b -= a; |
|||
b ^= ((a << 19) | (a >> 13)); |
|||
a += c; |
|||
c -= b; |
|||
c ^= ((b << 4) | (b >> 28)); |
|||
b += a; |
|||
} |
|||
|
|||
static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c) |
|||
{ |
|||
// Taken from lookup3, by Bob Jenkins.
|
|||
c ^= b; |
|||
c -= ((b << 14) | (b >> 18)); |
|||
a ^= c; |
|||
a -= ((c << 11) | (c >> 21)); |
|||
b ^= a; |
|||
b -= ((a << 25) | (a >> 7)); |
|||
c ^= b; |
|||
c -= ((b << 16) | (b >> 16)); |
|||
a ^= c; |
|||
a -= ((c << 4) | (c >> 28)); |
|||
b ^= a; |
|||
b -= ((a << 14) | (a >> 18)); |
|||
c ^= b; |
|||
c -= ((b << 24) | (b >> 8)); |
|||
} |
|||
|
|||
uint64_t uint256::GetHash(const uint256& salt) const |
|||
{ |
|||
uint32_t a, b, c; |
|||
const uint32_t *pn = (const uint32_t*)data; |
|||
const uint32_t *salt_pn = (const uint32_t*)salt.data; |
|||
a = b = c = 0xdeadbeef + WIDTH; |
|||
|
|||
a += pn[0] ^ salt_pn[0]; |
|||
b += pn[1] ^ salt_pn[1]; |
|||
c += pn[2] ^ salt_pn[2]; |
|||
HashMix(a, b, c); |
|||
a += pn[3] ^ salt_pn[3]; |
|||
b += pn[4] ^ salt_pn[4]; |
|||
c += pn[5] ^ salt_pn[5]; |
|||
HashMix(a, b, c); |
|||
a += pn[6] ^ salt_pn[6]; |
|||
b += pn[7] ^ salt_pn[7]; |
|||
HashFinal(a, b, c); |
|||
|
|||
return ((((uint64_t)b) << 32) | c); |
|||
} |
@ -0,0 +1,158 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_UINT256_H |
|||
#define BITCOIN_UINT256_H |
|||
|
|||
#include <assert.h> |
|||
#include <cstring> |
|||
#include <stdexcept> |
|||
#include <stdint.h> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
/** Template base class for fixed-sized opaque blobs. */ |
|||
template<unsigned int BITS> |
|||
class base_blob |
|||
{ |
|||
protected: |
|||
enum { WIDTH=BITS/8 }; |
|||
alignas(uint32_t) uint8_t data[WIDTH]; |
|||
public: |
|||
base_blob() |
|||
{ |
|||
memset(data, 0, sizeof(data)); |
|||
} |
|||
|
|||
explicit base_blob(const std::vector<unsigned char>& vch); |
|||
|
|||
bool IsNull() const |
|||
{ |
|||
for (int i = 0; i < WIDTH; i++) |
|||
if (data[i] != 0) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
void SetNull() |
|||
{ |
|||
memset(data, 0, sizeof(data)); |
|||
} |
|||
|
|||
friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; } |
|||
friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; } |
|||
friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; } |
|||
|
|||
std::string GetHex() const; |
|||
void SetHex(const char* psz); |
|||
void SetHex(const std::string& str); |
|||
std::string ToString() const; |
|||
|
|||
unsigned char* begin() |
|||
{ |
|||
return &data[0]; |
|||
} |
|||
|
|||
unsigned char* end() |
|||
{ |
|||
return &data[WIDTH]; |
|||
} |
|||
|
|||
const unsigned char* begin() const |
|||
{ |
|||
return &data[0]; |
|||
} |
|||
|
|||
const unsigned char* end() const |
|||
{ |
|||
return &data[WIDTH]; |
|||
} |
|||
|
|||
unsigned int size() const |
|||
{ |
|||
return sizeof(data); |
|||
} |
|||
|
|||
unsigned int GetSerializeSize(int nType, int nVersion) const |
|||
{ |
|||
return sizeof(data); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Serialize(Stream& s, int nType, int nVersion) const |
|||
{ |
|||
s.write((char*)data, sizeof(data)); |
|||
} |
|||
|
|||
template<typename Stream> |
|||
void Unserialize(Stream& s, int nType, int nVersion) |
|||
{ |
|||
s.read((char*)data, sizeof(data)); |
|||
} |
|||
}; |
|||
|
|||
/** 160-bit opaque blob.
|
|||
* @note This type is called uint160 for historical reasons only. It is an opaque |
|||
* blob of 160 bits and has no integer operations. |
|||
*/ |
|||
class uint160 : public base_blob<160> { |
|||
public: |
|||
uint160() {} |
|||
uint160(const base_blob<160>& b) : base_blob<160>(b) {} |
|||
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {} |
|||
}; |
|||
|
|||
/** 256-bit opaque blob.
|
|||
* @note This type is called uint256 for historical reasons only. It is an |
|||
* opaque blob of 256 bits and has no integer operations. Use arith_uint256 if |
|||
* those are required. |
|||
*/ |
|||
class uint256 : public base_blob<256> { |
|||
public: |
|||
uint256() {} |
|||
uint256(const base_blob<256>& b) : base_blob<256>(b) {} |
|||
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {} |
|||
|
|||
/** A cheap hash function that just returns 64 bits from the result, it can be
|
|||
* used when the contents are considered uniformly random. It is not appropriate |
|||
* when the value can easily be influenced from outside as e.g. a network adversary could |
|||
* provide values to trigger worst-case behavior. |
|||
* @note The result of this function is not stable between little and big endian. |
|||
*/ |
|||
uint64_t GetCheapHash() const |
|||
{ |
|||
uint64_t result; |
|||
memcpy((void*)&result, (void*)data, 8); |
|||
return result; |
|||
} |
|||
|
|||
/** A more secure, salted hash function.
|
|||
* @note This hash is not stable between little and big endian. |
|||
*/ |
|||
uint64_t GetHash(const uint256& salt) const; |
|||
}; |
|||
|
|||
/* uint256 from const char *.
|
|||
* This is a separate function because the constructor uint256(const char*) can result |
|||
* in dangerously catching uint256(0). |
|||
*/ |
|||
inline uint256 uint256S(const char *str) |
|||
{ |
|||
uint256 rv; |
|||
rv.SetHex(str); |
|||
return rv; |
|||
} |
|||
/* uint256 from std::string.
|
|||
* This is a separate function because the constructor uint256(const std::string &str) can result |
|||
* in dangerously catching uint256(0) via std::string(const char*). |
|||
*/ |
|||
inline uint256 uint256S(const std::string& str) |
|||
{ |
|||
uint256 rv; |
|||
rv.SetHex(str); |
|||
return rv; |
|||
} |
|||
|
|||
#endif // BITCOIN_UINT256_H
|
@ -0,0 +1,81 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#if defined(HAVE_CONFIG_H) |
|||
#include "config/bitcoin-config.h" |
|||
#endif |
|||
|
|||
#include "util.h" |
|||
#include "random.h" |
|||
#include "serialize.h" |
|||
#include "utilstrencodings.h" |
|||
#include "utiltime.h" |
|||
|
|||
#include <stdarg.h> |
|||
|
|||
#ifndef WIN32 |
|||
// for posix_fallocate
|
|||
#ifdef __linux__ |
|||
|
|||
#ifdef _POSIX_C_SOURCE |
|||
#undef _POSIX_C_SOURCE |
|||
#endif |
|||
|
|||
#define _POSIX_C_SOURCE 200112L |
|||
|
|||
#endif // __linux__
|
|||
|
|||
#include <algorithm> |
|||
#include <fcntl.h> |
|||
#include <sys/resource.h> |
|||
#include <sys/stat.h> |
|||
|
|||
#else |
|||
|
|||
#ifdef _MSC_VER |
|||
#pragma warning(disable:4786) |
|||
#pragma warning(disable:4804) |
|||
#pragma warning(disable:4805) |
|||
#pragma warning(disable:4717) |
|||
#endif |
|||
|
|||
#ifdef _WIN32_WINNT |
|||
#undef _WIN32_WINNT |
|||
#endif |
|||
#define _WIN32_WINNT 0x0501 |
|||
|
|||
#ifdef _WIN32_IE |
|||
#undef _WIN32_IE |
|||
#endif |
|||
#define _WIN32_IE 0x0501 |
|||
|
|||
#define WIN32_LEAN_AND_MEAN 1 |
|||
#ifndef NOMINMAX |
|||
#define NOMINMAX |
|||
#endif |
|||
|
|||
#include <io.h> /* for _commit */ |
|||
#include <shlobj.h> |
|||
#endif |
|||
|
|||
|
|||
using namespace std; |
|||
|
|||
bool fDebug = false; |
|||
bool fLogTimestamps = true; |
|||
bool fLogTimeMicros = false; |
|||
|
|||
|
|||
|
|||
int LogPrintStr(const std::string &str) |
|||
{ |
|||
int ret = 0; // Returns total number of characters written
|
|||
static bool fStartedNewLine = true; |
|||
// print to console
|
|||
ret = fwrite(str.data(), 1, str.size(), stdout); |
|||
fflush(stdout); |
|||
return ret; |
|||
} |
|||
|
@ -0,0 +1,62 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
/**
|
|||
* Server/client environment: argument handling, config file parsing, |
|||
* logging, thread wrappers |
|||
*/ |
|||
#ifndef BITCOIN_UTIL_H |
|||
#define BITCOIN_UTIL_H |
|||
|
|||
|
|||
#if defined(HAVE_CONFIG_H) |
|||
#include "config/bitcoin-config.h" |
|||
#endif |
|||
#include "tinyformat.h" |
|||
#include <string> |
|||
|
|||
|
|||
|
|||
/** Send a string to the log output */ |
|||
int LogPrintStr(const std::string &str); |
|||
|
|||
#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) |
|||
|
|||
/**
|
|||
* When we switch to C++11, this can be switched to variadic templates instead |
|||
* of this macro-based construction (see tinyformat.h). |
|||
*/ |
|||
#define MAKE_ERROR_AND_LOG_FUNC(n) \ |
|||
/** Print to debug.log if -debug=category switch is given OR category is NULL. */ \ |
|||
template<TINYFORMAT_ARGTYPES(n)> \ |
|||
static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ |
|||
{ \ |
|||
return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ |
|||
} \ |
|||
/** Log error and return false */ \ |
|||
template<TINYFORMAT_ARGTYPES(n)> \ |
|||
static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ |
|||
{ \ |
|||
LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ |
|||
return false; \ |
|||
} |
|||
|
|||
TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) |
|||
|
|||
/**
|
|||
* Zero-arg versions of logging and error, these are not covered by |
|||
* TINYFORMAT_FOREACH_ARGNUM |
|||
*/ |
|||
static inline int LogPrint(const char* category, const char* format) |
|||
{ |
|||
return LogPrintStr(format); |
|||
} |
|||
static inline bool error(const char* format) |
|||
{ |
|||
return LogPrintStr(std::string("ERROR: ") + format + "\n"); |
|||
} |
|||
|
|||
|
|||
#endif // BITCOIN_UTIL_H
|
@ -0,0 +1,692 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "utilstrencodings.h" |
|||
|
|||
#include "tinyformat.h" |
|||
|
|||
#include <cstdlib> |
|||
#include <cstring> |
|||
#include <errno.h> |
|||
#include <iomanip> |
|||
#include <limits> |
|||
|
|||
using namespace std; |
|||
|
|||
string SanitizeString(const string& str) |
|||
{ |
|||
/**
|
|||
* safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything |
|||
* even possibly remotely dangerous like & or > |
|||
*/ |
|||
static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()"); |
|||
string strResult; |
|||
for (std::string::size_type i = 0; i < str.size(); i++) |
|||
{ |
|||
if (safeChars.find(str[i]) != std::string::npos) |
|||
strResult.push_back(str[i]); |
|||
} |
|||
return strResult; |
|||
} |
|||
|
|||
string SanitizeFilename(const string& str) |
|||
{ |
|||
/**
|
|||
* safeChars chosen to restrict filename, keeping it simple to avoid cross-platform issues. |
|||
* http://stackoverflow.com/a/2306003
|
|||
*/ |
|||
static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890"); |
|||
string strResult; |
|||
for (std::string::size_type i = 0; i < str.size(); i++) |
|||
{ |
|||
if (safeChars.find(str[i]) != std::string::npos) |
|||
strResult.push_back(str[i]); |
|||
} |
|||
return strResult; |
|||
} |
|||
|
|||
std::string HexInt(uint32_t val) |
|||
{ |
|||
std::stringstream ss; |
|||
ss << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex << val; |
|||
return ss.str(); |
|||
} |
|||
|
|||
uint32_t ParseHexToUInt32(const std::string& str) { |
|||
std::istringstream converter(str); |
|||
uint32_t value; |
|||
converter >> std::hex >> value; |
|||
return value; |
|||
} |
|||
|
|||
const signed char p_util_hexdigit[256] = |
|||
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, |
|||
-1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; |
|||
|
|||
signed char HexDigit(char c) |
|||
{ |
|||
return p_util_hexdigit[(unsigned char)c]; |
|||
} |
|||
|
|||
bool IsHex(const string& str) |
|||
{ |
|||
for(std::string::const_iterator it(str.begin()); it != str.end(); ++it) |
|||
{ |
|||
if (HexDigit(*it) < 0) |
|||
return false; |
|||
} |
|||
return (str.size() > 0) && (str.size()%2 == 0); |
|||
} |
|||
|
|||
vector<unsigned char> ParseHex(const char* psz) |
|||
{ |
|||
// convert hex dump to vector
|
|||
vector<unsigned char> vch; |
|||
while (true) |
|||
{ |
|||
while (isspace(*psz)) |
|||
psz++; |
|||
signed char c = HexDigit(*psz++); |
|||
if (c == (signed char)-1) |
|||
break; |
|||
unsigned char n = (c << 4); |
|||
c = HexDigit(*psz++); |
|||
if (c == (signed char)-1) |
|||
break; |
|||
n |= c; |
|||
vch.push_back(n); |
|||
} |
|||
return vch; |
|||
} |
|||
|
|||
vector<unsigned char> ParseHex(const string& str) |
|||
{ |
|||
return ParseHex(str.c_str()); |
|||
} |
|||
|
|||
string EncodeBase64(const unsigned char* pch, size_t len) |
|||
{ |
|||
static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|||
|
|||
string strRet=""; |
|||
strRet.reserve((len+2)/3*4); |
|||
|
|||
int mode=0, left=0; |
|||
const unsigned char *pchEnd = pch+len; |
|||
|
|||
while (pch<pchEnd) |
|||
{ |
|||
int enc = *(pch++); |
|||
switch (mode) |
|||
{ |
|||
case 0: // we have no bits
|
|||
strRet += pbase64[enc >> 2]; |
|||
left = (enc & 3) << 4; |
|||
mode = 1; |
|||
break; |
|||
|
|||
case 1: // we have two bits
|
|||
strRet += pbase64[left | (enc >> 4)]; |
|||
left = (enc & 15) << 2; |
|||
mode = 2; |
|||
break; |
|||
|
|||
case 2: // we have four bits
|
|||
strRet += pbase64[left | (enc >> 6)]; |
|||
strRet += pbase64[enc & 63]; |
|||
mode = 0; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (mode) |
|||
{ |
|||
strRet += pbase64[left]; |
|||
strRet += '='; |
|||
if (mode == 1) |
|||
strRet += '='; |
|||
} |
|||
|
|||
return strRet; |
|||
} |
|||
|
|||
string EncodeBase64(const string& str) |
|||
{ |
|||
return EncodeBase64((const unsigned char*)str.c_str(), str.size()); |
|||
} |
|||
|
|||
vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid) |
|||
{ |
|||
static const int decode64_table[256] = |
|||
{ |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, |
|||
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
|||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, |
|||
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, |
|||
49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 |
|||
}; |
|||
|
|||
if (pfInvalid) |
|||
*pfInvalid = false; |
|||
|
|||
vector<unsigned char> vchRet; |
|||
vchRet.reserve(strlen(p)*3/4); |
|||
|
|||
int mode = 0; |
|||
int left = 0; |
|||
|
|||
while (1) |
|||
{ |
|||
int dec = decode64_table[(unsigned char)*p]; |
|||
if (dec == -1) break; |
|||
p++; |
|||
switch (mode) |
|||
{ |
|||
case 0: // we have no bits and get 6
|
|||
left = dec; |
|||
mode = 1; |
|||
break; |
|||
|
|||
case 1: // we have 6 bits and keep 4
|
|||
vchRet.push_back((left<<2) | (dec>>4)); |
|||
left = dec & 15; |
|||
mode = 2; |
|||
break; |
|||
|
|||
case 2: // we have 4 bits and get 6, we keep 2
|
|||
vchRet.push_back((left<<4) | (dec>>2)); |
|||
left = dec & 3; |
|||
mode = 3; |
|||
break; |
|||
|
|||
case 3: // we have 2 bits and get 6
|
|||
vchRet.push_back((left<<6) | dec); |
|||
mode = 0; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (pfInvalid) |
|||
switch (mode) |
|||
{ |
|||
case 0: // 4n base64 characters processed: ok
|
|||
break; |
|||
|
|||
case 1: // 4n+1 base64 character processed: impossible
|
|||
*pfInvalid = true; |
|||
break; |
|||
|
|||
case 2: // 4n+2 base64 characters processed: require '=='
|
|||
if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1) |
|||
*pfInvalid = true; |
|||
break; |
|||
|
|||
case 3: // 4n+3 base64 characters processed: require '='
|
|||
if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1) |
|||
*pfInvalid = true; |
|||
break; |
|||
} |
|||
|
|||
return vchRet; |
|||
} |
|||
|
|||
string DecodeBase64(const string& str) |
|||
{ |
|||
vector<unsigned char> vchRet = DecodeBase64(str.c_str()); |
|||
return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size()); |
|||
} |
|||
|
|||
string EncodeBase32(const unsigned char* pch, size_t len) |
|||
{ |
|||
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567"; |
|||
|
|||
string strRet=""; |
|||
strRet.reserve((len+4)/5*8); |
|||
|
|||
int mode=0, left=0; |
|||
const unsigned char *pchEnd = pch+len; |
|||
|
|||
while (pch<pchEnd) |
|||
{ |
|||
int enc = *(pch++); |
|||
switch (mode) |
|||
{ |
|||
case 0: // we have no bits
|
|||
strRet += pbase32[enc >> 3]; |
|||
left = (enc & 7) << 2; |
|||
mode = 1; |
|||
break; |
|||
|
|||
case 1: // we have three bits
|
|||
strRet += pbase32[left | (enc >> 6)]; |
|||
strRet += pbase32[(enc >> 1) & 31]; |
|||
left = (enc & 1) << 4; |
|||
mode = 2; |
|||
break; |
|||
|
|||
case 2: // we have one bit
|
|||
strRet += pbase32[left | (enc >> 4)]; |
|||
left = (enc & 15) << 1; |
|||
mode = 3; |
|||
break; |
|||
|
|||
case 3: // we have four bits
|
|||
strRet += pbase32[left | (enc >> 7)]; |
|||
strRet += pbase32[(enc >> 2) & 31]; |
|||
left = (enc & 3) << 3; |
|||
mode = 4; |
|||
break; |
|||
|
|||
case 4: // we have two bits
|
|||
strRet += pbase32[left | (enc >> 5)]; |
|||
strRet += pbase32[enc & 31]; |
|||
mode = 0; |
|||
} |
|||
} |
|||
|
|||
static const int nPadding[5] = {0, 6, 4, 3, 1}; |
|||
if (mode) |
|||
{ |
|||
strRet += pbase32[left]; |
|||
for (int n=0; n<nPadding[mode]; n++) |
|||
strRet += '='; |
|||
} |
|||
|
|||
return strRet; |
|||
} |
|||
|
|||
string EncodeBase32(const string& str) |
|||
{ |
|||
return EncodeBase32((const unsigned char*)str.c_str(), str.size()); |
|||
} |
|||
|
|||
vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid) |
|||
{ |
|||
static const int decode32_table[256] = |
|||
{ |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
|||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2, |
|||
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, |
|||
23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 |
|||
}; |
|||
|
|||
if (pfInvalid) |
|||
*pfInvalid = false; |
|||
|
|||
vector<unsigned char> vchRet; |
|||
vchRet.reserve((strlen(p))*5/8); |
|||
|
|||
int mode = 0; |
|||
int left = 0; |
|||
|
|||
while (1) |
|||
{ |
|||
int dec = decode32_table[(unsigned char)*p]; |
|||
if (dec == -1) break; |
|||
p++; |
|||
switch (mode) |
|||
{ |
|||
case 0: // we have no bits and get 5
|
|||
left = dec; |
|||
mode = 1; |
|||
break; |
|||
|
|||
case 1: // we have 5 bits and keep 2
|
|||
vchRet.push_back((left<<3) | (dec>>2)); |
|||
left = dec & 3; |
|||
mode = 2; |
|||
break; |
|||
|
|||
case 2: // we have 2 bits and keep 7
|
|||
left = left << 5 | dec; |
|||
mode = 3; |
|||
break; |
|||
|
|||
case 3: // we have 7 bits and keep 4
|
|||
vchRet.push_back((left<<1) | (dec>>4)); |
|||
left = dec & 15; |
|||
mode = 4; |
|||
break; |
|||
|
|||
case 4: // we have 4 bits, and keep 1
|
|||
vchRet.push_back((left<<4) | (dec>>1)); |
|||
left = dec & 1; |
|||
mode = 5; |
|||
break; |
|||
|
|||
case 5: // we have 1 bit, and keep 6
|
|||
left = left << 5 | dec; |
|||
mode = 6; |
|||
break; |
|||
|
|||
case 6: // we have 6 bits, and keep 3
|
|||
vchRet.push_back((left<<2) | (dec>>3)); |
|||
left = dec & 7; |
|||
mode = 7; |
|||
break; |
|||
|
|||
case 7: // we have 3 bits, and keep 0
|
|||
vchRet.push_back((left<<5) | dec); |
|||
mode = 0; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (pfInvalid) |
|||
switch (mode) |
|||
{ |
|||
case 0: // 8n base32 characters processed: ok
|
|||
break; |
|||
|
|||
case 1: // 8n+1 base32 characters processed: impossible
|
|||
case 3: // +3
|
|||
case 6: // +6
|
|||
*pfInvalid = true; |
|||
break; |
|||
|
|||
case 2: // 8n+2 base32 characters processed: require '======'
|
|||
if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1) |
|||
*pfInvalid = true; |
|||
break; |
|||
|
|||
case 4: // 8n+4 base32 characters processed: require '===='
|
|||
if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1) |
|||
*pfInvalid = true; |
|||
break; |
|||
|
|||
case 5: // 8n+5 base32 characters processed: require '==='
|
|||
if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1) |
|||
*pfInvalid = true; |
|||
break; |
|||
|
|||
case 7: // 8n+7 base32 characters processed: require '='
|
|||
if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1) |
|||
*pfInvalid = true; |
|||
break; |
|||
} |
|||
|
|||
return vchRet; |
|||
} |
|||
|
|||
string DecodeBase32(const string& str) |
|||
{ |
|||
vector<unsigned char> vchRet = DecodeBase32(str.c_str()); |
|||
return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size()); |
|||
} |
|||
|
|||
static bool ParsePrechecks(const std::string& str) |
|||
{ |
|||
if (str.empty()) // No empty string allowed
|
|||
return false; |
|||
if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
|
|||
return false; |
|||
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
|
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
bool ParseInt32(const std::string& str, int32_t *out) |
|||
{ |
|||
if (!ParsePrechecks(str)) |
|||
return false; |
|||
char *endp = NULL; |
|||
errno = 0; // strtol will not set errno if valid
|
|||
long int n = strtol(str.c_str(), &endp, 10); |
|||
if(out) *out = (int32_t)n; |
|||
// Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
|
|||
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
|
|||
// platforms the size of these types may be different.
|
|||
return endp && *endp == 0 && !errno && |
|||
n >= std::numeric_limits<int32_t>::min() && |
|||
n <= std::numeric_limits<int32_t>::max(); |
|||
} |
|||
|
|||
bool ParseInt64(const std::string& str, int64_t *out) |
|||
{ |
|||
if (!ParsePrechecks(str)) |
|||
return false; |
|||
char *endp = NULL; |
|||
errno = 0; // strtoll will not set errno if valid
|
|||
long long int n = strtoll(str.c_str(), &endp, 10); |
|||
if(out) *out = (int64_t)n; |
|||
// Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
|
|||
// we still have to check that the returned value is within the range of an *int64_t*.
|
|||
return endp && *endp == 0 && !errno && |
|||
n >= std::numeric_limits<int64_t>::min() && |
|||
n <= std::numeric_limits<int64_t>::max(); |
|||
} |
|||
|
|||
bool ParseDouble(const std::string& str, double *out) |
|||
{ |
|||
if (!ParsePrechecks(str)) |
|||
return false; |
|||
if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
|
|||
return false; |
|||
std::istringstream text(str); |
|||
text.imbue(std::locale::classic()); |
|||
double result; |
|||
text >> result; |
|||
if(out) *out = result; |
|||
return text.eof() && !text.fail(); |
|||
} |
|||
|
|||
std::string FormatParagraph(const std::string& in, size_t width, size_t indent) |
|||
{ |
|||
std::stringstream out; |
|||
size_t col = 0; |
|||
size_t ptr = 0; |
|||
while(ptr < in.size()) |
|||
{ |
|||
// Find beginning of next word
|
|||
ptr = in.find_first_not_of(' ', ptr); |
|||
if (ptr == std::string::npos) |
|||
break; |
|||
// Find end of next word
|
|||
size_t endword = in.find_first_of(' ', ptr); |
|||
if (endword == std::string::npos) |
|||
endword = in.size(); |
|||
// Add newline and indentation if this wraps over the allowed width
|
|||
if (col > 0) |
|||
{ |
|||
if ((col + endword - ptr) > width) |
|||
{ |
|||
out << '\n'; |
|||
for(size_t i=0; i<indent; ++i) |
|||
out << ' '; |
|||
col = 0; |
|||
} else |
|||
out << ' '; |
|||
} |
|||
// Append word
|
|||
out << in.substr(ptr, endword - ptr); |
|||
col += endword - ptr + 1; |
|||
ptr = endword; |
|||
} |
|||
return out.str(); |
|||
} |
|||
|
|||
std::string i64tostr(int64_t n) |
|||
{ |
|||
return strprintf("%d", n); |
|||
} |
|||
|
|||
std::string itostr(int n) |
|||
{ |
|||
return strprintf("%d", n); |
|||
} |
|||
|
|||
int64_t atoi64(const char* psz) |
|||
{ |
|||
#ifdef _MSC_VER |
|||
return _atoi64(psz); |
|||
#else |
|||
return strtoll(psz, NULL, 10); |
|||
#endif |
|||
} |
|||
|
|||
int64_t atoi64(const std::string& str) |
|||
{ |
|||
#ifdef _MSC_VER |
|||
return _atoi64(str.c_str()); |
|||
#else |
|||
return strtoll(str.c_str(), NULL, 10); |
|||
#endif |
|||
} |
|||
|
|||
int atoi(const std::string& str) |
|||
{ |
|||
return atoi(str.c_str()); |
|||
} |
|||
|
|||
/** Upper bound for mantissa.
|
|||
* 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer. |
|||
* Larger integers cannot consist of arbitrary combinations of 0-9: |
|||
* |
|||
* 999999999999999999 1^18-1 |
|||
* 9223372036854775807 (1<<63)-1 (max int64_t) |
|||
* 9999999999999999999 1^19-1 (would overflow) |
|||
*/ |
|||
static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL; |
|||
|
|||
/** Helper function for ParseFixedPoint */ |
|||
static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros) |
|||
{ |
|||
if(ch == '0') |
|||
++mantissa_tzeros; |
|||
else { |
|||
for (int i=0; i<=mantissa_tzeros; ++i) { |
|||
if (mantissa > (UPPER_BOUND / 10LL)) |
|||
return false; /* overflow */ |
|||
mantissa *= 10; |
|||
} |
|||
mantissa += ch - '0'; |
|||
mantissa_tzeros = 0; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) |
|||
{ |
|||
int64_t mantissa = 0; |
|||
int64_t exponent = 0; |
|||
int mantissa_tzeros = 0; |
|||
bool mantissa_sign = false; |
|||
bool exponent_sign = false; |
|||
int ptr = 0; |
|||
int end = val.size(); |
|||
int point_ofs = 0; |
|||
|
|||
if (ptr < end && val[ptr] == '-') { |
|||
mantissa_sign = true; |
|||
++ptr; |
|||
} |
|||
if (ptr < end) |
|||
{ |
|||
if (val[ptr] == '0') { |
|||
/* pass single 0 */ |
|||
++ptr; |
|||
} else if (val[ptr] >= '1' && val[ptr] <= '9') { |
|||
while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { |
|||
if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) |
|||
return false; /* overflow */ |
|||
++ptr; |
|||
} |
|||
} else return false; /* missing expected digit */ |
|||
} else return false; /* empty string or loose '-' */ |
|||
if (ptr < end && val[ptr] == '.') |
|||
{ |
|||
++ptr; |
|||
if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') |
|||
{ |
|||
while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { |
|||
if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) |
|||
return false; /* overflow */ |
|||
++ptr; |
|||
++point_ofs; |
|||
} |
|||
} else return false; /* missing expected digit */ |
|||
} |
|||
if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E')) |
|||
{ |
|||
++ptr; |
|||
if (ptr < end && val[ptr] == '+') |
|||
++ptr; |
|||
else if (ptr < end && val[ptr] == '-') { |
|||
exponent_sign = true; |
|||
++ptr; |
|||
} |
|||
if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { |
|||
while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { |
|||
if (exponent > (UPPER_BOUND / 10LL)) |
|||
return false; /* overflow */ |
|||
exponent = exponent * 10 + val[ptr] - '0'; |
|||
++ptr; |
|||
} |
|||
} else return false; /* missing expected digit */ |
|||
} |
|||
if (ptr != end) |
|||
return false; /* trailing garbage */ |
|||
|
|||
/* finalize exponent */ |
|||
if (exponent_sign) |
|||
exponent = -exponent; |
|||
exponent = exponent - point_ofs + mantissa_tzeros; |
|||
|
|||
/* finalize mantissa */ |
|||
if (mantissa_sign) |
|||
mantissa = -mantissa; |
|||
|
|||
/* convert to one 64-bit fixed-point value */ |
|||
exponent += decimals; |
|||
if (exponent < 0) |
|||
return false; /* cannot represent values smaller than 10^-decimals */ |
|||
if (exponent >= 18) |
|||
return false; /* cannot represent values larger than or equal to 10^(18-decimals) */ |
|||
|
|||
for (int i=0; i < exponent; ++i) { |
|||
if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL)) |
|||
return false; /* overflow */ |
|||
mantissa *= 10; |
|||
} |
|||
if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND) |
|||
return false; /* overflow */ |
|||
|
|||
if (amount_out) |
|||
*amount_out = mantissa; |
|||
|
|||
return true; |
|||
} |
|||
|
@ -0,0 +1,122 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
/**
|
|||
* Utilities for converting data from/to strings. |
|||
*/ |
|||
#ifndef BITCOIN_UTILSTRENCODINGS_H |
|||
#define BITCOIN_UTILSTRENCODINGS_H |
|||
|
|||
#include <stdint.h> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#define BEGIN(a) ((char*)&(a)) |
|||
#define END(a) ((char*)&((&(a))[1])) |
|||
#define UBEGIN(a) ((unsigned char*)&(a)) |
|||
#define UEND(a) ((unsigned char*)&((&(a))[1])) |
|||
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) |
|||
|
|||
/** This is needed because the foreach macro can't get over the comma in pair<t1, t2> */ |
|||
#define PAIRTYPE(t1, t2) std::pair<t1, t2> |
|||
|
|||
std::string SanitizeFilename(const std::string& str); |
|||
std::string SanitizeString(const std::string& str); |
|||
std::string HexInt(uint32_t val); |
|||
uint32_t ParseHexToUInt32(const std::string& str); |
|||
std::vector<unsigned char> ParseHex(const char* psz); |
|||
std::vector<unsigned char> ParseHex(const std::string& str); |
|||
signed char HexDigit(char c); |
|||
bool IsHex(const std::string& str); |
|||
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL); |
|||
std::string DecodeBase64(const std::string& str); |
|||
std::string EncodeBase64(const unsigned char* pch, size_t len); |
|||
std::string EncodeBase64(const std::string& str); |
|||
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL); |
|||
std::string DecodeBase32(const std::string& str); |
|||
std::string EncodeBase32(const unsigned char* pch, size_t len); |
|||
std::string EncodeBase32(const std::string& str); |
|||
|
|||
std::string i64tostr(int64_t n); |
|||
std::string itostr(int n); |
|||
int64_t atoi64(const char* psz); |
|||
int64_t atoi64(const std::string& str); |
|||
int atoi(const std::string& str); |
|||
|
|||
/**
|
|||
* Convert string to signed 32-bit integer with strict parse error feedback. |
|||
* @returns true if the entire string could be parsed as valid integer, |
|||
* false if not the entire string could be parsed or when overflow or underflow occurred. |
|||
*/ |
|||
bool ParseInt32(const std::string& str, int32_t *out); |
|||
|
|||
/**
|
|||
* Convert string to signed 64-bit integer with strict parse error feedback. |
|||
* @returns true if the entire string could be parsed as valid integer, |
|||
* false if not the entire string could be parsed or when overflow or underflow occurred. |
|||
*/ |
|||
bool ParseInt64(const std::string& str, int64_t *out); |
|||
|
|||
/**
|
|||
* Convert string to double with strict parse error feedback. |
|||
* @returns true if the entire string could be parsed as valid double, |
|||
* false if not the entire string could be parsed or when overflow or underflow occurred. |
|||
*/ |
|||
bool ParseDouble(const std::string& str, double *out); |
|||
|
|||
template<typename T> |
|||
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) |
|||
{ |
|||
std::string rv; |
|||
static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', |
|||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; |
|||
rv.reserve((itend-itbegin)*3); |
|||
for(T it = itbegin; it < itend; ++it) |
|||
{ |
|||
unsigned char val = (unsigned char)(*it); |
|||
if(fSpaces && it != itbegin) |
|||
rv.push_back(' '); |
|||
rv.push_back(hexmap[val>>4]); |
|||
rv.push_back(hexmap[val&15]); |
|||
} |
|||
|
|||
return rv; |
|||
} |
|||
|
|||
template<typename T> |
|||
inline std::string HexStr(const T& vch, bool fSpaces=false) |
|||
{ |
|||
return HexStr(vch.begin(), vch.end(), fSpaces); |
|||
} |
|||
|
|||
/**
|
|||
* Format a paragraph of text to a fixed width, adding spaces for |
|||
* indentation to any added line. |
|||
*/ |
|||
std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0); |
|||
|
|||
/**
|
|||
* Timing-attack-resistant comparison. |
|||
* Takes time proportional to length |
|||
* of first argument. |
|||
*/ |
|||
template <typename T> |
|||
bool TimingResistantEqual(const T& a, const T& b) |
|||
{ |
|||
if (b.size() == 0) return a.size() == 0; |
|||
size_t accumulator = a.size() ^ b.size(); |
|||
for (size_t i = 0; i < a.size(); i++) |
|||
accumulator |= a[i] ^ b[i%b.size()]; |
|||
return accumulator == 0; |
|||
} |
|||
|
|||
/** Parse number as fixed point according to JSON number syntax.
|
|||
* See http://json.org/number.gif
|
|||
* @returns true on success, false on error. |
|||
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger. |
|||
*/ |
|||
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); |
|||
|
|||
#endif // BITCOIN_UTILSTRENCODINGS_H
|
@ -0,0 +1,57 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#if defined(HAVE_CONFIG_H) |
|||
#include "config/bitcoin-config.h" |
|||
#endif |
|||
|
|||
#include "utiltime.h" |
|||
|
|||
#include <chrono> |
|||
#include <boost/date_time/posix_time/posix_time.hpp> |
|||
#include <boost/thread.hpp> |
|||
|
|||
using namespace std; |
|||
|
|||
static int64_t nMockTime = 0; //! For unit testing
|
|||
|
|||
int64_t GetTime() |
|||
{ |
|||
if (nMockTime) return nMockTime; |
|||
|
|||
return time(NULL); |
|||
} |
|||
|
|||
void SetMockTime(int64_t nMockTimeIn) |
|||
{ |
|||
nMockTime = nMockTimeIn; |
|||
} |
|||
|
|||
int64_t GetTimeMillis() |
|||
{ |
|||
return std::chrono::duration_cast<std::chrono::milliseconds>( |
|||
std::chrono::system_clock::now().time_since_epoch()).count(); |
|||
} |
|||
|
|||
int64_t GetTimeMicros() |
|||
{ |
|||
return std::chrono::duration_cast<std::chrono::microseconds>( |
|||
std::chrono::system_clock::now().time_since_epoch()).count(); |
|||
} |
|||
|
|||
void MilliSleep(int64_t n) |
|||
{ |
|||
boost::this_thread::sleep_for(boost::chrono::milliseconds(n)); |
|||
} |
|||
|
|||
std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) |
|||
{ |
|||
// std::locale takes ownership of the pointer
|
|||
std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat)); |
|||
std::stringstream ss; |
|||
ss.imbue(loc); |
|||
ss << boost::posix_time::from_time_t(nTime); |
|||
return ss.str(); |
|||
} |
@ -0,0 +1,20 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef BITCOIN_UTILTIME_H |
|||
#define BITCOIN_UTILTIME_H |
|||
|
|||
#include <stdint.h> |
|||
#include <string> |
|||
|
|||
int64_t GetTime(); |
|||
int64_t GetTimeMillis(); |
|||
int64_t GetTimeMicros(); |
|||
void SetMockTime(int64_t nMockTimeIn); |
|||
void MilliSleep(int64_t n); |
|||
|
|||
std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime); |
|||
|
|||
#endif // BITCOIN_UTILTIME_H
|
Loading…
Reference in new issue