Merge pull request #3 from jl777/beta

Beta
This commit is contained in:
Alrighttt
2019-06-14 14:33:25 +02:00
committed by GitHub
117 changed files with 9387 additions and 2747 deletions

5
.gitignore vendored
View File

@@ -132,6 +132,7 @@ src/cc/rogue/rogue
src/cc/rogue/rogue.so
src/cc/rogue/test.zip
src/cc/dapps/a.out
src/checkfile
src/foo.zip
@@ -145,8 +146,6 @@ src/rogue.530623577502174316.pack
src/rogue.530623577502174316.player
src/cc/rogue/config.h
src/cc/rogue/config.h
src/ROGUE.conf
@@ -155,3 +154,5 @@ src/rogue.scr
src/cc/rogue/confdefs.h
src/cc/rogue/x64
src/cc/dapps/a.out

View File

@@ -40,6 +40,7 @@ build:ubuntu:
- mkdir ${PACKAGE_DIR_LINUX}
- cp src/komodod
src/komodo-cli
zcutil/fetch-params.sh
${PACKAGE_DIR_LINUX}
- chmod +x ${PACKAGE_DIR_LINUX}/komodod
- chmod +x ${PACKAGE_DIR_LINUX}/komodo-cli
@@ -71,10 +72,8 @@ build:windows:
- cp src/komodod.exe
src/komodo-cli.exe
src/komodo-tx.exe
src/cc/rogue/rogue.exe
zcutil/wget64.exe
zcutil/fetch-params.bat
src/cc/rogue/x86_64-w64-mingw32/bin/libcurl-4.dll
src/cc/rogue/x86_64-w64-mingw32/bin/libncursesw6.dll
${PACKAGE_DIR_WINDOWS}
- zip -r ${PACKAGE_DIR_WINDOWS}.zip ${PACKAGE_DIR_WINDOWS}
- md5sum ${AGAMA_ARTIFACTS_WINDOWS} > ${AGAMA_ARTIFACTS_WINDOWS_CHECKSUM}

62
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,62 @@
# Komodo Core (komodod) Software Contribution Guidelines
Thank you for reaching out and trying to make Komodo an even better software application and blockchain platform. These contribution guidelines shall help you figuring out where you can be helpful and how to easily get started.
## Table of Contents
0. [Types of contributions we're looking for](#types-of-contributions-were-looking-for)
0. [Ground rules & expectations](#ground-rules--expectations)
0. [How to contribute](#how-to-contribute)
0. [Style guide](#style-guide)
0. [Setting up your environment](#setting-up-your-environment)
0. [Contribution review process](#contribution-review-process)
0. [Community](#community)
## Types of contributions we're looking for
There are many ways you can directly contribute to Komodo:
* Debug and test the Komodo Core code
* Find and fix bugs
* Improve suboptimal code
* Extend our software
* Perform a secure code review of Komodo Core and other Komodo-related software
Interested in making a contribution? Read on!
## Ground rules & expectations
Before we get started, here are a few things we expect from you (and that you should expect from others):
* Be kind and thoughtful in your conversations around this project. We all come from different backgrounds and projects, which means we likely have different perspectives on "how open source is done." Try to listen to others rather than convince them that your way is correct.
* Open Source Guides are released with a [Contributor Code of Conduct](./code_of_conduct.md). By participating in this project, you agree to abide by its terms.
* If you open a pull request, please ensure that your contribution passes all tests. If there are test failures, you will need to address them before we can merge your contribution.
* When adding content, please consider if it is widely valuable. Please don't add references or links to things you or your employer have created as others will do so if they appreciate it.
## How to contribute
If you'd like to contribute, start by searching through the [issues](https://github.com/komodoplatform/komodo/issues) and [pull requests](https://github.com/komodoplatform/komodo/pulls) to see whether someone else has raised a similar idea or question.
If you don't see your idea listed, and you think it can contribute to Komodo, do one of the following:
* **If your contribution is minor,** such as a fixing a typo, open a pull request.
* **If your contribution is major,** such as a new feature or bugfix, start by opening an issue first. That way, other contributors can weigh in on the discussion before you do any work.
## Style guide
Write clear, clean and consistent code. Follow well-known and established style guidelines like [Google's C++ Style Guide](https://google.github.io/styleguide/cppguide.html) or [Bjarne Stroustrup's C++ Style FAQ](http://www.stroustrup.com/bs_faq2.html).
## Setting up your environment
The Komodo Core (komodod) is mainly written in C++ with specific modules written in C. Follow the [Getting Started](https://github.com/komodoplatform/komodo#getting-started) instructions to build komodod from sources. For more informations about the Komodo Platform and a full API documentation please visit the official [Komodo developer documentation](https://docs.komodoplatform.com/).
## Contribution review process
Our team and community will review your contribution and start a transparent testing and quality assurance process. As soon as your contribution has undergone sucessful review and QA signoff it gets merged into the Komodo sourcecode.
## Community
Discussions about Komodo's development take place on our [discord server](https://discord.gg/yhfzqsg). Anybody is welcome to join these conversations. There is also a [newsletter](http://komodoplatform.com) with regular updates.
Wherever possible, do not take these conversations to private channels, including contacting the maintainers directly. Keeping communication public means everybody can benefit and learn from the conversation.
This contribution guideline is adapted from the Open Source Guides.

View File

@@ -38,7 +38,7 @@ This is the official Komodo sourcecode repository based on https://github.com/jl
## Tech Specification
- Max Supply: 200 million KMD
- Block Time: 1m 2s
- Block Time: 60 seconds
- Block Reward: 3 KMD
- Mining Algorithm: Equihash
@@ -84,7 +84,7 @@ brew update
brew upgrade
brew tap discoteq/discoteq; brew install flock
brew install autoconf autogen automake
brew install gcc@6
brew update && brew install gcc@8
brew install binutils
brew install protobuf
brew install coreutils

30
SECURITY.md Normal file
View File

@@ -0,0 +1,30 @@
## Reporting a Vulnerability
Please use the below [contact data](https://komodoplatform.com/.well-known/security.txt.asc) to report vulnerabilities. We kindly ask you to not publish or exploit any found vulnerabilities.
```
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Contact: security@komodoplatform.com
Contact: ca333@komodoplatform.com
Contact: noashh@komodoplatform.com
Encryption: http://pgp.key-server.io:11371/0x379287998EE6CF47
-----BEGIN PGP SIGNATURE-----
iQJNBAEBCAA3FiEEVez5U2AlPa805zvqN5KHmY7mz0cFAlz6EuMZHGNhMzMzQGtv
bW9kb3BsYXRmb3JtLmNvbQAKCRA3koeZjubPR8cIEACP+JjyXDIzjgIewMMi/02b
tsYswPyQ+9bAoEJnis3r94d1FP1rqXmt4oNz6VwFTqQLEa5opW+gvvaxBTFJSPb0
UzbS+1PjfAOox5cnT3Dnv9kcy4ECslnW/G+mH+85BUgz1HuqYc8A3kNQJL7KqLoi
YeD0Hd09KtlG+B4PWdnqLw/uvfbavSKdMn6WSIU6adNZWX0ewSubWPXvrWea5cI2
yKDdMcDqB8Sc9J4JR2L9zW8NqPQuaxfLQbkCt2tg9QjlClrAqQgb8OZQJgY9f1T/
kBlVXoA4ZUZeifvjSKxQ/3TdRFP+jbV9xsb6sr14zTx+Wcoqtgsh3l9F4+T3V2m8
/c/iS4mFlK31pJtwYyrJAq9hpggqymdCVi0Pa3yLZsEj3orBPaPWbmq2v7xeF3J8
y8vqAkt3M3T6251aZAKEcaN5RXYJW70CTseadwp0tmrAL2nIVmziNCMOF+Bufyxi
HddkasTcNX8VYfPCLWqBwrocx8d3n3E7dBGeS2x2iwuRVQ85pH5d+imxaMftcbqm
YrNuiqcI/0XDGk9pS6f1gpu5Eh5Q2QXGmOoRlfosfkAEfgFxfaMvmcu5Ay1s0gSR
MsTn0PrQyMYC3t3KpyP47C8ui9x7FtJFltR/QT4yzBF1QyDmINnK86ldQqSui402
2+gQFt7YFvLIBUiy1fh1Jw==
=UITq
-----END PGP SIGNATURE-----
```

View File

@@ -1,5 +1,5 @@
build_darwin_CC = gcc-6
build_darwin_CXX = g++-6
build_darwin_CC = gcc-8
build_darwin_CXX = g++-8
build_darwin_AR: = $(shell xcrun -f ar)
build_darwin_RANLIB: = $(shell xcrun -f ranlib)
build_darwin_STRIP: = $(shell xcrun -f strip)
@@ -10,8 +10,8 @@ build_darwin_SHA256SUM = shasum -a 256
build_darwin_DOWNLOAD = curl --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -L -f -o
#darwin host on darwin builder. overrides darwin host preferences.
darwin_CC= gcc-6
darwin_CXX= g++-6
darwin_CC= gcc-8
darwin_CXX= g++-8
darwin_AR:=$(shell xcrun -f ar)
darwin_RANLIB:=$(shell xcrun -f ranlib)
darwin_STRIP:=$(shell xcrun -f strip)

View File

@@ -1,9 +1,9 @@
OSX_MIN_VERSION=10.8
OSX_SDK_VERSION=10.11
OSX_MIN_VERSION=10.12
OSX_SDK_VERSION=10.12
OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk
LD64_VERSION=253.9
darwin_CC=gcc-6 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
darwin_CXX=g++-6 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
darwin_CC=gcc-8 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
darwin_CXX=g++-8 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
darwin_CFLAGS=-pipe
darwin_CXXFLAGS=$(darwin_CFLAGS)

View File

@@ -1,9 +1,10 @@
package=libcurl
$(package)_version=7.54.0
$(package)_version=7.64.1
$(package)_dependencies=openssl
$(package)_download_path=https://curl.haxx.se/download
$(package)_file_name=curl-$($(package)_version).tar.gz
$(package)_sha256_hash=a84b635941c74e26cce69dd817489bec687eb1f230e7d1897fc5b5f108b59adf
$(package)_config_opts_linux=--disable-shared --enable-static --prefix=$(host_prefix)
$(package)_sha256_hash=432d3f466644b9416bc5b649d344116a753aeaa520c8beaf024a90cba9d3d35d
$(package)_config_opts_linux=--disable-shared --enable-static --prefix=$(host_prefix) --host=x86_64-unknown-linux-gnu
$(package)_config_opts_mingw32=--enable-mingw --disable-shared --enable-static --prefix=$(host_prefix) --host=x86_64-w64-mingw32
$(package)_config_opts_darwin=--disable-shared --enable-static --prefix=$(host_prefix)
$(package)_cflags_darwin=-mmacosx-version-min=10.9
@@ -15,14 +16,23 @@ define $(package)_set_vars
endef
endif
define $(package)_config_cmds
$($(package)_conf_tool) $($(package)_config_opts)
ifeq ($(build_os),linux)
define $(package)_set_vars
$(package)_config_env=LD_LIBRARY_PATH="$(host_prefix)/lib" PKG_CONFIG_LIBDIR="$(host_prefix)/lib/pkgconfig" CPPFLAGS="-I$(host_prefix)/include" LDFLAGS="-L$(host_prefix)/lib"
endef
endif
define $(package)_config_cmds
echo '=== config for $(package):' && \
echo '$($(package)_config_env) $($(package)_conf_tool) $($(package)_config_opts)' && \
echo '=== ' && \
$($(package)_config_env) $($(package)_conf_tool) $($(package)_config_opts)
endef
ifeq ($(build_os),darwin)
define $(package)_build_cmds
$(MAKE) CPPFLAGS='-fPIC' CFLAGS='-mmacosx-version-min=10.9'
$(MAKE) CPPFLAGS="-I$(host_prefix)/include -fPIC" CFLAGS='-mmacosx-version-min=10.9'
endef
else
define $(package)_build_cmds
@@ -31,5 +41,6 @@ endef
endif
define $(package)_stage_cmds
echo 'Staging dir: $($(package)_staging_dir)$(host_prefix)/' && \
$(MAKE) DESTDIR=$($(package)_staging_dir) install
endef

View File

@@ -3,6 +3,7 @@ $(package)_version=1.1.1a
$(package)_download_path=https://www.openssl.org/source
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=fc20130f8b7cbd2fb918b2f14e2f429e109c31ddd0fb38fc5d71d9ffed3f9f41
$(package)_patches=ssl_fix.patch
define $(package)_set_vars
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
@@ -22,7 +23,6 @@ $(package)_config_opts+=no-comp
$(package)_config_opts+=no-crypto-mdebug
$(package)_config_opts+=no-crypto-mdebug-backtrace
$(package)_config_opts+=no-ct
$(package)_config_opts+=no-des
$(package)_config_opts+=no-dgram
$(package)_config_opts+=no-dsa
$(package)_config_opts+=no-dso
@@ -58,15 +58,12 @@ $(package)_config_opts+=no-scrypt
$(package)_config_opts+=no-sctp
$(package)_config_opts+=no-seed
$(package)_config_opts+=no-shared
$(package)_config_opts+=no-sock
$(package)_config_opts+=no-srp
$(package)_config_opts+=no-srtp
$(package)_config_opts+=no-ssl
$(package)_config_opts+=no-ssl3
$(package)_config_opts+=no-ssl3-method
$(package)_config_opts+=no-ssl-trace
$(package)_config_opts+=no-stdio
$(package)_config_opts+=no-tls
$(package)_config_opts+=no-tls1
$(package)_config_opts+=no-tls1-method
$(package)_config_opts+=no-ts
@@ -93,7 +90,8 @@ endef
define $(package)_preprocess_cmds
sed -i.old 's/built on: $date/built on: not available/' util/mkbuildinf.pl && \
sed -i.old "s|\"engines\", \"apps\", \"test\"|\"engines\"|" Configure
sed -i.old "s|\"engines\", \"apps\", \"test\"|\"engines\"|" Configure && \
patch -p1 < $($(package)_patch_dir)/ssl_fix.patch
endef
define $(package)_config_cmds

View File

@@ -47,7 +47,7 @@ native_packages := native_ccache
wallet_packages=bdb
ifeq ($(host_os),linux)
packages := boost openssl libevent zeromq $(zcash_packages) googletest #googlemock
packages := boost openssl libevent zeromq $(zcash_packages) googletest libcurl #googlemock
else
packages := boost openssl libevent zeromq $(zcash_packages) libcurl googletest #googlemock
endif

View File

@@ -0,0 +1,273 @@
From f725fe5b4b6504df08e30f5194d321c3025e2336 Mon Sep 17 00:00:00 2001
From: Matt Caswell <matt@openssl.org>
Date: Tue, 20 Nov 2018 15:32:55 +0000
Subject: [PATCH] Fix a RUN_ONCE bug
We have a number of instances where there are multiple "init" functions for
a single CRYPTO_ONCE variable, e.g. to load config automatically or to not
load config automatically. Unfortunately the RUN_ONCE mechanism was not
correctly giving the right return value where an alternative init function
was being used.
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7983)
---
crypto/init.c | 38 +++++++++-----
include/internal/thread_once.h | 92 ++++++++++++++++++++++++++++++++++
ssl/ssl_init.c | 6 ++-
3 files changed, 121 insertions(+), 15 deletions(-)
diff --git a/crypto/init.c b/crypto/init.c
index 209d1a483da..f20a12f069a 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -177,12 +177,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT;
static int load_crypto_strings_inited = 0;
-DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_crypto_strings)
-{
- /* Do nothing in this case */
- return 1;
-}
-
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)
{
int ret = 1;
@@ -201,6 +195,13 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)
return ret;
}
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings,
+ ossl_init_load_crypto_strings)
+{
+ /* Do nothing in this case */
+ return 1;
+}
+
static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)
{
@@ -218,6 +219,13 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)
return 1;
}
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers,
+ ossl_init_add_all_ciphers)
+{
+ /* Do nothing */
+ return 1;
+}
+
static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
{
@@ -235,7 +243,8 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
return 1;
}
-DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs)
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests,
+ ossl_init_add_all_digests)
{
/* Do nothing */
return 1;
@@ -255,7 +264,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_config)
config_inited = 1;
return 1;
}
-DEFINE_RUN_ONCE_STATIC(ossl_init_no_config)
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config)
{
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr,
@@ -595,8 +604,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
- && !RUN_ONCE(&load_crypto_strings,
- ossl_init_no_load_crypto_strings))
+ && !RUN_ONCE_ALT(&load_crypto_strings,
+ ossl_init_no_load_crypto_strings,
+ ossl_init_load_crypto_strings))
return 0;
if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
@@ -604,7 +614,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
return 0;
if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
- && !RUN_ONCE(&add_all_ciphers, ossl_init_no_add_algs))
+ && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers,
+ ossl_init_add_all_ciphers))
return 0;
if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
@@ -612,7 +623,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
return 0;
if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
- && !RUN_ONCE(&add_all_digests, ossl_init_no_add_algs))
+ && !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests,
+ ossl_init_add_all_digests))
return 0;
if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
@@ -624,7 +636,7 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG)
- && !RUN_ONCE(&config, ossl_init_no_config))
+ && !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config))
return 0;
if (opts & OPENSSL_INIT_LOAD_CONFIG) {
diff --git a/include/internal/thread_once.h b/include/internal/thread_once.h
index 224244353ab..e268a959ef3 100644
--- a/include/internal/thread_once.h
+++ b/include/internal/thread_once.h
@@ -9,6 +9,20 @@
#include <openssl/crypto.h>
+/*
+ * DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly
+ * once. It takes no arguments and returns and int result (1 for success or
+ * 0 for failure). Typical usage might be:
+ *
+ * DEFINE_RUN_ONCE(myinitfunc)
+ * {
+ * do_some_initialisation();
+ * if (init_is_successful())
+ * return 1;
+ *
+ * return 0;
+ * }
+ */
#define DEFINE_RUN_ONCE(init) \
static int init(void); \
int init##_ossl_ret_ = 0; \
@@ -17,10 +31,30 @@
init##_ossl_ret_ = init(); \
} \
static int init(void)
+
+/*
+ * DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly
+ * once that has been defined in another file via DEFINE_RUN_ONCE().
+ */
#define DECLARE_RUN_ONCE(init) \
extern int init##_ossl_ret_; \
void init##_ossl_(void);
+/*
+ * DEFINE_RUN_ONCE_STATIC: Define an initialiser function that should be run
+ * exactly once. This function will be declared as static within the file. It
+ * takes no arguments and returns and int result (1 for success or 0 for
+ * failure). Typical usage might be:
+ *
+ * DEFINE_RUN_ONCE_STATIC(myinitfunc)
+ * {
+ * do_some_initialisation();
+ * if (init_is_successful())
+ * return 1;
+ *
+ * return 0;
+ * }
+ */
#define DEFINE_RUN_ONCE_STATIC(init) \
static int init(void); \
static int init##_ossl_ret_ = 0; \
@@ -30,6 +64,46 @@
} \
static int init(void)
+/*
+ * DEFINE_RUN_ONCE_STATIC_ALT: Define an alternative initialiser function. This
+ * function will be declared as static within the file. It takes no arguments
+ * and returns an int result (1 for success or 0 for failure). An alternative
+ * initialiser function is expected to be associated with a primary initialiser
+ * function defined via DEFINE_ONCE_STATIC where both functions use the same
+ * CRYPTO_ONCE object to synchronise. Where an alternative initialiser function
+ * is used only one of the primary or the alternative initialiser function will
+ * ever be called - and that function will be called exactly once. Definitition
+ * of an alternative initialiser function MUST occur AFTER the definition of the
+ * primary initialiser function.
+ *
+ * Typical usage might be:
+ *
+ * DEFINE_RUN_ONCE_STATIC(myinitfunc)
+ * {
+ * do_some_initialisation();
+ * if (init_is_successful())
+ * return 1;
+ *
+ * return 0;
+ * }
+ *
+ * DEFINE_RUN_ONCE_STATIC_ALT(myaltinitfunc, myinitfunc)
+ * {
+ * do_some_alternative_initialisation();
+ * if (init_is_successful())
+ * return 1;
+ *
+ * return 0;
+ * }
+ */
+#define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \
+ static int initalt(void); \
+ static void initalt##_ossl_(void) \
+ { \
+ init##_ossl_ret_ = initalt(); \
+ } \
+ static int initalt(void)
+
/*
* RUN_ONCE - use CRYPTO_THREAD_run_once, and check if the init succeeded
* @once: pointer to static object of type CRYPTO_ONCE
@@ -43,3 +117,21 @@
*/
#define RUN_ONCE(once, init) \
(CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0)
+
+/*
+ * RUN_ONCE_ALT - use CRYPTO_THREAD_run_once, to run an alternative initialiser
+ * function and check if that initialisation succeeded
+ * @once: pointer to static object of type CRYPTO_ONCE
+ * @initalt: alternative initialiser function name that was previously given to
+ * DEFINE_RUN_ONCE_STATIC_ALT. This function must return 1 for
+ * success or 0 for failure.
+ * @init: primary initialiser function name that was previously given to
+ * DEFINE_RUN_ONCE_STATIC. This function must return 1 for success or
+ * 0 for failure.
+ *
+ * The return value is 1 on success (*) or 0 in case of error.
+ *
+ * (*) by convention, since the init function must return 1 on success.
+ */
+#define RUN_ONCE_ALT(once, initalt, init) \
+ (CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0)
diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c
index c0ccb9304a6..96526472c57 100644
--- a/ssl/ssl_init.c
+++ b/ssl/ssl_init.c
@@ -134,7 +134,8 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
return 1;
}
-DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_ssl_strings)
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings,
+ ossl_init_load_ssl_strings)
{
/* Do nothing in this case */
return 1;
@@ -207,7 +208,8 @@ int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS)
- && !RUN_ONCE(&ssl_strings, ossl_init_no_load_ssl_strings))
+ && !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings,
+ ossl_init_load_ssl_strings))
return 0;
if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS)

View File

@@ -65,6 +65,7 @@ testScripts=(
'disablewallet.py'
'zcjoinsplit.py'
'zcjoinsplitdoublespend.py'
'ivk_import_export.py'
'zkey_import_export.py'
'reorg_limit.py'
'getblocktemplate.py'

View File

@@ -3,7 +3,6 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import CryptoconditionsTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
@@ -11,13 +10,11 @@ from test_framework.util import assert_equal, assert_greater_than, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsOraclesTest(CryptoconditionsTestFramework):
def run_oracles_tests(self):
rpc = self.nodes[0]
rpc1 = self.nodes[1]
result = rpc1.oraclesaddress()
result = rpc.oraclesaddress()
@@ -54,159 +51,197 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework):
too_long_description = generate_random_string(4100)
result = rpc.oraclescreate("Test", too_long_description, "s")
assert_error(result)
# need uxtos to create oracle? Crashes if without generate
rpc.generate(2)
# valid creating oracles of different types
# using such naming to re-use it for data publishing / reading (e.g. oracle_s for s type)
valid_formats = ["s", "S", "d", "D", "c", "C", "t", "T", "i", "I", "l", "L", "h", "Ihh"]
for f in valid_formats:
result = rpc.oraclescreate("Test", "Test", f)
result = rpc.oraclescreate("Test_"+f, "Test_"+f, f)
assert_success(result)
globals()["oracle_{}".format(f)] = self.send_and_mine(result['hex'], rpc)
# trying to register with negative datafee
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100")
assert_error(result)
# trying to register with zero datafee
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "0")
assert_error(result)
# trying to register with datafee less than txfee
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "500")
assert_error(result)
# trying to register valid
for f in valid_formats:
# trying to register valid (unfunded)
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "10000")
assert_error(result)
# Fund the oracles
result = rpc.oraclesfund(globals()["oracle_{}".format(f)])
assert_success(result)
fund_txid = self.send_and_mine(result["hex"], rpc)
assert fund_txid, "got txid"
# trying to register valid (funded)
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "10000")
print(f)
assert_success(result)
register_txid = self.send_and_mine(result["hex"], rpc)
assert register_txid, "got txid"
# TODO: for most of the non valid oraclesregister and oraclessubscribe transactions generating and broadcasting now
# so trying only valid oraclessubscribe atm
for f in valid_formats:
result = rpc.oraclessubscribe(globals()["oracle_{}".format(f)], self.pubkey, "1")
assert_success(result)
subscribe_txid = self.send_and_mine(result["hex"], rpc)
assert register_txid, "got txid"
rpc.generate(1)
# now lets publish and read valid data for each oracle type
# s type
result = rpc.oraclesdata(globals()["oracle_{}".format("s")], "05416e746f6e")
assert_success(result)
# baton
oraclesdata_s = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("s")], oraclesdata_s, "1")
assert_equal("[u'Anton']", str(result["samples"][0]), "Data match")
oraclesdata_s = self.send_and_mine(result["hex"], rpc)
info = rpc.oraclesinfo(globals()["oracle_{}".format("s")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("s")], batonaddr, "1")
assert_equal("[u'Anton']", str(result["samples"][0]['data']), "Data match")
# S type
result = rpc.oraclesdata(globals()["oracle_{}".format("S")], "000161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161")
assert_success(result)
# baton
oraclesdata_S = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("S")], oraclesdata_S, "1")
assert_equal("[u'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("S")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("S")], batonaddr, "1")
assert_equal("[u'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']", str(result["samples"][0]['data']), "Data match")
# d type
result = rpc.oraclesdata(globals()["oracle_{}".format("d")], "0101")
assert_success(result)
# baton
oraclesdata_d = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("d")], oraclesdata_d, "1")
assert_equal("[u'01']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("d")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("d")], batonaddr, "1")
assert_equal("[u'01']", str(result["samples"][0]['data']), "Data match")
# D type
result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "010001")
assert_success(result)
# baton
oraclesdata_D = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("D")], oraclesdata_D, "1")
assert_equal("[u'01']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("D")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("D")], batonaddr, "1")
assert_equal("[u'01']", str(result["samples"][0]['data']), "Data match")
# c type
result = rpc.oraclesdata(globals()["oracle_{}".format("c")], "ff")
assert_success(result)
# baton
oraclesdata_c = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("c")], oraclesdata_c, "1")
assert_equal("[u'-1']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("c")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("c")], batonaddr, "1")
assert_equal("[u'-1']", str(result["samples"][0]['data']), "Data match")
# C type
result = rpc.oraclesdata(globals()["oracle_{}".format("C")], "ff")
assert_success(result)
# baton
oraclesdata_C = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("C")], oraclesdata_C, "1")
assert_equal("[u'255']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("C")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("C")], batonaddr, "1")
assert_equal("[u'255']", str(result["samples"][0]['data']), "Data match")
# t type
result = rpc.oraclesdata(globals()["oracle_{}".format("t")], "ffff")
assert_success(result)
# baton
oraclesdata_t = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("t")], oraclesdata_t, "1")
assert_equal("[u'-1']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("t")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("t")], batonaddr, "1")
assert_equal("[u'-1']", str(result["samples"][0]['data']), "Data match")
# T type
result = rpc.oraclesdata(globals()["oracle_{}".format("T")], "ffff")
assert_success(result)
# baton
oraclesdata_T = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("T")], oraclesdata_T, "1")
assert_equal("[u'65535']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("T")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("T")], batonaddr, "1")
assert_equal("[u'65535']", str(result["samples"][0]['data']), "Data match")
# i type
result = rpc.oraclesdata(globals()["oracle_{}".format("i")], "ffffffff")
assert_success(result)
# baton
oraclesdata_i = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("i")], oraclesdata_i, "1")
assert_equal("[u'-1']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("i")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("i")], batonaddr, "1")
assert_equal("[u'-1']", str(result["samples"][0]['data']), "Data match")
# I type
result = rpc.oraclesdata(globals()["oracle_{}".format("I")], "ffffffff")
assert_success(result)
# baton
oraclesdata_I = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("I")], oraclesdata_I, "1")
assert_equal("[u'4294967295']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("I")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("I")], batonaddr, "1")
assert_equal("[u'4294967295']", str(result["samples"][0]['data']), "Data match")
# l type
result = rpc.oraclesdata(globals()["oracle_{}".format("l")], "00000000ffffffff")
assert_success(result)
# baton
oraclesdata_l = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("l")], oraclesdata_l, "1")
# TODO: working not correct now!
#assert_equal("[u'-4294967296']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("l")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("l")], batonaddr, "1")
assert_equal("[u'-4294967296']", str(result["samples"][0]['data']), "Data match")
# L type
result = rpc.oraclesdata(globals()["oracle_{}".format("L")], "00000000ffffffff")
assert_success(result)
# baton
oraclesdata_L = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("L")], oraclesdata_L, "1")
assert_equal("[u'18446744069414584320']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("L")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("L")], batonaddr, "1")
assert_equal("[u'18446744069414584320']", str(result["samples"][0]['data']), "Data match")
# h type
result = rpc.oraclesdata(globals()["oracle_{}".format("h")], "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff")
assert_success(result)
# baton
oraclesdata_h = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("h")], oraclesdata_h, "1")
assert_equal("[u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("h")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("h")], batonaddr, "1")
assert_equal("[u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]['data']), "Data match")
# Ihh type
result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff")
assert_success(result)
# baton
oraclesdata_Ihh = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("Ihh")], oraclesdata_Ihh, "1")
assert_equal("[u'4294967295', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match")
info = rpc.oraclesinfo(globals()["oracle_{}".format("Ihh")])
batonaddr = info['registered'][0]['baton']
result = rpc.oraclessamples(globals()["oracle_{}".format("Ihh")], batonaddr, "1")
print(result)
assert_equal("[u'4294967295', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]['data']), "Data match")
def run_test(self):
print("Mining blocks...")

137
qa/rpc-tests/ivk_import_export.py Executable file
View File

@@ -0,0 +1,137 @@
#!/usr/bin/env python2
# Copyright (c) 2019 Bartlomiej Lisiecki
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_greater_than, start_nodes,\
initialize_chain_clean, connect_nodes_bi, wait_and_assert_operationid_status
import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
fee = Decimal('0.0001') # constant (but can be changed within reason)
class IVKImportExportTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 4)
def setup_network(self, split=False):
self.nodes = start_nodes(4, self.options.tmpdir, [[
'-nuparams=5ba81b19:101', # Overwinter
'-nuparams=76b809bb:102', # Sapling
]] * 4)
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,0,2)
connect_nodes_bi(self.nodes,0,3)
self.is_network_split=False
self.sync_all()
def run_test(self):
[alice, bob, charlie, miner] = self.nodes
# the sender loses 'amount' plus fee; to_addr receives exactly 'amount'
def z_send(from_node, from_addr, to_addr, amount):
global fee
opid = from_node.z_sendmany(from_addr,
[{"address": to_addr, "amount": Decimal(amount)}], 1, fee)
wait_and_assert_operationid_status(from_node, opid)
self.sync_all()
miner.generate(1)
self.sync_all()
def verify_utxos(node, amts, zaddr):
amts.sort(reverse=True)
txs = node.z_listreceivedbyaddress(zaddr)
def cmp_confirmations_high_to_low(a, b):
return cmp(b["amount"], a["amount"])
txs.sort(cmp_confirmations_high_to_low)
print("Sorted txs", txs)
print("amts", amts)
try:
assert_equal(amts, [tx["amount"] for tx in txs])
except AssertionError:
logging.error(
'Expected amounts: %r; txs: %r',
amts, txs)
raise
def get_private_balance(node):
balance = node.z_gettotalbalance()
return balance['private']
def find_imported_zaddr(node, import_zaddr):
zaddrs = node.z_listaddresses()
assert(import_zaddr in zaddrs)
return import_zaddr
# activate sapling
alice.generate(102)
self.sync_all()
# sanity-check the test harness
assert_equal(self.nodes[0].getblockcount(), 102)
# shield alice's coinbase funds to her zaddr
alice_zaddr = alice.z_getnewaddress('sapling')
res = alice.z_shieldcoinbase("*", alice_zaddr)
wait_and_assert_operationid_status(alice, res['opid'])
self.sync_all()
miner.generate(1)
self.sync_all()
# the amounts of each txn embodied which generates a single utxo:
amounts = map(Decimal, ['2.3', '3.7', '0.1', '0.5', '1.0', '0.19'])
# internal test consistency assertion:
assert_greater_than(
get_private_balance(alice),
reduce(Decimal.__add__, amounts))
# now get a pristine z-address for receiving transfers:
bob_zaddr = bob.z_getnewaddress('sapling')
verify_utxos(bob, [], bob_zaddr)
logging.info("sending pre-export txns...")
for amount in amounts[0:2]:
z_send(alice, alice_zaddr, bob_zaddr, amount)
logging.info("exporting ivk from bob...")
bob_ivk = bob.z_exportviewingkey(bob_zaddr)
logging.info("sending post-export txns...")
for amount in amounts[2:4]:
z_send(alice, alice_zaddr, bob_zaddr, amount)
verify_utxos(bob, amounts[:4], bob_zaddr)
logging.info("importing bob_ivk into charlie...")
# we need to pass bob_zaddr since it's a sapling address
charlie.z_importviewingkey(bob_ivk, 'yes', 0, bob_zaddr)
# z_importkey should have rescanned for new key, so this should pass:
verify_utxos(charlie, amounts[:4], bob_zaddr)
# verify idempotent behavior:
charlie.z_importviewingkey(bob_ivk, 'yes', 0, bob_zaddr)
verify_utxos(charlie, amounts[:4], bob_zaddr)
logging.info("Sending post-import txns...")
for amount in amounts[4:]:
z_send(alice, alice_zaddr, bob_zaddr, amount)
verify_utxos(bob, amounts, bob_zaddr)
verify_utxos(charlie, amounts, bob_zaddr)
if __name__ == '__main__':
IVKImportExportTest().main()

View File

@@ -491,7 +491,7 @@ libbitcoin_common_a_SOURCES = \
script/sign.cpp \
script/standard.cpp \
transaction_builder.cpp \
cc/CCtokensOpRet.cpp \
cc/CCtokenutils.cpp \
cc/CCutilbits.cpp \
$(BITCOIN_CORE_H) \
$(LIBZCASH_H)
@@ -524,6 +524,11 @@ if GLIBC_BACK_COMPAT
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
endif
if ENABLE_TESTS
libbitcoin_server_a_SOURCES += rpc/testtransactions.cpp
endif
# cli: zcash-cli
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -594,11 +599,19 @@ if ENABLE_PROTON
komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS)
endif
# [+] Decker: use static linking for libstdc++.6.dylib, libgomp.1.dylib, libgcc_s.1.dylib
if TARGET_DARWIN
komodod_LDFLAGS += -static-libgcc
endif
# bitcoin-cli binary #
komodo_cli_SOURCES = bitcoin-cli.cpp
komodo_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS)
komodo_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
komodo_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_DARWIN
komodo_cli_LDFLAGS += -static-libgcc
endif
# wallet-utility binary #
if ENABLE_WALLET

2
src/ac/k64 Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=K64 $1 $2 $3 $4 $5 $6

View File

@@ -1,2 +0,0 @@
#!/bin/bash
./komodo-cli -ac_name=ZEX $1 $2 $3 $4 $5 $6

2
src/ac/zexo Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=ZEXO $1 $2 $3 $4 $5 $6

View File

@@ -159,18 +159,6 @@
"136.243.102.225"
]
},
{
"ac_name": "MGNX",
"ac_supply": "12465003",
"ac_staked": "90",
"ac_reward": "2000000000",
"ac_halving": "525960",
"ac_cc": "2",
"ac_end": "2629800",
"addnode": [
"142.93.27.180"
]
},
{
"ac_name": "PGT",
"ac_supply": "10000000",
@@ -202,17 +190,6 @@
"144.76.217.232"
]
},
{
"ac_name": "ZEX",
"ac_founders": "1",
"ac_reward": "13000000000",
"ac_halving": "525600",
"ac_cc": "2",
"ac_pubkey": "039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af",
"addnode": [
"5.9.102.210"
]
},
{
"ac_name": "KSB",
"ac_supply": "1000000000",
@@ -268,5 +245,28 @@
"ac_name": "KOIN",
"ac_supply": "125000000",
"addnode": ["3.0.32.10"]
},
{
"ac_name": "ZEXO",
"ac_reward": "1478310502",
"ac_halving": "525600",
"ac_cc": "42",
"ac_ccenable": "236",
"ac_supply": "100000000",
"ac_perc": "77700",
"ac_staked": "93",
"ac_pubkey": "02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc",
"ac_public": "1",
"addnode": [
"195.201.20.230",
"80.240.17.222"
]
},
{
"ac_name": "K64",
"ac_reward": "0",
"ac_supply": "64000777",
"ac_staked": "10",
"addnode": ["18.197.20.21"]
}
]

View File

@@ -39,11 +39,10 @@ echo $pubkey
./komodod -pubkey=$pubkey -ac_name=SEC -ac_cc=333 -ac_supply=1000000000 -addnode=185.148.145.43 &
./komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 &
./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=178.63.77.56 &
./komodod -pubkey=$pubkey -ac_name=MGNX -ac_supply=12465003 -ac_staked=90 -ac_reward=2000000000 -ac_halving=525960 -ac_cc=2 -ac_end=2629800 -addnode=142.93.27.180 &
#./komodod -pubkey=$pubkey -ac_name=MGNX -ac_supply=12465003 -ac_staked=90 -ac_reward=2000000000 -ac_halving=525960 -ac_cc=2 -ac_end=2629800 -addnode=142.93.27.180 &
./komodod -pubkey=$pubkey -ac_name=PGT -ac_supply=10000000 -ac_end=1 -addnode=190.114.254.104 &
./komodod -pubkey=$pubkey -ac_name=KMDICE -ac_supply=10500000 -ac_reward=2500000000 -ac_halving=210000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=144.76.217.232 &
./komodod -pubkey=$pubkey -ac_name=DION -ac_supply=3900000000 -ac_reward=22260000000 -ac_staked=100 -ac_cc=1 -ac_end=4300000000 -addnode=51.75.124.34 &
./komodod -pubkey=$pubkey -ac_name=ZEX -ac_cc=2 -ac_founders=1 -ac_halving=525600 -ac_reward=13000000000 -ac_pubkey=039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af -addnode=5.9.102.210 &
./komodod -pubkey=$pubkey -ac_name=KSB -ac_supply=1000000000 -ac_end=1 -ac_public=1 -addnode=37.187.225.231 &
./komodod -pubkey=$pubkey -ac_name=OUR -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_supply=100000000 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c -ac_public=1 -addnode=51.255.195.65 -addnode=217.182.129.38 -addnode=37.187.225.231 &
./komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 &
@@ -51,3 +50,5 @@ echo $pubkey
./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -addnode=138.201.136.145 &
./komodod -pubkey=$pubkey -ac_name=VOTE2019 -ac_supply=123651638 -ac_public=1 -addnode=95.213.238.98 &
./komodod -pubkey=$pubkey -ac_name=KOIN -ac_supply=125000000 -addnode=3.0.32.10 &
./komodod -pubkey=$pubkey -ac_name=ZEXO -ac_supply=100000000 -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_ccenable=236 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc -ac_public=1 -addnode=80.240.17.222 &
./komodod -pubkey=$pubkey -ac_name=K64 -ac_supply=64000777 -ac_reward=0 -ac_staked=10 -addnode=18.197.20.211 &

View File

@@ -23,7 +23,7 @@
bool ImportGatewayValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn);
bool ImportGatewayExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid);
std::string ImportGatewayBind(uint64_t txfee,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t burnvout,std::string rawburntx,std::vector<uint8_t>proof,CPubKey destpub);
std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t burnvout,std::string rawburntx,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
std::string ImportGatewayWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
std::string ImportGatewayPartialSign(uint64_t txfee,uint256 lasttxid,std::string refcoin, std::string hex);
std::string ImportGatewayCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string refcoin,std::string hex);

View File

@@ -21,12 +21,12 @@
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format);
std::string OracleFund(int64_t txfee,uint256 oracletxid);
std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee);
std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount);
std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector <uint8_t> data);
// CCcustom
UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num);
UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num);
UniValue OracleInfo(uint256 origtxid);
UniValue OraclesList();

View File

@@ -18,17 +18,26 @@
#define CC_PAYMENTS_H
#include "CCinclude.h"
#include <gmp.h>
#include <key_io.h>
#define PAYMENTS_TXFEE 10000
#define PAYMENTS_MERGEOFSET 60 // 1H extra.
extern std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
extern int32_t lastSnapShotHeight;
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
// CCcustom
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsAirdropTokens(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr);
#endif

View File

@@ -17,35 +17,46 @@
#ifndef CC_PRICES_H
#define CC_PRICES_H
#include "komodo_defs.h"
#include "CCinclude.h"
int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind);
int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks);
extern void GetKomodoEarlytxidScriptPub();
extern CScript KOMODO_EARLYTXID_SCRIPTPUB;
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
// #define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) // defined in komodo_defs.h
#define PRICES_TXFEE 10000
#define PRICES_MAXLEVERAGE 777
#define PRICES_SMOOTHWIDTH 1
#define KOMODO_MAXPRICES 2048 // must be power of 2 and less than 8192
#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1))
#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1)
#define PRICES_MULT (KOMODO_MAXPRICES * 2)
#define PRICES_DIV (KOMODO_MAXPRICES * 3)
#define PRICES_INV (KOMODO_MAXPRICES * 4)
#define PRICES_MDD (KOMODO_MAXPRICES * 5)
#define PRICES_MMD (KOMODO_MAXPRICES * 6)
#define PRICES_MMM (KOMODO_MAXPRICES * 7)
#define PRICES_DDD (KOMODO_MAXPRICES * 8)
#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1)) // actually 1111 1000 0000 0000
#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1) // 0000 1000 0000 0000
#define PRICES_MULT (KOMODO_MAXPRICES * 2) // 0001 0000 0000 0000
#define PRICES_DIV (KOMODO_MAXPRICES * 3) // 0001 1000 0000 0000
#define PRICES_INV (KOMODO_MAXPRICES * 4) // 0010 0000 0000 0000
#define PRICES_MDD (KOMODO_MAXPRICES * 5) // 0010 1000 0000 0000
#define PRICES_MMD (KOMODO_MAXPRICES * 6) // 0011 0000 0000 0000
#define PRICES_MMM (KOMODO_MAXPRICES * 7) // 0011 1000 0000 0000
#define PRICES_DDD (KOMODO_MAXPRICES * 8) // 0100 0000 0000 0000
//#define PRICES_NORMFACTOR (int64_t)(SATOSHIDEN)
//#define PRICES_POINTFACTOR (int64_t)10000
#define PRICES_REVSHAREDUST 10000
#define PRICES_SUBREVSHAREFEE(amount) ((amount) * 199 / 200) // revshare fee percentage == 0.005
#define PRICES_MINAVAILFUNDFRACTION 0.1 // leveraged bet limit < fund fraction
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
// CCcustom
UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector<std::string> synthetic);
UniValue PricesAddFunding(uint64_t txfee,uint256 bettxid,int64_t amount);
UniValue PricesSetcostbasis(uint64_t txfee,uint256 bettxid);
UniValue PricesRekt(uint64_t txfee,uint256 bettxid,int32_t rektheight);
UniValue PricesCashout(uint64_t txfee,uint256 bettxid);
UniValue PricesBet(int64_t txfee,int64_t amount,int16_t leverage,std::vector<std::string> synthetic);
UniValue PricesAddFunding(int64_t txfee,uint256 bettxid,int64_t amount);
UniValue PricesSetcostbasis(int64_t txfee,uint256 bettxid);
UniValue PricesRekt(int64_t txfee,uint256 bettxid,int32_t rektheight);
UniValue PricesCashout(int64_t txfee,uint256 bettxid);
UniValue PricesInfo(uint256 bettxid,int32_t refheight);
UniValue PricesList();
UniValue PricesList(uint32_t filter, CPubKey mypk);
UniValue PricesGetOrderbook();
UniValue PricesRefillFund(int64_t amount);
#endif

View File

@@ -59,6 +59,8 @@ one other technical note is that komodod has the insight-explorer extensions bui
#define SMALLVAL 0.000000000000001
#define SATOSHIDEN ((uint64_t)100000000L)
#define dstr(x) ((double)(x) / SATOSHIDEN)
#define CCDISABLEALL memset(ASSETCHAINS_CCDISABLES,1,sizeof(ASSETCHAINS_CCDISABLES))
#define CCENABLE(x) ASSETCHAINS_CCDISABLES[((uint8_t)x)] = 0
#ifndef _BITS256
#define _BITS256
@@ -206,13 +208,13 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets);
CScript EncodeTokenImportOpRet(std::vector<uint8_t> origpubkey, std::string name, std::string description, uint256 srctokenid, std::vector<std::pair<uint8_t, vscript_t>> oprets);
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::pair<uint8_t, vscript_t> opretWithId);
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> oprets);
int64_t AddCClibtxfee(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk);
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description);
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, std::vector<std::pair<uint8_t, vscript_t>> &oprets);
uint8_t DecodeTokenImportOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, uint256 &srctokenid, std::vector<std::pair<uint8_t, vscript_t>> &oprets);
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> &oprets);
void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible);
bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vinPubkeys);
@@ -226,8 +228,11 @@ bool priv2addr(char *coinaddr,uint8_t buf33[33],uint8_t priv32[32]);
CPubKey buf2pk(uint8_t *buf33);
void endiancpy(uint8_t *dest,uint8_t *src,int32_t len);
uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv,int32_t entropyvout,int32_t usevout);
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk);
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2);
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, std::vector<std::vector<unsigned char>>* vData = NULL);
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData = NULL);
int32_t has_opret(const CTransaction &tx, uint8_t evalcode);
bool getCCopret(const CScript &scriptPubKey, CScript &opret);
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData);
CC *MakeCCcond1(uint8_t evalcode,CPubKey pk);
CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2);
CC* GetCryptoCondition(CScript const& scriptSig);
@@ -248,7 +253,7 @@ void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, c
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode);
bool IsCCInput(CScript const& scriptSig);
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime);
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime,int64_t &actualtxfee);
int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str);
uint256 revuint256(uint256 txid);
@@ -293,6 +298,9 @@ void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uin
bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen);
UniValue ValueFromAmount(const CAmount& amount);
int64_t TotalPubkeyNormalInputs(const CTransaction &tx, const CPubKey &pubkey);
int64_t TotalPubkeyCCInputs(const CTransaction &tx, const CPubKey &pubkey);
inline std::string STR_TOLOWER(const std::string &str) { std::string out; for (std::string::const_iterator i = str.begin(); i != str.end(); i++) out += std::tolower(*i); return out; }
// bitcoin LogPrintStr with category "-debug" cmdarg support for C++ ostringstream:
#define CCLOG_INFO 0

View File

@@ -1,5 +1,5 @@
/******************************************************************************
* Copyright © 2014-2018 The SuperNET Developers. *
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -14,6 +14,7 @@
******************************************************************************/
#include "CCtokens.h"
#include "importcoin.h"
/* TODO: correct this:
-----------------------------
@@ -102,22 +103,21 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
switch (funcid)
{
case 'c': // create wont be called to be verified as it has no CC inputs
case 'c': // token create should not be validated as it has no CC inputs, so return 'invalid'
// token tx structure for 'c':
//vin.0: normal input
//vout.0: issuance tokenoshis to CC
//vout.1: normal output for change (if any)
//vout.n-1: opreturn EVAL_TOKENS 'c' <tokenname> <description>
//if (evalCodeInOpret != EVAL_TOKENS)
// return eval->Invalid("unexpected TokenValidate for createtoken");
//else
return true;
return eval->Invalid("incorrect token funcid");
case 't': // transfer
// token tx structure for 't'
//vin.0: normal input
//vin.1 .. vin.n-1: valid CC outputs
//vout.0 to n-2: tokenoshis output to CC
//vout.n-2: normal output for change (if any)
//vout.n-1: opreturn <other evalcode> 't' tokenid <other contract payload>
//vout.n-1: opreturn EVAL_TOKENS 't' tokenid <other contract payload>
if (inputs == 0)
return eval->Invalid("no token inputs for transfer");
@@ -129,20 +129,7 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
return eval->Invalid("unexpected token funcid");
}
// forward validation if evalcode in opret is not EVAL_TOKENS
// init for forwarding validation call
//if (evalCodeInOpret != EVAL_TOKENS) { // TODO: should we check also only allowed for tokens evalcodes, like EVAL_ASSETS, EVAL_GATEWAYS?
// struct CCcontract_info *cpOther = NULL, C;
// cpOther = CCinit(&C, evalCodeInOpret);
// if (cpOther)
// return cpOther->validate(cpOther, eval, tx, nIn);
// else
// return eval->Invalid("unsupported evalcode in opret");
//}
return true;
// what does this do?
// return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts));
}
// helper funcs:
@@ -333,7 +320,8 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
vscript_t vopretExtra, vopretNonfungible;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
uint8_t evalCode = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim
uint8_t evalCodeNonfungible = 0;
uint8_t evalCode1 = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim
uint8_t evalCode2 = 0; // will be checked if zero or not
// test vouts for possible token use-cases:
@@ -354,12 +342,12 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
// non-fungible-eval -> EVAL_TOKENS -> assets-eval
if (vopretNonfungible.size() > 0)
evalCode = vopretNonfungible.begin()[0];
evalCodeNonfungible = evalCode1 = vopretNonfungible.begin()[0];
if (vopretExtra.size() > 0)
evalCode2 = vopretExtra.begin()[0];
if (evalCode == EVAL_TOKENS && evalCode2 != 0) {
evalCode = evalCode2; // for using MakeTokensCC1vout(evalcode,...) instead of MakeCC1vout(EVAL_TOKENS, evalcode...)
if (evalCode1 == EVAL_TOKENS && evalCode2 != 0) {
evalCode1 = evalCode2; // for using MakeTokensCC1vout(evalcode,...) instead of MakeCC1vout(EVAL_TOKENS, evalcode...)
evalCode2 = 0;
}
@@ -369,39 +357,41 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
// maybe this is dual-eval 1 pubkey or 1of2 pubkey vout?
if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) {
// check dual/three-eval 1 pubkey vout with the first pubkey
testVouts.push_back( std::make_pair(MakeTokensCC1vout(evalCode, evalCode2, tx.vout[v].nValue, voutPubkeys[0]), std::string("three-eval cc1 pk[0]")) );
testVouts.push_back( std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeys[0]), std::string("three-eval cc1 pk[0]")) );
if (evalCode2 != 0)
// also check in backward evalcode order
testVouts.push_back( std::make_pair(MakeTokensCC1vout(evalCode2, evalCode, tx.vout[v].nValue, voutPubkeys[0]), std::string("three-eval cc1 pk[0] backward-eval")) );
testVouts.push_back( std::make_pair(MakeTokensCC1vout(evalCode2, evalCode1, tx.vout[v].nValue, voutPubkeys[0]), std::string("three-eval cc1 pk[0] backward-eval")) );
if(voutPubkeys.size() == 2) {
// check dual/three eval 1of2 pubkeys vout
testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode, evalCode2, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]), std::string("three-eval cc1of2")) );
testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]), std::string("three-eval cc1of2")) );
// check dual/three eval 1 pubkey vout with the second pubkey
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode, evalCode2, tx.vout[v].nValue, voutPubkeys[1]), std::string("three-eval cc1 pk[1]")));
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, voutPubkeys[1]), std::string("three-eval cc1 pk[1]")));
if (evalCode2 != 0) {
// also check in backward evalcode order:
// check dual/three eval 1of2 pubkeys vout
testVouts.push_back(std::make_pair(MakeTokensCC1of2vout(evalCode2, evalCode, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]), std::string("three-eval cc1of2 backward-eval")));
testVouts.push_back(std::make_pair(MakeTokensCC1of2vout(evalCode2, evalCode1, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]), std::string("three-eval cc1of2 backward-eval")));
// check dual/three eval 1 pubkey vout with the second pubkey
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode, tx.vout[v].nValue, voutPubkeys[1]), std::string("three-eval cc1 pk[1] backward-eval")));
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode1, tx.vout[v].nValue, voutPubkeys[1]), std::string("three-eval cc1 pk[1] backward-eval")));
}
}
// maybe this is like gatewayclaim to single-eval token?
if( evalCodeNonfungible == 0 ) // do not allow to convert non-fungible to fungible token
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]), std::string("single-eval cc1 pk[0]")));
// maybe this is like gatewayclaim to single-eval token?
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]), std::string("single-eval cc1 pk[0]")));
// maybe this is like FillSell for non-fungible token?
if( evalCode != 0 )
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode, tx.vout[v].nValue, voutPubkeys[0]), std::string("dual-eval-token cc1 pk[0]")));
if( evalCode1 != 0 )
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeys[0]), std::string("dual-eval-token cc1 pk[0]")));
if( evalCode2 != 0 )
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, tx.vout[v].nValue, voutPubkeys[0]), std::string("dual-eval2-token cc1 pk[0]")));
// the same for pk[1]:
if (voutPubkeys.size() == 2) {
// the same for pk[1]:
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[1]), std::string("single-eval cc1 pk[1]")));
if (evalCode != 0)
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode, tx.vout[v].nValue, voutPubkeys[1]), std::string("dual-eval-token cc1 pk[1]")));
if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[1]), std::string("single-eval cc1 pk[1]")));
if (evalCode1 != 0)
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, voutPubkeys[1]), std::string("dual-eval-token cc1 pk[1]")));
if (evalCode2 != 0)
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, tx.vout[v].nValue, voutPubkeys[1]), std::string("dual-eval2-token cc1 pk[1]")));
}
@@ -413,52 +403,95 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
FilterOutTokensUnspendablePk(vinPubkeysUnfiltered, vinPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there)
for(std::vector<CPubKey>::iterator it = vinPubkeys.begin(); it != vinPubkeys.end(); it++) {
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it), std::string("single-eval cc1 self vin pk")));
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode, evalCode2, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk")));
if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it), std::string("single-eval cc1 self vin pk")));
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, evalCode2, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk")));
if (evalCode2 != 0)
// also check in backward evalcode order:
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk backward-eval")));
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode2, evalCode1, tx.vout[v].nValue, *it), std::string("three-eval cc1 self vin pk backward-eval")));
}
}
else {
CPubKey origPubkey;
vscript_t vorigPubkey;
std::string dummyName, dummyDescription;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (DecodeTokenCreateOpRet(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl);
return 0;
// try all test vouts:
for (auto t : testVouts) {
if (t.first == tx.vout[v]) { // test vout matches
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() valid amount=" << tx.vout[v].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl);
return tx.vout[v].nValue;
}
}
origPubkey = pubkey2pk(vorigPubkey);
// for 'c' recognize the tokens only to token originator pubkey (but not to unspendable <-- closed sec violation)
// maybe this is like gatewayclaim to single-eval token?
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey), std::string("single-eval cc1 orig-pk")));
// maybe this is like FillSell for non-fungible token?
if (evalCode != 0)
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode, tx.vout[v].nValue, origPubkey), std::string("dual-eval-token cc1 orig-pk")));
}
else { // funcid == 'c'
if (!tx.IsCoinImport()) {
// try all test vouts:
for (auto t : testVouts) {
if (t.first == tx.vout[v]) {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() valid amount=" << tx.vout[v].nValue << " msg=" << t.second << " evalCode=" << (int)evalCode << " evalCode2=" << (int)evalCode2 << " txid=" << tx.GetHash().GetHex() << " tokenid=" << reftokenid.GetHex() << std::endl);
return tx.vout[v].nValue;
vscript_t vorigPubkey;
std::string dummyName, dummyDescription;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (DecodeTokenCreateOpRet(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl);
return 0;
}
CPubKey origPubkey = pubkey2pk(vorigPubkey);
// TODO: add voutPubkeys for 'c' tx
/* this would not work for imported tokens:
// for 'c' recognize the tokens only to token originator pubkey (but not to unspendable <-- closed sec violation)
// maybe this is like gatewayclaim to single-eval token?
if (evalCodeNonfungible == 0) // do not allow to convert non-fungible to fungible token
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, origPubkey), std::string("single-eval cc1 orig-pk")));
// maybe this is like FillSell for non-fungible token?
if (evalCode1 != 0)
testVouts.push_back(std::make_pair(MakeTokensCC1vout(evalCode1, tx.vout[v].nValue, origPubkey), std::string("dual-eval-token cc1 orig-pk"))); */
// note: this would not work if there are several pubkeys in the tokencreator's wallet (AddNormalinputs does not use pubkey param):
// for tokenbase tx check that normal inputs sent from origpubkey > cc outputs
int64_t ccOutputs = 0;
for (auto vout : tx.vout)
if (vout.scriptPubKey.IsPayToCryptoCondition() //TODO: add voutPubkey validation
&& !IsTokenMarkerVout(vout)) // should not be marker here
ccOutputs += vout.nValue;
int64_t normalInputs = TotalPubkeyNormalInputs(tx, origPubkey); // check if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey)
LOGSTREAM("cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << " for tokenbase=" << reftokenid.GetHex() << std::endl);
if (normalInputs >= ccOutputs) {
LOGSTREAM("cctokens", CCLOG_DEBUG2, stream << indentStr << "IsTokensvout() assured normalInputs >= ccOutputs" << " for tokenbase=" << reftokenid.GetHex() << std::endl);
if (!IsTokenMarkerVout(tx.vout[v])) // exclude marker
return tx.vout[v].nValue;
else
return 0; // vout is good, but do not take marker into account
}
else {
LOGSTREAM("cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() skipping vout not fulfilled normalInputs >= ccOutput" << " for tokenbase=" << reftokenid.GetHex() << " normalInputs=" << normalInputs << " ccOutputs=" << ccOutputs << std::endl);
}
}
}
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() no valid vouts evalCode=" << (int)evalCode << " evalCode2=" << (int)evalCode2 << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl);
else {
// imported tokens are checked in the eval::ImportCoin() validation code
if (!IsTokenMarkerVout(tx.vout[v])) // exclude marker
return tx.vout[v].nValue;
else
return 0; // vout is good, but do not take marker into account
}
}
LOGSTREAM("cctokens", CCLOG_DEBUG1, stream << indentStr << "IsTokensvout() no valid vouts evalCode=" << (int)evalCode1 << " evalCode2=" << (int)evalCode2 << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl);
}
//std::cerr << indentStr; fprintf(stderr,"IsTokensvout() CC vout v.%d of n=%d amount=%.8f txid=%s\n",v,n,(double)0/COIN, tx.GetHash().GetHex().c_str());
}
//std::cerr << indentStr; fprintf(stderr,"IsTokensvout() normal output v.%d %.8f\n",v,(double)tx.vout[v].nValue/COIN);
return(0);
}
bool IsTokenMarkerVout(CTxOut vout) {
struct CCcontract_info *cpTokens, CCtokens_info;
cpTokens = CCinit(&CCtokens_info, EVAL_TOKENS);
return vout == MakeCC1vout(EVAL_TOKENS, vout.nValue, GetUnspendable(cpTokens, NULL));
}
// compares cc inputs vs cc outputs (to prevent feeding vouts from normal inputs)
bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 reftokenid)
{
@@ -582,6 +615,7 @@ int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, C
GetTokensCCaddress(cp, tokenaddr, pk);
SetCCunspents(unspentOutputs, tokenaddr,true);
if (unspentOutputs.empty()) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() no utxos for token dual/three eval addr=" << tokenaddr << " evalcode=" << (int)cp->evalcode << " additionalTokensEvalcode2=" << (int)cp->additionalTokensEvalcode2 << std::endl);
}
@@ -747,7 +781,7 @@ CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey) {
return CPubKey(); //return invalid pubkey
}
// returns token creation signed raw tx
std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, std::string description, vscript_t nonfungibleData)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -767,7 +801,7 @@ std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, st
cp = CCinit(&C, EVAL_TOKENS);
if (name.size() > 32 || description.size() > 4096) // this is also checked on rpc level
{
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "name len=" << name.size() << " or description len=" << description.size() << " is too big" << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "name len=" << name.size() << " or description len=" << description.size() << " is too big" << std::endl);
CCerror = "name should be <= 32, description should be <= 4096";
return("");
}
@@ -777,6 +811,13 @@ std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, st
if (AddNormalinputs(mtx, mypk, tokensupply + 2 * txfee, 64) > 0)
{
int64_t mypkInputs = TotalPubkeyNormalInputs(mtx, mypk);
if (mypkInputs < tokensupply) { // check that tokens amount are really issued with mypk (because in the wallet there maybe other privkeys)
CCerror = "some inputs signed not with -pubkey=pk";
return std::string("");
}
uint8_t destEvalCode = EVAL_TOKENS;
if( nonfungibleData.size() > 0 )
destEvalCode = nonfungibleData.begin()[0];
@@ -843,7 +884,7 @@ std::string TokenTransfer(int64_t txfee, uint256 tokenid, vscript_t destpubkey,
}
else {
CCerror = strprintf("no token inputs");
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << total << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << " for amount=" << total << std::endl);
}
//} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size());
}
@@ -880,7 +921,7 @@ UniValue TokenInfo(uint256 tokenid)
{
UniValue result(UniValue::VOBJ);
uint256 hashBlock;
CTransaction vintx;
CTransaction tokenbaseTx;
std::vector<uint8_t> origpubkey;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
vscript_t vopretNonfungible;
@@ -889,14 +930,20 @@ UniValue TokenInfo(uint256 tokenid)
cpTokens = CCinit(&tokensCCinfo, EVAL_TOKENS);
if( !GetTransaction(tokenid, vintx, hashBlock, false) )
if( !GetTransaction(tokenid, tokenbaseTx, hashBlock, false) )
{
fprintf(stderr, "TokenInfo() cant find tokenid\n");
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant find tokenid"));
return(result);
}
if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, origpubkey, name, description, oprets) != 'c')
if (hashBlock.IsNull()) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "the transaction is still in mempool"));
return(result);
}
if (tokenbaseTx.vout.size() > 0 && DecodeTokenCreateOpRet(tokenbaseTx.vout[tokenbaseTx.vout.size() - 1].scriptPubKey, origpubkey, name, description, oprets) != 'c')
{
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenInfo() passed tokenid isnt token creation txid" << std::endl);
result.push_back(Pair("result", "error"));
@@ -909,8 +956,8 @@ UniValue TokenInfo(uint256 tokenid)
result.push_back(Pair("name", name));
int64_t supply = 0, output;
for (int v = 0; v < vintx.vout.size() - 1; v++)
if ((output = IsTokensvout(false, true, cpTokens, NULL, vintx, v, tokenid)) > 0)
for (int v = 0; v < tokenbaseTx.vout.size() - 1; v++)
if ((output = IsTokensvout(false, true, cpTokens, NULL, tokenbaseTx, v, tokenid)) > 0)
supply += output;
result.push_back(Pair("supply", supply));
result.push_back(Pair("description", description));
@@ -919,6 +966,40 @@ UniValue TokenInfo(uint256 tokenid)
if( !vopretNonfungible.empty() )
result.push_back(Pair("data", HexStr(vopretNonfungible)));
if (tokenbaseTx.IsCoinImport()) { // if imported token
ImportProof proof;
CTransaction burnTx;
std::vector<CTxOut> payouts;
CTxDestination importaddress;
std::string sourceSymbol = "can't decode";
std::string sourceTokenId = "can't decode";
if (UnmarshalImportTx(tokenbaseTx, proof, burnTx, payouts))
{
// extract op_return to get burn source chain.
std::vector<uint8_t> burnOpret;
std::string targetSymbol;
uint32_t targetCCid;
uint256 payoutsHash;
std::vector<uint8_t> rawproof;
if (UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof)) {
if (rawproof.size() > 0) {
CTransaction tokenbasetx;
E_UNMARSHAL(rawproof, ss >> sourceSymbol;
if (!ss.eof())
ss >> tokenbasetx);
if (!tokenbasetx.IsNull())
sourceTokenId = tokenbasetx.GetHash().GetHex();
}
}
}
result.push_back(Pair("IsImported", "yes"));
result.push_back(Pair("sourceChain", sourceSymbol));
result.push_back(Pair("sourceTokenId", sourceTokenId));
}
return result;
}

View File

@@ -32,6 +32,7 @@ std::string CreateToken(int64_t txfee, int64_t assetsupply, std::string name, st
std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector<uint8_t> destpubkey, int64_t total);
int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, uint256 reftokenid);
CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey);
bool IsTokenMarkerVout(CTxOut vout);
int64_t GetTokenBalance(CPubKey pk, uint256 tokenid);
UniValue TokenInfo(uint256 tokenid);

View File

@@ -1,5 +1,21 @@
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
// encode decode tokens opret
// (moved to a separate file to enable linking lib common.so with importcoin.cpp)
// make token cryptoconditions and vouts
// This code was moved to a separate source file to enable linking libcommon.so (with importcoin.cpp which depends on some token functions)
#include "CCtokens.h"
@@ -44,6 +60,7 @@ CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey,
return(opret);
}
/*
// opret 'i' for imported tokens
CScript EncodeTokenImportOpRet(std::vector<uint8_t> origpubkey, std::string name, std::string description, uint256 srctokenid, std::vector<std::pair<uint8_t, vscript_t>> oprets)
{
@@ -62,7 +79,7 @@ CScript EncodeTokenImportOpRet(std::vector<uint8_t> origpubkey, std::string name
});
return(opret);
}
*/
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::pair<uint8_t, vscript_t> opretWithId)
@@ -158,37 +175,9 @@ uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t>
return (uint8_t)0;
}
// for imported tokens
uint8_t DecodeTokenImportOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, uint256 &srctokenid, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
{
vscript_t vopret, vblob;
uint8_t dummyEvalcode, funcid, opretId = 0;
GetOpReturnData(scriptPubKey, vopret);
oprets.clear();
if (vopret.size() > 2 && vopret.begin()[0] == EVAL_TOKENS && vopret.begin()[1] == 'i')
{
if (E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description; ss >> srctokenid;
while (!ss.eof()) {
ss >> opretId;
if (!ss.eof()) {
ss >> vblob;
oprets.push_back(std::make_pair(opretId, vblob));
}
}))
{
srctokenid = revuint256(srctokenid); // do not forget this
return(funcid);
}
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenImportOpRet() incorrect token import opret" << std::endl);
return (uint8_t)0;
}
// decodes token opret:
// decode token opret:
// for 't' returns all data from opret, vopretExtra contains other contract's data (currently only assets').
// for 'c' and 'i' returns only funcid. NOTE: nonfungible data is not returned
// for 'c' returns only funcid. NOTE: nonfungible data is not returned
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
{
vscript_t vopret, vblob, dummyPubkey, vnonfungibleDummy;
@@ -207,9 +196,6 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
if (script != NULL && vopret.size() > 2)
{
// NOTE: if parse error occures, parse might not be able to set error. It is safer to treat that it was eof if it is not set!
// bool isEof = true;
evalCodeTokens = script[0];
if (evalCodeTokens != EVAL_TOKENS) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect evalcode in tokens opret" << std::endl);
@@ -217,15 +203,13 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
}
funcId = script[1];
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "DecodeTokenOpRet decoded funcId=" << (char)(funcId ? funcId : ' ') << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "DecodeTokenOpRet() decoded funcId=" << (char)(funcId ? funcId : ' ') << std::endl);
switch (funcId)
{
case 'c':
return DecodeTokenCreateOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription, oprets);
case 'i':
return DecodeTokenImportOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription, dummySrcTokenId, oprets);
//break;
case 't':
// compatibility with old-style rogue or assets data (with no opretid):
@@ -293,4 +277,75 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
}
// make three-eval (token+evalcode+evalcode2) 1of2 cryptocondition:
CC *MakeTokensCCcond1of2(uint8_t evalcode, uint8_t evalcode2, CPubKey pk1, CPubKey pk2)
{
// make 1of2 sigs cond
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk1));
pks.push_back(CCNewSecp256k1(pk2));
std::vector<CC*> thresholds;
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode)));
if (evalcode != EVAL_TOKENS) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1of2()!
thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc
if (evalcode2 != 0)
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode
thresholds.push_back(CCNewThreshold(1, pks)); // this is 1 of 2 sigs cc
return CCNewThreshold(thresholds.size(), thresholds);
}
// overload to make two-eval (token+evalcode) 1of2 cryptocondition:
CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2) {
return MakeTokensCCcond1of2(evalcode, 0, pk1, pk2);
}
// make three-eval (token+evalcode+evalcode2) cryptocondition:
CC *MakeTokensCCcond1(uint8_t evalcode, uint8_t evalcode2, CPubKey pk)
{
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk));
std::vector<CC*> thresholds;
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode)));
if (evalcode != EVAL_TOKENS) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1()!
thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc
if (evalcode2 != 0)
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode
thresholds.push_back(CCNewThreshold(1, pks)); // signature
return CCNewThreshold(thresholds.size(), thresholds);
}
// overload to make two-eval (token+evalcode) cryptocondition:
CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) {
return MakeTokensCCcond1(evalcode, 0, pk);
}
// make three-eval (token+evalcode+evalcode2) 1of2 cc vout:
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk1, CPubKey pk2)
{
CTxOut vout;
CC *payoutCond = MakeTokensCCcond1of2(evalcode, evalcode2, pk1, pk2);
vout = CTxOut(nValue, CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
// overload to make two-eval (token+evalcode) 1of2 cc vout:
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2) {
return MakeTokensCC1of2vout(evalcode, 0, nValue, pk1, pk2);
}
// make three-eval (token+evalcode+evalcode2) cc vout:
CTxOut MakeTokensCC1vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk)
{
CTxOut vout;
CC *payoutCond = MakeTokensCCcond1(evalcode, evalcode2, pk);
vout = CTxOut(nValue, CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
// overload to make two-eval (token+evalcode) cc vout:
CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk) {
return MakeTokensCC1vout(evalcode, 0, nValue, pk);
}

View File

@@ -58,97 +58,79 @@ CC *MakeCCcond1(uint8_t evalcode,CPubKey pk)
return CCNewThreshold(2, {condCC, Sig});
}
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk)
int32_t has_opret(const CTransaction &tx, uint8_t evalcode)
{
int i = 0;
for ( auto vout : tx.vout )
{
//fprintf(stderr, "[txid.%s] 1.%i 2.%i 3.%i 4.%i\n",tx.GetHash().GetHex().c_str(), vout.scriptPubKey[0], vout.scriptPubKey[1], vout.scriptPubKey[2], vout.scriptPubKey[3]);
if ( vout.scriptPubKey.size() > 3 && vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[2] == evalcode )
return i;
i++;
}
return 0;
}
bool getCCopret(const CScript &scriptPubKey, CScript &opret)
{
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
CScript dummy; bool ret = false;
if ( scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) != 0 )
{
ret = true;
if ( vParams.size() == 1)
{
opret = CScript(vParams[0].begin()+6, vParams[0].end());
//fprintf(stderr, "vparams.%s\n", HexStr(vParams[0].begin(), vParams[0].end()).c_str());
}
}
return ret;
}
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData)
{
if ( opret.empty() )
return false;
vData.push_back(std::vector<unsigned char>(opret.begin(), opret.end()));
return true;
}
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue, CPubKey pk, std::vector<std::vector<unsigned char>>* vData)
{
CTxOut vout;
CC *payoutCond = MakeCCcond1(evalcode,pk);
vout = CTxOut(nValue,CCPubKey(payoutCond));
if ( vData )
{
//std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
//vPubKeys.push_back(pk);
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 1, vPubKeys, ( * vData));
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
}
cc_free(payoutCond);
return(vout);
}
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2)
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData)
{
CTxOut vout;
CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2);
vout = CTxOut(nValue,CCPubKey(payoutCond));
if ( vData )
{
//std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
// skip pubkeys. These need to maybe be optional and we need some way to get them out that is easy!
//vPubKeys.push_back(pk1);
//vPubKeys.push_back(pk2);
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 2, vPubKeys, ( * vData));
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
}
cc_free(payoutCond);
return(vout);
}
// make three-eval (token+evalcode+evalcode2) 1of2 cryptocondition:
CC *MakeTokensCCcond1of2(uint8_t evalcode, uint8_t evalcode2, CPubKey pk1, CPubKey pk2)
{
// make 1of2 sigs cond
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk1));
pks.push_back(CCNewSecp256k1(pk2));
std::vector<CC*> thresholds;
thresholds.push_back( CCNewEval(E_MARSHAL(ss << evalcode)) );
if( evalcode != EVAL_TOKENS ) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1of2()!
thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc
if( evalcode2 != 0 )
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode
thresholds.push_back(CCNewThreshold(1, pks)); // this is 1 of 2 sigs cc
return CCNewThreshold(thresholds.size(), thresholds);
}
// overload to make two-eval (token+evalcode) 1of2 cryptocondition:
CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2) {
return MakeTokensCCcond1of2(evalcode, 0, pk1, pk2);
}
// make three-eval (token+evalcode+evalcode2) cryptocondition:
CC *MakeTokensCCcond1(uint8_t evalcode, uint8_t evalcode2, CPubKey pk)
{
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk));
std::vector<CC*> thresholds;
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode)));
if (evalcode != EVAL_TOKENS) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1()!
thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc
if (evalcode2 != 0)
thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode2))); // add optional additional evalcode
thresholds.push_back(CCNewThreshold(1, pks)); // signature
return CCNewThreshold(thresholds.size(), thresholds);
}
// overload to make two-eval (token+evalcode) cryptocondition:
CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) {
return MakeTokensCCcond1(evalcode, 0, pk);
}
// make three-eval (token+evalcode+evalcode2) 1of2 cc vout:
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk1, CPubKey pk2)
{
CTxOut vout;
CC *payoutCond = MakeTokensCCcond1of2(evalcode, evalcode2, pk1, pk2);
vout = CTxOut(nValue, CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
// overload to make two-eval (token+evalcode) 1of2 cc vout:
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2) {
return MakeTokensCC1of2vout(evalcode, 0, nValue, pk1, pk2);
}
// make three-eval (token+evalcode+evalcode2) cc vout:
CTxOut MakeTokensCC1vout(uint8_t evalcode, uint8_t evalcode2, CAmount nValue, CPubKey pk)
{
CTxOut vout;
CC *payoutCond = MakeTokensCCcond1(evalcode, evalcode2, pk);
vout = CTxOut(nValue, CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
// overload to make two-eval (token+evalcode) cc vout:
CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk) {
return MakeTokensCC1vout(evalcode, 0, nValue, pk);
}
CC* GetCryptoCondition(CScript const& scriptSig)
{
auto pc = scriptSig.begin();
@@ -168,14 +150,19 @@ bool IsCCInput(CScript const& scriptSig)
return true;
}
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime)
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime, int64_t &actualtxfee)
{
LOCK(mempool.cs);
CCoinsView dummy;
CCoinsViewCache view(&dummy);
int64_t interest; uint64_t valuein;
CCoinsViewCache &view = *pcoinsTip;
CCoinsViewMemPool viewMemPool(pcoinsTip, mempool);
view.SetBackend(viewMemPool);
valuein = view.GetValueIn(height,&interest,tx,blocktime);
if ( valuein-tx.GetValueOut() > txfee )
actualtxfee = valuein-tx.GetValueOut();
if ( actualtxfee > txfee )
{
//fprintf(stderr, "txfee.%li vs txfee.%li\n", valuein-tx.GetValueOut(), txfee);
//fprintf(stderr, "actualtxfee.%li vs txfee.%li\n", actualtxfee, txfee);
return false;
}
return true;
@@ -640,7 +627,7 @@ bool komodo_txnotarizedconfirmed(uint256 txid)
fprintf(stderr,"komodo_txnotarizedconfirmed no hashBlock for txid %s\n",txid.ToString().c_str());
return(0);
}
else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txheight= pindex->GetHeight()) <= 0 )
else if ( (pindex= komodo_blockindex(hashBlock)) == 0 || (txheight= pindex->GetHeight()) <= 0 )
{
fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d %p for txid %s\n",txheight,pindex,txid.ToString().c_str());
return(0);
@@ -692,6 +679,57 @@ CPubKey check_signing_pubkey(CScript scriptSig)
return CPubKey();
}
// returns total of normal inputs signed with this pubkey
int64_t TotalPubkeyNormalInputs(const CTransaction &tx, const CPubKey &pubkey)
{
int64_t total = 0;
for (auto vin : tx.vin) {
CTransaction vintx;
uint256 hashBlock;
if (!IsCCInput(vin.scriptSig) && myGetTransaction(vin.prevout.hash, vintx, hashBlock)) {
typedef std::vector<unsigned char> valtype;
std::vector<valtype> vSolutions;
txnouttype whichType;
if (Solver(vintx.vout[vin.prevout.n].scriptPubKey, whichType, vSolutions)) {
switch (whichType) {
case TX_PUBKEY:
if (pubkey == CPubKey(vSolutions[0])) // is my input?
total += vintx.vout[vin.prevout.n].nValue;
break;
case TX_PUBKEYHASH:
if (pubkey.GetID() == CKeyID(uint160(vSolutions[0]))) // is my input?
total += vintx.vout[vin.prevout.n].nValue;
break;
}
}
}
}
return total;
}
// returns total of CC inputs signed with this pubkey
int64_t TotalPubkeyCCInputs(const CTransaction &tx, const CPubKey &pubkey)
{
int64_t total = 0;
for (auto vin : tx.vin) {
if (IsCCInput(vin.scriptSig)) {
CPubKey vinPubkey = check_signing_pubkey(vin.scriptSig);
if (vinPubkey.IsValid()) {
if (vinPubkey == pubkey) {
CTransaction vintx;
uint256 hashBlock;
if (myGetTransaction(vin.prevout.hash, vintx, hashBlock)) {
total += vintx.vout[vin.prevout.n].nValue;
}
}
}
}
}
return total;
}
bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn)
{
CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey;

116
src/cc/COptCCParams.cpp Normal file
View File

@@ -0,0 +1,116 @@
/*Descriptson and examples of COptCCParams class found in:
script/standard.h/cpp
class COptCCParams
structure of data in vData payload attached to end of CCvout:
param
OP_1
param
OP_2 ... etc until OP_16
OP_PUSHDATA4 is the last OP code to tell things its at the end.
taken from standard.cpp line 22: COptCCParams::COptCCParams(std::vector<unsigned char> &vch)
EXAMPLE taken from Verus how to create scriptPubKey from COptCCParams class:
EXAMPLE taken from Verus how to decode scriptPubKey from COptCCParams class:
*/
bool MakeGuardedOutput(CAmount value, CPubKey &dest, CTransaction &stakeTx, CTxOut &vout)
{
CCcontract_info *cp, C;
cp = CCinit(&C,EVAL_STAKEGUARD);
CPubKey ccAddress = CPubKey(ParseHex(cp->CChexstr));
// return an output that is bound to the stake transaction and can be spent by presenting either a signed condition by the original
// destination address or a properly signed stake transaction of the same utxo on a fork
vout = MakeCC1of2vout(EVAL_STAKEGUARD, value, dest, ccAddress);
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
vPubKeys.push_back(dest);
vPubKeys.push_back(ccAddress);
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hw << stakeTx.vin[0].prevout.hash;
hw << stakeTx.vin[0].prevout.n;
uint256 utxo = hw.GetHash();
vData.push_back(std::vector<unsigned char>(utxo.begin(), utxo.end())); // Can we use any data here to construct vector?
CStakeParams p;
if (GetStakeParams(stakeTx, p))
{
// prev block hash and height is here to make validation easy
vData.push_back(std::vector<unsigned char>(p.prevHash.begin(), p.prevHash.end()));
std::vector<unsigned char> height = std::vector<unsigned char>(4);
for (int i = 0; i < 4; i++)
{
height[i] = (p.blkHeight >> (8 * i)) & 0xff;
}
vData.push_back(height);
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, EVAL_STAKEGUARD, 1, 2, vPubKeys, vData);
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
return true;
}
return false;
}
bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTransaction &stakeTx, bool &cheating)
{
// an invalid or non-matching stake transaction cannot cheat
cheating = false;
//printf("ValidateMatchingStake: ccTx.vin[0].prevout.hash: %s, ccTx.vin[0].prevout.n: %d\n", ccTx.vin[0].prevout.hash.GetHex().c_str(), ccTx.vin[0].prevout.n);
if (ccTx.IsCoinBase())
{
CStakeParams p;
if (ValidateStakeTransaction(stakeTx, p))
{
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
CScript dummy;
if (ccTx.vout[voutNum].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && vParams.size() > 0)
{
COptCCParams ccp = COptCCParams(vParams[0]);
if (ccp.IsValid() & ccp.vData.size() >= 3 && ccp.vData[2].size() <= 4)
{
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hw << stakeTx.vin[0].prevout.hash;
hw << stakeTx.vin[0].prevout.n;
uint256 utxo = hw.GetHash();
uint32_t height = 0;
int i, dataLen = ccp.vData[2].size();
for (i = dataLen - 1; i >= 0; i--)
{
height = (height << 8) + ccp.vData[2][i];
}
// for debugging strange issue
// printf("iterator: %d, height: %d, datalen: %d\n", i, height, dataLen);
if (utxo == uint256(ccp.vData[0]))
{
if (p.prevHash != uint256(ccp.vData[1]) && p.blkHeight >= height)
{
cheating = true;
return true;
}
// if block height is equal and we are at the else, prevHash must have been equal
else if (p.blkHeight == height)
{
return true;
}
}
}
}
}
}
return false;
}

38
src/cc/Makefile_custom Executable file
View File

@@ -0,0 +1,38 @@
SHELL = /bin/sh
CC = gcc
CC_DARWIN = g++-8
CC_WIN = x86_64-w64-mingw32-gcc-posix
CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib
CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
CFLAGS_WIN = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
$(info $(OS))
OS := $(shell uname -s)
$(info $(OS))
TARGET = customcc.so
TARGET_DARWIN = customcc.dylib
TARGET_WIN = customcc.dll
SOURCES = cclib.cpp
#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/
all: $(TARGET)
$(TARGET): $(SOURCES)
$(info Building cclib to src/)
ifeq ($(OS),Darwin)
$(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES)
cp $(TARGET_DARWIN) ../libcc.dylib
else ifeq ($(HOST),x86_64-w64-mingw32)
$(info WINDOWS)
$(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES)
cp $(TARGET_WIN) ../libcc.dll
#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host
else
$(info LINUX)
$(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES)
cp $(TARGET) ../libcc.so
endif
clean:
rm -rf $(TARGET)

View File

@@ -1,6 +1,6 @@
SHELL = /bin/sh
CC = gcc
CC_DARWIN = g++-6
CC_DARWIN = g++-8
CC_WIN = x86_64-w64-mingw32-gcc-posix
CFLAGS_DARWIN = -DBUILD_ROGUE -std=c++11 -arch x86_64 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib
CFLAGS = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
@@ -14,7 +14,7 @@ TARGET = librogue.so
TARGET_DARWIN = librogue.dylib
TARGET_WIN = librogue.dll
SOURCES = cclib.cpp
#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/
#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/
all: $(TARGET)

View File

@@ -250,10 +250,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for channelpayment!");
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
return eval->Invalid("vin.1 is CC for channelpayment!");
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
return eval->Invalid("vin.2 is CC for channelpayment!");
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" is CC for channelpayment!");
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelpayment!");
else if ( ConstrainVout(tx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
@@ -283,8 +281,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("invalid previous tx OP_RETURN data!");
else if ( ConstrainVout(tx.vout[0],1,channeladdress,(p1-param2)*payment)==0 )
return eval->Invalid("vout.0 is CC or invalid CC change amount for channelpayment!");
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelpayment!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelpayment!");
else if (param1+param2!=p1)
return eval->Invalid("invalid payment depth!");
else if (tx.vout[3].nValue > prevTx.vout[0].nValue)
@@ -313,10 +311,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for channelclose!");
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
return eval->Invalid("vin.1 is CC for channelclose!");
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
return eval->Invalid("vin.2 is CC for channelclose!");
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" is CC for channelclose!");
else if ( ConstrainVout(tx.vout[0],1,channeladdress,0)==0 )
return eval->Invalid("vout.0 is CC for channelclose!");
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
@@ -329,8 +325,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
{
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
return eval->Invalid("invalid previous tx OP_RETURN data!");
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelclose!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelclose!");
else if (tx.vout[0].nValue != prevTx.vout[0].nValue)
return eval->Invalid("invalid CC amount, amount must match funds in channel");
}
@@ -358,10 +354,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("channelClose is not yet confirmed(notarised)!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for channelrefund!");
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
return eval->Invalid("vin.1 is CC for channelrefund!");
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
return eval->Invalid("vin.2 is CC for channelrefund!");
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" CC for channelrefund!");
else if ( ConstrainVout(tx.vout[0],1,srcmarker,CC_MARKER_VALUE)==0 )
return eval->Invalid("vout.0 is CC marker to srcpub or invalid amount for channelrefund!");
else if ( ConstrainVout(tx.vout[1],1,destmarker,CC_MARKER_VALUE)==0 )
@@ -376,8 +370,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
{
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
return eval->Invalid("invalid previous tx OP_RETURN data!");
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelrefund!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelrefund!");
else if (tx.vout[2].nValue != prevTx.vout[0].nValue)
return eval->Invalid("invalid amount, refund amount and funds in channel must match!");
}

View File

@@ -309,8 +309,8 @@ char *uppercase_str(char *buf,char *str);
char *lowercase_str(char *buf,char *str);
int32_t strsearch(char *strs[],int32_t num,char *name);
int32_t OS_getline(int32_t waitflag,char *line,int32_t max,char *dispstr);
int32_t sort64s(uint64_t *buf,uint32_t num,int32_t size);
int32_t revsort64s(uint64_t *buf,uint32_t num,int32_t size);
void sort64s(uint64_t *buf,uint32_t num,int32_t size);
void revsort64s(uint64_t *buf,uint32_t num,int32_t size);
int decode_base32(uint8_t *token,uint8_t *tokenstr,int32_t len);
int init_base32(char *tokenstr,uint8_t *token,int32_t len);
char *OS_mvstr();

View File

@@ -11,7 +11,7 @@
*/
CScript custom_opret(uint8_t funcid,CPubKey pk)
{
{
CScript opret; uint8_t evalcode = EVAL_CUSTOM;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk);
return(opret);
@@ -64,10 +64,17 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,COIN+txfee,64) >= COIN+txfee ) // add utxo to mtx
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk)); // make vout0
// add opreturn, change is automatically added and tx is properly signed
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,custom_opret('1',mypk));
return(custom_rawtxresult(result,rawtx,broadcastflag));
// make op_return payload as normal.
CScript opret = custom_opret('1',mypk);
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
if ( makeCCopret(opret, vData) )
{
// make vout0 with op_return included as payload.
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk,&vData));
fprintf(stderr, "vout size2.%li\n", mtx.vout.size());
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,CScript());
return(custom_rawtxresult(result,rawtx,broadcastflag));
}
}
return(result);
}
@@ -75,14 +82,24 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
char expectedaddress[64]; CPubKey pk;
if ( tx.vout.size() != 2 ) // make sure the tx only has 2 outputs
CScript opret; int32_t numvout = 0;
if ( has_opret(tx, EVAL_CUSTOM) == 0 )
{
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
if ( getCCopret(tx.vout[0].scriptPubKey,opret) )
numvout = 1;
}
else
{
opret = tx.vout[1].scriptPubKey;
numvout = 2;
}
if ( tx.vout.size() != numvout ) // make sure the tx only has appropriate outputs
return eval->Invalid("invalid number of vouts");
else if ( custom_opretdecode(pk,tx.vout[1].scriptPubKey) != '1' ) // verify has opreturn
else if ( custom_opretdecode(pk,opret) != '1' ) // verify opreturn payload
return eval->Invalid("invalid opreturn");
GetCCaddress(cp,expectedaddress,pk);
if ( IsCClibvout(cp,tx,0,expectedaddress) == COIN ) // make sure amount and destination matches
return(true);
else return eval->Invalid("invalid vout0 amount");
}

View File

@@ -592,7 +592,7 @@ void addmultisigaddress(char *refcoin,char *acname,int32_t M, char *pubkeys)
cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required)
{
cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,n,v; int64_t satoshis; bits256 txid;
cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,j=0,n,v; int64_t satoshis; bits256 txid;
*totalp = 0;
if ( (n= cJSON_GetArraySize(unspents)) > 0 )
{
@@ -610,7 +610,10 @@ cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required)
jaddi(vins,vin);
*totalp += satoshis;
if ( (*totalp) >= required )
break;
{
if (j<3) j++;
else break;
}
}
}
}
@@ -910,10 +913,11 @@ void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxi
processed++;
}
free(rawtx);
} else fprintf(stderr,"couldnt create rawtx\n");
} else fprintf(stderr,"couldnt create rawtx\n");
}
else
{
rawtx=0;
lasttxid = jbits256(item,"last_txid");
if ( lasttxid.txid==withdrawtxid.txid)
{
@@ -921,24 +925,27 @@ void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxi
}
else rawtx=jstr(item,"hex");
K=jint(item,"number_of_signs");
if ( rawtx!=0 && (clijson=addsignature(refcoin,"",rawtx,M)) != 0 )
if (rawtx!=0)
{
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
{
txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N);
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
}
else if ( jint(clijson,"partialtx") != 0 )
if ((clijson=addsignature(refcoin,"",rawtx,M)) != 0 )
{
txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N);
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
}
free_json(clijson);
processed++;
if ( lasttxid.txid==withdrawtxid.txid) free(rawtx);
}
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
{
txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N);
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
}
else if ( jint(clijson,"partialtx") != 0 )
{
txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N);
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
}
free_json(clijson);
processed++;
if ( lasttxid.txid==withdrawtxid.txid) free(rawtx);
}
} else fprintf(stderr,"couldnt create rawtx or find previous partial signed tx\n");
}
}
}

View File

@@ -315,6 +315,8 @@ cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char
{
long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[256];
sprintf(fname,"/tmp/zmigrate.%s",method);
//if ( (acname == 0 || acname[0] == 0) && strcmp(refcoin,"KMD") != 0 )
// acname = refcoin;
if ( acname[0] != 0 )
{
if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 )
@@ -664,6 +666,7 @@ int32_t z_exportkey(char *privkey,char *refcoin,char *acname,char *zaddr)
free(retstr);
return(0);
}
return(-1);
}
int32_t getnewaddress(char *coinaddr,char *refcoin,char *acname)
@@ -937,7 +940,505 @@ int32_t have_pending_opid(char *coinstr,int32_t clearresults)
return(pending);
}
int64_t utxo_value(char *refcoin,char *srcaddr,bits256 txid,int32_t v)
{
cJSON *txjson,*vouts,*vout,*sobj,*array; int32_t numvouts,numaddrs; int64_t val,value = 0; char *addr,str[65];
srcaddr[0] = 0;
if ( (txjson= get_rawtransaction(refcoin,"",txid)) != 0 )
{
if ( (vouts= jarray(&numvouts,txjson,"vout")) != 0 && v < numvouts )
{
vout = jitem(vouts,v);
if ( (val= jdouble(vout,"value")*SATOSHIDEN) != 0 && (sobj= jobj(vout,"scriptPubKey")) != 0 )
{
if ( (array= jarray(&numaddrs,sobj,"addresses")) != 0 && numaddrs == 1 && (addr= jstri(array,0)) != 0 && strlen(addr) < 64 )
{
strcpy(srcaddr,addr);
value = val;
} else printf("couldnt get unique address for %s/%d\n",bits256_str(str,txid),v);
} else printf("error getting value for %s/v%d\n",bits256_str(str,txid),v);
}
}
return(value);
}
int32_t verify_vin(char *refcoin,bits256 txid,int32_t v,char *cmpaddr)
{
cJSON *txjson,*vins,*vin; int32_t numvins; char vinaddr[64],str[65];
vinaddr[0] = 0;
if ( (txjson= get_rawtransaction(refcoin,"",txid)) != 0 )
{
if ( (vins= jarray(&numvins,txjson,"vin")) != 0 && v < numvins )
{
vin = jitem(vins,v);
if ( utxo_value(refcoin,vinaddr,jbits256(vin,"txid"),jint(vin,"vout")) > 0 && strcmp(vinaddr,cmpaddr) == 0 )
return(0);
printf("mismatched vinaddr.(%s) vs %s\n",vinaddr,cmpaddr);
}
}
return(-1);
}
int32_t txid_in_vins(char *refcoin,bits256 txid,bits256 cmptxid)
{
cJSON *txjson,*vins,*vin; int32_t numvins,v,vinvout; bits256 vintxid; char str[65];
if ( (txjson= get_rawtransaction(refcoin,"",txid)) != 0 )
{
if ( (vins= jarray(&numvins,txjson,"vin")) != 0 )
{
for (v=0; v<numvins; v++)
{
vin = jitem(vins,v);
vintxid = jbits256(vin,"txid");
vinvout = jint(vin,"vout");
if ( memcmp(&vintxid,&cmptxid,sizeof(vintxid)) == 0 && vinvout == 0 )
{
return(0);
}
}
}
}
return(-1);
}
void genpayout(char *coinstr,char *destaddr,int32_t amount)
{
char cmd[1024];
sprintf(cmd,"curl -s --url \"http://127.0.0.1:7783\" --data \"{\\\"userpass\\\":\\\"$userpass\\\",\\\"method\\\":\\\"withdraw\\\",\\\"coin\\\":\\\"%s\\\",\\\"outputs\\\":[{\\\"%s\\\":%.8f},{\\\"RWXL82m4xnBTg1kk6PuS2xekonu7oEeiJG\\\":0.0002}],\\\"broadcast\\\":1}\"\nsleep 3\n",coinstr,destaddr,dstr(amount+20000));
printf("%s",cmd);
}
bits256 SECONDVIN; int32_t SECONDVOUT;
void genrefund(char *cmd,char *coinstr,bits256 vintxid,char *destaddr,int64_t amount)
{
char str[65],str2[65];
sprintf(cmd,"curl -s --url \"http://127.0.0.1:7783\" --data \"{\\\"userpass\\\":\\\"$userpass\\\",\\\"method\\\":\\\"withdraw\\\",\\\"coin\\\":\\\"%s\\\",\\\"onevin\\\":2,\\\"utxotxid\\\":\\\"%s\\\",\\\"utxovout\\\":1,\\\"utxotxid2\\\":\\\"%s\\\",\\\"utxovout2\\\":%d,\\\"outputs\\\":[{\\\"%s\\\":%.8f}],\\\"broadcast\\\":1}\"\nsleep 3\n",coinstr,bits256_str(str,vintxid),bits256_str(str2,SECONDVIN),SECONDVOUT,destaddr,dstr(amount));
system(cmd);
}
struct addritem
{
int64_t total,numutxos;
char addr[64];
} ADDRESSES[1200];
struct claimitem
{
bits256 txid;
int64_t total,refundvalue;
int32_t numutxos,disputed,approved;
char oldaddr[64],destaddr[64],username[64];
} CLAIMS[10000];
int32_t NUM_ADDRESSES,NUM_CLAIMS;
int32_t itemvalid(char *refcoin,int64_t *refundedp,int64_t *waitingp,struct claimitem *item)
{
cJSON *curljson,*txids; int32_t i,numtxids; char str[65],str2[65],url[1000],*retstr; bits256 txid;
*refundedp = *waitingp = 0;
if ( item->refundvalue < 0 )
return(-1);
sprintf(url,"https://kmd.explorer.dexstats.info/insight-api-komodo/addr/%s",item->destaddr);
if ( (retstr= send_curl(url,"/tmp/itemvalid")) != 0 )
{
if ( (curljson= cJSON_Parse(retstr)) != 0 )
{
if ( (txids= jarray(&numtxids,curljson,"transactions")) != 0 )
{
for (i=0; i<numtxids; i++)
{
txid = jbits256i(txids,i);
if ( txid_in_vins(refcoin,txid,item->txid) == 0 )
{
printf("found item->txid %s inside %s\n",bits256_str(str,item->txid),bits256_str(str2,txid));
item->approved = 1;
break;
}
}
}
free_json(curljson);
}
//printf("%s\n",retstr);
free(retstr);
}
if ( item->approved != 0 )
return(1);
*waitingp = item->refundvalue;
return(-1);
}
void scan_claims(int32_t issueflag,char *refcoin,int32_t batchid)
{
char str[65]; int32_t i,num,numstolen=0,numcandidates=0,numinvalids=0,numrefunded=0,numwaiting=0; struct claimitem *item; int64_t batchmin,batchmax,waiting,refunded,possiblerefund=0,possiblestolen = 0,invalidsum=0,totalrefunded=0,waitingsum=0;
if ( batchid == 0 )
{
batchmin = 0;
batchmax = 7 * SATOSHIDEN;
}
else if ( batchid == 1 )
{
batchmin = 7 * SATOSHIDEN;
batchmax = 777 * SATOSHIDEN;
}
else if ( batchid == 2 )
{
batchmin = 1;//777 * SATOSHIDEN;
batchmax = 77777 * SATOSHIDEN;
}
else if ( batchid == 3 )
{
batchmin = 77777 * SATOSHIDEN;
batchmax = 1000000 * SATOSHIDEN;
}
for (i=0; i<NUM_CLAIMS; i++)
{
item = &CLAIMS[i];
if ( item->refundvalue < batchmin || item->refundvalue >= batchmax )
continue;
if ( itemvalid(refcoin,&refunded,&waiting,item) < 0 )
{
if ( refunded != 0 )
{
numrefunded++;
totalrefunded += refunded;
}
else if ( waiting != 0 )
{
numwaiting++;
waitingsum += waiting;
}
else
{
invalidsum += item->refundvalue;
numinvalids++;
}
continue;
}
if ( item->total > item->refundvalue*1.1 + 10*SATOSHIDEN )
{
printf("possible.%d stolen %s %.8f vs refund %.8f -> %.8f\n",batchid,item->oldaddr,dstr(item->total),dstr(item->refundvalue),dstr(item->total)-dstr(item->refundvalue));
numstolen++;
possiblestolen += (item->total - item->refundvalue);
item->approved = 0;
}
else
{
printf("candidate.%d %s %.8f vs refund %.8f -> %s\n",batchid,item->oldaddr,dstr(item->total),dstr(item->refundvalue),item->destaddr);
numcandidates++;
possiblerefund += item->refundvalue;
}
}
printf("batchid.%d TOTAL exposure %d %.8f, possible refund %d %.8f, invalids %d %.8f, numrefunded %d %.8f, waiting %d %.8f\n",batchid,numstolen,dstr(possiblestolen),numcandidates,dstr(possiblerefund),numinvalids,dstr(invalidsum),numrefunded,dstr(totalrefunded),numwaiting,dstr(waitingsum));
for (i=num=0; i<NUM_CLAIMS; i++)
{
item = &CLAIMS[i];
if ( item->approved != 0 )
{
printf("%d.%d: approved.%d %s %.8f vs refund %.8f -> %s\n",i,num,batchid,item->oldaddr,dstr(item->total),dstr(item->refundvalue),item->destaddr);
num++;
if ( issueflag != 0 )
{
static FILE *fp; char cmd[1024];
if ( fp == 0 )
fp = fopen("refund.log","wb");
genrefund(cmd,refcoin,item->txid,item->destaddr,item->refundvalue);
if ( fp != 0 )
{
fprintf(fp,"%s,%s,%s,%s,%s,%.8f,%s\n",item->username,refcoin,bits256_str(str,item->txid),item->oldaddr,item->destaddr,dstr(item->refundvalue),cmd);
fflush(fp);
}
memset(&SECONDVIN,0,sizeof(SECONDVIN));
SECONDVOUT = 1;
//printf(">>>>>>>>>>>>>>>>>> getchar after (%s)\n",cmd);
//getchar();
}
}
}
}
int32_t update_claimvalue(int32_t *disputedp,char *addr,int64_t amount,bits256 txid)
{
int32_t i; struct claimitem *item;
*disputedp = 0;
for (i=0; i<NUM_CLAIMS; i++)
{
if ( strcmp(addr,CLAIMS[i].oldaddr) == 0 )
{
item = &CLAIMS[i];
item->refundvalue = amount;
if ( bits256_nonz(item->txid) != 0 )
printf("disputed.%d %s claimed %.8f vs %.8f\n",item->disputed,addr,dstr(item->total),dstr(amount));
item->txid = txid;
if ( item->disputed != 0 )
*disputedp = 1;
return(i);
}
}
return(-1);
}
int64_t update_claimstats(char *username,char *oldaddr,char *destaddr,int64_t amount)
{
int32_t i; struct claimitem *item;
for (i=0; i<NUM_CLAIMS; i++)
{
if ( strcmp(oldaddr,CLAIMS[i].oldaddr) == 0 )
{
item = &CLAIMS[i];
if ( strcmp(destaddr,item->destaddr) != 0 )//|| strcmp(username,item->username) != 0 )
{
item->disputed++;
printf("disputed.%d claim.%-4d: (%36s -> %36s %s) vs. (%36s -> %36s %s) \n",item->disputed,i,oldaddr,destaddr,username,item->oldaddr,item->destaddr,item->username);
}
item->numutxos++;
item->total += amount;
return(amount);
}
}
item = &CLAIMS[NUM_CLAIMS++];
item->total = amount;
item->numutxos = 1;
strncpy(item->oldaddr,oldaddr,sizeof(item->oldaddr));
strncpy(item->destaddr,destaddr,sizeof(item->destaddr));
strncpy(item->username,username,sizeof(item->username));
printf("new claim.%-4d: %36s %16.8f -> %36s %s\n",NUM_CLAIMS,oldaddr,dstr(amount),destaddr,username);
return(amount);
}
int32_t update_addrstats(char *srcaddr,int64_t amount)
{
int32_t i; struct addritem *item;
for (i=0; i<NUM_ADDRESSES; i++)
{
if ( strcmp(srcaddr,ADDRESSES[i].addr) == 0 )
{
ADDRESSES[i].numutxos++;
ADDRESSES[i].total += amount;
return(i);
}
}
item = &ADDRESSES[NUM_ADDRESSES++];
item->total = amount;
item->numutxos = 1;
strcpy(item->addr,srcaddr);
printf("%d new address %s\n",NUM_ADDRESSES,srcaddr);
return(-1);
}
int64_t sum_of_vins(char *refcoin,int32_t *totalvinsp,int32_t *uniqaddrsp,bits256 txid)
{
cJSON *txjson,*vins,*vin; char str[65],srcaddr[64]; int32_t i,numarray; int64_t amount,total = 0;
if ( (txjson= get_rawtransaction(refcoin,"",txid)) != 0 )
{
if ( (vins= jarray(&numarray,txjson,"vin")) != 0)
{
for (i=0; i<numarray; i++)
{
if ( (vin= jitem(vins,i)) != 0 )
{
if ( (amount= utxo_value(refcoin,srcaddr,jbits256(vin,"txid"),jint(vin,"vout"))) == 0 )
printf("error getting value from %s/v%d\n",bits256_str(str,jbits256(vin,"txid")),jint(vin,"vout"));
else
{
if ( update_addrstats(srcaddr,amount) < 0 )
(*uniqaddrsp)++;
//printf("add %s <- %.8f\n",srcaddr,dstr(amount));
total += amount;
(*totalvinsp)++;
}
}
}
}
}
if ( total == 0 )
printf("sum_of_vins error %s\n",bits256_str(str,txid));
return(total);
}
void reconcile_claims(char *fname)
{
FILE *fp; double amount; int32_t i,n,numlines = 0; char buf[1024],fields[16][256],*str; int64_t total = 0;
if ( (fp= fopen(fname,"rb")) != 0 )
{
while ( fgets(buf,sizeof(buf),fp) > 0 )
{
//printf("%d.(%s)\n",numlines,buf);
str = buf;
n = i = 0;
memset(fields,0,sizeof(fields));
while ( *str != 0 )
{
if ( *str == ',' || *str == '\n' || *str == '\r' )
{
fields[n][i] = 0;
i = 0;
if ( n > 1 )
{
//printf("(%16s) ",fields[n]);
}
n++;
if ( *str == '\n' || *str == '\r' )
break;
}
if ( *str == ',' || *str == ' ' )
str++;
else fields[n][i++] = *str++;
}
//printf("%s\n",fields[0]);
total += update_claimstats(fields[1],fields[3],fields[6],atof(fields[4])*SATOSHIDEN + 0.0000000049);
numlines++;
}
fclose(fp);
}
printf("total claims %.8f\n",dstr(total));
}
int32_t main(int32_t argc,char **argv)
{
char *coinstr,*acstr,*addr,buf[64],srcaddr[64],str[65]; cJSON *retjson,*item; int32_t i,n,disputed,numdisputed,numsmall=0,numpayouts=0,numclaims=0,num=0,totalvins=0,uniqaddrs=0; int64_t amount,total = 0,total2 = 0,payout,maxpayout,smallpayout=0,totalpayout = 0,totaldisputed = 0,totaldisputed2 = 0,fundingamount = 0;
if ( argc != 2 )
{
printf("argc needs to be 2: <prog> coin\n");
return(-1);
}
if ( strcmp(argv[1],"KMD") == 0 )
{
REFCOIN_CLI = "./komodo-cli";
coinstr = clonestr("KMD");
acstr = "";
}
else if ( strcmp(argv[1],"CHIPS") == 0 )
{
REFCOIN_CLI = "./chips-cli";
coinstr = clonestr("CHIPS");
acstr = "";
}
else
{
sprintf(buf,"./komodo-cli -ac_name=%s",argv[1]);
REFCOIN_CLI = clonestr(buf);
coinstr = clonestr(argv[1]);
acstr = coinstr;
}
if ( 1 )//strcmp(coinstr,"KMD") == 0 )
{
sprintf(buf,"%s-Claims.csv",coinstr);
reconcile_claims(buf);
for (i=0; i<NUM_CLAIMS; i++)
{
if ( CLAIMS[i].disputed != 0 )
{
totaldisputed += CLAIMS[i].total;
printf("disputed %s %.8f\n",CLAIMS[i].oldaddr,dstr(CLAIMS[i].total));
}
}
printf("total disputed %.8f\n",dstr(totaldisputed));
totaldisputed2 = 0;
if ( (retjson= get_listunspent(coinstr,acstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(retjson)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(retjson,i);
amount = jdouble(item,"amount")*SATOSHIDEN;
if ( (addr= jstr(item,"address")) != 0 && strcmp(addr,"RWXL82m4xnBTg1kk6PuS2xekonu7oEeiJG") == 0 )
{
if ( amount != 20000 )
{
if ( amount > fundingamount )
{
fundingamount = amount;
SECONDVIN = jbits256(item,"txid");
SECONDVOUT = jint(item,"vout");
printf("set SECONDVIN to %s/v%d %.8f\n",bits256_str(str,SECONDVIN),SECONDVOUT,dstr(amount));
}
continue;
}
if ( strcmp(coinstr,"KMD") == 0 && verify_vin(coinstr,jbits256(item,"txid"),0,"R9JCEd6xnCxNUSpLrHEWvzPSh7CNXm7z75") < 0 )
{
printf("WARNING: imposter dust detected! %s\n",bits256_str(str,jbits256(item,"txid")));
continue;
}
else if ( strcmp(coinstr,"KMD") != 0 && verify_vin(coinstr,jbits256(item,"txid"),0,"R9MUnxXijovvSeT9sFuUX23TiFtVvZEGjT") < 0 )
{
printf("WARNING: imposter dust detected! %s\n",bits256_str(str,jbits256(item,"txid")));
continue;
}
amount = (utxo_value(coinstr,srcaddr,jbits256(item,"txid"),0) - 20000) * SATOSHIDEN;
//printf("%d: %s claimvalue %.8f\n",num,srcaddr,dstr(amount));
num++;
total2 += amount;
if ( update_claimvalue(&disputed,srcaddr,amount,jbits256(item,"txid")) >= 0 )
{
if ( disputed != 0 )
{
totaldisputed2 += amount;
numdisputed++;
}
else
{
numclaims++;
total += amount;
}
}
}
}
}
free_json(retjson);
printf("remaining refunds.%d %.8f, numclaims.%d %.8f, numdisputed.%d %.8f\n",num,dstr(total2),numclaims,dstr(total),numdisputed,dstr(totaldisputed2));
}
//scan_claims(0,coinstr,0);
//scan_claims(0,coinstr,1);
scan_claims(0,coinstr,2);
//scan_claims(0,coinstr,3);
}
else if ( (retjson= get_listunspent(coinstr,acstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(retjson)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(retjson,i);
if ( (addr= jstr(item,"address")) != 0 && strcmp(addr,"RSgD2cmm3niFRu2kwwtrEHoHMywJdkbkeF") == 0 )
{
if ( (amount= jdouble(item,"amount")*SATOSHIDEN) != 0 )
{
num++;
total += amount;
total2 += sum_of_vins(coinstr,&totalvins,&uniqaddrs,jbits256(item,"txid"));
}
}
}
}
free_json(retjson);
maxpayout = 0;
for (i=0; i<NUM_ADDRESSES; i++)
{
if ( ADDRESSES[i].total >= SATOSHIDEN )
{
payout = ADDRESSES[i].total / SATOSHIDEN;
if ( payout > maxpayout )
maxpayout = payout;
totalpayout += payout;
numpayouts++;
//if ( payout >= 7 )
//{
// numsmall++;
//smallpayout += payout;
genpayout(coinstr,ADDRESSES[i].addr,payout);
//}
//printf("%-4d: %-64s numutxos.%-4lld %llu\n",i,ADDRESSES[i].addr,ADDRESSES[i].numutxos,(long long)payout);
}
}
printf("num.%d total %.8f vs vintotal %.8f, totalvins.%d uniqaddrs.%d:%d totalpayout %llu maxpayout %llu numpayouts.%d numsmall.%d %llu\n",num,dstr(total),dstr(total2),totalvins,uniqaddrs,NUM_ADDRESSES,(long long)totalpayout,(long long)maxpayout,numpayouts,numsmall,(long long)smallpayout);
}
}
int32_t zmigratemain(int32_t argc,char **argv)
{
char buf[1024],*zsaddr,*coinstr;
if ( argc != 3 )

View File

@@ -53,6 +53,15 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn)
eval->state.GetRejectReason().data(),
tx.vin[nIn].prevout.hash.GetHex().data());
if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data());
CTransaction tmp;
if (mempool.lookup(tx.GetHash(), tmp))
{
// This is to remove a payments airdrop if it gets stuck in the mempool.
// Miner will mine 1 invalid block, but doesnt stop them mining until a restart.
// This would almost never happen in normal use.
std::list<CTransaction> dummy;
mempool.remove(tx,dummy,true);
}
return false;
}
@@ -69,8 +78,13 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
uint8_t ecode = cond->code[0];
if ( ASSETCHAINS_CCDISABLES[ecode] != 0 )
{
fprintf(stderr,"%s evalcode.%d %02x\n",txTo.GetHash().GetHex().c_str(),ecode,ecode);
return Invalid("disabled-code, -ac_ccenables didnt include this ecode");
// check if a height activation has been set.
if ( mapHeightEvalActivate[ecode] == 0 || this->GetCurrentHeight() == 0 || mapHeightEvalActivate[ecode] > this->GetCurrentHeight() )
{
fprintf(stderr,"%s evalcode.%d %02x\n",txTo.GetHash().GetHex().c_str(),ecode,ecode);
fprintf(stderr, "ac_ccactivateht: evalcode.%i activates at height.%i vs current height.%i\n", ecode, mapHeightEvalActivate[ecode], this->GetCurrentHeight());
return Invalid("disabled-code, -ac_ccenables didnt include this ecode");
}
}
std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
if ( ecode >= EVAL_FIRSTUSER && ecode <= EVAL_LASTUSER )

View File

@@ -571,8 +571,6 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("invalid gatewaysbind OP_RETURN data!");
else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for gatewaysbind!");
else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 )
return eval->Invalid("vin.1 is CC for gatewaysbind!");
else if ( ConstrainVout(tmptx.vout[0],1,gatewaystokensaddr,totalsupply)==0)
return eval->Invalid("invalid tokens to gateways vout for gatewaysbind!");
else if ( ConstrainVout(tmptx.vout[1],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0)
@@ -599,6 +597,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid(validationError);
}
else if ( DecodeOraclesCreateOpRet(tmptx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' )
return eval->Invalid("invalid oraclescreate OP_RETURN data");
else if (refcoin!=name)
{
sprintf(validationError,"mismatched oracle name %s != %s\n",name.c_str(),refcoin.c_str());
return eval->Invalid(validationError);
@@ -628,22 +628,25 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("deposit amount greater then bind total supply");
else if (komodo_txnotarizedconfirmed(deposittxid) == false)
return eval->Invalid("gatewaysdeposit tx is not yet confirmed(notarised)!");
else if (myGetTransaction(tx.vin[2].prevout.hash,tmptx,hashblock) == 0)
return eval->Invalid("invalid gatewaysdeposittxid!");
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
return eval->Invalid("vin.0 is normal for gatewaysclaim!");
else if (IsCCInput(tx.vin[1].scriptSig) == 0)
return eval->Invalid("vin.1 is CC for gatewaysclaim!");
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || myGetTransaction(tx.vin[2].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.2 is CC marker for gatewaysclaim or invalid marker amount!");
else if (tx.vin.size()>2)
{
i=1;
while (i<=tx.vin.size()-2)
{
if (IsCCInput(tx.vin[i].scriptSig)==0) return eval->Invalid("vin."+std::to_string(i)+" is CC for gatewaysclaim!");
i++;
}
}
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewaysclaim or invalid marker amount!");
else if (_GetCCaddress(destaddr,EVAL_TOKENS,pubkey)==0 || ConstrainVout(tx.vout[0],1,destaddr,amount)==0)
return eval->Invalid("invalid vout tokens to destpub for gatewaysclaim!");
else if (numvouts>2 && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || ConstrainVout(tx.vout[1],1,gatewaystokensaddr,tmptx.vout[tx.vin[1].prevout.n].nValue-amount)==0))
else if (numvouts>2 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || ConstrainVout(tx.vout[1],1,gatewaystokensaddr,tmptx.vout[tx.vin[1].prevout.n].nValue-amount)==0))
return eval->Invalid("invalid CC change vout for gatewaysclaim!");
else if (amount!=tmpamount)
return eval->Invalid("claimed amount different then deposit amount");
else if (tx.vout[0].nValue!=amount)
return eval->Invalid("claim amount not matching amount in opret");
return eval->Invalid("claimed amount different then deposit amount");
else if (pubkey!=tmppubkey)
return eval->Invalid("claim destination pubkey different than in deposit tx");
else
@@ -695,14 +698,10 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("refcoin different than in bind tx");
else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for gatewaysWithdraw!");
else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 )
return eval->Invalid("vin.1 is CC for gatewaysWithdraw!");
else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0)
return eval->Invalid("invalid marker vout for gatewaysWithdraw!");
else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0)
return eval->Invalid("invalid tokens to gateways vout for gatewaysWithdraw!");
else if (tmptx.vout[1].nValue!=amount)
return eval->Invalid("amount in opret not matching tx tokens amount!");
else if (komodo_txnotarizedconfirmed(withdrawtxid) == false)
return eval->Invalid("gatewayswithdraw tx is not yet confirmed(notarised)!");
else if (myGetTransaction(bindtxid,tmptx,hashblock) == 0)
@@ -717,8 +716,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
return eval->Invalid("vin.0 is normal for gatewayspartialsign!");
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.1 is CC marker for gatewayspartialsign or invalid marker amount!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewayspartialsign or invalid marker amount!");
else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 )
return eval->Invalid("vout.0 invalid marker for gatewayspartialsign!");
else if (K>M)
@@ -739,8 +738,6 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("refcoin different than in bind tx");
else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for gatewaysWithdraw!");
else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 )
return eval->Invalid("vin.1 is CC for gatewaysWithdraw!");
else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0)
return eval->Invalid("invalid marker vout for gatewaysWithdraw!");
else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0)
@@ -761,8 +758,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
return eval->Invalid("vin.0 is normal for gatewayscompletesigning!");
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.1 is CC marker for gatewayscompletesigning or invalid marker amount!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewayscompletesigning or invalid marker amount!");
else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 )
return eval->Invalid("vout.0 invalid marker for gatewayscompletesigning!");
else if (K<M)
@@ -800,8 +797,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for gatewaysmarkdone!");
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin.1 is CC marker for gatewaysmarkdone or invalid marker amount!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewaysmarkdone or invalid marker amount!");
else if (K<M)
return eval->Invalid("invalid number of signs!");
break;
@@ -959,7 +956,7 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0 )
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2) > 0 )
{
if (AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, totalsupply, 64)>0)
{
@@ -1038,7 +1035,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,4) > 0 )
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,3) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,destpub));
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG));
@@ -1110,7 +1107,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{
if ((inputs=AddGatewaysInputs(cp, mtx, gatewayspk, bindtxid, amount, 60)) > 0)
{
@@ -1188,7 +1185,7 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
}
}
}
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 4) > 0 )
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 2) > 0 )
{
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, amount, 60)) > 0)
{
@@ -1300,7 +1297,7 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
return("");
}
}
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
{
mtx.vin.push_back(CTxIn(tx.GetHash(),0,CScript()));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
@@ -1399,7 +1396,7 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
return("");
}
}
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
{
mtx.vin.push_back(CTxIn(lasttxid,0,CScript()));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
@@ -1464,7 +1461,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
{
mtx.vin.push_back(CTxIn(completetxid,0,CScript()));
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));

65
src/cc/hempcoin_notes.txt Normal file
View File

@@ -0,0 +1,65 @@
How this works:
- earlytxid must be a transaction included in the chain before block 100. The chain MUST not have any other of these type of tx before block 100, or someone may be able to change it and mess things up.
- When it gets to block 100, it takes the txid specified by the -earlytxid param (does not affect magic)
- Looks up the transaction searches for the opreturn, then permenantly appends it to the end of ac_script in RAM.
- After every daemon restart, the first time the daemon mines a block, or receives a block that pays ac_script it will look up the op_return and save it again.
- this enables it to always reach consensus but doesnt need to constantly keep looking up the tx in the chain.
- The trick is to use ac_founders=101 or higher so that nothing is ever paid to the unspendable CC address. Although it should still work without this it burns coins.
-ac_script can be any Global CC address you can spend to with an OP_RETURN. Here we use example of paymentsCC being used to fund a rewards plan, and a set of founders address's.
you can get the ac_script from another chain, but the op_return payload must generated on the chain itself. this command gives you the needed info to get the scripPubKey Hex:
./komodo-cli -ac_name=TEST paymentsfund '["5d536f54332db09f2be04593c54f764cf569e225f4d8df5155658c679e663682",1000]'
append: b8, to the end of ac_script, this changes magic value for -earlytxid chains vs normal ac_script and allows bypass of ac_supply paid to the scritpt as it would be unspendable and you would be unable to create the needed plans with no coins.
-ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8
-testnode=1 is not affecting magic and allows mining on a single node, we can use this to bootstrap the chain before syncing a second node to save time.
start chain and make sure to do the following steps before block 100 (set generate false/true is a good idea between steps)
./komodod -ac_name=TESTHC -ac_supply=1000000 -ac_reward=100000000000 -ac_cc=2 -ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8 -ac_founders=150 -ac_blocktime=20 -ac_nk=96,5 -testnode=1
create rewards plan and fund it with all or a % of the premine. Must be some amount. eg.
./komodo-cli -ac_name=TESTHC rewardscreatefunding test 50000 25 0 2 500
do rewards add funding:
./komodo-cli -ac_name=TESTHC rewardsaddfunding test 47a3150150bd196bd2086cae5e0c6b01a23785a04139fa660d169121a534b38e 1000
and get the script pubkey and op_return from this tx (no need to send it)
./komodo-cli -ac_name=TESTHC decoderawtransaction 010000000204ca4c7aaae62bb8fc9412ac010e047fa8d33c3f87d2adeb3e02170642ddfe370000000049483045022100d7b9a
4f28ca3a35f34dcdb6075e905cde1eaa962bd0619d0a8ed8e17e952bc99022077308e12325fc2a02c752ec3df9aeee1fc219ea54a4d3884834582b75c89815e01ffffffff08800132da3233d80c65e87b6db6a76dcf
188e4fdfa23198d69f647e67754cfb0000000049483045022100d6a8f7a1c4f6013f5897768ae0117fe61dfb72352d3e6652e64a6588db3ffcb102202aa1d041b24f9cbbf7028295b7c5e7f18b4f95ae39c13031dab
7f06634438e6801ffffffff0300e8764817000000302ea22c802065686d47a4049c2c845a71895a915eb84c04445896eec5dc0be40df0b31372da8103120c008203000401ccf0c0764817000000232103bbec93af84
0933ae2d35fc56eff24f34dbe26871402552f84c44f690945ccd79ac00000000000000002c6a2ae54174657374000000008eb334a52191160d66fa3941a08537a2016b0c5eae6c08d26b19bd500115a34700000000
From the return of this you need the scriptpubkey hex of vout 0:
scriptPubKey: 2ea22c802065686d47a4049c2c845a71895a915eb84c04445896eec5dc0be40df0b31372da8103120c008203000401cc
and the scriptpubkey hex of the OP_RETURN in vout 2.
OP_RETURN: 6a2ae54174657374000000008eb334a52191160d66fa3941a08537a2016b0c5eae6c08d26b19bd500115a347
create txidopreturn for this payment:
./komodo-cli -ac_name=TESTHC paymentstxidopret '[50,"2ea22c802065686d47a4049c2c845a71895a915eb84c04445896eec5dc0be40df0b31372da8103120c008203000401cc","6a2ae54174657374000000008eb334a52191160d66fa3941a08537a2016b0c5eae6c08d26b19bd500115a347"]'
create the txidopret for the founders reward(s) pubkeys: should be able to be a few here, not sure of max number yet. These can pay anything that does not need an opreturn. allocation and scriptpubkey hex.
./komodo-cli -ac_name=TESTHC paymentstxidopret '[50,"76a9146bf5dd9f679c87a3f83ea176f82148d26653c04388ac"]'
create payments plan:
./komodo-cli -ac_name=TESTHC paymentscreate '[0,0,"61f55f2f87dad3a37d42731a8cb73b3ebea1817abfa176218162c360a8bd7145","0550014823ffa0aa99d7dd7ca5292f4dd0a1b9156eddec03412c953f095181bc"]'
gives plan txid: ee7765be874fb084c00538b1b0488e8ecb857de253f09a9ba6ea8d3579b77d33
paymentsfund:
To do this you first need to change the type of tx generated by paymentsfund RPC. in payments.cpp go to line: 639 and comment it out, then uncomment the block of code under this.
change the line 646 to line 647 with comments, and line 650/651 aswell. This enables the RPC to generate the ccvout opreturn payload you need without sending the payment on the chain. Just decode the raw hex.
./komodo-cli -ac_name=TESTHC paymentsfund '["ee7765be874fb084c00538b1b0488e8ecb857de253f09a9ba6ea8d3579b77d33",1000,1]'
get the payment fund scriptpubkey hex from vout 0: (the split it at OP_CHECKCRYPTOCONDITION or 'cc' )
2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401cc 2a0401f00101246a22f046337db779358deaa69b9af053e27d85cb8e8e48b0b13805c084b04f87be6577ee75
put the second half into an OP_RETURN: (the remaining part of the the above scriptpubkey) eg.
./komodo-cli -ac_name=TESTHC opreturn_burn 1 2a0401f00101246a22f046337db779358deaa69b9af053e27d85cb8e8e48b0b13805c084b04f87be6577ee75
opret_burn takes any burn amount and arbitrary hex string. (RPC works, but may have bugs, likely use this for LABS too with some fixes)
this gives a raw hex. Decode it and check the OP_RETURN is right before sending.
-earlytxid=810bd62fb8353fad20267ff2050684b8829affa3edf6b366633931530791dfce
restart the chain with earlytxid param before height 100 on all nodes (if not using -testnode=1)
./komodod -ac_name=TESTHC -ac_supply=1000000 -ac_reward=100000000000 -ac_cc=2 -ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8 -ac_founders=150 -ac_blocktime=20 -ac_nk=96,5 -earlytxid=810bd62fb8353fad20267ff2050684b8829affa3edf6b366633931530791dfce
once the payments plan has been funded with the mined coinbase you can issue payments release when conditions of the plan are met to fund founders reward/rewards plan. eg.
./komodo-cli -ac_name=TESTHC paymentsrelease '["ee7765be874fb084c00538b1b0488e8ecb857de253f09a9ba6ea8d3579b77d33",500]'

View File

@@ -20,47 +20,35 @@
#include "primitives/transaction.h"
#include "cc/CCinclude.h"
#include <openssl/sha.h>
#include "cc/CCtokens.h"
#include "key_io.h"
#define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA"
/*
* CC Eval method for import coin.
*
* This method should control every parameter of the ImportCoin transaction, since it has no signature
* to protect it from malleability.
##### 0xffffffff is a special CCid for single chain/dual daemon imports
*/
extern std::string ASSETCHAINS_SELFIMPORT;
extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT;
extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
extern uint256 KOMODO_EARLYTXID;
// utilities from gateways.cpp
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);
uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid);
int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid);
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype);
uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype);
int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vector<uint8_t>proof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2);
char *nonportable_path(char *str);
char *portable_path(char *str);
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep);
void *filestr(long *allocsizep,char *_fname);
// ac_import=chain support:
// encode opret for gateways import
CScript EncodeImportTxOpRet(uint32_t targetCCid, std::string coin, std::vector<CPubKey> publishers, std::vector<uint256>txids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vector<uint8_t>proof, CPubKey destpub, int64_t amount)
{
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << coin << publishers << txids << height << cointxid << claimvout << rawburntx << proof << destpub << amount);
return(opret);
}
CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint256 bindtxid, std::vector<CPubKey> publishers, std::vector<uint256>txids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vector<uint8_t>proof, CPubKey destpub, int64_t amount)
{
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << coin << bindtxid << publishers << txids << height << cointxid << claimvout << rawburntx << proof << destpub << amount);
return(opret);
}
CScript EncodeCodaImportTxOpRet(uint32_t targetCCid, std::string coin, std::string burntx, uint256 bindtxid, CPubKey destpub, int64_t amount)
{
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << burntx << bindtxid << destpub << amount);
return(opret);
}
cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5)
{
char cmdstr[5000],fname[256],*jsonstr;
@@ -81,165 +69,66 @@ cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,
return(retjson);
}
bool ImportCoinGatewaysVerify(CTransaction oracletx, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vector<uint8_t>proof, uint256 merkleroot)
{
std::vector<uint256> txids;
uint256 proofroot;
std::string name, description, format;
int32_t i, numvouts;
if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey, name, description, format) != 'C' || name != refcoin)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify mismatched oracle name=" << name.c_str() << " != " << refcoin.c_str() << std::endl);
return false;
}
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in trusted merkleroot" << std::endl);
return true;
}
// make import tx with burntx and its proof of existence
// std::string MakeGatewaysImportTx(uint64_t txfee, uint256 oracletxid, int32_t height, std::string refcoin, std::vector<uint8_t> proof, std::string rawburntx, int32_t ivout, uint256 burntxid,std::string destaddr)
// {
// CMutableTransaction burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
// CTransaction oracletx,regtx; CPubKey regpk;
// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts;
// std::string name,desc,format; std::vector<CTxOut> vouts;
// std::vector<CPubKey> pubkeys; std::vector<uint256>txids;
// char markeraddr[64]; int64_t datafee;
// std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
// if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx))
// return std::string("");
// CAmount amount = GetCoinImportValue(burntx); // equal to int64_t
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx height=" << height << " coin=" << refcoin << " amount=" << (double)amount / COIN << " pubkeys num=" << pubkeys.size() << std::endl);
// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx cant find oracletxid=" << oracletxid.GetHex() << std::endl);
// return("");
// }
// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
// return("");
// }
// if (name!=refcoin || format!="Ihh")
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
// return("");
// }
// CCtxidaddr(markeraddr,oracletxid);
// SetCCunspents(unspentOutputs,markeraddr,true);
// for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
// {
// txid = it->first.txhash;
// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
// {
// pubkeys.push_back(regpk);
// n++;
// }
// }
// merkleroot = zeroid;
// for (i = m = 0; i < n; i++)
// {
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx using pubkeys[" << i << "]=" << HexStr(pubkeys[i]) << std::endl);
// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
// {
// if (merkleroot == zeroid)
// merkleroot = mhash, m = 1;
// else if (mhash == merkleroot)
// m ++;
// txids.push_back(txid);
// }
// }
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " nodes m=" << m << " of n=" << n << std::endl);
// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
// return("");
// }
// proofroot = BitcoinGetProofMerkleRoot(proof, txids);
// if (proofroot != merkleroot)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
// return("");
// }
// // check the burntxid is in the proof:
// if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid proof for this burntxid=" << burntxid.GetHex() << std::endl);
// return("");
// }
// burntx.vout.push_back(MakeBurnOutput(amount,0xffffffff,refcoin,vouts,proof,oracletxid,height));
// std::vector<uint256> leaftxids;
// BitcoinGetProofMerkleRoot(proof, leaftxids);
// MerkleBranch newBranch(0, leaftxids);
// TxProof txProof = std::make_pair(burntxid, newBranch);
// CTxDestination dest = DecodeDestination(destaddr.c_str());
// CScript scriptPubKey = GetScriptForDestination(dest);
// vouts.push_back(CTxOut(amount,scriptPubKey));
// return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts)));
// }
// makes source tx for self import tx
std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx)
CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount)
{
const int64_t txfee = 10000;
int64_t inputs, change;
CPubKey myPubKey = Mypubkey();
struct CCcontract_info *cpDummy, C;
cpDummy = CCinit(&C, EVAL_TOKENS);
cpDummy = CCinit(&C, EVAL_TOKENS); // this is just for FinalizeCCTx to work
mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
if( (inputs = AddNormalinputs(mtx, myPubKey, txfee, 4)) == 0 ) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeSelfImportSourceTx: cannot find normal imputs for txfee" << std::endl);
return std::string("");
if (AddNormalinputs(mtx, myPubKey, 2 * txfee, 4) == 0) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeSelfImportSourceTx() warning: cannot find normal inputs for txfee" << std::endl);
}
CScript scriptPubKey = GetScriptForDestination(dest);
mtx.vout.push_back(CTxOut(txfee, scriptPubKey));
change = inputs - txfee;
if( change != 0 )
mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(myPubKey)) << OP_CHECKSIG));
//make opret with amount:
return FinalizeCCTx(0, cpDummy, mtx, myPubKey, txfee, CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN << (uint8_t)'A' << amount));
//make opret with 'burned' amount:
FinalizeCCTx(0, cpDummy, mtx, myPubKey, txfee, CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN << (uint8_t)'A' << amount));
return mtx;
}
// make sure vin0 is signed by ASSETCHAINS_OVERRIDE_PUBKEY33
int32_t CheckVin0PubKey(const CTransaction &sourcetx)
// make sure vin is signed by pubkey33
bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33])
{
CTransaction vintx;
uint256 blockHash;
char destaddr[64], pkaddr[64];
if( !myGetTransaction(sourcetx.vin[0].prevout.hash, vintx, blockHash) ) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVin0PubKey() could not load vintx" << sourcetx.vin[0].prevout.hash.GetHex() << std::endl);
return(-1);
if (i < 0 || i >= sourcetx.vin.size())
return false;
if( !myGetTransaction(sourcetx.vin[i].prevout.hash, vintx, blockHash) ) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() could not load vintx" << sourcetx.vin[i].prevout.hash.GetHex() << std::endl);
return false;
}
if( sourcetx.vin[0].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr, vintx.vout[sourcetx.vin[0].prevout.n].scriptPubKey) != 0 )
if( sourcetx.vin[i].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr, vintx.vout[sourcetx.vin[i].prevout.n].scriptPubKey) != 0 )
{
pubkey2addr(pkaddr, ASSETCHAINS_OVERRIDE_PUBKEY33);
pubkey2addr(pkaddr, pubkey33);
if (strcmp(pkaddr, destaddr) == 0) {
return(0);
return true;
}
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVin0PubKey() mismatched vin0[prevout.n=" << sourcetx.vin[0].prevout.n << "] -> destaddr=" << destaddr << " vs pkaddr=" << pkaddr << std::endl);
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() mismatched vin[" << i << "].prevout.n=" << sourcetx.vin[i].prevout.n << " -> destaddr=" << destaddr << " vs pkaddr=" << pkaddr << std::endl);
}
return -1;
return false;
}
// ac_import=PUBKEY support:
// prepare a tx for creating import tx and quasi-burn tx
int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount) // find burnTx with hash from "other" daemon
int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull) // find burnTx with hash from "other" daemon
{
MerkleBranch newBranch;
CMutableTransaction tmpmtx;
CTransaction sourcetx;
//CTransaction sourcetx;
tmpmtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
/*
if (!E_UNMARSHAL(ParseHex(rawsourcetx), ss >> sourcetx)) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: could not unmarshal source tx" << std::endl);
return(-1);
@@ -248,9 +137,9 @@ int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript
if (sourcetx.vout.size() == 0) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: vout size is 0" << std::endl);
return -1;
}
} */
if (ivout < 0) { // "ivout < 0" means "find"
/*if (ivout < 0) { // "ivout < 0" means "find"
// try to find vout
CPubKey myPubkey = Mypubkey();
ivout = 0;
@@ -262,38 +151,49 @@ int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript
if (ivout >= sourcetx.vout.size()) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: needed vout not found" << std::endl);
return -1;
}
} */
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "GetSelfimportProof: using vout[" << ivout << "] of the passed rawtx" << std::endl);
int32_t ivout = 0;
scriptPubKey = sourcetx.vout[ivout].scriptPubKey;
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "GetSelfimportProof: using vout[" << ivout << "] of the passed rawtx" << std::endl);
CScript scriptPubKey = sourceMtx.vout[ivout].scriptPubKey;
//mtx is template for import tx
mtx = sourcetx;
mtx.fOverwintered = tmpmtx.fOverwintered;
templateMtx = sourceMtx;
templateMtx.fOverwintered = tmpmtx.fOverwintered;
//malleability fix for burn tx:
//mtx.nExpiryHeight = tmpmtx.nExpiryHeight;
mtx.nExpiryHeight = sourcetx.nExpiryHeight;
templateMtx.nExpiryHeight = sourceMtx.nExpiryHeight;
mtx.nVersionGroupId = tmpmtx.nVersionGroupId;
mtx.nVersion = tmpmtx.nVersion;
mtx.vout.clear();
mtx.vout.resize(1);
mtx.vout[0].nValue = burnAmount;
mtx.vout[0].scriptPubKey = scriptPubKey;
templateMtx.nVersionGroupId = tmpmtx.nVersionGroupId;
templateMtx.nVersion = tmpmtx.nVersion;
templateMtx.vout.clear();
templateMtx.vout.resize(1);
// not sure we need this now as we create sourcetx ourselves:
if (sourcetx.GetHash() != sourcetxid) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: passed source txid incorrect" << std::endl);
return(-1);
}
// check ac_pubkey:
if (CheckVin0PubKey(sourcetx) < 0) {
uint8_t evalCode, funcId;
int64_t burnAmount;
vscript_t vopret;
if( !GetOpReturnData(sourceMtx.vout.back().scriptPubKey, vopret) ||
!E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> burnAmount)) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof() could not unmarshal source tx opret" << std::endl);
return -1;
}
proof = std::make_pair(sourcetxid, newBranch);
templateMtx.vout[0].nValue = burnAmount;
templateMtx.vout[0].scriptPubKey = scriptPubKey;
// not sure we need this now as we create sourcetx ourselves:
/*if (sourcetx.GetHash() != sourcetxid) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: passed source txid incorrect" << std::endl);
return(-1);
}*/
// check ac_pubkey:
if (!CheckVinPubKey(sourceMtx, 0, ASSETCHAINS_OVERRIDE_PUBKEY33)) {
return -1;
}
proofNull = ImportProof(std::make_pair(sourceMtx.GetHash(), newBranch));
return 0;
}
@@ -452,71 +352,123 @@ int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector<CT
}
int32_t CheckGATEWAYimport(CTransaction importTx,CTransaction burnTx,std::string refcoin,std::vector<uint8_t> proof,
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub)
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount)
{
// CTransaction oracletx,regtx; CPubKey regpk;
// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts;
// std::string name,desc,format; std::vector<CTxOut> vouts;
// std::vector<CPubKey> pubkeys; std::vector<uint256>txids;
// char markeraddr[64]; int64_t datafee;
// std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CTransaction oracletx,bindtx,regtx; int32_t i,m,n=0,numvouts; uint8_t M,N,taddr,prefix,prefix2,wiftype;
uint256 txid,oracletxid,tmporacletxid,merkleroot,mhash,hashBlock;
std::string name,desc,format,coin; std::vector<CTxOut> vouts; CPubKey regpk;
std::vector<CPubKey> pubkeys,tmppubkeys,tmppublishers; char markeraddr[64],deposit[64],destaddr[64],tmpdest[64]; int64_t datafee;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
// ASSETCHAINS_SELFIMPORT is coin
if (KOMODO_EARLYTXID!=zeroid && bindtxid!=KOMODO_EARLYTXID)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid import gateway. On this chain only valid import gateway is " << KOMODO_EARLYTXID.GetHex() << std::endl);
return(-1);
}
// check for valid burn from external coin blockchain and if valid return(0);
// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl);
// return(-1);
// }
// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
// return(-1);
// }
// if (name!=refcoin || format!="Ihh")
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
// return(-1);
// }
// CCtxidaddr(markeraddr,oracletxid);
// SetCCunspents(unspentOutputs,markeraddr,true);
// for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
// {
// txid = it->first.txhash;
// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
// {
// pubkeys.push_back(regpk);
// n++;
// }
// }
// merkleroot = zeroid;
// for (i = m = 0; i < n; i++)
// {
// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
// {
// if (merkleroot == zeroid)
// merkleroot = mhash, m = 1;
// else if (mhash == merkleroot)
// m ++;
// txids.push_back(txid);
// }
// }
// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
// return(-1);
// }
// proofroot = BitcoinGetProofMerkleRoot(proof, txids);
// if (proofroot != merkleroot)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
// return(-1);
// }
// // check the burntxid is in the proof:
// if (std::find(txids.begin(), txids.end(), burnTx.GetHash()) == txids.end()) {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid proof for this burntxid=" << burnTx.GetHash().GetHex() << std::endl);
// return(-1);
// }
if (GetTransaction(bindtxid, bindtx, hashBlock, false) == 0 || (numvouts = bindtx.vout.size()) <= 0)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport cant find bindtxid=" << bindtxid.GetHex() << std::endl);
return(-1);
}
else if (DecodeImportGatewayBindOpRet(deposit,bindtx.vout[numvouts - 1].scriptPubKey,coin,oracletxid,M,N,tmppubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid bind tx. bindtxid=" << bindtxid.GetHex() << std::endl);
return(-1);
}
else if (refcoin!=coin)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid coin " << refcoin << "!=" << coin << std::endl);
return(-1);
}
else if ( N == 0 || N > 15 || M > N )
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid N or M " << std::endl);
return(-1);
}
else if (tmppubkeys.size()!=N)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport not enough pubkeys for given N " << std::endl);
return(-1);
}
else if (komodo_txnotarizedconfirmed(bindtxid) == false)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport bindtx not yet confirmed/notarized" << std::endl);
return(-1);
}
else if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl);
return(-1);
}
else if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
return(-1);
}
else if (name!=refcoin || format!="Ihh")
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
return(-1);
}
CCtxidaddr(markeraddr,oracletxid);
SetCCunspents(unspentOutputs,markeraddr,false);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
&& DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
{
pubkeys.push_back(regpk);
n++;
}
}
if (pubkeys.size()!=tmppubkeys.size())
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport different number of bind and oracle pubkeys " << tmppubkeys.size() << "!=" << pubkeys.size() << std::endl);
return(-1);
}
merkleroot = zeroid;
for (i = m = 0; i < n; i++)
{
if ((mhash = CCOraclesReverseScan("importgateway-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
{
if (merkleroot == zeroid)
merkleroot = mhash, m = 1;
else if (mhash == merkleroot)
m ++;
tmppublishers.push_back(pubkeys[i]);
}
}
if (publishers.size()!=tmppublishers.size())
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport different number of publishers for burtx in oracle" << std::endl);
return(-1);
}
else if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
return(-1);
}
else if ( ImportGatewayVerify(deposit,oracletxid,burnvout,refcoin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount )
{
CCerror = strprintf("burntxid didnt validate !");
LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl);
return(-1);
}
else if (importTx.vout[0].nValue!=amount)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport import amount different than in burntx" << std::endl);
return(-1);
}
Getscriptaddress(destaddr,importTx.vout[0].scriptPubKey);
Getscriptaddress(tmpdest,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
if (strcmp(destaddr,tmpdest)!=0)
{
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport import coins destination different than in burntx" << std::endl);
return(-1);
}
return(0);
}
@@ -545,7 +497,7 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransacti
}
//ac_pubkey check:
if (CheckVin0PubKey(sourcetx) < 0) {
if (!CheckVinPubKey(sourcetx, 0, ASSETCHAINS_OVERRIDE_PUBKEY33)) {
return -1;
}
@@ -554,9 +506,11 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransacti
uint8_t evalCode, funcId;
int64_t amount;
GetOpReturnData(sourcetx.vout.back().scriptPubKey, vopret);
if (vopret.size() == 0 || !E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> amount) || evalCode != EVAL_IMPORTCOIN || funcId != 'A') {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "no or incorrect opret to validate in source txid=" << sourcetxid.GetHex() << std::endl);
if (!GetOpReturnData(sourcetx.vout.back().scriptPubKey, vopret) ||
vopret.size() == 0 ||
!E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> amount) ||
evalCode != EVAL_IMPORTCOIN || funcId != 'A') {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "none or incorrect opret to validate in source txid=" << sourcetxid.GetHex() << std::endl);
return -1;
}
@@ -571,21 +525,156 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransacti
return(0);
}
/*
* CC Eval method for import coin.
*
* This method should control every parameter of the ImportCoin transaction, since it has no signature
* to protect it from malleability.
##### 0xffffffff is a special CCid for single chain/dual daemon imports
*/
bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &importTx,unsigned int nIn)
bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction &burnTx, std::vector<CTxOut> & payouts, const ImportProof &proof, const std::vector<uint8_t> &rawproof)
{
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; uint64_t txfee = 10000; int32_t height,burnvout; std::vector<CPubKey> publishers;
uint32_t targetCcid; std::string targetSymbol,srcaddr,destaddr,receipt,rawburntx; uint256 payoutsHash,bindtxid; std::vector<uint8_t> rawproof;
std::vector<uint256> txids; CPubKey destpub;
vscript_t vimportOpret;
if (!GetOpReturnData(importTx.vout.back().scriptPubKey, vimportOpret) ||
vimportOpret.empty())
return eval->Invalid("invalid-import-tx-no-opret");
if ( importTx.vout.size() < 2 )
uint256 tokenid = zeroid;
if (vimportOpret.begin()[0] == EVAL_TOKENS) { // for tokens (new opret with tokens)
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 1 )
return eval->Invalid("no-tokens-migrate-on-LABS");
struct CCcontract_info *cpTokens, CCtokens_info;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
uint8_t evalCodeInOpret;
std::vector<CPubKey> voutTokenPubkeys;
vscript_t vnonfungibleOpret;
cpTokens = CCinit(&CCtokens_info, EVAL_TOKENS);
if (DecodeTokenOpRet(importTx.vout.back().scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets) == 0)
return eval->Invalid("cannot-decode-import-tx-token-opret");
uint8_t nonfungibleEvalCode = EVAL_TOKENS; // init to no non-fungibles
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vnonfungibleOpret);
if (!vnonfungibleOpret.empty())
nonfungibleEvalCode = vnonfungibleOpret.begin()[0];
// check if burn tx at least has cc evaltoken vins (we cannot get cc input)
bool hasTokenVin = false;
for (auto vin : burnTx.vin)
if (cpTokens->ismyvin(vin.scriptSig))
hasTokenVin = true;
if (!hasTokenVin)
return eval->Invalid("burn-tx-has-no-token-vins");
// calc outputs for burn tx
CAmount ccBurnOutputs = 0;
for (auto v : burnTx.vout)
if (v.scriptPubKey.IsPayToCryptoCondition() &&
CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey
ccBurnOutputs += v.nValue;
// calc outputs for import tx
CAmount ccImportOutputs = 0;
for (auto v : importTx.vout)
if (v.scriptPubKey.IsPayToCryptoCondition() &&
!IsTokenMarkerVout(v)) // should not be marker here
ccImportOutputs += v.nValue;
if (ccBurnOutputs != ccImportOutputs)
return eval->Invalid("token-cc-burned-output-not-equal-cc-imported-output");
}
else if (vimportOpret.begin()[0] != EVAL_IMPORTCOIN) {
return eval->Invalid("import-tx-incorrect-opret-eval");
}
// for tokens check burn, import, tokenbase tx
if (!tokenid.IsNull()) {
std::string sourceSymbol;
CTransaction tokenbaseTx;
if (!E_UNMARSHAL(rawproof, ss >> sourceSymbol; ss >> tokenbaseTx))
return eval->Invalid("cannot-unmarshal-rawproof-for-tokens");
uint256 sourceTokenId;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
uint8_t evalCodeInOpret;
std::vector<CPubKey> voutTokenPubkeys;
if (burnTx.vout.size() > 0 && DecodeTokenOpRet(burnTx.vout.back().scriptPubKey, evalCodeInOpret, sourceTokenId, voutTokenPubkeys, oprets) == 0)
return eval->Invalid("cannot-decode-burn-tx-token-opret");
if (sourceTokenId != tokenbaseTx.GetHash()) // check tokenid in burn tx opret maches the passed tokenbase tx (to prevent cheating by importing user)
return eval->Invalid("incorrect-token-creation-tx-passed");
std::vector<std::pair<uint8_t, vscript_t>> opretsSrc;
vscript_t vorigpubkeySrc;
std::string nameSrc, descSrc;
if (DecodeTokenCreateOpRet(tokenbaseTx.vout.back().scriptPubKey, vorigpubkeySrc, nameSrc, descSrc, opretsSrc) == 0)
return eval->Invalid("cannot-decode-token-creation-tx");
std::vector<std::pair<uint8_t, vscript_t>> opretsImport;
vscript_t vorigpubkeyImport;
std::string nameImport, descImport;
if (importTx.vout.size() == 0 || DecodeTokenCreateOpRet(importTx.vout.back().scriptPubKey, vorigpubkeySrc, nameSrc, descSrc, opretsImport) == 0)
return eval->Invalid("cannot-decode-token-import-tx");
// check that name,pubkey,description in import tx correspond ones in token creation tx in the source chain:
if (vorigpubkeySrc != vorigpubkeyImport ||
nameSrc != nameImport ||
descSrc != descImport)
return eval->Invalid("import-tx-token-params-incorrect");
}
// Check burntx shows correct outputs hash
// if (payoutsHash != SerializeHash(payouts)) // done in ImportCoin
// return eval->Invalid("wrong-payouts");
TxProof merkleBranchProof;
std::vector<uint256> notaryTxids;
// Check proof confirms existance of burnTx
if (proof.IsMerkleBranch(merkleBranchProof)) {
uint256 target = merkleBranchProof.second.Exec(burnTx.GetHash());
LOGSTREAM("importcoin", CCLOG_DEBUG2, stream << "Eval::ImportCoin() momom target=" << target.GetHex() << " merkleBranchProof.first=" << merkleBranchProof.first.GetHex() << std::endl);
if (!CheckMoMoM(merkleBranchProof.first, target)) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MoMoM check failed for importtx=" << importTx.GetHash().GetHex() << std::endl);
return eval->Invalid("momom-check-fail");
}
}
else if (proof.IsNotaryTxids(notaryTxids)) {
if (!CheckNotariesApproval(burnTx.GetHash(), notaryTxids)) {
return eval->Invalid("notaries-approval-check-fail");
}
}
else {
return eval->Invalid("invalid-import-proof");
}
/* if (vimportOpret.begin()[0] == EVAL_TOKENS)
return eval->Invalid("test-invalid-tokens-are-good!!");
else
return eval->Invalid("test-invalid-coins-are-good!!"); */
return true;
}
bool Eval::ImportCoin(const std::vector<uint8_t> params, const CTransaction &importTx, unsigned int nIn)
{
ImportProof proof;
CTransaction burnTx;
std::vector<CTxOut> payouts;
CAmount txfee = 10000, amount;
int32_t height, burnvout;
std::vector<CPubKey> publishers;
uint32_t targetCcid;
std::string targetSymbol, srcaddr, destaddr, receipt, rawburntx;
uint256 payoutsHash, bindtxid, burntxid;
std::vector<uint8_t> rawproof;
std::vector<uint256> txids;
CPubKey destpub;
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "Validating import tx..., txid=" << importTx.GetHash().GetHex() << std::endl);
if (strcmp(ASSETCHAINS_SYMBOL, "CFEKDIMXY6") == 0 && chainActive.Height() <= 44693)
return true;
if (importTx.vout.size() < 2)
return Invalid("too-few-vouts");
// params
if (!UnmarshalImportTx(importTx, proof, burnTx, payouts))
@@ -597,38 +686,47 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
// burn params
if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash, rawproof))
return Invalid("invalid-burn-tx");
// check burn amount
{
uint64_t burnAmount = burnTx.vout.back().nValue;
if (burnAmount == 0)
return Invalid("invalid-burn-amount");
uint64_t totalOut = 0;
for (int i=0; i<importTx.vout.size(); i++)
totalOut += importTx.vout[i].nValue;
if (totalOut > burnAmount || totalOut < burnAmount-txfee )
return Invalid("payout-too-high-or-too-low");
}
if (burnTx.vout.size() == 0)
return Invalid("invalid-burn-tx-no-vouts");
// check burned normal amount >= import amount && burned amount <= import amount + txfee (extra txfee is for miners and relaying, see GetImportCoinValue() func)
CAmount burnAmount = burnTx.vout.back().nValue;
if (burnAmount == 0)
return Invalid("invalid-burn-amount");
CAmount totalOut = 0;
for (auto v : importTx.vout)
if (!v.scriptPubKey.IsPayToCryptoCondition())
totalOut += v.nValue;
if (totalOut > burnAmount || totalOut < burnAmount - txfee)
return Invalid("payout-too-high-or-too-low");
// Check burntx shows correct outputs hash
if (payoutsHash != SerializeHash(payouts))
return Invalid("wrong-payouts");
if (targetCcid < KOMODO_FIRSTFUNGIBLEID)
return Invalid("chain-not-fungible");
// Check proof confirms existance of burnTx
if ( targetCcid != 0xffffffff )
{
if ( targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol() )
if (targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol())
return Invalid("importcoin-wrong-chain");
uint256 target = proof.second.Exec(burnTx.GetHash());
if (!CheckMoMoM(proof.first, target))
return Invalid("momom-check-fail");
if (!CheckMigration(this, importTx, burnTx, payouts, proof, rawproof))
return false; // eval->Invalid() is called in the func
}
else
{
TxProof merkleBranchProof;
if (!proof.IsMerkleBranch(merkleBranchProof))
return Invalid("invalid-import-proof-for-0xFFFFFFFF");
if ( targetSymbol == "BEAM" )
{
if ( ASSETCHAINS_BEAMPORT == 0 )
return Invalid("BEAM-import-without-port");
else if ( CheckBEAMimport(proof,rawproof,burnTx,payouts) < 0 )
else if ( CheckBEAMimport(merkleBranchProof,rawproof,burnTx,payouts) < 0 )
return Invalid("BEAM-import-failure");
}
else if ( targetSymbol == "CODA" )
@@ -642,16 +740,20 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
{
if ( ASSETCHAINS_SELFIMPORT != "PUBKEY" )
return Invalid("PUBKEY-import-when-notPUBKEY");
else if ( CheckPUBKEYimport(proof,rawproof,burnTx,payouts) < 0 )
else if ( CheckPUBKEYimport(merkleBranchProof,rawproof,burnTx,payouts) < 0 )
return Invalid("PUBKEY-import-failure");
}
else
{
if ( targetSymbol != ASSETCHAINS_SELFIMPORT )
return Invalid("invalid-gateway-import-coin");
else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub) < 0 )
else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,burntxid,height,burnvout,rawburntx,destpub,amount)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,burntxid,height,burnvout,rawburntx,destpub,amount) < 0 )
return Invalid("GATEWAY-import-failure");
}
}
// return Invalid("test-invalid");
LOGSTREAM("importcoin", CCLOG_DEBUG2, stream << "Valid import tx! txid=" << importTx.GetHash().GetHex() << std::endl);
return Valid();
}

View File

@@ -25,6 +25,8 @@
#define KMD_TADDR 0
#define CC_MARKER_VALUE 10000
extern uint256 KOMODO_EARLYTXID;
CScript EncodeImportGatewayBindOpRet(uint8_t funcid,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> importgatewaypubkeys,uint8_t taddr,uint8_t prefix,uint8_t prefix2,uint8_t wiftype)
{
CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY;
@@ -212,7 +214,7 @@ int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvo
}
if (std::find(txids.begin(), txids.end(), burntxid) == txids.end())
{
LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify invalid proof for this burntxid" << std::endl);
LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify invalid proof for this burntxid " << burntxid.GetHex() << std::endl);
return 0;
}
if ( DecodeHexTx(tx,deposithex) != 0 )
@@ -557,13 +559,19 @@ std::string ImportGatewayBind(uint64_t txfee,std::string coin,uint256 oracletxid
return("");
}
std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t claimvout,std::string rawburntx,std::vector<uint8_t>proof,CPubKey destpub)
std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t claimvout,std::string rawburntx,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()), burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction bindtx; CPubKey mypk; uint256 oracletxid,merkleroot,mhash,hashBlock,txid; std::vector<CTxOut> vouts;
int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::string coin; struct CCcontract_info *cp,C;
std::vector<CPubKey> pubkeys,publishers; std::vector<uint256> txids; char str[128],burnaddr[64]; int64_t amount;
std::vector<CPubKey> pubkeys,publishers; std::vector<uint256> txids; char str[128],burnaddr[64];
if (KOMODO_EARLYTXID!=zeroid && bindtxid!=KOMODO_EARLYTXID)
{
CCerror = strprintf("CheckGATEWAYimport invalid import gateway. On this chain only valid import gateway is %s",KOMODO_EARLYTXID.GetHex());
LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
cp = CCinit(&C,EVAL_IMPORTGATEWAY);
if ( txfee == 0 )
txfee = 10000;
@@ -572,7 +580,6 @@ std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,
{
return std::string("");
}
amount=burntx.vout[0].nValue;
LOGSTREAM("importgateway",CCLOG_DEBUG1, stream << "ImportGatewayDeposit ht." << height << " " << refcoin << " " << (double)amount/COIN << " numpks." << (int32_t)pubkeys.size() << std::endl);
if ( GetTransaction(bindtxid,bindtx,hashBlock,false) == 0 || (numvouts= bindtx.vout.size()) <= 0 )
{
@@ -611,18 +618,18 @@ std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,
LOGSTREAM("importgateway",CCLOG_INFO, stream << "burntxid." << burntxid.GetHex() << " m." << m << " of n." << n << std::endl);
if ( merkleroot == zeroid || m < n/2 )
{
CCerror = strprintf("couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d",height,coin.c_str(),uint256_str(str,oracletxid),m,n);
CCerror = strprintf("couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d",height,refcoin.c_str(),uint256_str(str,oracletxid),m,n);
LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( ImportGatewayVerify(burnaddr,oracletxid,claimvout,coin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount )
if ( ImportGatewayVerify(burnaddr,oracletxid,claimvout,refcoin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount )
{
CCerror = strprintf("burntxid didnt validate!");
LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
vouts.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG));
burntx.vout.push_back(MakeBurnOutput((CAmount)amount,0xffffffff,refcoin,vouts,proof,bindtxid,publishers,txids,height,claimvout,rawburntx,destpub));
burntx.vout.push_back(MakeBurnOutput((CAmount)amount,0xffffffff,refcoin,vouts,proof,bindtxid,publishers,txids,burntxid,height,claimvout,rawburntx,destpub,amount));
std::vector<uint256> leaftxids;
BitcoinGetProofMerkleRoot(proof, leaftxids);
MerkleBranch newBranch(0, leaftxids);

View File

@@ -4,6 +4,8 @@ rm *.so rogue/rogue games/tetris games/prices
echo rogue
make -f Makefile_rogue
./makerogue
rm ../libcc.so
cp librogue.so ../libcc.so
echo sudoku/musig/dilithium
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp
@@ -16,4 +18,3 @@ echo games prices
echo customcc stub
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp

View File

@@ -1,7 +1,7 @@
#!/bin/sh
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp
cp customcc.so ../libcc.so
cd ..
make
cd cc
if make -f Makefile_custom "$@"; then
echo CUSTOMCC BUILD SUCCESSFUL
else
echo CUSTOMCC BUILD FAILED
exit 1
fi

View File

@@ -92,10 +92,11 @@
vout.n-1: opreturn with oracletxid, prevbatontxid and data in proper format
*/
extern int32_t komodo_currentheight();
#define PUBKEY_SPOOFING_FIX_ACTIVATION 1563148800
#define CC_MARKER_VALUE 10000
// start of consensus code
CScript EncodeOraclesCreateOpRet(uint8_t funcid,std::string name,std::string description,std::string format)
{
CScript opret; uint8_t evalcode = EVAL_ORACLES;
@@ -124,6 +125,7 @@ uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,s
CScript EncodeOraclesOpRet(uint8_t funcid,uint256 oracletxid,CPubKey pk,int64_t num)
{
CScript opret; uint8_t evalcode = EVAL_ORACLES;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << oracletxid << pk << num);
return(opret);
}
@@ -131,11 +133,12 @@ CScript EncodeOraclesOpRet(uint8_t funcid,uint256 oracletxid,CPubKey pk,int64_t
uint8_t DecodeOraclesOpRet(const CScript &scriptPubKey,uint256 &oracletxid,CPubKey &pk,int64_t &num)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey,vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && script[0] == EVAL_ORACLES )
{
if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0)
if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S' || script[1] == 'F') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0)
return(f);
else return(script[1]);
}
@@ -633,9 +636,21 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio
else return(true);
}
int32_t GetLatestTimestamp(int32_t height)
{
uint256 blockHash; CBlock block; CBlockIndex* pindex;
blockHash = chainActive[height]->GetBlockHash();
pindex = mapBlockIndex[blockHash];
return(pindex->nTime);
}
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{
uint256 txid,oracletxid,batontxid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; uint8_t *script; std::vector<uint8_t> vopret,data; CScript scriptPubKey; CPubKey publisher;
uint256 oracletxid,batontxid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; int64_t amount; uint256 hashblock;
uint8_t *script; std::vector<uint8_t> vopret,data; CPubKey publisher,tmppk,oraclespk; char tmpaddress[64],vinaddress[64],oraclesaddr[64];
CTransaction tmptx; std::string name,desc,format;
numvins = tx.vin.size();
numvouts = tx.vout.size();
preventCCvins = preventCCvouts = -1;
@@ -643,10 +658,11 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
return eval->Invalid("no vouts");
else
{
txid = tx.GetHash();
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
if ( vopret.size() > 2 )
{
{
oraclespk=GetUnspendable(cp,0);
Getscriptaddress(oraclesaddr,CScript() << ParseHex(HexStr(oraclespk)) << OP_CHECKSIG);
script = (uint8_t *)vopret.data();
switch ( script[1] )
{
@@ -657,13 +673,45 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
// vout.n-1: opreturn with name and description and format for data
return eval->Invalid("unexpected OraclesValidate for create");
break;
case 'R': // register
case 'F': // fund (activation on Jul 15th 2019 00:00)
// vins.*: normal inputs
// vout.0: txfee to oracle CC address of users pubkey
// vout.1: change, if any
// vout.n-1: opreturn with createtxid, pubkey and amount
return eval->Invalid("unexpected OraclesValidate for create");
break;
case 'R': // register
// vin.0: normal inputs
// vin.n-1: CC input from pubkeys oracle CC addres - to prove that register came from pubkey that is registred (activation on Jul 15th 2019 00:00)
// vout.0: txfee tag to normal marker address
// vout.1: baton CC utxo
// vout.2: change, if any
// vout.2: marker from oraclesfund tx to normal pubkey address (activation on Jul 15th 2019 00:00)
// vout.n-2: change, if any
// vout.n-1: opreturn with createtxid, pubkey and price per data point
return eval->Invalid("unexpected OraclesValidate for register");
if (GetLatestTimestamp(eval->GetCurrentHeight())>PUBKEY_SPOOFING_FIX_ACTIVATION)
{
if ((numvouts=tx.vout.size()) < 1 || DecodeOraclesOpRet(tx.vout[numvouts-1].scriptPubKey,oracletxid,tmppk,amount)!='R')
return eval->Invalid("invalid oraclesregister OP_RETURN data!");
else if (myGetTransaction(oracletxid,tmptx,hashblock) == 0)
return eval->Invalid("invalid oraclescreate txid!");
else if ((numvouts=tmptx.vout.size()) < 1 || DecodeOraclesCreateOpRet(tmptx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C')
return eval->Invalid("invalid oraclescreate OP_RETURN data!");
else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for oraclescreate!");
else if (ConstrainVout(tmptx.vout[0],0,oraclesaddr,txfee)==0)
return eval->Invalid("invalid marker for oraclescreate!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for oraclesregister!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0
|| tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE || !Getscriptaddress(vinaddress,tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].scriptPubKey)
|| !GetCCaddress(cp,tmpaddress,tmppk) || strcmp(tmpaddress,vinaddress)!=0)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC for oraclesregister or pubkey not same as vin pubkey, register must be done from owner of pubkey that registers to oracle!!");
else if (CCtxidaddr(tmpaddress,oracletxid).IsValid() && ConstrainVout(tx.vout[0],0,tmpaddress,txfee)==0)
return eval->Invalid("invalid marker for oraclesregister!");
else if (!Getscriptaddress(tmpaddress,CScript() << ParseHex(HexStr(tmppk)) << OP_CHECKSIG) || ConstrainVout(tx.vout[2],0,tmpaddress,CC_MARKER_VALUE)==0)
return eval->Invalid("pubkey in OP_RETURN and in vout.2 not matching, register must be done from owner of pubkey that registers to oracle!");
}
else return eval->Invalid("unexpected OraclesValidate for register");
break;
case 'S': // subscribe
// vins.*: normal inputs
@@ -762,6 +810,45 @@ int64_t LifetimeOraclesFunds(struct CCcontract_info *cp,uint256 oracletxid,CPubK
return(total);
}
int64_t AddMyOraclesFunds(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 oracletxid)
{
char coinaddr[64],funcid; int64_t nValue,tmpamount; uint256 tmporacletxid,txid,hashBlock,ignoretxid; int32_t numvouts,vout,ignorevin;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; CTransaction vintx; CPubKey tmppk;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr,true);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
nValue = it->second.satoshis;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && (numvouts=vintx.vout.size())>0)
{
if ((funcid=DecodeOraclesOpRet(vintx.vout[numvouts-1].scriptPubKey,tmporacletxid,tmppk,tmpamount))!=0 && funcid=='F' && tmppk==pk
&& tmporacletxid==oracletxid && tmpamount==nValue && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout)==0)
{
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
return (nValue);
}
} else fprintf(stderr,"couldnt find transaction\n");
}
BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx)
{
const CTransaction &txmempool = e.GetTx();
const uint256 &hash = txmempool.GetHash();
nValue=txmempool.vout[0].nValue;
if ((funcid=DecodeOraclesOpRet(txmempool.vout[txmempool.vout.size()-1].scriptPubKey,tmporacletxid,tmppk,tmpamount))!=0 && funcid=='F'
&& tmppk==pk && tmporacletxid==oracletxid && tmpamount==nValue && myIsutxo_spentinmempool(ignoretxid,ignorevin,hash,0)==0)
{
mtx.vin.push_back(CTxIn(hash,0,CScript()));
return (nValue);
}
}
return (0);
}
std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -802,10 +889,36 @@ std::string OracleCreate(int64_t txfee,std::string name,std::string description,
return("");
}
std::string OracleFund(int64_t txfee,uint256 oracletxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,oraclespk; struct CCcontract_info *cp,C;
if (GetLatestTimestamp(komodo_currentheight())<PUBKEY_SPOOFING_FIX_ACTIVATION)
{
CCerror = strprintf("oraclesfund not active yet, activation scheduled for July 15th");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2))
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('F',oracletxid,mypk,CC_MARKER_VALUE)));
}
CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,markerpubkey,batonpk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64];
CPubKey mypk,markerpubkey,batonpk,oraclespk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64];
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
@@ -816,12 +929,20 @@ std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee)
return("");
}
mypk = pubkey2pk(Mypubkey());
oraclespk = GetUnspendable(cp,0);
batonpk = OracleBatonPk(batonaddr,cp);
markerpubkey = CCtxidaddr(markeraddr,oracletxid);
if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 )
if (AddNormalinputs(mtx,mypk,3*txfee,4))
{
if (GetLatestTimestamp(komodo_currentheight())>PUBKEY_SPOOFING_FIX_ACTIVATION && AddMyOraclesFunds(cp,mtx,mypk,oracletxid)!=CC_MARKER_VALUE)
{
CCerror = strprintf("error adding inputs from your Oracles CC address, please fund it first with oraclesfund rpc!");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,batonpk));
if (GetLatestTimestamp(komodo_currentheight())>PUBKEY_SPOOFING_FIX_ACTIVATION) mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee)));
}
CCerror = strprintf("error adding normal inputs");
@@ -929,50 +1050,81 @@ UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatl
{
str[0] = 0;
j = oracle_format(&hash,&val,str,format[i],data,j,datalen);
obj.push_back(str);
if ( j < 0 )
break;
obj.push_back(str);
if ( j >= datalen )
break;
}
return(obj);
}
UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num)
UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx,oracletx; uint256 hashBlock,btxid,oracletxid;
CPubKey pk; std::string name,description,format; int32_t numvouts,n=0; std::vector<uint8_t> data; char *formatstr = 0;
UniValue result(UniValue::VOBJ),b(UniValue::VARR); CTransaction tx,oracletx; uint256 txid,hashBlock,btxid,oracletxid;
CPubKey pk; std::string name,description,format; int32_t numvouts,n=0,vout; std::vector<uint8_t> data; char *formatstr = 0;
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; int64_t nValue;
result.push_back(Pair("result","success"));
if ( GetTransaction(reforacletxid,oracletx,hashBlock,false) != 0 && (numvouts=oracletx.vout.size()) > 0 )
{
if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' )
{
while ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0 )
BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx)
{
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
const CTransaction &txmempool = e.GetTx();
const uint256 &hash = txmempool.GetHash();
if ((numvouts=txmempool.vout.size())>0 && DecodeOraclesData(txmempool.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
{
if ( (formatstr= (char *)format.c_str()) == 0 )
formatstr = (char *)"";
a.push_back(OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()));
batontxid = btxid;
if ( ++n >= num )
UniValue a(UniValue::VOBJ);
a.push_back(Pair("txid",hash.GetHex()));
a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size())));
b.push_back(a);
if ( ++n >= num && num != 0)
break;
} else break;
}
}
SetCCtxids(addressIndex,batonaddr,true);
if (addressIndex.size()>0)
{
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.end()-1; it!=addressIndex.begin(); it--)
{
txid=it->first.txhash;
vout = (int32_t)it->first.index;
nValue = (int64_t)it->second;
if (vout==1 && nValue==10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0 )
{
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
{
if ( (formatstr= (char *)format.c_str()) == 0 )
formatstr = (char *)"";
UniValue a(UniValue::VOBJ);
a.push_back(Pair("txid",txid.GetHex()));
a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size())));
b.push_back(a);
if ( ++n >= num && num != 0)
break;
}
}
}
}
}
}
result.push_back(Pair("samples",a));
result.push_back(Pair("samples",b));
return(result);
}
UniValue OracleInfo(uint256 origtxid)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR);
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; int32_t height;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk;
CTransaction tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk;
struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector <uint8_t> data;
std::map<CPubKey,std::pair<uint256,int32_t>> publishers;
cp = CCinit(&C,EVAL_ORACLES);
CCtxidaddr(markeraddr,origtxid);
if ( GetTransaction(origtxid,tx,hashBlock,false) == 0 )
@@ -996,28 +1148,38 @@ UniValue OracleInfo(uint256 origtxid)
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
if ( GetTransaction(txid,regtx,hashBlock,false) != 0 )
height = (int32_t)it->second.blockHeight;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 &&
DecodeOraclesOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid )
{
if ( regtx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid )
if (publishers.find(pk)==publishers.end() || height>publishers[pk].second)
{
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("publisher",pubkey33_str(str,(uint8_t *)pk.begin())));
Getscriptaddress(batonaddr,regtx.vout[1].scriptPubKey);
batontxid = OracleBatonUtxo(10000,cp,oracletxid,batonaddr,pk,data);
obj.push_back(Pair("baton",batonaddr));
obj.push_back(Pair("batontxid",uint256_str(str,batontxid)));
funding = LifetimeOraclesFunds(cp,oracletxid,pk);
sprintf(numstr,"%.8f",(double)funding/COIN);
obj.push_back(Pair("lifetime",numstr));
funding = AddOracleInputs(cp,mtx,oracletxid,pk,0,0);
sprintf(numstr,"%.8f",(double)funding/COIN);
obj.push_back(Pair("funds",numstr));
sprintf(numstr,"%.8f",(double)datafee/COIN);
obj.push_back(Pair("datafee",numstr));
a.push_back(obj);
publishers[pk].first=txid;
publishers[pk].second=height;
}
}
}
for (std::map<CPubKey,std::pair<uint256,int32_t>>::iterator it = publishers.begin(); it != publishers.end(); ++it)
{
if ( GetTransaction(it->second.first,tx,hashBlock,false) != 0 && DecodeOraclesOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R')
{
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("publisher",pubkey33_str(str,(uint8_t *)pk.begin())));
Getscriptaddress(batonaddr,tx.vout[1].scriptPubKey);
batontxid = OracleBatonUtxo(10000,cp,oracletxid,batonaddr,pk,data);
obj.push_back(Pair("baton",batonaddr));
obj.push_back(Pair("batontxid",uint256_str(str,batontxid)));
funding = LifetimeOraclesFunds(cp,oracletxid,pk);
sprintf(numstr,"%.8f",(double)funding/COIN);
obj.push_back(Pair("lifetime",numstr));
funding = AddOracleInputs(cp,mtx,oracletxid,pk,0,0);
sprintf(numstr,"%.8f",(double)funding/COIN);
obj.push_back(Pair("funds",numstr));
sprintf(numstr,"%.8f",(double)datafee/COIN);
obj.push_back(Pair("datafee",numstr));
a.push_back(obj);
}
}
result.push_back(Pair("registered",a));
}
}
@@ -1028,7 +1190,7 @@ UniValue OraclesList()
{
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction createtx; std::string name,description,format; char str[65];
cp = CCinit(&C,EVAL_ORACLES);
SetCCtxids(addressIndex,cp->normaladdr,true);
SetCCtxids(addressIndex,cp->normaladdr,false);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
txid = it->first.txhash;
@@ -1042,4 +1204,3 @@ UniValue OraclesList()
}
return(result);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -195,6 +195,7 @@ bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransactio
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{
uint256 txid,fundingtxid,hashBlock,vinfundingtxid; uint64_t vinsbits,sbits,APR,minseconds,maxseconds,mindeposit,amount,reward,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint8_t funcid; CScript scriptPubKey; CTransaction fundingTx,vinTx;
int64_t dummy;
numvins = tx.vin.size();
numvouts = tx.vout.size();
preventCCvins = preventCCvouts = -1;
@@ -255,7 +256,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
return eval->Invalid("unexpected normal vin for unlock");
}
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, dummy) )
return eval->Invalid("txfee is too high");
amount = vinTx.vout[0].nValue;
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);

View File

@@ -28,6 +28,7 @@ class CChainPower;
#include "pow.h"
#include "tinyformat.h"
#include "uint256.h"
extern int8_t is_STAKED(const char *chain_name);
#include <vector>
@@ -36,6 +37,8 @@ class CChainPower;
static const int SPROUT_VALUE_VERSION = 1001400;
static const int SAPLING_VALUE_VERSION = 1010100;
extern int32_t ASSETCHAINS_LWMAPOS;
extern char ASSETCHAINS_SYMBOL[65];
extern uint64_t ASSETCHAINS_NOTARY_PAY[];
struct CDiskBlockPos
{
@@ -118,7 +121,7 @@ enum BlockStatus: uint32_t {
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade
BLOCK_IN_TMPFILE = 256
BLOCK_IN_TMPFILE = 256
};
//! Short-hand for the highest consensus validity we implement.
@@ -238,7 +241,7 @@ public:
CBlockIndex* pskip;
//! height of the entry in the chain. The genesis block has height 0
int64_t newcoins,zfunds,sproutfunds; int8_t segid; // jl777 fields
int64_t newcoins,zfunds,sproutfunds,nNotaryPay; int8_t segid; // jl777 fields
//! Which # file this block is stored in (blk?????.dat)
int nFile;
@@ -309,6 +312,7 @@ public:
phashBlock = NULL;
newcoins = zfunds = 0;
segid = -2;
nNotaryPay = 0;
pprev = NULL;
pskip = NULL;
nFile = 0;
@@ -543,6 +547,11 @@ public:
if ((s.GetType() & SER_DISK) && (nVersion >= SAPLING_VALUE_VERSION)) {
READWRITE(nSaplingValue);
}
if ( (s.GetType() & SER_DISK) && (is_STAKED(ASSETCHAINS_SYMBOL) != 0) && ASSETCHAINS_NOTARY_PAY[0] != 0 )
{
READWRITE(nNotaryPay);
READWRITE(segid);
}
}
uint256 GetBlockHash() const

View File

@@ -92,6 +92,7 @@ static CBlock CreateGenesisBlock(uint32_t nTime, const uint256& nNonce, const st
void *chainparams_commandline(void *ptr);
#include "komodo_defs.h"
int32_t ASSETCHAINS_BLOCKTIME = 60;
uint64_t ASSETCHAINS_NK[2];
const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
@@ -282,6 +283,14 @@ void *chainparams_commandline(void *ptr)
mainParams.consensus.nPowTargetSpacing = ASSETCHAINS_BLOCKTIME;
}
mainParams.SetDefaultPort(ASSETCHAINS_P2PPORT);
if ( ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 )
{
//BOOST_STATIC_ASSERT(equihash_parameters_acceptable(ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]));
mainParams.SetNValue(ASSETCHAINS_NK[0]);
mainParams.SetKValue(ASSETCHAINS_NK[1]);
}
if ( KOMODO_TESTNODE != 0 )
mainParams.SetMiningRequiresPeers(false);
if ( ASSETCHAINS_RPCPORT == 0 )
ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1;
mainParams.pchMessageStart[0] = ASSETCHAINS_MAGIC & 0xff;

View File

@@ -119,6 +119,9 @@ public:
void SetDefaultPort(uint16_t port) { nDefaultPort = port; }
void SetCheckpointData(CCheckpointData checkpointData);
void SetNValue(uint64_t n) { nEquihashN = n; }
void SetKValue(uint64_t k) { nEquihashK = k; }
void SetMiningRequiresPeers(bool flag) { fMiningRequiresPeers = flag; }
//void setnonce(uint32_t nonce) { memcpy(&genesis.nNonce,&nonce,sizeof(nonce)); }
//void settimestamp(uint32_t timestamp) { genesis.nTime = timestamp; }

View File

@@ -18,6 +18,9 @@
#include "importcoin.h"
#include "main.h"
#include "notarisationdb.h"
#include "merkleblock.h"
#include "cc/CCinclude.h"
/*
* The crosschain workflow.
@@ -64,11 +67,12 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
if (kmdHeight < 0 || kmdHeight > chainActive.Height())
return uint256();
int seenOwnNotarisations = 0;
int seenOwnNotarisations = 0, i = 0;
int authority = GetSymbolAuthority(symbol);
std::set<uint256> tmp_moms;
for (int i=0; i<NOTARISATION_SCAN_LIMIT_BLOCKS; i++) {
for (i=0; i<NOTARISATION_SCAN_LIMIT_BLOCKS; i++) {
if (i > kmdHeight) break;
NotarisationsInBlock notarisations;
uint256 blockHash = *chainActive[kmdHeight-i]->phashBlock;
@@ -82,17 +86,17 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
seenOwnNotarisations++;
if (seenOwnNotarisations == 1)
destNotarisationTxid = nota.first;
else if (seenOwnNotarisations == 2)
else if (seenOwnNotarisations == 7)
goto end;
//break;
}
}
if (seenOwnNotarisations == 1) {
if (seenOwnNotarisations >= 1) {
BOOST_FOREACH(Notarisation& nota, notarisations) {
if (GetSymbolAuthority(nota.second.symbol) == authority)
if (nota.second.ccId == targetCCid) {
moms.push_back(nota.second.MoM);
tmp_moms.insert(nota.second.MoM);
//fprintf(stderr, "added mom: %s\n",nota.second.MoM.GetHex().data());
}
}
@@ -105,6 +109,10 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
return uint256();
end:
// add set to vector. Set makes sure there are no dupes included.
moms.clear();
std::copy(tmp_moms.begin(), tmp_moms.end(), std::back_inserter(moms));
//fprintf(stderr, "SeenOwnNotarisations.%i moms.size.%li blocks scanned.%i\n",seenOwnNotarisations, moms.size(), i);
return GetMerkleRoot(moms);
}
@@ -138,7 +146,7 @@ int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &fou
/* On KMD */
TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid,
const TxProof assetChainProof)
const TxProof assetChainProof, int32_t offset)
{
/*
* Here we are given a proof generated by an assetchain A which goes from given txid to
@@ -173,6 +181,9 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_
kmdHeight = ScanNotarisationsFromHeight(kmdHeight, isTarget, nota);
if (!kmdHeight)
throw std::runtime_error("Cannot find notarisation for target inclusive of source");
if ( offset != 0 )
kmdHeight += offset;
// Get MoMs for kmd height and symbol
std::vector<uint256> moms;
@@ -219,24 +230,27 @@ cont:
* Takes an importTx that has proof leading to assetchain root
* and extends proof to cross chain root
*/
void CompleteImportTransaction(CTransaction &importTx)
void CompleteImportTransaction(CTransaction &importTx, int32_t offset)
{
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; std::vector<uint8_t> rawproof;
ImportProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; std::vector<uint8_t> rawproof;
if (!UnmarshalImportTx(importTx, proof, burnTx, payouts))
throw std::runtime_error("Couldn't parse importTx");
throw std::runtime_error("Couldn't unmarshal importTx");
std::string targetSymbol;
uint32_t targetCCid;
uint256 payoutsHash;
if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof))
throw std::runtime_error("Couldn't parse burnTx");
throw std::runtime_error("Couldn't unmarshal burnTx");
proof = GetCrossChainProof(burnTx.GetHash(), targetSymbol.data(), targetCCid, proof);
TxProof merkleBranch;
if( !proof.IsMerkleBranch(merkleBranch) )
throw std::runtime_error("Incorrect import tx proof");
TxProof newMerkleBranch = GetCrossChainProof(burnTx.GetHash(), targetSymbol.data(), targetCCid, merkleBranch, offset);
ImportProof newProof(newMerkleBranch);
importTx = MakeImportCoinTransaction(proof, burnTx, payouts);
importTx = MakeImportCoinTransaction(newProof, burnTx, payouts);
}
bool IsSameAssetChain(const Notarisation &nota) {
return strcmp(nota.second.symbol, ASSETCHAINS_SYMBOL) == 0;
};
@@ -298,6 +312,111 @@ bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom)
}
/*
* Check notaries approvals for the txoutproofs of burn tx
* (alternate check if MoMoM check has failed)
* Params:
* burntxid - txid of burn tx on the source chain
* rawproof - array of txids of notaries' proofs
*/
bool CheckNotariesApproval(uint256 burntxid, const std::vector<uint256> & notaryTxids)
{
int count = 0;
// get notaries:
uint8_t notaries_pubkeys[64][33];
std::vector< std::vector<uint8_t> > alreadySigned;
//unmarshal notaries approval txids
for(auto notarytxid : notaryTxids ) {
EvalRef eval;
CBlockIndex block;
CTransaction notarytx; // tx with notary approval of txproof existence
// get notary approval tx
if (eval->GetTxConfirmed(notarytxid, notarytx, block)) {
std::vector<uint8_t> vopret;
if (!notarytx.vout.empty() && GetOpReturnData(notarytx.vout.back().scriptPubKey, vopret)) {
std::vector<uint8_t> txoutproof;
if (E_UNMARSHAL(vopret, ss >> txoutproof)) {
CMerkleBlock merkleBlock;
std::vector<uint256> prooftxids;
// extract block's merkle tree
if (E_UNMARSHAL(txoutproof, ss >> merkleBlock)) {
// extract proven txids:
merkleBlock.txn.ExtractMatches(prooftxids);
if (merkleBlock.txn.ExtractMatches(prooftxids) != merkleBlock.header.hashMerkleRoot || // check block merkle root is correct
std::find(prooftxids.begin(), prooftxids.end(), burntxid) != prooftxids.end()) { // check burn txid is in proven txids list
if (komodo_notaries(notaries_pubkeys, block.GetHeight(), block.GetBlockTime()) >= 0) {
// check it is a notary who signed approved tx:
int i;
for (i = 0; i < sizeof(notaries_pubkeys) / sizeof(notaries_pubkeys[0]); i++) {
std::vector<uint8_t> vnotarypubkey(notaries_pubkeys[i], notaries_pubkeys[i] + 33);
#ifdef TESTMODE
char test_notary_pubkey_hex[] = "029fa302968bbae81f41983d2ec20445557b889d31227caec5d910d19b7510ef86";
uint8_t test_notary_pubkey33[33];
decode_hex(test_notary_pubkey33, 33, test_notary_pubkey_hex);
#endif
if (CheckVinPubKey(notarytx, 0, notaries_pubkeys[i]) // is signed by a notary?
&& std::find(alreadySigned.begin(), alreadySigned.end(), vnotarypubkey) == alreadySigned.end() // check if notary not re-used
#ifdef TESTMODE
|| CheckVinPubKey(notarytx, 0, test_notary_pubkey33) // test
#endif
)
{
alreadySigned.push_back(vnotarypubkey);
count++;
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "CheckNotariesApproval() notary approval checked, count=" << count << std::endl);
break;
}
}
if (i == sizeof(notaries_pubkeys) / sizeof(notaries_pubkeys[0]))
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "CheckNotariesApproval() txproof not signed by a notary or reused" << std::endl);
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() cannot get current notaries pubkeys" << std::endl);
}
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() burntxid not found in txoutproof or incorrect txoutproof" << std::endl);
}
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() could not unmarshal merkleBlock" << std::endl);
}
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() could not unmarshal txoutproof" << std::endl);
}
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() no opret in the notary tx" << std::endl);
}
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() could not load notary tx" << std::endl);
}
}
bool retcode;
#ifdef TESTMODE
if (count < 1) { // 1 for test
#else
if (count < 5) {
#endif
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckNotariesApproval() not enough signed notary transactions=" << count << std::endl);
retcode = false;
}
else
retcode = true;
return retcode;
}
/*
* On assetchain

View File

@@ -38,11 +38,11 @@ TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx);
uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight,
std::vector<uint256> &moms, uint256 &destNotarisationTxid);
TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid,
const TxProof assetChainProof);
void CompleteImportTransaction(CTransaction &importTx);
const TxProof assetChainProof,int32_t offset);
void CompleteImportTransaction(CTransaction &importTx,int32_t offset);
/* On assetchain */
bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom);
bool CheckNotariesApproval(uint256 burntxid, const std::vector<uint256> & notaryTxids);
#endif /* CROSSCHAIN_H */

View File

@@ -54,33 +54,84 @@
#define __BYTE_ORDER BYTE_ORDER
#endif
*/
static EhSolverCancelledException solver_cancelled;
int8_t ZeroizeUnusedBits(size_t N, unsigned char* hash, size_t hLen)
{
uint8_t rem = N % 8;
if (rem)
{
// clear lowest 8-rem bits
const size_t step = GetSizeInBytes(N);
for (size_t i = step - 1; i < hLen; i += step)
{
uint8_t b = 0xff << (8-rem);
hash[i] &= b;
}
}
return(0);
}
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);
if ( ASSETCHAINS_NK[0] == 0 && ASSETCHAINS_NK[1] == 0 )
memcpy(personalization, "ZcashPoW", 8);
else
memcpy(personalization, "NandKPoW", 8);
memcpy(personalization+8, &le_N, 4);
memcpy(personalization+12, &le_K, 4);
const uint8_t outlen = (512 / N) * GetSizeInBytes(N);
BOOST_STATIC_ASSERT(!((!outlen) || (outlen > BLAKE2B_OUTBYTES)));
return crypto_generichash_blake2b_init_salt_personal(&base_state,
NULL, 0, // No key.
(512/N)*N/8,
outlen,
NULL, // No salt.
personalization);
}
void GenerateHash(const eh_HashState& base_state, eh_index g,
unsigned char* hash, size_t hLen)
unsigned char* hash, size_t hLen, size_t N)
{
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);
if ( ASSETCHAINS_NK[0] == 0 && ASSETCHAINS_NK[1] == 0 )
{
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);
}
else
{
uint32_t myHash[16] = {0};
uint32_t startIndex = g & 0xFFFFFFF0;
for (uint32_t g2 = startIndex; g2 <= g; g2++) {
uint32_t tmpHash[16] = {0};
eh_HashState state;
state = base_state;
eh_index lei = htole32(g2);
crypto_generichash_blake2b_update(&state, (const unsigned char*) &lei,
sizeof(eh_index));
crypto_generichash_blake2b_final(&state, (unsigned char*)&tmpHash[0], static_cast<uint8_t>(hLen));
for (uint32_t idx = 0; idx < 16; idx++) myHash[idx] += tmpHash[idx];
}
memcpy(hash, &myHash[0], hLen);
ZeroizeUnusedBits(N, hash, hLen);
}
}
void ExpandArray(const unsigned char* in, size_t in_len,
@@ -88,7 +139,7 @@ void ExpandArray(const unsigned char* in, size_t in_len,
size_t bit_len, size_t byte_pad)
{
assert(bit_len >= 8);
assert(8*sizeof(uint32_t) >= 7+bit_len);
assert(8*sizeof(uint32_t) >= bit_len);
size_t out_width { (bit_len+7)/8 + byte_pad };
assert(out_len == 8*out_width*in_len/bit_len);
@@ -131,10 +182,10 @@ void CompressArray(const unsigned char* in, size_t in_len,
size_t bit_len, size_t byte_pad)
{
assert(bit_len >= 8);
assert(8*sizeof(uint32_t) >= 7+bit_len);
assert(8*sizeof(uint32_t) >= bit_len);
size_t in_width { (bit_len+7)/8 + byte_pad };
assert(out_len == bit_len*in_len/(8*in_width));
assert(out_len == (bit_len*in_len/in_width + 7)/8);
uint32_t bit_len_mask { ((uint32_t)1 << bit_len) - 1 };
@@ -148,17 +199,23 @@ void CompressArray(const unsigned char* in, size_t in_len,
// When we have fewer than 8 bits left in the accumulator, read the next
// input element.
if (acc_bits < 8) {
if (j < in_len) {
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
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;
}
else {
acc_value <<= 8 - acc_bits;
acc_bits += 8 - acc_bits;;
}
}
acc_bits -= 8;
out[i] = (acc_value >> acc_bits) & 0xFF;
@@ -207,7 +264,7 @@ std::vector<eh_index> GetIndicesFromMinimal(std::vector<unsigned char> minimal,
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)) {
for (size_t i = 0; i < lenIndices; i += sizeof(eh_index)) {
ret.push_back(ArrayToEhIndex(array.data()+i));
}
return ret;
@@ -221,7 +278,7 @@ std::vector<unsigned char> GetMinimalFromIndices(std::vector<eh_index> indices,
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++) {
for (size_t i = 0; i < indices.size(); i++) {
EhIndexToArray(indices[i], array.data()+(i*sizeof(eh_index)));
}
std::vector<unsigned char> ret(minLen);
@@ -254,12 +311,12 @@ FullStepRow<WIDTH>::FullStepRow(const unsigned char* hashIn, size_t hInLen,
}
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) :
FullStepRow<WIDTH>::FullStepRow(const FullStepRow<W>& a, const FullStepRow<W>& b, size_t len, size_t lenIndices, size_t trim) :
StepRow<WIDTH> {a}
{
assert(len+lenIndices <= W);
assert(len-trim+(2*lenIndices) <= WIDTH);
for (int i = trim; i < len; i++)
for (size_t 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);
@@ -281,7 +338,7 @@ 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++) {
for (size_t i = 0; i < len; i++) {
if (hash[i] != 0)
return false;
}
@@ -301,10 +358,10 @@ std::vector<unsigned char> FullStepRow<WIDTH>::GetIndices(size_t len, size_t len
}
template<size_t WIDTH>
bool HasCollision(StepRow<WIDTH>& a, StepRow<WIDTH>& b, int l)
bool HasCollision(StepRow<WIDTH>& a, StepRow<WIDTH>& b, size_t l)
{
// This doesn't need to be constant time.
for (int j = 0; j < l; j++) {
for (size_t j = 0; j < l; j++) {
if (a.hash[j] != b.hash[j])
return false;
}
@@ -326,7 +383,7 @@ TruncatedStepRow<WIDTH>::TruncatedStepRow(const TruncatedStepRow<W>& a, const Tr
{
assert(len+lenIndices <= W);
assert(len-trim+(2*lenIndices) <= WIDTH);
for (int i = trim; i < len; i++)
for (size_t i = static_cast<size_t>(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);
@@ -355,10 +412,10 @@ std::shared_ptr<eh_trunc> TruncatedStepRow<WIDTH>::GetTruncatedIndices(size_t le
#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(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled)
{
eh_index init_size { 1 << (CollisionBitLength + 1) };
eh_index init_size { 1U << (CollisionBitLength + 1) };
// 1) Generate first list
LogPrint("pow", "Generating first list\n");
@@ -368,16 +425,16 @@ bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state,
X.reserve(init_size);
unsigned char tmpHash[HashOutput];
for (eh_index g = 0; X.size() < init_size; g++) {
GenerateHash(base_state, g, tmpHash, HashOutput);
GenerateHash(base_state, g, tmpHash, HashOutput, N);
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);
X.emplace_back(tmpHash+(i*GetSizeInBytes(N)), GetSizeInBytes(N), HashLength,
CollisionBitLength, static_cast<int>(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++) {
for (unsigned int r = 1; r < K && X.size() > 0; r++) {
LogPrint("pow", "Round %d:\n", r);
// 2a) Sort the list
LogPrint("pow", "- Sorting list\n");
@@ -385,20 +442,20 @@ bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state,
if (cancelled(ListSorting)) throw solver_cancelled;
LogPrint("pow", "- Finding collisions\n");
int i = 0;
int posFree = 0;
size_t i = 0;
size_t 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;
size_t 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++) {
for (size_t l = 0; l < j - 1; l++) {
for (size_t 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);
}
@@ -442,16 +499,16 @@ bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state,
std::sort(X.begin(), X.end(), CompareSR(hashLen));
if (cancelled(FinalSorting)) throw solver_cancelled;
LogPrint("pow", "- Finding collisions\n");
int i = 0;
size_t i = 0;
while (i < X.size() - 1) {
int j = 1;
size_t 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++) {
for (size_t l = 0; l < j - 1; l++) {
for (size_t 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);
@@ -475,20 +532,21 @@ bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state,
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;
size_t i = 0;
size_t posFree = 0;
assert(X.size() > 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;
size_t 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++) {
for (size_t l = 0; l < j - 1; l++) {
for (size_t 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);
@@ -526,10 +584,10 @@ void CollideBranches(std::vector<FullStepRow<WIDTH>>& X, const size_t hlen, cons
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(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled)
{
eh_index init_size { 1 << (CollisionBitLength + 1) };
eh_index init_size { 1U << (CollisionBitLength + 1) };
eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength + 1) };
// First run the algorithm with truncated indices
@@ -547,16 +605,16 @@ bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
Xt.reserve(init_size);
unsigned char tmpHash[HashOutput];
for (eh_index g = 0; Xt.size() < init_size; g++) {
GenerateHash(base_state, g, tmpHash, HashOutput);
GenerateHash(base_state, g, tmpHash, HashOutput, N);
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);
Xt.emplace_back(tmpHash+(i*GetSizeInBytes(N)), GetSizeInBytes(N), HashLength, CollisionBitLength,
static_cast<eh_index>(g*IndicesPerHashOutput)+i, static_cast<unsigned int>(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++) {
for (unsigned int r = 1; r < K && Xt.size() > 0; r++) {
LogPrint("pow", "Round %d:\n", r);
// 2a) Sort the list
LogPrint("pow", "- Sorting list\n");
@@ -564,21 +622,21 @@ bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
if (cancelled(ListSorting)) throw solver_cancelled;
LogPrint("pow", "- Finding collisions\n");
int i = 0;
int posFree = 0;
size_t i = 0;
size_t 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;
size_t 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++) {
//bool checking_for_zero = (i == 0 && Xt[0].IsZero(hashLen));
for (size_t l = 0; l < j - 1; l++) {
for (size_t 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,
@@ -628,16 +686,16 @@ bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
std::sort(Xt.begin(), Xt.end(), CompareSR(hashLen));
if (cancelled(FinalSorting)) throw solver_cancelled;
LogPrint("pow", "- Finding collisions\n");
int i = 0;
size_t i = 0;
while (i < Xt.size() - 1) {
int j = 1;
size_t 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++) {
for (size_t l = 0; l < j - 1; l++) {
for (size_t 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);
@@ -676,10 +734,10 @@ bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
eh_index newIndex { UntruncateIndex(partialSoln.get()[i], j, CollisionBitLength + 1) };
if (j == 0 || newIndex % IndicesPerHashOutput == 0) {
GenerateHash(base_state, newIndex/IndicesPerHashOutput,
tmpHash, HashOutput);
tmpHash, HashOutput, N);
}
icv.emplace_back(tmpHash+((newIndex % IndicesPerHashOutput) * N/8),
N/8, HashLength, CollisionBitLength, newIndex);
icv.emplace_back(tmpHash+((newIndex % IndicesPerHashOutput) * GetSizeInBytes(N)),
GetSizeInBytes(N), HashLength, CollisionBitLength, newIndex);
if (cancelled(PartialGeneration)) throw solver_cancelled;
}
boost::optional<std::vector<FullStepRow<FinalFullWidth>>> ic = icv;
@@ -697,7 +755,7 @@ bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
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);
size_t lti = rti-(static_cast<size_t>(1)<<r);
CollideBranches(*ic, hashLen, lenIndices,
CollisionByteLength,
CollisionBitLength + 1,
@@ -760,16 +818,16 @@ bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<
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);
GenerateHash(base_state, i/IndicesPerHashOutput, tmpHash, HashOutput, N);
X.emplace_back(tmpHash+((i % IndicesPerHashOutput) * GetSizeInBytes(N)),
GetSizeInBytes(N), 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) {
for (size_t 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));
@@ -795,50 +853,74 @@ bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<
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(const 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(const 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);
// Explicit instantiations for Equihash<96,3>
template int Equihash<150,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,
template bool Equihash<150,5>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(const 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,
template bool Equihash<150,5>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(const 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);
template bool Equihash<150,5>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);
// Explicit instantiations for Equihash<48,5>
template int Equihash<144,5>::InitialiseState(eh_HashState& base_state);
#ifdef ENABLE_MINING
template bool Equihash<144,5>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<144,5>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
#endif
template bool Equihash<144,5>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);
// Explicit instantiations for Equihash<96,5>
template int Equihash<ASSETCHAINS_N,ASSETCHAINS_K>::InitialiseState(eh_HashState& base_state);
#ifdef ENABLE_MINING
template bool Equihash<ASSETCHAINS_N,ASSETCHAINS_K>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<ASSETCHAINS_N,ASSETCHAINS_K>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
#endif
template bool Equihash<ASSETCHAINS_N,ASSETCHAINS_K>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);
// Explicit instantiations for Equihash<96,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(const 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(const 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);
// Explicit instantiations for Equihash<48,5>
template int Equihash<210,9>::InitialiseState(eh_HashState& base_state);
#ifdef ENABLE_MINING
template bool Equihash<210,9>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<210,9>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(const std::vector<unsigned char>&)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
#endif
template bool Equihash<210,9>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);

View File

@@ -10,6 +10,7 @@
#include "utilstrencodings.h"
#include "sodium.h"
#include "komodo_nk.h"
#include <cstring>
#include <exception>
@@ -24,6 +25,9 @@ typedef crypto_generichash_blake2b_state eh_HashState;
typedef uint32_t eh_index;
typedef uint8_t eh_trunc;
#define BLAKE2B_OUTBYTES 64
extern uint64_t ASSETCHAINS_NK[2];
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);
@@ -61,7 +65,7 @@ public:
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);
friend bool HasCollision(StepRow<W>& a, StepRow<W>& b, size_t l);
};
class CompareSR
@@ -77,7 +81,7 @@ public:
};
template<size_t WIDTH>
bool HasCollision(StepRow<WIDTH>& a, StepRow<WIDTH>& b, int l);
bool HasCollision(StepRow<WIDTH>& a, StepRow<WIDTH>& b, size_t l);
template<size_t WIDTH>
class FullStepRow : public StepRow<WIDTH>
@@ -94,7 +98,7 @@ public:
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(const FullStepRow<W>& a, const FullStepRow<W>& b, size_t len, size_t lenIndices, size_t 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; }
@@ -159,17 +163,22 @@ inline constexpr size_t equihash_solution_size(unsigned int N, unsigned int K) {
return (1 << K)*(N/(K+1)+1)/8;
}
constexpr uint8_t GetSizeInBytes(size_t N)
{
return static_cast<uint8_t>((N + 7) / 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 % 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 { HashOutput = IndicesPerHashOutput * GetSizeInBytes(N) };
enum : size_t { CollisionBitLength=N/(K+1) };
enum : size_t { CollisionByteLength=(CollisionBitLength+7)/8 };
enum : size_t { HashLength=(K+1)*CollisionByteLength };
@@ -184,79 +193,100 @@ public:
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(const 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(const 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"
/*
* Equihash 200,9 (KMD/Zcash)
* Equihash 150,5 (beam)
* Equihash 144,5 (SnowGem)
* Equihash 96,5 (Minex)
* Equihash 48,5 (regtest)
* Equihash 210,9 (Aion) */
static Equihash<96,3> Eh96_3;
static Equihash<200,9> Eh200_9;
static Equihash<96,5> Eh96_5;
static Equihash<150,5> Eh150_5;
static Equihash<144,5> Eh144_5;
static Equihash<ASSETCHAINS_N,ASSETCHAINS_K> Eh96_5;
static Equihash<48,5> Eh48_5;
static Equihash<210,9> Eh210_9;
#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) { \
if (n == 200 && k == 9) { \
Eh200_9.InitialiseState(base_state); \
} else if (n == 150 && k == 5) { \
Eh150_5.InitialiseState(base_state); \
} else if (n == 144 && k == 5) { \
Eh144_5.InitialiseState(base_state); \
} else if (n == ASSETCHAINS_N && k == ASSETCHAINS_K) { \
Eh96_5.InitialiseState(base_state); \
} else if (n == 48 && k == 5) { \
Eh48_5.InitialiseState(base_state); \
} else if (n == 210 && k == 9) { \
Eh210_9.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(const 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) {
if (n == 200 && k == 9) {
return Eh200_9.BasicSolve(base_state, validBlock, cancelled);
} else if (n == 96 && k == 5) {
} else if (n == 150 && k == 5) {
return Eh150_5.BasicSolve(base_state, validBlock, cancelled);
} else if (n == 144 && k == 5) {
return Eh144_5.BasicSolve(base_state, validBlock, cancelled);
} else if (n == ASSETCHAINS_N && k == ASSETCHAINS_K) {
return Eh96_5.BasicSolve(base_state, validBlock, cancelled);
} else if (n == 48 && k == 5) {
} else if (n == 48 && k == 5) {
return Eh48_5.BasicSolve(base_state, validBlock, cancelled);
} else if (n == 210 && k == 9) {
return Eh210_9.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)
const std::function<bool(const 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(const 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) {
if (n == 200 && k == 9) {
return Eh200_9.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == 96 && k == 5) {
} else if (n == 150 && k == 5) {
return Eh150_5.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == 144 && k == 5) {
return Eh144_5.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == ASSETCHAINS_N && k == ASSETCHAINS_K) {
return Eh96_5.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == 48 && k == 5) {
} else if (n == 48 && k == 5) {
return Eh48_5.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == 210 && k == 9) {
return Eh210_9.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)
const std::function<bool(const std::vector<unsigned char>&)> validBlock)
{
return EhOptimisedSolve(n, k, base_state, validBlock,
[](EhSolverCancelCheck pos) { return false; });
@@ -264,14 +294,18 @@ inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const
#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) { \
if (n == 200 && k == 9) { \
ret = Eh200_9.IsValidSolution(base_state, soln); \
} else if (n == 150 && k == 5) { \
ret = Eh150_5.IsValidSolution(base_state, soln); \
} else if (n == 144 && k == 5) { \
ret = Eh144_5.IsValidSolution(base_state, soln); \
} else if (n == ASSETCHAINS_N && k == ASSETCHAINS_K) { \
ret = Eh96_5.IsValidSolution(base_state, soln); \
} else if (n == 48 && k == 5) { \
ret = Eh48_5.IsValidSolution(base_state, soln); \
} else if (n == 210 && k == 9) { \
ret = Eh210_9.IsValidSolution(base_state, soln); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
}

View File

@@ -1,134 +1,134 @@
// (C) 2018 Michael Toutonghi
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*
This provides the PoW hash function for Verus, enabling CPU mining.
*/
#ifndef VERUS_HASH_H_
#define VERUS_HASH_H_
#include <cstring>
#include <vector>
#include <cpuid.h>
extern "C"
{
#include "crypto/haraka.h"
#include "crypto/haraka_portable.h"
}
class CVerusHash
{
public:
static void Hash(void *result, const void *data, size_t len);
static void (*haraka512Function)(unsigned char *out, const unsigned char *in);
static void init();
CVerusHash() { }
CVerusHash &Write(const unsigned char *data, size_t len);
CVerusHash &Reset()
{
curBuf = buf1;
result = buf2;
curPos = 0;
std::fill(buf1, buf1 + sizeof(buf1), 0);
return *this;
}
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
void ClearExtra()
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
}
}
void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }
void Finalize(unsigned char hash[32])
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
(*haraka512Function)(hash, curBuf);
}
else
std::memcpy(hash, curBuf, 32);
}
private:
// only buf1, the first source, needs to be zero initialized
unsigned char buf1[64] = {0}, buf2[64];
unsigned char *curBuf = buf1, *result = buf2;
size_t curPos = 0;
};
class CVerusHashV2
{
public:
static void Hash(void *result, const void *data, size_t len);
static void (*haraka512Function)(unsigned char *out, const unsigned char *in);
static void init();
CVerusHashV2() {}
CVerusHashV2 &Write(const unsigned char *data, size_t len);
CVerusHashV2 &Reset()
{
curBuf = buf1;
result = buf2;
curPos = 0;
std::fill(buf1, buf1 + sizeof(buf1), 0);
return *this;
}
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
void ClearExtra()
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
}
}
void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }
void Finalize(unsigned char hash[32])
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
(*haraka512Function)(hash, curBuf);
}
else
std::memcpy(hash, curBuf, 32);
}
private:
// only buf1, the first source, needs to be zero initialized
unsigned char buf1[64] = {0}, buf2[64];
unsigned char *curBuf = buf1, *result = buf2;
size_t curPos = 0;
};
extern void verus_hash(void *result, const void *data, size_t len);
extern void verus_hash_v2(void *result, const void *data, size_t len);
inline bool IsCPUVerusOptimized()
{
unsigned int eax,ebx,ecx,edx;
if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx))
{
return false;
}
return ((ecx & (bit_AVX | bit_AES)) == (bit_AVX | bit_AES));
};
#endif
// (C) 2018 Michael Toutonghi
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*
This provides the PoW hash function for Verus, enabling CPU mining.
*/
#ifndef VERUS_HASH_H_
#define VERUS_HASH_H_
#include <cstring>
#include <vector>
#include <cpuid.h>
extern "C"
{
#include "crypto/haraka.h"
#include "crypto/haraka_portable.h"
}
class CVerusHash
{
public:
static void Hash(void *result, const void *data, size_t len);
static void (*haraka512Function)(unsigned char *out, const unsigned char *in);
static void init();
CVerusHash() { }
CVerusHash &Write(const unsigned char *data, size_t len);
CVerusHash &Reset()
{
curBuf = buf1;
result = buf2;
curPos = 0;
std::fill(buf1, buf1 + sizeof(buf1), 0);
return *this;
}
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
void ClearExtra()
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
}
}
void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }
void Finalize(unsigned char hash[32])
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
(*haraka512Function)(hash, curBuf);
}
else
std::memcpy(hash, curBuf, 32);
}
private:
// only buf1, the first source, needs to be zero initialized
unsigned char buf1[64] = {0}, buf2[64];
unsigned char *curBuf = buf1, *result = buf2;
size_t curPos = 0;
};
class CVerusHashV2
{
public:
static void Hash(void *result, const void *data, size_t len);
static void (*haraka512Function)(unsigned char *out, const unsigned char *in);
static void init();
CVerusHashV2() {}
CVerusHashV2 &Write(const unsigned char *data, size_t len);
CVerusHashV2 &Reset()
{
curBuf = buf1;
result = buf2;
curPos = 0;
std::fill(buf1, buf1 + sizeof(buf1), 0);
return *this;
}
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
void ClearExtra()
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
}
}
void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }
void Finalize(unsigned char hash[32])
{
if (curPos)
{
std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
(*haraka512Function)(hash, curBuf);
}
else
std::memcpy(hash, curBuf, 32);
}
private:
// only buf1, the first source, needs to be zero initialized
unsigned char buf1[64] = {0}, buf2[64];
unsigned char *curBuf = buf1, *result = buf2;
size_t curPos = 0;
};
extern void verus_hash(void *result, const void *data, size_t len);
extern void verus_hash_v2(void *result, const void *data, size_t len);
inline bool IsCPUVerusOptimized()
{
unsigned int eax,ebx,ecx,edx;
if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx))
{
return false;
}
return ((ecx & (bit_AVX | bit_AES)) == (bit_AVX | bit_AES));
};
#endif

View File

@@ -24,7 +24,7 @@
// * Shut down WEEKS_UNTIL_DEPRECATION weeks' worth of blocks after the estimated release block height.
// * A warning is shown during the DEPRECATION_WARN_LIMIT worth of blocks prior to shut down.
static const int WEEKS_UNTIL_DEPRECATION = 52;
static const int DEPRECATION_HEIGHT = 1600000;
static const int DEPRECATION_HEIGHT = 2200000;
static const int APPROX_RELEASE_HEIGHT = DEPRECATION_HEIGHT - (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 60);
// Number of blocks before deprecation to warn users

2
src/fiat/k64 Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=K64 $1 $2 $3 $4 $5 $6

View File

@@ -1,2 +0,0 @@
#!/bin/bash
./komodo-cli -ac_name=ZEX $1 $2 $3 $4 $5 $6

2
src/fiat/zexo Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=ZEXO $1 $2 $3 $4 $5 $6

View File

@@ -44,5 +44,19 @@ TEST(Keys, EncodeAndDecodeSapling)
auto addr2 = boost::get<libzcash::SaplingPaymentAddress>(paymentaddr2);
EXPECT_EQ(addr, addr2);
}
{
auto ivk = sk.ToXFVK().fvk.in_viewing_key();
std::string ivk_string = EncodeViewingKey(ivk);
EXPECT_EQ(
ivk_string.substr(0, 5),
Params().Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY));
auto viewing_key = DecodeViewingKey(ivk_string);
EXPECT_TRUE(IsValidViewingKey(viewing_key));
auto ivk2 = boost::get<libzcash::SaplingIncomingViewingKey>(&viewing_key);
ASSERT_TRUE(ivk2 != nullptr);
EXPECT_EQ(*ivk2, ivk);
}
}
}

View File

@@ -24,28 +24,63 @@
#include "script/sign.h"
#include "wallet/wallet.h"
#include "cc/CCinclude.h"
int32_t komodo_nextheight();
CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride)
// makes import tx for either coins or tokens
CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride)
{
std::vector<uint8_t> payload = E_MARSHAL(ss << EVAL_IMPORTCOIN);
//std::vector<uint8_t> payload = E_MARSHAL(ss << EVAL_IMPORTCOIN);
CScript scriptSig;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
if (mtx.fOverwintered)
mtx.nExpiryHeight = 0;
mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload));
mtx.vout = payouts;
auto importData = E_MARSHAL(ss << proof; ss << burnTx);
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << importData));
if (nExpiryHeightOverride != 0)
mtx.nExpiryHeight = nExpiryHeightOverride; //this is for construction of the tx used for validating importtx
if (mtx.vout.size() == 0)
return CTransaction(mtx);
// add special import tx vin:
scriptSig << E_MARSHAL(ss << EVAL_IMPORTCOIN); // simple payload for coins
mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), scriptSig));
if (nExpiryHeightOverride != 0)
mtx.nExpiryHeight = nExpiryHeightOverride; //this is for validation code, to make a tx used for validating the import tx
auto importData = E_MARSHAL(ss << EVAL_IMPORTCOIN; ss << proof; ss << burnTx); // added evalcode to differentiate importdata from token opret
// if it is tokens:
vscript_t vopret;
GetOpReturnData(mtx.vout.back().scriptPubKey, vopret);
if (!vopret.empty()) {
std::vector<uint8_t> vorigpubkey;
uint8_t funcId;
std::vector <std::pair<uint8_t, vscript_t>> oprets;
std::string name, desc;
if (DecodeTokenCreateOpRet(mtx.vout.back().scriptPubKey, vorigpubkey, name, desc, oprets) == 'c') { // parse token 'c' opret
mtx.vout.pop_back(); //remove old token opret
oprets.push_back(std::make_pair(OPRETID_IMPORTDATA, importData));
mtx.vout.push_back(CTxOut(0, EncodeTokenCreateOpRet('c', vorigpubkey, name, desc, oprets))); // make new token 'c' opret with importData
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeImportCoinTransaction() incorrect token import opret" << std::endl);
}
}
else { //no opret in coin payouts
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << importData)); // import tx's opret now is in the vout's tail
}
return CTransaction(mtx);
}
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof)
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string targetSymbol, const std::vector<CTxOut> payouts, const std::vector<uint8_t> rawproof)
{
std::vector<uint8_t> opret;
opret = E_MARSHAL(ss << VARINT(targetCCid);
opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN; // should mark burn opret to differentiate it from token opret
ss << VARINT(targetCCid);
ss << targetSymbol;
ss << SerializeHash(payouts);
ss << rawproof);
@@ -53,20 +88,23 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb
}
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub)
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount)
{
std::vector<uint8_t> opret;
opret = E_MARSHAL(ss << VARINT(targetCCid);
opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN;
ss << VARINT(targetCCid);
ss << targetSymbol;
ss << SerializeHash(payouts);
ss << rawproof;
ss << bindtxid;
ss << publishers;
ss << txids;
ss << burntxid;
ss << height;
ss << burnvout;
ss << rawburntx;
ss << destpub);
ss << destpub;
ss << amount);
return CTxOut(value, CScript() << OP_RETURN << opret);
}
@@ -75,7 +113,8 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb
std::string receipt)
{
std::vector<uint8_t> opret;
opret = E_MARSHAL(ss << VARINT(targetCCid);
opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN;
ss << VARINT(targetCCid);
ss << targetSymbol;
ss << SerializeHash(payouts);
ss << rawproof;
@@ -85,39 +124,114 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb
}
bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,
std::vector<CTxOut> &payouts)
bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, CTransaction &burnTx, std::vector<CTxOut> &payouts)
{
std::vector<uint8_t> vData;
GetOpReturnData(importTx.vout[importTx.vout.size()-1].scriptPubKey, vData);
if (importTx.vout.size() < 1) return false;
payouts = std::vector<CTxOut>(importTx.vout.begin(), importTx.vout.end()-1);
return importTx.vin.size() == 1 &&
importTx.vin[0].scriptSig == (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN)) &&
E_UNMARSHAL(vData, ss >> proof; ss >> burnTx);
if (importTx.vout.size() < 1)
return false;
if (importTx.vin.size() != 1 || importTx.vin[0].scriptSig != (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN))) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalImportTx() incorrect import tx vin" << std::endl);
return false;
}
std::vector<uint8_t> vImportData;
GetOpReturnData(importTx.vout.back().scriptPubKey, vImportData);
if (vImportData.empty()) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalImportTx() no opret" << std::endl);
return false;
}
if (vImportData.begin()[0] == EVAL_TOKENS) { // if it is tokens
// get import data after token opret:
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vorigpubkey;
std::string name, desc;
if (DecodeTokenCreateOpRet(importTx.vout.back().scriptPubKey, vorigpubkey, name, desc, oprets) == 0) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalImportTx() could not decode token opret" << std::endl);
return false;
}
GetOpretBlob(oprets, OPRETID_IMPORTDATA, vImportData); // fetch import data after token opret
for (std::vector<std::pair<uint8_t, vscript_t>>::const_iterator i = oprets.begin(); i != oprets.end(); i++)
if ((*i).first == OPRETID_IMPORTDATA) {
oprets.erase(i); // remove import data from token opret to restore original payouts:
break;
}
payouts = std::vector<CTxOut>(importTx.vout.begin(), importTx.vout.end()-1); //exclude opret with import data
payouts.push_back(CTxOut(0, EncodeTokenCreateOpRet('c', vorigpubkey, name, desc, oprets))); // make original payouts token opret (without import data)
}
else {
//payouts = std::vector<CTxOut>(importTx.vout.begin()+1, importTx.vout.end()); // see next
payouts = std::vector<CTxOut>(importTx.vout.begin(), importTx.vout.end() - 1); // skip opret; and it is now in the back
}
uint8_t evalCode;
bool retcode = E_UNMARSHAL(vImportData, ss >> evalCode; ss >> proof; ss >> burnTx);
if (!retcode)
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalImportTx() could not unmarshal import data" << std::endl);
return retcode;
}
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t>&rawproof)
{
std::vector<uint8_t> burnOpret; uint32_t ccid = 0; bool isEof=true;
std::vector<uint8_t> vburnOpret; uint32_t ccid = 0;
uint8_t evalCode;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof; isEof=ss.eof();) || !isEof;
if (burnTx.vout.size() == 0)
return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, vburnOpret);
if (vburnOpret.empty()) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalBurnTx() cannot unmarshal burn tx: empty burn opret" << std::endl);
return false;
}
if (vburnOpret.begin()[0] == EVAL_TOKENS) { //if it is tokens
std::vector<std::pair<uint8_t, vscript_t>> oprets;
uint256 tokenid;
uint8_t evalCodeInOpret;
std::vector<CPubKey> voutTokenPubkeys;
if (DecodeTokenOpRet(burnTx.vout.back().scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets) != 't')
return false;
//skip token opret:
GetOpretBlob(oprets, OPRETID_BURNDATA, vburnOpret); // fetch burnOpret after token opret
if (vburnOpret.empty()) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalBurnTx() cannot unmarshal token burn tx: empty burn opret for tokenid=" << tokenid.GetHex() << std::endl);
return false;
}
}
if (vburnOpret.begin()[0] == EVAL_IMPORTCOIN) {
uint8_t evalCode;
bool isEof = true;
return E_UNMARSHAL(vburnOpret, ss >> evalCode;
ss >> VARINT(*targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof; isEof = ss.eof();) || !isEof; // if isEof == false it means we have successfully read the vars upto 'rawproof'
// and it might be additional data further that we do not need here so we allow !isEof
}
else {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalBurnTx() invalid eval code in opret" << std::endl);
return false;
}
}
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt)
{
std::vector<uint8_t> burnOpret,rawproof; bool isEof=true;
std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash;
uint8_t evalCode;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
return (E_UNMARSHAL(burnOpret, ss >> VARINT(targetCCid);
return (E_UNMARSHAL(burnOpret, ss >> evalCode;
ss >> VARINT(targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof;
@@ -125,24 +239,28 @@ bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::strin
ss >> receipt));
}
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub)
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,uint256& burntxid,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub, int64_t &amount)
{
std::vector<uint8_t> burnOpret,rawproof; bool isEof=true;
uint32_t targetCCid; uint256 payoutsHash; std::string targetSymbol;
uint8_t evalCode;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
return (E_UNMARSHAL(burnOpret, ss >> VARINT(targetCCid);
return (E_UNMARSHAL(burnOpret, ss >> evalCode;
ss >> VARINT(targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof;
ss >> bindtxid;
ss >> publishers;
ss >> txids;
ss >> burntxid;
ss >> height;
ss >> burnvout;
ss >> rawburntx;
ss >> destpub));
ss >> destpub;
ss >> amount));
}
@@ -151,16 +269,55 @@ bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPu
*/
CAmount GetCoinImportValue(const CTransaction &tx)
{
TxProof proof;
ImportProof proof;
CTransaction burnTx;
std::vector<CTxOut> payouts;
if (UnmarshalImportTx(tx, proof, burnTx, payouts)) {
return burnTx.vout.size() ? burnTx.vout.back().nValue : 0;
bool isNewImportTx = false;
if ((isNewImportTx = UnmarshalImportTx(tx, proof, burnTx, payouts))) {
if (burnTx.vout.size() > 0) {
vscript_t vburnOpret;
GetOpReturnData(burnTx.vout.back().scriptPubKey, vburnOpret);
if (vburnOpret.empty()) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetCoinImportValue() empty burn opret" << std::endl);
return 0;
}
if (isNewImportTx && vburnOpret.begin()[0] == EVAL_TOKENS) { //if it is tokens
uint8_t evalCodeInOpret;
uint256 tokenid;
std::vector<CPubKey> voutTokenPubkeys;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (DecodeTokenOpRet(tx.vout.back().scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets) == 0)
return 0;
uint8_t nonfungibleEvalCode = EVAL_TOKENS; // init as if no non-fungibles
vscript_t vnonfungibleOpret;
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vnonfungibleOpret);
if (!vnonfungibleOpret.empty())
nonfungibleEvalCode = vnonfungibleOpret.begin()[0];
// calc outputs for burn tx
int64_t ccBurnOutputs = 0;
for (auto v : burnTx.vout)
if (v.scriptPubKey.IsPayToCryptoCondition() &&
CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey
ccBurnOutputs += v.nValue;
return ccBurnOutputs + burnTx.vout.back().nValue; // total token burned value
}
else
return burnTx.vout.back().nValue; // coin burned value
}
}
return 0;
}
/*
* CoinImport is different enough from normal script execution that it's not worth
* making all the mods neccesary in the interpreter to do the dispatch correctly.

View File

@@ -22,22 +22,90 @@
#include "script/interpreter.h"
#include <cryptoconditions.h>
enum ProofKind : uint8_t {
PROOF_NONE = 0x00,
PROOF_MERKLEBRANCH = 0x11,
PROOF_NOTARYTXIDS = 0x12,
PROOF_MERKLEBLOCK = 0x13
};
class ImportProof {
private:
uint8_t proofKind;
TxProof proofBranch;
std::vector<uint256> notaryTxids;
std::vector<uint8_t> proofBlock;
public:
ImportProof() { proofKind = PROOF_NONE; }
ImportProof(const TxProof &_proofBranch) {
proofKind = PROOF_MERKLEBRANCH; proofBranch = _proofBranch;
}
ImportProof(const std::vector<uint256> &_notaryTxids) {
proofKind = PROOF_NOTARYTXIDS; notaryTxids = _notaryTxids;
}
ImportProof(const std::vector<uint8_t> &_proofBlock) {
proofKind = PROOF_MERKLEBLOCK; proofBlock = _proofBlock;
}
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(proofKind);
if (proofKind == PROOF_MERKLEBRANCH)
READWRITE(proofBranch);
else if (proofKind == PROOF_NOTARYTXIDS)
READWRITE(notaryTxids);
else if (proofKind == PROOF_MERKLEBLOCK)
READWRITE(proofBlock);
else
proofKind = PROOF_NONE; // if we have read some trash
}
bool IsMerkleBranch(TxProof &_proofBranch) const {
if (proofKind == PROOF_MERKLEBRANCH) {
_proofBranch = proofBranch;
return true;
}
else
return false;
}
bool IsNotaryTxids(std::vector<uint256> &_notaryTxids) const {
if (proofKind == PROOF_NOTARYTXIDS) {
_notaryTxids = notaryTxids;
return true;
}
else
return false;
}
bool IsMerkleBlock(std::vector<uint8_t> &_proofBlock) const {
if (proofKind == PROOF_MERKLEBLOCK) {
_proofBlock = proofBlock;
return true;
}
else
return false;
}
};
CAmount GetCoinImportValue(const CTransaction &tx);
CTransaction MakeImportCoinTransaction(const TxProof proof,
const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride = 0);
CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride = 0);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string targetSymbol, const std::vector<CTxOut> payouts, const std::vector<uint8_t> rawproof);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256>txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub);
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256>txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,std::string srcaddr,
std::string receipt);
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t> &rawproof);
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt);
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub);
bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,std::vector<CTxOut> &payouts);
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,uint256& burntxid,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub, int64_t &amount);
bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, CTransaction &burnTx,std::vector<CTxOut> &payouts);
bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state);
@@ -45,4 +113,9 @@ void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, i
void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs);
int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs);
bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33]);
CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount);
int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull);
#endif /* IMPORTCOIN_H */

View File

@@ -35,6 +35,7 @@
#include "httprpc.h"
#include "key.h"
#include "notarisationdb.h"
#ifdef ENABLE_MINING
#include "key_io.h"
#endif
@@ -55,6 +56,7 @@
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif
#include <stdint.h>
#include <stdio.h>
@@ -89,9 +91,11 @@
using namespace std;
extern void ThreadSendAlert();
extern bool komodo_dailysnapshot(int32_t height);
extern int32_t KOMODO_LOADINGBLOCKS;
extern bool VERUS_MINTBLOCKS;
extern char ASSETCHAINS_SYMBOL[];
extern int32_t KOMODO_SNAPSHOT_INTERVAL;
ZCJoinSplit* pzcashParams = NULL;
@@ -1622,6 +1626,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain");
break;
}
if ( ASSETCHAINS_CC != 0 && KOMODO_SNAPSHOT_INTERVAL != 0 && chainActive.Height() >= KOMODO_SNAPSHOT_INTERVAL )
{
if ( !komodo_dailysnapshot(chainActive.Height()) )
{
strLoadError = _("daily snapshot failed, please reindex your chain.");
break;
}
}
if (!fReindex) {
uiInterface.InitMessage(_("Rewinding blocks if needed..."));

View File

@@ -128,6 +128,19 @@ public:
return ret;
}
std::string operator()(const libzcash::SaplingIncomingViewingKey& vk) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << vk;
std::vector<unsigned char> serkey(ss.begin(), ss.end());
std::vector<unsigned char> data;
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY), data);
memory_cleanse(serkey.data(), serkey.size());
memory_cleanse(data.data(), data.size());
return ret;
}
std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
};
@@ -175,6 +188,7 @@ public:
// perform ceiling division to get the number of 5-bit clusters.
const size_t ConvertedSaplingPaymentAddressSize = ((32 + 11) * 8 + 4) / 5;
const size_t ConvertedSaplingExtendedSpendingKeySize = (ZIP32_XSK_SIZE * 8 + 4) / 5;
const size_t ConvertedSaplingIncomingViewingKeySize = (32 * 8 + 4) / 5;
} // namespace
CKey DecodeSecret(const std::string& str)
@@ -346,7 +360,19 @@ libzcash::ViewingKey DecodeViewingKey(const std::string& str)
return ret;
}
}
memory_cleanse(data.data(), data.size());
data.clear();
auto bech = bech32::Decode(str);
if(bech.first == Params().Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY) &&
bech.second.size() == ConvertedSaplingIncomingViewingKeySize) {
// Bech32 decoding
data.reserve((bech.second.size() * 5) / 8);
if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
libzcash::SaplingIncomingViewingKey ret;
ss >> ret;
return ret;
}
}
return libzcash::InvalidEncoding();
}

View File

@@ -713,9 +713,9 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar
sp->MoMdepth = MoMdepth;
}
komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth);
if ( ASSETCHAINS_SYMBOL[0] != 0 )
//if ( ASSETCHAINS_SYMBOL[0] != 0 )
printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth);
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
if ( signedfp == 0 )
@@ -803,7 +803,10 @@ int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys
return(-1);
}
// int32_t !
// int32_t (!!!)
/*
read blackjok3rtt comments in main.cpp
*/
int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
{
static int32_t hwmheight;
@@ -897,8 +900,8 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
}
numvalid = bitweight(signedmask);
if ( ((height < 90000 || (signedmask & 1) != 0) && numvalid >= KOMODO_MINRATIFY) ||
(numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) ||
numvalid > (numnotaries/5) )
(numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) ||
numvalid > (numnotaries/5) )
{
if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0)
{
@@ -918,7 +921,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
fflush(signedfp);
}
transaction = i;
printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts);
printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts);
}
notarized = 1;
}
@@ -1014,7 +1017,9 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height);
if ( !fJustCheck && pindex->GetHeight() == hwmheight )
komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0);
} else fprintf(stderr,"komodo_connectblock: unexpected null pindex\n");
}
else
{ fprintf(stderr,"komodo_connectblock: unexpected null pindex\n"); return(0); }
//KOMODO_INITDONE = (uint32_t)time(NULL);
//fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight());
if (fJustCheck)
@@ -1025,6 +1030,12 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
return(1);
if ( notarisations.size() > 1 || (notarisations.size() == 1 && notarisations[0] != 1) )
return(-1);
fprintf(stderr,"komodo_connectblock: unxexpected behaviour when fJustCheck == true, report blackjok3rtt plz ! \n");
/* this needed by gcc-8, it counts here that control reaches end of non-void function without this.
by default, we count that if control reached here -> the valid notarization isnt in position 1 or there are too many notarizations in this block.
*/
return(-1);
}
else return(0);
}

View File

@@ -29,6 +29,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar
unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
bool EnsureWalletIsAvailable(bool avoidException);
extern bool fRequestShutdown;
extern CScript KOMODO_EARLYTXID_SCRIPTPUB;
int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew);
uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht);
@@ -75,7 +76,8 @@ int tx_height( const uint256 &hash ){
nHeight = it->second->GetHeight();
//fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight);
} else {
fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() );
// Unconfirmed xtns
//fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() );
}
return nHeight;
}
@@ -206,8 +208,11 @@ try_again:
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
/* printf("[ Decker ] SSL: %s\n", curl_version()); */
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // this is useful for debug, but seems crash on libcurl/7.64.1 OpenSSL/1.1.1b zlib/1.2.8 librtmp/2.3
}
if ( userpass != 0 )
curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
@@ -677,11 +682,32 @@ int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx);
int32_t komodo_isPoS(CBlock *pblock,int32_t height)
int32_t komodo_isPoS2(CBlock *pblock)
{
int32_t n,vout,numvouts; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
CBlockIndex *pindex = komodo_blockindex(pblock->GetHash());
if ( pindex != 0 && pindex->segid >= -1 )
{
//fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid);
if ( pindex->segid == -1 )
return(0);
else return(1);
}
return (-1);
}
int32_t komodo_isPoS(CBlock *pblock,int32_t height,bool fJustCheck)
{
int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
if ( ASSETCHAINS_STAKED != 0 )
{
if ( fJustCheck )
{
// check pindex first, if that does not work, continue with slow check.
if ( (ret= komodo_isPoS2(pblock)) == 1 )
return (1);
else if ( ret == 0 )
return (0);
}
n = pblock->vtx.size();
//fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size());
if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+(ASSETCHAINS_MARMARA!=0) )
@@ -1091,6 +1117,17 @@ int32_t komodo_blockheight(uint256 hash)
return(0);
}
uint32_t komodo_blocktime(uint256 hash)
{
BlockMap::const_iterator it; CBlockIndex *pindex = 0;
if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() )
{
if ( (pindex= it->second) != 0 )
return(pindex->nTime);
}
return(0);
}
int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
{
int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex;
@@ -1224,7 +1261,6 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
return(0);
int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0;
txn_count = pblock->vtx.size();
if ( ASSETCHAINS_FOUNDERS != 0 )
{
nSubsidy = GetBlockSubsidy(height,Params().GetConsensus());
@@ -1242,8 +1278,9 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
else commission = 0;
}
}
else
else if ( pblock != 0 )
{
txn_count = pblock->vtx.size();
for (i=0; i<txn_count; i++)
{
n = pblock->vtx[i].vout.size();
@@ -1385,10 +1422,6 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
percPoS = (percPoS*100) / (m+n);
else
// This seems to be inverse. The actual PoS % is backwards in the first 100 blocks.
// I dont't understand the math here, or why its backwards, so I am just disabling it for VerusHash.
// No doubt this is probably wrong for equihash aswell, we may need to test an equihash chain with the rule above.
// Need to ask james what the deal is here! Seems to be causeing ALL the problems.
percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
}
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 )
@@ -1569,7 +1602,7 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh
int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash)
{
CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; arith_uint256 POWTarget;
CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; arith_uint256 POWTarget;
if ( ASSETCHAINS_STAKED == 100 && height <= 10 )
return(1);
BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash());
@@ -1596,7 +1629,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
if ( slowflag != 0 && prevtime != 0 )
{
if ( komodo_isPoS(pblock,height) != 0 )
if ( komodo_isPoS(pblock,height,false) != 0 )
{
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"",PoSperc);
}
@@ -1628,7 +1661,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
}
else if ( slowflag == 0 ) // previous blocks are not seen yet, do the best approx
{
if ( komodo_isPoS(pblock,height) != 0 )
if ( komodo_isPoS(pblock,height,false) != 0 )
isPoS = 1;
}
if ( slowflag != 0 && isPoS != 0 )
@@ -1855,7 +1888,7 @@ uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount)
// Because of reorgs we cannot use the notarized height value.
// We need to basically guess here and just pay some static amount.
// Has the unwanted effect of varying coin emission, but cannot be helped.
fprintf(stderr, "era.%i paying total of %lu\n",curEra, ASSETCHAINS_NOTARY_PAY[curEra]);
//fprintf(stderr, "era.%i paying total of %lu\n",curEra, ASSETCHAINS_NOTARY_PAY[curEra]);
ret = ASSETCHAINS_NOTARY_PAY[curEra] / notarycount;
return(ret);
}
@@ -1870,13 +1903,8 @@ int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *sc
if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) )
{
memcpy(scriptbuf,script,len);
if ( komodo_voutupdate(true,&isratification,0,scriptbuf,len,height,uint256(),1,1,&voutmask,&specialtx,&notarizedheight,0,1,0,timestamp) == -2 )
if ( komodo_voutupdate(true,&isratification,0,scriptbuf,len,height,uint256(),1,1,&voutmask,&specialtx,&notarizedheight,0,1,0,timestamp) != -2 )
{
fprintf(stderr, ">>>>>>VALID NOTARIZATION ht.%i\n",notarizedheight);
}
else
{
// This should no longer happen. Unless notaries are making actual invalid notarizations.
fprintf(stderr, "<<<<<<INVALID NOTARIZATION ht.%i\n",notarizedheight);
return(0);
}
@@ -2029,15 +2057,83 @@ uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height)
}
if ( matches != 0 && matches == NotarisationNotaries.size() && totalsats == total )
{
fprintf(stderr, "Validated coinbase matches notarisation in tx position 1.\n" );
//fprintf(stderr, "Validated coinbase matches notarisation in tx position 1.\n" );
return(totalsats);
}
return(0);
}
bool komodo_appendACscriptpub()
{
static bool didinit = false;
if ( didinit )
return didinit;
if ( ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] == 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] == 51 )
{
CTransaction tx; uint256 blockhash;
// get transaction and check that it occured before height 100.
if ( myGetTransaction(KOMODO_EARLYTXID,tx,blockhash) && mapBlockIndex[blockhash]->GetHeight() < 100 )
{
for (int i = 0; i < tx.vout.size(); i++)
{
if ( tx.vout[i].scriptPubKey[0] == OP_RETURN )
{
ASSETCHAINS_SCRIPTPUB.pop_back(); ASSETCHAINS_SCRIPTPUB.pop_back(); // remove last 2 chars.
// get OP_RETURN from txid and append the HexStr of it to scriptpub
ASSETCHAINS_SCRIPTPUB.append(HexStr(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end()));
//fprintf(stderr, "ac_script.%s\n",ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
return true;
}
}
}
fprintf(stderr, "could not get KOMODO_EARLYTXID.%s OP_RETURN data. Restart with correct txid!\n", KOMODO_EARLYTXID.GetHex().c_str());
StartShutdown();
}
return false;
}
void GetKomodoEarlytxidScriptPub()
{
if ( KOMODO_EARLYTXID == zeroid )
{
fprintf(stderr, "Restart deamon with -earlytxid.\n");
StartShutdown();
return;
}
if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_SNAPSHOT_INTERVAL == 0 )
{
fprintf(stderr, "Prices->paymentsCC contract must have -ac_snapshot enabled to pay out.\n");
StartShutdown();
return;
}
if ( chainActive.Height() < 100 )
{
fprintf(stderr, "Cannot fetch -earlytxid before block 100.\n");
StartShutdown();
return;
}
CTransaction tx; uint256 blockhash; int32_t i;
// get transaction and check that it occured before height 100.
if ( myGetTransaction(KOMODO_EARLYTXID,tx,blockhash) && mapBlockIndex[blockhash]->GetHeight() < 100 )
{
for (i = 0; i < tx.vout.size(); i++)
if ( tx.vout[i].scriptPubKey[0] == OP_RETURN )
break;
if ( i < tx.vout.size() )
{
KOMODO_EARLYTXID_SCRIPTPUB = CScript(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end());
fprintf(stderr, "KOMODO_EARLYTXID_SCRIPTPUB.%s\n", HexStr(KOMODO_EARLYTXID_SCRIPTPUB.begin(),KOMODO_EARLYTXID_SCRIPTPUB.end()).c_str());
return;
}
}
fprintf(stderr, "INVALID -earlytxid, restart daemon with correct txid.\n");
StartShutdown();
}
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
{
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0;
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false;
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
checktoshis = komodo_commission(pblock,height);
@@ -2059,6 +2155,12 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
}
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
static bool didinit = false;
if ( !didinit && height > 100 && KOMODO_EARLYTXID != zeroid && komodo_appendACscriptpub() )
{
fprintf(stderr, "appended CC_op_return to ASSETCHAINS_SCRIPTPUB.%s\n", ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
}
if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) )
{
decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str());
@@ -2195,11 +2297,11 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
else if ( ASSETCHAINS_STAKED != 0 )
failed = 0;
}
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 )
{
if ( height == 1 )
{
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 )
{
int32_t scriptlen; uint8_t scripthex[10000];
script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0];
@@ -2211,7 +2313,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1);
} else return(-1);
}
else
else if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0];
scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size();
@@ -2418,7 +2520,6 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
komodo_segids(hashbuf,nHeight-101,100);
if ( *blocktimep < tipindex->nTime+60)
*blocktimep = tipindex->nTime+60;
//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
bool resetstaker = false;
if ( array != 0 )
@@ -2503,9 +2604,8 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
}
}
lasttime = (uint32_t)time(NULL);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
}
//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep);
block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
for (i=winners=0; i<numkp; i++)
{
@@ -2518,44 +2618,28 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
}
kp = &array[i];
eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address,PoSperc);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
if ( eligible > 0 )
{
besttime = m = 0;
besttime = 0;
if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address,PoSperc) )
{
while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address,PoSperc) )
// have elegible utxo to stake with.
if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
{
besttime = eligible;
eligible--;
if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier
break;
m++;
//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
// is better than the previous best, so use it instead.
earliest = eligible;
best_scriptPubKey = kp->scriptPubKey;
*utxovaluep = (uint64_t)kp->nValue;
decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str());
*utxovoutp = kp->vout;
*txtimep = kp->txtime;
}
}
else
{
//fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
continue;
}
eligible = besttime;
winners++;
//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
{
earliest = eligible;
best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey;
*utxovaluep = (uint64_t)kp->nValue;
//decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str());
decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str());
*utxovoutp = kp->vout;
*txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime;
//fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
}
} //else fprintf(stderr,"utxo not eligible\n");
if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier
break;
} else continue;
}
}
if ( numkp < 1000 && array != 0 )
if ( numkp < 500 && array != 0 )
{
free(array);
array = 0;
@@ -2574,7 +2658,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i];
txNew.vin[0].prevout.hash = revtxid;
txNew.vin[0].prevout.n = *utxovoutp;
txNew.vout[0].scriptPubKey = best_scriptPubKey;// CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
txNew.vout[0].scriptPubKey = best_scriptPubKey;
txNew.vout[0].nValue = *utxovaluep - txfee;
txNew.nLockTime = earliest;
CTransaction txNewConst(txNew);
@@ -2585,7 +2669,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
ptr = (uint8_t *)&sigdata.scriptSig[0];
siglen = sigdata.scriptSig.size();
for (i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
utxosig[i] = ptr[i];
}
else
{
@@ -2597,12 +2681,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
{
//fprintf(stderr," siglen.%d\n",siglen);
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest;
}
} //else fprintf(stderr,"no earliest utxo for staking\n");
//fprintf(stderr,"end scan of utxo for staking t.%u counter.%d numkp.%d winners.%d\n",(uint32_t)time(NULL),counter,numkp,winners);
}
return(siglen);
}

View File

@@ -15,6 +15,7 @@
#ifndef KOMODO_DEFS_H
#define KOMODO_DEFS_H
#include "komodo_nk.h"
#define ASSETCHAINS_MINHEIGHT 128
#define ASSETCHAINS_MAX_ERAS 3
@@ -30,6 +31,221 @@
#define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019
#define _COINBASE_MATURITY 100
// KMD Notary Seasons
// 1: May 1st 2018 1530921600
// 2: July 15th 2019 1563148800 -> estimated height 1444000
// 3: 3rd season ending isnt known, so use very far times in future.
// 1751328000 = dummy timestamp, 1 July 2025!
// 7113400 = 5x current KMD blockheight.
// to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays.
#define NUM_KMD_SEASONS 3
#define NUM_KMD_NOTARIES 64
static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, 1751328000};
static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, 7113400};
// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above.
static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] =
{
{
{ "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" },
{ "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" },
{ "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" },
{ "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" },
{ "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" },
{ "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" },
{ "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" },
{ "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" },
{ "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" },
{ "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" },
{ "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10
{ "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" },
{ "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" },
{ "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" },
{ "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" },
{ "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15
{ "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" },
{ "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" },
{ "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" },
{ "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" },
{ "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20
{ "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" },
{ "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" },
{ "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" },
{ "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" },
{ "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" },
{ "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" },
{ "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" },
{ "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" },
{ "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" },
{ "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30
{ "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" },
{ "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" },
{ "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" },
{ "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" },
{ "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" },
{ "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" },
{ "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" },
{ "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" },
{ "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" },
{ "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40
{ "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" },
{ "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" },
{ "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" },
{ "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" },
{ "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" },
{ "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" },
{ "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" },
{ "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" },
{ "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" },
{ "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50
{ "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" },
{ "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" },
{ "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" },
{ "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" },
{ "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" },
{ "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" },
{ "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" },
{ "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" },
{ "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" },
{ "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60
{ "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" },
{ "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" },
{ "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" }
},
{
{"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" },
{"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" },
{"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" },
{"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" },
{"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" },
{"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" },
{"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" },
{"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" },
{"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" },
{"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" },
{"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10
{"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" },
{"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" },
{"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" },
{"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" },
{"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" },
{"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" },
{"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" },
{"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" },
{"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" },
{"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20
{"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" },
{"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" },
{"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" },
{"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" },
{"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" },
{"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" },
{"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" },
{"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" },
{"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" },
{"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30
{"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" },
{"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" },
{"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" },
{"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" },
{"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" },
{"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" },
{"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" },
{"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" },
{"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" },
{"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40
{"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" },
{"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" },
{"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" },
{"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" },
{"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" },
{"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" },
{"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" },
{"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" },
{"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" },
{"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50
{"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" },
{"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" },
{"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" },
{"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" },
{"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" },
{"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" },
{"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" },
{"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" },
{"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" },
{"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60
{"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" },
{"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" },
{"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" },
},
{
{"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0
{"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" },
{"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" },
{"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" },
{"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" },
{"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" },
{"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" },
{"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" },
{"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" },
{"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" },
{"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10
{"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" },
{"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" },
{"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" },
{"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" },
{"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" },
{"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" },
{"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" },
{"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" },
{"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" },
{"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20
{"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" },
{"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" },
{"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" },
{"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" },
{"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" },
{"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" },
{"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" },
{"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" },
{"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" },
{"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30
{"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" },
{"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" },
{"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" },
{"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" },
{"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" },
{"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" },
{"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" },
{"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" },
{"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" },
{"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40
{"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" },
{"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" },
{"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" },
{"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" },
{"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" },
{"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" },
{"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" },
{"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" },
{"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" },
{"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50
{"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" },
{"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" },
{"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" },
{"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" },
{"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" },
{"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" },
{"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" },
{"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" },
{"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" },
{"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60
{"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" },
{"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" },
{"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63
}
};
#define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7)))
#define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7)))
#define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7)))
@@ -37,7 +253,12 @@
#define KOMODO_MAXNVALUE (((uint64_t)1 << 63) - 1)
#define KOMODO_BIT63SET(x) ((x) & ((uint64_t)1 << 63))
#define KOMODO_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN)
//#ifndef TESTMODE
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
//#else
//#define PRICES_DAYWINDOW (7)
//#endif
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
int32_t MAX_BLOCK_SIZE(int32_t height);
@@ -53,7 +274,7 @@ extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOM
extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET;
extern bool VERUS_MINTBLOCKS;
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2];
extern const char *ASSETCHAINS_ALGORITHMS[];
extern int32_t VERUS_MIN_STAKEAGE;
extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
@@ -62,7 +283,7 @@ extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS
extern std::vector<std::string> ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS;
extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD;
extern uint256 KOMODO_EARLYTXID;
extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE;
extern uint32_t ASSETCHAINS_CC;
@@ -76,15 +297,21 @@ extern int32_t VERUS_MIN_STAKEAGE;
extern std::string DONATION_PUBKEY;
extern uint8_t ASSETCHAINS_PRIVATE;
extern int32_t USE_EXTERNAL_PUBKEY;
extern char NOTARYADDRS[64][64];
extern char NOTARYADDRS[64][64]; // should be depreciated later. Only affects labs.
extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64];
extern int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL;
extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT;
int tx_height( const uint256 &hash );
extern std::vector<std::string> vWhiteListAddress;
extern std::map <std::int8_t, int32_t> mapHeightEvalActivate;
void komodo_netevent(std::vector<uint8_t> payload);
int32_t getacseason(uint32_t timestamp);
#define IGUANA_MAXSCRIPTSIZE 10001
#define KOMODO_KVDURATION 1440
#define KOMODO_KVBINARY 2
#define PRICES_SMOOTHWIDTH 1
#define PRICES_MAXDATAPOINTS 8
uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
@@ -92,12 +319,13 @@ char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,
int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width);
int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen);
uint32_t komodo_blocktime(uint256 hash);
int32_t komodo_longestchain();
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
int8_t komodo_segid(int32_t nocache,int32_t height);
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight);
char *komodo_pricename(char *name,int32_t ind);
int32_t komodo_priceind(char *symbol);
int32_t komodo_priceind(const char *symbol);
int32_t komodo_pricesinit();
int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip);
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth);
@@ -106,6 +334,7 @@ uint32_t komodo_heightstamp(int32_t height);
int64_t komodo_pricemult(int32_t ind);
int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks);
uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
int32_t komodo_currentheight();
#endif

View File

@@ -627,7 +627,7 @@ int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t to
const char *banned_txids[] =
{
"78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", //233559
"78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", // vout1 only 233559
"00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172
"e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187
"f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188
@@ -645,8 +645,24 @@ const char *banned_txids[] =
// all vouts banned
"c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748
"305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204
//"43416a0c4da6b1a5c1d375bdbe8f7dc8d44d8f60df593d3376aa8221ec66357e", // vout0 only
//"1eb295ed54c47f35cbccd7e7e40d03041f1853581da6d41102a9d8813782b6cb",
//"db121e4012222adfc841824984a2a90b7e5b018dd71307822537d58160195e43",
//"28f95b8148ac4ae6e09c7380e34422fab41d568a411e53dc94823e36a3d6f386",
//"01d8c839463bda2f2f6400ede4611357913684927a767422a8560ead1b22557c",
//"6e4980a9e1bd669f4df04732dc6f11b7773b6de88d1abcf89a6b9007d72ef9ac",
//"6cc1d0495170bc0e11fd3925297623562e529ea1336b66ea61f8a1159041aed2",
};
int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts)
{
if ( k < indallvouts )
return(vout == 1);
else if ( k == indallvouts || k == indallvouts+1 )
return(1);
else return(vout == 0);
}
int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max)
{
int32_t i;
@@ -691,7 +707,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim
{
for (k=0; k<numbanned; k++)
{
if ( block.vtx[i].vin[j].prevout.hash == array[k] && (block.vtx[i].vin[j].prevout.n == 1 || k >= indallvouts) )
if ( block.vtx[i].vin[j].prevout.hash == array[k] && komodo_checkvout(block.vtx[i].vin[j].prevout.n,k,indallvouts) != 0 ) //(block.vtx[i].vin[j].prevout.n == 1 || k >= indallvouts) )
{
printf("banned tx.%d being used at ht.%d txi.%d vini.%d\n",k,height,i,j);
return(-1);
@@ -1555,7 +1571,6 @@ extern std::vector<uint8_t> Mineropret; // opreturn data set by the data gatheri
#define KOMODO_LOCALPRICE_CACHESIZE 13
#define KOMODO_MAXPRICES 2048
#define PRICES_SMOOTHWIDTH 1
#define PRICES_MAXDATAPOINTS 8
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0)
@@ -2018,8 +2033,10 @@ int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector<std::string> s
{
char url[32768],*symbol,*timestr; cJSON *json,*obj; int32_t i,n=0,retval=-1; uint32_t uprice,timestamp;
sprintf(url,"https://api.iextrading.com/1.0/tops/last?symbols=%s",GetArg("-ac_stocks","").c_str());
if ( (json= send_curl(url,(char *)"iex")) != 0 ) //if ( (json= get_urljson(url)) != 0 )
fprintf(stderr,"url.(%s)\n",url);
if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"iex")) != 0 ) //
{
fprintf(stderr,"stocks.(%s)\n",jprint(json,0));
if ( (n= cJSON_GetArraySize(json)) > 0 )
{
retval = n;
@@ -2057,7 +2074,7 @@ uint32_t get_dailyfx(uint32_t *prices)
//{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"}
char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0;
sprintf(url,"https://api.openrates.io/latest?base=USD");
if ( (json= send_curl(url,(char *)"dailyfx")) != 0 )
if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"dailyfx")) != 0 )
{
if ( (rates= jobj(json,(char *)"rates")) != 0 )
{
@@ -2080,7 +2097,7 @@ uint32_t get_binanceprice(const char *symbol)
{
char url[512]; cJSON *json; uint32_t price = 0;
sprintf(url,"https://api.binance.com/api/v1/ticker/price?symbol=%sBTC",symbol);
if ( (json= send_curl(url,(char *)"bnbprice")) != 0 )
if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"bnbprice")) != 0 )
{
price = jdouble(json,(char *)"price")*SATOSHIDEN + 0.0000000049;
free_json(json);
@@ -2401,8 +2418,8 @@ char *komodo_pricename(char *name,int32_t ind)
}
return(0);
}
int32_t komodo_priceind(char *symbol)
// finds index for its symbol name
int32_t komodo_priceind(const char *symbol)
{
char name[65]; int32_t i,n = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t));
for (i=1; i<n; i++)
@@ -2413,7 +2430,7 @@ int32_t komodo_priceind(char *symbol)
}
return(-1);
}
// returns price value which is in a 10% interval for more than 50% points for the preceding 24 hours
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth)
{
int32_t i,j,k,n,iter,correlation,maxcorrelation=0; int64_t firstprice,price,sum,den,mult,refprice,lowprice,highprice;
@@ -2596,7 +2613,7 @@ static int cmp_llu(const void *a, const void*b)
else return(1);
}
static int64_t sort64(int64_t *l, int32_t llen)
static void sort64(int64_t *l, int32_t llen)
{
qsort(l,llen,sizeof(uint64_t),cmp_llu);
}
@@ -2610,7 +2627,7 @@ static int revcmp_llu(const void *a, const void*b)
else return(1);
}
static int64_t revsort64(int64_t *l, int32_t llen)
static void revsort64(int64_t *l, int32_t llen)
{
qsort(l,llen,sizeof(uint64_t),revcmp_llu);
}
@@ -2802,4 +2819,3 @@ int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblo
pthread_mutex_unlock(&pricemutex);
return(retval);
}

View File

@@ -29,6 +29,7 @@ uint64_t komodo_paxtotal();
int32_t komodo_longestchain();
uint64_t komodo_maxallowed(int32_t baseid);
int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max);
int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts);
pthread_mutex_t komodo_mutex,staked_mutex;
@@ -44,7 +45,7 @@ struct komodo_state KOMODO_STATES[34];
#define _COINBASE_MATURITY 100
int COINBASE_MATURITY = _COINBASE_MATURITY;//100;
unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10;
uint256 KOMODO_EARLYTXID;
int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,IS_STAKED_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS;
int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1;
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
@@ -53,6 +54,7 @@ bool VERUS_MINTBLOCKS;
std::vector<uint8_t> Mineropret;
std::vector<std::string> vWhiteListAddress;
char NOTARYADDRS[64][64];
char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64];
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096];
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT;
@@ -109,6 +111,12 @@ uint64_t PENDING_KOMODO_TX;
extern int32_t KOMODO_LOADINGBLOCKS;
unsigned int MAX_BLOCK_SIGOPS = 20000;
int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL;
CScript KOMODO_EARLYTXID_SCRIPTPUB;
int32_t ASSETCHAINS_EARLYTXIDCONTRACT;
std::map <std::int8_t, int32_t> mapHeightEvalActivate;
struct komodo_kv *KOMODO_KV;
pthread_mutex_t KOMODO_KV_mutex,KOMODO_CC_mutex;

10
src/komodo_nk.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef KOMODO_NK_H
#define KOMODO_NK_H
//#define ASSETCHAINS_N 77
//#define ASSETCHAINS_K 3
#define ASSETCHAINS_N 96
#define ASSETCHAINS_K 5
#endif

View File

@@ -20,6 +20,7 @@
#include "notaries_staked.h"
#define KOMODO_MAINNET_START 178999
#define KOMODO_NOTARIES_HEIGHT1 814000
const char *Notaries_genesis[][2] =
{
@@ -60,194 +61,78 @@ const char *Notaries_genesis[][2] =
{ "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" },
};
const char *Notaries_elected0[][2] =
{
{ "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" },
{ "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" },
{ "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" },
{ "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" },
{ "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" },
{ "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" },
{ "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" },
{ "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" },
{ "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" },
{ "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" },
{ "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10
{ "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" },
{ "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" },
{ "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" },
{ "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" },
{ "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15
{ "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" },
{ "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" },
{ "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" },
{ "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" },
{ "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20
{ "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" },
{ "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" },
{ "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" },
{ "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" },
{ "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" },
{ "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" },
{ "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" },
{ "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" },
{ "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" },
{ "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30
{ "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" },
{ "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" },
{ "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" },
{ "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" },
{ "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" },
{ "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" },
{ "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" },
{ "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" },
{ "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" },
{ "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40
{ "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" },
{ "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" },
{ "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" },
{ "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" },
{ "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" },
{ "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" },
{ "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" },
{ "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" },
{ "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" },
{ "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50
{ "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" },
{ "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" },
{ "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" },
{ "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" },
{ "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" },
{ "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" },
{ "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" },
{ "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" },
{ "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" },
{ "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60
{ "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" },
{ "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" },
{ "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" }
};
#define KOMODO_NOTARIES_TIMESTAMP1 1525132800 // May 1st 2018 1530921600 // 7/7/2017
#define KOMODO_NOTARIES_HEIGHT1 ((814000 / KOMODO_ELECTION_GAP) * KOMODO_ELECTION_GAP)
const char *Notaries_elected1[][2] =
{
{"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" },
{"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" },
{"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" },
{"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" },
{"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" },
{"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" },
{"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" },
{"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" },
{"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" },
{"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" },
{"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10
{"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" },
{"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" },
{"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" },
{"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" },
{"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" },
{"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" },
{"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" },
{"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" },
{"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" },
{"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20
{"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" },
{"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" },
{"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" },
{"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" },
{"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" },
{"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" },
{"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" },
{"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" },
{"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" },
{"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30
{"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" },
{"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" },
{"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" },
{"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" },
{"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" },
{"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" },
{"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" },
{"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" },
{"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" },
{"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40
{"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" },
{"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" },
{"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" },
{"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" },
{"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" },
{"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" },
{"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" },
{"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" },
{"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" },
{"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50
{"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" },
{"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" },
{"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" },
{"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" },
{"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" },
{"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" },
{"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" },
{"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" },
{"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" },
{"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60
{"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" },
{"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" },
{"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" },
};
#define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9"
int32_t getkmdseason(int32_t height)
{
if ( height <= KMD_SEASON_HEIGHTS[0] )
return(1);
for (int32_t i = 1; i < NUM_KMD_SEASONS; i++)
{
if ( height <= KMD_SEASON_HEIGHTS[i] && height >= KMD_SEASON_HEIGHTS[i-1] )
return(i+1);
}
return(0);
};
int32_t getacseason(uint32_t timestamp)
{
if ( timestamp <= KMD_SEASON_TIMESTAMPS[0] )
return(1);
for (int32_t i = 1; i < NUM_KMD_SEASONS; i++)
{
if ( timestamp <= KMD_SEASON_TIMESTAMPS[i] && timestamp >= KMD_SEASON_TIMESTAMPS[i-1] )
return(i+1);
}
return(0);
};
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp)
{
static uint8_t elected_pubkeys0[64][33],elected_pubkeys1[64][33],did0,did1; static int32_t n0,n1;
int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp;
static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33],didinit[NUM_KMD_SEASONS];
if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 )
timestamp = komodo_heightstamp(height);
else if ( ASSETCHAINS_SYMBOL[0] == 0 )
timestamp = 0;
// If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW.
if (is_STAKED(ASSETCHAINS_SYMBOL) == 0)
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 )
{
if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 )
timestamp = 0;
if ( (timestamp != 0 && timestamp <= KOMODO_NOTARIES_TIMESTAMP1) || (ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_NOTARIES_HEIGHT1) )
int32_t kmd_season = 0;
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
if ( did0 == 0 )
{
n0 = (int32_t)(sizeof(Notaries_elected0)/sizeof(*Notaries_elected0));
for (i=0; i<n0; i++) {
decode_hex(elected_pubkeys0[i],33,(char *)Notaries_elected0[i][1]);
}
did0 = 1;
}
memcpy(pubkeys,elected_pubkeys0,n0 * 33);
//if ( ASSETCHAINS_SYMBOL[0] != 0 )
//fprintf(stderr,"%s height.%d t.%u elected.%d notaries\n",ASSETCHAINS_SYMBOL,height,timestamp,n0);
return(n0);
// This is KMD, use block heights to determine the KMD notary season..
if ( height >= KOMODO_NOTARIES_HARDCODED )
kmd_season = getkmdseason(height);
}
else //if ( (timestamp != 0 && timestamp <= KOMODO_NOTARIES_TIMESTAMP2) || height <= KOMODO_NOTARIES_HEIGHT2 )
else
{
if ( did1 == 0 )
// This is a non LABS assetchain, use timestamp to detemine notary pubkeys.
kmd_season = getacseason(timestamp);
}
if ( kmd_season != 0 )
{
if ( didinit[kmd_season-1] == 0 )
{
n1 = (int32_t)(sizeof(Notaries_elected1)/sizeof(*Notaries_elected1));
for (i=0; i<n1; i++) {
decode_hex(elected_pubkeys1[i],33,(char *)Notaries_elected1[i][1]);
for (i=0; i<NUM_KMD_NOTARIES; i++)
decode_hex(kmd_pubkeys[kmd_season-1][i],33,(char *)notaries_elected[kmd_season-1][i][1]);
if ( ASSETCHAINS_PRIVATE != 0 )
{
// this is PIRATE, we need to populate the address array for the notary exemptions.
for (i = 0; i<NUM_KMD_NOTARIES; i++)
pubkey2addr((char *)NOTARY_ADDRESSES[kmd_season-1][i],(uint8_t *)kmd_pubkeys[kmd_season-1][i]);
}
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
fprintf(stderr,"%s height.%d t.%u elected.%d notaries2\n",ASSETCHAINS_SYMBOL,height,timestamp,n1);
did1 = 1;
didinit[kmd_season-1] = 1;
}
memcpy(pubkeys,elected_pubkeys1,n1 * 33);
return(n1);
memcpy(pubkeys,kmd_pubkeys[kmd_season-1],NUM_KMD_NOTARIES * 33);
return(NUM_KMD_NOTARIES);
}
}
else if (timestamp != 0)
{ // here we can activate our pubkeys for STAKED chains everythig is in notaries_staked.cpp
else if ( timestamp != 0 )
{
// here we can activate our pubkeys for LABS chains everythig is in notaries_staked.cpp
int32_t staked_era; int8_t numSN;
uint8_t staked_pubkeys[64][33];
staked_era = STAKED_era(timestamp);

View File

@@ -14,6 +14,7 @@
******************************************************************************/
#include "komodo_defs.h"
#include "key_io.h"
#include "cc/CCinclude.h"
#include <string.h>
#ifdef _WIN32
@@ -1425,7 +1426,7 @@ void komodo_configfile(char *symbol,uint16_t rpcport)
#ifndef FROM_CLI
if ( (fp= fopen(fname,"wb")) != 0 )
{
fprintf(fp,"rpcuser=user%u\nrpcpassword=pass%s\nrpcport=%u\nserver=1\ntxindex=1\nrpcworkqueue=256\nrpcallowip=127.0.0.1\n",crc,password,rpcport);
fprintf(fp,"rpcuser=user%u\nrpcpassword=pass%s\nrpcport=%u\nserver=1\ntxindex=1\nrpcworkqueue=256\nrpcallowip=127.0.0.1\nrpcbind=127.0.0.1\n",crc,password,rpcport);
fclose(fp);
printf("Created (%s)\n",fname);
} else printf("Couldnt create (%s)\n",fname);
@@ -1539,7 +1540,7 @@ uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extr
printf("ports\n");
}*/
char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1}\"";
char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1,\\\"notarypay\\\":%i}\"";
@@ -1667,16 +1668,33 @@ extern int64_t MAX_MONEY;
void komodo_cbopretupdate(int32_t forceflag);
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals);
int8_t equihash_params_possible(uint64_t n, uint64_t k)
{
/* To add more of these you also need to edit:
* equihash.cpp very end of file with the tempate to point to the new param numbers
* equihash.h
* line 210/217 (declaration of equihash class)
* Add this object to the following functions:
* EhInitialiseState
* EhBasicSolve
* EhOptimisedSolve
* EhIsValidSolution
* Alternatively change ASSETCHAINS_N and ASSETCHAINS_K in komodo_nk.h for fast testing.
*/
if ( k == 9 && (n == 200 || n == 210) )
return(0);
if ( k == 5 && (n == 150 || n == 144 || n == 96 || n == 48) )
return(0);
if ( k == ASSETCHAINS_K && n == ASSETCHAINS_N)
return(0);
return(-1);
}
void komodo_args(char *argv0)
{
extern const char *Notaries_elected1[][2];
std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256];
std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512];
IS_KOMODO_NOTARY = GetBoolArg("-notary", false);
IS_STAKED_NOTARY = GetArg("-stakednotary", -1);
if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) {
fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n");
StartShutdown();
}
memset(ccenables,0,sizeof(ccenables));
memset(disablebits,0,sizeof(disablebits));
if ( GetBoolArg("-gen", false) != 0 )
@@ -1688,23 +1706,31 @@ void komodo_args(char *argv0)
DONATION_PUBKEY = GetArg("-donation", "");
NOTARY_PUBKEY = GetArg("-pubkey", "");
KOMODO_DEALERNODE = GetArg("-dealer",0);
KOMODO_TESTNODE = GetArg("-testnode",0);
if ( strlen(NOTARY_PUBKEY.c_str()) == 66 )
{
decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str());
USE_EXTERNAL_PUBKEY = 1;
if ( IS_KOMODO_NOTARY == 0 )
{
// We dont have any chain data yet, so use system clock to guess.
// I think on season change should reccomend notaries to use -notary to avoid needing this.
int32_t kmd_season = getacseason(time(NULL));
for (i=0; i<64; i++)
if ( strcmp(NOTARY_PUBKEY.c_str(),Notaries_elected1[i][1]) == 0 )
if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[kmd_season][NUM_KMD_NOTARIES][1]) == 0 )
{
IS_KOMODO_NOTARY = 1;
KOMODO_MININGTHREADS = 1;
mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
IS_STAKED_NOTARY = -1;
fprintf(stderr,"running as notary.%d %s\n",i,Notaries_elected1[i][0]);
fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[kmd_season][NUM_KMD_NOTARIES][0]);
break;
}
}
}
if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) {
fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n");
StartShutdown();
}
name = GetArg("-ac_name","");
if ( argv0 != 0 )
@@ -1729,10 +1755,35 @@ void komodo_args(char *argv0)
ASSETCHAINS_BLOCKTIME = GetArg("-ac_blocktime",60);
ASSETCHAINS_PUBLIC = GetArg("-ac_public",0);
ASSETCHAINS_PRIVATE = GetArg("-ac_private",0);
KOMODO_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0);
Split(GetArg("-ac_nk",""), ASSETCHAINS_NK, 0);
// -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height....
Split(GetArg("-ac_ccactivateht",""), ccEnablesHeight, 0);
// fill map with all eval codes and activation height of 0.
for ( int i = 0; i < 256; i++ )
mapHeightEvalActivate[i] = 0;
for ( int i = 0; i < 512; i++ )
{
int32_t ecode = ccEnablesHeight[i];
int32_t ht = ccEnablesHeight[i+1];
if ( ecode > 256 )
fprintf(stderr, "ac_ccactivateht: invalid evalcode.%i must be between 0 and 256.\n", ecode);
else if ( ht > 0 )
{
// update global map.
mapHeightEvalActivate[ecode] = ht;
fprintf(stderr, "ac_ccactivateht: ecode.%i activates at height.%i\n", ecode, mapHeightEvalActivate[ecode]);
}
i++;
}
if ( (KOMODO_REWIND= GetArg("-rewind",0)) != 0 )
{
printf("KOMODO_REWIND %d\n",KOMODO_REWIND);
}
KOMODO_EARLYTXID = Parseuint256(GetArg("-earlytxid","0").c_str());
ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0);
if ( name.c_str()[0] != 0 )
{
std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0]));
@@ -1749,6 +1800,14 @@ void komodo_args(char *argv0)
break;
}
}
if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH && ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 )
{
if ( equihash_params_possible(ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]) == -1 )
{
printf("equihash values N.%li and K.%li are not currently available\n", ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]);
exit(0);
} else printf("ASSETCHAINS_ALGO, algorithm set to equihash with N.%li and K.%li\n", ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]);
}
if (i == ASSETCHAINS_NUMALGOS)
{
printf("ASSETCHAINS_ALGO, %s not supported. using equihash\n", selectedAlgo.c_str());
@@ -1901,7 +1960,12 @@ void komodo_args(char *argv0)
StartShutdown();
}
// else it can be gateway coin
else if (!ASSETCHAINS_SELFIMPORT.empty() && (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_SUPPLY>10 || ASSETCHAINS_COMMISSION!=0))
{
fprintf(stderr,"when using gateway import these must be set: -ac_end=1 -ac_supply=0 -ac_perc=0\n");
StartShutdown();
}
if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 )
ASSETCHAINS_STAKED = 100;
@@ -1974,7 +2038,7 @@ void komodo_args(char *argv0)
fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n");
StartShutdown();
}
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 )
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 )
{
fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size());
extraptr = extrabuf;
@@ -2034,6 +2098,7 @@ void komodo_args(char *argv0)
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS);
if ( ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
fprintf(stderr, "set founders reward.%li\n",ASSETCHAINS_FOUNDERS_REWARD);
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD);
}
}
@@ -2104,6 +2169,19 @@ void komodo_args(char *argv0)
komodo_cbopretupdate(1); // will set Mineropret
fprintf(stderr,"This blockchain uses data produced from CoinDesk Bitcoin Price Index\n");
}
if ( ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 )
{
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NK[0]),(void *)&ASSETCHAINS_NK[0]);
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NK[1]),(void *)&ASSETCHAINS_NK[1]);
}
if ( KOMODO_SNAPSHOT_INTERVAL != 0 )
{
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(KOMODO_SNAPSHOT_INTERVAL),(void *)&KOMODO_SNAPSHOT_INTERVAL);
}
if ( ASSETCHAINS_EARLYTXIDCONTRACT != 0 )
{
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_EARLYTXIDCONTRACT),(void *)&ASSETCHAINS_EARLYTXIDCONTRACT);
}
}
addn = GetArg("-seednode","");
@@ -2171,7 +2249,10 @@ void komodo_args(char *argv0)
sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL);
if ( (fp= fopen(fname,"wb")) != 0 )
{
fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146");
int8_t notarypay = 0;
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
notarypay = 1;
fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay);
fclose(fp);
//printf("created (%s)\n",fname);
} else printf("error creating (%s)\n",fname);
@@ -2237,6 +2318,66 @@ void komodo_args(char *argv0)
fprintf(stderr,"-ac_private for a non-PIRATE chain is not supported. The only reason to have an -ac_private chain is for total privacy and that is best achieved with the largest anon set. PIRATE has that and it is recommended to just use PIRATE\n");
StartShutdown();
}
// Set cc enables for all existing ac_cc chains here.
if ( strcmp("AXO",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("CCL",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("COQUI",ASSETCHAINS_SYMBOL) == 0 )
{
CCDISABLEALL;
CCENABLE(EVAL_DICE);
CCENABLE(EVAL_CHANNELS);
CCENABLE(EVAL_ORACLES);
CCENABLE(EVAL_ASSETS);
CCENABLE(EVAL_TOKENS);
}
if ( strcmp("DION",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("EQL",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("ILN",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("OUR",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("ZEXO",ASSETCHAINS_SYMBOL) == 0 )
{
// No CCs used on this chain yet.
CCDISABLEALL;
}
if ( strcmp("SEC",ASSETCHAINS_SYMBOL) == 0 )
{
CCDISABLEALL;
CCENABLE(EVAL_ASSETS);
CCENABLE(EVAL_TOKENS);
CCENABLE(EVAL_ORACLES);
}
if ( strcmp("KMDICE",ASSETCHAINS_SYMBOL) == 0 )
{
CCDISABLEALL;
CCENABLE(EVAL_FAUCET);
CCENABLE(EVAL_DICE);
CCENABLE(EVAL_ORACLES);
}
} else BITCOIND_RPCPORT = GetArg("-rpcport", BaseParams().RPCPort());
KOMODO_DPOWCONFS = GetArg("-dpowconfs",dpowconfs);
if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"SUPERNET") == 0 || strcmp(ASSETCHAINS_SYMBOL,"DEX") == 0 || strcmp(ASSETCHAINS_SYMBOL,"COQUI") == 0 || strcmp(ASSETCHAINS_SYMBOL,"PIRATE") == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDICE") == 0 )

View File

@@ -642,6 +642,106 @@ UniValue komodo_snapshot(int top)
return(result);
}
bool komodo_snapshot2(std::map <std::string, CAmount> &addressAmounts)
{
if ( fAddressIndex && pblocktree != 0 )
{
return pblocktree->Snapshot2(addressAmounts, 0);
}
else return false;
}
int32_t lastSnapShotHeight = 0;
std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
bool komodo_dailysnapshot(int32_t height)
{
int reorglimit = 100;
uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,undo_height,extraoffset;
// NOTE: To make this 100% safe under all sync conditions, it should be using a notarized notarization, from the DB.
// Under heavy reorg attack, its possible `komodo_notarized_height` can return a height that can't be found on chain sync.
// However, the DB can reorg the last notarization. By using 2 deep, we know 100% that the previous notarization cannot be reorged by online nodes,
// and as such will always be notarizing the same height. May need to check heights on scan back to make sure they are confirmed in correct order.
if ( (extraoffset= height % KOMODO_SNAPSHOT_INTERVAL) != 0 )
{
// we are on chain init, and need to scan all the way back to the correct height, other wise our node will have a diffrent snapshot to online nodes.
// use the notarizationsDB to scan back from the consesnus height to get the offset we need.
std::string symbol; Notarisation nota;
symbol.assign(ASSETCHAINS_SYMBOL);
if ( ScanNotarisationsDB(height-extraoffset, symbol, 100, nota) == 0 )
undo_height = height-extraoffset-reorglimit;
else undo_height = nota.second.height;
//fprintf(stderr, "height.%i-extraoffset.%i = startscanfrom.%i to get undo_height.%i\n", height, extraoffset, height-extraoffset, undo_height);
}
else
{
// we are at the right height in connect block to scan back to last notarized height.
notarized_height = komodo_notarized_height(&prevMoMheight,&notarized_hash,&notarized_desttxid);
notarized_height > height-reorglimit ? undo_height = notarized_height : undo_height = height-reorglimit;
}
fprintf(stderr, "doing snapshot for height.%i undo_height.%i\n", height, undo_height);
// if we already did this height dont bother doing it again, this is just a reorg. The actual snapshot height cannot be reorged.
if ( undo_height == lastSnapShotHeight )
return true;
std::map <std::string, int64_t> addressAmounts;
if ( !komodo_snapshot2(addressAmounts) )
return false;
// undo blocks in reverse order
for (int32_t n = height; n > undo_height; n--)
{
//fprintf(stderr, "undoing block.%i\n",n);
CBlockIndex *pindex; CBlock block;
if ( (pindex= komodo_chainactive(n)) == 0 || komodo_blockload(block, pindex) != 0 )
return false;
// undo transactions in reverse order
for (int32_t i = block.vtx.size() - 1; i >= 0; i--)
{
const CTransaction &tx = block.vtx[i];
CTxDestination vDest;
// loop vouts reverse order, remove value recieved.
for (unsigned int k = tx.vout.size(); k-- > 0;)
{
const CTxOut &out = tx.vout[k];
if ( ExtractDestination(out.scriptPubKey, vDest) )
{
addressAmounts[CBitcoinAddress(vDest).ToString()] -= out.nValue;
if ( addressAmounts[CBitcoinAddress(vDest).ToString()] < 1 )
addressAmounts.erase(CBitcoinAddress(vDest).ToString());
//fprintf(stderr, "VOUT: address.%s remove_coins.%li\n",CBitcoinAddress(vDest).ToString().c_str(), out.nValue);
}
}
// loop vins in reverse order, get prevout and return the sent balance.
for (unsigned int j = tx.vin.size(); j-- > 0;)
{
uint256 blockhash; CTransaction txin;
if ( !tx.IsCoinImport() && !tx.IsCoinBase() && myGetTransaction(tx.vin[j].prevout.hash,txin,blockhash) )
{
int vout = tx.vin[j].prevout.n;
if ( ExtractDestination(txin.vout[vout].scriptPubKey, vDest) )
{
//fprintf(stderr, "VIN: address.%s add_coins.%li\n",CBitcoinAddress(vDest).ToString().c_str(), txin.vout[vout].nValue);
addressAmounts[CBitcoinAddress(vDest).ToString()] += txin.vout[vout].nValue;
}
}
}
}
}
vAddressSnapshot.clear(); // clear existing snapshot
// convert address string to destination for easier conversion to what ever is required, eg, scriptPubKey.
for ( auto element : addressAmounts)
vAddressSnapshot.push_back(make_pair(element.second, DecodeDestination(element.first)));
// sort the vector by amount, highest at top.
std::sort(vAddressSnapshot.rbegin(), vAddressSnapshot.rend());
//for (int j = 0; j < 50; j++)
// fprintf(stderr, "j.%i address.%s nValue.%li\n",j, CBitcoinAddress(vAddressSnapshot[j].second).ToString().c_str(), vAddressSnapshot[j].first );
// include only top 3999 address.
if ( vAddressSnapshot.size() > 3999 ) vAddressSnapshot.resize(3999);
lastSnapShotHeight = undo_height;
fprintf(stderr, "vAddressSnapshot.size.%li\n", vAddressSnapshot.size());
return true;
}
//////////////////////////////////////////////////////////////////////////////
//
// mapOrphanTransactions
@@ -796,7 +896,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
} else if (txout.scriptPubKey.IsPayToCryptoCondition() == 0 && txout.IsDust(::minRelayTxFee)) {
} else if (whichType != TX_CRYPTOCONDITION && txout.IsDust(::minRelayTxFee)) {
reason = "dust";
return false;
}
@@ -1241,16 +1341,19 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState
if ( *(int32_t *)&array[0] == 0 )
numbanned = komodo_bannedset(&indallvouts,array,(int32_t)(sizeof(array)/sizeof(*array)));
n = tx.vin.size();
for (j=0; j<n; j++)
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
for (k=0; k<numbanned; k++)
for (j=0; j<n; j++)
{
if ( tx.vin[j].prevout.hash == array[k] && (tx.vin[j].prevout.n == 1 || k >= indallvouts) )
for (k=0; k<numbanned; k++)
{
static uint32_t counter;
if ( counter++ < 100 )
printf("MEMPOOL: banned tx.%d being used at ht.%d vout.%d\n",k,(int32_t)chainActive.Tip()->GetHeight(),j);
return(false);
if ( tx.vin[j].prevout.hash == array[k] && komodo_checkvout(tx.vin[j].prevout.n,k,indallvouts) != 0 ) //(tx.vin[j].prevout.n == 1 || k >= indallvouts) )
{
static uint32_t counter;
if ( counter++ < 100 )
printf("MEMPOOL: banned tx.%d being used at ht.%d vout.%d\n",k,(int32_t)chainActive.Tip()->GetHeight(),j);
return(false);
}
}
}
}
@@ -1273,25 +1376,24 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState
}
}
int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only
int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private chains only
{
static int32_t didinit; static char notaryaddrs[sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) + 1][64];
int32_t i;
if ( didinit == 0 )
int32_t season = getacseason(tiptime);
if ( NOTARY_ADDRESSES[season-1][0][0] == 0 )
{
uint8_t pubkey33[33];
for (i=0; i<=sizeof(Notaries_elected1)/sizeof(*Notaries_elected1); i++)
{
if ( i < sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) )
decode_hex(pubkey33,33,(char *)Notaries_elected1[i][1]);
else decode_hex(pubkey33,33,(char *)CRYPTO777_PUBSECPSTR);
pubkey2addr((char *)notaryaddrs[i],(uint8_t *)pubkey33);
}
didinit = 1;
uint8_t pubkeys[64][33];
komodo_notaries(pubkeys,0,tiptime);
}
for (i=0; i<=sizeof(Notaries_elected1)/sizeof(*Notaries_elected1); i++)
if ( strcmp(coinaddr,notaryaddrs[i]) == 0 )
if ( strcmp(coinaddr,CRYPTO777_KMDADDR) == 0 )
return(1);
for (int32_t i = 0; i < NUM_KMD_NOTARIES; i++)
{
if ( strcmp(coinaddr,NOTARY_ADDRESSES[season-1][i]) == 0 )
{
//fprintf(stderr, "coinaddr.%s notaryaddress[%i].%s\n",coinaddr,i,NOTARY_ADDRESSES[season-1][i]);
return(1);
}
}
return(0);
}
@@ -1384,7 +1486,7 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio
//
char destaddr[65];
Getscriptaddress(destaddr,txout.scriptPubKey);
if ( komodo_isnotaryvout(destaddr) == 0 )
if ( komodo_isnotaryvout(destaddr,tiptime) == 0 )
{
invalid_private_taddr = 1;
//return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain");
@@ -3003,7 +3105,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
*pfClean = false;
bool fClean = true;
komodo_disconnect(pindex,block);
//komodo_disconnect(pindex,block); does nothing?
CBlockUndo blockUndo;
CDiskBlockPos pos = pindex->GetUndoPos();
if (pos.IsNull())
@@ -3096,7 +3198,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr);
// undo spending activity
addressIndex.push_back(make_pair(CAddressIndexKey(keyType, addrHash, pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1));
// restore unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
}
@@ -3269,7 +3370,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
auto verifier = libzcash::ProofVerifier::Strict();
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
int32_t futureblock;
CAmount blockReward = 0;
CAmount blockReward = 0; uint64_t notarypaycheque = 0;
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
if (!CheckBlock(&futureblock,pindex->GetHeight(),pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
{
@@ -3292,7 +3393,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
{
// do a full block scan to get notarisation position and to enforce a valid notarization is in position 1.
// if notarisation in the block, must be position 1 and the coinbase must pay notaries.
int notarisationTx = komodo_connectblock(true,pindex,*(CBlock *)&block);
int32_t notarisationTx = komodo_connectblock(true,pindex,*(CBlock *)&block);
// -1 means that the valid notarization isnt in position 1 or there are too many notarizations in this block.
if ( notarisationTx == -1 )
return state.DoS(100, error("ConnectBlock(): Notarization is not in TX position 1 or block contains more than 1 notarization! Invalid Block!"),
@@ -3307,8 +3408,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("ConnectBlock(): Notaries have not been paid!"),
REJECT_INVALID, "bad-cb-amount");
// calculate the notaries compensation and validate the amounts and pubkeys are correct.
uint64_t notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->GetHeight());
fprintf(stderr, "notarypaycheque.%lu\n", notarypaycheque);
notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->GetHeight());
//fprintf(stderr, "notarypaycheque.%lu\n", notarypaycheque);
if ( notarypaycheque > 0 )
blockReward += notarypaycheque;
else
@@ -3497,8 +3598,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
fprintf(stderr,"valueout %.8f too big\n",(double)valueout/COIN);
return state.DoS(100, error("ConnectBlock(): GetValueOut too big"),REJECT_INVALID,"tx valueout is too big");
}
prevsum = voutsum;
voutsum += valueout;
//prevsum = voutsum;
//voutsum += valueout;
/*if ( KOMODO_VALUETOOBIG(voutsum) != 0 )
{
fprintf(stderr,"voutsum %.8f too big\n",(double)voutsum/COIN);
@@ -3714,6 +3815,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
//FlushStateToDisk();
komodo_connectblock(false,pindex,*(CBlock *)&block); // dPoW state update.
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
{
// Update the notary pay with the latest payment.
pindex->nNotaryPay = pindex->pprev->nNotaryPay + notarypaycheque;
//fprintf(stderr, "total notary pay.%li\n", pindex->nNotaryPay);
}
return true;
}
@@ -3923,6 +4030,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
DisconnectNotarisations(block);
}
pindexDelete->segid = -2;
pindexDelete->nNotaryPay = 0;
pindexDelete->newcoins = 0;
pindexDelete->zfunds = 0;
@@ -3943,7 +4051,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
CValidationState stateDummy;
// don't keep staking or invalid transactions
if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight(),true) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
{
mempool.remove(tx, removed, true);
}
@@ -3975,11 +4083,11 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
{
CTransaction &tx = block.vtx[i];
//if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0))))
if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)))
if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight(),true) != 0)))
{
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->EraseFromWallet(tx.GetHash());
if ( !GetBoolArg("-disablewallet", false) )
pwalletMain->EraseFromWallet(tx.GetHash());
#endif
}
else
@@ -4156,6 +4264,16 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
komodo_pricesupdate(pindexNew->GetHeight(),pblock);
if ( ASSETCHAINS_SAPLING <= 0 && pindexNew->nTime > KOMODO_SAPLING_ACTIVATION - 24*3600 )
komodo_activate_sapling(pindexNew);
if ( ASSETCHAINS_CC != 0 && KOMODO_SNAPSHOT_INTERVAL != 0 && (pindexNew->GetHeight() % KOMODO_SNAPSHOT_INTERVAL) == 0 && pindexNew->GetHeight() >= KOMODO_SNAPSHOT_INTERVAL )
{
uint64_t start = time(NULL);
if ( !komodo_dailysnapshot(pindexNew->GetHeight()) )
{
fprintf(stderr, "daily snapshot failed, please reindex your chain\n");
StartShutdown();
}
fprintf(stderr, "snapshot completed in: %lu seconds\n", time(NULL)-start);
}
return true;
}
@@ -4980,7 +5098,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
CValidationState state;
CTransaction Tx;
const CTransaction &tx = (CTransaction)block.vtx[i];
if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height) != 0)))
if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height,true) != 0)))
continue;
Tx = tx;
if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync
@@ -6095,7 +6213,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
}
LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->GetHeight(), nGoodTransactions);
return true;
}
@@ -6360,7 +6478,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
try {
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
//CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
CBufferedFile blkdat(fileIn, 32*MAX_BLOCK_SIZE(10000000), MAX_BLOCK_SIZE(10000000)+8, SER_DISK, CLIENT_VERSION);
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE(10000000), MAX_BLOCK_SIZE(10000000)+8, SER_DISK, CLIENT_VERSION);
uint64_t nRewind = blkdat.GetPos();
while (!blkdat.eof()) {
boost::this_thread::interruption_point();
@@ -6387,15 +6505,15 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
}
try {
// read block
CBlock block;
uint64_t nBlockPos = blkdat.GetPos();
if (dbp)
dbp->nPos = nBlockPos;
blkdat.SetLimit(nBlockPos + nSize);
blkdat.SetPos(nBlockPos);
CBlock block;
blkdat >> block;
nRewind = blkdat.GetPos();
// detect out of order blocks, and store them for later
uint256 hash = block.GetHash();
if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) {
@@ -6413,8 +6531,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
nLoaded++;
if (state.IsError())
break;
} else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->GetHeight() % 1000 == 0) {
LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->GetHeight());
} else if (hash != chainparams.GetConsensus().hashGenesisBlock && komodo_blockheight(hash) % 1000 == 0) {
LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), komodo_blockheight(hash));
}
// Recursively process earlier encountered successors of this block
@@ -6426,6 +6544,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
while (range.first != range.second) {
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
if (ReadBlockFromDisk(mapBlockIndex.count(hash)!=0?mapBlockIndex[hash]->GetHeight():0,block, it->second,1))
{
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),

View File

@@ -88,7 +88,7 @@ static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 100;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default for -txexpirydelta, in number of blocks */
static const unsigned int DEFAULT_TX_EXPIRY_DELTA = 20;
static const unsigned int DEFAULT_TX_EXPIRY_DELTA = 200;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
static const unsigned int MAX_TEMPFILE_SIZE = 0x1000000; // 16 MiB 0x8000000

View File

@@ -156,6 +156,7 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &Notar
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len);
CScript komodo_mineropret(int32_t nHeight);
bool komodo_appendACscriptpub();
CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
{
@@ -290,9 +291,9 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
txvalue = tx.GetValueOut();
if ( KOMODO_VALUETOOBIG(txvalue) != 0 )
continue;
if ( KOMODO_VALUETOOBIG(txvalue + voutsum) != 0 )
continue;
voutsum += txvalue;
//if ( KOMODO_VALUETOOBIG(txvalue + voutsum) != 0 ) // has been commented from main.cpp ?
// continue;
//voutsum += txvalue;
if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 )
{
//fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure nHeight.%d nTime.%u vs locktime.%u\n",nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime);
@@ -371,7 +372,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
}
dPriority += (double)nValueIn * nConf;
}
if ( numSN != 0 && TMP_NotarisationNotaries.size() >= numSN / 5 )
if ( numSN != 0 && notarypubkeys[0][0] != 0 && TMP_NotarisationNotaries.size() >= numSN / 5 )
{
// check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems)
std::set<int> checkdupes( TMP_NotarisationNotaries.begin(), TMP_NotarisationNotaries.end() );
@@ -418,7 +419,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
NotarisationNotaries = TMP_NotarisationNotaries;
dPriority = 1e16;
fNotarisationBlock = true;
fprintf(stderr, "Notarisation %s set to maximum priority\n",hash.ToString().c_str());
//fprintf(stderr, "Notarisation %s set to maximum priority\n",hash.ToString().c_str());
}
}
}
@@ -652,6 +653,12 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
txNew.vout[1].nValue = commission;
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
static bool didinit = false;
if ( !didinit && nHeight > 100 && KOMODO_EARLYTXID != zeroid && komodo_appendACscriptpub() )
{
fprintf(stderr, "appended ccopreturn to ASSETCHAINS_SCRIPTPUB.%s\n", ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
}
//fprintf(stderr,"mine to -ac_script\n");
//txNew.vout[1].scriptPubKey = CScript() << ParseHex();
int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
@@ -721,7 +728,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
}
return(0);
}
fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
//fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
} else fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
}
if ( ASSETCHAINS_CBOPRET != 0 )
@@ -803,12 +810,17 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
//fprintf(stderr,"check validity\n");
if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) // invokes CC checks
{
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
{
LEAVE_CRITICAL_SECTION(cs_main);
LEAVE_CRITICAL_SECTION(mempool.cs);
}
throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
}
//fprintf(stderr,"valid\n");
}
}
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
{
LEAVE_CRITICAL_SECTION(cs_main);
LEAVE_CRITICAL_SECTION(mempool.cs);
@@ -895,14 +907,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake)
{
CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i,len;
if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 )
if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 )
{
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
pubkey = ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY);
scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG;
}
else
else
{
len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
len >>= 1;
@@ -1044,7 +1056,7 @@ int32_t roundrobin_delay;
arith_uint256 HASHTarget,HASHTarget_POW;
// wait for peers to connect
int32_t waitForPeers(const CChainParams &chainparams)
void waitForPeers(const CChainParams &chainparams)
{
if (chainparams.MiningRequiresPeers())
{
@@ -1608,9 +1620,10 @@ void static BitcoinMiner()
if ( notaryid != My_notaryid )
My_notaryid = notaryid;
std::string solver;
//if ( notaryid >= 0 || ASSETCHAINS_SYMBOL[0] != 0 )
solver = "tromp";
//else solver = "default";
if ( ASSETCHAINS_NK[0] == 0 && ASSETCHAINS_NK[1] == 0 )
solver = "tromp";
else
solver = "default";
assert(solver == "tromp" || solver == "default");
LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k);
if ( ASSETCHAINS_SYMBOL[0] != 0 )
@@ -1951,11 +1964,11 @@ void static BitcoinMiner()
ehSolverRuns.increment();
if (found) {
int32_t i; uint256 hash = pblock->GetHash();
for (i=0; i<32; i++)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height);
FOUND_BLOCK = 1;
KOMODO_MAYBEMINED = Mining_height;
//for (i=0; i<32; i++)
// fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
//fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height);
//FOUND_BLOCK = 1;
//KOMODO_MAYBEMINED = Mining_height;
break;
}
} catch (EhSolverCancelledException&) {
@@ -1968,12 +1981,12 @@ void static BitcoinMiner()
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
// Regtest mode doesn't require peers
if ( FOUND_BLOCK != 0 )
/*if ( FOUND_BLOCK != 0 )
{
FOUND_BLOCK = 0;
fprintf(stderr,"FOUND_BLOCK!\n");
//sleep(2000);
}
} */
if (vNodes.empty() && chainparams.MiningRequiresPeers())
{
if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT )

View File

@@ -18,7 +18,7 @@ int8_t is_STAKED(const char *chain_name)
if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0)
return(STAKED);
else STAKED = 0;
if ( (strcmp(chain_name, "LABS") == 0) || (strcmp(chain_name, "LABSTH") == 0) )
if ( (strcmp(chain_name, "LABS") == 0) )
STAKED = 1; // These chains are allowed coin emissions.
else if ( (strncmp(chain_name, "LABS", 4) == 0) )
STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed.
@@ -113,7 +113,14 @@ void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) {
// staked era is set.
pthread_mutex_lock(&staked_mutex);
for (int i = 0; i<numNotaries; i++)
{
pubkey2addr((char *)NOTARYADDRS[i],(uint8_t *)pubkeys[i]);
if ( memcmp(NOTARY_PUBKEY33,pubkeys[i],33) == 0 )
{
NOTARY_ADDRESS.assign(NOTARYADDRS[i]);
IS_STAKED_NOTARY = i;
}
}
pthread_mutex_unlock(&staked_mutex);
}
}

View File

@@ -5,115 +5,62 @@
#include "crosschain.h"
#include "cc/CCinclude.h"
static const int32_t iguanaPort = 9997;
static const int32_t iguanaPort = 9333;
static const int8_t BTCminsigs = 13;
static const int8_t overrideMinSigs = 6;
static const int8_t overrideMinSigs = 7;
static const char *iguanaSeeds[8][1] =
{
{"80.240.17.222"},
{"94.23.1.95"},
{"103.6.12.112"},
{"18.224.176.46"},
{"45.76.120.247"},
{"185.62.57.32"},
{"103.6.12.112"},
{"103.6.12.112"},
{"103.6.12.112"},
{"149.28.253.160"},
{"68.183.226.124"},
{"149.28.246.230"},
};
static const int STAKED_ERA_GAP = 777;
static const int NUM_STAKED_ERAS = 4;
static const int STAKED_NOTARIES_TIMESTAMP[NUM_STAKED_ERAS] = {1542964044, 1549188000, 1604233333, 1604244444};
static const int32_t num_notaries_STAKED[NUM_STAKED_ERAS] = { 17, 25, 19, 17 };
static const int STAKED_NOTARIES_TIMESTAMP[NUM_STAKED_ERAS] = {1604244444, 1604244444, 1604244444, 1604244444};
static const int32_t num_notaries_STAKED[NUM_STAKED_ERAS] = { 22, 1, 1, 1 };
// Era array of pubkeys.
static const char *notaries_STAKED[NUM_STAKED_ERAS][64][2] =
{
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "03f87f1bccb744d90fdbf7fad1515a98e9fc7feb1800e460d2e7565b88c3971bf3" }, //RMwEpnaVe3cesWbMqqKYPPkaLcDkooTDgZ
{"smk762", "02eacef682d2f86e0103c18f4da46116e17196f3fb8f73ed931acb78e81d8e1aa5" }, // RQVvzJ8gepCDVjhqCAc5Tia1kTmt8KDPL9
{"jorian", "02150c410a606b898bcab4f083e48e0f98a510e0d48d4db367d37f318d26ae72e3" }, // RFgzxZe2P4RWKx6E9QGPK3rx3TXeWxSqa8
{"blackjok3r", "035fc678bf796ad52f69e1f5759be54ec671c559a22adf27eed067e0ddf1531574" }, // RTcYRJ6WopYkUqcmksyjxoV1CueYyqxFuk right
{"Alright", "02b718c60a035f77b7103a507d36aed942b4f655b8d13bce6f28b8eac523944278" }, //RG77F4mQpP1K1q2CDSc2vZSJvKUZgF8R26
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8 right
{"CrisF", "03745656c8991c4597828aad2820760c43c00ff2e3b381fef3b5c040f32a7b3a34" }, // RNhYJAaPHJCVXGWNVEJeP3TfepEPdhjrRr right
{"smk762", "02381616fbc02d3f0398c912fe7b7daf2f3f29e55dc35287f686b15686d8135a9f" }, // RSchwBApVquaG6mXH31bQ6P83kMN4Hound right
{"jorian", "0343eec31037d7b909efd968a5b5e7af60321bf7e464da28f815f0fb23ee7aadd7" }, // RJorianBXNwfNDYPxtNYJJ6vX7Z3VdTR25 right
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" }, //RN2KsQGW36Ah4NorJDxLJp2xiYJJEzk9Y6
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL right
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2 right
{"gt", "02312dcecb6e4a32927a075972d3c009f3c68635d8100562cc1813ea66751b9fde" }, // RCg4tzKWQ7i3wrZEU8bvCbCQ4xRJnHnyoo right
{"CMaurice", "026c6d094523e810641b89f2d7f0ddd8f0b59d97c32e1fa97f0e3e0ac119c26ae4" }, // RSjayeSuYUE1E22rBjnqoexobaRjbAZ2Yb right
{"Bar_F1sh_Rel", "0395f2d9dd9ccb78caf74bff49b6d959afb95af746462e1b35f4a167d8e82b3666" }, // RBbLxJagCA9QHDazQvfnDZe874V1K4Gu8t
{"jusoaresf", "02dfb7ed72a23f6d07f0ea2f28192ee174733cc8412ec0f97b073007b78fab6346" }, // RBQGfE5Hxsjm1BPraTxbneRuNasPDuoLnu
{"mylo", "03f6b7fcaf0b8b8ec432d0de839a76598b78418dadd50c8e5594c0e557d914ec09" }, // RXN4hoZkhUkkrnef9nTUDw3E3vVALAD8Kx
{"blackjok3r2", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"blackjok3r3", "03c3e4c0206551dbf3a4b24d18e5d2737080541184211e3bfd2b1092177410b9c2" }, // RMMav2AVse5XHPvDfTzRpMbFhK3GqFmtSN
{"kmdkrazy", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"alrighttest", "02e9dfe248f453b499315a90375e58a1c9ad79f5f3932ecb2205399a0f262d65fc" }, // RBevSstS8JtDXMEFNcJws4QTYN4PcE2VL5
{"alrighttest1", "03527c7ecd6a8c5db6d685a64e6e18c1edb49e2f057a434f56c3f1253a26e9c6a2" }, // RBw2jNU3dnGk86ZLqPMadJwRwg3NU8eC6s
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "024d19acf0d5de212cdd50326cd143292545d366a71b2b9c6df9f2110de2dfa1f2" }, // RKtAD2kyRRMx4EiG1eeTNprF5h2nmGbzzu
{"smk762", "029f6c1f38c4d6825acb3b4b5147f7992e943b617cdaa0f4f5f36187e239d52d5a" }, // RPy6Xj2LWrxNoEW9YyREDgBZDZZ5qURXBU
{"jorian", "0288e682c1ac449f1b85c4acb2d0bcd216d5df34c15fd18b8a8dd5fa64b8ece8ef" }, // RR1yT5aB19VwFoUCGTW4q4pk4qmhHEEE4t
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" }, //RN2KsQGW36Ah4NorJDxLJp2xiYJJEzk9Y6
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2
{"jusoaresf", "02dfb7ed72a23f6d07f0ea2f28192ee174733cc8412ec0f97b073007b78fab6346" }, // RBQGfE5Hxsjm1BPraTxbneRuNasPDuoLnu
{"mylo", "03f6b7fcaf0b8b8ec432d0de839a76598b78418dadd50c8e5594c0e557d914ec09" }, // RXN4hoZkhUkkrnef9nTUDw3E3vVALAD8Kx
{"greentea", "02054c14ae81838a063d22a75eaa3c961415f6825a57c8b8e4148d19dad64f128e" }, // REF7R76WpL1v7nSXjjiNHtRa2xYtq5qk1p
{"CMaurice", "025830ce81bd1301fb67d5872344efa7a9ff99ae85fe1234f18c085db9072b740f" }, // RX7pXUaV24xFn6DVKV8t3PrRF3gKw6TBjf
{"kmdkrazy", "02da444a2627d420f1f622fcdfb9bddb67d6d4241ad6b4d5054716ddbde8a25dfb" }, // RJPJBbHcm5mkAxhkkERHRfEE9Cvkr4Euoi
{"Bar_F1sh_Rel", "0395f2d9dd9ccb78caf74bff49b6d959afb95af746462e1b35f4a167d8e82b3666" }, // RBbLxJagCA9QHDazQvfnDZe874V1K4Gu8t
{"zatJUM", "030fff499b6dc0215344b28a0b6b4becdfb00cd34cd1b36b983ec14f47965fd4bc" }, // RSoEDLBasth7anxS8gbkg6KgeGiz8rhqv1
{"zatJUM", "030fff499b6dc0215344b28a0b6b4becdfb00cd34cd1b36b983ec14f47965fd4bc" }, // RSoEDLBasth7anxS8gbkg6KgeGiz8rhqv1 right
{"dwy", "03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff" }, // RKhZMqRF361FSGFAzstP5AhozekPjoVh5q
{"dukeleto", "03e4322510ee46d417b8382fe124f5a381a3cef6aef08f8a4e90c66a42a04b4015" }, // RB8vS1fkGuttoNYkA2B1ivNn8vhqbCEqbe
{"gcharang", "03336ca9db27cb6e882830e20dc525884e27dc94d557a5e68b972a5cbf9e8c62a8" }, // RJYiWn3FRCSSLf9Pe5RJcbrKQYosaMburP
{"ca333", "03a18a33313ccdbf3c9778776e33c423e073ff5833fa1de092ce9e921de52f22f6" }, // RX333A56jWdeW15MwZsaW3mHxGaDu2Yutp
{"computergenie", "03448ce28fb21748e8b05bbe32d6b1e758b589ac1eb359e5d552f8868f2b75dc92" }, // RGeniexxkjnR34hg7ZnCf36kmfuJusf6rE
{"gcharang", "021569dd350d99e685a739c5b36bd01f217efb4f448a6f9a56da80c5edf6ce20ee" }, // RE8SsNwhYoygXJSvw9DuQbJicDc28dwR78 right
{"computergenie", "027313dabde94fb72f823231d0a1c59fc7baa2e5b3bb2af97ca7d70aae116026b9" }, // RLabsCGxTRqJcJvz6foKuXAB61puJ2x8yt right
{"daemonfox", "0383484bdc745b2b953c85b5a0c496a1f27bc42ae971f15779ed1532421b3dd943" }, //
{"SHossain", "02791f5c215b8a19c143a98e3371ff03b5613df9ac430c4a331ca55fed5761c800" }, // RKdLoHkyeorXmMtj91B1AAnAGiwsdt9MdF
{"Nabob", "03ee91c20b6d26e3604022f42df6bb8de6f669da4591f93b568778cba13d9e9ddf" }, // RRwCLPZDzpHEFJnLev4phy51e2stHRUAaU
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "024d19acf0d5de212cdd50326cd143292545d366a71b2b9c6df9f2110de2dfa1f2" }, // RKtAD2kyRRMx4EiG1eeTNprF5h2nmGbzzu
{"smk762", "029f6c1f38c4d6825acb3b4b5147f7992e943b617cdaa0f4f5f36187e239d52d5a" }, // RPy6Xj2LWrxNoEW9YyREDgBZDZZ5qURXBU
{"jorian", "0288e682c1ac449f1b85c4acb2d0bcd216d5df34c15fd18b8a8dd5fa64b8ece8ef" }, // RR1yT5aB19VwFoUCGTW4q4pk4qmhHEEE4t
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2
{"greentea", "02054c14ae81838a063d22a75eaa3c961415f6825a57c8b8e4148d19dad64f128e" }, // REF7R76WpL1v7nSXjjiNHtRa2xYtq5qk1p
{"CMaurice", "025830ce81bd1301fb67d5872344efa7a9ff99ae85fe1234f18c085db9072b740f" }, // RX7pXUaV24xFn6DVKV8t3PrRF3gKw6TBjf
{"Bar_F1sh_Rel", "0395f2d9dd9ccb78caf74bff49b6d959afb95af746462e1b35f4a167d8e82b3666" }, // RBbLxJagCA9QHDazQvfnDZe874V1K4Gu8t
{"zatJUM", "030fff499b6dc0215344b28a0b6b4becdfb00cd34cd1b36b983ec14f47965fd4bc" }, // RSoEDLBasth7anxS8gbkg6KgeGiz8rhqv1
{"dwy", "03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff" }, // RKhZMqRF361FSGFAzstP5AhozekPjoVh5q
{"gcharang", "03336ca9db27cb6e882830e20dc525884e27dc94d557a5e68b972a5cbf9e8c62a8" }, // RJYiWn3FRCSSLf9Pe5RJcbrKQYosaMburP
{"computergenie", "03448ce28fb21748e8b05bbe32d6b1e758b589ac1eb359e5d552f8868f2b75dc92" }, // RGeniexxkjnR34hg7ZnCf36kmfuJusf6rE
{"daemonfox", "0383484bdc745b2b953c85b5a0c496a1f27bc42ae971f15779ed1532421b3dd943" }, //
{"SHossain", "02791f5c215b8a19c143a98e3371ff03b5613df9ac430c4a331ca55fed5761c800" }, // RKdLoHkyeorXmMtj91B1AAnAGiwsdt9MdF
{"Nabob", "03ee91c20b6d26e3604022f42df6bb8de6f669da4591f93b568778cba13d9e9ddf" }, // RRwCLPZDzpHEFJnLev4phy51e2stHRUAaU
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "03f87f1bccb744d90fdbf7fad1515a98e9fc7feb1800e460d2e7565b88c3971bf3" }, //RMwEpnaVe3cesWbMqqKYPPkaLcDkooTDgZ
{"smk762", "02eacef682d2f86e0103c18f4da46116e17196f3fb8f73ed931acb78e81d8e1aa5" }, // RQVvzJ8gepCDVjhqCAc5Tia1kTmt8KDPL9
{"jorian", "02150c410a606b898bcab4f083e48e0f98a510e0d48d4db367d37f318d26ae72e3" }, // RFgzxZe2P4RWKx6E9QGPK3rx3TXeWxSqa8
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" }, //RN2KsQGW36Ah4NorJDxLJp2xiYJJEzk9Y6
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2
{"jusoaresf", "02dfb7ed72a23f6d07f0ea2f28192ee174733cc8412ec0f97b073007b78fab6346" }, // RBQGfE5Hxsjm1BPraTxbneRuNasPDuoLnu
{"mylo", "03f6b7fcaf0b8b8ec432d0de839a76598b78418dadd50c8e5594c0e557d914ec09" }, // RXN4hoZkhUkkrnef9nTUDw3E3vVALAD8Kx
{"blackjok3r2", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"blackjok3r3", "03c3e4c0206551dbf3a4b24d18e5d2737080541184211e3bfd2b1092177410b9c2" }, // RMMav2AVse5XHPvDfTzRpMbFhK3GqFmtSN
{"kmdkrazy", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"alrighttest", "02e9dfe248f453b499315a90375e58a1c9ad79f5f3932ecb2205399a0f262d65fc" }, // RBevSstS8JtDXMEFNcJws4QTYN4PcE2VL5
{"alrighttest1", "03527c7ecd6a8c5db6d685a64e6e18c1edb49e2f057a434f56c3f1253a26e9c6a2" }, // RBw2jNU3dnGk86ZLqPMadJwRwg3NU8eC6s
{"PHBA2061", "039fc98c764bc85aed97d690d7942a4fd1190b2fa4f5f4c5c8e0957fac5c6ede00" }, // RPHba2o61hcpX4ds91oj3sKJ8aDXv6QdQf right
{"Exile13", "0247b2120a39faf83678b5de6883e039180ff42925bcb298d32f3792cd59001aae" }, // RTDJ3CDZ6ANbeDKab8nqTVrGw7ViAKLeDV right
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
}
};

View File

@@ -344,6 +344,9 @@ bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& param
{
if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH)
return true;
if ( ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 && pblock->GetHash().ToString() == "027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71" )
return true;
unsigned int n = params.EquihashN();
unsigned int k = params.EquihashK();

View File

@@ -43,10 +43,15 @@
#include <regex>
#include "cc/CCinclude.h"
#include "cc/CCPrices.h"
using namespace std;
extern int32_t KOMODO_INSYNC;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp);
#include "komodo_defs.h"
#include "komodo_structs.h"
@@ -129,6 +134,9 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("error", "null blockhash"));
return(result);
}
uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height;
notarized_height = komodo_notarized_height(&prevMoMheight,&notarized_hash,&notarized_desttxid);
result.push_back(Pair("last_notarized_height", notarized_height));
result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
@@ -280,6 +288,9 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex)
UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
UniValue result(UniValue::VOBJ);
uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height;
notarized_height = komodo_notarized_height(&prevMoMheight,&notarized_hash,&notarized_desttxid);
result.push_back(Pair("last_notarized_height", notarized_height));
result.push_back(Pair("hash", block.GetHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
@@ -1155,17 +1166,17 @@ UniValue paxprice(const UniValue& params, bool fHelp)
}
return ret;
}
int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind)
// fills pricedata with raw price, correlated and smoothed values for numblock
/*int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind)
{
int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; uint32_t rawprices[1440*6],*ptr; int64_t *tmpbuf;
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH;
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH; // need 2*PRICES_DAYWINDOW previous raw price points to calc PRICES_DAYWINDOW correlated points to calc, in turn, smoothed point
komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1);
if ( firstheight < width )
return(-1);
for (i=0; i<width; i++)
{
if ( (n= komodo_heightpricebits(&ignore,rawprices,firstheight + numblocks - 1 - i)) < 0 )
if ( (n= komodo_heightpricebits(&ignore,rawprices,firstheight + numblocks - 1 - i)) < 0 ) // stores raw prices in backward order
return(-1);
if ( numpricefeeds < 0 )
numpricefeeds = n;
@@ -1176,26 +1187,28 @@ int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,
ptr[1] = rawprices[0]; // timestamp
}
rngval = seed;
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++)
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++) // calculates +PRICES_DAYWINDOW more correlated values
{
rngval = (rngval*11109 + 13849);
ptr = (uint32_t *)&pricedata[i*3];
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 )
// takes previous PRICES_DAYWINDOW raw prices and calculates correlated price value
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 ) // skip is 6 == sizeof(int64_t)/sizeof(int32_t)*3
return(-3);
}
tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW);
for (i=0; i<numblocks; i++)
pricedata[i*3+2] = komodo_priceave(tmpbuf,&pricedata[i*3+1],3);
// takes previous PRICES_DAYWINDOW correlated price values and calculates smoothed value
pricedata[i*3+2] = komodo_priceave(tmpbuf,&pricedata[i*3+1],3);
free(tmpbuf);
return(0);
}
}*/
UniValue prices(const UniValue& params, bool fHelp)
{
if ( fHelp || params.size() != 1 )
throw runtime_error("prices maxsamples\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t *tmpbuf,smoothed,*correlated; char name[64],*str; uint32_t rawprices[1440*6],*prices; uint32_t i,width,j,numpricefeeds=-1,n,numsamples,nextheight,offset,ht;
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t *tmpbuf,smoothed,*correlated,checkprices[PRICES_MAXDATAPOINTS]; char name[64],*str; uint32_t rawprices[1440*6],*prices; uint32_t i,width,j,numpricefeeds=-1,n,numsamples,nextheight,offset,ht;
if ( ASSETCHAINS_CBOPRET == 0 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
@@ -1255,13 +1268,30 @@ UniValue prices(const UniValue& params, bool fHelp)
rngval = (rngval*11109 + 13849);
if ( (correlated[i]= komodo_pricecorrelated(rngval,j,&prices[offset],1,0,PRICES_SMOOTHWIDTH)) < 0 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "null correlated price");
{
if ( komodo_priceget(checkprices,j,nextheight-1-i,1) >= 0 )
{
if ( checkprices[1] != correlated[i] )
{
//fprintf(stderr,"ind.%d ht.%d %.8f != %.8f\n",j,nextheight-1-i,(double)checkprices[1]/COIN,(double)correlated[i]/COIN);
correlated[i] = checkprices[1];
}
}
}
}
tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW);
for (i=0; i<maxsamples&&i<numsamples; i++)
{
offset = j*width + i;
smoothed = komodo_priceave(tmpbuf,&correlated[i],1);
if ( komodo_priceget(checkprices,j,nextheight-1-i,1) >= 0 )
{
if ( checkprices[2] != smoothed )
{
fprintf(stderr,"ind.%d ht.%d %.8f != %.8f\n",j,nextheight-1-i,(double)checkprices[2]/COIN,(double)smoothed/COIN);
smoothed = checkprices[2];
}
}
UniValue parr(UniValue::VARR);
parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j)));
parr.push_back(ValueFromAmount(correlated[i]));
@@ -1298,6 +1328,156 @@ UniValue prices(const UniValue& params, bool fHelp)
return ret;
}
// pricesbet rpc implementation
UniValue pricesbet(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
throw runtime_error("pricesbet amount leverage \"synthetic-expression\"\n"
"amount is in coins\n"
"leverage is integer non-zero value, positive for long, negative for short position\n"
"synthetic-expression example \"BTC_USD, 1\"\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
CAmount txfee = 10000;
CAmount amount = atof(params[0].get_str().c_str()) * COIN;
int16_t leverage = (int16_t)atoi(params[1].get_str().c_str());
if (leverage == 0)
throw runtime_error("invalid leverage\n");
std::string sexpr = params[2].get_str();
std::vector<std::string> vexpr;
SplitStr(sexpr, vexpr);
// debug print parsed strings:
std::cerr << "parsed synthetic: ";
for (auto s : vexpr)
std::cerr << s << " ";
std::cerr << std::endl;
return PricesBet(txfee, amount, leverage, vexpr);
}
// pricesaddfunding rpc implementation
UniValue pricesaddfunding(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error("pricesaddfunding bettxid amount\n"
"where amount is in coins\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
CAmount txfee = 10000;
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
if (bettxid.IsNull())
throw runtime_error("invalid bettxid\n");
CAmount amount = atof(params[1].get_str().c_str()) * COIN;
if (amount <= 0)
throw runtime_error("invalid amount\n");
return PricesAddFunding(txfee, bettxid, amount);
}
// rpc pricessetcostbasis implementation
UniValue pricessetcostbasis(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error("pricessetcostbasis bettxid\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
if (bettxid.IsNull())
throw runtime_error("invalid bettxid\n");
int64_t txfee = 10000;
return PricesSetcostbasis(txfee, bettxid);
}
// pricescashout rpc implementation
UniValue pricescashout(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error("pricescashout bettxid\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
if (bettxid.IsNull())
throw runtime_error("invalid bettxid\n");
int64_t txfee = 10000;
return PricesCashout(txfee, bettxid);
}
// pricesrekt rpc implementation
UniValue pricesrekt(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error("pricesrekt bettxid height\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
if (bettxid.IsNull())
throw runtime_error("invalid bettxid\n");
int32_t height = atoi(params[0].get_str().c_str());
int64_t txfee = 10000;
return PricesRekt(txfee, bettxid, height);
}
// pricesrekt rpc implementation
UniValue pricesgetorderbook(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error("pricesgetorderbook\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
return PricesGetOrderbook();
}
// pricesrekt rpc implementation
UniValue pricesrefillfund(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error("pricesrefillfund amount\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
CAmount amount = atof(params[0].get_str().c_str()) * COIN;
return PricesRefillFund(amount);
}
UniValue gettxout(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 3)
@@ -1534,6 +1714,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("synced", KOMODO_INSYNC!=0));
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->GetHeight() : -1));
obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex()));
obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
@@ -1672,7 +1853,6 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
/* Construct the output array. */
UniValue res(UniValue::VARR); const CBlockIndex *forked;
BOOST_FOREACH(const CBlockIndex* block, setTips)
BOOST_FOREACH(const CBlockIndex* block, setTips)
{
UniValue obj(UniValue::VOBJ);

View File

@@ -108,6 +108,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "lockunspent", 0 },
{ "lockunspent", 1 },
{ "importprivkey", 2 },
{ "importprivkey", 3 },
{ "importaddress", 2 },
{ "verifychain", 0 },
{ "verifychain", 1 },
@@ -174,6 +175,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getNotarisationsForBlock", 0},
{ "height_MoM", 1},
{ "calc_MoM", 2},
{ "migrate_completeimporttransaction", 1},
};
class CRPCConvertTable

View File

@@ -38,6 +38,7 @@
#include "key_io.h"
#include "cc/CCImportGateway.h"
#include "cc/CCtokens.h"
#include <stdint.h>
#include <univalue.h>
@@ -52,6 +53,8 @@ extern std::string CCerror;
extern std::string ASSETCHAINS_SELFIMPORT;
extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT;
int32_t ensure_CCrequirements(uint8_t evalcode);
bool EnsureWalletIsAvailable(bool avoidException);
int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip);
int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height);
@@ -60,8 +63,8 @@ uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
extern std::string ASSETCHAINS_SELFIMPORT;
std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx);
int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount);
//std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx);
//int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount);
std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector<CTxOut> vouts);
UniValue assetchainproof(const UniValue& params, bool fHelp)
@@ -137,12 +140,12 @@ UniValue MoMoMdata(const UniValue& params, bool fHelp)
int kmdheight = atoi(params[1].get_str().c_str());
uint32_t ccid = atoi(params[2].get_str().c_str());
ret.push_back(Pair("coin",symbol));
ret.push_back(Pair("kmdheight",kmdheight));
ret.push_back(Pair("kmdheight",kmdheight-5));
ret.push_back(Pair("ccid", (int) ccid));
uint256 destNotarisationTxid;
std::vector<uint256> moms;
uint256 MoMoM = CalculateProofRoot(symbol, ccid, kmdheight, moms, destNotarisationTxid);
uint256 MoMoM = CalculateProofRoot(symbol, ccid, kmdheight-5, moms, destNotarisationTxid);
UniValue valMoms(UniValue::VARR);
for (int i=0; i<moms.size(); i++) valMoms.push_back(moms[i].GetHex());
@@ -185,7 +188,7 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp)
"If neccesary, the transaction should be funded using fundrawtransaction.\n"
"Finally, the transaction should be signed using signrawtransaction\n"
"The finished export transaction, plus the payouts, should be passed to "
"the \"migrate_createimporttransaction\" method on a KMD node to get the corresponding "
"the \"migrate_createimporttransaction\" method to get the corresponding "
"import transaction.\n"
);
@@ -206,19 +209,30 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp)
if (strcmp(ASSETCHAINS_SYMBOL,targetSymbol.c_str()) == 0)
throw runtime_error("cant send a coin to the same chain");
/// Tested 44 vins p2pkh inputs as working. Set this at 25, but its a tx size limit.
// likely with a single RPC you can limit it by the size of tx.
if (tx.vout.size() > 25)
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot have more than 50 vins, transaction too large.");
CAmount burnAmount = 0;
for (int i=0; i<tx.vout.size(); i++) burnAmount += tx.vout[i].nValue;
if (burnAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export a negative or zero value.");
// This is due to MAX MONEY in target. We set it at min 1 million coins, so you cant export more than 1 million,
// without knowing the MAX money on the target this was the easiest solution.
if (burnAmount > 1000000LL*COIN)
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export more than 1 million coins per export.");
/* note: we marshal to rawproof in a different way (to be able to add other objects)
rawproof.resize(strlen(ASSETCHAINS_SYMBOL));
ptr = rawproof.data();
for (i=0; i<rawproof.size(); i++)
ptr[i] = ASSETCHAINS_SYMBOL[i];
ptr[i] = ASSETCHAINS_SYMBOL[i]; */
const std::string chainSymbol(ASSETCHAINS_SYMBOL);
rawproof = E_MARSHAL(ss << chainSymbol); // add src chain name
CTxOut burnOut = MakeBurnOutput(burnAmount+txfee, ccid, targetSymbol, tx.vout,rawproof);
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << tx.vout))));
@@ -228,26 +242,311 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp)
return ret;
}
// creates burn tx as an alternative to 'migrate_converttoexport()'
UniValue migrate_createburntransaction(const UniValue& params, bool fHelp)
{
UniValue ret(UniValue::VOBJ);
//uint8_t *ptr;
//uint8_t i;
uint32_t ccid = ASSETCHAINS_CC;
int64_t txfee = 10000;
if (fHelp || params.size() != 3 && params.size() != 4)
throw runtime_error(
"migrate_createburntransaction dest_symbol dest_addr amount [tokenid]\n"
"\nCreates a raw burn transaction to make a cross-chain coin or non-fungible token transfer.\n"
"The parameters:\n"
"dest_symbol destination chain ac_name\n"
"dest_addr address on the destination chain where coins are to be sent or pubkey if tokens are to be sent\n"
"amount amount in coins to be burned on the source chain and sent to the destination address/pubkey on the destination chain, for tokens should be equal to 1\n"
"tokenid token id, if tokens are transferred (optional). Only non-fungible tokens are supported\n"
"\n"
"The transaction should be sent using sendrawtransaction to the source chain\n"
"The finished burn transaction and payouts should be also passed to "
"the \"migrate_createimporttransaction\" method to get the corresponding import transaction.\n"
);
if (ASSETCHAINS_CC < KOMODO_FIRSTFUNGIBLEID)
throw runtime_error("-ac_cc < KOMODO_FIRSTFUNGIBLEID");
if (ASSETCHAINS_SYMBOL[0] == 0)
throw runtime_error("Must be called on assetchain");
// if -pubkey not set it sends change to null pubkey.
// we need a better way to return errors from this function!
if (ensure_CCrequirements(225) < 0)
throw runtime_error("You need to set -pubkey, or run setpukbey RPC, or imports are disabled on this chain.");
string targetSymbol = params[0].get_str();
if (targetSymbol.size() == 0 || targetSymbol.size() > 32)
throw runtime_error("targetSymbol length must be >0 and <=32");
if (strcmp(ASSETCHAINS_SYMBOL, targetSymbol.c_str()) == 0)
throw runtime_error("cant send a coin to the same chain");
std::string dest_addr_or_pubkey = params[1].get_str();
CAmount burnAmount;
if(params.size() == 3)
burnAmount = (CAmount)( atof(params[2].get_str().c_str()) * COIN + 0.00000000499999 );
else
burnAmount = atoll(params[2].get_str().c_str());
if (burnAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export a negative or zero value.");
if (burnAmount > 1000000LL * COIN)
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export more than 1 million coins per export.");
uint256 tokenid = zeroid;
if( params.size() == 4 )
tokenid = Parseuint256(params[3].get_str().c_str());
if ( tokenid != zeroid && strcmp("LABS", targetSymbol.c_str()))
throw JSONRPCError(RPC_TYPE_ERROR, "There is no tokens support on LABS.");
CPubKey myPubKey = Mypubkey();
struct CCcontract_info *cpTokens, C;
cpTokens = CCinit(&C, EVAL_TOKENS);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
const std::string chainSymbol(ASSETCHAINS_SYMBOL);
std::vector<uint8_t> rawproof; //(chainSymbol.begin(), chainSymbol.end());
if (tokenid.IsNull()) { // coins
int64_t inputs;
if ((inputs = AddNormalinputs(mtx, myPubKey, burnAmount + txfee, 10)) == 0) {
throw runtime_error("not enough funds, or need to merge utxos first\n");
}
CTxDestination txdest = DecodeDestination(dest_addr_or_pubkey.c_str());
CScript scriptPubKey = GetScriptForDestination(txdest);
if (!scriptPubKey.IsPayToPublicKeyHash()) {
throw JSONRPCError(RPC_TYPE_ERROR, "Incorrect destination addr.");
}
mtx.vout.push_back(CTxOut(burnAmount, scriptPubKey)); // 'model' vout
ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << mtx.vout)))); // save 'model' vout
rawproof = E_MARSHAL(ss << chainSymbol); // add src chain name
CTxOut burnOut = MakeBurnOutput(burnAmount+txfee, ccid, targetSymbol, mtx.vout, rawproof); //make opret with burned amount
mtx.vout.clear(); // remove 'model' vout
int64_t change = inputs - (burnAmount+txfee);
if (change != 0)
mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(myPubKey)) << OP_CHECKSIG)); // make change here to prevent it from making in FinalizeCCtx
mtx.vout.push_back(burnOut); // mtx now has only burned vout (that is, amount sent to OP_RETURN making it unspendable)
//std::string exportTxHex = FinalizeCCTx(0, cpTokens, mtx, myPubKey, txfee, CScript()); // no change no opret
}
else { // tokens
CTransaction tokenbasetx;
uint256 hashBlock;
vscript_t vopretNonfungible;
vscript_t vopretBurnData;
std::vector<uint8_t> vorigpubkey, vdestpubkey;
std::string name, description;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (!myGetTransaction(tokenid, tokenbasetx, hashBlock))
throw runtime_error("Could not load token creation tx\n");
// check if it is non-fungible tx and get its second evalcode from non-fungible payload
if (tokenbasetx.vout.size() == 0)
throw runtime_error("No vouts in token tx\n");
if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, vorigpubkey, name, description, oprets) != 'c')
throw runtime_error("Incorrect token creation tx\n");
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
/* allow fungible tokens:
if (vopretNonfungible.empty())
throw runtime_error("No non-fungible token data\n"); */
uint8_t destEvalCode = EVAL_TOKENS;
if (!vopretNonfungible.empty())
destEvalCode = vopretNonfungible.begin()[0];
// check non-fungible tokens amount
if (!vopretNonfungible.empty() && burnAmount != 1)
throw JSONRPCError(RPC_TYPE_ERROR, "For non-fungible tokens amount should be equal to 1.");
vdestpubkey = ParseHex(dest_addr_or_pubkey);
CPubKey destPubKey = pubkey2pk(vdestpubkey);
if (!destPubKey.IsValid())
throw runtime_error("Invalid destination pubkey\n");
int64_t inputs;
if ((inputs = AddNormalinputs(mtx, myPubKey, txfee, 1)) == 0) // for miners in dest chain
throw runtime_error("No normal input found for two txfee\n");
int64_t ccInputs;
if ((ccInputs = AddTokenCCInputs(cpTokens, mtx, myPubKey, tokenid, burnAmount, 4)) < burnAmount)
throw runtime_error("No token inputs found (please try to consolidate tokens)\n");
// make payouts (which will be in the import tx with token):
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens, NULL))); // new marker to token cc addr, burnable and validated, vout position now changed to 0 (from 1)
mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, burnAmount, destPubKey));
std::vector<std::pair<uint8_t, vscript_t>> voprets;
if (!vopretNonfungible.empty())
voprets.push_back(std::make_pair(OPRETID_NONFUNGIBLEDATA, vopretNonfungible)); // add additional opret with non-fungible data
mtx.vout.push_back(CTxOut((CAmount)0, EncodeTokenCreateOpRet('c', vorigpubkey, name, description, voprets))); // make token import opret
ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << mtx.vout)))); // save payouts for import tx
rawproof = E_MARSHAL(ss << chainSymbol << tokenbasetx); // add src chain name and token creation tx
CTxOut burnOut = MakeBurnOutput(0, ccid, targetSymbol, mtx.vout, rawproof); //make opret with amount=0 because tokens are burned, not coins (see next vout)
mtx.vout.clear(); // remove payouts
// now make burn transaction:
mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, burnAmount, pubkey2pk(ParseHex(CC_BURNPUBKEY)))); // burn tokens
int64_t change = inputs - txfee;
if (change != 0)
mtx.vout.push_back(CTxOut(change, CScript() << ParseHex(HexStr(myPubKey)) << OP_CHECKSIG)); // make change here to prevent it from making in FinalizeCCtx
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(pubkey2pk(ParseHex(CC_BURNPUBKEY))); // maybe we do not need this because ccTokens has the const for burn pubkey
int64_t ccChange = ccInputs - burnAmount;
if (ccChange != 0)
mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, ccChange, myPubKey));
GetOpReturnData(burnOut.scriptPubKey, vopretBurnData);
mtx.vout.push_back(CTxOut(txfee, EncodeTokenOpRet(tokenid, voutTokenPubkeys, std::make_pair(OPRETID_BURNDATA, vopretBurnData)))); //burn txfee for miners in dest chain
}
std::string burnTxHex = FinalizeCCTx(0, cpTokens, mtx, myPubKey, txfee, CScript()); //no change, no opret
ret.push_back(Pair("BurnTxHex", burnTxHex));
return ret;
}
// util func to check burn tx and source chain params
void CheckBurnTxSource(uint256 burntxid, UniValue &info) {
CTransaction burnTx;
uint256 blockHash;
if (!GetTransaction(burntxid, burnTx, blockHash, true))
throw std::runtime_error("Cannot find burn transaction");
if (blockHash.IsNull())
throw std::runtime_error("Burn tx still in mempool");
uint256 payoutsHash;
std::string targetSymbol;
uint32_t targetCCid;
std::vector<uint8_t> rawproof;
if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof))
throw std::runtime_error("Cannot unmarshal burn tx data");
vscript_t vopret;
std::string sourceSymbol;
CTransaction tokenbasetxStored;
uint256 tokenid = zeroid;
if (burnTx.vout.size() > 0 && GetOpReturnData(burnTx.vout.back().scriptPubKey, vopret) && !vopret.empty()) {
if (vopret.begin()[0] == EVAL_TOKENS) {
if (!E_UNMARSHAL(rawproof, ss >> sourceSymbol; ss >> tokenbasetxStored))
throw std::runtime_error("Cannot unmarshal rawproof for tokens");
uint8_t evalCode;
std::vector<CPubKey> voutPubkeys;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if( DecodeTokenOpRet(burnTx.vout.back().scriptPubKey, evalCode, tokenid, voutPubkeys, oprets) == 0 )
throw std::runtime_error("Cannot decode token opret in burn tx");
if( tokenid != tokenbasetxStored.GetHash() )
throw std::runtime_error("Incorrect tokenbase in burn tx");
CTransaction tokenbasetx;
uint256 hashBlock;
if (!myGetTransaction(tokenid, tokenbasetx, hashBlock)) {
throw std::runtime_error("Could not load tokenbase tx");
}
// check if nonfungible data present
if (tokenbasetx.vout.size() > 0) {
std::vector<uint8_t> origpubkey;
std::string name, description;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
vscript_t vopretNonfungible;
if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, origpubkey, name, description, oprets) == 'c') {
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
if (vopretNonfungible.empty())
throw std::runtime_error("Could not migrate fungible tokens");
}
else
throw std::runtime_error("Could not decode opreturn in tokenbase tx");
}
else
throw std::runtime_error("Incorrect tokenbase tx: not opreturn");
struct CCcontract_info *cpTokens, CCtokens_info;
cpTokens = CCinit(&CCtokens_info, EVAL_TOKENS);
int64_t ccInputs = 0, ccOutputs = 0;
if( !TokensExactAmounts(true, cpTokens, ccInputs, ccOutputs, NULL, burnTx, tokenid) )
throw std::runtime_error("Incorrect token burn tx: cc inputs <> cc outputs");
}
else if (vopret.begin()[0] == EVAL_IMPORTCOIN) {
if (!E_UNMARSHAL(rawproof, ss >> sourceSymbol))
throw std::runtime_error("Cannot unmarshal rawproof for coins");
}
else
throw std::runtime_error("Incorrect eval code in opreturn");
}
else
throw std::runtime_error("No opreturn in burn tx");
if (sourceSymbol != ASSETCHAINS_SYMBOL)
throw std::runtime_error("Incorrect source chain in rawproof");
if (targetCCid != ASSETCHAINS_CC)
throw std::runtime_error("Incorrect CCid in burn tx");
if (targetSymbol == ASSETCHAINS_SYMBOL)
throw std::runtime_error("Must not be called on the destination chain");
// fill info to return for the notary operator (if manual notarization) or user
info.push_back(Pair("SourceSymbol", sourceSymbol));
info.push_back(Pair("TargetSymbol", targetSymbol));
info.push_back(Pair("TargetCCid", std::to_string(targetCCid)));
if (!tokenid.IsNull())
info.push_back(Pair("tokenid", tokenid.GetHex()));
}
/*
* The process to migrate funds
* The process to migrate funds from a chain to chain
*
* Create a transaction on assetchain:
* 1.Create a transaction on assetchain (deprecated):
* 1.1 generaterawtransaction
* 1.2 migrate_converttoexport
* 1.3 fundrawtransaction
* 1.4 signrawtransaction
*
* generaterawtransaction
* migrate_converttoexport
* fundrawtransaction
* signrawtransaction
* alternatively, burn (export) transaction may be created with this new rpc call:
* 1. migrate_createburntransaction
*
* migrate_createimportransaction
* migrate_completeimporttransaction
* next steps:
* 2. migrate_createimporttransaction
* 3. migrate_completeimporttransaction
*/
UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error("migrate_createimporttransaction burnTx payouts\n\n"
"Create an importTx given a burnTx and the corresponding payouts, hex encoded");
if (fHelp || params.size() < 2)
throw runtime_error("migrate_createimporttransaction burnTx payouts [notarytxid-1]..[notarytxid-N]\n\n"
"Create an importTx given a burnTx and the corresponding payouts, hex encoded\n"
"optional notarytxids are txids of notary operator proofs of burn tx existense (from destination chain).\n"
"Do not make subsequent call to migrate_completeimporttransaction if notary txids are set");
if (ASSETCHAINS_CC < KOMODO_FIRSTFUNGIBLEID)
throw runtime_error("-ac_cc < KOMODO_FIRSTFUNGIBLEID");
@@ -261,26 +560,52 @@ UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp)
if (!E_UNMARSHAL(txData, ss >> burnTx))
throw runtime_error("Couldn't parse burnTx");
if( burnTx.vin.size() == 0 )
throw runtime_error("No vins in the burnTx");
if (burnTx.vout.size() == 0)
throw runtime_error("No vouts in the burnTx");
vector<CTxOut> payouts;
if (!E_UNMARSHAL(ParseHexV(params[1], "argument 2"), ss >> payouts))
throw runtime_error("Couldn't parse payouts");
uint256 txid = burnTx.GetHash();
TxProof proof = GetAssetchainProof(burnTx.GetHash(),burnTx);
ImportProof importProof;
if (params.size() == 2) { // standard MoMoM based notarization
// get MoM import proof
importProof = ImportProof(GetAssetchainProof(burnTx.GetHash(), burnTx));
}
else { // notarization by manual operators notary tx
UniValue info(UniValue::VOBJ);
CheckBurnTxSource(burnTx.GetHash(), info);
CTransaction importTx = MakeImportCoinTransaction(proof, burnTx, payouts);
// get notary import proof
std::vector<uint256> notaryTxids;
for (int i = 2; i < params.size(); i++) {
uint256 txid = Parseuint256(params[i].get_str().c_str());
if (txid.IsNull())
throw runtime_error("Incorrect notary approval txid");
notaryTxids.push_back(txid);
}
importProof = ImportProof(notaryTxids);
}
return HexStr(E_MARSHAL(ss << importTx));
CTransaction importTx = MakeImportCoinTransaction(importProof, burnTx, payouts);
std::string importTxHex = HexStr(E_MARSHAL(ss << importTx));
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("ImportTxHex", importTxHex));
return ret;
}
UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error("migrate_completeimporttransaction importTx\n\n"
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error("migrate_completeimporttransaction importTx [offset]\n\n"
"Takes a cross chain import tx with proof generated on assetchain "
"and extends proof to target chain proof root");
"and extends proof to target chain proof root\n"
"offset is optional, use it to increase the used KMD height, use when import fails.");
if (ASSETCHAINS_SYMBOL[0] != 0)
throw runtime_error("Must be called on KMD");
@@ -288,63 +613,130 @@ UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp)
CTransaction importTx;
if (!E_UNMARSHAL(ParseHexV(params[0], "argument 1"), ss >> importTx))
throw runtime_error("Couldn't parse importTx");
int32_t offset = 0;
if ( params.size() == 2 )
offset = params[1].get_int();
CompleteImportTransaction(importTx);
CompleteImportTransaction(importTx, offset);
return HexStr(E_MARSHAL(ss << importTx));
std::string importTxHex = HexStr(E_MARSHAL(ss << importTx));
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("ImportTxHex", importTxHex));
return ret;
}
/*
* Alternate coin migration solution if MoMoM migration has failed
*
* The workflow:
* On the source chain user calls migrate_createburntransaction, sends the burn tx to the chain and sends its txid and the source chain name to the notary operators (off-chain)
* the notary operators call migrate_checkburntransactionsource on the source chain
* on the destination chain the notary operators call migrate_createnotaryapprovaltransaction and pass the burn txid and txoutproof received from the previous call,
* the notary operators send the approval transactions to the chain and send their txids to the user (off-chain)
* on the source chain the user calls migrate_createimporttransaction and passes to it notary txids as additional parameters
* then the user sends the import transaction to the destination chain (where the notary approvals will be validated)
*/
// checks if burn tx exists and params stored in the burn tx match to the source chain
// returns txproof
// run it on the source chain
UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error("migrate_checkburntransactionsource burntxid\n\n"
"checks if params stored in the burn tx match to its tx chain");
if (ASSETCHAINS_SYMBOL[0] == 0)
throw runtime_error("Must be called on asset chain");
uint256 burntxid = Parseuint256(params[0].get_str().c_str());
UniValue result(UniValue::VOBJ);
CheckBurnTxSource(burntxid, result); // check and get burn tx data
// get tx proof for burn tx
UniValue nextparams(UniValue::VARR);
UniValue txids(UniValue::VARR);
txids.push_back(burntxid.GetHex());
nextparams.push_back(txids);
result.push_back(Pair("TxOutProof", gettxoutproof(nextparams, false))); // get txoutproof
result.push_back(Pair("result", "success")); // get txoutproof
return result;
}
// creates a tx for the dest chain with txproof
// used as a momom-backup manual import solution
// run it on the dest chain
UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error("migrate_createnotaryapprovaltransaction burntxid txoutproof\n\n"
"Creates a tx for destination chain with burn tx proof\n"
"txoutproof should be retrieved by komodo-cli migrate_checkburntransactionsource call on the source chain\n" );
if (ASSETCHAINS_SYMBOL[0] == 0)
throw runtime_error("Must be called on asset chain");
uint256 burntxid = Parseuint256(params[0].get_str().c_str());
if (burntxid.IsNull())
throw runtime_error("Couldn't parse burntxid or it is null");
std::vector<uint8_t> proofData = ParseHex(params[1].get_str());
CMerkleBlock merkleBlock;
std::vector<uint256> prooftxids;
if (!E_UNMARSHAL(proofData, ss >> merkleBlock))
throw runtime_error("Couldn't parse txoutproof");
merkleBlock.txn.ExtractMatches(prooftxids);
if (std::find(prooftxids.begin(), prooftxids.end(), burntxid) == prooftxids.end())
throw runtime_error("No burntxid in txoutproof");
const int64_t txfee = 10000;
struct CCcontract_info *cpDummy, C;
cpDummy = CCinit(&C, EVAL_TOKENS); // just for FinalizeCCtx to work
// creating a tx with proof:
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
if (AddNormalinputs(mtx, Mypubkey(), txfee*2, 4) == 0)
throw runtime_error("Cannot find normal inputs\n");
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG));
std::string notaryTxHex = FinalizeCCTx(0, cpDummy, mtx, Mypubkey(), txfee, CScript() << OP_RETURN << E_MARSHAL(ss << proofData;));
UniValue result(UniValue::VOBJ);
result.push_back(Pair("NotaryTxHex", notaryTxHex));
return result;
}
// creates a source 'quasi-burn' tx for AC_PUBKEY
// run it on the same asset chain
UniValue selfimport(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
CMutableTransaction sourceMtx, templateMtx;
std::string destaddr;
std::string source;
std::string rawsourcetx;
std::string sourceTxHex;
std::string importTxHex;
CTransaction burnTx;
CTxOut burnOut;
uint64_t burnAmount;
uint256 sourcetxid, blockHash;
std::vector<CTxOut> vouts;
std::vector<uint8_t> rawproof, rawproofEmpty;
int32_t ivout = 0;
CScript scriptPubKey;
TxProof proof;
std::vector<uint8_t> rawproof;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("selfimport only works on -ac_import chains");
if (fHelp || params.size() != 2)
throw runtime_error("selfimport destaddr amount\n"
//old: "selfimport rawsourcetx sourcetxid {nvout|\"find\"} amount \n"
//TODO: "or selfimport rawburntx burntxid {nvout|\"find\"} rawproof source bindtxid height} \n"
"\ncreates self import coin transaction");
/* OLD selfimport schema:
rawsourcetx = params[0].get_str();
sourcetxid = Parseuint256((char *)params[1].get_str().c_str()); // allow for txid != hash(rawtx)
int32_t ivout = -1;
if( params[2].get_str() != "find" ) {
if( !std::all_of(params[2].get_str().begin(), params[2].get_str().end(), ::isdigit) ) // check if not all chars are digit
throw std::runtime_error("incorrect nvout param");
ivout = atoi(params[2].get_str().c_str());
}
burnAmount = atof(params[3].get_str().c_str()) * COIN + 0.00000000499999; */
destaddr = params[0].get_str();
burnAmount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999;
source = ASSETCHAINS_SELFIMPORT; //defaults to -ac_import=... param
/* TODO for gateways:
if ( params.size() >= 5 )
{
rawproof = ParseHex(params[4].get_str().c_str());
if ( params.size() == 6 )
source = params[5].get_str();
} */
if (source == "BEAM")
{
@@ -364,51 +756,34 @@ UniValue selfimport(const UniValue& params, bool fHelp)
}
else if (source == "PUBKEY")
{
ImportProof proofNull;
CTxDestination dest = DecodeDestination(destaddr.c_str());
rawsourcetx = MakeSelfImportSourceTx(dest, burnAmount, sourceMtx);
sourcetxid = sourceMtx.GetHash();
CMutableTransaction sourceMtx = MakeSelfImportSourceTx(dest, burnAmount); // make self-import source tx
vscript_t rawProofEmpty;
CMutableTransaction templateMtx;
// prepare self-import 'quasi-burn' tx and also create vout for import tx (in mtx.vout):
if (GetSelfimportProof(source, templateMtx, scriptPubKey, proof, rawsourcetx, ivout, sourcetxid, burnAmount) < 0)
throw std::runtime_error("Failed validating selfimport");
if (GetSelfimportProof(sourceMtx, templateMtx, proofNull) < 0)
throw std::runtime_error("Failed creating selfimport template tx");
vouts = templateMtx.vout;
burnOut = MakeBurnOutput(burnAmount, 0xffffffff, ASSETCHAINS_SELFIMPORT, vouts, rawproofEmpty);
burnOut = MakeBurnOutput(burnAmount, 0xffffffff, ASSETCHAINS_SELFIMPORT, vouts, rawProofEmpty);
templateMtx.vout.clear();
templateMtx.vout.push_back(burnOut); // burn tx has only opret with vouts and optional proof
burnTx = templateMtx; // complete the creation of 'quasi-burn' tx
std::string hextx = HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(proof, burnTx, vouts)));
CTxDestination address;
bool fValidAddress = ExtractDestination(scriptPubKey, address);
result.push_back(Pair("sourceTxHex", rawsourcetx));
result.push_back(Pair("importTxHex", hextx));
result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx
result.push_back(Pair("DestinationAddress", EncodeDestination(address))); // notify user about the address where the funds will be sent
sourceTxHex = HexStr(E_MARSHAL(ss << sourceMtx));
importTxHex = HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(proofNull, burnTx, vouts)));
result.push_back(Pair("SourceTxHex", sourceTxHex));
result.push_back(Pair("ImportTxHex", importTxHex));
return result;
}
else if (source == ASSETCHAINS_SELFIMPORT)
{
throw std::runtime_error("not implemented yet\n");
if (params.size() != 8)
throw runtime_error("use \'selfimport rawburntx burntxid nvout rawproof source bindtxid height\' to import from a coin chain\n");
uint256 bindtxid = Parseuint256((char *)params[6].get_str().c_str());
int32_t height = atoi((char *)params[7].get_str().c_str());
// source is external coin is the assetchains symbol in the burnTx OP_RETURN
// burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent
//std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, "");
// result.push_back(Pair("hex", hextx));
// result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx
return -1;
}
return result;
}
@@ -536,13 +911,13 @@ UniValue importgatewaydeposit(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
CMutableTransaction mtx; std::vector<uint8_t> rawproof;
std::string hex,coin,rawburntx; int32_t height,burnvout;
std::string hex,coin,rawburntx; int32_t height,burnvout; int64_t amount;
CPubKey destpub; std::vector<CTxOut> vouts; uint256 bindtxid,burntxid;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewaydeposit only works on -ac_import chains");
if ( fHelp || params.size() != 8)
throw runtime_error("use \'importgatewaydeposit bindtxid height coin burntxid nvout rawburntx rawproof destpub\' to import deposited coins\n");
if ( fHelp || params.size() != 9)
throw runtime_error("use \'importgatewaydeposit bindtxid height coin burntxid nvout rawburntx rawproof destpub amount\' to import deposited coins\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
CCerror = "";
@@ -554,6 +929,7 @@ UniValue importgatewaydeposit(const UniValue& params, bool fHelp)
rawburntx = params[5].get_str();
rawproof = ParseHex(params[6].get_str());
destpub = ParseHex(params[7].get_str());
amount = atof(params[8].get_str().c_str()) * COIN + 0.00000000499999;
if (coin == "BEAM" || coin == "CODA")
{
ERR_RESULT("for BEAM and CODA import use importdual RPC");
@@ -564,7 +940,7 @@ UniValue importgatewaydeposit(const UniValue& params, bool fHelp)
ERR_RESULT("source coin not equal to ac_import name");
return result;
}
hex = ImportGatewayDeposit(0, bindtxid, height, coin, burntxid, burnvout, rawburntx, rawproof, destpub);
hex = ImportGatewayDeposit(0, bindtxid, height, coin, burntxid, burnvout, rawburntx, rawproof, destpub, amount);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
@@ -626,6 +1002,7 @@ UniValue importgatewaypartialsign(const UniValue& params, bool fHelp)
coin = params[1].get_str();
parthex = params[2].get_str();
hex = ImportGatewayPartialSign(0,txid,coin,parthex);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
@@ -771,36 +1148,43 @@ UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp)
//out.push_back(make_pair("blocktime",(int)));
UniValue labs(UniValue::VARR);
UniValue kmd(UniValue::VARR);
// Gets KMD notaries on KMD... but LABS notaries on labs chains needs to be fixed so LABS are identified on KMD.
int8_t numNN = 0; uint8_t notarypubkeys[64][33] = {0};
int8_t numNN = 0, numSN = 0; uint8_t notarypubkeys[64][33] = {0}; uint8_t LABSpubkeys[64][33] = {0};
numNN = komodo_notaries(notarypubkeys, height, chainActive[height]->nTime);
numSN = numStakedNotaries(LABSpubkeys,STAKED_era(chainActive[height]->nTime));
BOOST_FOREACH(const Notarisation& n, nibs)
{
UniValue item(UniValue::VOBJ); UniValue notaryarr(UniValue::VARR); std::vector<int8_t> NotarisationNotaries;
if ( is_STAKED(n.second.symbol) != 0 )
continue; // for now just skip this... need to fetch diff pubkeys for these chains. labs.push_back(item);
uint256 hash; CTransaction tx;
if ( GetTransaction(n.first,tx,hash,false) )
{
if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) )
continue;
if ( NotarisationNotaries.size() < numNN/5 )
continue;
if ( is_STAKED(n.second.symbol) != 0 )
{
if ( !GetNotarisationNotaries(LABSpubkeys, numSN, tx.vin, NotarisationNotaries) )
continue;
}
else
{
if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) )
continue;
}
}
item.push_back(make_pair("txid", n.first.GetHex()));
item.push_back(make_pair("chain", n.second.symbol));
item.push_back(make_pair("height", (int)n.second.height));
item.push_back(make_pair("blockhash", n.second.blockHash.GetHex()));
item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used.
//item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used.
for ( auto notary : NotarisationNotaries )
notaryarr.push_back(notary);
item.push_back(make_pair("notaries",notaryarr));
kmd.push_back(item);
if ( is_STAKED(n.second.symbol) != 0 )
labs.push_back(item);
else
kmd.push_back(item);
}
out.push_back(make_pair("KMD", kmd));
//out.push_back(make_pair("LABS", labs));
out.push_back(make_pair("LABS", labs));
return out;
}
@@ -933,14 +1317,15 @@ UniValue getimports(const UniValue& params, bool fHelp)
{
UniValue objTx(UniValue::VOBJ);
objTx.push_back(Pair("txid",tx.GetHash().ToString()));
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
TotalImported += tx.vout[0].nValue;
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[0].nValue)));
if (ExtractDestination(tx.vout[0].scriptPubKey, importaddress))
ImportProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
TotalImported += tx.vout[0].nValue; // were vouts swapped?
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[1].nValue)));
if (ExtractDestination(tx.vout[1].scriptPubKey, importaddress))
{
objTx.push_back(Pair("address", CBitcoinAddress(importaddress).ToString()));
}
UniValue objBurnTx(UniValue::VOBJ);
UniValue objBurnTx(UniValue::VOBJ);
CPubKey vinPubkey;
if (UnmarshalImportTx(tx, proof, burnTx, payouts))
{
if (burnTx.vout.size() == 0)
@@ -953,8 +1338,14 @@ UniValue getimports(const UniValue& params, bool fHelp)
{
if (rawproof.size() > 0)
{
std::string sourceSymbol(rawproof.begin(), rawproof.end());
std::string sourceSymbol;
CTransaction tokenbasetx;
E_UNMARSHAL(rawproof, ss >> sourceSymbol;
if (!ss.eof())
ss >> tokenbasetx );
objBurnTx.push_back(Pair("source", sourceSymbol));
if( !tokenbasetx.IsNull() )
objBurnTx.push_back(Pair("tokenid", tokenbasetx.GetHash().GetHex()));
}
}
}
@@ -967,3 +1358,144 @@ UniValue getimports(const UniValue& params, bool fHelp)
result.push_back(Pair("time", block.GetBlockTime()));
return result;
}
// outputs burn transactions in the wallet
UniValue getwalletburntransactions(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
"getwalletburntransactions \"count\"\n\n"
"Lists most recent wallet burn transactions up to \'count\' parameter\n"
"parameter \'count\' is optional. If omitted, defaults to 10 burn transactions"
"\n\n"
"\nResult:\n"
"[\n"
" {\n"
" \"txid\": (string)\n"
" \"burnedAmount\" : (numeric)\n"
" \"targetSymbol\" : (string)\n"
" \"targetCCid\" : (numeric)\n"
" }\n"
"]\n"
"\nExamples:\n"
+ HelpExampleCli("getwalletburntransactions", "100")
+ HelpExampleRpc("getwalletburntransactions", "100")
+ HelpExampleCli("getwalletburntransactions", "")
+ HelpExampleRpc("getwalletburntransactions", "")
);
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = "*";
isminefilter filter = ISMINE_SPENDABLE;
int nCount = 10;
if (params.size() == 1)
nCount = atoi(params[0].get_str());
if (nCount < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
UniValue ret(UniValue::VARR);
std::list<CAccountingEntry> acentries;
CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
// iterate backwards until we have nCount items to return:
for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
{
LOGSTREAM("importcoin", CCLOG_DEBUG2, stream << "pwtx iterpos=" << (int32_t)pwtx->nOrderPos << " txid=" << pwtx->GetHash().GetHex() << std::endl);
vscript_t vopret;
std::string targetSymbol;
uint32_t targetCCid; uint256 payoutsHash;
std::vector<uint8_t> rawproof;
if (pwtx->vout.size() > 0 && GetOpReturnData(pwtx->vout.back().scriptPubKey, vopret) && !vopret.empty() &&
UnmarshalBurnTx(*pwtx, targetSymbol, &targetCCid, payoutsHash, rawproof)) {
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("txid", pwtx->GetHash().GetHex()));
if (vopret.begin()[0] == EVAL_TOKENS) {
// get burned token value
std::vector<std::pair<uint8_t, vscript_t>> oprets;
uint256 tokenid;
uint8_t evalCodeInOpret;
std::vector<CPubKey> voutTokenPubkeys;
//skip token opret:
if (DecodeTokenOpRet(pwtx->vout.back().scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets) != 0) {
CTransaction tokenbasetx;
uint256 hashBlock;
if (myGetTransaction(tokenid, tokenbasetx, hashBlock)) {
std::vector<uint8_t> vorigpubkey;
std::string name, description;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (tokenbasetx.vout.size() > 0 &&
DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, vorigpubkey, name, description, oprets) == 'c')
{
uint8_t destEvalCode = EVAL_TOKENS; // init set to fungible token:
vscript_t vopretNonfungible;
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
if (!vopretNonfungible.empty())
destEvalCode = vopretNonfungible.begin()[0];
int64_t burnAmount = 0;
for (auto v : pwtx->vout)
if (v.scriptPubKey.IsPayToCryptoCondition() &&
CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(destEvalCode ? destEvalCode : EVAL_TOKENS, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey
burnAmount += v.nValue;
entry.push_back(Pair("burnedAmount", ValueFromAmount(burnAmount)));
entry.push_back(Pair("tokenid", tokenid.GetHex()));
}
}
}
}
else
entry.push_back(Pair("burnedAmount", ValueFromAmount(pwtx->vout.back().nValue))); // coins
// check for corrupted strings (look for non-printable chars) from some older versions
// which caused "couldn't parse reply from server" error on client:
if (std::find_if(targetSymbol.begin(), targetSymbol.end(), [](int c) {return !std::isprint(c);}) != targetSymbol.end())
targetSymbol = "<value corrupted>";
entry.push_back(Pair("targetSymbol", targetSymbol));
entry.push_back(Pair("targetCCid", std::to_string(targetCCid)));
if (mytxid_inmempool(pwtx->GetHash()))
entry.push_back(Pair("inMempool", "yes"));
ret.push_back(entry);
}
} //else fprintf(stderr,"null pwtx\n
if ((int)ret.size() >= (nCount))
break;
}
// ret is newest to oldest
if (nCount > (int)ret.size())
nCount = ret.size();
vector<UniValue> arrTmp = ret.getValues();
vector<UniValue>::iterator first = arrTmp.begin();
vector<UniValue>::iterator last = arrTmp.begin();
std::advance(last, nCount);
if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
ret.clear();
ret.setArray();
ret.push_backV(arrTmp);
return ret;
}

View File

@@ -49,8 +49,10 @@
using namespace std;
#include "komodo_defs.h"
extern int32_t ASSETCHAINS_FOUNDERS;
extern int32_t ASSETCHAINS_FOUNDERS;
uint64_t komodo_commission(const CBlock *pblock,int32_t height);
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex);
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
/**
@@ -58,7 +60,8 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
* or over the difficulty averaging window if 'lookup' is nonpositive.
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
int64_t GetNetworkHashPS(int lookup, int height) {
int64_t GetNetworkHashPS(int lookup, int height)
{
CBlockIndex *pb = chainActive.LastTip();
if (height >= 0 && height < chainActive.Height())
@@ -1009,6 +1012,7 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp)
"\nResult:\n"
"{\n"
" \"miner\" : x.xxx (numeric) The mining reward amount in KMD.\n"
" \"ac_pubkey\" : x.xxx (numeric) The mining reward amount in KMD.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getblocksubsidy", "1000")
@@ -1019,14 +1023,36 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp)
int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
if (nHeight < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
CAmount nFoundersReward = 0;
CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
UniValue result(UniValue::VOBJ);
result.push_back(Pair("miner", ValueFromAmount(nReward)));
//result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
if ( ASSETCHAINS_FOUNDERS == 0 && ASSETCHAINS_COMMISSION != 0 )
{
// ac comission chains need the block to exist to calulate the reward.
if ( nHeight <= chainActive.Height() )
{
CBlockIndex* pblockIndex = chainActive[nHeight];
CBlock block;
if ( komodo_blockload(block, pblockIndex) == 0 )
nFoundersReward = komodo_commission(&block, nHeight);
}
}
else if ( ASSETCHAINS_FOUNDERS != 0 )
{
// Assetchains founders chains have a fixed reward so can be calculated at any given height.
nFoundersReward = komodo_commission(0, nHeight);
}
result.push_back(Pair("ac_pubkey", ValueFromAmount(nFoundersReward)));
}
return result;
}
static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------

View File

@@ -69,14 +69,16 @@ bool komodo_txnotarizedconfirmed(uint256 txid);
uint32_t komodo_chainactive_timestamp();
int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp);
extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA;
extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA,KOMODO_INSYNC;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
uint32_t komodo_segid32(char *coinaddr);
int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height);
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
int8_t StakedNotaryID(std::string &notaryname, char *Raddress);
uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount);
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
#define KOMODO_VERSION "0.3.3b"
#define KOMODO_VERSION "0.4.0a"
#define VERUS_VERSION "0.4.0g"
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAINS_CC;
@@ -168,7 +170,7 @@ UniValue geterablockheights(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getnotarysendmany\n"
"geterablockheights\n"
"Returns a JSON object with the first block in each era.\n"
);
@@ -235,6 +237,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
obj.push_back(Pair("KMDversion", KOMODO_VERSION));
obj.push_back(Pair("synced", KOMODO_INSYNC!=0));
//obj.push_back(Pair("VRSCversion", VERUS_VERSION));
obj.push_back(Pair("notarized", notarized_height));
obj.push_back(Pair("prevMoMheight", prevMoMheight));
@@ -1216,6 +1219,106 @@ UniValue getaddressdeltas(const UniValue& params, bool fHelp)
}
}
CAmount checkburnaddress(CAmount &received, int64_t &nNotaryPay, int32_t &height, std::string sAddress)
{
CBitcoinAddress address(sAddress);
uint160 hashBytes; int type = 0; CAmount balance = 0;
if (address.GetIndexKey(hashBytes, type, false))
{
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
if (GetAddressIndex(hashBytes, type, addressIndex))
{
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
if (it->second > 0)
received += it->second;
balance += it->second;
}
// Get notary pay from current chain tip
CBlockIndex* pindex = chainActive.LastTip();
nNotaryPay = pindex->nNotaryPay;
height = pindex->GetHeight();
}
}
return balance;
}
UniValue checknotarization(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"checknotarization\n"
"\nReturns true if burn address balance is greater than total notary pay. (requires addressindex to be enabled).\n"
);
UniValue result(UniValue::VOBJ); CAmount balance = 0, received = 0; int64_t nNotaryPay = 0; int32_t height;
// helper to test burn address's
/*uint8_t priv[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t pub[33] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
char coinaddr[64]; uint8_t buf33[33];
//pubkey2addr(coinaddr, pub);
priv2addr(coinaddr,buf33,priv);
fprintf(stderr, "what.%s\n", coinaddr);
result.push_back(Pair("address", coinaddr));
return result;
*/
if ( ASSETCHAINS_NOTARY_PAY[0] == 0 )
throw runtime_error("only works for ac_notarypay chains");
// pubkey 020000000000000000000000000000000
balance = checkburnaddress(received, nNotaryPay, height, "REDVp3ox1pbcWYCzySadfHhk8UU3HM4k5x");
if ( nNotaryPay >= balance || received != balance )
return false;
return true;
}
UniValue getnotarypayinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getnotarypayinfo\n"
"\nReturns infomation about ac_notaypay status (requires addressindex to be enabled).\n"
"\nResult:\n"
"{\n"
" \"height\" (number) The current block height\n"
" \"balance\" (number) The current balance of the burn address\n"
" \"spent\" (bool) true if coins have been spent from the burn address\n"
" \"Total_NotaryPay\" (number) Total amount paid to notaries\n"
" \"Estimated_Notarizations_Left\" (number) the estimated amount of notarizations left before the balance is consumed\n"
" \"Estimated_Days_Left\" (number) the estimated amount of days the current balance will last\n"
" \"Estimated_Height\" (number) the estimated block height funds will run out\n"
"}\n"
);
if ( ASSETCHAINS_NOTARY_PAY[0] == 0 )
throw runtime_error("only works for ac_notarypay chains");
UniValue result(UniValue::VOBJ); CAmount balance = 0, received = 0; int64_t TotalNotaryPay = 0, NotaryPay, notaleft = 0, daysleft = 0, notarycount; int32_t height, endheight = 0; uint8_t notarypubkeys[64][33] = {0};
// pubkey 020000000000000000000000000000000
balance = checkburnaddress(received, TotalNotaryPay, height, "REDVp3ox1pbcWYCzySadfHhk8UU3HM4k5x");
notarycount = komodo_notaries(notarypubkeys, height, chainActive[height]->GetBlockTime());
NotaryPay = komodo_notarypayamount(height, notarycount)*notarycount;
bool spent = (received != balance);
if ( !spent )
{
notaleft = ((int64_t)balance - TotalNotaryPay) / NotaryPay;
daysleft = (((ASSETCHAINS_BLOCKTIME * 5) * notaleft) / 3600) / 24;
endheight = (notaleft * 5) + height;
}
result.push_back(Pair("height", height));
result.push_back(Pair("balance", ValueFromAmount(balance)));
result.push_back(Pair("spent", spent));
result.push_back(Pair("Total_NotaryPay", ValueFromAmount(TotalNotaryPay)));
result.push_back(Pair("Estimated_Notarizations_Left", notaleft));
result.push_back(Pair("Estimated_Days_Left", daysleft));
result.push_back(Pair("Estimated_Height", endheight));
return result;
}
UniValue getaddressbalance(const UniValue& params, bool fHelp)
{
if (fHelp ||params.size() > 2 || params.size() == 0)
@@ -1281,8 +1384,13 @@ UniValue getsnapshot(const UniValue& params, bool fHelp)
if (params.size() > 0 && !params[0].isNull()) {
top = atoi(params[0].get_str().c_str());
if (top <= 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer");
if ( top < 0 )
{
if ( KOMODO_SNAPSHOT_INTERVAL == 0 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer");
else
top = -1;
}
}
if ( fHelp || params.size() > 1)
@@ -1329,7 +1437,7 @@ UniValue getsnapshot(const UniValue& params, bool fHelp)
UniValue getaddresstxids(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
if (fHelp || params.size() > 2 || params.size() < 1)
throw runtime_error(
"getaddresstxids (ccvout)\n"
"\nReturns the txids for an address(es) (requires addressindex to be enabled).\n"

View File

@@ -219,7 +219,6 @@ int32_t komodo_longestchain()
depth--;
if ( num > (n >> 1) )
{
extern char ASSETCHAINS_SYMBOL[];
if ( 0 && height != KOMODO_LONGESTCHAIN )
fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height);
KOMODO_LONGESTCHAIN = height;

View File

@@ -48,6 +48,8 @@
#include <univalue.h>
int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp);
using namespace std;
extern char ASSETCHAINS_SYMBOL[];
@@ -185,10 +187,13 @@ int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout)
void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, int nHeight = 0, int nConfirmations = 0, int nBlockTime = 0)
{
uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height;
notarized_height = komodo_notarized_height(&prevMoMheight,&notarized_hash,&notarized_desttxid);
uint256 txid = tx.GetHash();
entry.push_back(Pair("txid", txid.GetHex()));
entry.push_back(Pair("overwintered", tx.fOverwintered));
entry.push_back(Pair("version", tx.nVersion));
entry.push_back(Pair("last_notarized_height", notarized_height));
if (tx.fOverwintered) {
entry.push_back(Pair("versiongroupid", HexInt(tx.nVersionGroupId)));
}
@@ -203,7 +208,7 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
else if (tx.IsCoinImport()) {
in.push_back(Pair("is_import", "1"));
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
ImportProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
if (UnmarshalImportTx(tx, proof, burnTx, payouts))
{
if (burnTx.vout.size() == 0)
@@ -217,7 +222,8 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
{
if (rawproof.size() > 0)
{
std::string sourceSymbol(rawproof.begin(), rawproof.end());
std::string sourceSymbol;
E_UNMARSHAL(rawproof, ss >> sourceSymbol);
in.push_back(Pair("address", "IMP-" + sourceSymbol + "-" + burnTx.GetHash().ToString()));
}
}

View File

@@ -35,6 +35,10 @@ void RegisterMiningRPCCommands(CRPCTable &tableRPC);
/** Register raw transaction RPC commands */
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
/** Register test transaction RPC commands */
void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC);
static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC)
{
RegisterBlockchainRPCCommands(tableRPC);
@@ -42,6 +46,9 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC)
RegisterMiscRPCCommands(tableRPC);
RegisterMiningRPCCommands(tableRPC);
RegisterRawTransactionRPCCommands(tableRPC);
#ifdef TESTMODE
RegisterTesttransactionsRPCCommands(tableRPC);
#endif
}
#endif

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2019 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -45,6 +46,7 @@
using namespace RPCServer;
using namespace std;
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
static bool fRPCRunning = false;
static bool fRPCInWarmup = true;
@@ -350,9 +352,13 @@ static const CRPCCommand vRPCCommands[] =
{ "crosschain", "getNotarisationsForBlock", &getNotarisationsForBlock, true },
{ "crosschain", "scanNotarisationsDB", &scanNotarisationsDB, true },
{ "crosschain", "getimports", &getimports, true },
{ "crosschain", "getwalletburntransactions", &getwalletburntransactions, true },
{ "crosschain", "migrate_converttoexport", &migrate_converttoexport, true },
{ "crosschain", "migrate_createburntransaction", &migrate_createburntransaction, true },
{ "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true },
{ "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true },
{ "crosschain", "migrate_checkburntransactionsource", &migrate_checkburntransactionsource, true },
{ "crosschain", "migrate_createnotaryapprovaltransaction", &migrate_createnotaryapprovaltransaction, true },
{ "crosschain", "selfimport", &selfimport, true },
{ "crosschain", "importdual", &importdual, true },
//ImportGateway
@@ -450,6 +456,7 @@ static const CRPCCommand vRPCCommands[] =
{ "oracles", "oracleslist", &oracleslist, true },
{ "oracles", "oraclesinfo", &oraclesinfo, true },
{ "oracles", "oraclescreate", &oraclescreate, true },
{ "oracles", "oraclesfund", &oraclesfund, true },
{ "oracles", "oraclesregister", &oraclesregister, true },
{ "oracles", "oraclessubscribe", &oraclessubscribe, true },
{ "oracles", "oraclesdata", &oraclesdata, true },
@@ -459,7 +466,15 @@ static const CRPCCommand vRPCCommands[] =
{ "prices", "prices", &prices, true },
{ "prices", "pricesaddress", &pricesaddress, true },
{ "prices", "priceslist", &priceslist, true },
{ "prices", "mypriceslist", &mypriceslist, true },
{ "prices", "pricesinfo", &pricesinfo, true },
{ "prices", "pricesbet", &pricesbet, true },
{ "prices", "pricessetcostbasis", &pricessetcostbasis, true },
{ "prices", "pricescashout", &pricescashout, true },
{ "prices", "pricesrekt", &pricesrekt, true },
{ "prices", "pricesaddfunding", &pricesaddfunding, true },
{ "prices", "pricesgetorderbook", &pricesgetorderbook, true },
{ "prices", "pricesrefillfund", &pricesrefillfund, true },
// Pegs
{ "pegs", "pegsaddress", &pegsaddress, true },
@@ -476,12 +491,15 @@ static const CRPCCommand vRPCCommands[] =
{ "marmara", "marmaralock", &marmara_lock, true },
// Payments
{ "payments", "paymentsaddress", &paymentsaddress, true },
{ "payments", "paymentstxidopret", &payments_txidopret, true },
{ "payments", "paymentscreate", &payments_create, true },
{ "payments", "paymentslist", &payments_list, true },
{ "payments", "paymentsinfo", &payments_info, true },
{ "payments", "paymentsfund", &payments_fund, true },
{ "payments", "paymentsaddress", &paymentsaddress, true },
{ "payments", "paymentstxidopret", &payments_txidopret, true },
{ "payments", "paymentscreate", &payments_create, true },
{ "payments", "paymentsairdrop", &payments_airdrop, true },
{ "payments", "paymentsairdroptokens", &payments_airdroptokens, true },
{ "payments", "paymentslist", &payments_list, true },
{ "payments", "paymentsinfo", &payments_info, true },
{ "payments", "paymentsfund", &payments_fund, true },
{ "payments", "paymentsmerge", &payments_merge, true },
{ "payments", "paymentsrelease", &payments_release, true },
{ "CClib", "cclibaddress", &cclibaddress, true },
@@ -538,6 +556,8 @@ static const CRPCCommand vRPCCommands[] =
/* Address index */
{ "addressindex", "getaddressmempool", &getaddressmempool, true },
{ "addressindex", "getaddressutxos", &getaddressutxos, false },
{ "addressindex", "checknotarization", &checknotarization, false },
{ "addressindex", "getnotarypayinfo", &getnotarypayinfo, false },
{ "addressindex", "getaddressdeltas", &getaddressdeltas, false },
{ "addressindex", "getaddresstxids", &getaddresstxids, false },
{ "addressindex", "getaddressbalance", &getaddressbalance, false },
@@ -561,10 +581,6 @@ static const CRPCCommand vRPCCommands[] =
{ "util", "reconsiderblock", &reconsiderblock, true },
/* Not shown in help */
{ "hidden", "setmocktime", &setmocktime, true },
{ "hidden", "test_ac", &test_ac, true },
{ "hidden", "test_heirmarker", &test_heirmarker, true },
{ "hidden", "test_proof", &test_proof, true },
{ "hidden", "test_burntx", &test_burntx, true },
#ifdef ENABLE_WALLET
@@ -635,6 +651,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "z_importviewingkey", &z_importviewingkey, true },
{ "wallet", "z_exportwallet", &z_exportwallet, true },
{ "wallet", "z_importwallet", &z_importwallet, true },
{ "wallet", "opreturn_burn", &opreturn_burn, true },
// TODO: rearrange into another category
{ "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true },
@@ -839,21 +856,30 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue &params
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
{
return "> komodo-cli " + methodname + " " + args + "\n";
if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
return "> komodo-cli " + methodname + " " + args + "\n";
} else if ((strncmp(ASSETCHAINS_SYMBOL, "HUSH3", 5) == 0) ) {
return "> hush-cli " + methodname + " " + args + "\n";
} else {
return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n";
}
}
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
{
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:7771/\n";
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:" + to_string(ASSETCHAINS_RPCPORT) + "/\n";
}
string experimentalDisabledHelpMsg(const string& rpc, const string& enableArg)
{
string daemon = ASSETCHAINS_SYMBOL[0] == 0 ? "komodod" : "hushd";
string ticker = ASSETCHAINS_SYMBOL[0] == 0 ? "komodo" : ASSETCHAINS_SYMBOL;
return "\nWARNING: " + rpc + " is disabled.\n"
"To enable it, restart zcashd with the -experimentalfeatures and\n"
"To enable it, restart " + daemon + " with the -experimentalfeatures and\n"
"-" + enableArg + " commandline options, or add these two lines\n"
"to the zcash.conf file:\n\n"
"to the " + ticker + ".conf file:\n\n"
"experimentalfeatures=1\n"
+ enableArg + "=1\n";
}

View File

@@ -210,6 +210,8 @@ extern UniValue getaddresstxids(const UniValue& params, bool fHelp);
extern UniValue getsnapshot(const UniValue& params, bool fHelp);
extern UniValue getaddressbalance(const UniValue& params, bool fHelp);
extern UniValue getpeerinfo(const UniValue& params, bool fHelp);
extern UniValue checknotarization(const UniValue& params, bool fHelp);
extern UniValue getnotarypayinfo(const UniValue& params, bool fHelp);
extern UniValue ping(const UniValue& params, bool fHelp);
extern UniValue addnode(const UniValue& params, bool fHelp);
extern UniValue disconnectnode(const UniValue& params, bool fHelp);
@@ -265,12 +267,14 @@ extern UniValue oraclesaddress(const UniValue& params, bool fHelp);
extern UniValue oracleslist(const UniValue& params, bool fHelp);
extern UniValue oraclesinfo(const UniValue& params, bool fHelp);
extern UniValue oraclescreate(const UniValue& params, bool fHelp);
extern UniValue oraclesfund(const UniValue& params, bool fHelp);
extern UniValue oraclesregister(const UniValue& params, bool fHelp);
extern UniValue oraclessubscribe(const UniValue& params, bool fHelp);
extern UniValue oraclesdata(const UniValue& params, bool fHelp);
extern UniValue oraclessamples(const UniValue& params, bool fHelp);
extern UniValue pricesaddress(const UniValue& params, bool fHelp);
extern UniValue priceslist(const UniValue& params, bool fHelp);
extern UniValue mypriceslist(const UniValue& params, bool fHelp);
extern UniValue pricesinfo(const UniValue& params, bool fHelp);
extern UniValue pegsaddress(const UniValue& params, bool fHelp);
extern UniValue marmaraaddress(const UniValue& params, bool fHelp);
@@ -285,8 +289,11 @@ extern UniValue marmara_lock(const UniValue& params, bool fHelp);
extern UniValue paymentsaddress(const UniValue& params, bool fHelp);
extern UniValue payments_release(const UniValue& params, bool fHelp);
extern UniValue payments_fund(const UniValue& params, bool fHelp);
extern UniValue payments_merge(const UniValue& params, bool fHelp);
extern UniValue payments_txidopret(const UniValue& params, bool fHelp);
extern UniValue payments_create(const UniValue& params, bool fHelp);
extern UniValue payments_airdrop(const UniValue& params, bool fHelp);
extern UniValue payments_airdroptokens(const UniValue& params, bool fHelp);
extern UniValue payments_info(const UniValue& params, bool fHelp);
extern UniValue payments_list(const UniValue& params, bool fHelp);
@@ -466,6 +473,7 @@ extern UniValue z_shieldcoinbase(const UniValue& params, bool fHelp); // in rpcw
extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_getoperationresult(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_listoperationids(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue opreturn_burn(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpcmisc.cpp
extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp
extern UniValue z_validatepaymentdisclosure(const UniValue &params, bool fHelp); // in rpcdisclosure.cpp
@@ -478,9 +486,13 @@ extern UniValue crosschainproof(const UniValue& params, bool fHelp);
extern UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp);
extern UniValue scanNotarisationsDB(const UniValue& params, bool fHelp);
extern UniValue getimports(const UniValue& params, bool fHelp);
extern UniValue getwalletburntransactions(const UniValue& params, bool fHelp);
extern UniValue migrate_converttoexport(const UniValue& params, bool fHelp);
extern UniValue migrate_createburntransaction(const UniValue& params, bool fHelp);
extern UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp);
extern UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp);
extern UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp);
extern UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fHelp);
extern UniValue notaries(const UniValue& params, bool fHelp);
extern UniValue minerids(const UniValue& params, bool fHelp);
@@ -493,11 +505,14 @@ extern UniValue paxdeposit(const UniValue& params, bool fHelp);
extern UniValue paxwithdraw(const UniValue& params, bool fHelp);
extern UniValue prices(const UniValue& params, bool fHelp);
extern UniValue pricesbet(const UniValue& params, bool fHelp);
extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp);
extern UniValue pricescashout(const UniValue& params, bool fHelp);
extern UniValue pricesrekt(const UniValue& params, bool fHelp);
extern UniValue pricesaddfunding(const UniValue& params, bool fHelp);
extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp);
extern UniValue pricesrefillfund(const UniValue& params, bool fHelp);
// test rpc:
extern UniValue test_ac(const UniValue& params, bool fHelp);
extern UniValue test_heirmarker(const UniValue& params, bool fHelp);
extern UniValue test_burntx(const UniValue& params, bool fHelp);
extern UniValue test_proof(const UniValue& params, bool fHelp);
#endif // BITCOIN_RPCSERVER_H

View File

@@ -0,0 +1,268 @@
// Copyright (c) 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.
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include <stdexcept>
#include "amount.h"
#include "chain.h"
#include "chainparams.h"
#include "checkpoints.h"
#include "crosschain.h"
#include "base58.h"
#include "consensus/validation.h"
#include "cc/eval.h"
#include "main.h"
#include "primitives/transaction.h"
#include "rpc/server.h"
#include "streams.h"
#include "sync.h"
#include "util.h"
#include "script/script.h"
#include "script/script_error.h"
#include "script/sign.h"
#include "script/standard.h"
#include <stdint.h>
#include <univalue.h>
#include <regex>
#include "cc/CCinclude.h"
#include "cc/CCPrices.h"
using namespace std;
int32_t ensure_CCrequirements(uint8_t evalcode);
UniValue test_ac(const UniValue& params, bool fHelp)
{
// make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 4))
throw runtime_error("incorrect params\n");
if (ensure_CCrequirements(EVAL_HEIR) < 0)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
std::vector<unsigned char> pubkey1;
std::vector<unsigned char> pubkey2;
pubkey1 = ParseHex(params[0].get_str().c_str());
pubkey2 = ParseHex(params[1].get_str().c_str());
CPubKey pk1 = pubkey2pk(pubkey1);
CPubKey pk2 = pubkey2pk(pubkey2);
if (!pk1.IsValid() || !pk2.IsValid())
throw runtime_error("invalid pubkey\n");
int64_t txfee = 10000;
int64_t amount = atoll(params[2].get_str().c_str()) * COIN;
uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str());
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60);
if (normalInputs < txfee + amount)
throw runtime_error("not enough normals\n");
mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2));
CScript opret;
fundingtxid = revuint256(fundingtxid);
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0);
cp = CCinit(&C, EVAL_HEIR);
return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret));
}
UniValue test_heirmarker(const UniValue& params, bool fHelp)
{
// make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 1))
throw runtime_error("incorrect params\n");
if (ensure_CCrequirements(EVAL_HEIR) < 0)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
if (normalInputs < 10000)
throw runtime_error("not enough normals\n");
mtx.vin.push_back(CTxIn(fundingtxid, 1));
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey));
CScript opret;
fundingtxid = revuint256(fundingtxid);
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0);
cp = CCinit(&C, EVAL_HEIR);
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
}
UniValue test_burntx(const UniValue& params, bool fHelp)
{
// make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 1))
throw runtime_error("incorrect params\n");
if (ensure_CCrequirements(EVAL_TOKENS) < 0)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str());
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
if (normalInputs < 10000)
throw runtime_error("not enough normals\n");
CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY));
mtx.vin.push_back(CTxIn(tokenid, 0));
mtx.vin.push_back(CTxIn(tokenid, 1));
mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk));
std::vector<CPubKey> voutPubkeys;
voutPubkeys.push_back(burnpk);
cp = CCinit(&C, EVAL_TOKENS);
std::vector<uint8_t> vopret;
GetNonfungibleData(tokenid, vopret);
if (vopret.size() > 0)
cp->additionalTokensEvalcode2 = vopret.begin()[0];
uint8_t tokenpriv[33];
char unspendableTokenAddr[64];
CPubKey unspPk = GetUnspendable(cp, tokenpriv);
GetCCaddress(cp, unspendableTokenAddr, unspPk);
CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr);
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t()))));
}
UniValue test_proof(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
std::vector<uint8_t>proof;
if (fHelp || (params.size() != 2))
throw runtime_error("incorrect params\n");
proof = ParseHex(params[0].get_str());
uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str());
std::vector<uint256> txids;
CMerkleBlock merkleBlock;
if (!E_UNMARSHAL(proof, ss >> merkleBlock)) {
result.push_back(Pair("error", "could not unmarshal proof"));
return result;
}
uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids);
result.push_back(Pair("source_root", merkleRoot.GetHex()));
for (int i = 0; i < txids.size(); i++)
std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl;
std::vector<bool> vMatches(txids.size());
for (auto v : vMatches) v = true;
CPartialMerkleTree verifTree(txids, vMatches);
result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex()));
if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) {
fprintf(stderr, "invalid proof for this cointxid\n");
}
std::vector<uint256> vMerkleTree;
bool f;
::BuildMerkleTree(&f, txids, vMerkleTree);
std::vector<uint256> vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree);
uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0);
result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex()));
return result;
}
extern CScript prices_costbasisopret(uint256 bettxid, CPubKey mypk, int32_t height, int64_t costbasis);
UniValue test_pricesmarker(const UniValue& params, bool fHelp)
{
// make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 1))
throw runtime_error("incorrect params\n");
if (ensure_CCrequirements(EVAL_PRICES) < 0)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
uint256 bettxid = Parseuint256((char *)params[0].get_str().c_str());
cp = CCinit(&C, EVAL_PRICES);
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
if (normalInputs < 10000)
throw runtime_error("not enough normals\n");
mtx.vin.push_back(CTxIn(bettxid, 1));
mtx.vout.push_back(CTxOut(1000, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG));
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, prices_costbasisopret(bettxid, myPubkey, 100, 100)));
}
static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
/* Not shown in help */
{ "hidden", "test_ac", &test_ac, true },
{ "hidden", "test_heirmarker", &test_heirmarker, true },
{ "hidden", "test_proof", &test_proof, true },
{ "hidden", "test_burntx", &test_burntx, true },
{ "hidden", "test_pricesmarker", &test_pricesmarker, true }
};
void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
}

View File

@@ -85,6 +85,7 @@ const CScriptExt &CScriptExt::AddCheckLockTimeVerify(int64_t unlocktime) const
*((CScript *)this) << OP_DROP;
return *this;
}
return *this;
}
// combined CLTV script and P2PKH

View File

@@ -458,13 +458,13 @@ uint32_t komodo_segid32(char *coinaddr);
{"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} \
};
int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top ,std::vector <std::pair<CAmount, std::string>> &vaddr, UniValue *ret)
bool CBlockTreeDB::Snapshot2(std::map <std::string, CAmount> &addressAmounts, UniValue *ret)
{
int64_t total = 0; int64_t totalAddresses = 0; std::string address;
int64_t utxos = 0; int64_t ignoredAddresses = 0, cryptoConditionsUTXOs = 0, cryptoConditionsTotals = 0;
DECLARE_IGNORELIST
boost::scoped_ptr<CDBIterator> iter(NewIterator());
std::map <std::string, CAmount> addressAmounts;
//std::map <std::string, CAmount> addressAmounts;
for (iter->SeekToLast(); iter->Valid(); iter->Prev())
{
boost::this_thread::interruption_point();
@@ -481,45 +481,46 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top ,std::vector
try {
CAmount nValue;
iter->GetValue(nValue);
if ( nValue == 0 )
continue;
getAddressFromIndex(indexKey.type, indexKey.hashBytes, address);
if ( indexKey.type == 3 )
{
cryptoConditionsUTXOs++;
cryptoConditionsTotals += nValue;
total += nValue;
continue;
}
if ( nValue > dustthreshold )
std::map <std::string, int>::iterator ignored = ignoredMap.find(address);
if (ignored != ignoredMap.end())
{
std::map <std::string, int>::iterator ignored = ignoredMap.find(address);
if (ignored != ignoredMap.end())
{
fprintf(stderr,"ignoring %s\n", address.c_str());
ignoredAddresses++;
continue;
}
std::map <std::string, CAmount>::iterator pos = addressAmounts.find(address);
if ( pos == addressAmounts.end() )
{
// insert new address + utxo amount
//fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue);
addressAmounts[address] = nValue;
totalAddresses++;
}
else
{
// update unspent tally for this address
//fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue);
addressAmounts[address] += nValue;
}
//fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN);
// total += nValue;
utxos++;
} //else fprintf(stderr,"ignoring amount=0 UTXO for %s\n", address.c_str());
fprintf(stderr,"ignoring %s\n", address.c_str());
ignoredAddresses++;
continue;
}
std::map <std::string, CAmount>::iterator pos = addressAmounts.find(address);
if ( pos == addressAmounts.end() )
{
// insert new address + utxo amount
//fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue);
addressAmounts[address] = nValue;
totalAddresses++;
}
else
{
// update unspent tally for this address
//fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue);
addressAmounts[address] += nValue;
}
//fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN);
// total += nValue;
utxos++;
total += nValue;
}
catch (const std::exception& e)
{
fprintf(stderr, "DONE %s: LevelDB addressindex exception! - %s\n", __func__, e.what());
break;
return false; //break; this means failiure of DB? we need to exit here if so for consensus code!
}
}
}
@@ -530,30 +531,18 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top ,std::vector
}
}
//fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses);
for (std::pair<std::string, CAmount> element : addressAmounts)
vaddr.push_back( make_pair(element.second, element.first) );
std::sort(vaddr.rbegin(), vaddr.rend());
int topN = 0;
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it)
{
total += it->first;
topN++;
// If requested, only show top N addresses in output JSON
if ( top == topN )
break;
}
// this is for the snapshot RPC, you can skip this by passing a 0 as the last argument.
if (ret)
{
// Total amount in this snapshot, which is less than circulating supply if top parameter is used
// Use the address_total for a total of all address included when using top parameter.
ret->push_back(make_pair("total", (double) (total+cryptoConditionsTotals)/ COIN ));
// Total circulating supply without CC vouts.
ret->push_back(make_pair("total", (double) (total)/ COIN ));
// Average amount in each address of this snapshot
ret->push_back(make_pair("average",(double) (total/COIN) / totalAddresses ));
// Total number of utxos processed in this snaphot
ret->push_back(make_pair("utxos", utxos));
// Total number of addresses in this snaphot
ret->push_back(make_pair("total_addresses", top ? top : totalAddresses ));
ret->push_back(make_pair("total_addresses", totalAddresses ));
// Total number of ignored addresses in this snaphot
ret->push_back(make_pair("ignored_addresses", ignoredAddresses));
// Total number of crypto condition utxos we skipped
@@ -561,22 +550,39 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top ,std::vector
// Total value of skipped crypto condition utxos
ret->push_back(make_pair("cc_utxo_value", (double) cryptoConditionsTotals / COIN));
// total of all the address's, does not count coins in CC vouts.
ret->push_back(make_pair("address_total", (double) total/ COIN ));
ret->push_back(make_pair("total_includeCCvouts", (double) (total+cryptoConditionsTotals)/ COIN ));
// The snapshot finished at this block height
ret->push_back(make_pair("ending_height", chainActive.Height()));
}
return(topN);
return true;
}
extern std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
UniValue CBlockTreeDB::Snapshot(int top)
{
int topN = 0;
std::vector <std::pair<CAmount, std::string>> vaddr;
//std::vector <std::vector <std::pair<CAmount, CScript>>> tokenids;
std::map <std::string, CAmount> addressAmounts;
UniValue result(UniValue::VOBJ);
UniValue addressesSorted(UniValue::VARR);
result.push_back(Pair("start_time", (int) time(NULL)));
if ( Snapshot2(0,top,vaddr,&result) != 0 )
if ( (vAddressSnapshot.size() > 0 && top < 0) || (Snapshot2(addressAmounts,&result) && top >= 0) )
{
if ( top > -1 )
{
for (std::pair<std::string, CAmount> element : addressAmounts)
vaddr.push_back( make_pair(element.second, element.first) );
std::sort(vaddr.rbegin(), vaddr.rend());
}
else
{
for ( auto address : vAddressSnapshot )
vaddr.push_back(make_pair(address.first, CBitcoinAddress(address.second).ToString()));
top = vAddressSnapshot.size();
}
int topN = 0;
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it)
{
UniValue obj(UniValue::VOBJ);
@@ -712,6 +718,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nTx = diskindex.nTx;
pindexNew->nSproutValue = diskindex.nSproutValue;
pindexNew->nSaplingValue = diskindex.nSaplingValue;
pindexNew->segid = diskindex.segid;
pindexNew->nNotaryPay = diskindex.nNotaryPay;
//fprintf(stderr,"loadguts ht.%d\n",pindexNew->GetHeight());
// Consistency checks
auto header = pindexNew->GetBlockHeader();

View File

@@ -116,7 +116,7 @@ public:
bool LoadBlockIndexGuts();
bool blockOnchainActive(const uint256 &hash);
UniValue Snapshot(int top);
int32_t Snapshot2(int64_t dustthreshold, int32_t top,std::vector <std::pair<CAmount, std::string>> &vaddr, UniValue *ret);
bool Snapshot2(std::map <std::string, CAmount> &addressAmounts, UniValue *ret);
};
#endif // BITCOIN_TXDB_H

View File

@@ -394,27 +394,23 @@ void ParseParameters(int argc, const char* const argv[])
}
}
// split string using by space or comma as a delimiter char
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals)
{
stringstream ss(strVal);
std::string str;
while ( ss.peek() == ' ' )
ss.ignore();
while ( ss >> str )
{
if ( str.size() == 0 )
continue;
if ( str[str.size()-1] == ',' )
str.resize(str.size()-1);
outVals.push_back(str);
while ( ss.peek() == ' ' )
ss.ignore();
if ( ss.peek() == ',' )
ss.ignore();
while ( ss.peek() == ' ' )
while (!ss.eof()) {
int c;
std::string str;
while (std::isspace(ss.peek()))
ss.ignore();
while ((c = ss.get()) != EOF && !std::isspace(c) && c != ',')
str += c;
if (!str.empty())
outVals.push_back(str);
}
}

View File

@@ -287,6 +287,9 @@ template <typename Callable> void TraceThread(const char* name, Callable func)
}
}
// split string using by space or comma as a delimiter char
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals);
#define KOMODO_ASSETCHAIN_MAXLEN 65

View File

@@ -24,6 +24,7 @@ int32_t ASSETCHAINS_LWMAPOS = 0;
int32_t VERUS_BLOCK_POSUNITS = 1000;
int32_t ASSETCHAINS_OVERWINTER = 227520;
int32_t ASSETCHAINS_SAPLING = 227520;
int32_t KOMODO_TESTNODE = 0;
unsigned int MAX_BLOCK_SIGOPS = 20000;

View File

@@ -46,6 +46,7 @@
#include <thread>
#include "paymentdisclosuredb.h"
int32_t komodo_blockheight(uint256 hash);
using namespace libzcash;
@@ -677,7 +678,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
if (mapBlockIndex.find(wtx.hashBlock) == mapBlockIndex.end()) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("mapBlockIndex does not contain block hash %s", wtx.hashBlock.ToString()));
}
wtxHeight = mapBlockIndex[wtx.hashBlock]->GetHeight();
wtxHeight = komodo_blockheight(wtx.hashBlock);
wtxDepth = wtx.GetDepthInMainChain();
}
LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n",

View File

@@ -55,6 +55,7 @@ using namespace libzcash;
extern char ASSETCHAINS_SYMBOL[65];
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
int32_t komodo_blockheight(uint256 hash);
int tx_height( const uint256 &hash );
extern UniValue signrawtransaction(const UniValue& params, bool fHelp);
extern UniValue sendrawtransaction(const UniValue& params, bool fHelp);
@@ -836,7 +837,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
if (mapBlockIndex.find(wtx.hashBlock) == mapBlockIndex.end()) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("mapBlockIndex does not contain block hash %s", wtx.hashBlock.ToString()));
}
wtxHeight = mapBlockIndex[wtx.hashBlock]->GetHeight();
wtxHeight = komodo_blockheight(wtx.hashBlock);
wtxDepth = wtx.GetDepthInMainChain();
}
LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n",

View File

@@ -33,7 +33,17 @@
#include <boost/filesystem/path.hpp>
#include <db_cxx.h>
#ifdef BUILD_ROGUE
#ifdef __APPLE__
#include "../depends/x86_64-apple-darwin18.6.0/include/db_cxx.h"
#elif defined(_WIN32)
#include "../depends/x86_64-w64-mingw32/include/db_cxx.h"
#else
#include "../depends/x86_64-unknown-linux-gnu/include/db_cxx.h"
#endif
#else
#include <db_cxx.h>
#endif
extern unsigned int nWalletDBUpdated;

View File

@@ -526,6 +526,59 @@ TEST(WalletTests, FindMySaplingNotes) {
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
}
TEST(WalletTests, FindMySaplingNotesWithIvkOnly) {
SelectParams(CBaseChainParams::REGTEST);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
auto consensusParams = Params().GetConsensus();
TestWallet wallet;
// Generate dummy Sapling address
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
HDSeed seed(rawSeed);
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
auto addr = sk.DefaultAddress();
auto expsk = sk.expsk;
auto fvk = expsk.full_viewing_key();
auto pk = sk.DefaultAddress();
auto ivk = fvk.in_viewing_key();
// Generate dummy Sapling note
libzcash::SaplingNote note(pk, 50000);
auto cm = note.cm().get();
SaplingMerkleTree tree;
tree.append(cm);
auto anchor = tree.root();
auto witness = tree.witness();
// Generate transaction
auto builder = TransactionBuilder(consensusParams, 1);
ASSERT_TRUE(builder.AddSaplingSpend(expsk, note, anchor, witness));
builder.AddSaplingOutput(fvk.ovk, pk, 25000, {});
auto maybe_tx = builder.Build();
ASSERT_EQ(static_cast<bool>(maybe_tx), true);
auto tx = maybe_tx.get();
// No Sapling notes can be found in tx which does not belong to the wallet
CWalletTx wtx {&wallet, tx};
ASSERT_FALSE(wallet.HaveSaplingSpendingKey(fvk));
ASSERT_FALSE(wallet.HaveSaplingIncomingViewingKey(addr));
auto noteMap = wallet.FindMySaplingNotes(wtx).first;
EXPECT_EQ(0, noteMap.size());
// Add ivk to wallet, so Sapling notes can be found
ASSERT_TRUE(wallet.AddSaplingIncomingViewingKey(ivk, addr));
ASSERT_FALSE(wallet.HaveSaplingSpendingKey(fvk));
ASSERT_TRUE(wallet.HaveSaplingIncomingViewingKey(addr));
noteMap = wallet.FindMySaplingNotes(wtx).first;
EXPECT_EQ(2, noteMap.size());
// Revert to default
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
}
TEST(WalletTests, FindMySproutNotes) {
CWallet wallet;
@@ -1627,6 +1680,63 @@ TEST(WalletTests, WriteWitnessCache) {
wallet.SetBestChain(walletdb, loc);
}
TEST(WalletTests, SetBestChainIgnoresTxsWithoutShieldedData) {
SelectParams(CBaseChainParams::REGTEST);
TestWallet wallet;
MockWalletDB walletdb;
CBlockLocator loc;
// Set up transparent address
CKey tsk = DecodeSecret(tSecretRegtest);
wallet.AddKey(tsk);
auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID());
// Set up a Sprout address
auto sk = libzcash::SproutSpendingKey::random();
wallet.AddSproutSpendingKey(sk);
// Generate a transparent transaction that is ours
CMutableTransaction t;
t.vout.resize(1);
t.vout[0].nValue = 90*CENT;
t.vout[0].scriptPubKey = scriptPubKey;
CWalletTx wtxTransparent {nullptr, t};
wallet.AddToWallet(wtxTransparent, true, NULL);
// Generate a Sprout transaction that is ours
auto wtxSprout = GetValidReceive(sk, 10, true);
auto noteMap = wallet.FindMySproutNotes(wtxSprout);
wtxSprout.SetSproutNoteData(noteMap);
wallet.AddToWallet(wtxSprout, true, NULL);
// Generate a Sprout transaction that only involves our transparent address
auto sk2 = libzcash::SproutSpendingKey::random();
auto wtxInput = GetValidReceive(sk2, 10, true);
auto note = GetNote(sk2, wtxInput, 0, 0);
auto wtxTmp = GetValidSpend(sk2, note, 5);
CMutableTransaction mtx {wtxTmp};
mtx.vout[0].scriptPubKey = scriptPubKey;
CWalletTx wtxSproutTransparent {NULL, mtx};
wallet.AddToWallet(wtxSproutTransparent, true, NULL);
EXPECT_CALL(walletdb, TxnBegin())
.WillOnce(Return(true));
EXPECT_CALL(walletdb, WriteTx(wtxTransparent.GetHash(), wtxTransparent))
.Times(0);
EXPECT_CALL(walletdb, WriteTx(wtxSprout.GetHash(), wtxSprout))
.Times(1).WillOnce(Return(true));
EXPECT_CALL(walletdb, WriteTx(wtxSproutTransparent.GetHash(), wtxSproutTransparent))
.Times(0);
EXPECT_CALL(walletdb, WriteWitnessCacheSize(0))
.WillOnce(Return(true));
EXPECT_CALL(walletdb, WriteBestBlock(loc))
.WillOnce(Return(true));
EXPECT_CALL(walletdb, TxnCommit())
.WillOnce(Return(true));
wallet.SetBestChain(walletdb, loc);
}
TEST(WalletTests, UpdateSproutNullifierNoteMap) {
TestWallet wallet;
uint256 r {GetRandHash()};

Some files were not shown because too many files have changed in this diff Show More