diff --git a/code_of_conduct.md b/code_of_conduct.md index c4592cc325a..a5caabf68c9 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -48,7 +48,6 @@ You may send reports to [our Conduct email](mailto:developer@komodoplatform.com) If you wish to contact specific maintainers directly, the following have made themselves available for conduct issues: -- Benny Fairbank (benny at komodoplatform.com) - Support Team (support at komodoplatform.com) - ca333 (ca333 at komodoplatform.com) @@ -58,4 +57,3 @@ version 1.3.0, available at [homepage]: https://www.contributor-covenant.org [version]: https://www.contributor-covenant.org/version/1/3/0/ - diff --git a/configure.ac b/configure.ac index b169ec4c8c5..323590a43c2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 7) -define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_BUILD, 0) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt index a6e8be20753..92df0ed8420 100644 --- a/contrib/seeds/nodes_main.txt +++ b/contrib/seeds/nodes_main.txt @@ -1,6 +1,4 @@ -185.25.48.236:27485 -185.25.48.236:27487 -185.64.105.111:27485 -185.64.105.111:27487 -185.25.48.72:27485 -185.25.48.72:27487 +199.127.60.142:7770 +104.238.221.61:7770 +209.222.101.247:7770 +103.195.100.32:7770 diff --git a/src/Makefile.am b/src/Makefile.am index 23cff51cba9..2266258bd7e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,16 +31,7 @@ BITCOIN_INCLUDES += -I$(srcdir)/snark BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark BITCOIN_INCLUDES += -I$(srcdir)/univalue/include -if TARGET_WINDOWS -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl -endif -if TARGET_DARWIN -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl -endif -if TARGET_LINUX -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl -endif - +LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CLI=libbitcoin_cli.a @@ -53,6 +44,7 @@ LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a +LIBCJSON=libcjson.a if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a @@ -91,6 +83,19 @@ $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " +#%.o: %.c +# $(CC) -c -o $@ $< + +#$(LIBCJSON): cJSON.o komodo_cJSON.o komodo_cutils.o +# $(AR) cr $(LIBCJSON) $^ + +# libcjson build +LIBCJSON=libcjson.a +libcjson_a_SOURCES = cJSON.c \ + komodo_cJSON.c komodo_cutils.cpp +libcjson_a_CPPFLAGS=-fPIC +EXTRA_LIBRARIES += $(LIBCJSON) + # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ @@ -280,6 +285,7 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: zcashd libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +libbitcoin_server_a_CPPFLAGS += -fPIC libbitcoin_server_a_SOURCES = \ sendalert.cpp \ addrman.cpp \ @@ -306,7 +312,6 @@ libbitcoin_server_a_SOURCES = \ cc/oracles.cpp \ cc/prices.cpp \ cc/pegs.cpp \ - cc/marmara.cpp \ cc/payments.cpp \ cc/gateways.cpp \ cc/channels.cpp \ @@ -353,6 +358,7 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ validationinterface.cpp \ + mini-gmp.c \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -478,10 +484,25 @@ libbitcoin_common_a_SOURCES = \ crypto/verus_hash.h \ crypto/verus_hash.cpp \ hash.cpp \ + hex.c \ importcoin.cpp \ key.cpp \ key_io.cpp \ keystore.cpp \ + komodo_structs.cpp \ + komodo.cpp \ + komodo_bitcoind.cpp \ + komodo_ccdata.cpp \ + komodo_curve25519.cpp \ + komodo_events.cpp \ + komodo_gateway.cpp \ + komodo_globals.cpp \ + komodo_interest.cpp \ + komodo_jumblr.cpp \ + komodo_kv.cpp \ + komodo_notary.cpp \ + komodo_pax.cpp \ + komodo_utils.cpp \ netbase.cpp \ metrics.cpp \ primitives/block.cpp \ @@ -580,6 +601,7 @@ komodod_LDADD += $(LIBBITCOIN_WALLET) endif komodod_LDADD += \ + $(LIBCJSON) \ $(BOOST_LIBS) \ $(BDB_LIBS) \ $(SSL_LIBS) \ @@ -591,7 +613,8 @@ komodod_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) + $(LIBZCASH_LIBS) \ + -lcurl if TARGET_DARWIN komodod_LDADD += libcc.dylib $(LIBSECP256K1) diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index bfbccc196ad..93aa7bc058f 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -14,7 +14,9 @@ komodo_test_SOURCES = \ test-komodo/test_sha256_crypto.cpp \ test-komodo/test_script_standard_tests.cpp \ test-komodo/test_addrman.cpp \ - test-komodo/test_netbase_tests.cpp + test-komodo/test_netbase_tests.cpp \ + test-komodo/test_events.cpp \ + test-komodo/test_hex.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/ac.json b/src/ac.json index 7ffed005a95..f0405721181 100644 --- a/src/ac.json +++ b/src/ac.json @@ -53,18 +53,6 @@ "ac_supply": "999999" } , - "COQUICASH": { - "ac_supply": "72000000", - "ac_reward": "7200000000", - "ac_staked": "50", - "ac_halving": "420000", - "ac_cc": "2", - "ac_ccenable": "227,235,236,241", - "addnode": [ - "78.47.108.168" - ] - } - , "WLC": { "ac_supply": "210000000" @@ -81,20 +69,12 @@ } , - "AXO": { - "ac_supply": "200000000", - "ac_ccactivate": "130000" - } - , + "ETOMIC": { "ac_supply": "100000000" } - , - "BTCH": { - "ac_supply": "20998641" - } , "NINJA": { diff --git a/src/ac/axo b/src/ac/axo deleted file mode 100755 index 18d38cac070..00000000000 --- a/src/ac/axo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/ac/btch b/src/ac/btch deleted file mode 100755 index 6a57ea8d1f7..00000000000 --- a/src/ac/btch +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/coquicash b/src/ac/coquicash deleted file mode 100755 index c882b223923..00000000000 --- a/src/ac/coquicash +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=COQUICASH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/oot b/src/ac/oot deleted file mode 100755 index 4c7c6b68345..00000000000 --- a/src/ac/oot +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 diff --git a/src/assetchains.json b/src/assetchains.json index 68486cfbe27..460ee637151 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -1,9 +1,4 @@ [ - { - "ac_name": "AXO", - "ac_supply": "200000000", - "ac_ccactivate": "130000" - }, { "ac_name": "BET", "ac_supply": "999999" @@ -12,10 +7,6 @@ "ac_name": "BOTS", "ac_supply": "999999" }, - { - "ac_name": "BTCH", - "ac_supply": "20998641" - }, { "ac_name": "CCL", "ac_supply": "200000000", @@ -25,16 +16,6 @@ "spentindex": "1", "addnode": ["142.93.136.89", "195.201.22.89"] }, - { - "ac_name": "COQUICASH", - "ac_supply": "72000000", - "ac_reward": "7200000000", - "ac_staked": "50", - "ac_halving": "420000", - "ac_cc": "2", - "ac_ccenable": "227,235,236,241", - "addnode": ["78.47.108.168"] - }, { "ac_name": "CRYPTO", "ac_supply": "999999" @@ -94,12 +75,6 @@ "ac_name": "NINJA", "ac_supply": "100000000" }, - { - "ac_name": "OOT", - "ac_supply": "216000000", - "ac_sapling": "5000000", - "addnode": ["88.99.212.81"] - }, { "ac_name": "PANGEA", "ac_supply": "999999" diff --git a/src/assetchains.old b/src/assetchains.old index 26815545548..f13325eeab0 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -4,12 +4,9 @@ delay=60 source pubkey.txt echo $pubkey -./komodod -pubkey=$pubkey -ac_name=AXO -ac_supply=200000000 -ac_ccactivate=130000 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=BTCH -ac_supply=20998641 -addnode=95.213.238.98 & ./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 $1 & -./komodod -pubkey=$pubkey -ac_name=COQUICASH -ac_supply=72000000 -ac_reward=7200000000 -ac_staked=50 -ac_halving=420000 -ac_cc=2 -ac_ccenable=227,235,236,241 -addnode=78.47.108.168 $1 & ./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=GLEEC -ac_supply=210000000 -ac_public=1 -ac_staked=100 -addnode=95.217.161.126 $1 & @@ -22,7 +19,6 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=95.217.44.58 -addnode=138.201.136.145 $1 & ./komodod -pubkey=$pubkey -ac_name=MSHARK -ac_supply=1400000 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=NINJA -ac_supply=100000000 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=OOT -ac_supply=216000000 -ac_sapling=5000000 -addnode=88.99.212.81 $1 & ./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=88.99.212.81 $1 & ./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=95.213.238.98 $1 & diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index ef7b09a37f0..0e933f3cc6e 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -57,7 +57,6 @@ static bool fDaemon; #include "komodo_defs.h" -#define KOMODO_ASSETCHAIN_MAXLEN 65 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern int32_t ASSETCHAINS_BLOCKTIME; extern uint64_t ASSETCHAINS_CBOPRET; @@ -108,7 +107,8 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; +extern bool IS_KOMODO_NOTARY; +extern int32_t USE_EXTERNAL_PUBKEY; extern uint32_t ASSETCHAIN_INIT; extern std::string NOTARY_PUBKEY; int32_t komodo_is_issuer(); diff --git a/src/bits256.h b/src/bits256.h new file mode 100644 index 00000000000..33c54ad558c --- /dev/null +++ b/src/bits256.h @@ -0,0 +1,14 @@ +#pragma once +#include "stdint.h" + +union _bits128 { uint8_t bytes[16]; uint16_t ushorts[8]; uint32_t uints[4]; uint64_t ulongs[2]; uint64_t txid; }; +typedef union _bits128 bits128; + +union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; +typedef union _bits256 bits256; + +union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; +typedef union _bits320 bits320; + +union _bits384 { bits256 sig; uint8_t bytes[48]; uint16_t ushorts[24]; uint32_t uints[12]; uint64_t ulongs[6]; uint64_t txid; }; +typedef union _bits384 bits384; \ No newline at end of file diff --git a/src/cJSON.c b/src/cJSON.c index 09da0688983..bbead0587d7 100644 --- a/src/cJSON.c +++ b/src/cJSON.c @@ -58,8 +58,8 @@ #include "cJSON.h" /* define our own boolean type */ -//#define true ((cJSON_bool)1) -//#define false ((cJSON_bool)0) +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) typedef struct { const unsigned char *json; diff --git a/src/cc/CCMarmara.h b/src/cc/CCMarmara.h deleted file mode 100644 index 85f9175d17a..00000000000 --- a/src/cc/CCMarmara.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - - -#ifndef CC_MARMARA_H -#define CC_MARMARA_H - -#include "CCinclude.h" -#include "../komodo_cJSON.h" - -#define MARMARA_GROUPSIZE 60 -#define MARMARA_MINLOCK (1440 * 3 * 30) -#define MARMARA_MAXLOCK (1440 * 24 * 30) -#define MARMARA_VINS 16 -#define EVAL_MARMARA 0xef - -extern uint8_t ASSETCHAINS_MARMARA; -uint64_t komodo_block_prg(uint32_t nHeight); -int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid); -int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid); -UniValue MarmaraCreditloop(uint256 txid); -UniValue MarmaraSettlement(uint64_t txfee,uint256 batontxid); -UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height); - -UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr); // [[pk0, shares0], [pk1, shares1], ...] -UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag); -UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid); -UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency); - -bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); - -// CCcustom -UniValue MarmaraInfo(); - -#endif diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 6c66b3599fd..1ae0241207b 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "key_io.h" #include "CCinclude.h" #include "CCassets.h" @@ -27,7 +27,6 @@ #include "CCOracles.h" #include "CCPrices.h" #include "CCPegs.h" -#include "CCMarmara.h" #include "CCPayments.h" #include "CCGateways.h" #include "CCtokens.h" @@ -189,17 +188,6 @@ uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, #undef FUNCNAME #undef EVALCODE -// Marmara -#define FUNCNAME IsMarmaraInput -#define EVALCODE EVAL_MARMARA -const char *MarmaraCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; -const char *MarmaraNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; -char MarmaraCChexstr[67] = { "03afc5be570d0ff419425cfcc580cc762ab82baad88c148f5b028d7db7bfeee61d" }; -uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0xdf, 0x05, 0xfe, 0xa2, 0x62, 0x41, 0xa9, 0x09, 0x0f, 0x2a, 0x6b, 0x11, 0x2c, 0xbe, 0xbd, 0x06, 0x31, 0x8d, 0xc0, 0xb9, 0x96, 0x76, 0x3f, 0x24 }; -#include "CCcustom.inc" -#undef FUNCNAME -#undef EVALCODE - // Payments #define FUNCNAME IsPaymentsInput #define EVALCODE EVAL_PAYMENTS @@ -402,14 +390,6 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; - case EVAL_MARMARA: - strcpy(cp->unspendableCCaddr,MarmaraCCaddr); - strcpy(cp->normaladdr,MarmaraNormaladdr); - strcpy(cp->CChexstr,MarmaraCChexstr); - memcpy(cp->CCpriv,MarmaraCCpriv,32); - cp->validate = MarmaraValidate; - cp->ismyvin = IsMarmaraInput; - break; case EVAL_PAYMENTS: strcpy(cp->unspendableCCaddr,PaymentsCCaddr); strcpy(cp->normaladdr,PaymentsNormaladdr); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 1d28e2cc939..5f689f7a5f1 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -16,6 +16,8 @@ #ifndef CC_INCLUDE_H #define CC_INCLUDE_H +#include "hex.h" // for decode_hex and is_hexstr + /*! \file CCinclude.h \brief A Documented file. @@ -85,13 +87,6 @@ Details. #define CCDISABLEALL memset(ASSETCHAINS_CCDISABLES,1,sizeof(ASSETCHAINS_CCDISABLES)) #define CCENABLE(x) ASSETCHAINS_CCDISABLES[((uint8_t)x)] = 0 -/* moved to komodo_cJSON.h -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif -*/ /// \endcond /// identifiers of additional data blobs in token opreturn script: @@ -285,13 +280,6 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo /// @param[out] currentheight current chain height bool NSPV_myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, int32_t &txheight, int32_t ¤theight); -/// decodes char array in hex encoding to byte array -int32_t decode_hex(uint8_t *bytes, int32_t n, char *hex); - -/// checks if char string has hex symbols -/// @returns no zero if string has only hex symbols -int32_t is_hexstr(char *str,int32_t n); - /// CCgettxout returns the amount of an utxo. The function does this without loading the utxo transaction from the chain, by using coin cache /// @param txid transaction id of the utxo /// @param vout utxo transaction vout order number diff --git a/src/cc/Makefile b/src/cc/Makefile index 3e988f27935..24b94226a5a 100644 --- a/src/cc/Makefile +++ b/src/cc/Makefile @@ -2,9 +2,10 @@ SHELL = /bin/sh CC = gcc CC_DARWIN = g++-6 CC_WIN = x86_64-w64-mingw32-gcc-posix -CFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib -CFLAGS = -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 -c -CFLAGS_WIN = -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 -c +CFLAGS = -arch x86_64 +CXXFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib +CXXFLAGS = -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 -c +CXXFLAGS_WIN = -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 -c DEBUGFLAGS = -O0 -D _DEBUG RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) @@ -13,21 +14,27 @@ $(info $(OS)) TARGET = ../libcc.so TARGET_DARWIN = ../libcc.dylib TARGET_WIN = ../libcc.dll -SOURCES = cclib.cpp -#HEADERS = $(shell echo ../cryptoconditions/include/*.h) +SOURCES = cclib.cpp ../cJSON.c +OBJS = cclib.o ../cJSON.o all: $(TARGET) -$(TARGET): $(SOURCES) +%.o: %.c + $(CC) -o $@ $< $(CFLAGS) $(DEBUGFLAGS) + +%.o: %.cpp + $(CC) -o $@ $< $(CXXFLAGS) $(DEBUGFLAGS) + +$(TARGET): $(OBJS) $(info Building cclib to src/) ifeq ($(OS),Darwin) - $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(SOURCES) + $(CC_DARWIN) $(CXXFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(OBJS) else ifeq ($(OS),Linux) - $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES) + $(CC) $(CXXFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJS) #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info WINDOWS) - $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(SOURCES) + $(CC_WIN) $(CXXFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(OBJS) endif clean: diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index 36495314887..f4a4db8444e 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -26,6 +26,7 @@ #include "chain.h" #include "core_io.h" #include "crosschain.h" +#include "hex.h" #define FAUCET2SIZE COIN #define EVAL_FAUCET2 EVAL_FIRSTUSER @@ -612,7 +613,7 @@ std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *para if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) { len >>= 1; - decode_hex(buf,len,(char *)rawhex.c_str()); + decode_hex(buf,len,rawhex.c_str()); hash = bits256_doublesha256(0,buf,len); if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) { diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index e0b185cbc72..4428876668a 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -288,7 +288,6 @@ int64_t iguana_memfree(struct OS_memspace *mem,void *ptr,int32_t size); // generic functions bits256 iguana_merkle(char *symbol,bits256 *tree,int32_t txn_count); bits256 bits256_calctxid(char *symbol,uint8_t *serialized,int32_t len); -int32_t unhex(char c); void touppercase(char *str); uint32_t is_ipaddr(char *str); void iguana_bitmap(char *space,int32_t max,char *name); @@ -297,14 +296,10 @@ int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); int32_t is_decimalstr(char *str); void tolowercase(char *str); -char *clonestr(char *str); -int32_t is_hexstr(char *str,int32_t n); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); void reverse_hexstr(char *str); int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len); uint16_t parse_ipaddr(char *ipaddr,char *ip_port); int32_t bitweight(uint64_t x); -uint8_t _decode_hex(char *hex); char *uppercase_str(char *buf,char *str); char *lowercase_str(char *buf,char *str); int32_t strsearch(char *strs[],int32_t num,char *name); @@ -375,7 +370,7 @@ void calc_base64_encodestr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_base64_decodestr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_hexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_unhexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); -int32_t safecopy(char *dest,char *src,long len); +int32_t safecopy(char *dest,const char *src,long len); double dxblend(double *destp,double val,double decay); uint64_t calc_ipbits(char *ip_port); diff --git a/src/cc/dapps/cJSON.c b/src/cc/dapps/cJSON.c index e1d7801a1d6..6f9a2bdb336 100644 --- a/src/cc/dapps/cJSON.c +++ b/src/cc/dapps/cJSON.c @@ -766,7 +766,7 @@ int64_t conv_cJSON_float(cJSON *json,char *field) int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field) { - int32_t safecopy(char *dest,char *src,long len); + int32_t safecopy(char *dest,const char *src,long len); char *str; cJSON *obj; int32_t len; diff --git a/src/cc/dapps/dappstd.c b/src/cc/dapps/dappstd.c index 82366315c95..c27f79d21b3 100644 --- a/src/cc/dapps/dappstd.c +++ b/src/cc/dapps/dappstd.c @@ -22,6 +22,7 @@ #include #include #include +#include "bits256.h" extern struct games_state globalR; void *gamesiterate(struct games_state *rs); @@ -39,12 +40,6 @@ char whoami[MAXSTR]; #define KOMODO_ASSETCHAIN_MAXLEN 65 char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],IPADDRESS[100]; -#ifndef _BITS256 -#define _BITS256 -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; -#endif - #ifdef _WIN32 #ifdef _MSC_VER int gettimeofday(struct timeval * tp, struct timezone * tzp) @@ -81,112 +76,6 @@ double OS_milliseconds() return(millis); } -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; @@ -218,7 +107,7 @@ char *parse_conf_line(char *line,char *field) return(clonestr(line)); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) @@ -243,9 +132,9 @@ int32_t safecopy(char *dest,char *src,long len) #define true 1 #define false 0 //#ifdef STANDALONE -//#include "../komodo/src/komodo_cJSON.c" +//#include "../komodo/src/komodo_cJSON.h" //#else -#include "../komodo_cJSON.c" +#include "../komodo_cJSON.h" //#endif int32_t games_replay(uint64_t seed,int32_t sleeptime); @@ -291,7 +180,7 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } -uint8_t *OS_fileptr(long *allocsizep,char *fname) +uint8_t *OS_fileptr(long *allocsizep,const char *fname) { long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index ac1f8840095..dec5249af9d 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -31,108 +31,6 @@ void myprintf(const char* format, ...) va_end( marker ); } -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} - -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //myprintf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //myprintf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - myprintf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //myprintf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //myprintf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; @@ -164,7 +62,7 @@ char *clonestr(char *str) return(clone); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) diff --git a/src/cc/dapps/zmigrate.c b/src/cc/dapps/zmigrate.c index f7d9e3feb51..1f97ff88e94 100644 --- a/src/cc/dapps/zmigrate.c +++ b/src/cc/dapps/zmigrate.c @@ -35,108 +35,6 @@ bits256 zeroid; -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} - -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; @@ -168,7 +66,7 @@ char *clonestr(char *str) return(clone); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 48d1049f91f..4374d9663d6 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCdice.h" // timeout @@ -936,7 +936,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, if ( (iswin= DiceIsWinner(entropy,entropyvout,txid,tx,vinTx,hash,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) { // will only happen for fundingPubKey - if ( KOMODO_INSYNC != 0 && KOMODO_DEALERNODE != 0 ) + if ( KOMODO_INSYNC != 0 && IS_KOMODO_DEALERNODE ) DiceQueue(iswin,sbits,fundingtxid,txid,tx,entropyvout); } else @@ -1788,8 +1788,7 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx { if ( myGetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock) != 0 ) { - flag = KOMODO_DEALERNODE != 0; - if ( KOMODO_DEALERNODE != 0 && scriptPubKey == fundingPubKey ) + if ( IS_KOMODO_DEALERNODE && scriptPubKey == fundingPubKey ) { bettorentropy = DiceGetEntropy(betTx,'B'); if ( (iswin= DiceIsWinner(hentropyproof,entropyvout,txid,betTx,entropyTx,bettorentropy,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) @@ -1818,7 +1817,7 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx } } } - if ( didinit == 0 && KOMODO_DEALERNODE == 0 && scriptPubKey == fundingPubKey ) + if ( didinit == 0 && !IS_KOMODO_DEALERNODE && scriptPubKey == fundingPubKey ) { strcpy(_planstr,planstr); dealer0_fundingtxid = fundingtxid; diff --git a/src/cc/eval.h b/src/cc/eval.h index 1324d5e2127..2534338bad6 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -53,7 +53,6 @@ EVAL(EVAL_ORACLES, 0xec) \ EVAL(EVAL_PRICES, 0xed) \ EVAL(EVAL_PEGS, 0xee) \ - EVAL(EVAL_MARMARA, 0xef) \ EVAL(EVAL_PAYMENTS, 0xf0) \ EVAL(EVAL_GATEWAYS, 0xf1) \ EVAL(EVAL_TOKENS, 0xf2) \ diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index 2c0a08451f1..74dfe43d966 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCfaucet.h" #include "../txmempool.h" @@ -202,7 +202,7 @@ UniValue FaucetGet(const CPubKey& pk, uint64_t txfee) if ( (len= (int32_t)result[JSON_HEXTX].getValStr().size()) > 0 && len < 65536 ) { len >>= 1; - decode_hex(buf,len,(char *)result[JSON_HEXTX].getValStr().c_str()); + decode_hex(buf,len,result[JSON_HEXTX].getValStr().c_str()); hash = bits256_doublesha256(0,buf,len); if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) { diff --git a/src/cc/includes/curve25519.h b/src/cc/includes/curve25519.h index 657fab4d011..46d6b15a5f7 100755 --- a/src/cc/includes/curve25519.h +++ b/src/cc/includes/curve25519.h @@ -19,17 +19,7 @@ #include #include #include - -union _bits128 { uint8_t bytes[16]; uint16_t ushorts[8]; uint32_t uints[4]; uint64_t ulongs[2]; uint64_t txid; }; -typedef union _bits128 bits128; -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; - -union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; -typedef union _bits320 bits320; - -union _bits384 { bits256 sig; uint8_t bytes[48]; uint16_t ushorts[24]; uint32_t uints[12]; uint64_t ulongs[6]; uint64_t txid; }; -typedef union _bits384 bits384; +#include "bits256.h" struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; }; struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; }; diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp index 68625c0382b..91c458eaec6 100644 --- a/src/cc/marmara.cpp +++ b/src/cc/marmara.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCMarmara.h" /* diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 0c6edb284dc..048ade82adb 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCPayments.h" /* diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 0fcc2e512c3..f0debddba90 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -1961,24 +1961,14 @@ UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) for (int i = 0; i<1000000; i++, nonce++) { CMutableTransaction tmpmtx = mtx; - //int32_t len; - //uint8_t txbuf[32768]; rawtx = FinalizeCCTx(0, cp, tmpmtx, mypk, txfee, prices_finalopret(true, bettxid, mypk, betinfo.lastheight, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, myfee, nonce)); - //if ((len = (int32_t)rawtx.size()) > 0 && len < sizeof(txbuf) / sizeof(txbuf[0]) * 2) - //{ - // len >>= 1; // sizeof hex divide by 2 - //decode_hex(txbuf, len, (char *)rawtx.c_str()); - //bits256 hash = bits256_doublesha256(0, txbuf, len); - uint256 hash = tmpmtx.GetHash(); - //if ((hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0) - if ((hash.begin()[0] & 0xff) == 0 && (hash.begin()[31] & 0xff) == 0) - { - fprintf(stderr, "found valid txid after %d iterations %u\n", i, (uint32_t)time(NULL)); - return(prices_rawtxresult(result, rawtx, 0)); - } - //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); - //} + uint256 hash = tmpmtx.GetHash(); + if ((hash.begin()[0] & 0xff) == 0 && (hash.begin()[31] & 0xff) == 0) + { + fprintf(stderr, "found valid txid after %d iterations %u\n", i, (uint32_t)time(NULL)); + return(prices_rawtxresult(result, rawtx, 0)); + } } fprintf(stderr, "couldnt generate valid txid %u\n", (uint32_t)time(NULL)); diff --git a/src/cc/rogue/extern.h b/src/cc/rogue/extern.h index c62646b67ee..2c3905daae5 100644 --- a/src/cc/rogue/extern.h +++ b/src/cc/rogue/extern.h @@ -194,7 +194,5 @@ void md_onsignal_exit(void); void md_onsignal_default(void); int md_issymlink(char *sp); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); - #endif diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c index 093b73d703d..c3adbedd8ba 100644 --- a/src/cc/rogue/main.c +++ b/src/cc/rogue/main.c @@ -23,6 +23,8 @@ #include #include +#include "bits256.h" + char USERPASS[8192]; uint16_t ROGUE_PORT; extern char Gametxidstr[67]; @@ -32,12 +34,6 @@ extern char Gametxidstr[67]; #define KOMODO_ASSETCHAIN_MAXLEN 65 char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],IPADDRESS[100]; -#ifndef _BITS256 -#define _BITS256 -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; -#endif - #ifdef _WIN32 #ifdef _MSC_VER int gettimeofday(struct timeval * tp, struct timezone * tzp) @@ -76,112 +72,6 @@ double OS_milliseconds() return(millis); } -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; @@ -229,7 +119,7 @@ char *parse_conf_line(char *line,char *field) return(clonestr(line)); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) @@ -254,9 +144,9 @@ int32_t safecopy(char *dest,char *src,long len) #define true 1 #define false 0 #ifdef STANDALONE -#include "../komodo/src/komodo_cJSON.c" +#include "../komodo/src/komodo_cJSON.h" #else -#include "../../komodo_cJSON.c" +#include "../../komodo_cJSON.h" #endif int32_t rogue_replay(uint64_t seed,int32_t sleeptime); @@ -301,7 +191,7 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } -uint8_t *OS_fileptr(long *allocsizep,char *fname) +uint8_t *OS_fileptr(long *allocsizep,const char *fname) { long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; diff --git a/src/cc/rogue/rogue.h b/src/cc/rogue/rogue.h index 65ddf1e514a..960316219c9 100644 --- a/src/cc/rogue/rogue.h +++ b/src/cc/rogue/rogue.h @@ -47,6 +47,7 @@ #include "extern.h" +#include "bits256.h" #undef lines @@ -351,12 +352,6 @@ #define SATOSHIDEN ((uint64_t)100000000L) #define dstr(x) ((double)(x) / SATOSHIDEN) -#ifndef _BITS256 -#define _BITS256 -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; -#endif - #include "rogue_player.h" // interface to rpc struct rogue_state diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 679a6913a42..264bd512dbb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -182,8 +182,17 @@ class CMainParams : public CChainParams { assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) + + vSeeds.push_back(CDNSSeedData("komodoseeds.org", "kmd.komodoseeds.org")); // decker + vSeeds.push_back(CDNSSeedData("kmd.sh", "seeds1.kmd.sh")); // decker + vSeeds.push_back(CDNSSeedData("cipig.net", "kmdseed.cipig.net")); // cipig + vSeeds.push_back(CDNSSeedData("lordofthechains.com", "kmdseeds.lordofthechains.com")); // gcharang + + /* + vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); + vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); + */ + // TODO: we need more seed crawlers from other community members base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); @@ -571,7 +580,7 @@ void *chainparams_commandline() pCurrentParams->SetNValue(ASSETCHAINS_NK[0]); pCurrentParams->SetKValue(ASSETCHAINS_NK[1]); } - if ( KOMODO_TESTNODE != 0 ) + if ( IS_KOMODO_TESTNODE ) pCurrentParams->SetMiningRequiresPeers(false); if ( ASSETCHAINS_RPCPORT == 0 ) ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index e3dac3ca641..f518769fb2d 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -23,12 +23,10 @@ * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0x3c,0x8e}, 7770}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xdd,0x3d}, 7770}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xde,0x65,0xf7}, 7770}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xc3,0x64,0x20}, 7770} }; static SeedSpec6 pnSeed6_test[] = { diff --git a/src/clientversion.h b/src/clientversion.h index 4acff1b93ab..475da424d25 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -32,7 +32,7 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 7 -#define CLIENT_VERSION_REVISION 0 +#define CLIENT_VERSION_REVISION 1 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 0a081c0868a..4b1cae233f3 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -19,6 +19,7 @@ #include "main.h" #include "notarisationdb.h" #include "merkleblock.h" +#include "hex.h" #include "cc/CCinclude.h" diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 29a4d18ddb1..f11dd5a4b35 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -167,7 +167,7 @@ static Fulfillment_t *thresholdToFulfillment(const CC *cond) { for (int i=0; isize; i++) { sub = subconditions[i]; - if (needed && (fulfillment = asnFulfillmentNew(sub))) { + if (needed && (fulfillment = asnFulfillmentNew(sub)) != NULL) { asn_set_add(&tf->subfulfillments, fulfillment); needed--; } else { diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index b4d961d6e2c..fed35be4368 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -19,7 +19,6 @@ #include #include -#include #include "../include/cryptoconditions.h" #include "include/sha256.h" #include "asn/asn_application.h" @@ -216,7 +215,7 @@ void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t * ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); - return 0; + return; } sha256(buf, rc.encoded, out); } diff --git a/src/fiat/axo b/src/fiat/axo deleted file mode 100755 index 18d38cac070..00000000000 --- a/src/fiat/axo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/btch b/src/fiat/btch deleted file mode 100755 index 6a57ea8d1f7..00000000000 --- a/src/fiat/btch +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/coquicash b/src/fiat/coquicash deleted file mode 100755 index c882b223923..00000000000 --- a/src/fiat/coquicash +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=COQUICASH $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/oot b/src/fiat/oot deleted file mode 100755 index 4c7c6b68345..00000000000 --- a/src/fiat/oot +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 diff --git a/src/hex.c b/src/hex.c new file mode 100644 index 00000000000..5e8c68b7c04 --- /dev/null +++ b/src/hex.c @@ -0,0 +1,140 @@ +#include +#include "hex.h" + +/*** + * turn a char into its hex value + * A '5' becomes a 5, 'B' (or 'b') becomes 11. + * @param c the input + * @returns the value + */ +int32_t unhex(char c) +{ + if ( c >= '0' && c <= '9' ) + return(c - '0'); + else if ( c >= 'a' && c <= 'f' ) + return(c - 'a' + 10); + else if ( c >= 'A' && c <= 'F' ) + return(c - 'A' + 10); + return(-1); +} + +/*** + * Check n characters of a string to see if it can be + * interpreted as a hex string + * @param str the input + * @param n the size of input to check, 0 to check until null terminator found + * @returns 0 on error, othewise a positive number + */ +int32_t is_hexstr(const char *str,int32_t n) +{ + int32_t i; + if ( str == 0 || str[0] == 0 ) + return(0); + for (i=0; str[i]!=0; i++) + { + if ( n > 0 && i >= n ) + break; + if ( unhex(str[i]) < 0 ) + break; + } + if ( n == 0 ) + return(i); + return(i == n); +} + +/*** + * Decode a 2 character hex string into its value + * @param hex the string (i.e. 'ff') + * @returns the value (i.e. 255) + */ +unsigned char _decode_hex(const char *hex) +{ + return (unhex(hex[0])<<4) | unhex(hex[1]); +} + +/*** + * Turn a hex string into bytes + * NOTE: If there is 1 extra character in a null-terminated str, treat the first char as a full byte + * + * @param bytes where to store the output (will be cleared if hex has invalid chars) + * @param n number of bytes to process + * @param hex the input (will ignore CR/LF) + * @returns the number of bytes processed + */ +int32_t decode_hex(uint8_t *bytes, int32_t n,const char *str) +{ + uint8_t extra = 0; + // check validity of input + if ( is_hexstr(str,n) <= 0 ) + { + memset(bytes,0,n); // give no results + return 0; + } + if (str[n*2+1] == 0 && str[n*2] != 0) + { + // special case: odd number of char, then null terminator + // treat first char as a whole byte + bytes[0] = unhex(str[0]); + extra = 1; + bytes++; + str++; + } + if ( n > 0 ) + { + for (int i=0; i>4) & 0xf); + hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); + } + hexbytes[len*2] = 0; + return((int32_t)len*2+1); +} + +/*** + * Convert a bits256 into a hex character string + * @param hexstr the results + * @param x the input + * @returns a pointer to hexstr + */ +char *bits256_str(char hexstr[65],bits256 x) +{ + init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); + return(hexstr); +} diff --git a/src/hex.h b/src/hex.h new file mode 100644 index 00000000000..1361c8bc0f2 --- /dev/null +++ b/src/hex.h @@ -0,0 +1,65 @@ +/*** + * Routines for char to hex conversions + */ +#pragma once +#include +#include "bits256.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*** + * turn a char into its hex value + * A '5' becomes a 5, 'B' (or 'b') becomes 11. + * @param c the input + * @returns the value + */ +int32_t unhex(char c); + +/*** + * Check n characters of a string to see if it can be + * interpreted as a hex string + * @param str the input + * @param n the size of input to check, 0 to check until null terminator found + * @returns 0 on error, othewise a positive number + */ +int32_t is_hexstr(const char *str,int32_t n); + +/*** + * Decode a 2 character hex string into its value + * @param hex the string (i.e. 'ff') + * @returns the value (i.e. 255) + */ +unsigned char _decode_hex(const char *hex) ; + +/*** + * Turn a hex string into bytes + * @param bytes where to store the output + * @param n number of bytes to process + * @param hex the input (will ignore CR/LF) + * @returns the number of bytes processed (not an indicator of success) + */ +int32_t decode_hex(uint8_t *bytes, int32_t n,const char *in); + +/**** + * Convert a binary array of bytes into a hex string + * @param hexbytes the result + * @param message the array of bytes + * @param len the length of message + * @returns the length of hexbytes (including null terminator) + */ +int32_t init_hexbytes_noT(char *hexbytes, unsigned char *message, long len); + +/*** + * Convert a bits256 into a hex character string + * @param hexstr the results + * @param x the input + * @returns a pointer to hexstr + */ +char *bits256_str(char hexstr[65], bits256 x); + +#ifdef __cplusplus +} +#endif diff --git a/src/init.cpp b/src/init.cpp index 92219f852cb..c601cdf5da0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -35,6 +35,7 @@ #include "httprpc.h" #include "key.h" #include "notarisationdb.h" +#include "komodo_notary.h" #ifdef ENABLE_MINING #include "key_io.h" @@ -100,8 +101,6 @@ extern bool VERUS_MINTBLOCKS; extern char ASSETCHAINS_SYMBOL[]; extern int32_t KOMODO_SNAPSHOT_INTERVAL; -extern void komodo_init(int32_t height); - ZCJoinSplit* pzcashParams = NULL; #ifdef ENABLE_WALLET diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index f2d0d1ac542..509a53abe30 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -42,7 +42,6 @@ using namespace std; #include "uint256.h" #include "arith_uint256.h" #include "komodo_structs.h" -#include "komodo_globals.h" #include "komodo_defs.h" #include "komodo_interest.h" diff --git a/src/komodo.cpp b/src/komodo.cpp new file mode 100644 index 00000000000..4791544d5fa --- /dev/null +++ b/src/komodo.cpp @@ -0,0 +1,815 @@ +/****************************************************************************** + * 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 "komodo.h" +#include "komodo_extern_globals.h" +#include "komodo_notary.h" +#include "mem_read.h" + +void komodo_currentheight_set(int32_t height) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + sp->CURRENT_HEIGHT = height; +} + +extern NSPV_inforesp NSPV_inforesult; + +int32_t komodo_currentheight() +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( KOMODO_NSPV_SUPERLITE ) + { + return (NSPV_inforesult.height); + } + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + return(sp->CURRENT_HEIGHT); + else return(0); +} + +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) +{ + int32_t func; + + try + { + if ( (func= fgetc(fp)) != EOF ) + { + bool matched = false; + if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + matched = true; + else + matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + + int32_t ht; + if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) + throw komodo::parse_error("Unable to read height from file"); + if ( func == 'P' ) + { + std::shared_ptr pk = std::make_shared(fp, ht); + if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) + { + komodo_eventadd_pubkeys(sp, symbol, ht, pk); + } + } + else if ( func == 'N' || func == 'M' ) + { + std::shared_ptr evt = std::make_shared(fp, ht, func == 'M'); + komodo_eventadd_notarized(sp, symbol, ht, evt); + } + else if ( func == 'U' ) // deprecated + { + std::shared_ptr evt = std::make_shared(fp, ht); + } + else if ( func == 'K' || func == 'T') + { + std::shared_ptr evt = std::make_shared(fp, ht, func == 'T'); + komodo_eventadd_kmdheight(sp, symbol, ht, evt); + } + else if ( func == 'R' ) + { + std::shared_ptr evt = std::make_shared(fp, ht); + // check for oversized opret + if ( evt->opret.size() < 16384*4 ) + komodo_eventadd_opreturn(sp, symbol, ht, evt); + } + else if ( func == 'D' ) + { + printf("unexpected function D[%d]\n",ht); + } + else if ( func == 'V' ) + { + std::shared_ptr evt = std::make_shared(fp, ht); + komodo_eventadd_pricefeed(sp, symbol, ht, evt); + } + } // retrieved the func + } + catch(const komodo::parse_error& pe) + { + LogPrintf("Error occurred in parsestatefile: %s\n", pe.what()); + func = -1; + } + return func; +} + +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) +{ + int32_t func = -1; + + try + { + long fpos = *fposp; + if ( fpos < datalen ) + { + func = filedata[fpos++]; + + bool matched = false; + if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + matched = true; + else + matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + + int32_t ht; + if ( mem_read(ht, filedata, fpos, datalen) != sizeof(ht) ) + throw komodo::parse_error("Unable to parse height from file data"); + if ( func == 'P' ) + { + std::shared_ptr pk = std::make_shared(filedata, fpos, datalen, ht); + if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) + { + komodo_eventadd_pubkeys(sp, symbol, ht, pk); + } + } + else if ( func == 'N' || func == 'M' ) + { + std::shared_ptr ntz = + std::make_shared(filedata, fpos, datalen, ht, func == 'M'); + komodo_eventadd_notarized(sp, symbol, ht, ntz); + } + else if ( func == 'U' ) // deprecated + { + std::shared_ptr u = + std::make_shared(filedata, fpos, datalen, ht); + } + else if ( func == 'K' || func == 'T' ) + { + std::shared_ptr kmd_ht = + std::make_shared(filedata, fpos, datalen, ht, func == 'T'); + komodo_eventadd_kmdheight(sp, symbol, ht, kmd_ht); + } + else if ( func == 'R' ) + { + std::shared_ptr opret = + std::make_shared(filedata, fpos, datalen, ht); + komodo_eventadd_opreturn(sp, symbol, ht, opret); + } + else if ( func == 'D' ) + { + printf("unexpected function D[%d]\n",ht); + } + else if ( func == 'V' ) + { + std::shared_ptr pf = + std::make_shared(filedata, fpos, datalen, ht); + komodo_eventadd_pricefeed(sp, symbol, ht, pf); + } + *fposp = fpos; + } + } + catch( const komodo::parse_error& pe) + { + LogPrintf("Unable to parse state file data. Error: %s\n", pe.what()); + func = -1; + } + return func; +} + +/*** + * @brief persist event to file stream + * @param evt the event + * @param fp the file + * @returns the number of bytes written + */ +size_t write_event(std::shared_ptr evt, FILE *fp) +{ + std::stringstream ss; + ss << evt; + std::string buf = ss.str(); + return fwrite(buf.c_str(), buf.size(), 1, fp); +} + +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries, + uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals, + uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue, + uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) +{ + static FILE *fp; + static int32_t errs,didinit; + static uint256 zero; + struct komodo_state *sp; + char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + int32_t retval,ht,func; + uint8_t num,pubkeys[64][33]; + + if ( didinit == 0 ) + { + portable_mutex_init(&KOMODO_KV_mutex); + portable_mutex_init(&KOMODO_CC_mutex); + didinit = 1; + } + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + { + KOMODO_INITDONE = (uint32_t)time(NULL); + printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); + return; + } + if ( fp == 0 ) + { + komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); + if ( (fp= fopen(fname,"rb+")) != 0 ) + { + if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) + fseek(fp,0,SEEK_END); + else + { + fprintf(stderr,"komodo_faststateinit retval.%d\n",retval); + while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 ) + ; + } + } else fp = fopen(fname,"wb+"); + KOMODO_INITDONE = (uint32_t)time(NULL); + } + if ( height <= 0 ) + { + return; + } + if ( fp != 0 ) // write out funcid, height, other fields, call side effect function + { + if ( KMDheight != 0 ) + { + std::shared_ptr kmd_ht = std::make_shared(height); + kmd_ht->kheight = KMDheight; + kmd_ht->timestamp = KMDtimestamp; + write_event(kmd_ht, fp); + komodo_eventadd_kmdheight(sp,symbol,height,kmd_ht); + } + else if ( opretbuf != 0 && opretlen > 0 ) + { + std::shared_ptr evt = std::make_shared(height); + evt->txid = txhash; + evt->vout = vout; + evt->value = opretvalue; + for(uint16_t i = 0; i < opretlen; ++i) + evt->opret.push_back(opretbuf[i]); + write_event(evt, fp); + komodo_eventadd_opreturn(sp,symbol,height,evt); + } + else if ( notarypubs != 0 && numnotaries > 0 ) + { + std::shared_ptr pk = std::make_shared(height); + pk->num = numnotaries; + memcpy(pk->pubkeys, notarypubs, 33 * 64); + write_event(pk, fp); + komodo_eventadd_pubkeys(sp,symbol,height,pk); + } + else if ( voutmask != 0 && numvouts > 0 ) + { + std::shared_ptr evt = std::make_shared(height); + evt->n = numvouts; + evt->nid = notaryid; + memcpy(evt->mask, &voutmask, sizeof(voutmask)); + memcpy(evt->hash, &txhash, sizeof(txhash)); + write_event(evt, fp); + } + else if ( pvals != 0 && numpvals > 0 ) + { + int32_t i,nonz = 0; + for (i=0; i<32; i++) + if ( pvals[i] != 0 ) + nonz++; + if ( nonz >= 32 ) + { + std::shared_ptr evt = std::make_shared(height); + evt->num = numpvals; + for( uint8_t i = 0; i < evt->num; ++i) + evt->prices[i] = pvals[i]; + write_event(evt, fp); + komodo_eventadd_pricefeed(sp,symbol,height,evt); + } + } + else if ( height != 0 ) + { + if ( sp != 0 ) + { + std::shared_ptr evt = std::make_shared(height); + memcpy(evt->dest, dest, sizeof(evt->dest)-1); + evt->blockhash = sp->NOTARIZED_HASH; + evt->desttxid = sp->NOTARIZED_DESTTXID; + evt->notarizedheight = sp->NOTARIZED_HEIGHT; + evt->MoM = sp->MoM; + evt->MoMdepth = sp->MoMdepth; + write_event(evt, fp); + komodo_eventadd_notarized(sp,symbol,height,evt); + } + } + fflush(fp); + } +} + +int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) +{ + static int32_t last_rewind; int32_t rewindtarget; CBlockIndex *pindex; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + return(0); + if ( IsInitialBlockDownload() == 0 && ((pindex= komodo_getblockindex(srchash)) == 0 || pindex->GetHeight() != notarized_height) ) + { + if ( sp->NOTARIZED_HEIGHT > 0 && sp->NOTARIZED_HEIGHT < notarized_height ) + rewindtarget = sp->NOTARIZED_HEIGHT - 1; + else if ( notarized_height > 101 ) + rewindtarget = notarized_height - 101; + else rewindtarget = 0; + if ( rewindtarget != 0 && rewindtarget > KOMODO_REWIND && rewindtarget > last_rewind ) + { + if ( last_rewind != 0 ) + { + //KOMODO_REWIND = rewindtarget; + fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,notarized_height,srchash.ToString().c_str(),sp->NOTARIZED_HEIGHT,rewindtarget); + } + last_rewind = rewindtarget; + } + return(0); + } else return(1); +} + +int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf, + int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp, + int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized, + uint64_t signedmask,uint32_t timestamp) +{ + static uint256 zero; static FILE *signedfp; + int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + return(-1); + if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) + { + if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY ) + { + printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); + prevKOMODO_LASTMINED = KOMODO_LASTMINED; + KOMODO_LASTMINED = height; + } + decode_hex(crypto777,33,CRYPTO777_PUBSECPSTR); + /*for (k=0; k<33; k++) + printf("%02x",crypto777[k]); + printf(" crypto777 "); + for (k=0; k>>>>>>> "); + } + else if ( komodo_chosennotary(&nid,height,scriptbuf + 1,timestamp) >= 0 ) + { + //printf("found notary.k%d\n",k); + if ( notaryid < 64 ) + { + if ( notaryid < 0 ) + { + notaryid = nid; + *voutmaskp |= (1LL << j); + } + else if ( notaryid != nid ) + { + //for (i=0; i<33; i++) + // printf("%02x",scriptbuf[i+1]); + //printf(" %s mismatch notaryid.%d k.%d\n",ASSETCHAINS_SYMBOL,notaryid,nid); + notaryid = 64; + *voutmaskp = 0; + } + else *voutmaskp |= (1LL << j); + } + } + } + if ( scriptbuf[len++] == 0x6a ) + { + struct komodo_ccdata ccdata; struct komodo_ccdataMoMoM MoMoMdata; + int32_t validated = 0,nameoffset,opoffset = 0; + if ( (opretlen= scriptbuf[len++]) == 0x4c ) + opretlen = scriptbuf[len++]; + else if ( opretlen == 0x4d ) + { + opretlen = scriptbuf[len++]; + opretlen += (scriptbuf[len++] << 8); + } + opoffset = len; + matched = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( strcmp("KMD",(char *)&scriptbuf[len+32 * 2 + 4]) == 0 ) + matched = 1; + } + else + { + if ( scriptbuf[len] == 'K' ) + { + //fprintf(stderr,"i.%d j.%d KV OPRET len.%d %.8f\n",i,j,opretlen,dstr(value)); + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + return(-1); + } + if ( strcmp(ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + matched = 1; + } + offset = 32 * (1 + matched) + 4; + nameoffset = (int32_t)strlen((char *)&scriptbuf[len+offset]); + nameoffset++; + memset(&ccdata,0,sizeof(ccdata)); + strncpy(ccdata.symbol,(char *)&scriptbuf[len+offset],sizeof(ccdata.symbol)); + if ( j == 1 && opretlen >= len+offset-opoffset ) + { + memset(&MoMoMdata,0,sizeof(MoMoMdata)); + if ( matched == 0 && signedmask != 0 && bitweight(signedmask) >= KOMODO_MINRATIFY ) + notarized = 1; + if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 || strcmp("BEER",ccdata.symbol) == 0) + notarized = 1; + if ( 0 && opretlen != 149 ) + printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); + if ( matched != 0 ) + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); + if ( matched != 0 ) + validated = komodo_validate_chain(srchash,*notarizedheightp); + else validated = 1; + // Any notarization that is matched and has a decodable op_return is enough to pay notaries. Otherwise bugs! + if ( fJustCheck && matched != 0 ) + return(-2); + if ( notarized != 0 && validated != 0 ) + { + //sp->NOTARIZED_HEIGHT = *notarizedheightp; + //sp->NOTARIZED_HASH = srchash; + //sp->NOTARIZED_DESTTXID = desttxid; + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + len += nameoffset; + ccdata.MoMdata.notarized_height = *notarizedheightp; + ccdata.MoMdata.height = height; + ccdata.MoMdata.txi = i; + //printf("nameoffset.%d len.%d + 36 %d opoffset.%d vs opretlen.%d\n",nameoffset,len,len+36,opoffset,opretlen); + if ( len+36-opoffset <= opretlen ) + { + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); + ccdata.MoMdata.MoM = MoM; + ccdata.MoMdata.MoMdepth = MoMdepth & 0xffff; + if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) + { + len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); + //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) + // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); + ccdata.len = sizeof(ccdata.CCid); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) + if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) + { + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); + len += iguana_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); + MoMoMdata.len += sizeof(MoMoMdata.MoMoM) + sizeof(uint32_t)*4; + if ( len+MoMoMdata.numpairs*8-opoffset == opretlen ) + { + MoMoMdata.pairs = (struct komodo_ccdatapair *)calloc(MoMoMdata.numpairs,sizeof(*MoMoMdata.pairs)); + for (k=0; k *notarizedheightp || (MoMdepth&0xffff) < 0 ) + { + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + } + else + { + komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata); + if ( matched != 0 ) + printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); + } + if ( MoMoMdata.pairs != 0 ) + free(MoMoMdata.pairs); + memset(&ccdata,0,sizeof(ccdata)); + memset(&MoMoMdata,0,sizeof(MoMoMdata)); + } + else if ( ASSETCHAINS_SYMBOL[0] == 0 && matched != 0 && notarized != 0 && validated != 0 ) + komodo_rwccdata((char *)"KMD",1,&ccdata,0); + + if ( matched != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height ) + { + sp->NOTARIZED_HEIGHT = *notarizedheightp; + sp->NOTARIZED_HASH = srchash; + sp->NOTARIZED_DESTTXID = desttxid; + if ( MoM != zero && (MoMdepth&0xffff) > 0 ) + { + sp->MoM = MoM; + 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 ) + 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 ) + { + char fname[512]; + komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); + if ( (signedfp= fopen(fname,"rb+")) == 0 ) + signedfp = fopen(fname,"wb"); + else fseek(signedfp,0,SEEK_END); + } + if ( signedfp != 0 ) + { + fwrite(&height,1,sizeof(height),signedfp); + fwrite(&signedmask,1,sizeof(signedmask),signedfp); + fflush(signedfp); + } + if ( opretlen > len && scriptbuf[len] == 'A' ) + { + //for (i=0; i 600000 && matched != 0 ) + printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); + } + else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 ) + { + if ( notaryid >= 0 && notaryid < 64 ) + komodo_paxpricefeed(height,&scriptbuf[len],opretlen); + } + else if ( matched != 0 ) + { + //int32_t k; for (k=0; k= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + { + for (k=0; k<32; k++) + if ( scriptbuf[len+k] != 0 ) + break; + if ( k == 32 ) + { + *isratificationp = 1; + printf("ISRATIFICATION (%s)\n",(char *)&scriptbuf[len+32*2+4]); + } + } + + if ( *isratificationp == 0 && (signedmask != 0 || (scriptbuf[len] != 'X' && scriptbuf[len] != 'A')) ) // && scriptbuf[len] != 'I') + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + } + } + return(notaryid); +} + +// Special tx have vout[0] -> CRYPTO777 +// with more than KOMODO_MINRATIFY pay2pubkey outputs -> ratify +// if all outputs to notary -> notary utxo +// if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed +// OP_RETURN: 'D' -> deposit, 'W' -> withdraw + +int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); + +int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) +{ + int32_t i; + if ( scriptlen == 25 && memcmp(&scriptPubKey[3],rmd160,20) == 0 ) + return(0); + else if ( scriptlen == 35 ) + { + for (i=0; i notarisations; + uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; + int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; + if ( pindex == 0 ) + { + fprintf(stderr,"komodo_connectblock null pindex\n"); + return(0); + } + memset(&zero,0,sizeof(zero)); + komodo_init(pindex->GetHeight()); + KOMODO_INITDONE = (uint32_t)time(NULL); + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + { + fprintf(stderr,"unexpected null komodostateptr.[%s]\n",ASSETCHAINS_SYMBOL); + return(0); + } + //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); + // Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes. + if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || STAKED_NOTARY_ID > -1 ) + { + staked_era = STAKED_era(pindex->GetBlockTime()); + if ( !fJustCheck && staked_era != lastStakedEra ) + { + uint8_t tmp_pubkeys[64][33]; + int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era); + UpdateNotaryAddrs(tmp_pubkeys,numSN); + STAKED_ERA = staked_era; + lastStakedEra = staked_era; + } + } + numnotaries = komodo_notaries(pubkeys,pindex->GetHeight(),pindex->GetBlockTime()); + calc_rmd160_sha256(rmd160,pubkeys[0],33); + if ( pindex->GetHeight() > hwmheight ) + hwmheight = pindex->GetHeight(); + else + { + if ( pindex->GetHeight() != hwmheight ) + { + printf("%s hwmheight.%d vs pindex->GetHeight().%d t.%u reorg.%d\n",ASSETCHAINS_SYMBOL,hwmheight,pindex->GetHeight(),(uint32_t)pindex->nTime,hwmheight-pindex->GetHeight()); + komodo_purge_ccdata((int32_t)pindex->GetHeight()); + hwmheight = pindex->GetHeight(); + } + if (!fJustCheck) + { + komodo_event_rewind(sp,symbol,pindex->GetHeight()); + komodo_stateupdate(pindex->GetHeight(),0,0,0,zero,0,0,0,0,-pindex->GetHeight(),pindex->nTime,0,0,0,0,zero,0); + } + } + komodo_currentheight_set(chainActive.LastTip()->GetHeight()); + int transaction = 0; + if ( pindex != 0 ) + { + height = pindex->GetHeight(); + txn_count = block.vtx.size(); + for (i=0; i 1 && ASSETCHAINS_NOTARY_PAY[0] != 0 ) + break; + txhash = block.vtx[i].GetHash(); + numvouts = block.vtx[i].vout.size(); + notaryid = -1; + voutmask = specialtx = notarizedheight = isratification = notarized = 0; + signedmask = (height < 91400) ? 1 : 0; + numvins = block.vtx[i].vin.size(); + for (j=0; j 0 ) + { + if ( (k= komodo_notarycmp(scriptPubKey,scriptlen,pubkeys,numnotaries,rmd160)) >= 0 ) + signedmask |= (1LL << k); + else if ( 0 && numvins >= 17 ) + { + int32_t k; + for (k=0; k= KOMODO_MINRATIFY) || + (numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) || + numvalid > (numnotaries/5) ) + { + if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0) + { + static FILE *signedfp; + if ( signedfp == 0 ) + { + char fname[512]; + komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); + if ( (signedfp= fopen(fname,"rb+")) == 0 ) + signedfp = fopen(fname,"wb"); + else fseek(signedfp,0,SEEK_END); + } + if ( signedfp != 0 ) + { + fwrite(&height,1,sizeof(height),signedfp); + fwrite(&signedmask,1,sizeof(signedmask),signedfp); + 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); + } + notarized = 1; + } + // simulate DPoW in regtest mode for dpowconfs tests/etc + if ( Params().NetworkIDString() == "regtest" && ( height%7 == 0) ) { + notarized = 1; + sp->NOTARIZED_HEIGHT = height; + sp->NOTARIZED_HASH = block.GetHash(); + sp->NOTARIZED_DESTTXID = txhash; + } + for (j=0; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) + { + memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); + notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); + if ( fJustCheck && notaryid == -2 ) + { + // We see a valid notarisation here, save its location. + notarisations.push_back(i); + } + if ( 0 && i > 0 ) + { + for (k=0; k 2 ) + { + numvalid = 0; + memset(pubkeys,0,sizeof(pubkeys)); + for (j=1; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) + { + memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); + if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) + { + memcpy(pubkeys[numvalid++],scriptbuf+1,33); + for (k=0; k<33; k++) + printf("%02x",scriptbuf[k+1]); + printf(" <- new notary.[%d]\n",j-1); + } + } + } + if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 ) + { + if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) + { + memset(&txhash,0,sizeof(txhash)); + komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); + printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); + } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); + } + } + } + } + if ( !fJustCheck && IS_KOMODO_NOTARY && ASSETCHAINS_SYMBOL[0] == 0 ) + 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"); return(0); } + //KOMODO_INITDONE = (uint32_t)time(NULL); + //fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight()); + if (fJustCheck) + { + if ( notarisations.size() == 0 ) + return(0); + if ( notarisations.size() == 1 && notarisations[0] == 1 ) + 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); +} diff --git a/src/komodo.h b/src/komodo.h index 88e741df7f7..bdf0913933f 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -12,30 +12,23 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once +#include +#include +#include +#include -#ifndef H_KOMODO_H -#define H_KOMODO_H -#include "komodo_defs.h" -#include "notaries_staked.h" - -#ifdef _WIN32 -#define printf(...) -#endif +#include "uint256.h" // Todo: // verify: reorgs #define KOMODO_ASSETCHAINS_WAITNOTARIZE #define KOMODO_PAXMAX (10000 * COIN) -extern int32_t NOTARIZED_HEIGHT; -uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; -#include -#include -#include -#include #include "uthash.h" #include "utlist.h" +#include "chain.h" int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); @@ -43,11 +36,10 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); bool check_pprevnotarizedht(); #include "komodo_structs.h" -#include "komodo_globals.h" #include "komodo_utils.h" #include "komodo_curve25519.h" -#include "komodo_cJSON.c" +#include "komodo_cJSON.h" #include "komodo_bitcoind.h" #include "komodo_interest.h" #include "komodo_pax.h" @@ -60,731 +52,22 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char #include "komodo_events.h" #include "komodo_ccdata.h" -void komodo_currentheight_set(int32_t height) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - sp->CURRENT_HEIGHT = height; -} - -extern struct NSPV_inforesp NSPV_inforesult; -int32_t komodo_currentheight() -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( KOMODO_NSPV_SUPERLITE ) - { - return (NSPV_inforesult.height); - } - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - return(sp->CURRENT_HEIGHT); - else return(0); -} - -int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) -{ - static int32_t errs; - int32_t func,ht,notarized_height,num,matched=0,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; - if ( (func= fgetc(fp)) != EOF ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - matched = 1; - else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && func != 'T' ) - printf("[%s] matched.%d fpos.%ld func.(%d %c) ht.%d\n",ASSETCHAINS_SYMBOL,matched,ftell(fp),func,func,ht); - if ( func == 'P' ) - { - if ( (num= fgetc(fp)) <= 64 ) - { - if ( fread(pubkeys,33,num,fp) != num ) - errs++; - else - { - //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); - } - } else printf("illegal num.%d\n",num); - } - else if ( func == 'N' || func == 'M' ) - { - if ( fread(¬arized_height,1,sizeof(notarized_height),fp) != sizeof(notarized_height) ) - errs++; - if ( fread(¬arized_hash,1,sizeof(notarized_hash),fp) != sizeof(notarized_hash) ) - errs++; - if ( fread(¬arized_desttxid,1,sizeof(notarized_desttxid),fp) != sizeof(notarized_desttxid) ) - errs++; - if ( func == 'M' ) - { - if ( fread(&MoM,1,sizeof(MoM),fp) != sizeof(MoM) ) - errs++; - if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); - } - else - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - //if ( matched != 0 ) global independent states -> inside *sp - komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); - } - else if ( func == 'U' ) // deprecated - { - uint8_t n,nid; uint256 hash; uint64_t mask; - n = fgetc(fp); - nid = fgetc(fp); - //printf("U %d %d\n",n,nid); - if ( fread(&mask,1,sizeof(mask),fp) != sizeof(mask) ) - errs++; - if ( fread(&hash,1,sizeof(hash),fp) != sizeof(hash) ) - errs++; - //if ( matched != 0 ) - // komodo_eventadd_utxo(sp,symbol,ht,nid,hash,mask,n); - } - else if ( func == 'K' ) - { - int32_t kheight; - if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); - } - else if ( func == 'T' ) - { - int32_t kheight,ktimestamp; - if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) - errs++; - if ( fread(&ktimestamp,1,sizeof(ktimestamp),fp) != sizeof(ktimestamp) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); - } - else if ( func == 'R' ) - { - uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; - if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) - errs++; - if ( fread(&v,1,sizeof(v),fp) != sizeof(v) ) - errs++; - if ( fread(&ovalue,1,sizeof(ovalue),fp) != sizeof(ovalue) ) - errs++; - if ( fread(&olen,1,sizeof(olen),fp) != sizeof(olen) ) - errs++; - if ( olen < sizeof(opret) ) - { - if ( fread(opret,1,olen,fp) != olen ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) - { - int32_t i; for (i=0; i global PAX - } else - { - int32_t i; - for (i=0; i global PVALS - //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); - komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); - } else printf("error loading pvals[%d]\n",numpvals); - } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); - return(func); - } else return(-1); -} - -int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen) -{ - if ( *fposp+size <= datalen ) - { - memcpy(dest,&filedata[*fposp],size); - (*fposp) += size; - return(size); - } - return(-1); -} +void komodo_currentheight_set(int32_t height); -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) -{ - static int32_t errs; - int32_t func= -1,ht,notarized_height,MoMdepth,num,matched=0; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; long fpos = *fposp; - if ( fpos < datalen ) - { - func = filedata[fpos++]; - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - matched = 1; - else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) - errs++; - if ( func == 'P' ) - { - if ( (num= filedata[fpos++]) <= 64 ) - { - if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) - errs++; - else - { - //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); - } - } else printf("illegal num.%d\n",num); - } - else if ( func == 'N' || func == 'M' ) - { - if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) - errs++; - if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) - errs++; - if ( memread(¬arized_desttxid,sizeof(notarized_desttxid),filedata,&fpos,datalen) != sizeof(notarized_desttxid) ) - errs++; - if ( func == 'M' ) - { - if ( memread(&MoM,sizeof(MoM),filedata,&fpos,datalen) != sizeof(MoM) ) - errs++; - if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); - } - else - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); - } - else if ( func == 'U' ) // deprecated - { - uint8_t n,nid; uint256 hash; uint64_t mask; - n = filedata[fpos++]; - nid = filedata[fpos++]; - //printf("U %d %d\n",n,nid); - if ( memread(&mask,sizeof(mask),filedata,&fpos,datalen) != sizeof(mask) ) - errs++; - if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) - errs++; - } - else if ( func == 'K' ) - { - int32_t kheight; - if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) - errs++; - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); - } - else if ( func == 'T' ) - { - int32_t kheight,ktimestamp; - if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) - errs++; - if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); - } - else if ( func == 'R' ) - { - uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; - if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) - errs++; - if ( memread(&v,sizeof(v),filedata,&fpos,datalen) != sizeof(v) ) - errs++; - if ( memread(&ovalue,sizeof(ovalue),filedata,&fpos,datalen) != sizeof(ovalue) ) - errs++; - if ( memread(&olen,sizeof(olen),filedata,&fpos,datalen) != sizeof(olen) ) - errs++; - if ( olen < sizeof(opret) ) - { - if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) - { - int32_t i; for (i=0; i global PAX - } else - { - int32_t i; - for (i=0; i global PVALS - //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); - komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); - } else printf("error loading pvals[%d]\n",numpvals); - } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); - *fposp = fpos; - return(func); - } - return(-1); -} +int32_t komodo_currentheight(); -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) -{ - static FILE *fp; static int32_t errs,didinit; static uint256 zero; - struct komodo_state *sp; char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t retval,ht,func; uint8_t num,pubkeys[64][33]; - if ( didinit == 0 ) - { - portable_mutex_init(&KOMODO_KV_mutex); - portable_mutex_init(&KOMODO_CC_mutex); - didinit = 1; - } - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - { - KOMODO_INITDONE = (uint32_t)time(NULL); - printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); - return; - } - //printf("[%s] (%s) -> (%s)\n",ASSETCHAINS_SYMBOL,symbol,dest); - if ( fp == 0 ) - { - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); - if ( (fp= fopen(fname,"rb+")) != 0 ) - { - if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) - fseek(fp,0,SEEK_END); - else - { - fprintf(stderr,"komodo_faststateinit retval.%d\n",retval); - while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 ) - ; - } - } else fp = fopen(fname,"wb+"); - KOMODO_INITDONE = (uint32_t)time(NULL); - } - if ( height <= 0 ) - { - //printf("early return: stateupdate height.%d\n",height); - return; - } - if ( fp != 0 ) // write out funcid, height, other fields, call side effect function - { - //printf("fpos.%ld ",ftell(fp)); - if ( KMDheight != 0 ) - { - if ( KMDtimestamp != 0 ) - { - fputc('T',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) - errs++; - if ( fwrite(&KMDtimestamp,1,sizeof(KMDtimestamp),fp) != sizeof(KMDtimestamp) ) - errs++; - } - else - { - fputc('K',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) - errs++; - } - komodo_eventadd_kmdheight(sp,symbol,height,KMDheight,KMDtimestamp); - } - else if ( opretbuf != 0 && opretlen > 0 ) - { - uint16_t olen = opretlen; - fputc('R',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) - errs++; - if ( fwrite(&vout,1,sizeof(vout),fp) != sizeof(vout) ) - errs++; - if ( fwrite(&opretvalue,1,sizeof(opretvalue),fp) != sizeof(opretvalue) ) - errs++; - if ( fwrite(&olen,1,sizeof(olen),fp) != olen ) - errs++; - if ( fwrite(opretbuf,1,olen,fp) != olen ) - errs++; -//printf("create ht.%d R opret[%d] sp.%p\n",height,olen,sp); - //komodo_opreturn(height,opretvalue,opretbuf,olen,txhash,vout); - komodo_eventadd_opreturn(sp,symbol,height,txhash,opretvalue,vout,opretbuf,olen); - } - else if ( notarypubs != 0 && numnotaries > 0 ) - { - printf("ht.%d func P[%d] errs.%d\n",height,numnotaries,errs); - fputc('P',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numnotaries,fp); - if ( fwrite(notarypubs,33,numnotaries,fp) != numnotaries ) - errs++; - komodo_eventadd_pubkeys(sp,symbol,height,numnotaries,notarypubs); - } - else if ( voutmask != 0 && numvouts > 0 ) - { - //printf("ht.%d func U %d %d errs.%d hashsize.%ld\n",height,numvouts,notaryid,errs,sizeof(txhash)); - fputc('U',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numvouts,fp); - fputc(notaryid,fp); - if ( fwrite(&voutmask,1,sizeof(voutmask),fp) != sizeof(voutmask) ) - errs++; - if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) - errs++; - //komodo_eventadd_utxo(sp,symbol,height,notaryid,txhash,voutmask,numvouts); - } - else if ( pvals != 0 && numpvals > 0 ) - { - int32_t i,nonz = 0; - for (i=0; i<32; i++) - if ( pvals[i] != 0 ) - nonz++; - if ( nonz >= 32 ) - { - fputc('V',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numpvals,fp); - if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals ) - errs++; - komodo_eventadd_pricefeed(sp,symbol,height,pvals,numpvals); - //printf("ht.%d V numpvals[%d]\n",height,numpvals); - } - //printf("save pvals height.%d numpvals.%d\n",height,numpvals); - } - else if ( height != 0 ) - { - //printf("ht.%d func N ht.%d errs.%d\n",height,NOTARIZED_HEIGHT,errs); - if ( sp != 0 ) - { - if ( sp->MoMdepth != 0 && sp->MoM != zero ) - fputc('M',fp); - else fputc('N',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&sp->NOTARIZED_HEIGHT,1,sizeof(sp->NOTARIZED_HEIGHT),fp) != sizeof(sp->NOTARIZED_HEIGHT) ) - errs++; - if ( fwrite(&sp->NOTARIZED_HASH,1,sizeof(sp->NOTARIZED_HASH),fp) != sizeof(sp->NOTARIZED_HASH) ) - errs++; - if ( fwrite(&sp->NOTARIZED_DESTTXID,1,sizeof(sp->NOTARIZED_DESTTXID),fp) != sizeof(sp->NOTARIZED_DESTTXID) ) - errs++; - if ( sp->MoMdepth != 0 && sp->MoM != zero ) - { - if ( fwrite(&sp->MoM,1,sizeof(sp->MoM),fp) != sizeof(sp->MoM) ) - errs++; - if ( fwrite(&sp->MoMdepth,1,sizeof(sp->MoMdepth),fp) != sizeof(sp->MoMdepth) ) - errs++; - } - komodo_eventadd_notarized(sp,symbol,height,dest,sp->NOTARIZED_HASH,sp->NOTARIZED_DESTTXID,sp->NOTARIZED_HEIGHT,sp->MoM,sp->MoMdepth); - } - } - fflush(fp); - } -} +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); -int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) -{ - static int32_t last_rewind; int32_t rewindtarget; CBlockIndex *pindex; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - return(0); - if ( IsInitialBlockDownload() == 0 && ((pindex= komodo_getblockindex(srchash)) == 0 || pindex->GetHeight() != notarized_height) ) - { - if ( sp->NOTARIZED_HEIGHT > 0 && sp->NOTARIZED_HEIGHT < notarized_height ) - rewindtarget = sp->NOTARIZED_HEIGHT - 1; - else if ( notarized_height > 101 ) - rewindtarget = notarized_height - 101; - else rewindtarget = 0; - if ( rewindtarget != 0 && rewindtarget > KOMODO_REWIND && rewindtarget > last_rewind ) - { - if ( last_rewind != 0 ) - { - //KOMODO_REWIND = rewindtarget; - fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,notarized_height,srchash.ToString().c_str(),sp->NOTARIZED_HEIGHT,rewindtarget); - } - last_rewind = rewindtarget; - } - return(0); - } else return(1); -} +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); -int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp) -{ - static uint256 zero; static FILE *signedfp; - int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - return(-1); - if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) - { - if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY != 0 ) - { - printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); - prevKOMODO_LASTMINED = KOMODO_LASTMINED; - KOMODO_LASTMINED = height; - } - decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); - /*for (k=0; k<33; k++) - printf("%02x",crypto777[k]); - printf(" crypto777 "); - for (k=0; k>>>>>>> "); - } - else if ( komodo_chosennotary(&nid,height,scriptbuf + 1,timestamp) >= 0 ) - { - //printf("found notary.k%d\n",k); - if ( notaryid < 64 ) - { - if ( notaryid < 0 ) - { - notaryid = nid; - *voutmaskp |= (1LL << j); - } - else if ( notaryid != nid ) - { - //for (i=0; i<33; i++) - // printf("%02x",scriptbuf[i+1]); - //printf(" %s mismatch notaryid.%d k.%d\n",ASSETCHAINS_SYMBOL,notaryid,nid); - notaryid = 64; - *voutmaskp = 0; - } - else *voutmaskp |= (1LL << j); - } - } - } - if ( scriptbuf[len++] == 0x6a ) - { - struct komodo_ccdata ccdata; struct komodo_ccdataMoMoM MoMoMdata; - int32_t validated = 0,nameoffset,opoffset = 0; - if ( (opretlen= scriptbuf[len++]) == 0x4c ) - opretlen = scriptbuf[len++]; - else if ( opretlen == 0x4d ) - { - opretlen = scriptbuf[len++]; - opretlen += (scriptbuf[len++] << 8); - } - opoffset = len; - matched = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( strcmp("KMD",(char *)&scriptbuf[len+32 * 2 + 4]) == 0 ) - matched = 1; - } - else - { - if ( scriptbuf[len] == 'K' ) - { - //fprintf(stderr,"i.%d j.%d KV OPRET len.%d %.8f\n",i,j,opretlen,dstr(value)); - komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); - return(-1); - } - if ( strcmp(ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) - matched = 1; - } - offset = 32 * (1 + matched) + 4; - nameoffset = (int32_t)strlen((char *)&scriptbuf[len+offset]); - nameoffset++; - memset(&ccdata,0,sizeof(ccdata)); - strncpy(ccdata.symbol,(char *)&scriptbuf[len+offset],sizeof(ccdata.symbol)); - if ( j == 1 && opretlen >= len+offset-opoffset ) - { - memset(&MoMoMdata,0,sizeof(MoMoMdata)); - if ( matched == 0 && signedmask != 0 && bitweight(signedmask) >= KOMODO_MINRATIFY ) - notarized = 1; - if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 || strcmp("BEER",ccdata.symbol) == 0) - notarized = 1; - if ( 0 && opretlen != 149 ) - printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); - if ( matched != 0 ) - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); - if ( matched != 0 ) - validated = komodo_validate_chain(srchash,*notarizedheightp); - else validated = 1; - // Any notarization that is matched and has a decodable op_return is enough to pay notaries. Otherwise bugs! - if ( fJustCheck && matched != 0 ) - return(-2); - if ( notarized != 0 && validated != 0 ) - { - //sp->NOTARIZED_HEIGHT = *notarizedheightp; - //sp->NOTARIZED_HASH = srchash; - //sp->NOTARIZED_DESTTXID = desttxid; - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - len += nameoffset; - ccdata.MoMdata.notarized_height = *notarizedheightp; - ccdata.MoMdata.height = height; - ccdata.MoMdata.txi = i; - //printf("nameoffset.%d len.%d + 36 %d opoffset.%d vs opretlen.%d\n",nameoffset,len,len+36,opoffset,opretlen); - if ( len+36-opoffset <= opretlen ) - { - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); - ccdata.MoMdata.MoM = MoM; - ccdata.MoMdata.MoMdepth = MoMdepth & 0xffff; - if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) - { - len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); - //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) - // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); - ccdata.len = sizeof(ccdata.CCid); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) - if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) - { - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); - len += iguana_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); - MoMoMdata.len += sizeof(MoMoMdata.MoMoM) + sizeof(uint32_t)*4; - if ( len+MoMoMdata.numpairs*8-opoffset == opretlen ) - { - MoMoMdata.pairs = (struct komodo_ccdatapair *)calloc(MoMoMdata.numpairs,sizeof(*MoMoMdata.pairs)); - for (k=0; k *notarizedheightp || (MoMdepth&0xffff) < 0 ) - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - else - { - komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata); - if ( matched != 0 ) - printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); - } - if ( MoMoMdata.pairs != 0 ) - free(MoMoMdata.pairs); - memset(&ccdata,0,sizeof(ccdata)); - memset(&MoMoMdata,0,sizeof(MoMoMdata)); - } - else if ( ASSETCHAINS_SYMBOL[0] == 0 && matched != 0 && notarized != 0 && validated != 0 ) - komodo_rwccdata((char *)"KMD",1,&ccdata,0); - - if ( matched != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height ) - { - sp->NOTARIZED_HEIGHT = *notarizedheightp; - sp->NOTARIZED_HASH = srchash; - sp->NOTARIZED_DESTTXID = desttxid; - if ( MoM != zero && (MoMdepth&0xffff) > 0 ) - { - sp->MoM = MoM; - 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 ) - 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 ) - { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); - if ( (signedfp= fopen(fname,"rb+")) == 0 ) - signedfp = fopen(fname,"wb"); - else fseek(signedfp,0,SEEK_END); - } - if ( signedfp != 0 ) - { - fwrite(&height,1,sizeof(height),signedfp); - fwrite(&signedmask,1,sizeof(signedmask),signedfp); - fflush(signedfp); - } - if ( opretlen > len && scriptbuf[len] == 'A' ) - { - //for (i=0; i 600000 && matched != 0 ) - printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); - } - else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 ) - { - if ( notaryid >= 0 && notaryid < 64 ) - komodo_paxpricefeed(height,&scriptbuf[len],opretlen); - } - else if ( matched != 0 ) - { - //int32_t k; for (k=0; k= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) - { - for (k=0; k<32; k++) - if ( scriptbuf[len+k] != 0 ) - break; - if ( k == 32 ) - { - *isratificationp = 1; - printf("ISRATIFICATION (%s)\n",(char *)&scriptbuf[len+32*2+4]); - } - } +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); - if ( *isratificationp == 0 && (signedmask != 0 || (scriptbuf[len] != 'X' && scriptbuf[len] != 'A')) ) // && scriptbuf[len] != 'I') - komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); - } - } - return(notaryid); -} +int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid, + uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i, + int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp, + uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); -/*int32_t komodo_isratify(int32_t isspecial,int32_t numvalid) -{ - if ( isspecial != 0 && numvalid >= KOMODO_MINRATIFY ) - return(1); - else return(0); -}*/ +int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height); // Special tx have vout[0] -> CRYPTO777 // with more than KOMODO_MINRATIFY pay2pubkey outputs -> ratify @@ -794,255 +77,10 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); -int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) -{ - int32_t i; - if ( scriptlen == 25 && memcmp(&scriptPubKey[3],rmd160,20) == 0 ) - return(0); - else if ( scriptlen == 35 ) - { - for (i=0; i notarisations; - uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; - int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; - if ( pindex == 0 ) - { - fprintf(stderr,"komodo_connectblock null pindex\n"); - return(0); - } - memset(&zero,0,sizeof(zero)); - komodo_init(pindex->GetHeight()); - KOMODO_INITDONE = (uint32_t)time(NULL); - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - { - fprintf(stderr,"unexpected null komodostateptr.[%s]\n",ASSETCHAINS_SYMBOL); - return(0); - } - //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); - // Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes. - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || IS_STAKED_NOTARY > -1 ) - { - staked_era = STAKED_era(pindex->GetBlockTime()); - if ( !fJustCheck && staked_era != lastStakedEra ) - { - uint8_t tmp_pubkeys[64][33]; - int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era); - UpdateNotaryAddrs(tmp_pubkeys,numSN); - STAKED_ERA = staked_era; - lastStakedEra = staked_era; - } - } - numnotaries = komodo_notaries(pubkeys,pindex->GetHeight(),pindex->GetBlockTime()); - calc_rmd160_sha256(rmd160,pubkeys[0],33); - if ( pindex->GetHeight() > hwmheight ) - hwmheight = pindex->GetHeight(); - else - { - if ( pindex->GetHeight() != hwmheight ) - { - printf("%s hwmheight.%d vs pindex->GetHeight().%d t.%u reorg.%d\n",ASSETCHAINS_SYMBOL,hwmheight,pindex->GetHeight(),(uint32_t)pindex->nTime,hwmheight-pindex->GetHeight()); - komodo_purge_ccdata((int32_t)pindex->GetHeight()); - hwmheight = pindex->GetHeight(); - } - if (!fJustCheck) - { - komodo_event_rewind(sp,symbol,pindex->GetHeight()); - komodo_stateupdate(pindex->GetHeight(),0,0,0,zero,0,0,0,0,-pindex->GetHeight(),pindex->nTime,0,0,0,0,zero,0); - } - } - komodo_currentheight_set(chainActive.LastTip()->GetHeight()); - int transaction = 0; - if ( pindex != 0 ) - { - height = pindex->GetHeight(); - txn_count = block.vtx.size(); - for (i=0; i 1 && ASSETCHAINS_NOTARY_PAY[0] != 0 ) - break; - txhash = block.vtx[i].GetHash(); - numvouts = block.vtx[i].vout.size(); - notaryid = -1; - voutmask = specialtx = notarizedheight = isratification = notarized = 0; - signedmask = (height < 91400) ? 1 : 0; - numvins = block.vtx[i].vin.size(); - for (j=0; j 0 ) - { - if ( (k= komodo_notarycmp(scriptPubKey,scriptlen,pubkeys,numnotaries,rmd160)) >= 0 ) - signedmask |= (1LL << k); - else if ( 0 && numvins >= 17 ) - { - int32_t k; - for (k=0; k= KOMODO_MINRATIFY) || - (numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) || - numvalid > (numnotaries/5) ) - { - if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0) - { - static FILE *signedfp; - if ( signedfp == 0 ) - { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); - if ( (signedfp= fopen(fname,"rb+")) == 0 ) - signedfp = fopen(fname,"wb"); - else fseek(signedfp,0,SEEK_END); - } - if ( signedfp != 0 ) - { - fwrite(&height,1,sizeof(height),signedfp); - fwrite(&signedmask,1,sizeof(signedmask),signedfp); - 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); - } - notarized = 1; - } - // simulate DPoW in regtest mode for dpowconfs tests/etc - if ( Params().NetworkIDString() == "regtest" && ( height%7 == 0) ) { - notarized = 1; - sp->NOTARIZED_HEIGHT = height; - sp->NOTARIZED_HASH = block.GetHash(); - sp->NOTARIZED_DESTTXID = txhash; - } - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf("(tx.%d: ",i); - for (j=0; j= 235300 && block.vtx[0].vout[1].nValue >= 100000*COIN ) - block.vtx[0].vout[1].nValue = 0; - break; - } - } - }*/ - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf("%.8f ",dstr(block.vtx[i].vout[j].nValue)); - len = block.vtx[i].vout[j].scriptPubKey.size(); - - if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) - { - memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); - notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); - if ( fJustCheck && notaryid == -2 ) - { - // We see a valid notarisation here, save its location. - notarisations.push_back(i); - } - if ( 0 && i > 0 ) - { - for (k=0; k 2 ) - { - numvalid = 0; - memset(pubkeys,0,sizeof(pubkeys)); - for (j=1; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) - { - memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); - if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) - { - memcpy(pubkeys[numvalid++],scriptbuf+1,33); - for (k=0; k<33; k++) - printf("%02x",scriptbuf[k+1]); - printf(" <- new notary.[%d]\n",j-1); - } - } - } - if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 ) - { - if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) - { - memset(&txhash,0,sizeof(txhash)); - komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); - printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); - } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); - } - } - } - } - if ( !fJustCheck && IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - 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"); return(0); } - //KOMODO_INITDONE = (uint32_t)time(NULL); - //fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight()); - if (fJustCheck) - { - if ( notarisations.size() == 0 ) - return(0); - if ( notarisations.size() == 1 && notarisations[0] == 1 ) - 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); -} - -#endif +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp new file mode 100644 index 00000000000..d74a5064b21 --- /dev/null +++ b/src/komodo_bitcoind.cpp @@ -0,0 +1,2642 @@ +/****************************************************************************** + * 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 "komodo_bitcoind.h" +#include "komodo_extern_globals.h" +#include "komodo_utils.h" // OS_milliseconds +#include "komodo_notary.h" // komodo_chosennotary() + +/************************************************************************ + * + * Initialize the string handler so that it is thread safe + * + ************************************************************************/ + +void init_string(struct return_string *s) +{ + s->len = 0; + s->ptr = (char *)calloc(1,s->len+1); + if ( s->ptr == NULL ) + { + fprintf(stderr,"init_string malloc() failed\n"); + StartShutdown(); + } + s->ptr[0] = '\0'; +} + +int tx_height( const uint256 &hash ){ + int nHeight = 0; + CTransaction tx; + uint256 hashBlock; + if (!GetTransaction(hash, tx, hashBlock, true)) { + fprintf(stderr,"tx hash %s does not exist!\n", hash.ToString().c_str() ); + } + + BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); + if (it != mapBlockIndex.end()) { + nHeight = it->second->GetHeight(); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + } else { + // Unconfirmed xtns + //fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); + } + return nHeight; +} + + +/************************************************************************ + * + * Use the "writer" to accumulate text until done + * + ************************************************************************/ + +size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s) +{ + size_t new_len = s->len + size*nmemb; + s->ptr = (char *)realloc(s->ptr,new_len+1); + if ( s->ptr == NULL ) + { + fprintf(stderr, "accumulate realloc() failed\n"); + StartShutdown(); + } + memcpy(s->ptr+s->len,ptr,size*nmemb); + s->ptr[new_len] = '\0'; + s->len = new_len; + return(size * nmemb); +} + +/************************************************************************ + * + * return the current system time in milliseconds + * + ************************************************************************/ + +#define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field +#ifdef EXTRACT_BITCOIND_RESULT + +/************************************************************************ + * + * perform post processing of the results + * + ************************************************************************/ + +char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params) +{ + long i,j,len; char *retstr = 0; cJSON *json,*result,*error; + //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); + if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 ) + { + if ( strcmp(command,"signrawtransaction") != 0 ) + printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); + return(rpcstr); + } + json = cJSON_Parse(rpcstr); + if ( json == 0 ) + { + printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); + free(rpcstr); + return(0); + } + result = cJSON_GetObjectItem(json,"result"); + error = cJSON_GetObjectItem(json,"error"); + if ( error != 0 && result != 0 ) + { + if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) + { + retstr = cJSON_Print(result); + len = strlen(retstr); + if ( retstr[0] == '"' && retstr[len-1] == '"' ) + { + for (i=1,j=0; itype&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) + { + if ( strcmp(command,"signrawtransaction") != 0 ) + printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr); + } + free(rpcstr); + } else retstr = rpcstr; + free_json(json); + //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); + return(retstr); +} +#endif + +/************************************************************************ + * + * perform the query + * + ************************************************************************/ + +char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) +{ + static int didinit,count,count2; static double elapsedsum,elapsedsum2; + struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; + char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; + if ( didinit == 0 ) + { + didinit = 1; + curl_global_init(CURL_GLOBAL_ALL); //init the curl session + } + numretries = 0; + if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) + specialcase = 1; + else specialcase = 0; + if ( url[0] == 0 ) + strcpy(url,"http://127.0.0.1:7876/nxt"); + if ( specialcase != 0 && 0 ) + printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); +try_again: + if ( retstrp != 0 ) + *retstrp = 0; + starttime = OS_milliseconds(); + curl_handle = curl_easy_init(); + init_string(&s); + headers = curl_slist_append(0,"Expect:"); + + curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); + curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl_handle,CURLOPT_URL, url); + curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function + curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback + curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash + curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback + //curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + //curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2); + + if ( strncmp(url,"https",5) == 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); + databuf = 0; + if ( params != 0 ) + { + if ( command != 0 && specialcase == 0 ) + { + len = strlen(params); + if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) { + bracket0 = bracket1 = (char *)""; + } + else + { + bracket0 = (char *)"["; + bracket1 = (char *)"]"; + } + + databuf = (char *)malloc(256 + strlen(command) + strlen(params)); + sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); + //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); + // + } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params); + curl_easy_setopt(curl_handle,CURLOPT_POST,1L); + if ( databuf != 0 ) + curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf); + else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params); + } + //laststart = milliseconds(); + res = curl_easy_perform(curl_handle); + curl_slist_free_all(headers); + curl_easy_cleanup(curl_handle); + if ( databuf != 0 ) // clean up temporary buffer + { + free(databuf); + databuf = 0; + } + if ( res != CURLE_OK ) + { + numretries++; + if ( specialcase != 0 ) + { + fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); + free(s.ptr); + return(0); + } + else if ( numretries >= 1 ) + { + fprintf(stderr,"Maximum number of retries exceeded!\n"); + free(s.ptr); + return(0); + } + if ( (rand() % 1000) == 0 ) + printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); + free(s.ptr); + sleep((1< (%s)\n",params,s.ptr); + count2++; + elapsedsum2 += (OS_milliseconds() - starttime); + if ( (count2 % 10000) == 0) + printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command); + return(s.ptr); + } + } + printf("bitcoind_RPC: impossible case\n"); + free(s.ptr); + return(0); +} + +static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data) +{ + size_t realsize = (size * nmemb); + struct MemoryStruct *mem = (struct MemoryStruct *)data; + mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); + if ( mem->memory != 0 ) + { + if ( ptr != 0 ) + memcpy(&(mem->memory[mem->size]),ptr,realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + } + //printf("got %d bytes\n",(int32_t)(size*nmemb)); + return(realsize); +} + +char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) +{ + struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; + if ( (cHandle= *cHandlep) == NULL ) + *cHandlep = cHandle = curl_easy_init(); + else curl_easy_reset(cHandle); + //#ifdef DEBUG + //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); + //#endif + curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); + curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0); + //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1); + curl_easy_setopt(cHandle,CURLOPT_URL,url); + curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10); + if ( userpass != 0 && userpass[0] != 0 ) + curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); + if ( postfields != 0 && postfields[0] != 0 ) + { + curl_easy_setopt(cHandle,CURLOPT_POST,1); + curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); + } + if ( hdr0 != NULL && hdr0[0] != 0 ) + { + //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:""); + headers = curl_slist_append(headers,hdr0); + if ( hdr1 != 0 && hdr1[0] != 0 ) + headers = curl_slist_append(headers,hdr1); + if ( hdr2 != 0 && hdr2[0] != 0 ) + headers = curl_slist_append(headers,hdr2); + if ( hdr3 != 0 && hdr3[0] != 0 ) + headers = curl_slist_append(headers,hdr3); + } //headers = curl_slist_append(0,"Expect:"); + if ( headers != 0 ) + curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers); + //res = curl_easy_perform(cHandle); + memset(&chunk,0,sizeof(chunk)); + curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); + curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk); + curl_easy_perform(cHandle); + curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code); + if ( headers != 0 ) + curl_slist_free_all(headers); + if ( code != 200 ) + printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory); + return(chunk.memory); +} + +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) +{ + //static void *cHandle; + char url[512],*retstr=0,*retstr2=0,postdata[8192]; + if ( params == 0 || params[0] == 0 ) + params = (char *)"[]"; + if ( strlen(params) < sizeof(postdata)-128 ) + { + sprintf(url,(char *)"http://127.0.0.1:%u",port); + sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); + // printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); + retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); + //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); + } + // fprintf(stderr, "RPC RESP: %s\n", retstr2); + return(retstr2); +} + +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp) +{ + char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0; + params[0] = 0; + *kmdnotarized_heightp = 0; + if ( strcmp(dest,"KMD") == 0 ) + { + port = KMD_PORT; + userpass = KMDUSERPASS; + } + else if ( strcmp(dest,"BTC") == 0 ) // this is no longer strictly BTC; depends on -notary= path + { + port = DEST_PORT; + userpass = BTCUSERPASS; + } + else return(0); + if ( userpass[0] != 0 ) + { + if ( strcmp("BTC",dest) != 0 ) + { + if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) + { + //printf("(%s)\n",jsonstr); + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (item= jobj(json,(char *)"result")) != 0 ) + { + height = jint(item,(char *)"blocks"); + *kmdnotarized_heightp = height; + } + free_json(json); + } + free(jsonstr); + } + } else { + if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getblockchaininfo",params,port)) != 0 ) + { + //printf("(%s)\n",jsonstr); + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (item= jobj(json,(char *)"result")) != 0 ) + { + height = jint(item,(char *)"blocks"); + *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height; + } + free_json(json); + } + free(jsonstr); + } + } + sprintf(params,"[\"%s\", 1]",txidstr); + if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) + { + //printf("(%s)\n",jsonstr); + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (item= jobj(json,(char *)"result")) != 0 ) + { + txid_confirmations = jint(item,(char *)"rawconfirmations"); + if ( txid_confirmations > 0 && height > txid_confirmations ) + txid_height = height - txid_confirmations; + else txid_height = height; + //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height); + } + free_json(json); + } + free(jsonstr); + } + } + return(txid_height); +} + +int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH) +{ + int32_t i; uint256 hash; char params[256]; + for (i=0; i<32; i++) + ((uint8_t *)&hash)[i] = script[2+i]; + if ( hash == NOTARIZED_HASH ) + return(1); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]); + printf(" notarized, "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&hash)[i]); + printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height); + return(-1); +} + +void komodo_reconsiderblock(uint256 blockhash) +{ + char params[256],*jsonstr,*hexstr; + sprintf(params,"[\"%s\"]",blockhash.ToString().c_str()); + if ( (jsonstr= komodo_issuemethod(ASSETCHAINS_USERPASS,(char *)"reconsiderblock",params,ASSETCHAINS_RPCPORT)) != 0 ) + { + //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> (%s)\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT,jsonstr); + free(jsonstr); + } + //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> NULL\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT); +} + +int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) +{ + char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; + script = _script; + /*params[0] = '['; + params[1] = '"'; + for (i=0; i<32; i++) + sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); + strcat(params,"\", 1]");*/ + sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); + if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) + return(0); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); + if ( strcmp(dest,"KMD") == 0 ) + { + if ( KMDUSERPASS[0] != 0 ) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); + //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); + } + }//else jsonstr = _dex_getrawtransaction(); + else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok + } + else if ( strcmp(dest,"BTC") == 0 ) + { + if ( BTCUSERPASS[0] != 0 ) + { + jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,DEST_PORT); + } + //else jsonstr = _dex_getrawtransaction(); + else return(0); + } + else + { + printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); + return(-1); + } + if ( jsonstr != 0 ) + { + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != 0 ) + { + vout = jitem(vouts,n-1); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("vout.(%s)\n",jprint(vout,0)); + if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) + { + if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) + { + //printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str()); + len = strlen(hexstr) >> 1; + decode_hex(script,len,hexstr); + if ( script[1] == 0x4c ) + { + script++; + len--; + } + else if ( script[1] == 0x4d ) + { + script += 2; + len -= 2; + } + retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH); + } + } + } + free_json(txjson); + } + free(jsonstr); + } + return(retval); +} + +CScript komodo_makeopret(CBlock *pblock, bool fNew) +{ + std::vector vLeaves; + vLeaves.push_back(pblock->hashPrevBlock); + for (int32_t i = 0; i < pblock->vtx.size()-(fNew ? 0 : 1); i++) + vLeaves.push_back(pblock->vtx[i].GetHash()); + uint256 merkleroot = GetMerkleRoot(vLeaves); + CScript opret; + opret << OP_RETURN << E_MARSHAL(ss << merkleroot); + return(opret); +} + +uint64_t komodo_seed(int32_t height) +{ + uint64_t seed = 0; + seed = (height << 13) ^ (height << 2); + seed <<= 21; + seed |= (height & 0xffffffff); + seed ^= (seed << 17) ^ (seed << 1); + return(seed); +} + +uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) +{ + CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; + *valuep = 0; + if (!GetTransaction(hash, tx, hashBlock, true)) + { + //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); + return(0); + } + numvouts = tx.vout.size(); + //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); + if ( n < numvouts ) + { + *valuep = tx.vout[n].nValue; + opret = tx.vout[numvouts-1].scriptPubKey; + if (ExtractDestination(tx.vout[n].scriptPubKey, address)) + strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); + } + return(tx.nLockTime); +} + +CBlockIndex *komodo_getblockindex(uint256 hash) +{ + BlockMap::const_iterator it = mapBlockIndex.find(hash); + return((it != mapBlockIndex.end()) ? it->second : NULL); +} + +uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) +{ + CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0; + *valuep = 0; + if (!GetTransaction(hash, tx, hashBlock, true)) + { + //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); + return(0); + } + if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) + txtime = pindex->nTime; + else txtime = tx.nLockTime; + //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); + if ( n < tx.vout.size() ) + { + *valuep = tx.vout[n].nValue; + if (ExtractDestination(tx.vout[n].scriptPubKey, address)) + strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); + } + return(txtime); +} + +CScript EncodeStakingOpRet(uint256 merkleroot) +{ + CScript opret; uint8_t evalcode = 77; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << merkleroot); + return(opret); +} + +uint8_t DecodeStakingOpRet(CScript scriptPubKey, uint256 &merkleroot) +{ + std::vector vopret; uint8_t evalcode; + GetOpReturnData(scriptPubKey, vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> evalcode; ss >> merkleroot) != 0 && evalcode == 77 ) + { + //fprintf(stderr, "evalcode.%i merkleroot.%s\n",evalcode, merkleroot.GetHex().c_str() ); + return(1); + } + return(0); +} + +int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp) +{ + if ( timestamp > nStakedDecemberHardforkTimestamp || komodo_heightstamp(height) > nStakedDecemberHardforkTimestamp ) //December 2019 hardfork + return(1); + else return(0); +} + +int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp) +{ + return komodo_newStakerActive(height, timestamp) == 1; +} + +bool komodo_checkopret(CBlock *pblock, CScript &merkleroot) +{ + merkleroot = pblock->vtx.back().vout.back().scriptPubKey; + return(merkleroot.IsOpReturn() && merkleroot == komodo_makeopret(pblock, false)); +} + +bool komodo_hardfork_active(uint32_t time) +{ + return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork +} + +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey) +{ + std::vector vLeaves; + // rereate coinbase tx + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = fNew ? (CScript() << nHeight << CScriptNum(1)) + COINBASE_FLAGS : pblock->vtx[0].vin[0].scriptSig; + txNew.vout.resize(1); + txNew.vout[0].scriptPubKey = scriptPubKey; + txNew.vout[0].nValue = 0; + txNew.nExpiryHeight = 0; + txNew.nLockTime = 0; + //fprintf(stderr, "validation: coinbasetx.%s\n", EncodeHexTx(txNew).c_str()); + //fprintf(stderr, "txnew.%s\n", txNew.GetHash().ToString().c_str()); + vLeaves.push_back(txNew.GetHash()); + vLeaves.push_back(prevBlockHash); + for (int32_t i = 1; i < pblock->vtx.size()-(fNew ? 0 : 1); i++) + vLeaves.push_back(pblock->vtx[i].GetHash()); + return GetMerkleRoot(vLeaves); +} + +int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) +{ + int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid, merkleroot; CScript opret; + if ( ASSETCHAINS_STAKED != 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+komodo_hasOpRet(height,pblock->nTime) ) + { + txid = pblock->vtx[n-1].vin[0].prevout.hash; + vout = pblock->vtx[n-1].vin[0].prevout.n; + txtime = komodo_txtime(opret,&value,txid,vout,destaddr); + if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) + { + if ( addressout != 0 ) *addressout = voutaddress; + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + //fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr); + if ( komodo_newStakerActive(height, pblock->nTime) != 0 ) + { + if ( DecodeStakingOpRet(pblock->vtx[n-1].vout[1].scriptPubKey, merkleroot) != 0 && komodo_calcmerkleroot(pblock, pblock->hashPrevBlock, height, false, pblock->vtx[0].vout[0].scriptPubKey) == merkleroot ) + { + return(1); + } + } + else + { + if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 ) + { + return(1); + } + } + } + } + } + return(0); +} + +void komodo_disconnect(CBlockIndex *pindex,CBlock& block) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + //fprintf(stderr,"disconnect ht.%d\n",pindex->GetHeight()); + komodo_init(pindex->GetHeight()); + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + //sp->rewinding = pindex->GetHeight(); + //fprintf(stderr,"-%d ",pindex->GetHeight()); + } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->GetHeight(),ASSETCHAINS_SYMBOL); +} + +int32_t komodo_is_notarytx(const CTransaction& tx) +{ + uint8_t *ptr; static uint8_t crypto777[33]; + if ( tx.vout.size() > 0 ) + { + ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0]; + if ( ptr != 0 ) + { + if ( crypto777[0] == 0 ) + decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); + if ( memcmp(ptr+1,crypto777,33) == 0 ) + { + //printf("found notarytx\n"); + return(1); + } + } + } + return(0); +} + +int32_t komodo_block2height(CBlock *block) +{ + static uint32_t match,mismatch; + int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex = NULL; + BlockMap::const_iterator it = mapBlockIndex.find(block->GetHash()); + if ( it != mapBlockIndex.end() && (pindex = it->second) != 0 ) + { + height2 = (int32_t)pindex->GetHeight(); + if ( height2 >= 0 ) + return(height2); + } + if ( pindex && block != 0 && block->vtx[0].vin.size() > 0 ) + { + ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0]; + if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 ) + { + //for (i=0; i<6; i++) + // printf("%02x",ptr[i]); + n = ptr[0]; + for (i=0; ivtx[0].vin[0].scriptSig.size(),height); + } + } + if ( height != height2 ) + { + //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); + mismatch++; + if ( height2 >= 0 ) + height = height2; + } else match++; + return(height); +} + +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) +{ + int32_t n; + if ( KOMODO_LOADINGBLOCKS == 0 ) + memset(pubkey33,0xff,33); + else memset(pubkey33,0,33); + if ( block->vtx[0].vout.size() > 0 ) + { + txnouttype whichType; + std::vector> vch; + if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) + { + CPubKey pubKey(vch[0]); + if (pubKey.IsValid()) + { + memcpy(pubkey33,vch[0].data(),33); + return true; + } + else memset(pubkey33,0,33); + } + else memset(pubkey33,0,33); + } + return(0); +} + +int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) +{ + block.SetNull(); + // Open history file to read + CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION); + if (filein.IsNull()) + return(-1); + // Read block + try { filein >> block; } + catch (const std::exception& e) + { + fprintf(stderr,"readblockfromdisk err B\n"); + return(-1); + } + return(0); +} + +uint32_t komodo_chainactive_timestamp() +{ + if ( chainActive.LastTip() != 0 ) + return((uint32_t)chainActive.LastTip()->GetBlockTime()); + else return(0); +} + +CBlockIndex *komodo_chainactive(int32_t height) +{ + if ( chainActive.LastTip() != 0 ) + { + if ( height <= chainActive.LastTip()->GetHeight() ) + return(chainActive[height]); + // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->GetHeight()); + } + //fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height); + return(0); +} + +uint32_t komodo_heightstamp(int32_t height) +{ + CBlockIndex *ptr; + if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) + return(ptr->nTime); + //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); + return(0); +} + +void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) +{ + int32_t num,i; CBlock block; + memset(pubkey33,0,33); + if ( pindex != 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + komodo_block2pubkey33(pubkey33,&block); + } +} + +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height) +{ + // after the season HF block ALL new notaries instantly become elegible. + int32_t i,j,n,duplicate; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33]; + memset(mids,-1,sizeof(*mids)*66); + n = komodo_notaries(notarypubs33,height,0); + for (i=duplicate=0; i<66; i++) + { + if ( (pindex= komodo_chainactive(height-i)) != 0 ) + { + blocktimes[i] = pindex->nTime; + if ( komodo_blockload(block,pindex) == 0 ) + { + komodo_block2pubkey33(pubkeys[i],&block); + for (j=0; j= 0 && i > 0 && mids[i] == mids[0] ) + duplicate++; + } + } + if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) ) + return(1); + else return(0); +} + +int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) +{ + int32_t i,j,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33]; + numnotaries = komodo_notaries(notarypubs33,height,0); + for (i=nonz=0; i= 82000 ) + { + if ( notaryid >= 0 ) + { + for (i=1; i<66; i++) + { + if ( mids[i] == notaryid ) + { + if ( height > 792000 ) + { + for (j=0; j<66; j++) + fprintf(stderr,"%d ",mids[j]); + fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i); + return(-1); + } else break; + } + } + if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 ) + { + if ( height > 807000 ) + return(-2); + } + return(1); + } else return(0); + } + else + { + if ( height >= 34000 && notaryid >= 0 ) + { + if ( height < 79693 ) + limit = 64; + else if ( height < 82000 ) + limit = 8; + else limit = 66; + for (i=1; i 225000 ) + return(-1); + } + } + //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit); + return(1); + } + } + return(0); +} + +int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) +{ + int32_t depth,notarized_ht; uint256 MoM,kmdtxid; + depth = komodo_MoMdata(¬arized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip); + memset(MoMp,0,sizeof(*MoMp)); + memset(kmdtxidp,0,sizeof(*kmdtxidp)); + *notarized_heightp = 0; + if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) + { + *MoMp = MoM; + *notarized_heightp = notarized_ht; + *kmdtxidp = kmdtxid; + } + return(depth); +} + +CBlockIndex *komodo_blockindex(uint256 hash) +{ + BlockMap::const_iterator it; CBlockIndex *pindex = 0; + if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() ) + pindex = it->second; + return(pindex); +} + +int32_t komodo_blockheight(uint256 hash) +{ + BlockMap::const_iterator it; CBlockIndex *pindex = 0; + if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() ) + { + if ( (pindex= it->second) != 0 ) + return(pindex->GetHeight()); + } + 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; + if ( (pindex= chainActive.LastTip()) == 0 ) + return(-1); + notarized_height = komodo_notarizeddata(pindex->GetHeight(),¬arized_hash,¬arized_desttxid); + *notarized_heightp = notarized_height; + BlockMap::const_iterator it; + if ( notarized_height >= 0 && notarized_height <= pindex->GetHeight() && (it = mapBlockIndex.find(notarized_hash)) != mapBlockIndex.end() && (notary = it->second) != NULL ) + { + //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->GetHeight(),notarized_height,notarized_hash.ToString().c_str()); + if ( notary->GetHeight() == notarized_height ) // if notarized_hash not in chain, reorg + { + if ( nHeight < notarized_height ) + { + //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + return(-1); + } + else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) + { + fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + return(-1); + } + } //else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->GetHeight()); + } + //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) + // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->GetHeight()); + return(0); +} + +uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) +{ + LOCK(cs_main); + CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; + *txheighttimep = *txheightp = *tiptimep = 0; + *valuep = 0; + if ( !GetTransaction(hash,tx,hashBlock,true) ) + return(0); + uint32_t locktime = 0; + if ( n < tx.vout.size() ) + { + if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) + { + *valuep = tx.vout[n].nValue; + *txheightp = pindex->GetHeight(); + *txheighttimep = pindex->nTime; + if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 ) + *tiptimep = (uint32_t)tipindex->nTime; + locktime = tx.nLockTime; + //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); + } + } + return(locktime); +} + +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); + +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) +{ + uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; + if ( (pindex= chainActive[tipheight]) != 0 ) + tiptime = (uint32_t)pindex->nTime; + else fprintf(stderr,"cant find height[%d]\n",tipheight); + if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) + { + if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) + return(komodo_interest(*txheightp,value,*locktimep,tiptime)); + //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); + else fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); + } + return(0); +} + +int32_t komodo_nextheight() +{ + CBlockIndex *pindex; int32_t ht; + if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) + return(ht+1); + else return(komodo_longestchain() + 1); +} + +int32_t komodo_isrealtime(int32_t *kmdheightp) +{ + struct komodo_state *sp; CBlockIndex *pindex; + if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) + *kmdheightp = sp->CURRENT_HEIGHT; + else *kmdheightp = 0; + if ( (pindex= chainActive.LastTip()) != 0 && pindex->GetHeight() >= (int32_t)komodo_longestchain() ) + return(1); + else return(0); +} + +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) +{ + dispflag = 1; + if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) + { + if ( txheight > 246748 ) + { + if ( txheight < 247205 ) + cmptime -= 16000; + if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) + { + if ( tx.nLockTime != 1477258935 && dispflag != 0 ) + { + fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(uint32_t)tx.nLockTime,cmptime); + } + return(-1); + } + if ( 0 && dispflag != 0 ) + fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(int32_t)tx.nLockTime,cmptime); + } + } + return(0); +} + +/* + komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on. + + komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass + + commission must be in coinbase.vout[1] and must be >= 10000 sats + PoS stake must be without txfee and in the last tx in the block at vout[0] + */ + +CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); + +uint64_t komodo_commission(const CBlock *pblock,int32_t height) +{ + static bool didinit = false,ishush3 = false; + // LABS fungible chains, cannot have any block reward! + if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) + return(0); + + if (!didinit) { + ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; + didinit = true; + } + + int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0; + if ( ASSETCHAINS_FOUNDERS != 0 ) + { + nSubsidy = GetBlockSubsidy(height,Params().GetConsensus()); + //fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION)); + commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN); + + if (ishush3) { + int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111; + // HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves. + // You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25 + // but to tell the AC params, I need to say "11% of 11.25" is 1.25 + // 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually + // Transition period of 128 blocks has BR=FR=0 + if (height < TRANSITION) { + commission = 0; + } else if (height < HALVING1) { + commission = starting_commission; + } else if (height < HALVING1+1*INTERVAL) { + commission = starting_commission / 2; + } else if (height < HALVING1+2*INTERVAL) { + commission = starting_commission / 4; + } else if (height < HALVING1+3*INTERVAL) { + commission = starting_commission / 8; + } else if (height < HALVING1+4*INTERVAL) { + commission = starting_commission / 16; + } else if (height < HALVING1+5*INTERVAL) { + commission = starting_commission / 32; + } else if (height < HALVING1+6*INTERVAL) { // Block 5380000 + // Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting + commission = starting_commission / 64; + } else if (height < HALVING1+7*INTERVAL) { + // Block reward will be zero before this is ever reached + commission = starting_commission / 128; // Block 6220000 + } + } + + if ( ASSETCHAINS_FOUNDERS > 1 ) + { + if ( (height % ASSETCHAINS_FOUNDERS) == 0 ) + { + if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) + commission = commission * ASSETCHAINS_FOUNDERS; + else + commission = ASSETCHAINS_FOUNDERS_REWARD; + } + else commission = 0; + } + } + else if ( pblock != 0 ) + { + txn_count = pblock->vtx.size(); + for (i=0; ivtx[i].vout.size(); + for (j=0; j 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) + break; + //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); + if ( i != 0 || j != 1 ) + total += pblock->vtx[i].vout[j].nValue; + if ( total > 1000000 * COIN ) + { + total = 1000000 * COIN; + break; + } + } + } + commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000; + //commission = ((total * ASSETCHAINS_COMMISSION) / COIN); + } + if ( commission < 10000 ) + commission = 0; + //fprintf(stderr,"-> %.8f\n",(double)commission/COIN); + return(commission); +} + +uint32_t komodo_segid32(char *coinaddr) +{ + bits256 addrhash; + vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr)); + return(addrhash.uints[0]); +} + +int8_t komodo_segid(int32_t nocache,int32_t height) +{ + CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout,newStakerActive; uint256 txid,merkleroot; CScript opret; int8_t segid = -1; + if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) + { + if ( nocache == 0 && pindex->segid >= -1 ) + return(pindex->segid); + if ( komodo_blockload(block,pindex) == 0 ) + { + newStakerActive = komodo_newStakerActive(height, block.nTime); + txn_count = block.vtx.size(); + if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pindex->nTime) ) + { + txid = block.vtx[txn_count-1].vin[0].prevout.hash; + vout = block.vtx[txn_count-1].vin[0].prevout.n; + txtime = komodo_txtime(opret,&value,txid,vout,destaddr); + if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + if ( newStakerActive == 1 && block.vtx[txn_count-1].vout.size() == 2 && DecodeStakingOpRet(block.vtx[txn_count-1].vout[1].scriptPubKey, merkleroot) != 0 ) + newStakerActive++; + if ( newStakerActive == 2 || (newStakerActive == 0 && strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value) ) + { + segid = komodo_segid32(voutaddr) & 0x3f; + //fprintf(stderr, "komodo_segid: ht.%i --> %i\n",height,pindex->segid); + } + } //else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); + } + } + // The new staker sets segid in komodo_checkPOW, this persists after restart by being saved in the blockindex for blocks past the HF timestamp, to keep backwards compatibility. + // PoW blocks cannot contain a staking tx. If segid has not yet been set, we can set it here accurately. + if ( pindex->segid == -2 ) + pindex->segid = segid; + } + return(segid); +} + +void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) +{ + static uint8_t prevhashbuf[100]; static int32_t prevheight; + int32_t i; + if ( height == prevheight && n == 100 ) + memcpy(hashbuf,prevhashbuf,100); + else + { + memset(hashbuf,0xff,n); + for (i=0; i 10 && (tipindex= komodo_chainactive(height - 1)) != 0 ) // disable offchain diffchange + { + diff = (nTime - tipindex->GetMedianTimePast()); + tipdiff = (nTime - tipindex->nTime); + if ( tipdiff > 13*ASSETCHAINS_BLOCKTIME ) + diff = tipdiff; + if ( diff >= 13 * ASSETCHAINS_BLOCKTIME && (height < 30 || tipdiff > 2*ASSETCHAINS_BLOCKTIME) ) + { + mult = diff - 12 * ASSETCHAINS_BLOCKTIME; + mult = (mult / ASSETCHAINS_BLOCKTIME) * ASSETCHAINS_BLOCKTIME + ASSETCHAINS_BLOCKTIME / 2; + origtarget = bnTarget; + bnTarget = bnTarget * arith_uint256(mult * mult); + easy.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + if ( bnTarget < origtarget || bnTarget > easy ) // deal with overflow + { + bnTarget = easy; + fprintf(stderr,"tipdiff.%d diff.%d height.%d miner overflowed mult.%lld, set to mindiff\n",tipdiff,diff,height,(long long)mult); + } else fprintf(stderr,"tipdiff.%d diff.%d height.%d miner elapsed %d, adjust by factor of %lld\n",tipdiff,diff,height,diff,(long long)mult); + } //else fprintf(stderr,"height.%d tipdiff.%d diff %d, vs %d\n",height,tipdiff,diff,13*ASSETCHAINS_BLOCKTIME); + } else fprintf(stderr,"adaptive cant find height.%d\n",height); + return(bnTarget); +} + +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive) +{ + int32_t oldflag = 0,dispflag = 0; + CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val; + *percPoSp = percPoS = 0; + + if ( newStakerActive == 0 && height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) + return(target); + + sum = arith_uint256(0); + ave = sum; + if ( newStakerActive != 0 ) + { + easydiff.SetCompact(ASSETCHAINS_STAKED_MIN_POW_DIFF,&fNegative,&fOverflow); + if ( height <= 10 ) + return(easydiff); + } + else + easydiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); + for (i=n=m=0; i<100; i++) + { + ht = height - 100 + i; + if ( ht <= 1 ) + continue; + if ( (pindex= komodo_chainactive(ht)) != 0 ) + { + if ( komodo_segid(0,ht) >= 0 ) + { + n++; + percPoS++; + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"0"); + } + else + { + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"1"); + sum += UintToArith256(pindex->GetBlockHash()); + m++; + } + } //else fprintf(stderr, "pindex returned null ht.%i\n",ht); + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) + fprintf(stderr," %d, ",percPoS); + } + if ( m+n < 100 ) + { + // We do actual PoS % at the start. Requires coin distribution in first 10 blocks! + if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) + percPoS = (percPoS*100) / (m+n); + else + percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; + } + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); + *percPoSp = percPoS; + if ( m > 0 ) + { + ave = (sum / arith_uint256(m)); + if ( ave > target ) + ave = target; + } else ave = target; //easydiff; //else return(target); + if ( percPoS == 0 ) + percPoS = 1; + if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget + { + if ( oldflag != 0 ) + bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); + else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); + fprintf(stderr," increase diff -> "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," floor diff "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&target)[i]); + fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); + } + } + else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget + { + if ( oldflag != 0 ) + { + bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); + bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); + } + else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); + if ( bnTarget > easydiff ) + bnTarget = easydiff; + else if ( bnTarget < ave ) // overflow + { + bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); + if ( bnTarget < ave ) + bnTarget = ave; + } + if ( dispflag != 0 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); + fprintf(stderr," decrease diff -> "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," floor diff "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&target)[i]); + fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); + } + } + else + bnTarget = ave; // recent ave is perfect + if ( newStakerActive != 0 && bnTarget > easydiff ) + bnTarget = easydiff; + return(bnTarget); +} + +uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr,int32_t PoSperc) +{ + bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t segid,minage,i,iter=0; int64_t diff=0; uint32_t txtime,segid32,winner = 0 ; uint64_t value,coinage; + txtime = komodo_txtime2(&value,txid,vout,address); + if ( validateflag == 0 ) + { + //fprintf(stderr,"blocktime.%u -> ",blocktime); + if ( blocktime < prevtime+3 ) + blocktime = prevtime+3; + if ( blocktime < GetTime()-60 ) + blocktime = GetTime()+30; + //fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime); + } + if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 ) + { + //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime); + return(0); + } + if ( value < SATOSHIDEN ) + return(0); + value /= SATOSHIDEN; + mindiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); + ratio = (mindiff / bnTarget); + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + komodo_segids(hashbuf,nHeight-101,100); + segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); + segid = ((nHeight + segid32) & 0x3f); + for (iter=0; iter<600; iter++) + { + if ( blocktime+iter+segid*2 < txtime+minage ) + continue; + diff = (iter + blocktime - txtime - minage); + // Disable PoS64 on VerusHash, doesnt work properly. + if ( 0 ) // ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) + { + /*if ( PoSperc < ASSETCHAINS_STAKED ) + { + // Under PoS % target and we need to increase diff. + //fprintf(stderr, "PoS too low diff.%i changed to.",diff); + diff = diff * ( (ASSETCHAINS_STAKED - PoSperc + 1) * (ASSETCHAINS_STAKED - PoSperc + 1) * ( nHeight < 50 ? 1000 : 1)); + //fprintf(stderr, "%i \n",diff); + } + else */ + if ( PoSperc > ASSETCHAINS_STAKED ) + { + // Over PoS target need to lower diff. + //fprintf(stderr, "PoS too high diff.%i changed to.",diff); + diff = diff / ( (PoSperc - ASSETCHAINS_STAKED + 1) * (PoSperc - ASSETCHAINS_STAKED + 1) ); + //fprintf(stderr, "%i \n",diff); + } + } + if ( diff < 0 ) + diff = 60; + else if ( diff > 3600*24*30 ) + { + //printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage); + diff = 3600*24*30; + } + if ( iter > 0 ) + diff += segid*2; + coinage = (value * diff); + if ( 0 ) //&& ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) + { + if ( PoSperc < ASSETCHAINS_STAKED ) + { + // Under PoS % target and we need to increase diff. + //fprintf(stderr, "PoS too low diff.%i changed to.",diff); + if ( blocktime+iter+segid*2 > prevtime+128 ) + coinage *= ((blocktime+iter+segid*2) - (prevtime+102)); + //fprintf(stderr, "%i \n",diff); + } + } + if ( blocktime+iter+segid*2 > prevtime+480 ) + coinage *= ((blocktime+iter+segid*2) - (prevtime+400)); + coinage256 = arith_uint256(coinage+1); + hashval = ratio * (UintToArith256(hash) / coinage256); + if ( hashval <= bnTarget ) + { + winner = 1; + if ( validateflag == 0 ) + { + //fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid); + blocktime += iter; + blocktime += segid * 2; + } + break; + } + if ( validateflag != 0 ) + { + /*for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff); */ + break; + } + } + //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); + if ( 0 && validateflag != 0 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d ht.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff,nHeight); + } + if ( nHeight < 10 ) + return(blocktime); + return(blocktime * winner); +} + +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, merkleroot; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; arith_uint256 POWTarget; + if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) + return(1); + BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); + pindex = it != mapBlockIndex.end() ? it->second : NULL; + int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); + // Get PoSperc and POW Target. slowflag only here, calling it when blocks out of order causes problems. + if ( slowflag != 0 ) + { + POWTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); + } + else + { + // checks opret merkle root and existence of staking tx. + return(komodo_isPoS(pblock,height,0)); + } + txn_count = pblock->vtx.size(); + //fprintf(stderr,"checkblock n.%d vins.%d vouts.%d %.8f %.8f\n",txn_count,(int32_t)pblock->vtx[txn_count-1].vin.size(),(int32_t)pblock->vtx[txn_count-1].vout.size(),(double)pblock->vtx[txn_count-1].vout[0].nValue/COIN,(double)pblock->vtx[txn_count-1].vout[1].nValue/COIN); + if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) + { + it = mapBlockIndex.find(pblock->hashPrevBlock); + if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL ) + prevtime = (uint32_t)previndex->nTime; + + txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; + vout = pblock->vtx[txn_count-1].vin[0].prevout.n; + if ( slowflag != 0 && prevtime != 0 ) + { + if ( komodo_isPoS(pblock,height,0) != 0 ) + { + // checks utxo is eligible to stake this block + eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,(char *)"",PoSperc); + } + if ( eligible == 0 || eligible > pblock->nTime ) + { + if ( 0 && ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime)); + } + else + { + isPoS = 1; + /* + If POWTarget is easydiff, then we have no possible way to detect a PoW block from a staking block! + The simplest fix is to make the min diff for PoW blocks higher than the staking mindiff. + The logic here, is that all PoS equihash solutions MUST be under the POW target diff, + The floor diff can be adjusted with ASSETCHAINS_STAKED_MIN_POW_DIFF, this is a hardforking change. + */ + if ( ASSETCHAINS_STAKED < 100 && bhash < POWTarget ) + { + fprintf(stderr,"[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); + isPoS = 0; + } + } + } + } + //fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS); + return(isPoS != 0); +} + +bool GetStakeParams(const CTransaction &stakeTx, CStakeParams &stakeParams); +bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTransaction &stakeTx, bool &cheating); + +// for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes +bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) +{ + CBlockIndex *pastBlockIndex; + uint256 txid, blkHash; + int32_t txn_count; + uint32_t voutNum; + CAmount value; + bool isPOS = false; + CTxDestination voutaddress, destaddress, cbaddress; + arith_uint256 target, hash; + CTransaction tx; + + if (!pblock->IsVerusPOSBlock()) + { + printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height); + //pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget()); + //printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str()); + return false; + } + + char voutaddr[64], destaddr[64], cbaddr[64]; + + txn_count = pblock->vtx.size(); + + if ( txn_count > 1 ) + { + target.SetCompact(pblock->GetVerusPOSTarget()); + txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; + voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n; + value = pblock->vtx[txn_count-1].vout[0].nValue; + + { + bool validHash = (value != 0); + bool enablePOSNonce = CPOSNonce::NewPOSActive(height); + uint256 rawHash; + arith_uint256 posHash; + + if (validHash && enablePOSNonce) + { + validHash = pblock->GetRawVerusPOSHash(rawHash, height); + posHash = UintToArith256(rawHash) / value; + if (!validHash || posHash > target) + { + validHash = false; + printf("ERROR: invalid nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", + pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); + } + } + if (validHash) + { + if (slowflag == 0) + { + isPOS = true; + } + else if (!(pastBlockIndex = komodo_chainactive(height - 100))) + { + fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); + } + else + if (!GetTransaction(txid, tx, blkHash, true)) + { + fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str()); + } + else + { + CBlockHeader bh = pastBlockIndex->GetBlockHeader(); + uint256 pastHash = bh.GetVerusEntropyHash(height - 100); + + // if height is over when Nonce is required to be the new format, we check that the new format is correct + // if over when we have the new POS hash function, we validate that as well + // they are 100 blocks apart + CPOSNonce nonce = pblock->nNonce; + + //printf("before nNonce: %s, height: %d\n", pblock->nNonce.GetHex().c_str(), height); + //validHash = pblock->GetRawVerusPOSHash(rawHash, height); + //hash = UintToArith256(rawHash) / tx.vout[voutNum].nValue; + //printf("Raw POShash: %s\n", hash.GetHex().c_str()); + + hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash)); + + //printf("after nNonce: %s, height: %d\n", nonce.GetHex().c_str(), height); + //printf("POShash: %s\n\n", hash.GetHex().c_str()); + + if (posHash == hash && hash <= target) + { + BlockMap::const_iterator it = mapBlockIndex.find(blkHash); + if ((it == mapBlockIndex.end()) || + !(pastBlockIndex = it->second) || + (height - pastBlockIndex->GetHeight()) < VERUS_MIN_STAKEAGE) + { + fprintf(stderr,"ERROR: invalid PoS block %s - stake source too new or not found\n",blkHash.ToString().c_str()); + } + else + { + // make sure we have the right target + CBlockIndex *previndex; + it = mapBlockIndex.find(pblock->hashPrevBlock); + if (it == mapBlockIndex.end() || !(previndex = it->second)) + { + fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str()); + } + else + { + arith_uint256 cTarget; + uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus()); + cTarget.SetCompact(nBits); + bool nonceOK = true; + + // check to see how many fail + //if (nonce != pblock->nNonce) + // printf("Mismatched nNonce: %s\nblkHash: %s, height: %d\n", nonce.GetHex().c_str(), pblock->GetHash().GetHex().c_str(), height); + + if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum)) + { + fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str()); + nonceOK = false; + } + else + { + if (cTarget != target) + { + fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); + nonceOK = false; + } + } + if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && + ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) ) + { + strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); + strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); + if ( !strcmp(destaddr,voutaddr) ) + { + isPOS = true; + CTransaction &cbtx = pblock->vtx[0]; + for (int i = 0; i < cbtx.vout.size(); i++) + { + if (CScriptExt::ExtractVoutDestination(cbtx, i, cbaddress)) + { + strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str()); + if (!strcmp(destaddr,cbaddr)) + continue; + } + else + { + if (cbtx.vout[i].scriptPubKey.IsOpReturn()) + continue; + isPOS = false; + break; + } + } + } + else + { + fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake or coinbase destination\n",blkHash.ToString().c_str()); + } + } + } + } + } + else + { + printf("ERROR: malformed nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", + pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); + } + } + } + } + } + return(isPOS); +} + +uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount) +{ + int8_t curEra = 0; int64_t ret = 0; + // if we have an end block in the first era, find our current era + if ( ASSETCHAINS_ENDSUBSIDY[0] > 1 ) + { + for ( curEra = 0; curEra <= ASSETCHAINS_LASTERA; curEra++ ) + { + if ( ASSETCHAINS_ENDSUBSIDY[curEra] > nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 ) + break; + } + } + if ( curEra > ASSETCHAINS_LASTERA ) + return(0); + + if ( notarycount == 0 ) + { + fprintf(stderr, "komodo_notarypayamount failed num notaries is 0!\n"); + return(0); + } + // 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]); + ret = ASSETCHAINS_NOTARY_PAY[curEra] / notarycount; + return(ret); +} + +int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len) +{ + // Check the notarisation is valid, and extract notarised height. + uint64_t voutmask; + uint8_t scriptbuf[10001]; + int32_t isratification,specialtx,notarizedheight; + + 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,¬arizedheight,0,1,0,timestamp) != -2 ) + { + fprintf(stderr, "<<<<< &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len) +{ + // fetch notary pubkey array. + uint64_t total = 0, AmountToPay = 0; + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, timestamp); + + // No point going further, no notaries can be paid. + if ( notarypubkeys[0][0] == 0 ) + return(0); + + // Check the notarisation is valid. + int32_t notarizedheight = komodo_getnotarizedheight(timestamp, height, script, len); + if ( notarizedheight == 0 ) + return(0); + + // resize coinbase vouts to number of notary nodes +1 for coinbase itself. + txNew.vout.resize(NotarisationNotaries.size()+1); + + // Calcualte the amount to pay according to the current era. + AmountToPay = komodo_notarypayamount(height,NotarisationNotaries.size()); + if ( AmountToPay == 0 ) + return(0); + + // loop over notarisation vins and add transaction to coinbase. + // Commented prints here can be used to verify manually the pubkeys match. + for (int8_t n = 0; n < NotarisationNotaries.size(); n++) + { + uint8_t *ptr; + txNew.vout[n+1].scriptPubKey.resize(35); + ptr = (uint8_t *)&txNew.vout[n+1].scriptPubKey[0]; + ptr[0] = 33; + for (int8_t i=0; i<33; i++) + { + ptr[i+1] = notarypubkeys[NotarisationNotaries[n]][i]; + //fprintf(stderr,"%02x",ptr[i+1]); + } + ptr[34] = OP_CHECKSIG; + //fprintf(stderr," set notary %i PUBKEY33 into vout[%i] amount.%lu\n",NotarisationNotaries[n],n+1,AmountToPay); + txNew.vout[n+1].nValue = AmountToPay; + total += txNew.vout[n+1].nValue; + } + return(total); +} + +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries) +{ + uint8_t *script; int32_t scriptlen; + if ( notarypubkeys[0][0] == 0 ) + return false; + BOOST_FOREACH(const CTxIn& txin, vin) + { + uint256 hash; CTransaction tx1; + if ( GetTransaction(txin.prevout.hash,tx1,hash,false) ) + { + for (int8_t i = 0; i < numNN; i++) + { + script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0]; + scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size(); + if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 ) + NotarisationNotaries.push_back(i); + } + } else return false; + } + return true; +} + +uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) +{ + std::vector NotarisationNotaries; uint8_t *script; int32_t scriptlen; + uint64_t timestamp = pblock->nTime; + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, timestamp); + if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) ) + return(0); + + // check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems) + std::set checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() ); + if ( checkdupes.size() != NotarisationNotaries.size() ) { + fprintf(stderr, "Possible notarisation is signed multiple times by same notary. It is invalid.\n"); + return(0); + } + const CChainParams& chainparams = Params(); + const Consensus::Params &consensusParams = chainparams.GetConsensus(); + uint64_t totalsats = 0; + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, height); + if ( pblock->vtx[1].vout.size() == 2 && pblock->vtx[1].vout[1].nValue == 0 ) + { + // Get the OP_RETURN for the notarisation + uint8_t *script = (uint8_t *)&pblock->vtx[1].vout[1].scriptPubKey[0]; + int32_t scriptlen = (int32_t)pblock->vtx[1].vout[1].scriptPubKey.size(); + if ( script[0] == OP_RETURN ) + { + // Create the coinbase tx again, using the extracted data, this is the same function the miner uses, with the same data. + // This allows us to know exactly that the coinbase is correct. + totalsats = komodo_notarypay(txNew, NotarisationNotaries, pblock->nTime, height, script, scriptlen); + } + else + { + fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen); + return(0); + } + } else return(0); + + // if notarypay fails, because the notarisation is not valid, exit now as txNew was not created. + // This should never happen, as the notarisation is checked before this function is called. + if ( totalsats == 0 ) + { + fprintf(stderr, "notary pay returned 0!\n"); + return(0); + } + + int8_t n = 0, i = 0, matches = 0; + uint64_t total = 0, AmountToPay = 0; + + // get the pay amount from the created tx. + AmountToPay = txNew.vout[1].nValue; + + // Check the created coinbase pays the correct notaries. + BOOST_FOREACH(const CTxOut& txout, pblock->vtx[0].vout) + { + // skip the coinbase paid to the miner. + if ( n == 0 ) + { + n++; + continue; + } + // Check the pubkeys match the pubkeys in the notarisation. + script = (uint8_t *)&txout.scriptPubKey[0]; + scriptlen = (int32_t)txout.scriptPubKey.size(); + if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[NotarisationNotaries[n-1]],33) == 0 ) + { + // check the value is correct + if ( pblock->vtx[0].vout[n].nValue == AmountToPay ) + { + matches++; + total += txout.nValue; + //fprintf(stderr, "MATCHED AmountPaid.%lu notaryid.%i\n",AmountToPay,NotarisationNotaries[n-1]); + } + else fprintf(stderr, "NOT MATCHED AmountPaid.%llu AmountToPay.%llu notaryid.%i\n", (long long)pblock->vtx[0].vout[n].nValue, (long long)AmountToPay, NotarisationNotaries[n-1]); + } + n++; + } + if ( matches != 0 && matches == NotarisationNotaries.size() && totalsats == total ) + { + //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() < KOMODO_EARLYTXID_HEIGHT ) + { + 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() < KOMODO_EARLYTXID_HEIGHT ) + { + fprintf(stderr, "Cannot fetch -earlytxid before block %d.\n",KOMODO_EARLYTXID_HEIGHT); + 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() < KOMODO_EARLYTXID_HEIGHT ) + { + 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; static bool didinit = false; + if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) + { + checktoshis = komodo_commission(pblock,height); + if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 ) + { + //fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN); + return(-1); + } + else if ( checktoshis != 0 ) + { + script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0]; + scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size(); + if ( 0 ) + { + int32_t i; + for (i=0; ivtx[0].vout[1].nValue/COIN); + } + if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + static bool didinit = false; + if ( !didinit && height > KOMODO_EARLYTXID_HEIGHT && 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()); + if ( memcmp(scripthex,script,scriptlen) == 0 ) + matched = scriptlen; + } + } + else if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) == 0 ) + matched = 35; + else if ( scriptlen == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG && memcmp(script+3,ASSETCHAINS_OVERRIDE_PUBKEYHASH,20) == 0 ) + matched = 25; + if ( matched == 0 ) + { + if ( 0 && ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + int32_t i; + for (i=0; ivtx[0].vout[1].nValue != checktoshis ) + { + fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue)); + return(-1); + } + } + } + return(checktoshis); +} + +bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; + +int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,int32_t height) +{ + uint256 hash,merkleroot; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,scriptlen,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; + if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" ) + KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; + if ( !CheckEquihashSolution(pblock, Params()) ) + { + fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height); + return(-1); + } + hash = pblock->GetHash(); + bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); + bhash = UintToArith256(hash); + possible = komodo_block2pubkey33(pubkey33,pblock); + if ( height == 0 ) + { + if ( slowflag != 0 ) + { + fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget); + return(0); + } + BlockMap::const_iterator it = mapBlockIndex.find(pblock->hashPrevBlock); + if ( it != mapBlockIndex.end() && (pprev= it->second) != 0 ) + height = pprev->GetHeight() + 1; + if ( height == 0 ) + return(0); + } + //if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) + // bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime); + if ( ASSETCHAINS_LWMAPOS != 0 && bhash > bnTarget ) + { + // if proof of stake is active, check if this is a valid PoS block before we fail + if (verusCheckPOSBlock(slowflag, pblock, height)) + { + return(0); + } + } + if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget ) + { + failed = 1; + if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case + { + if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 ) + { + for (i=0; i= 2 ) // must PoS or have at least 16x better PoW + { + CBlockIndex *pindex; + BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); + pindex = it != mapBlockIndex.end() ? it->second : NULL; + int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); + if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) + { + if ( slowflag == 0 || height <= 100 ) // need all past 100 blocks to calculate PoW target + return(0); + if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 + return(-1); + else + { + bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); + if ( bhash > bnTarget ) + { + for (i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]); + fprintf(stderr," > "); + for (i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED); + return(-1); + } + else + { + if ( newStakerActive != 0 ) + { + // PoW fake blocks will be rejected here. If a staking tx is included in a block that meets PoW min diff after block 100, then this will reject it. + if ( pblock->vtx.size() > 1 && pblock->vtx[pblock->vtx.size()-1].vout.size() == 2 && DecodeStakingOpRet(pblock->vtx[pblock->vtx.size()-1].vout[1].scriptPubKey, merkleroot) != 0 ) + { + fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL,height,bhash.GetCompact(),bnTarget.GetCompact()); + return(-1); + } + // set the pindex->segid as this is now fully validated to be a PoW block. + if ( pindex != 0 ) + { + pindex->segid = -1; + //fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); + } + } + failed = 0; + } + } + } + else if ( is_PoSblock < 0 ) + { + fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); + return(-1); + } + else + { + if ( slowflag != 0 && newStakerActive != 0 ) + { + int8_t segid = -2; + // the value passed to stakeTxValue, is the blockreward + the valuein-valueout(txfee) of the last tx in the block. + // the coinbase must pay the fees from the last transaction and the block reward at a minimum. + if ( pblock->vtx.size() < 1 || pblock->vtx[0].vout.size() < 1 ) + { + fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); + return(-1); + } + else if ( pblock->vtx[0].vout[0].nValue < stakeTxValue ) + { + fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); + return(-1); + } + // set the pindex->segid as this is now fully validated to be a PoS block. + char voutaddr[64]; CTxDestination voutaddress; + if ( ExtractDestination(pblock->vtx.back().vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + segid = komodo_segid32(voutaddr) & 0x3f; + } + if ( pindex != 0 && segid >= 0 ) + { + pindex->segid = segid; + //fprintf(stderr,"PoS block set segid.%d <- %d\n",height,pindex->segid); + } + } + failed = 0; + } + } + if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) + { + if ( height == 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]; + scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size(); + if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) + { + decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + if ( memcmp(scripthex,script,scriptlen) != 0 ) + return(-1); + } else return(-1); + } + 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(); + if ( scriptlen != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + return(-1); + } + } + else + { + if ( komodo_checkcommission(pblock,height) < 0 ) + return(-1); + } + } + // Consensus rule to force miners to mine the notary coinbase payment happens in ConnectBlock + // the default daemon miner, checks the actual vins so the only way this will fail, is if someone changes the miner, + // and then creates txs to the crypto address meeting min sigs and puts it in tx position 1. + // If they go through this effort, the block will still fail at connect block, and will be auto purged by the temp file fix. + if ( failed == 0 && ASSETCHAINS_NOTARY_PAY[0] != 0 && pblock->vtx.size() > 1 ) + { + // We check the full validation in ConnectBlock directly to get the amount for coinbase. So just approx here. + if ( slowflag == 0 && pblock->vtx[0].vout.size() > 1 ) + { + // Check the notarisation tx is to the crypto address. + if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 ) + { + fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); + return(-1); + } + // Check min sigs. + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, pblock->nTime); + if ( pblock->vtx[1].vin.size() < numSN/5 ) + { + fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size()); + return(-1); + } + } + } + +//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed); + if ( failed != 0 && possible == 0 && notaryid < 0 ) + return(-1); + else return(0); +} + +int32_t komodo_acpublic(uint32_t tiptime) +{ + int32_t acpublic = ASSETCHAINS_PUBLIC; CBlockIndex *pindex; + if ( acpublic == 0 ) + { + if ( tiptime == 0 ) + { + if ( (pindex= chainActive.LastTip()) != 0 ) + tiptime = pindex->nTime; + } + if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE ) + acpublic = 1; + } + return(acpublic); +} + +int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock) +{ + CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0,sproutfunds=0; + n = pblock->vtx.size(); + for (i=0; ivtx[i]; + if ( (m= tx.vin.size()) > 0 ) + { + for (j=0; j= vintx.vout.size() ) + { + fprintf(stderr,"ERROR: %s/v%d cant find\n",txid.ToString().c_str(),vout); + return(0); + } + vinsum += vintx.vout[vout].nValue; + } + } + if ( (m= tx.vout.size()) > 0 ) + { + for (j=0; j %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str()); + } + script = (uint8_t *)&tx.vout[j].scriptPubKey[0]; + if ( script == 0 || script[0] != 0x6a ) + { + if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 ) + voutsum += tx.vout[j].nValue; + } + } + BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) + { + zfunds -= joinsplit.vpub_new; + zfunds += joinsplit.vpub_old; + sproutfunds -= joinsplit.vpub_new; + sproutfunds += joinsplit.vpub_old; + } + zfunds -= tx.valueBalance; + } + *zfundsp = zfunds; + *sproutfundsp = sproutfunds; + if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times + return(3 * SATOSHIDEN); + //if ( voutsum-vinsum+zfunds > 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 ) + //. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds)); + return(voutsum - vinsum); +} + +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) +{ + CBlockIndex *pindex; CBlock block; int64_t zfunds=0,sproutfunds=0,supply = 0; + //fprintf(stderr,"coinsupply %d\n",height); + *zfundsp = *sproutfundsp = 0; + if ( (pindex= komodo_chainactive(height)) != 0 ) + { + while ( pindex != 0 && pindex->GetHeight() > 0 ) + { + if ( pindex->newcoins == 0 && pindex->zfunds == 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + pindex->newcoins = komodo_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block); + else + { + fprintf(stderr,"error loading block.%d\n",pindex->GetHeight()); + return(0); + } + } + supply += pindex->newcoins; + zfunds += pindex->zfunds; + sproutfunds += pindex->sproutfunds; + //printf("start ht.%d new %.8f -> supply %.8f zfunds %.8f -> %.8f\n",pindex->GetHeight(),dstr(pindex->newcoins),dstr(supply),dstr(pindex->zfunds),dstr(zfunds)); + pindex = pindex->pprev; + } + } + *zfundsp = zfunds; + *sproutfundsp = sproutfunds; + return(supply); +} + +struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) +{ + uint256 hash; uint32_t segid32; struct komodo_staking *kp; + segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); + if ( *numkp >= *maxkp ) + { + *maxkp += 1000; + array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); + //fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array); + } + kp = &array[(*numkp)++]; + //fprintf(stderr,"kp.%p num.%d\n",kp,*numkp); + memset(kp,0,sizeof(*kp)); + strcpy(kp->address,address); + kp->txid = txid; + kp->vout = vout; + kp->hashval = UintToArith256(hash); + kp->txtime = txtime; + kp->segid32 = segid32; + kp->nValue = nValue; + kp->scriptPubKey = pk; + return(array); +} + +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot) +{ + static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; + int32_t PoSperc = 0, newStakerActive; + std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + uint64_t cbPerc = *utxovaluep, tocoinbase = 0; + if (!EnsureWalletIsAvailable(0)) + return 0; + + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + assert(pwalletMain != NULL); + *utxovaluep = 0; + memset(utxotxidp,0,sizeof(*utxotxidp)); + memset(utxovoutp,0,sizeof(*utxovoutp)); + memset(utxosig,0,72); + if ( (tipindex= chainActive.Tip()) == 0 ) + return(0); + nHeight = tipindex->GetHeight() + 1; + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + if ( *blocktimep < tipindex->nTime+60 ) + *blocktimep = tipindex->nTime+60; + komodo_segids(hashbuf,nHeight-101,100); + // this was for VerusHash PoS64 + //tmpTarget = komodo_PoWtarget(&PoSperc,bnTarget,nHeight,ASSETCHAINS_STAKED); + bool resetstaker = false; + if ( array != 0 ) + { + LOCK(cs_main); + CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; + CBlock block; CTxDestination addressout; + if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) + { + resetstaker = true; + fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",ASSETCHAINS_SYMBOL,nHeight); + } + } + + if ( resetstaker || array == 0 || time(NULL) > lasttime+600 ) + { + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + if ( array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + BOOST_FOREACH(const COutput& out, vecOutputs) + { + if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) + { + fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),counter); + return(0); + } + counter++; + if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) + { + //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); + continue; + } + CAmount nValue = out.tx->vout[out.i].nValue; + if ( nValue < COIN || !out.fSpendable ) + continue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + if ( ExtractDestination(pk,address) != 0 ) + { + if ( IsMine(*pwalletMain,address) == 0 ) + continue; + if ( myGetTransaction(out.tx->GetHash(),tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); + //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); + } + } + } + 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); + } + block_from_future_rejecttime = (uint32_t)GetTime() + ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX; + for (i=winners=0; iGetHeight()+1 > nHeight ) + { + fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),i); + return(0); + } + kp = &array[i]; + eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc); + if ( eligible > 0 ) + { + besttime = 0; + if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc) ) + { + // have elegible utxo to stake with. + if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) + { + // 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; + } + /*if ( eligible < block_from_future_rejecttime ) + { + // better to scan all and choose earliest! + fprintf(stderr, "block_from_future_rejecttime.%u vs eligible.%u \n", block_from_future_rejecttime, eligible); + break; + } */ + } + } + } + if ( numkp < 500 && array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + if ( earliest != 0 ) + { + bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + const CKeyStore& keystore = *pwalletMain; + txNew.vin.resize(1); + txNew.vout.resize(1); + txfee = 0; + for (i=0; i<32; i++) + ((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; + txNew.vout[0].nValue = *utxovaluep - txfee; + txNew.nLockTime = earliest; + txNew.nExpiryHeight = nHeight; + if ( (newStakerActive= komodo_newStakerActive(nHeight,earliest)) != 0 ) + { + if ( cbPerc > 0 && cbPerc <= 100 ) + { + tocoinbase = txNew.vout[0].nValue*cbPerc/100; + txNew.vout[0].nValue -= tocoinbase; + } + txNew.vout.resize(2); + txNew.vout[1].scriptPubKey = EncodeStakingOpRet(merkleroot); + txNew.vout[1].nValue = 0; + } + CTransaction txNewConst(txNew); + signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); + UpdateTransaction(txNew,0,sigdata); + ptr = (uint8_t *)&sigdata.scriptSig[0]; + siglen = sigdata.scriptSig.size(); + for (i=0; i @@ -31,7 +31,6 @@ 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); uint32_t komodo_heightstamp(int32_t height); @@ -52,36 +51,9 @@ struct return_string { char *ptr; size_t len; }; * ************************************************************************/ -void init_string(struct return_string *s) -{ - s->len = 0; - s->ptr = (char *)calloc(1,s->len+1); - if ( s->ptr == NULL ) - { - fprintf(stderr,"init_string malloc() failed\n"); - StartShutdown(); - } - s->ptr[0] = '\0'; -} - -int tx_height( const uint256 &hash ){ - int nHeight = 0; - CTransaction tx; - uint256 hashBlock; - if (!GetTransaction(hash, tx, hashBlock, true)) { - fprintf(stderr,"tx hash %s does not exist!\n", hash.ToString().c_str() ); - } - - BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); - if (it != mapBlockIndex.end()) { - nHeight = it->second->GetHeight(); - //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); - } else { - // Unconfirmed xtns - //fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); - } - return nHeight; -} +void init_string(struct return_string *s); + +int tx_height( const uint256 &hash ); /************************************************************************ @@ -90,20 +62,7 @@ int tx_height( const uint256 &hash ){ * ************************************************************************/ -size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s) -{ - size_t new_len = s->len + size*nmemb; - s->ptr = (char *)realloc(s->ptr,new_len+1); - if ( s->ptr == NULL ) - { - fprintf(stderr, "accumulate realloc() failed\n"); - StartShutdown(); - } - memcpy(s->ptr+s->len,ptr,size*nmemb); - s->ptr[new_len] = '\0'; - s->len = new_len; - return(size * nmemb); -} +size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s); /************************************************************************ * @@ -120,49 +79,7 @@ size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string * * ************************************************************************/ -char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params) -{ - long i,j,len; char *retstr = 0; cJSON *json,*result,*error; - //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); - if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 ) - { - if ( strcmp(command,"signrawtransaction") != 0 ) - printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); - return(rpcstr); - } - json = cJSON_Parse(rpcstr); - if ( json == 0 ) - { - printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); - free(rpcstr); - return(0); - } - result = cJSON_GetObjectItem(json,"result"); - error = cJSON_GetObjectItem(json,"error"); - if ( error != 0 && result != 0 ) - { - if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) - { - retstr = cJSON_Print(result); - len = strlen(retstr); - if ( retstr[0] == '"' && retstr[len-1] == '"' ) - { - for (i=1,j=0; itype&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) - { - if ( strcmp(command,"signrawtransaction") != 0 ) - printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr); - } - free(rpcstr); - } else retstr = rpcstr; - free_json(json); - //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); - return(retstr); -} +char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params); #endif /************************************************************************ @@ -171,1142 +88,91 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * * ************************************************************************/ -char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) -{ - static int didinit,count,count2; static double elapsedsum,elapsedsum2; - struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; - char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; - if ( didinit == 0 ) - { - didinit = 1; - curl_global_init(CURL_GLOBAL_ALL); //init the curl session - } - numretries = 0; - if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) - specialcase = 1; - else specialcase = 0; - if ( url[0] == 0 ) - strcpy(url,"http://127.0.0.1:7876/nxt"); - if ( specialcase != 0 && 0 ) - printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); -try_again: - if ( retstrp != 0 ) - *retstrp = 0; - starttime = OS_milliseconds(); - curl_handle = curl_easy_init(); - init_string(&s); - headers = curl_slist_append(0,"Expect:"); - - curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); - curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl_handle,CURLOPT_URL, url); - curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function - curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback - curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash - curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback - //curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - //curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2); - - if ( strncmp(url,"https",5) == 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); - databuf = 0; - if ( params != 0 ) - { - if ( command != 0 && specialcase == 0 ) - { - len = strlen(params); - if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) { - bracket0 = bracket1 = (char *)""; - } - else - { - bracket0 = (char *)"["; - bracket1 = (char *)"]"; - } - - databuf = (char *)malloc(256 + strlen(command) + strlen(params)); - sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); - //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); - // - } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params); - curl_easy_setopt(curl_handle,CURLOPT_POST,1L); - if ( databuf != 0 ) - curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf); - else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params); - } - //laststart = milliseconds(); - res = curl_easy_perform(curl_handle); - curl_slist_free_all(headers); - curl_easy_cleanup(curl_handle); - if ( databuf != 0 ) // clean up temporary buffer - { - free(databuf); - databuf = 0; - } - if ( res != CURLE_OK ) - { - numretries++; - if ( specialcase != 0 ) - { - fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); - free(s.ptr); - return(0); - } - else if ( numretries >= 1 ) - { - fprintf(stderr,"Maximum number of retries exceeded!\n"); - free(s.ptr); - return(0); - } - if ( (rand() % 1000) == 0 ) - printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); - free(s.ptr); - sleep((1< (%s)\n",params,s.ptr); - count2++; - elapsedsum2 += (OS_milliseconds() - starttime); - if ( (count2 % 10000) == 0) - printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command); - return(s.ptr); - } - } - printf("bitcoind_RPC: impossible case\n"); - free(s.ptr); - return(0); -} - -static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data) -{ - size_t realsize = (size * nmemb); - struct MemoryStruct *mem = (struct MemoryStruct *)data; - mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); - if ( mem->memory != 0 ) - { - if ( ptr != 0 ) - memcpy(&(mem->memory[mem->size]),ptr,realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - } - //printf("got %d bytes\n",(int32_t)(size*nmemb)); - return(realsize); -} - -char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) -{ - struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; - if ( (cHandle= *cHandlep) == NULL ) - *cHandlep = cHandle = curl_easy_init(); - else curl_easy_reset(cHandle); - //#ifdef DEBUG - //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); - //#endif - curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); - curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0); - //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1); - curl_easy_setopt(cHandle,CURLOPT_URL,url); - curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10); - if ( userpass != 0 && userpass[0] != 0 ) - curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); - if ( postfields != 0 && postfields[0] != 0 ) - { - curl_easy_setopt(cHandle,CURLOPT_POST,1); - curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); - } - if ( hdr0 != NULL && hdr0[0] != 0 ) - { - //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:""); - headers = curl_slist_append(headers,hdr0); - if ( hdr1 != 0 && hdr1[0] != 0 ) - headers = curl_slist_append(headers,hdr1); - if ( hdr2 != 0 && hdr2[0] != 0 ) - headers = curl_slist_append(headers,hdr2); - if ( hdr3 != 0 && hdr3[0] != 0 ) - headers = curl_slist_append(headers,hdr3); - } //headers = curl_slist_append(0,"Expect:"); - if ( headers != 0 ) - curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers); - //res = curl_easy_perform(cHandle); - memset(&chunk,0,sizeof(chunk)); - curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); - curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk); - curl_easy_perform(cHandle); - curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code); - if ( headers != 0 ) - curl_slist_free_all(headers); - if ( code != 200 ) - printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory); - return(chunk.memory); -} - -char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - //static void *cHandle; - char url[512],*retstr=0,*retstr2=0,postdata[8192]; - if ( params == 0 || params[0] == 0 ) - params = (char *)"[]"; - if ( strlen(params) < sizeof(postdata)-128 ) - { - sprintf(url,(char *)"http://127.0.0.1:%u",port); - sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); - // printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); - retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); - //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); - } - // fprintf(stderr, "RPC RESP: %s\n", retstr2); - return(retstr2); -} - -int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp) -{ - char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0; - params[0] = 0; - *kmdnotarized_heightp = 0; - if ( strcmp(dest,"KMD") == 0 ) - { - port = KMD_PORT; - userpass = KMDUSERPASS; - } - else if ( strcmp(dest,"BTC") == 0 ) // this is no longer strictly BTC; depends on -notary= path - { - port = DEST_PORT; - userpass = BTCUSERPASS; - } - else return(0); - if ( userpass[0] != 0 ) - { - if ( strcmp("BTC",dest) != 0 ) - { - if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) - { - //printf("(%s)\n",jsonstr); - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (item= jobj(json,(char *)"result")) != 0 ) - { - height = jint(item,(char *)"blocks"); - *kmdnotarized_heightp = height; - } - free_json(json); - } - free(jsonstr); - } - } else { - if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getblockchaininfo",params,port)) != 0 ) - { - //printf("(%s)\n",jsonstr); - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (item= jobj(json,(char *)"result")) != 0 ) - { - height = jint(item,(char *)"blocks"); - *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height; - } - free_json(json); - } - free(jsonstr); - } - } - sprintf(params,"[\"%s\", 1]",txidstr); - if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) - { - //printf("(%s)\n",jsonstr); - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (item= jobj(json,(char *)"result")) != 0 ) - { - txid_confirmations = jint(item,(char *)"rawconfirmations"); - if ( txid_confirmations > 0 && height > txid_confirmations ) - txid_height = height - txid_confirmations; - else txid_height = height; - //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height); - } - free_json(json); - } - free(jsonstr); - } - } - return(txid_height); -} - -int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH) -{ - int32_t i; uint256 hash; char params[256]; - for (i=0; i<32; i++) - ((uint8_t *)&hash)[i] = script[2+i]; - if ( hash == NOTARIZED_HASH ) - return(1); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]); - printf(" notarized, "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height); - return(-1); -} - -void komodo_reconsiderblock(uint256 blockhash) -{ - char params[256],*jsonstr,*hexstr; - sprintf(params,"[\"%s\"]",blockhash.ToString().c_str()); - if ( (jsonstr= komodo_issuemethod(ASSETCHAINS_USERPASS,(char *)"reconsiderblock",params,ASSETCHAINS_RPCPORT)) != 0 ) - { - //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> (%s)\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT,jsonstr); - free(jsonstr); - } - //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> NULL\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT); -} - -int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) -{ - char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; - script = _script; - /*params[0] = '['; - params[1] = '"'; - for (i=0; i<32; i++) - sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); - strcat(params,"\", 1]");*/ - sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); - if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) - return(0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); - if ( strcmp(dest,"KMD") == 0 ) - { - if ( KMDUSERPASS[0] != 0 ) - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); - //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); - } - }//else jsonstr = _dex_getrawtransaction(); - else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok - } - else if ( strcmp(dest,"BTC") == 0 ) - { - if ( BTCUSERPASS[0] != 0 ) - { - jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,DEST_PORT); - } - //else jsonstr = _dex_getrawtransaction(); - else return(0); - } - else - { - printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); - return(-1); - } - if ( jsonstr != 0 ) - { - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != 0 ) - { - vout = jitem(vouts,n-1); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("vout.(%s)\n",jprint(vout,0)); - if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) - { - if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) - { - //printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str()); - len = strlen(hexstr) >> 1; - decode_hex(script,len,hexstr); - if ( script[1] == 0x4c ) - { - script++; - len--; - } - else if ( script[1] == 0x4d ) - { - script += 2; - len -= 2; - } - retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH); - } - } - } - free_json(txjson); - } - free(jsonstr); - } - return(retval); -} - -CScript komodo_makeopret(CBlock *pblock, bool fNew) -{ - std::vector vLeaves; - vLeaves.push_back(pblock->hashPrevBlock); - for (int32_t i = 0; i < pblock->vtx.size()-(fNew ? 0 : 1); i++) - vLeaves.push_back(pblock->vtx[i].GetHash()); - uint256 merkleroot = GetMerkleRoot(vLeaves); - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << merkleroot); - return(opret); -} - -/*uint256 komodo_getblockhash(int32_t height) - { - uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; - memset(&hash,0,sizeof(hash)); - sprintf(params,"[%d]",height); - if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 ) - { - if ( (result= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (hexstr= jstr(result,(char *)"result")) != 0 ) - { - if ( is_hexstr(hexstr,0) == 64 ) - { - decode_hex(revbuf,32,hexstr); - for (i=0; i<32; i++) - ((uint8_t *)&hash)[i] = revbuf[31-i]; - } - } - free_json(result); - } - printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash); - free(jsonstr); - } - return(hash); - } - - uint256 _komodo_getblockhash(int32_t height);*/ - -uint64_t komodo_seed(int32_t height) -{ - uint64_t seed = 0; - /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds... - { - uint256 hash,zero; CBlockIndex *pindex; - memset(&hash,0,sizeof(hash)); - memset(&zero,0,sizeof(zero)); - if ( height > 10 ) - height -= 10; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - hash = _komodo_getblockhash(height); - if ( memcmp(&hash,&zero,sizeof(hash)) == 0 ) - hash = komodo_getblockhash(height); - int32_t i; - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" seed.%d\n",height); - seed = arith_uint256(hash.GetHex()).GetLow64(); - } - else*/ - { - seed = (height << 13) ^ (height << 2); - seed <<= 21; - seed |= (height & 0xffffffff); - seed ^= (seed << 17) ^ (seed << 1); - } - return(seed); -} - -uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) -{ - CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; - *valuep = 0; - if (!GetTransaction(hash, tx, -#ifndef KOMODO_ZCASH - Params().GetConsensus(), -#endif - hashBlock, true)) - { - //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - return(0); - } - numvouts = tx.vout.size(); - //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - if ( n < numvouts ) - { - *valuep = tx.vout[n].nValue; - opret = tx.vout[numvouts-1].scriptPubKey; - if (ExtractDestination(tx.vout[n].scriptPubKey, address)) - strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); - } - return(tx.nLockTime); -} - -CBlockIndex *komodo_getblockindex(uint256 hash) -{ - BlockMap::const_iterator it = mapBlockIndex.find(hash); - return((it != mapBlockIndex.end()) ? it->second : NULL); -} +char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params); -uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) -{ - CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0; - *valuep = 0; - if (!GetTransaction(hash, tx, -#ifndef KOMODO_ZCASH - Params().GetConsensus(), -#endif - hashBlock, true)) - { - //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - return(0); - } - if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) - txtime = pindex->nTime; - else txtime = tx.nLockTime; - //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - if ( n < tx.vout.size() ) - { - *valuep = tx.vout[n].nValue; - if (ExtractDestination(tx.vout[n].scriptPubKey, address)) - strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); - } - return(txtime); -} - -CScript EncodeStakingOpRet(uint256 merkleroot) -{ - CScript opret; uint8_t evalcode = 77; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << merkleroot); - return(opret); -} +static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data); -uint8_t DecodeStakingOpRet(CScript scriptPubKey, uint256 &merkleroot) -{ - std::vector vopret; uint8_t evalcode; - GetOpReturnData(scriptPubKey, vopret); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> evalcode; ss >> merkleroot) != 0 && evalcode == 77 ) - { - //fprintf(stderr, "evalcode.%i merkleroot.%s\n",evalcode, merkleroot.GetHex().c_str() ); - return(1); - } - return(0); -} - -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp) -{ - if ( timestamp > nStakedDecemberHardforkTimestamp || komodo_heightstamp(height) > nStakedDecemberHardforkTimestamp ) //December 2019 hardfork - return(1); - else return(0); -} +char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); -int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp) -{ - return((ASSETCHAINS_MARMARA!=0 || komodo_newStakerActive(height, timestamp) == 1)); -} +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -bool komodo_checkopret(CBlock *pblock, CScript &merkleroot) -{ - merkleroot = pblock->vtx.back().vout.back().scriptPubKey; - return(merkleroot.IsOpReturn() && merkleroot == komodo_makeopret(pblock, false)); -} +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -bool komodo_hardfork_active(uint32_t time) -{ - return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork -} +int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH); -bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx); +void komodo_reconsiderblock(uint256 blockhash); -uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey) -{ - std::vector vLeaves; - // rereate coinbase tx - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = fNew ? (CScript() << nHeight << CScriptNum(1)) + COINBASE_FLAGS : pblock->vtx[0].vin[0].scriptSig; - txNew.vout.resize(1); - txNew.vout[0].scriptPubKey = scriptPubKey; - txNew.vout[0].nValue = 0; - txNew.nExpiryHeight = 0; - txNew.nLockTime = 0; - //fprintf(stderr, "validation: coinbasetx.%s\n", EncodeHexTx(txNew).c_str()); - //fprintf(stderr, "txnew.%s\n", txNew.GetHash().ToString().c_str()); - vLeaves.push_back(txNew.GetHash()); - vLeaves.push_back(prevBlockHash); - for (int32_t i = 1; i < pblock->vtx.size()-(fNew ? 0 : 1); i++) - vLeaves.push_back(pblock->vtx[i].GetHash()); - return GetMerkleRoot(vLeaves); -} - -int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) -{ - int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid, merkleroot; CScript opret; - if ( ASSETCHAINS_STAKED != 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+komodo_hasOpRet(height,pblock->nTime) ) - { - txid = pblock->vtx[n-1].vin[0].prevout.hash; - vout = pblock->vtx[n-1].vin[0].prevout.n; - txtime = komodo_txtime(opret,&value,txid,vout,destaddr); - if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) - { - if ( addressout != 0 ) *addressout = voutaddress; - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - //fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr); - if ( komodo_newStakerActive(height, pblock->nTime) != 0 ) - { - if ( DecodeStakingOpRet(pblock->vtx[n-1].vout[1].scriptPubKey, merkleroot) != 0 && komodo_calcmerkleroot(pblock, pblock->hashPrevBlock, height, false, pblock->vtx[0].vout[0].scriptPubKey) == merkleroot ) - { - return(1); - } - } - else - { - if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 ) - { - if ( ASSETCHAINS_MARMARA == 0 ) - return(1); - else - { - if ( pblock->vtx[n-1].vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= pblock->vtx[n-1].vout.size()) == 2 ) - { - //fprintf(stderr,"validate proper %s %s signature and unlockht preservation\n",voutaddr,destaddr); - return(MarmaraPoScheck(destaddr,opret,pblock->vtx[n-1])); - } - else - { - fprintf(stderr,"reject ht.%d PoS block\n",height); - return(strcmp(ASSETCHAINS_SYMBOL,"MTST2") == 0); // allow until MTST3 - } - } - } - } - } - } - } - return(0); -} - -void komodo_disconnect(CBlockIndex *pindex,CBlock& block) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - //fprintf(stderr,"disconnect ht.%d\n",pindex->GetHeight()); - komodo_init(pindex->GetHeight()); - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - //sp->rewinding = pindex->GetHeight(); - //fprintf(stderr,"-%d ",pindex->GetHeight()); - } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->GetHeight(),ASSETCHAINS_SYMBOL); -} - -int32_t komodo_is_notarytx(const CTransaction& tx) -{ - uint8_t *ptr; static uint8_t crypto777[33]; - if ( tx.vout.size() > 0 ) - { - ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0]; - if ( ptr != 0 ) - { - if ( crypto777[0] == 0 ) - decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); - if ( memcmp(ptr+1,crypto777,33) == 0 ) - { - //printf("found notarytx\n"); - return(1); - } - } - } - return(0); -} - -int32_t komodo_block2height(CBlock *block) -{ - static uint32_t match,mismatch; - int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex = NULL; - BlockMap::const_iterator it = mapBlockIndex.find(block->GetHash()); - if ( it != mapBlockIndex.end() && (pindex = it->second) != 0 ) - { - height2 = (int32_t)pindex->GetHeight(); - if ( height2 >= 0 ) - return(height2); - } - if ( pindex && block != 0 && block->vtx[0].vin.size() > 0 ) - { - ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0]; - if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 ) - { - //for (i=0; i<6; i++) - // printf("%02x",ptr[i]); - n = ptr[0]; - for (i=0; ivtx[0].vin[0].scriptSig.size(),height); - } - //komodo_init(height); - } - if ( height != height2 ) - { - //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); - mismatch++; - if ( height2 >= 0 ) - height = height2; - } else match++; - return(height); -} - -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) -{ - int32_t n; - if ( KOMODO_LOADINGBLOCKS == 0 ) - memset(pubkey33,0xff,33); - else memset(pubkey33,0,33); - if ( block->vtx[0].vout.size() > 0 ) - { - txnouttype whichType; - vector> vch = vector>(); - if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) - { - CPubKey pubKey(vch[0]); - if (pubKey.IsValid()) - { - memcpy(pubkey33,vch[0].data(),33); - return true; - } - else memset(pubkey33,0,33); - } - else memset(pubkey33,0,33); - } - return(0); -} - -int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) -{ - block.SetNull(); - // Open history file to read - CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION); - if (filein.IsNull()) - return(-1); - // Read block - try { filein >> block; } - catch (const std::exception& e) - { - fprintf(stderr,"readblockfromdisk err B\n"); - return(-1); - } - return(0); -} - -uint32_t komodo_chainactive_timestamp() -{ - if ( chainActive.LastTip() != 0 ) - return((uint32_t)chainActive.LastTip()->GetBlockTime()); - else return(0); -} +int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID); -CBlockIndex *komodo_chainactive(int32_t height) -{ - if ( chainActive.LastTip() != 0 ) - { - if ( height <= chainActive.LastTip()->GetHeight() ) - return(chainActive[height]); - // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->GetHeight()); - } - //fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height); - return(0); -} - -uint32_t komodo_heightstamp(int32_t height) -{ - CBlockIndex *ptr; - if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) - return(ptr->nTime); - //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); - return(0); -} - -/*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted -{ - int32_t i,num; uint8_t pubkeys[64][33]; CBlock block; - if ( pindex->didinit != 0 ) - return; - //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->GetHeight(),pindex->notaryid,height); - if ( pindex->didinit == 0 ) - { - pindex->notaryid = -1; - if ( KOMODO_LOADINGBLOCKS == 0 ) - memset(pindex->pubkey33,0xff,33); - else memset(pindex->pubkey33,0,33); - if ( komodo_blockload(block,pindex) == 0 ) - { - komodo_block2pubkey33(pindex->pubkey33,&block); - //for (i=0; i<33; i++) - // fprintf(stderr,"%02x",pindex->pubkey33[i]); - //fprintf(stderr," set pubkey at height %d/%d\n",pindex->GetHeight(),height); - //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 ) - // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0); - } // else fprintf(stderr,"error loading block at %d/%d",pindex->GetHeight(),height); - } - if ( pindex->didinit != 0 && pindex->GetHeight() >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->GetHeight(),(uint32_t)pindex->nTime)) > 0 ) - { - for (i=0; ipubkey33,33) == 0 ) - { - pindex->notaryid = i; - break; - } - } - if ( 0 && i == num ) - { - for (i=0; i<33; i++) - fprintf(stderr,"%02x",pindex->pubkey33[i]); - fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->GetHeight(),height); - } - } -}*/ - -void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) -{ - int32_t num,i; CBlock block; - memset(pubkey33,0,33); - if ( pindex != 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - komodo_block2pubkey33(pubkey33,&block); - } -} - -/*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33) -{ - int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33]; - if ( (pindex= chainActive[height]) != 0 ) - { - if ( pindex->didinit != 0 ) - { - if ( destpubkey33 != 0 ) - memcpy(destpubkey33,pindex->pubkey33,33); - return(pindex->notaryid); - } - komodo_index2pubkey33(pubkey33,pindex,height); - if ( destpubkey33 != 0 ) - memcpy(destpubkey33,pindex->pubkey33,33); - if ( pindex->didinit != 0 ) - return(pindex->notaryid); - timestamp = pindex->GetBlockTime(); - if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; inTime; - if ( komodo_blockload(block,pindex) == 0 ) - { - komodo_block2pubkey33(pubkeys[i],&block); - for (j=0; j= 0 && i > 0 && mids[i] == mids[0] ) - duplicate++; - } - } - if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) ) - return(1); - else return(0); -} - -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) -{ - int32_t i,j,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33]; - numnotaries = komodo_notaries(notarypubs33,height,0); - for (i=nonz=0; i= 82000 ) - { - if ( notaryid >= 0 ) - { - for (i=1; i<66; i++) - { - if ( mids[i] == notaryid ) - { - if ( height > 792000 ) - { - for (j=0; j<66; j++) - fprintf(stderr,"%d ",mids[j]); - fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i); - return(-1); - } else break; - } - } - if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 ) - { - if ( height > 807000 ) - return(-2); - } - return(1); - } else return(0); - } - else - { - if ( height >= 34000 && notaryid >= 0 ) - { - if ( height < 79693 ) - limit = 64; - else if ( height < 82000 ) - limit = 8; - else limit = 66; - for (i=1; i 225000 ) - return(-1); - } - } - //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit); - return(1); - } - } - return(0); -} - -int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) -{ - int32_t depth,notarized_ht; uint256 MoM,kmdtxid; - depth = komodo_MoMdata(¬arized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip); - memset(MoMp,0,sizeof(*MoMp)); - memset(kmdtxidp,0,sizeof(*kmdtxidp)); - *notarized_heightp = 0; - if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) - { - *MoMp = MoM; - *notarized_heightp = notarized_ht; - *kmdtxidp = kmdtxid; - } - return(depth); -} - -CBlockIndex *komodo_blockindex(uint256 hash) -{ - BlockMap::const_iterator it; CBlockIndex *pindex = 0; - if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() ) - pindex = it->second; - return(pindex); -} +CScript komodo_makeopret(CBlock *pblock, bool fNew); -int32_t komodo_blockheight(uint256 hash) -{ - BlockMap::const_iterator it; CBlockIndex *pindex = 0; - if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() ) - { - if ( (pindex= it->second) != 0 ) - return(pindex->GetHeight()); - } - 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; - if ( (pindex= chainActive.LastTip()) == 0 ) - return(-1); - notarized_height = komodo_notarizeddata(pindex->GetHeight(),¬arized_hash,¬arized_desttxid); - *notarized_heightp = notarized_height; - BlockMap::const_iterator it; - if ( notarized_height >= 0 && notarized_height <= pindex->GetHeight() && (it = mapBlockIndex.find(notarized_hash)) != mapBlockIndex.end() && (notary = it->second) != NULL ) - { - //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->GetHeight(),notarized_height,notarized_hash.ToString().c_str()); - if ( notary->GetHeight() == notarized_height ) // if notarized_hash not in chain, reorg - { - if ( nHeight < notarized_height ) - { - //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - return(-1); - } - else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) - { - fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - return(-1); - } - } //else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->GetHeight()); - } - //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) - // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->GetHeight()); - return(0); -} - -uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) -{ - LOCK(cs_main); - CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; - *txheighttimep = *txheightp = *tiptimep = 0; - *valuep = 0; - if ( !GetTransaction(hash,tx,hashBlock,true) ) - return(0); - uint32_t locktime = 0; - if ( n < tx.vout.size() ) - { - if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) - { - *valuep = tx.vout[n].nValue; - *txheightp = pindex->GetHeight(); - *txheighttimep = pindex->nTime; - if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 ) - *tiptimep = (uint32_t)tipindex->nTime; - locktime = tx.nLockTime; - //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); - } - } - return(locktime); -} - -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); - -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) -{ - uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; - if ( (pindex= chainActive[tipheight]) != 0 ) - tiptime = (uint32_t)pindex->nTime; - else fprintf(stderr,"cant find height[%d]\n",tipheight); - if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) - { - if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) - return(komodo_interest(*txheightp,value,*locktimep,tiptime)); - //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); - else fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); - } - return(0); -} - -int32_t komodo_nextheight() -{ - CBlockIndex *pindex; int32_t ht; - if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) - return(ht+1); - else return(komodo_longestchain() + 1); -} +uint64_t komodo_seed(int32_t height); -int32_t komodo_isrealtime(int32_t *kmdheightp) -{ - struct komodo_state *sp; CBlockIndex *pindex; - if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) - *kmdheightp = sp->CURRENT_HEIGHT; - else *kmdheightp = 0; - if ( (pindex= chainActive.LastTip()) != 0 && pindex->GetHeight() >= (int32_t)komodo_longestchain() ) - return(1); - else return(0); -} - -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) -{ - dispflag = 1; - if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) - { - if ( txheight > 246748 ) - { - if ( txheight < 247205 ) - cmptime -= 16000; - if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) - { - if ( tx.nLockTime != 1477258935 && dispflag != 0 ) - { - fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(uint32_t)tx.nLockTime,cmptime); - } - return(-1); - } - if ( 0 && dispflag != 0 ) - fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(int32_t)tx.nLockTime,cmptime); - } - } - return(0); -} +uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr); + +CBlockIndex *komodo_getblockindex(uint256 hash); + +uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr); + +CScript EncodeStakingOpRet(uint256 merkleroot); + +uint8_t DecodeStakingOpRet(CScript scriptPubKey, uint256 &merkleroot); + +int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); + +int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp); + +bool komodo_checkopret(CBlock *pblock, CScript &merkleroot); + +bool komodo_hardfork_active(uint32_t time); + +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); + +int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout); + +void komodo_disconnect(CBlockIndex *pindex,CBlock& block); + +int32_t komodo_is_notarytx(const CTransaction& tx); + +int32_t komodo_block2height(CBlock *block); + +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); + +int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); + +uint32_t komodo_chainactive_timestamp(); + +CBlockIndex *komodo_chainactive(int32_t height); + +uint32_t komodo_heightstamp(int32_t height); + +void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); + +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height); + +int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); + +int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],uint32_t blocktimes[66],int32_t height,uint8_t pubkey33[33],uint32_t blocktime); + +int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); + +CBlockIndex *komodo_blockindex(uint256 hash); + +int32_t komodo_blockheight(uint256 hash); + +uint32_t komodo_blocktime(uint256 hash); + +int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash); + +uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n); + +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_nextheight(); + +int32_t komodo_isrealtime(int32_t *kmdheightp); + +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag); /* komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on. @@ -1317,1313 +183,51 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_ PoS stake must be without txfee and in the last tx in the block at vout[0] */ -CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); +uint64_t komodo_commission(const CBlock *pblock,int32_t height); -uint64_t komodo_commission(const CBlock *pblock,int32_t height) -{ - static bool didinit = false,ishush3 = false; - // LABS fungible chains, cannot have any block reward! - if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) - return(0); - - if (!didinit) { - ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; - didinit = true; - } - - int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0; - if ( ASSETCHAINS_FOUNDERS != 0 ) - { - nSubsidy = GetBlockSubsidy(height,Params().GetConsensus()); - //fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION)); - commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN); - - if (ishush3) { - int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111; - // HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves. - // You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25 - // but to tell the AC params, I need to say "11% of 11.25" is 1.25 - // 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually - // Transition period of 128 blocks has BR=FR=0 - if (height < TRANSITION) { - commission = 0; - } else if (height < HALVING1) { - commission = starting_commission; - } else if (height < HALVING1+1*INTERVAL) { - commission = starting_commission / 2; - } else if (height < HALVING1+2*INTERVAL) { - commission = starting_commission / 4; - } else if (height < HALVING1+3*INTERVAL) { - commission = starting_commission / 8; - } else if (height < HALVING1+4*INTERVAL) { - commission = starting_commission / 16; - } else if (height < HALVING1+5*INTERVAL) { - commission = starting_commission / 32; - } else if (height < HALVING1+6*INTERVAL) { // Block 5380000 - // Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting - commission = starting_commission / 64; - } else if (height < HALVING1+7*INTERVAL) { - // Block reward will be zero before this is ever reached - commission = starting_commission / 128; // Block 6220000 - } - } - - if ( ASSETCHAINS_FOUNDERS > 1 ) - { - if ( (height % ASSETCHAINS_FOUNDERS) == 0 ) - { - if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) - commission = commission * ASSETCHAINS_FOUNDERS; - else - commission = ASSETCHAINS_FOUNDERS_REWARD; - } - else commission = 0; - } - } - else if ( pblock != 0 ) - { - txn_count = pblock->vtx.size(); - for (i=0; ivtx[i].vout.size(); - for (j=0; j 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) - break; - //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); - if ( i != 0 || j != 1 ) - total += pblock->vtx[i].vout[j].nValue; - if ( total > 1000000 * COIN ) - { - total = 1000000 * COIN; - break; - } - } - } - commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000; - //commission = ((total * ASSETCHAINS_COMMISSION) / COIN); - } - if ( commission < 10000 ) - commission = 0; - //fprintf(stderr,"-> %.8f\n",(double)commission/COIN); - return(commission); -} - -uint32_t komodo_segid32(char *coinaddr) -{ - bits256 addrhash; - vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr)); - return(addrhash.uints[0]); -} +uint32_t komodo_segid32(char *coinaddr); -int8_t komodo_segid(int32_t nocache,int32_t height) -{ - CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout,newStakerActive; uint256 txid,merkleroot; CScript opret; int8_t segid = -1; - if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) - { - if ( nocache == 0 && pindex->segid >= -1 ) - return(pindex->segid); - if ( komodo_blockload(block,pindex) == 0 ) - { - newStakerActive = komodo_newStakerActive(height, block.nTime); - txn_count = block.vtx.size(); - if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pindex->nTime) ) - { - txid = block.vtx[txn_count-1].vin[0].prevout.hash; - vout = block.vtx[txn_count-1].vin[0].prevout.n; - txtime = komodo_txtime(opret,&value,txid,vout,destaddr); - if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) - { - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - if ( newStakerActive == 1 && block.vtx[txn_count-1].vout.size() == 2 && DecodeStakingOpRet(block.vtx[txn_count-1].vout[1].scriptPubKey, merkleroot) != 0 ) - newStakerActive++; - if ( newStakerActive == 2 || (newStakerActive == 0 && strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value) ) - { - segid = komodo_segid32(voutaddr) & 0x3f; - //fprintf(stderr, "komodo_segid: ht.%i --> %i\n",height,pindex->segid); - } - } //else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); - } - } - // The new staker sets segid in komodo_checkPOW, this persists after restart by being saved in the blockindex for blocks past the HF timestamp, to keep backwards compatibility. - // PoW blocks cannot contain a staking tx. If segid has not yet been set, we can set it here accurately. - if ( pindex->segid == -2 ) - pindex->segid = segid; - } - return(segid); -} - -void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) -{ - static uint8_t prevhashbuf[100]; static int32_t prevheight; - int32_t i; - if ( height == prevheight && n == 100 ) - memcpy(hashbuf,prevhashbuf,100); - else - { - memset(hashbuf,0xff,n); - for (i=0; i 10 && (tipindex= komodo_chainactive(height - 1)) != 0 ) // disable offchain diffchange - { - diff = (nTime - tipindex->GetMedianTimePast()); - tipdiff = (nTime - tipindex->nTime); - if ( tipdiff > 13*ASSETCHAINS_BLOCKTIME ) - diff = tipdiff; - if ( diff >= 13 * ASSETCHAINS_BLOCKTIME && (height < 30 || tipdiff > 2*ASSETCHAINS_BLOCKTIME) ) - { - mult = diff - 12 * ASSETCHAINS_BLOCKTIME; - mult = (mult / ASSETCHAINS_BLOCKTIME) * ASSETCHAINS_BLOCKTIME + ASSETCHAINS_BLOCKTIME / 2; - origtarget = bnTarget; - bnTarget = bnTarget * arith_uint256(mult * mult); - easy.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - if ( bnTarget < origtarget || bnTarget > easy ) // deal with overflow - { - bnTarget = easy; - fprintf(stderr,"tipdiff.%d diff.%d height.%d miner overflowed mult.%lld, set to mindiff\n",tipdiff,diff,height,(long long)mult); - } else fprintf(stderr,"tipdiff.%d diff.%d height.%d miner elapsed %d, adjust by factor of %lld\n",tipdiff,diff,height,diff,(long long)mult); - } //else fprintf(stderr,"height.%d tipdiff.%d diff %d, vs %d\n",height,tipdiff,diff,13*ASSETCHAINS_BLOCKTIME); - } else fprintf(stderr,"adaptive cant find height.%d\n",height); - return(bnTarget); -} - -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive) -{ - int32_t oldflag = 0,dispflag = 0; - CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val; - *percPoSp = percPoS = 0; - - if ( newStakerActive == 0 && height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) - return(target); - - sum = arith_uint256(0); - ave = sum; - if ( newStakerActive != 0 ) - { - easydiff.SetCompact(ASSETCHAINS_STAKED_MIN_POW_DIFF,&fNegative,&fOverflow); - if ( height <= 10 ) - return(easydiff); - } - else - easydiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); - for (i=n=m=0; i<100; i++) - { - ht = height - 100 + i; - if ( ht <= 1 ) - continue; - if ( (pindex= komodo_chainactive(ht)) != 0 ) - { - if ( komodo_segid(0,ht) >= 0 ) - { - n++; - percPoS++; - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"0"); - } - else - { - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"1"); - sum += UintToArith256(pindex->GetBlockHash()); - m++; - } - } //else fprintf(stderr, "pindex returned null ht.%i\n",ht); - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) - fprintf(stderr," %d, ",percPoS); - } - if ( m+n < 100 ) - { - // We do actual PoS % at the start. Requires coin distribution in first 10 blocks! - if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) - percPoS = (percPoS*100) / (m+n); - else - percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; - } - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); - *percPoSp = percPoS; - if ( m > 0 ) - { - ave = (sum / arith_uint256(m)); - if ( ave > target ) - ave = target; - } else ave = target; //easydiff; //else return(target); - if ( percPoS == 0 ) - percPoS = 1; - if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget - { - if ( oldflag != 0 ) - bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); - else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); - fprintf(stderr," increase diff -> "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," floor diff "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&target)[i]); - fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); - } - } - else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget - { - if ( oldflag != 0 ) - { - bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); - bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); - } - else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); - if ( bnTarget > easydiff ) - bnTarget = easydiff; - else if ( bnTarget < ave ) // overflow - { - bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); - if ( bnTarget < ave ) - bnTarget = ave; - } - if ( dispflag != 0 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); - fprintf(stderr," decrease diff -> "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," floor diff "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&target)[i]); - fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); - } - } - else - bnTarget = ave; // recent ave is perfect - if ( newStakerActive != 0 && bnTarget > easydiff ) - bnTarget = easydiff; - return(bnTarget); -} - -uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr,int32_t PoSperc) -{ - bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t segid,minage,i,iter=0; int64_t diff=0; uint32_t txtime,segid32,winner = 0 ; uint64_t value,coinage; - txtime = komodo_txtime2(&value,txid,vout,address); - if ( validateflag == 0 ) - { - //fprintf(stderr,"blocktime.%u -> ",blocktime); - if ( blocktime < prevtime+3 ) - blocktime = prevtime+3; - if ( blocktime < GetTime()-60 ) - blocktime = GetTime()+30; - //fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime); - } - if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 ) - { - //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime); - return(0); - } - if ( value < SATOSHIDEN ) - return(0); - value /= SATOSHIDEN; - mindiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); - ratio = (mindiff / bnTarget); - if ( (minage= nHeight*3) > 6000 ) // about 100 blocks - minage = 6000; - komodo_segids(hashbuf,nHeight-101,100); - segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); - segid = ((nHeight + segid32) & 0x3f); - for (iter=0; iter<600; iter++) - { - if ( blocktime+iter+segid*2 < txtime+minage ) - continue; - diff = (iter + blocktime - txtime - minage); - // Disable PoS64 on VerusHash, doesnt work properly. - if ( 0 ) // ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) - { - /*if ( PoSperc < ASSETCHAINS_STAKED ) - { - // Under PoS % target and we need to increase diff. - //fprintf(stderr, "PoS too low diff.%i changed to.",diff); - diff = diff * ( (ASSETCHAINS_STAKED - PoSperc + 1) * (ASSETCHAINS_STAKED - PoSperc + 1) * ( nHeight < 50 ? 1000 : 1)); - //fprintf(stderr, "%i \n",diff); - } - else */ - if ( PoSperc > ASSETCHAINS_STAKED ) - { - // Over PoS target need to lower diff. - //fprintf(stderr, "PoS too high diff.%i changed to.",diff); - diff = diff / ( (PoSperc - ASSETCHAINS_STAKED + 1) * (PoSperc - ASSETCHAINS_STAKED + 1) ); - //fprintf(stderr, "%i \n",diff); - } - } - if ( diff < 0 ) - diff = 60; - else if ( diff > 3600*24*30 ) - { - //printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage); - diff = 3600*24*30; - } - if ( iter > 0 ) - diff += segid*2; - coinage = (value * diff); - if ( 0 ) //&& ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) - { - if ( PoSperc < ASSETCHAINS_STAKED ) - { - // Under PoS % target and we need to increase diff. - //fprintf(stderr, "PoS too low diff.%i changed to.",diff); - if ( blocktime+iter+segid*2 > prevtime+128 ) - coinage *= ((blocktime+iter+segid*2) - (prevtime+102)); - //fprintf(stderr, "%i \n",diff); - } - } - if ( blocktime+iter+segid*2 > prevtime+480 ) - coinage *= ((blocktime+iter+segid*2) - (prevtime+400)); - coinage256 = arith_uint256(coinage+1); - hashval = ratio * (UintToArith256(hash) / coinage256); - if ( hashval <= bnTarget ) - { - winner = 1; - if ( validateflag == 0 ) - { - //fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid); - blocktime += iter; - blocktime += segid * 2; - } - break; - } - if ( validateflag != 0 ) - { - /*for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - fprintf(stderr," vs "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff); */ - break; - } - } - //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); - if ( 0 && validateflag != 0 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - fprintf(stderr," vs "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d ht.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff,nHeight); - } - if ( nHeight < 10 ) - return(blocktime); - return(blocktime * winner); -} - -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, merkleroot; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; arith_uint256 POWTarget; - if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) - return(1); - BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); - pindex = it != mapBlockIndex.end() ? it->second : NULL; - int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); - // Get PoSperc and POW Target. slowflag only here, calling it when blocks out of order causes problems. - if ( slowflag != 0 ) - { - POWTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); - } - else - { - // checks opret merkle root and existence of staking tx. - return(komodo_isPoS(pblock,height,0)); - } - txn_count = pblock->vtx.size(); - //fprintf(stderr,"checkblock n.%d vins.%d vouts.%d %.8f %.8f\n",txn_count,(int32_t)pblock->vtx[txn_count-1].vin.size(),(int32_t)pblock->vtx[txn_count-1].vout.size(),(double)pblock->vtx[txn_count-1].vout[0].nValue/COIN,(double)pblock->vtx[txn_count-1].vout[1].nValue/COIN); - if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) - { - it = mapBlockIndex.find(pblock->hashPrevBlock); - if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL ) - prevtime = (uint32_t)previndex->nTime; - - txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; - vout = pblock->vtx[txn_count-1].vin[0].prevout.n; - if ( slowflag != 0 && prevtime != 0 ) - { - if ( komodo_isPoS(pblock,height,0) != 0 ) - { - // checks utxo is eligible to stake this block - eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,(char *)"",PoSperc); - } - if ( eligible == 0 || eligible > pblock->nTime ) - { - if ( 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime)); - } - else - { - isPoS = 1; - /* - If POWTarget is easydiff, then we have no possible way to detect a PoW block from a staking block! - The simplest fix is to make the min diff for PoW blocks higher than the staking mindiff. - The logic here, is that all PoS equihash solutions MUST be under the POW target diff, - The floor diff can be adjusted with ASSETCHAINS_STAKED_MIN_POW_DIFF, this is a hardforking change. - */ - if ( ASSETCHAINS_STAKED < 100 && bhash < POWTarget ) - { - fprintf(stderr,"[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); - isPoS = 0; - } - } - } - } - //fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS); - return(isPoS != 0); -} - -bool GetStakeParams(const CTransaction &stakeTx, CStakeParams &stakeParams); -bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTransaction &stakeTx, bool &cheating); +int8_t komodo_segid(int32_t nocache,int32_t height); + +void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n); + +uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout); + +arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime); + +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); + +uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr,int32_t PoSperc); + +int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash); // for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes -bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) -{ - CBlockIndex *pastBlockIndex; - uint256 txid, blkHash; - int32_t txn_count; - uint32_t voutNum; - CAmount value; - bool isPOS = false; - CTxDestination voutaddress, destaddress, cbaddress; - arith_uint256 target, hash; - CTransaction tx; - - if (!pblock->IsVerusPOSBlock()) - { - printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height); - //pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget()); - //printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str()); - return false; - } - - char voutaddr[64], destaddr[64], cbaddr[64]; - - txn_count = pblock->vtx.size(); - - if ( txn_count > 1 ) - { - target.SetCompact(pblock->GetVerusPOSTarget()); - txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; - voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n; - value = pblock->vtx[txn_count-1].vout[0].nValue; - - { - bool validHash = (value != 0); - bool enablePOSNonce = CPOSNonce::NewPOSActive(height); - uint256 rawHash; - arith_uint256 posHash; - - if (validHash && enablePOSNonce) - { - validHash = pblock->GetRawVerusPOSHash(rawHash, height); - posHash = UintToArith256(rawHash) / value; - if (!validHash || posHash > target) - { - validHash = false; - printf("ERROR: invalid nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", - pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); - } - } - if (validHash) - { - if (slowflag == 0) - { - isPOS = true; - } - else if (!(pastBlockIndex = komodo_chainactive(height - 100))) - { - fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); - } - else -#ifndef KOMODO_ZCASH - if (!GetTransaction(txid, tx, Params().GetConsensus(), blkHash, true)) -#else - if (!GetTransaction(txid, tx, blkHash, true)) -#endif - { - fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str()); - } - else - { - CBlockHeader bh = pastBlockIndex->GetBlockHeader(); - uint256 pastHash = bh.GetVerusEntropyHash(height - 100); - - // if height is over when Nonce is required to be the new format, we check that the new format is correct - // if over when we have the new POS hash function, we validate that as well - // they are 100 blocks apart - CPOSNonce nonce = pblock->nNonce; - - //printf("before nNonce: %s, height: %d\n", pblock->nNonce.GetHex().c_str(), height); - //validHash = pblock->GetRawVerusPOSHash(rawHash, height); - //hash = UintToArith256(rawHash) / tx.vout[voutNum].nValue; - //printf("Raw POShash: %s\n", hash.GetHex().c_str()); - - hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash)); - - //printf("after nNonce: %s, height: %d\n", nonce.GetHex().c_str(), height); - //printf("POShash: %s\n\n", hash.GetHex().c_str()); - - if (posHash == hash && hash <= target) - { - BlockMap::const_iterator it = mapBlockIndex.find(blkHash); - if ((it == mapBlockIndex.end()) || - !(pastBlockIndex = it->second) || - (height - pastBlockIndex->GetHeight()) < VERUS_MIN_STAKEAGE) - { - fprintf(stderr,"ERROR: invalid PoS block %s - stake source too new or not found\n",blkHash.ToString().c_str()); - } - else - { - // make sure we have the right target - CBlockIndex *previndex; - it = mapBlockIndex.find(pblock->hashPrevBlock); - if (it == mapBlockIndex.end() || !(previndex = it->second)) - { - fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str()); - } - else - { - arith_uint256 cTarget; - uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus()); - cTarget.SetCompact(nBits); - bool nonceOK = true; - - // check to see how many fail - //if (nonce != pblock->nNonce) - // printf("Mismatched nNonce: %s\nblkHash: %s, height: %d\n", nonce.GetHex().c_str(), pblock->GetHash().GetHex().c_str(), height); - - if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum)) - { - fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str()); - nonceOK = false; - } - else - { - if (cTarget != target) - { - fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); - nonceOK = false; - } - } - if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && - ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) ) - { - strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); - strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); - if ( !strcmp(destaddr,voutaddr) ) - { - isPOS = true; - CTransaction &cbtx = pblock->vtx[0]; - for (int i = 0; i < cbtx.vout.size(); i++) - { - if (CScriptExt::ExtractVoutDestination(cbtx, i, cbaddress)) - { - strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str()); - if (!strcmp(destaddr,cbaddr)) - continue; - } - else - { - if (cbtx.vout[i].scriptPubKey.IsOpReturn()) - continue; - isPOS = false; - break; - } - } - } - else - { - fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake or coinbase destination\n",blkHash.ToString().c_str()); - } - } - } - } - } - else - { - printf("ERROR: malformed nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", - pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); - } - } - } - } - } - return(isPOS); -} - -uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount) -{ - int8_t curEra = 0; int64_t ret = 0; - // if we have an end block in the first era, find our current era - if ( ASSETCHAINS_ENDSUBSIDY[0] > 1 ) - { - for ( curEra = 0; curEra <= ASSETCHAINS_LASTERA; curEra++ ) - { - if ( ASSETCHAINS_ENDSUBSIDY[curEra] > nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 ) - break; - } - } - if ( curEra > ASSETCHAINS_LASTERA ) - return(0); - - if ( notarycount == 0 ) - { - fprintf(stderr, "komodo_notarypayamount failed num notaries is 0!\n"); - return(0); - } - // 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]); - ret = ASSETCHAINS_NOTARY_PAY[curEra] / notarycount; - return(ret); -} - -int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len) -{ - // Check the notarisation is valid, and extract notarised height. - uint64_t voutmask; - uint8_t scriptbuf[10001]; - int32_t isratification,specialtx,notarizedheight; - - 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,¬arizedheight,0,1,0,timestamp) != -2 ) - { - fprintf(stderr, "<<<<< &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len) -{ - // fetch notary pubkey array. - uint64_t total = 0, AmountToPay = 0; - int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; - numSN = komodo_notaries(notarypubkeys, height, timestamp); - - // No point going further, no notaries can be paid. - if ( notarypubkeys[0][0] == 0 ) - return(0); - - // Check the notarisation is valid. - int32_t notarizedheight = komodo_getnotarizedheight(timestamp, height, script, len); - if ( notarizedheight == 0 ) - return(0); - - // resize coinbase vouts to number of notary nodes +1 for coinbase itself. - txNew.vout.resize(NotarisationNotaries.size()+1); - - // Calcualte the amount to pay according to the current era. - AmountToPay = komodo_notarypayamount(height,NotarisationNotaries.size()); - if ( AmountToPay == 0 ) - return(0); - - // loop over notarisation vins and add transaction to coinbase. - // Commented prints here can be used to verify manually the pubkeys match. - for (int8_t n = 0; n < NotarisationNotaries.size(); n++) - { - uint8_t *ptr; - txNew.vout[n+1].scriptPubKey.resize(35); - ptr = (uint8_t *)&txNew.vout[n+1].scriptPubKey[0]; - ptr[0] = 33; - for (int8_t i=0; i<33; i++) - { - ptr[i+1] = notarypubkeys[NotarisationNotaries[n]][i]; - //fprintf(stderr,"%02x",ptr[i+1]); - } - ptr[34] = OP_CHECKSIG; - //fprintf(stderr," set notary %i PUBKEY33 into vout[%i] amount.%lu\n",NotarisationNotaries[n],n+1,AmountToPay); - txNew.vout[n+1].nValue = AmountToPay; - total += txNew.vout[n+1].nValue; - } - return(total); -} - -bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries) -{ - uint8_t *script; int32_t scriptlen; - if ( notarypubkeys[0][0] == 0 ) - return false; - BOOST_FOREACH(const CTxIn& txin, vin) - { - uint256 hash; CTransaction tx1; - if ( GetTransaction(txin.prevout.hash,tx1,hash,false) ) - { - for (int8_t i = 0; i < numNN; i++) - { - script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0]; - scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size(); - if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 ) - NotarisationNotaries.push_back(i); - } - } else return false; - } - return true; -} - -uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) -{ - std::vector NotarisationNotaries; uint8_t *script; int32_t scriptlen; - uint64_t timestamp = pblock->nTime; - int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; - numSN = komodo_notaries(notarypubkeys, height, timestamp); - if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) ) - return(0); - - // check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems) - std::set checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() ); - if ( checkdupes.size() != NotarisationNotaries.size() ) { - fprintf(stderr, "Possible notarisation is signed multiple times by same notary. It is invalid.\n"); - return(0); - } - const CChainParams& chainparams = Params(); - const Consensus::Params &consensusParams = chainparams.GetConsensus(); - uint64_t totalsats = 0; - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, height); - if ( pblock->vtx[1].vout.size() == 2 && pblock->vtx[1].vout[1].nValue == 0 ) - { - // Get the OP_RETURN for the notarisation - uint8_t *script = (uint8_t *)&pblock->vtx[1].vout[1].scriptPubKey[0]; - int32_t scriptlen = (int32_t)pblock->vtx[1].vout[1].scriptPubKey.size(); - if ( script[0] == OP_RETURN ) - { - // Create the coinbase tx again, using the extracted data, this is the same function the miner uses, with the same data. - // This allows us to know exactly that the coinbase is correct. - totalsats = komodo_notarypay(txNew, NotarisationNotaries, pblock->nTime, height, script, scriptlen); - } - else - { - fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen); - return(0); - } - } else return(0); - - // if notarypay fails, because the notarisation is not valid, exit now as txNew was not created. - // This should never happen, as the notarisation is checked before this function is called. - if ( totalsats == 0 ) - { - fprintf(stderr, "notary pay returned 0!\n"); - return(0); - } - - int8_t n = 0, i = 0, matches = 0; - uint64_t total = 0, AmountToPay = 0; - - // get the pay amount from the created tx. - AmountToPay = txNew.vout[1].nValue; - - // Check the created coinbase pays the correct notaries. - BOOST_FOREACH(const CTxOut& txout, pblock->vtx[0].vout) - { - // skip the coinbase paid to the miner. - if ( n == 0 ) - { - n++; - continue; - } - // Check the pubkeys match the pubkeys in the notarisation. - script = (uint8_t *)&txout.scriptPubKey[0]; - scriptlen = (int32_t)txout.scriptPubKey.size(); - if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[NotarisationNotaries[n-1]],33) == 0 ) - { - // check the value is correct - if ( pblock->vtx[0].vout[n].nValue == AmountToPay ) - { - matches++; - total += txout.nValue; - //fprintf(stderr, "MATCHED AmountPaid.%lu notaryid.%i\n",AmountToPay,NotarisationNotaries[n-1]); - } - else fprintf(stderr, "NOT MATCHED AmountPaid.%llu AmountToPay.%llu notaryid.%i\n", (long long)pblock->vtx[0].vout[n].nValue, (long long)AmountToPay, NotarisationNotaries[n-1]); - } - n++; - } - if ( matches != 0 && matches == NotarisationNotaries.size() && totalsats == total ) - { - //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() < KOMODO_EARLYTXID_HEIGHT ) - { - 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() < KOMODO_EARLYTXID_HEIGHT ) - { - fprintf(stderr, "Cannot fetch -earlytxid before block %d.\n",KOMODO_EARLYTXID_HEIGHT); - 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() < KOMODO_EARLYTXID_HEIGHT ) - { - 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; static bool didinit = false; - if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) - { - checktoshis = komodo_commission(pblock,height); - if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 ) - { - //fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN); - return(-1); - } - else if ( checktoshis != 0 ) - { - script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0]; - scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size(); - if ( 0 ) - { - int32_t i; - for (i=0; ivtx[0].vout[1].nValue/COIN); - } - if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - static bool didinit = false; - if ( !didinit && height > KOMODO_EARLYTXID_HEIGHT && 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()); - if ( memcmp(scripthex,script,scriptlen) == 0 ) - matched = scriptlen; - } - } - else if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) == 0 ) - matched = 35; - else if ( scriptlen == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG && memcmp(script+3,ASSETCHAINS_OVERRIDE_PUBKEYHASH,20) == 0 ) - matched = 25; - if ( matched == 0 ) - { - if ( 0 && ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - int32_t i; - for (i=0; ivtx[0].vout[1].nValue != checktoshis ) - { - fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue)); - return(-1); - } - } - } - return(checktoshis); -} - -bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; - -int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,int32_t height) -{ - uint256 hash,merkleroot; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,scriptlen,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; - if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" ) - KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; - if ( !CheckEquihashSolution(pblock, Params()) ) - { - fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height); - return(-1); - } - hash = pblock->GetHash(); - bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); - bhash = UintToArith256(hash); - possible = komodo_block2pubkey33(pubkey33,pblock); - if ( height == 0 ) - { - if ( slowflag != 0 ) - { - fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget); - return(0); - } - BlockMap::const_iterator it = mapBlockIndex.find(pblock->hashPrevBlock); - if ( it != mapBlockIndex.end() && (pprev= it->second) != 0 ) - height = pprev->GetHeight() + 1; - if ( height == 0 ) - return(0); - } - //if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) - // bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime); - if ( ASSETCHAINS_LWMAPOS != 0 && bhash > bnTarget ) - { - // if proof of stake is active, check if this is a valid PoS block before we fail - if (verusCheckPOSBlock(slowflag, pblock, height)) - { - return(0); - } - } - if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget ) - { - failed = 1; - if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case - { - if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 ) - { - for (i=0; i= 2 ) // must PoS or have at least 16x better PoW - { - CBlockIndex *pindex; - BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); - pindex = it != mapBlockIndex.end() ? it->second : NULL; - int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); - if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) - { - if ( slowflag == 0 || height <= 100 ) // need all past 100 blocks to calculate PoW target - return(0); - if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 - return(-1); - else - { - bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); - if ( bhash > bnTarget ) - { - for (i=31; i>=16; i--) - fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]); - fprintf(stderr," > "); - for (i=31; i>=16; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED); - return(-1); - } - else - { - if ( newStakerActive != 0 ) - { - // PoW fake blocks will be rejected here. If a staking tx is included in a block that meets PoW min diff after block 100, then this will reject it. - if ( pblock->vtx.size() > 1 && pblock->vtx[pblock->vtx.size()-1].vout.size() == 2 && DecodeStakingOpRet(pblock->vtx[pblock->vtx.size()-1].vout[1].scriptPubKey, merkleroot) != 0 ) - { - fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL,height,bhash.GetCompact(),bnTarget.GetCompact()); - return(-1); - } - // set the pindex->segid as this is now fully validated to be a PoW block. - if ( pindex != 0 ) - { - pindex->segid = -1; - //fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); - } - } - failed = 0; - } - } - } - else if ( is_PoSblock < 0 ) - { - fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); - return(-1); - } - else - { - if ( slowflag != 0 && newStakerActive != 0 ) - { - int8_t segid = -2; - // the value passed to stakeTxValue, is the blockreward + the valuein-valueout(txfee) of the last tx in the block. - // the coinbase must pay the fees from the last transaction and the block reward at a minimum. - if ( pblock->vtx.size() < 1 || pblock->vtx[0].vout.size() < 1 ) - { - fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); - return(-1); - } - else if ( pblock->vtx[0].vout[0].nValue < stakeTxValue ) - { - fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); - return(-1); - } - // set the pindex->segid as this is now fully validated to be a PoS block. - char voutaddr[64]; CTxDestination voutaddress; - if ( ExtractDestination(pblock->vtx.back().vout[0].scriptPubKey,voutaddress) ) - { - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - segid = komodo_segid32(voutaddr) & 0x3f; - } - if ( pindex != 0 && segid >= 0 ) - { - pindex->segid = segid; - //fprintf(stderr,"PoS block set segid.%d <- %d\n",height,pindex->segid); - } - } - failed = 0; - } - } - if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) - { - if ( height == 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]; - scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size(); - if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) - { - decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); - if ( memcmp(scripthex,script,scriptlen) != 0 ) - return(-1); - } else return(-1); - } - 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(); - if ( scriptlen != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) - return(-1); - } - } - else - { - if ( komodo_checkcommission(pblock,height) < 0 ) - return(-1); - } - } - // Consensus rule to force miners to mine the notary coinbase payment happens in ConnectBlock - // the default daemon miner, checks the actual vins so the only way this will fail, is if someone changes the miner, - // and then creates txs to the crypto address meeting min sigs and puts it in tx position 1. - // If they go through this effort, the block will still fail at connect block, and will be auto purged by the temp file fix. - if ( failed == 0 && ASSETCHAINS_NOTARY_PAY[0] != 0 && pblock->vtx.size() > 1 ) - { - // We check the full validation in ConnectBlock directly to get the amount for coinbase. So just approx here. - if ( slowflag == 0 && pblock->vtx[0].vout.size() > 1 ) - { - // Check the notarisation tx is to the crypto address. - if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 ) - { - fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); - return(-1); - } - // Check min sigs. - int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; - numSN = komodo_notaries(notarypubkeys, height, pblock->nTime); - if ( pblock->vtx[1].vin.size() < numSN/5 ) - { - fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size()); - return(-1); - } - } - } - -//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed); - if ( failed != 0 && possible == 0 && notaryid < 0 ) - return(-1); - else return(0); -} - -int32_t komodo_acpublic(uint32_t tiptime) -{ - int32_t acpublic = ASSETCHAINS_PUBLIC; CBlockIndex *pindex; - if ( acpublic == 0 ) - { - if ( tiptime == 0 ) - { - if ( (pindex= chainActive.LastTip()) != 0 ) - tiptime = pindex->nTime; - } - if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - } - return(acpublic); -} - -int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock) -{ - CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0,sproutfunds=0; - n = pblock->vtx.size(); - for (i=0; ivtx[i]; - if ( (m= tx.vin.size()) > 0 ) - { - for (j=0; j= vintx.vout.size() ) - { - fprintf(stderr,"ERROR: %s/v%d cant find\n",txid.ToString().c_str(),vout); - return(0); - } - vinsum += vintx.vout[vout].nValue; - } - } - if ( (m= tx.vout.size()) > 0 ) - { - for (j=0; j %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str()); - } - script = (uint8_t *)&tx.vout[j].scriptPubKey[0]; - if ( script == 0 || script[0] != 0x6a ) - { - if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 ) - voutsum += tx.vout[j].nValue; - } - } - BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) - { - zfunds -= joinsplit.vpub_new; - zfunds += joinsplit.vpub_old; - sproutfunds -= joinsplit.vpub_new; - sproutfunds += joinsplit.vpub_old; - } - zfunds -= tx.valueBalance; - } - *zfundsp = zfunds; - *sproutfundsp = sproutfunds; - if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times - return(3 * SATOSHIDEN); - //if ( voutsum-vinsum+zfunds > 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 ) - //. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds)); - return(voutsum - vinsum); -} - -int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) -{ - CBlockIndex *pindex; CBlock block; int64_t zfunds=0,sproutfunds=0,supply = 0; - //fprintf(stderr,"coinsupply %d\n",height); - *zfundsp = *sproutfundsp = 0; - if ( (pindex= komodo_chainactive(height)) != 0 ) - { - while ( pindex != 0 && pindex->GetHeight() > 0 ) - { - if ( pindex->newcoins == 0 && pindex->zfunds == 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - pindex->newcoins = komodo_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block); - else - { - fprintf(stderr,"error loading block.%d\n",pindex->GetHeight()); - return(0); - } - } - supply += pindex->newcoins; - zfunds += pindex->zfunds; - sproutfunds += pindex->sproutfunds; - //printf("start ht.%d new %.8f -> supply %.8f zfunds %.8f -> %.8f\n",pindex->GetHeight(),dstr(pindex->newcoins),dstr(supply),dstr(pindex->zfunds),dstr(zfunds)); - pindex = pindex->pprev; - } - } - *zfundsp = zfunds; - *sproutfundsp = sproutfunds; - return(supply); -} +bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height); + +uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); + +int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); + +uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); + +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); + +uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height); + +bool komodo_appendACscriptpub(); + +void GetKomodoEarlytxidScriptPub(); + +int64_t komodo_checkcommission(CBlock *pblock,int32_t height); + +int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,int32_t height); + +int32_t komodo_acpublic(uint32_t tiptime); + +int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock); + +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); + struct komodo_staking { char address[64]; @@ -2635,234 +239,6 @@ struct komodo_staking CScript scriptPubKey; }; -struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) -{ - uint256 hash; uint32_t segid32; struct komodo_staking *kp; - segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); - if ( *numkp >= *maxkp ) - { - *maxkp += 1000; - array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); - //fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array); - } - kp = &array[(*numkp)++]; - //fprintf(stderr,"kp.%p num.%d\n",kp,*numkp); - memset(kp,0,sizeof(*kp)); - strcpy(kp->address,address); - kp->txid = txid; - kp->vout = vout; - kp->hashval = UintToArith256(hash); - kp->txtime = txtime; - kp->segid32 = segid32; - kp->nValue = nValue; - kp->scriptPubKey = pk; - return(array); -} - -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot) -{ - static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; - int32_t PoSperc = 0, newStakerActive; - set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; - uint64_t cbPerc = *utxovaluep, tocoinbase = 0; - if (!EnsureWalletIsAvailable(0)) - return 0; - - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); - assert(pwalletMain != NULL); - *utxovaluep = 0; - memset(utxotxidp,0,sizeof(*utxotxidp)); - memset(utxovoutp,0,sizeof(*utxovoutp)); - memset(utxosig,0,72); - if ( (tipindex= chainActive.Tip()) == 0 ) - return(0); - nHeight = tipindex->GetHeight() + 1; - if ( (minage= nHeight*3) > 6000 ) // about 100 blocks - minage = 6000; - if ( *blocktimep < tipindex->nTime+60 ) - *blocktimep = tipindex->nTime+60; - komodo_segids(hashbuf,nHeight-101,100); - // this was for VerusHash PoS64 - //tmpTarget = komodo_PoWtarget(&PoSperc,bnTarget,nHeight,ASSETCHAINS_STAKED); - bool resetstaker = false; - if ( array != 0 ) - { - LOCK(cs_main); - CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; - CBlock block; CTxDestination addressout; - if ( ASSETCHAINS_MARMARA != 0 ) - resetstaker = true; - else if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) - { - resetstaker = true; - fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",ASSETCHAINS_SYMBOL,nHeight); - } - } - - if ( resetstaker || array == 0 || time(NULL) > lasttime+600 ) - { - LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); - if ( array != 0 ) - { - free(array); - array = 0; - maxkp = numkp = 0; - lasttime = 0; - } - if ( ASSETCHAINS_MARMARA == 0 ) - { - BOOST_FOREACH(const COutput& out, vecOutputs) - { - if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) - { - fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),counter); - return(0); - } - counter++; - if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) - { - //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); - continue; - } - CAmount nValue = out.tx->vout[out.i].nValue; - if ( nValue < COIN || !out.fSpendable ) - continue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; - if ( ExtractDestination(pk,address) != 0 ) - { - if ( IsMine(*pwalletMain,address) == 0 ) - continue; - if ( myGetTransaction(out.tx->GetHash(),tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) - { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); - //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); - } - } - } - } - else - { - struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk; - std::vector > unspentOutputs; - cp = CCinit(&C,EVAL_MARMARA); - mypk = pubkey2pk(Mypubkey()); - Marmarapk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( (nValue= it->second.satoshis) < COIN ) - continue; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - const CScript &scriptPubKey = tx.vout[vout].scriptPubKey; - if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk ) - { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey); - } - // else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp); - } - } - } - 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); - } - block_from_future_rejecttime = (uint32_t)GetTime() + ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX; - for (i=winners=0; iGetHeight()+1 > nHeight ) - { - fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),i); - return(0); - } - kp = &array[i]; - eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc); - if ( eligible > 0 ) - { - besttime = 0; - if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc) ) - { - // have elegible utxo to stake with. - if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) - { - // 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; - } - /*if ( eligible < block_from_future_rejecttime ) - { - // better to scan all and choose earliest! - fprintf(stderr, "block_from_future_rejecttime.%u vs eligible.%u \n", block_from_future_rejecttime, eligible); - break; - } */ - } - } - } - if ( numkp < 500 && array != 0 ) - { - free(array); - array = 0; - maxkp = numkp = 0; - lasttime = 0; - } - if ( earliest != 0 ) - { - bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - const CKeyStore& keystore = *pwalletMain; - txNew.vin.resize(1); - txNew.vout.resize(1); - txfee = 0; - for (i=0; i<32; i++) - ((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; - txNew.vout[0].nValue = *utxovaluep - txfee; - txNew.nLockTime = earliest; - txNew.nExpiryHeight = nHeight; - if ( (newStakerActive= komodo_newStakerActive(nHeight,earliest)) != 0 ) - { - if ( cbPerc > 0 && cbPerc <= 100 ) - { - tocoinbase = txNew.vout[0].nValue*cbPerc/100; - txNew.vout[0].nValue -= tocoinbase; - } - txNew.vout.resize(2); - txNew.vout[1].scriptPubKey = EncodeStakingOpRet(merkleroot); - txNew.vout[1].nValue = 0; - } - CTransaction txNewConst(txNew); - if ( ASSETCHAINS_MARMARA == 0 ) - { - signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); - UpdateTransaction(txNew,0,sigdata); - ptr = (uint8_t *)&sigdata.scriptSig[0]; - siglen = sigdata.scriptSig.size(); - for (i=0; i 0 ) - signSuccess = true; - else signSuccess = false; - } - if (!signSuccess) - fprintf(stderr,"failed to create signature\n"); - else - *blocktimep = earliest; - } - return(siglen); -} +struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk); + +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index 10140ad0232..14c190de36d 100644 --- a/src/komodo_cJSON.c +++ b/src/komodo_cJSON.c @@ -21,13 +21,11 @@ THE SOFTWARE. */ -/* cJSON */ -/* JSON parser in C. */ #include -#include "cJSON.h" #include "komodo_cJSON.h" -#include "cJSON.c" +#include "cJSON.h" +#include "hex.h" #ifndef DBL_EPSILON #define DBL_EPSILON 2.2204460492503131E-16 @@ -158,7 +156,7 @@ int64_t conv_cJSON_float(cJSON *json,char *field) int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field) { - int32_t safecopy(char *dest,char *src,long len); + int32_t safecopy(char *dest,const char *src,long len); char *str; cJSON *obj; int32_t len; diff --git a/src/komodo_cJSON.h b/src/komodo_cJSON.h index 3586b5cbf5b..8fdb338c738 100644 --- a/src/komodo_cJSON.h +++ b/src/komodo_cJSON.h @@ -34,9 +34,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef komodo_cJSON__h -#define komodo_cJSON__h +#pragma once #include #include @@ -46,9 +44,13 @@ #include #include +#include "bits256.h" #include "cJSON.h" -//#include "../crypto777/OS_portable.h" +#ifndef SATOSHIDEN +#define SATOSHIDEN ((uint64_t)100000000L) +#define dstr(x) ((double)(x) / SATOSHIDEN) +#endif #define MAX_JSON_FIELD 4096 // on the big side @@ -57,11 +59,7 @@ extern "C" { #endif -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif +#include "komodo_cutils.h" /* Macros for creating things quickly. */ #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) @@ -141,8 +139,8 @@ extern "C" #define jfieldname get_cJSON_fieldname + long stripquotes(char *str); + #ifdef __cplusplus } #endif - -#endif diff --git a/src/komodo_ccdata.cpp b/src/komodo_ccdata.cpp new file mode 100644 index 00000000000..31cd95ffbaf --- /dev/null +++ b/src/komodo_ccdata.cpp @@ -0,0 +1,266 @@ +/****************************************************************************** + * 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 "komodo_ccdata.h" +#include "komodo_extern_globals.h" + +struct komodo_ccdata *CC_data; +int32_t CC_firstheight; + +uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); + +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) +{ + static uint256 zero; CBlockIndex *pindex; int32_t i; std::vector tree, leaves; + bool fMutated; + MoMdepth &= 0xffff; // In case it includes the ccid + if ( MoMdepth >= height ) + return(zero); + for (i=0; ihashMerkleRoot); + else + return(zero); + } + return BuildMerkleTree(&fMutated, leaves, tree); +} + +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi) +{ + struct komodo_ccdata_entry *allMoMs=0; struct komodo_ccdata *ccdata,*tmpptr; int32_t i,num,max; + bool fMutated; std::vector tree, leaves; + num = max = 0; + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height <= kmdendi && ccdata->MoMdata.height >= kmdstarti ) + { + if ( num >= max ) + { + max += 100; + allMoMs = (struct komodo_ccdata_entry *)realloc(allMoMs,max * sizeof(*allMoMs)); + } + allMoMs[num].MoM = ccdata->MoMdata.MoM; + allMoMs[num].notarized_height = ccdata->MoMdata.notarized_height; + allMoMs[num].kmdheight = ccdata->MoMdata.height; + allMoMs[num].txi = ccdata->MoMdata.txi; + strcpy(allMoMs[num].symbol,ccdata->symbol); + num++; + } + if ( ccdata->MoMdata.height < kmdstarti ) + break; + } + portable_mutex_unlock(&KOMODO_CC_mutex); + if ( (*nump= num) > 0 ) + { + for (i=0; i= 0) { + if ( mdata->numpairs >= maxpairs ) + { + maxpairs += 100; + mdata->pairs = (struct komodo_ccdatapair *)realloc(mdata->pairs,sizeof(*mdata->pairs)*maxpairs); + //fprintf(stderr,"pairs reallocated to %p num.%d\n",mdata->pairs,mdata->numpairs); + } + } else { + fprintf(stderr,"komodo_addpair.maxpairs %d must be >= 0\n",(int32_t)maxpairs); + return(-1); + } + mdata->pairs[mdata->numpairs].notarized_height = notarized_height; + mdata->pairs[mdata->numpairs].MoMoMoffset = offset; + mdata->numpairs++; + return(maxpairs); +} + +int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height) +{ + uint8_t hexdata[8192]; struct komodo_ccdata *ccdata,*tmpptr; int32_t len,maxpairs,i,retval=-1,depth,starti,endi,CCid=0; struct komodo_ccdata_entry *allMoMs; + starti = endi = depth = len = maxpairs = 0; + hexstr[0] = 0; + if ( sizeof(hexdata)*2+1 > hexsize ) + { + fprintf(stderr,"hexsize.%d too small for %d\n",hexsize,(int32_t)sizeof(hexdata)); + return(-1); + } + memset(mdata,0,sizeof(*mdata)); + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height < kmdheight ) + { + //fprintf(stderr,"%s notarized.%d kmd.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height,ccdata->MoMdata.height); + if ( strcmp(ccdata->symbol,symbol) == 0 ) + { + if ( endi == 0 ) + { + endi = ccdata->MoMdata.height; + CCid = ccdata->CCid; + } + if ( (mdata->numpairs == 1 && notarized_height == 0) || ccdata->MoMdata.notarized_height <= notarized_height ) + { + starti = ccdata->MoMdata.height + 1; + if ( notarized_height == 0 ) + notarized_height = ccdata->MoMdata.notarized_height; + break; + } + } + starti = ccdata->MoMdata.height; + } + } + portable_mutex_unlock(&KOMODO_CC_mutex); + mdata->kmdstarti = starti; + mdata->kmdendi = endi; + if ( starti != 0 && endi != 0 && endi >= starti ) + { + if ( (allMoMs= komodo_allMoMs(&depth,&mdata->MoMoM,starti,endi)) != 0 ) + { + mdata->MoMoMdepth = depth; + for (i=0; inumpairs > 0 ) + { + len += iguana_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); + len += iguana_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); + for (i=0; inumpairs; i++) + { + if ( len + sizeof(uint32_t)*2 > sizeof(hexdata) ) + { + fprintf(stderr,"%s %d %d i.%d of %d exceeds hexdata.%d\n",symbol,kmdheight,notarized_height,i,mdata->numpairs,(int32_t)sizeof(hexdata)); + break; + } + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); + } + if ( i == mdata->numpairs && len*2+1 < hexsize ) + { + init_hexbytes_noT(hexstr,hexdata,len); + //fprintf(stderr,"hexstr.(%s)\n",hexstr); + retval = 0; + } else fprintf(stderr,"%s %d %d too much hexdata[%d] for hexstr[%d]\n",symbol,kmdheight,notarized_height,len,hexsize); + } + free(allMoMs); + } + } + return(retval); +} + +void komodo_purge_ccdata(int32_t height) +{ + struct komodo_ccdata *ccdata,*tmpptr; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height >= height ) + { + printf("PURGE %s notarized.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height); + DL_DELETE(CC_data,ccdata); + free(ccdata); + } else break; + } + portable_mutex_unlock(&KOMODO_CC_mutex); + } + else + { + // purge notarized data + } +} + +// this is just a demo of ccdata processing to create example data for the MoMoM and allMoMs calls +int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata) +{ + uint256 hash,zero; bits256 tmp; int32_t i,nonz; struct komodo_ccdata *ptr; struct notarized_checkpoint *np; + return(0); // disable this path as libscott method is much better + if ( rwflag == 0 ) + { + // load from disk + } + else + { + // write to disk + } + if ( ccdata->MoMdata.height > 0 && (CC_firstheight == 0 || ccdata->MoMdata.height < CC_firstheight) ) + CC_firstheight = ccdata->MoMdata.height; + for (nonz=i=0; i<32; i++) + { + if ( (tmp.bytes[i]= ((uint8_t *)&ccdata->MoMdata.MoM)[31-i]) != 0 ) + nonz++; + } + if ( nonz == 0 ) + return(0); + memcpy(&hash,&tmp,sizeof(hash)); + //fprintf(stderr,"[%s] ccdata.%s id.%d notarized_ht.%d MoM.%s height.%d/t%d\n",ASSETCHAINS_SYMBOL,ccdata->symbol,ccdata->CCid,ccdata->MoMdata.notarized_height,hash.ToString().c_str(),ccdata->MoMdata.height,ccdata->MoMdata.txi); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( CC_data != 0 && (CC_data->MoMdata.height > ccdata->MoMdata.height || (CC_data->MoMdata.height == ccdata->MoMdata.height && CC_data->MoMdata.txi >= ccdata->MoMdata.txi)) ) + { + printf("out of order detected? SKIP CC_data ht.%d/txi.%d vs ht.%d/txi.%d\n",CC_data->MoMdata.height,CC_data->MoMdata.txi,ccdata->MoMdata.height,ccdata->MoMdata.txi); + } + else + { + ptr = (struct komodo_ccdata *)calloc(1,sizeof(*ptr)); + *ptr = *ccdata; + portable_mutex_lock(&KOMODO_CC_mutex); + DL_PREPEND(CC_data,ptr); + portable_mutex_unlock(&KOMODO_CC_mutex); + } + } + else + { + if ( MoMoMdata != 0 && MoMoMdata->pairs != 0 ) + { + for (i=0; inumpairs; i++) + { + if ( (np= komodo_npptr(MoMoMdata->pairs[i].notarized_height)) != 0 ) + { + memset(&zero,0,sizeof(zero)); + if ( memcmp(&np->MoMoM,&zero,sizeof(np->MoMoM)) == 0 ) + { + np->MoMoM = MoMoMdata->MoMoM; + np->MoMoMdepth = MoMoMdata->MoMoMdepth; + np->MoMoMoffset = MoMoMdata->MoMoMoffset; + np->kmdstarti = MoMoMdata->kmdstarti; + np->kmdendi = MoMoMdata->kmdendi; + } + else if ( memcmp(&np->MoMoM,&MoMoMdata->MoMoM,sizeof(np->MoMoM)) != 0 || np->MoMoMdepth != MoMoMdata->MoMoMdepth || np->MoMoMoffset != MoMoMdata->MoMoMoffset || np->kmdstarti != MoMoMdata->kmdstarti || np->kmdendi != MoMoMdata->kmdendi ) + { + fprintf(stderr,"preexisting MoMoM mismatch: %s (%d %d %d %d) vs %s (%d %d %d %d)\n",np->MoMoM.ToString().c_str(),np->MoMoMdepth,np->MoMoMoffset,np->kmdstarti,np->kmdendi,MoMoMdata->MoMoM.ToString().c_str(),MoMoMdata->MoMoMdepth,MoMoMdata->MoMoMoffset,MoMoMdata->kmdstarti,MoMoMdata->kmdendi); + } + } + } + } + } + return(1); +} diff --git a/src/komodo_ccdata.h b/src/komodo_ccdata.h index 3969532fd7f..939b0b98396 100644 --- a/src/komodo_ccdata.h +++ b/src/komodo_ccdata.h @@ -12,258 +12,18 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once +#include "komodo.h" -#ifndef H_KOMODOCCDATA_H -#define H_KOMODOCCDATA_H +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); -struct komodo_ccdata *CC_data; -int32_t CC_firstheight; +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); -uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); +int32_t komodo_addpair(struct komodo_ccdataMoMoM *mdata,int32_t notarized_height,int32_t offset,int32_t maxpairs); -uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) -{ - static uint256 zero; CBlockIndex *pindex; int32_t i; std::vector tree, leaves; - bool fMutated; - MoMdepth &= 0xffff; // In case it includes the ccid - if ( MoMdepth >= height ) - return(zero); - for (i=0; ihashMerkleRoot); - else - return(zero); - } - return BuildMerkleTree(&fMutated, leaves, tree); -} +int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); -struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi) -{ - struct komodo_ccdata_entry *allMoMs=0; struct komodo_ccdata *ccdata,*tmpptr; int32_t i,num,max; - bool fMutated; std::vector tree, leaves; - num = max = 0; - portable_mutex_lock(&KOMODO_CC_mutex); - DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) - { - if ( ccdata->MoMdata.height <= kmdendi && ccdata->MoMdata.height >= kmdstarti ) - { - if ( num >= max ) - { - max += 100; - allMoMs = (struct komodo_ccdata_entry *)realloc(allMoMs,max * sizeof(*allMoMs)); - } - allMoMs[num].MoM = ccdata->MoMdata.MoM; - allMoMs[num].notarized_height = ccdata->MoMdata.notarized_height; - allMoMs[num].kmdheight = ccdata->MoMdata.height; - allMoMs[num].txi = ccdata->MoMdata.txi; - strcpy(allMoMs[num].symbol,ccdata->symbol); - num++; - } - if ( ccdata->MoMdata.height < kmdstarti ) - break; - } - portable_mutex_unlock(&KOMODO_CC_mutex); - if ( (*nump= num) > 0 ) - { - for (i=0; i= 0) { - if ( mdata->numpairs >= maxpairs ) - { - maxpairs += 100; - mdata->pairs = (struct komodo_ccdatapair *)realloc(mdata->pairs,sizeof(*mdata->pairs)*maxpairs); - //fprintf(stderr,"pairs reallocated to %p num.%d\n",mdata->pairs,mdata->numpairs); - } - } else { - fprintf(stderr,"komodo_addpair.maxpairs %d must be >= 0\n",(int32_t)maxpairs); - return(-1); - } - mdata->pairs[mdata->numpairs].notarized_height = notarized_height; - mdata->pairs[mdata->numpairs].MoMoMoffset = offset; - mdata->numpairs++; - return(maxpairs); -} - -int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height) -{ - uint8_t hexdata[8192]; struct komodo_ccdata *ccdata,*tmpptr; int32_t len,maxpairs,i,retval=-1,depth,starti,endi,CCid=0; struct komodo_ccdata_entry *allMoMs; - starti = endi = depth = len = maxpairs = 0; - hexstr[0] = 0; - if ( sizeof(hexdata)*2+1 > hexsize ) - { - fprintf(stderr,"hexsize.%d too small for %d\n",hexsize,(int32_t)sizeof(hexdata)); - return(-1); - } - memset(mdata,0,sizeof(*mdata)); - portable_mutex_lock(&KOMODO_CC_mutex); - DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) - { - if ( ccdata->MoMdata.height < kmdheight ) - { - //fprintf(stderr,"%s notarized.%d kmd.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height,ccdata->MoMdata.height); - if ( strcmp(ccdata->symbol,symbol) == 0 ) - { - if ( endi == 0 ) - { - endi = ccdata->MoMdata.height; - CCid = ccdata->CCid; - } - if ( (mdata->numpairs == 1 && notarized_height == 0) || ccdata->MoMdata.notarized_height <= notarized_height ) - { - starti = ccdata->MoMdata.height + 1; - if ( notarized_height == 0 ) - notarized_height = ccdata->MoMdata.notarized_height; - break; - } - } - starti = ccdata->MoMdata.height; - } - } - portable_mutex_unlock(&KOMODO_CC_mutex); - mdata->kmdstarti = starti; - mdata->kmdendi = endi; - if ( starti != 0 && endi != 0 && endi >= starti ) - { - if ( (allMoMs= komodo_allMoMs(&depth,&mdata->MoMoM,starti,endi)) != 0 ) - { - mdata->MoMoMdepth = depth; - for (i=0; inumpairs > 0 ) - { - len += iguana_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); - len += iguana_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); - for (i=0; inumpairs; i++) - { - if ( len + sizeof(uint32_t)*2 > sizeof(hexdata) ) - { - fprintf(stderr,"%s %d %d i.%d of %d exceeds hexdata.%d\n",symbol,kmdheight,notarized_height,i,mdata->numpairs,(int32_t)sizeof(hexdata)); - break; - } - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); - } - if ( i == mdata->numpairs && len*2+1 < hexsize ) - { - init_hexbytes_noT(hexstr,hexdata,len); - //fprintf(stderr,"hexstr.(%s)\n",hexstr); - retval = 0; - } else fprintf(stderr,"%s %d %d too much hexdata[%d] for hexstr[%d]\n",symbol,kmdheight,notarized_height,len,hexsize); - } - free(allMoMs); - } - } - return(retval); -} - -void komodo_purge_ccdata(int32_t height) -{ - struct komodo_ccdata *ccdata,*tmpptr; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - portable_mutex_lock(&KOMODO_CC_mutex); - DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) - { - if ( ccdata->MoMdata.height >= height ) - { - printf("PURGE %s notarized.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height); - DL_DELETE(CC_data,ccdata); - free(ccdata); - } else break; - } - portable_mutex_unlock(&KOMODO_CC_mutex); - } - else - { - // purge notarized data - } -} +void komodo_purge_ccdata(int32_t height); // this is just a demo of ccdata processing to create example data for the MoMoM and allMoMs calls -int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata) -{ - uint256 hash,zero; bits256 tmp; int32_t i,nonz; struct komodo_ccdata *ptr; struct notarized_checkpoint *np; - return(0); // disable this path as libscott method is much better - if ( rwflag == 0 ) - { - // load from disk - } - else - { - // write to disk - } - if ( ccdata->MoMdata.height > 0 && (CC_firstheight == 0 || ccdata->MoMdata.height < CC_firstheight) ) - CC_firstheight = ccdata->MoMdata.height; - for (nonz=i=0; i<32; i++) - { - if ( (tmp.bytes[i]= ((uint8_t *)&ccdata->MoMdata.MoM)[31-i]) != 0 ) - nonz++; - } - if ( nonz == 0 ) - return(0); - memcpy(&hash,&tmp,sizeof(hash)); - //fprintf(stderr,"[%s] ccdata.%s id.%d notarized_ht.%d MoM.%s height.%d/t%d\n",ASSETCHAINS_SYMBOL,ccdata->symbol,ccdata->CCid,ccdata->MoMdata.notarized_height,hash.ToString().c_str(),ccdata->MoMdata.height,ccdata->MoMdata.txi); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( CC_data != 0 && (CC_data->MoMdata.height > ccdata->MoMdata.height || (CC_data->MoMdata.height == ccdata->MoMdata.height && CC_data->MoMdata.txi >= ccdata->MoMdata.txi)) ) - { - printf("out of order detected? SKIP CC_data ht.%d/txi.%d vs ht.%d/txi.%d\n",CC_data->MoMdata.height,CC_data->MoMdata.txi,ccdata->MoMdata.height,ccdata->MoMdata.txi); - } - else - { - ptr = (struct komodo_ccdata *)calloc(1,sizeof(*ptr)); - *ptr = *ccdata; - portable_mutex_lock(&KOMODO_CC_mutex); - DL_PREPEND(CC_data,ptr); - portable_mutex_unlock(&KOMODO_CC_mutex); - } - } - else - { - if ( MoMoMdata != 0 && MoMoMdata->pairs != 0 ) - { - for (i=0; inumpairs; i++) - { - if ( (np= komodo_npptr(MoMoMdata->pairs[i].notarized_height)) != 0 ) - { - memset(&zero,0,sizeof(zero)); - if ( memcmp(&np->MoMoM,&zero,sizeof(np->MoMoM)) == 0 ) - { - np->MoMoM = MoMoMdata->MoMoM; - np->MoMoMdepth = MoMoMdata->MoMoMdepth; - np->MoMoMoffset = MoMoMdata->MoMoMoffset; - np->kmdstarti = MoMoMdata->kmdstarti; - np->kmdendi = MoMoMdata->kmdendi; - } - else if ( memcmp(&np->MoMoM,&MoMoMdata->MoMoM,sizeof(np->MoMoM)) != 0 || np->MoMoMdepth != MoMoMdata->MoMoMdepth || np->MoMoMoffset != MoMoMdata->MoMoMoffset || np->kmdstarti != MoMoMdata->kmdstarti || np->kmdendi != MoMoMdata->kmdendi ) - { - fprintf(stderr,"preexisting MoMoM mismatch: %s (%d %d %d %d) vs %s (%d %d %d %d)\n",np->MoMoM.ToString().c_str(),np->MoMoMdepth,np->MoMoMoffset,np->kmdstarti,np->kmdendi,MoMoMdata->MoMoM.ToString().c_str(),MoMoMdata->MoMoMdepth,MoMoMdata->MoMoMoffset,MoMoMdata->kmdstarti,MoMoMdata->kmdendi); - } - } - } - } - } - return(1); -} - -#endif +int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata); diff --git a/src/komodo_curve25519.cpp b/src/komodo_curve25519.cpp new file mode 100644 index 00000000000..1b0dc7bb2bf --- /dev/null +++ b/src/komodo_curve25519.cpp @@ -0,0 +1,299 @@ +/****************************************************************************** + * 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 "komodo_curve25519.h" +#include "komodo_utils.h" // for vcalc_sha256 + +void store_limb(uint8_t *out,uint64_t in) +{ + int32_t i; + for (i=0; i<8; i++,in>>=8) + out[i] = (in & 0xff); +} + +static inline uint64_t load_limb(uint8_t *in) +{ + return + ((uint64_t)in[0]) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24) | + (((uint64_t)in[4]) << 32) | + (((uint64_t)in[5]) << 40) | + (((uint64_t)in[6]) << 48) | + (((uint64_t)in[7]) << 56); +} + +// Take a little-endian, 32-byte number and expand it into polynomial form +bits320 fexpand(bits256 basepoint) +{ + bits320 out; + out.ulongs[0] = load_limb(basepoint.bytes) & 0x7ffffffffffffLL; + out.ulongs[1] = (load_limb(basepoint.bytes+6) >> 3) & 0x7ffffffffffffLL; + out.ulongs[2] = (load_limb(basepoint.bytes+12) >> 6) & 0x7ffffffffffffLL; + out.ulongs[3] = (load_limb(basepoint.bytes+19) >> 1) & 0x7ffffffffffffLL; + out.ulongs[4] = (load_limb(basepoint.bytes+24) >> 12) & 0x7ffffffffffffLL; + return(out); +} + +#if __amd64__ +// Multiply two numbers: output = in2 * in +// output must be distinct to both inputs. The inputs are reduced coefficient form, the output is not. +// Assumes that in[i] < 2**55 and likewise for in2. On return, output[i] < 2**52 +bits320 fmul(const bits320 in2,const bits320 in) +{ + uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; bits320 out; + r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; + s0 = in2.ulongs[0], s1 = in2.ulongs[1], s2 = in2.ulongs[2], s3 = in2.ulongs[3], s4 = in2.ulongs[4]; + t[0] = ((uint128_t) r0) * s0; + t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; + t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; + t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; + t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; + r4 *= 19, r1 *= 19, r2 *= 19, r3 *= 19; + t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; + t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; + t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; + t[3] += ((uint128_t) r4) * s4; + r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); + t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); + t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); + t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffLL; c = (uint64_t)(t[3] >> 51); + t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; + r2 += c; + out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; + return(out); +} + +bits320 fsquare_times(const bits320 in,uint64_t count) +{ + uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,c,d0,d1,d2,d4,d419; bits320 out; + r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; + do + { + d0 = r0 * 2; + d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; + d4 = d419 * 2; + t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); + t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); + t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); + t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); + t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); + + r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); + t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); + t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); + t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffL; c = (uint64_t)(t[3] >> 51); + t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; + r2 += c; + } while( --count ); + out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; + return(out); +} + +// donna: Take a fully reduced polynomial form number and contract it into a little-endian, 32-byte array +bits256 fcontract(const bits320 input) +{ + uint128_t t[5]; int32_t i; bits256 out; + for (i=0; i<5; i++) + t[i] = input.ulongs[i]; + fcontract_iter(t,1), fcontract_iter(t,1); + // donna: now t is between 0 and 2^255-1, properly carried. + // donna: case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. + t[0] += 19, fcontract_iter(t,1); + // now between 19 and 2^255-1 in both cases, and offset by 19. + t[0] += 0x8000000000000 - 19; + for (i=1; i<5; i++) + t[i] += 0x8000000000000 - 1; + // now between 2^255 and 2^256-20, and offset by 2^255. + fcontract_iter(t,0); + store_limb(out.bytes,t[0] | (t[1] << 51)); + store_limb(out.bytes+8,(t[1] >> 13) | (t[2] << 38)); + store_limb(out.bytes+16,(t[2] >> 26) | (t[3] << 25)); + store_limb(out.bytes+24,(t[3] >> 39) | (t[4] << 12)); + return(out); +} + +bits256 curve25519(bits256 mysecret,bits256 basepoint) +{ + bits320 bp,x,z; + mysecret.bytes[0] &= 0xf8, mysecret.bytes[31] &= 0x7f, mysecret.bytes[31] |= 0x40; + bp = fexpand(basepoint); + cmult(&x,&z,mysecret,bp); + return(fcontract(fmul(x,crecip(z)))); +} +#endif + +// Calculates nQ where Q is the x-coordinate of a point on the curve +// resultx/resultz: the x coordinate of the resulting curve point (short form) +// n: a little endian, 32-byte number +// q: a point of the curve (short form) +void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q) +{ + int32_t i,j; bits320 a,b,c,d,e,f,g,h,*t; + bits320 Zero320bits,One320bits, *nqpqx = &a,*nqpqz = &b,*nqx = &c,*nqz = &d,*nqpqx2 = &e,*nqpqz2 = &f,*nqx2 = &g,*nqz2 = &h; + memset(&Zero320bits,0,sizeof(Zero320bits)); + memset(&One320bits,0,sizeof(One320bits)), One320bits.ulongs[0] = 1; + a = d = e = g = Zero320bits, b = c = f = h = One320bits; + *nqpqx = q; + for (i=0; i<32; i++) + { + uint8_t byte = secret.bytes[31 - i]; + for (j=0; j<8; j++) + { + const uint64_t bit = byte >> 7; + swap_conditional(nqx,nqpqx,bit), swap_conditional(nqz,nqpqz,bit); + fmonty(nqx2,nqz2,nqpqx2,nqpqz2,nqx,nqz,nqpqx,nqpqz,q); + swap_conditional(nqx2,nqpqx2,bit), swap_conditional(nqz2,nqpqz2,bit); + t = nqx, nqx = nqx2, nqx2 = t; + t = nqz, nqz = nqz2, nqz2 = t; + t = nqpqx, nqpqx = nqpqx2, nqpqx2 = t; + t = nqpqz, nqpqz = nqpqz2, nqpqz2 = t; + byte <<= 1; + } + } + *resultx = *nqx, *resultz = *nqz; +} + +#ifndef _WIN32 +void OS_randombytes(unsigned char *x,long xlen); +#endif + +bits256 rand256(int32_t privkeyflag) +{ + bits256 randval; + #ifndef __WIN32 + OS_randombytes(randval.bytes,sizeof(randval)); + #else + randombytes_buf(randval.bytes,sizeof(randval)); + #endif + if ( privkeyflag != 0 ) + randval.bytes[0] &= 0xf8, randval.bytes[31] &= 0x7f, randval.bytes[31] |= 0x40; + return(randval); +} + +bits256 curve25519_basepoint9() +{ + bits256 basepoint; + memset(&basepoint,0,sizeof(basepoint)); + basepoint.bytes[0] = 9; + return(basepoint); +} + +bits256 curve25519_keypair(bits256 *pubkeyp) +{ + bits256 privkey; + privkey = rand256(1); + *pubkeyp = curve25519(privkey,curve25519_basepoint9()); + //printf("[%llx %llx] ",privkey.txid,(*pubkeyp).txid); + return(privkey); +} + +bits256 curve25519_shared(bits256 privkey,bits256 otherpub) +{ + bits256 shared,hash; + shared = curve25519(privkey,otherpub); + vcalc_sha256(0,hash.bytes,shared.bytes,sizeof(shared)); + //printf("priv.%llx pub.%llx shared.%llx -> hash.%llx\n",privkey.txid,pubkey.txid,shared.txid,hash.txid); + //hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; + return(hash); +} + +int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint) +{ + bits256 val,p,bp; + memcpy(p.bytes,secret,sizeof(p)); + memcpy(bp.bytes,basepoint,sizeof(bp)); + val = curve25519(p,bp); + memcpy(mypublic,val.bytes,sizeof(val)); + return(0); +} + +uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen) +{ + static uint8_t basepoint[32] = {9}; + uint64_t addr; uint8_t hash[32]; + if ( pass != 0 && passlen != 0 ) + vcalc_sha256(0,mysecret,pass,passlen); + mysecret[0] &= 248, mysecret[31] &= 127, mysecret[31] |= 64; + curve25519_donna(mypublic,mysecret,basepoint); + vcalc_sha256(0,hash,mypublic,32); + memcpy(&addr,hash,sizeof(addr)); + return(addr); +} + +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase) +{ + uint256 privkey; + conv_NXTpassword((uint8_t *)&privkey,(uint8_t *)pubkeyp,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + return(privkey); +} + +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey) +{ + bits256 sig,hash,otherpub,checksig,pubkey,privkey; uint256 usig; + memcpy(&privkey,&_privkey,sizeof(privkey)); + vcalc_sha256(0,hash.bytes,buf,len); + otherpub = curve25519(hash,curve25519_basepoint9()); + pubkey = curve25519(privkey,curve25519_basepoint9()); + sig = curve25519_shared(privkey,otherpub); + checksig = curve25519_shared(hash,pubkey); + /*int32_t i; for (i=0; i "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&privkey)[i]); + printf(" -> "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&pubkey)[i]); + printf(" pubkey\n");*/ + memcpy(&usig,&sig,sizeof(usig)); + return(usig); +} + +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) +{ + bits256 hash,checksig,pubkey; static uint256 zeroes; + memcpy(&pubkey,&_pubkey,sizeof(pubkey)); + if ( memcmp(&pubkey,&zeroes,sizeof(pubkey)) != 0 ) + { + vcalc_sha256(0,hash.bytes,buf,len); + checksig = curve25519_shared(hash,pubkey); + /*int32_t i; for (i=0; i "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&hash)[i]); + printf(" -> "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&pubkey)[i]); + printf(" verify pubkey\n"); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&sig)[i]); + printf(" sig vs"); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&checksig)[i]); + printf(" checksig\n");*/ + if ( memcmp(&checksig,&sig,sizeof(sig)) != 0 ) + return(-1); + //else printf("VALIDATED\n"); + } + return(0); +} diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index cba40561b8b..9b755c11838 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -12,17 +12,19 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef H_KOMODO25519_H -#define H_KOMODO25519_H -// derived from curve25519_donna +#pragma once #include #include #include +#include "bits256.h" + #ifdef _WIN32 #include #endif + +#include "komodo_structs.h" + bits320 fmul(const bits320 in2,const bits320 in); bits320 fexpand(bits256 basepoint); bits256 fcontract(const bits320 input); @@ -49,37 +51,10 @@ static inline void fdifference_backwards(uint64_t *out,const uint64_t *in) out[i] = in[i] + two54m8 - out[i]; } -void store_limb(uint8_t *out,uint64_t in) -{ - int32_t i; - for (i=0; i<8; i++,in>>=8) - out[i] = (in & 0xff); -} - -static inline uint64_t load_limb(uint8_t *in) -{ - return - ((uint64_t)in[0]) | - (((uint64_t)in[1]) << 8) | - (((uint64_t)in[2]) << 16) | - (((uint64_t)in[3]) << 24) | - (((uint64_t)in[4]) << 32) | - (((uint64_t)in[5]) << 40) | - (((uint64_t)in[6]) << 48) | - (((uint64_t)in[7]) << 56); -} +void store_limb(uint8_t *out,uint64_t in); // Take a little-endian, 32-byte number and expand it into polynomial form -bits320 fexpand(bits256 basepoint) -{ - bits320 out; - out.ulongs[0] = load_limb(basepoint.bytes) & 0x7ffffffffffffLL; - out.ulongs[1] = (load_limb(basepoint.bytes+6) >> 3) & 0x7ffffffffffffLL; - out.ulongs[2] = (load_limb(basepoint.bytes+12) >> 6) & 0x7ffffffffffffLL; - out.ulongs[3] = (load_limb(basepoint.bytes+19) >> 1) & 0x7ffffffffffffLL; - out.ulongs[4] = (load_limb(basepoint.bytes+24) >> 12) & 0x7ffffffffffffLL; - return(out); -} +bits320 fexpand(bits256 basepoint); #if __amd64__ // donna: special gcc mode for 128-bit integers. It's implemented on 64-bit platforms only as far as I know. @@ -103,62 +78,9 @@ static inline bits320 fscalar_product(const bits320 in,const uint64_t scalar) // Multiply two numbers: output = in2 * in // output must be distinct to both inputs. The inputs are reduced coefficient form, the output is not. // Assumes that in[i] < 2**55 and likewise for in2. On return, output[i] < 2**52 -bits320 fmul(const bits320 in2,const bits320 in) -{ - uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; bits320 out; - r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; - s0 = in2.ulongs[0], s1 = in2.ulongs[1], s2 = in2.ulongs[2], s3 = in2.ulongs[3], s4 = in2.ulongs[4]; - t[0] = ((uint128_t) r0) * s0; - t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; - t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; - t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; - t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; - r4 *= 19, r1 *= 19, r2 *= 19, r3 *= 19; - t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; - t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; - t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; - t[3] += ((uint128_t) r4) * s4; - r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); - t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); - t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); - t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffLL; c = (uint64_t)(t[3] >> 51); - t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); - r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; - r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; - r2 += c; - out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; - return(out); -} +bits320 fmul(const bits320 in2,const bits320 in); -bits320 fsquare_times(const bits320 in,uint64_t count) -{ - uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,c,d0,d1,d2,d4,d419; bits320 out; - r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; - do - { - d0 = r0 * 2; - d1 = r1 * 2; - d2 = r2 * 2 * 19; - d419 = r4 * 19; - d4 = d419 * 2; - t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); - t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); - t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); - t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); - t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); - - r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); - t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); - t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); - t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffL; c = (uint64_t)(t[3] >> 51); - t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); - r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; - r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; - r2 += c; - } while( --count ); - out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; - return(out); -} +bits320 fsquare_times(const bits320 in,uint64_t count); static inline void fcontract_iter(uint128_t t[5],int32_t flag) { @@ -170,36 +92,9 @@ static inline void fcontract_iter(uint128_t t[5],int32_t flag) } // donna: Take a fully reduced polynomial form number and contract it into a little-endian, 32-byte array -bits256 fcontract(const bits320 input) -{ - uint128_t t[5]; int32_t i; bits256 out; - for (i=0; i<5; i++) - t[i] = input.ulongs[i]; - fcontract_iter(t,1), fcontract_iter(t,1); - // donna: now t is between 0 and 2^255-1, properly carried. - // donna: case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. - t[0] += 19, fcontract_iter(t,1); - // now between 19 and 2^255-1 in both cases, and offset by 19. - t[0] += 0x8000000000000 - 19; - for (i=1; i<5; i++) - t[i] += 0x8000000000000 - 1; - // now between 2^255 and 2^256-20, and offset by 2^255. - fcontract_iter(t,0); - store_limb(out.bytes,t[0] | (t[1] << 51)); - store_limb(out.bytes+8,(t[1] >> 13) | (t[2] << 38)); - store_limb(out.bytes+16,(t[2] >> 26) | (t[3] << 25)); - store_limb(out.bytes+24,(t[3] >> 39) | (t[4] << 12)); - return(out); -} +bits256 fcontract(const bits320 input); -bits256 curve25519(bits256 mysecret,bits256 basepoint) -{ - bits320 bp,x,z; - mysecret.bytes[0] &= 0xf8, mysecret.bytes[31] &= 0x7f, mysecret.bytes[31] |= 0x40; - bp = fexpand(basepoint); - cmult(&x,&z,mysecret,bp); - return(fcontract(fmul(x,crecip(z)))); -} +bits256 curve25519(bits256 mysecret,bits256 basepoint); #else // from curve25519-donna.c @@ -829,32 +724,7 @@ static inline void swap_conditional(bits320 *a,bits320 *b,uint64_t iswap) // resultx/resultz: the x coordinate of the resulting curve point (short form) // n: a little endian, 32-byte number // q: a point of the curve (short form) -void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q) -{ - int32_t i,j; bits320 a,b,c,d,e,f,g,h,*t; - bits320 Zero320bits,One320bits, *nqpqx = &a,*nqpqz = &b,*nqx = &c,*nqz = &d,*nqpqx2 = &e,*nqpqz2 = &f,*nqx2 = &g,*nqz2 = &h; - memset(&Zero320bits,0,sizeof(Zero320bits)); - memset(&One320bits,0,sizeof(One320bits)), One320bits.ulongs[0] = 1; - a = d = e = g = Zero320bits, b = c = f = h = One320bits; - *nqpqx = q; - for (i=0; i<32; i++) - { - uint8_t byte = secret.bytes[31 - i]; - for (j=0; j<8; j++) - { - const uint64_t bit = byte >> 7; - swap_conditional(nqx,nqpqx,bit), swap_conditional(nqz,nqpqz,bit); - fmonty(nqx2,nqz2,nqpqx2,nqpqz2,nqx,nqz,nqpqx,nqpqz,q); - swap_conditional(nqx2,nqpqx2,bit), swap_conditional(nqz2,nqpqz2,bit); - t = nqx, nqx = nqx2, nqx2 = t; - t = nqz, nqz = nqz2, nqz2 = t; - t = nqpqx, nqpqx = nqpqx2, nqpqx2 = t; - t = nqpqz, nqpqz = nqpqz2, nqpqz2 = t; - byte <<= 1; - } - } - *resultx = *nqx, *resultz = *nqz; -} +void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q); // Shamelessly copied from donna's code that copied djb's code, changed a little inline bits320 crecip(const bits320 z) @@ -884,130 +754,20 @@ inline bits320 crecip(const bits320 z) /* 2^255 - 21 */ return(fmul(t0, a)); } -#ifndef _WIN32 -void OS_randombytes(unsigned char *x,long xlen); -#endif +bits256 rand256(int32_t privkeyflag); -bits256 rand256(int32_t privkeyflag) -{ - bits256 randval; - #ifndef __WIN32 - OS_randombytes(randval.bytes,sizeof(randval)); - #else - randombytes_buf(randval.bytes,sizeof(randval)); - #endif - if ( privkeyflag != 0 ) - randval.bytes[0] &= 0xf8, randval.bytes[31] &= 0x7f, randval.bytes[31] |= 0x40; - return(randval); -} +bits256 curve25519_basepoint9(); -bits256 curve25519_basepoint9() -{ - bits256 basepoint; - memset(&basepoint,0,sizeof(basepoint)); - basepoint.bytes[0] = 9; - return(basepoint); -} +bits256 curve25519_keypair(bits256 *pubkeyp); -bits256 curve25519_keypair(bits256 *pubkeyp) -{ - bits256 privkey; - privkey = rand256(1); - *pubkeyp = curve25519(privkey,curve25519_basepoint9()); - //printf("[%llx %llx] ",privkey.txid,(*pubkeyp).txid); - return(privkey); -} +bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -bits256 curve25519_shared(bits256 privkey,bits256 otherpub) -{ - bits256 shared,hash; - shared = curve25519(privkey,otherpub); - vcalc_sha256(0,hash.bytes,shared.bytes,sizeof(shared)); - //printf("priv.%llx pub.%llx shared.%llx -> hash.%llx\n",privkey.txid,pubkey.txid,shared.txid,hash.txid); - //hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; - return(hash); -} +int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint); -int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint) -{ - bits256 val,p,bp; - memcpy(p.bytes,secret,sizeof(p)); - memcpy(bp.bytes,basepoint,sizeof(bp)); - val = curve25519(p,bp); - memcpy(mypublic,val.bytes,sizeof(val)); - return(0); -} - -uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen) -{ - static uint8_t basepoint[32] = {9}; - uint64_t addr; uint8_t hash[32]; - if ( pass != 0 && passlen != 0 ) - vcalc_sha256(0,mysecret,pass,passlen); - mysecret[0] &= 248, mysecret[31] &= 127, mysecret[31] |= 64; - curve25519_donna(mypublic,mysecret,basepoint); - vcalc_sha256(0,hash,mypublic,32); - memcpy(&addr,hash,sizeof(addr)); - return(addr); -} - -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase) -{ - uint256 privkey; - conv_NXTpassword((uint8_t *)&privkey,(uint8_t *)pubkeyp,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); - return(privkey); -} +uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen); -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey) -{ - bits256 sig,hash,otherpub,checksig,pubkey,privkey; uint256 usig; - memcpy(&privkey,&_privkey,sizeof(privkey)); - vcalc_sha256(0,hash.bytes,buf,len); - otherpub = curve25519(hash,curve25519_basepoint9()); - pubkey = curve25519(privkey,curve25519_basepoint9()); - sig = curve25519_shared(privkey,otherpub); - checksig = curve25519_shared(hash,pubkey); - /*int32_t i; for (i=0; i "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&privkey)[i]); - printf(" -> "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" pubkey\n");*/ - memcpy(&usig,&sig,sizeof(usig)); - return(usig); -} +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) -{ - bits256 hash,checksig,pubkey; static uint256 zeroes; - memcpy(&pubkey,&_pubkey,sizeof(pubkey)); - if ( memcmp(&pubkey,&zeroes,sizeof(pubkey)) != 0 ) - { - vcalc_sha256(0,hash.bytes,buf,len); - checksig = curve25519_shared(hash,pubkey); - /*int32_t i; for (i=0; i "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" -> "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" verify pubkey\n"); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&sig)[i]); - printf(" sig vs"); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&checksig)[i]); - printf(" checksig\n");*/ - if ( memcmp(&checksig,&sig,sizeof(sig)) != 0 ) - return(-1); - //else printf("VALIDATED\n"); - } - return(0); -} +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey); -#endif +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp new file mode 100644 index 00000000000..4fa84fe6932 --- /dev/null +++ b/src/komodo_cutils.cpp @@ -0,0 +1,60 @@ +#include "komodo_cutils.h" +#include "stdlib.h" //malloc +#include "hex.h" + +#ifdef __APPLE__ +#include // sleep +#endif + +int32_t safecopy(char *dest,const char *src,long len) +{ + int32_t i = -1; + if ( src != 0 && dest != 0 && src != dest ) + { + if ( dest != 0 ) + memset(dest,0,len); + for (i=0; i"; + } + clone = (char *)malloc(strlen(str)+16); + strcpy(clone,str); + return(clone); +} diff --git a/src/komodo_cutils.h b/src/komodo_cutils.h new file mode 100644 index 00000000000..6d9a25c90ea --- /dev/null +++ b/src/komodo_cutils.h @@ -0,0 +1,19 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +int32_t safecopy(char *dest,const char *src,long len); + +long _stripwhite(char *buf,int accept); + +char *clonestr(char *str); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/komodo_defs.h b/src/komodo_defs.h index b4b118a5760..c9a2c0587fa 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -37,6 +37,7 @@ #define ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF 27 #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 #define _COINBASE_MATURITY 100 +#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff // KMD Notary Seasons // 1: May 1st 2018 1530921600 @@ -491,7 +492,8 @@ extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_FOUNDERS_REWARD; extern uint64_t ASSETCHAINS_TIMELOCKGTE; extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOMODO_INITDONE; -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,KOMODO_NSPV; +extern bool IS_KOMODO_NOTARY; +extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED,KOMODO_NSPV; extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET; extern bool VERUS_MINTBLOCKS; extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2]; @@ -499,27 +501,29 @@ extern const char *ASSETCHAINS_ALGORITHMS[]; extern int32_t VERUS_MIN_STAKEAGE; extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; -extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA; +extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; extern std::vector 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 bool IS_KOMODO_DEALERNODE; +extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE; extern uint32_t ASSETCHAINS_CC; extern std::string CCerror,ASSETCHAINS_CCLIB; extern uint8_t ASSETCHAINS_CCDISABLES[256]; extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; -extern int32_t KOMODO_EXCHANGEWALLET; +extern bool IS_MODE_EXCHANGEWALLET; 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 NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; -extern int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL,IS_STAKED_NOTARY,STAKED_ERA; +extern bool IS_KOMODO_TESTNODE; +extern int32_t KOMODO_SNAPSHOT_INTERVAL,STAKED_NOTARY_ID,STAKED_ERA; extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT; extern int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; int tx_height( const uint256 &hash ); diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp new file mode 100644 index 00000000000..e9c4b68aff1 --- /dev/null +++ b/src/komodo_events.cpp @@ -0,0 +1,187 @@ +/****************************************************************************** + * 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 "komodo_events.h" +#include "komodo_extern_globals.h" +#include "komodo_bitcoind.h" // komodo_verifynotarization +#include "komodo_notary.h" // komodo_notarized_update +#include "komodo_pax.h" // komodo_pvals +#include "komodo_gateway.h" // komodo_opreturn + +/***** + * Add a notarized event to the collection + * @param sp the state to add to + * @param symbol + * @param height + * @param ntz the event + */ +void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr ntz) +{ + char *coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; + + if ( IS_KOMODO_NOTARY + && komodo_verifynotarization(symbol,ntz->dest,height,ntz->notarizedheight,ntz->blockhash, ntz->desttxid) < 0 ) + { + static uint32_t counter; + if ( counter++ < 100 ) + printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n", + ASSETCHAINS_SYMBOL,height,ntz->notarizedheight, ntz->dest); + } + else if ( strcmp(symbol,coin) == 0 ) + { + if ( sp != nullptr ) + { + sp->add_event(symbol, height, ntz); + komodo_notarized_update(sp,height, ntz->notarizedheight, ntz->blockhash, ntz->desttxid, ntz->MoM, ntz->MoMdepth); + } + } +} + +/***** + * Add a pubkeys event to the collection + * @param sp where to add + * @param symbol + * @param height + * @param pk the event + */ +void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pk) +{ + if (sp != nullptr) + { + sp->add_event(symbol, height, pk); + komodo_notarysinit(height, pk->pubkeys, pk->num); + } +} + +/******** + * Add a pricefeed event to the collection + * @param sp where to add + * @param symbol + * @param height + * @param pf the event + */ +void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pf) +{ + if (sp != nullptr) + { + sp->add_event(symbol, height, pf); + komodo_pvals(height,pf->prices, pf->num); + } +} + +/***** + * Add an opreturn event to the collection + * @param sp where to add + * @param symbol + * @param height + * @param opret the event + */ +void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) +{ + if ( sp != nullptr && ASSETCHAINS_SYMBOL[0] != 0) + { + sp->add_event(symbol, height, opret); + komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); + } +} + +/***** + * @brief Undo an event + * @note seems to only work for KMD height events + * @param sp the state object + * @param ev the event to undo + */ +void komodo_event_undo(komodo_state *sp, std::shared_ptr ev) +{ + switch ( ev->type ) + { + case KOMODO_EVENT_RATIFY: + printf("rewind of ratify, needs to be coded.%d\n",ev->height); + break; + case KOMODO_EVENT_NOTARIZED: + break; + case KOMODO_EVENT_KMDHEIGHT: + if ( ev->height <= sp->SAVEDHEIGHT ) + sp->SAVEDHEIGHT = ev->height; + break; + case KOMODO_EVENT_PRICEFEED: + // backtrack prices; + break; + case KOMODO_EVENT_OPRETURN: + // backtrack opreturns + break; + } +} + + +void komodo_event_rewind(komodo_state *sp, char *symbol, int32_t height) +{ + if ( sp != nullptr ) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) + { + printf("undo KOMODO_LASTMINED %d <- %d\n",KOMODO_LASTMINED,prevKOMODO_LASTMINED); + KOMODO_LASTMINED = prevKOMODO_LASTMINED; + prevKOMODO_LASTMINED = 0; + } + while ( sp->events.size() > 0) + { + auto ev = sp->events.back(); + if (ev-> height < height) + break; + komodo_event_undo(sp, ev); + sp->events.pop_back(); + } + } +} + +void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp) +{ + if ( sp != nullptr ) + { + if ( kmdheight > sp->SAVEDHEIGHT ) + { + sp->SAVEDHEIGHT = kmdheight; + sp->SAVEDTIMESTAMP = timestamp; + } + if ( kmdheight > sp->CURRENT_HEIGHT ) + sp->CURRENT_HEIGHT = kmdheight; + } +} + +/****** + * @brief handle a height change event (forward or rewind) + * @param sp + * @param symbol + * @param height + * @param kmdht the event + */ +void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr kmdht) +{ + if (sp != nullptr) + { + if ( kmdht->kheight > 0 ) // height is advancing + { + + sp->add_event(symbol, height, kmdht); + komodo_setkmdheight(sp, kmdht->kheight, kmdht->timestamp); + } + else // rewinding + { + std::shared_ptr e = std::make_shared(height); + sp->add_event(symbol, height, e); + komodo_event_rewind(sp,symbol,height); + } + } +} diff --git a/src/komodo_events.h b/src/komodo_events.h index 5500a341eb2..31cd2407dfc 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -12,207 +12,22 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef H_KOMODOEVENTS_H -#define H_KOMODOEVENTS_H +#pragma once #include "komodo_defs.h" +#include "komodo_structs.h" -struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen) -{ - struct komodo_event *ep=0; uint16_t len = (uint16_t)(sizeof(*ep) + datalen); - if ( sp != 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - portable_mutex_lock(&komodo_mutex); - ep = (struct komodo_event *)calloc(1,len); - ep->len = len; - ep->height = height; - ep->type = type; - strcpy(ep->symbol,symbol); - if ( datalen != 0 ) - memcpy(ep->space,data,datalen); - sp->Komodo_events = (struct komodo_event **)realloc(sp->Komodo_events,(1 + sp->Komodo_numevents) * sizeof(*sp->Komodo_events)); - sp->Komodo_events[sp->Komodo_numevents++] = ep; - portable_mutex_unlock(&komodo_mutex); - } - return(ep); -} - -void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) -{ - static uint32_t counter; int32_t verified=0; char *coin; struct komodo_event_notarized N; - coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; - if ( IS_KOMODO_NOTARY != 0 && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) - { - if ( counter++ < 100 ) - printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n",ASSETCHAINS_SYMBOL,height,notarizedheight,dest); - } - else if ( strcmp(symbol,coin) == 0 ) - { - if ( 0 && IS_KOMODO_NOTARY != 0 && verified != 0 ) - fprintf(stderr,"validated [%s] ht.%d notarized %d\n",coin,height,notarizedheight); - memset(&N,0,sizeof(N)); - N.blockhash = notarized_hash; - N.desttxid = notarized_desttxid; - N.notarizedheight = notarizedheight; - N.MoM = MoM; - N.MoMdepth = MoMdepth; - strncpy(N.dest,dest,sizeof(N.dest)-1); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_NOTARIZED,(uint8_t *)&N,sizeof(N)); - if ( sp != 0 ) - komodo_notarized_update(sp,height,notarizedheight,notarized_hash,notarized_desttxid,MoM,MoMdepth); - } -} - -void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) -{ - struct komodo_event_pubkeys P; - //printf("eventadd pubkeys ht.%d\n",height); - memset(&P,0,sizeof(P)); - P.num = num; - memcpy(P.pubkeys,pubkeys,33 * num); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_RATIFY,(uint8_t *)&P,(int32_t)(sizeof(P.num) + 33 * num)); - if ( sp != 0 ) - komodo_notarysinit(height,pubkeys,num); -} - -void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num) -{ - struct komodo_event_pricefeed F; - if ( num == sizeof(F.prices)/sizeof(*F.prices) ) - { - memset(&F,0,sizeof(F)); - F.num = num; - memcpy(F.prices,prices,sizeof(*F.prices) * num); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_PRICEFEED,(uint8_t *)&F,(int32_t)(sizeof(F.num) + sizeof(*F.prices) * num)); - if ( sp != 0 ) - komodo_pvals(height,prices,num); - } //else fprintf(stderr,"skip pricefeed[%d]\n",num); -} - -void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen) -{ - struct komodo_event_opreturn O; uint8_t *opret; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - opret = (uint8_t *)calloc(1,sizeof(O) + opretlen + 16); - O.txid = txid; - O.value = value; - O.vout = vout; - memcpy(opret,&O,sizeof(O)); - memcpy(&opret[sizeof(O)],buf,opretlen); - O.oplen = (int32_t)(opretlen + sizeof(O)); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_OPRETURN,opret,O.oplen); - free(opret); - if ( sp != 0 ) - komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); - } -} - -void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) -{ - switch ( ep->type ) - { - case KOMODO_EVENT_RATIFY: printf("rewind of ratify, needs to be coded.%d\n",ep->height); break; - case KOMODO_EVENT_NOTARIZED: break; - case KOMODO_EVENT_KMDHEIGHT: - if ( ep->height <= sp->SAVEDHEIGHT ) - sp->SAVEDHEIGHT = ep->height; - break; - case KOMODO_EVENT_PRICEFEED: - // backtrack prices; - break; - case KOMODO_EVENT_OPRETURN: - // backtrack opreturns - break; - } -} +void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr ntz); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) -{ - struct komodo_event *ep; - if ( sp != 0 ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) - { - printf("undo KOMODO_LASTMINED %d <- %d\n",KOMODO_LASTMINED,prevKOMODO_LASTMINED); - KOMODO_LASTMINED = prevKOMODO_LASTMINED; - prevKOMODO_LASTMINED = 0; - } - while ( sp->Komodo_events != 0 && sp->Komodo_numevents > 0 ) - { - if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != 0 ) - { - if ( ep->height < height ) - break; - //printf("[%s] undo %s event.%c ht.%d for rewind.%d\n",ASSETCHAINS_SYMBOL,symbol,ep->type,ep->height,height); - komodo_event_undo(sp,ep); - sp->Komodo_numevents--; - } - } - } -} +void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pk); -void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp) -{ - if ( sp != 0 ) - { - if ( kmdheight > sp->SAVEDHEIGHT ) - { - sp->SAVEDHEIGHT = kmdheight; - sp->SAVEDTIMESTAMP = timestamp; - } - if ( kmdheight > sp->CURRENT_HEIGHT ) - sp->CURRENT_HEIGHT = kmdheight; - } -} +void komodo_eventadd_pricefeed(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pf); -void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) -{ - uint32_t buf[2]; - if ( kmdheight > 0 ) - { - buf[0] = (uint32_t)kmdheight; - buf[1] = timestamp; - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_KMDHEIGHT,(uint8_t *)buf,sizeof(buf)); - if ( sp != 0 ) - komodo_setkmdheight(sp,kmdheight,timestamp); - } - else - { - //fprintf(stderr,"REWIND kmdheight.%d\n",kmdheight); - kmdheight = -kmdheight; - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_REWIND,(uint8_t *)&height,sizeof(height)); - if ( sp != 0 ) - komodo_event_rewind(sp,symbol,height); - } -} +void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr opret); +void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,std::shared_ptr kmd_ht); -/*void komodo_eventadd_deposit(int32_t actionflag,char *symbol,int32_t height,uint64_t komodoshis,char *fiat,uint64_t fiatoshis,uint8_t rmd160[20],bits256 kmdtxid,uint16_t kmdvout,uint64_t price) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_DEPOSIT,kmdtxid,komodoshis,kmdvout,opret,opretlen); - } - - void komodo_eventadd_issued(int32_t actionflag,char *symbol,int32_t height,int32_t fiatheight,bits256 fiattxid,uint16_t fiatvout,bits256 kmdtxid,uint16_t kmdvout,uint64_t fiatoshis) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_ISSUED,fiattxid,fiatoshis,fiatvout,opret,opretlen); - } - - void komodo_eventadd_withdraw(int32_t actionflag,char *symbol,int32_t height,uint64_t komodoshis,char *fiat,uint64_t fiatoshis,uint8_t rmd160[20],bits256 fiattxid,int32_t fiatvout,uint64_t price) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_WITHDRAW,fiattxid,fiatoshis,fiatvout,opret,opretlen); - } - - void komodo_eventadd_redeemed(int32_t actionflag,char *symbol,int32_t height,bits256 kmdtxid,uint16_t kmdvout,int32_t fiatheight,bits256 fiattxid,uint16_t fiatvout,uint64_t komodoshis) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_REDEEMED,kmdtxid,komodoshis,kmdvout,opret,opretlen); - }*/ +void komodo_event_undo(komodo_state *sp, std::shared_ptr ep); -// process events -// +void komodo_event_rewind(komodo_state *sp,char *symbol,int32_t height); -#endif +void komodo_setkmdheight(komodo_state *sp,int32_t kmdheight,uint32_t timestamp); diff --git a/src/komodo_extern_globals.h b/src/komodo_extern_globals.h new file mode 100644 index 00000000000..23c7c1ce146 --- /dev/null +++ b/src/komodo_extern_globals.h @@ -0,0 +1,97 @@ +#pragma once +/****************************************************************************** + * Copyright © 2021 Komodo Core 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. * + * * + ******************************************************************************/ +/**** + * This file provides extern access to variables in komodo_globals.h + * Please think twice before adding to this list. Can it be done with a better scope? + */ +#include "komodo_structs.h" +#include +#include + +extern bool IS_KOMODO_NOTARY; +extern bool IS_KOMODO_DEALERNODE; +extern char KMDUSERPASS[8192+512+1]; +extern char BTCUSERPASS[8192]; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern char ASSETCHAINS_USERPASS[4096]; +extern uint8_t NOTARY_PUBKEY33[33]; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEYHASH[20]; +extern uint8_t ASSETCHAINS_PUBLIC; +extern uint8_t ASSETCHAINS_PRIVATE; +extern uint8_t ASSETCHAINS_TXPOW; +extern uint16_t KMD_PORT; +extern uint16_t BITCOIND_RPCPORT; +extern uint16_t DEST_PORT; +extern uint16_t ASSETCHAINS_P2PPORT; +extern uint16_t ASSETCHAINS_RPCPORT; +extern uint16_t ASSETCHAINS_BEAMPORT; +extern uint16_t ASSETCHAINS_CODAPORT; +extern int32_t KOMODO_INSYNC; +extern int32_t KOMODO_LASTMINED; +extern int32_t prevKOMODO_LASTMINED; +extern int32_t KOMODO_CCACTIVATE; +extern int32_t JUMBLR_PAUSE; +extern int32_t NUM_PRICES; +extern int32_t KOMODO_MININGTHREADS; +extern int32_t STAKED_NOTARY_ID; +extern int32_t USE_EXTERNAL_PUBKEY; +extern int32_t KOMODO_CHOSEN_ONE; +extern int32_t ASSETCHAINS_SEED; +extern int32_t KOMODO_ON_DEMAND; +extern int32_t KOMODO_EXTERNAL_NOTARIES; +extern int32_t KOMODO_PASSPORT_INITDONE; +extern int32_t KOMODO_EXTERNAL_NOTARIES; +extern int32_t KOMODO_PAX; +extern int32_t KOMODO_REWIND; +extern int32_t STAKED_ERA; +extern int32_t KOMODO_CONNECTING; +extern int32_t KOMODO_EXTRASATOSHI; +extern int32_t ASSETCHAINS_FOUNDERS; +extern int32_t ASSETCHAINS_CBMATURITY; +extern int32_t KOMODO_NSPV; +extern int32_t KOMODO_LOADINGBLOCKS; // not actually in komodo_globals.h, but used in several places +extern uint32_t *PVALS; +extern uint32_t ASSETCHAINS_CC; +extern uint32_t KOMODO_STOPAT; +extern uint32_t KOMODO_DPOWCONFS; +extern uint32_t STAKING_MIN_DIFF; +extern uint32_t ASSETCHAIN_INIT; +extern uint32_t ASSETCHAINS_NUMALGOS; +extern uint32_t ASSETCHAINS_MINDIFF[3]; +extern uint64_t PENDING_KOMODO_TX; +extern uint64_t ASSETCHAINS_TIMELOCKGTE; +extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1]; +extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1]; +extern uint64_t ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; +extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1]; +extern uint64_t ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1]; +extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; +extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; +extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; +extern uint64_t ASSETCHAINS_CBOPRET; + +extern std::mutex komodo_mutex; +extern std::vector Mineropret; +extern pthread_mutex_t KOMODO_KV_mutex; +extern pthread_mutex_t KOMODO_CC_mutex; +extern komodo_kv *KOMODO_KV; +extern pax_transaction *PAX; +extern knotaries_entry *Pubkeys; +extern komodo_state KOMODO_STATES[34]; + +int32_t komodo_baseid(char *origbase); +uint64_t komodo_current_supply(uint32_t nHeight); diff --git a/src/komodo_gateway.cpp b/src/komodo_gateway.cpp new file mode 100644 index 00000000000..d840df4574a --- /dev/null +++ b/src/komodo_gateway.cpp @@ -0,0 +1,2723 @@ +/****************************************************************************** + * 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 "komodo.h" +#include "komodo_extern_globals.h" +#include "komodo_utils.h" // komodo_stateptrget +#include "komodo_bitcoind.h" // komodo_checkcommission + +struct komodo_extremeprice +{ + uint256 blockhash; + uint32_t pricebits,timestamp; + int32_t height; + int16_t dir,ind; +} ExtremePrice; + +uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; +int64_t PriceMult[KOMODO_MAXPRICES]; + +struct komodo_priceinfo +{ + FILE *fp; + char symbol[64]; +} PRICES[KOMODO_MAXPRICES]; + +const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) +// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" +const char *Forex[] = +{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" +}; // must be in ECB list + +int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) +{ + int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; + *available = *deposited = *issued = *withdrawn = *approved = *redeemed = 0; + if ( (baseid= komodo_baseid(base)) >= 0 ) + { + if ( (sp= komodo_stateptrget(base)) != 0 ) + { + *deposited = sp->deposited; + *issued = sp->issued; + *withdrawn = sp->withdrawn; + *approved = sp->approved; + *redeemed = sp->redeemed; + maxval = sp->approved; + if ( sp->withdrawn > maxval ) + maxval = sp->withdrawn; + netliability = (sp->issued - maxval) - sp->shorted; + maxallowed = komodo_maxallowed(baseid); + if ( netliability < maxallowed ) + *available = (maxallowed - netliability); + //printf("%llu - %llu %s %.8f %.8f %.8f %.8f %.8f\n",(long long)maxallowed,(long long)netliability,base,dstr(*deposited),dstr(*issued),dstr(*withdrawn),dstr(*approved),dstr(*redeemed)); + return(0); + } else printf("pax_fiatstatus cant get basesp.%s\n",base); + } // else printf("pax_fiatstatus illegal base.%s\n",base); + return(-1); +} + +void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type) +{ + memcpy(buf,&txid,32); + memcpy(&buf[32],&vout,2); + buf[34] = type; +} + +struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type) +{ + struct pax_transaction *pax; uint8_t buf[35]; + std::lock_guard lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + return(pax); +} + +struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout) +{ + struct pax_transaction *pax; int32_t i; uint8_t types[] = { 'I', 'D', 'X', 'A', 'W' }; + for (i=0; i lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + pax->type = type; + memcpy(pax->buf,buf,sizeof(pax->buf)); + HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); + //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark); + } + if ( pax != 0 ) + { + pax->marked = mark; + //if ( height > 214700 || pax->height > 214700 ) + // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); + + } + return(pax); +} + +void komodo_paxdelete(struct pax_transaction *pax) +{ + return; // breaks when out of order + std::lock_guard lock(komodo_mutex); + HASH_DELETE(hh,PAX,pax); +} + +void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context +{ + struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*s; + //if ( KOMODO_PAX == 0 ) + // return; + //if ( strcmp(symbol,ASSETCHAINS_SYMBOL) != 0 ) + // return; + sp = komodo_stateptr(str,dest); + { + std::lock_guard lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + pax->type = type; + memcpy(pax->buf,buf,sizeof(pax->buf)); + HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); + addflag = 1; + if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + { + int32_t i; for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&txid)[i]); + printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); + } + } + } + if ( coinaddr != 0 ) + { + strcpy(pax->coinaddr,coinaddr); + if ( value != 0 ) + pax->komodoshis = value; + if ( symbol != 0 ) + strcpy(pax->symbol,symbol); + if ( source != 0 ) + strcpy(pax->source,source); + if ( fiatoshis != 0 ) + pax->fiatoshis = fiatoshis; + if ( rmd160 != 0 ) + memcpy(pax->rmd160,rmd160,20); + if ( height != 0 ) + pax->height = height; + if ( otherheight != 0 ) + pax->otherheight = otherheight; + } + else + { + pax->marked = height; + //printf("pax.%p MARK DEPOSIT ht.%d other.%d\n",pax,height,otherheight); + } +} + +int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax) +{ + int32_t i,len = 0; + if ( rwflag == 1 ) + { + for (i=0; i<32; i++) + opretbuf[len++] = ((uint8_t *)&pax->txid)[i]; + opretbuf[len++] = pax->vout & 0xff; + opretbuf[len++] = (pax->vout >> 8) & 0xff; + } + else + { + for (i=0; i<32; i++) + ((uint8_t *)&pax->txid)[i] = opretbuf[len++]; + //for (i=0; i<32; i++) + // printf("%02x",((uint8_t *)&pax->txid)[31-i]); + pax->vout = opretbuf[len++]; + pax->vout += ((uint32_t)opretbuf[len++] << 8); + //printf(" txid v.%d\n",pax->vout); + } + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); + if ( rwflag != 0 ) + { + memcpy(&opretbuf[len],pax->rmd160,20), len += 20; + for (i=0; i<4; i++) + opretbuf[len++] = pax->source[i]; + } + else + { + memcpy(pax->rmd160,&opretbuf[len],20), len += 20; + for (i=0; i<4; i++) + pax->source[i] = opretbuf[len++]; + } + return(len); +} + +int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo) +{ + struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + //if ( KOMODO_PAX == 0 ) + // return(0); + incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); + //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 + + // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 + + //for (i=0; i>>>>>> %s: (%s) fiat %.8f kmdheight.%d other.%d -> %s %.8f\n",type=='A'?"approvedA":"issuedX",baseids[n]>=0?CURRENCIES[baseids[n]]:"???",dstr(p.fiatoshis),kmdheights[n],otherheights[n],coinaddr,dstr(values[n])); + } + } + } + else + { + for (i=0; i<4; i++) + base[i] = opretbuf[opretlen-4+i]; + for (j=0; j<32; j++) + { + ((uint8_t *)&txids[n])[j] = opretbuf[len++]; + //printf("%02x",((uint8_t *)&txids[n])[j]); + } + vouts[n] = opretbuf[len++]; + vouts[n] = (opretbuf[len++] << 8) | vouts[n]; + baseids[n] = komodo_baseid(base); + if ( (pax= komodo_paxfinds(txids[n],vouts[n])) != 0 ) + { + values[n] = (strcmp("KMD",base) == 0) ? pax->komodoshis : pax->fiatoshis; + srcvalues[n] = (strcmp("KMD",base) == 0) ? pax->fiatoshis : pax->komodoshis; + kmdheights[n] = pax->height; + otherheights[n] = pax->otherheight; + memcpy(&rmd160s[n * 20],pax->rmd160,20); + } + } + //printf(" komodo_issued_opreturn issuedtxid v%d i.%d opretlen.%d\n",vouts[n],n,opretlen); + } + } + return(n); +} + +int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) +{ + int32_t ratio; + if ( seed == 0 && checkvalue != 0 ) + { + ratio = ((value << 6) / checkvalue); + if ( ratio >= 60 && ratio <= 67 ) + return(0); + else + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); + return(-1); + } + } + else if ( checkvalue != 0 ) + { + ratio = ((value << 10) / checkvalue); + if ( ratio >= 1023 && ratio <= 1025 ) + return(0); + } + return(value != checkvalue); +} + +uint64_t komodo_paxtotal() +{ + struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp; + if ( KOMODO_PASSPORT_INITDONE == 0 ) //KOMODO_PAX == 0 || + return(0); + if ( komodo_isrealtime(&ht) == 0 ) + return(0); + else + { + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->marked != 0 ) + continue; + if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' ) + str = pax->symbol; + else str = pax->source; + basesp = komodo_stateptrget(str); + if ( basesp != 0 && pax->didstats == 0 ) + { + if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) + { + if ( pax2->fiatoshis != 0 ) + { + pax->komodoshis = pax2->komodoshis; + pax->fiatoshis = pax2->fiatoshis; + basesp->issued += pax->fiatoshis; + pax->didstats = 1; + if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p issued %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,str,dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight); + pax2->marked = pax->height; + pax->marked = pax->height; + } + } + else if ( pax->type == 'W' ) + { + //bitcoin_address(coinaddr,addrtype,rmd160,20); + if ( (checktoshis= komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis)) != 0 ) + { + if ( komodo_paxcmp(pax->source,pax->height,pax->komodoshis,checktoshis,seed) != 0 ) + { + pax->marked = pax->height; + //printf("WITHDRAW.%s mark <- %d %.8f != %.8f\n",pax->source,pax->height,dstr(checktoshis),dstr(pax->komodoshis)); + } + else if ( pax->validated == 0 ) + { + pax->validated = pax->komodoshis = checktoshis; + //int32_t j; for (j=0; j<32; j++) + // printf("%02x",((uint8_t *)&pax->txid)[j]); + //if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) + // printf(" v%d %p got WITHDRAW.%s kmd.%d ht.%d %.8f -> %.8f/%.8f\n",pax->vout,pax,pax->source,pax->height,pax->otherheight,dstr(pax->fiatoshis),dstr(pax->komodoshis),dstr(checktoshis)); + } + } + } + } + } + } + komodo_stateptr(symbol,dest); + HASH_ITER(hh,PAX,pax,tmp) + { + pax->ready = 0; + if ( 0 && pax->type == 'A' ) + printf("%p pax.%s <- %s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->symbol,pax->source,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); + if ( pax->marked != 0 ) + continue; + if ( strcmp(symbol,pax->symbol) == 0 || pax->type == 'A' ) + { + if ( pax->marked == 0 ) + { + if ( komodo_is_issuer() != 0 ) + { + if ( pax->validated != 0 && pax->type == 'D' ) + { + total += pax->fiatoshis; + pax->ready = 1; + } + } + else if ( pax->approved != 0 && pax->type == 'A' ) + { + if ( pax->validated != 0 ) + { + total += pax->komodoshis; + pax->ready = 1; + } + else + { + seed = 0; + checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); + //printf("paxtotal PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); + //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); + if ( seed != 0 && checktoshis != 0 ) + { + if ( checktoshis == pax->komodoshis ) + { + total += pax->komodoshis; + pax->validated = pax->komodoshis; + pax->ready = 1; + } else pax->marked = pax->height; + } + } + } + if ( 0 && pax->ready != 0 ) + printf("%p (%c) pax.%s marked.%d %.8f -> %.8f validated.%d approved.%d ready.%d ht.%d\n",pax,pax->type,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0,pax->ready,pax->height); + } + } + } + //printf("paxtotal %.8f\n",dstr(total)); + return(total); +} + +int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order +{ + struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384*4]; int32_t i,n,ht,len=0; uint64_t total = 0; + if ( KOMODO_PAX == 0 || KOMODO_PASSPORT_INITDONE == 0 ) + return(0); + if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) + return(0); + n = 0; + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->type == 'W' ) + { + if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'A')) != 0 ) + { + if ( pax2->approved != 0 ) + pax->approved = pax2->approved; + } + else if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'X')) != 0 ) + pax->approved = pax->height; + //printf("pending_withdraw: pax %s marked.%u approved.%u validated.%llu\n",pax->symbol,pax->marked,pax->approved,(long long)pax->validated); + if ( pax->marked == 0 && pax->approved == 0 && pax->validated != 0 ) //strcmp((char *)"KMD",pax->symbol) == 0 && + { + if ( n < sizeof(paxes)/sizeof(*paxes) ) + { + paxes[n++] = pax; + //int32_t j; for (j=0; j<32; j++) + // printf("%02x",((uint8_t *)&pax->txid)[j]); + //printf(" %s.(kmdht.%d ht.%d marked.%u approved.%d validated %.8f) %.8f\n",pax->source,pax->height,pax->otherheight,pax->marked,pax->approved,dstr(pax->validated),dstr(pax->komodoshis)); + } + } + } + } + opretstr[0] = 0; + if ( n > 0 ) + { + opretbuf[len++] = 'A'; + qsort(paxes,n,sizeof(*paxes),_paxorder); + for (i=0; i>3)*7 ) + len += komodo_rwapproval(1,&opretbuf[len],paxes[i]); + } + if ( len > 0 ) + init_hexbytes_noT(opretstr,opretbuf,len); + } + //fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); + return(len); +} + +int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) +{ + struct pax_transaction *pax,*tmp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint8_t *script,opcode,opret[16384*4],data[16384*4]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask,sum = 0; + if ( KOMODO_PASSPORT_INITDONE == 0 )//KOMODO_PAX == 0 || + return(0); + struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); + sp = komodo_stateptr(symbol,dest); + strcpy(symbol,base); + if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) + return(0); + PENDING_KOMODO_TX = 0; + for (i=0; i<3; i++) + { + if ( komodo_isrealtime(&ht) != 0 ) + break; + sleep(1); + } + if ( i == 3 ) + { + if ( tokomodo == 0 ) + printf("%s not realtime ht.%d\n",ASSETCHAINS_SYMBOL,ht); + return(0); + } + if ( tokomodo == 0 ) + { + opcode = 'I'; + } + else + { + opcode = 'X'; + if ( 1 || komodo_paxtotal() == 0 ) + return(0); + } + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->type != 'D' && pax->type != 'A' ) + continue; + { +#ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE + if ( pax->height > 236000 ) + { + if ( kmdsp != 0 && kmdsp->NOTARIZED_HEIGHT >= pax->height ) + pax->validated = pax->komodoshis; + else if ( kmdsp->CURRENT_HEIGHT > pax->height+30 ) + pax->validated = pax->ready = 0; + } + else + { + if ( kmdsp != 0 && (kmdsp->NOTARIZED_HEIGHT >= pax->height || kmdsp->CURRENT_HEIGHT > pax->height+30) ) // assumes same chain as notarize + pax->validated = pax->komodoshis; + else pax->validated = pax->ready = 0; + } +#else + pax->validated = pax->komodoshis; +#endif + } + if ( ASSETCHAINS_SYMBOL[0] != 0 && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) + { + //if ( pax->height > 214700 || strcmp(ASSETCHAINS_SYMBOL,symbol) == 0 ) + // printf("miner.[%s]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed)); + continue; + } + /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); + if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) + { + printf("reject 2\n"); + continue; + }*/ + if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) ) + { + if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 ) + printf("pax->symbol.%s != %s or null pax->validated %.8f ready.%d ht.(%d %d)\n",pax->symbol,symbol,dstr(pax->validated),pax->ready,kmdsp->CURRENT_HEIGHT,pax->height); + pax->marked = pax->height; + continue; + } + if ( pax->ready == 0 ) + continue; + if ( pax->type == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( kmdsp != 0 ) + { + if ( (baseid= komodo_baseid(pax->symbol)) < 0 || ((1LL << baseid) & sp->RTmask) == 0 ) + { + printf("not RT for (%s) %llx baseid.%d %llx\n",pax->symbol,(long long)sp->RTmask,baseid,(long long)(1LL< %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); + if ( opcode == 'I' ) + { + sum += pax->fiatoshis; + if ( sum > available ) + break; + } + txNew->vout.resize(numvouts+1); + txNew->vout[numvouts].nValue = (opcode == 'I') ? pax->fiatoshis : pax->komodoshis; + txNew->vout[numvouts].scriptPubKey.resize(25); + script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; + *script++ = 0x76; + *script++ = 0xa9; + *script++ = 20; + memcpy(script,pax->rmd160,20), script += 20; + *script++ = 0x88; + *script++ = 0xac; + if ( tokomodo == 0 ) + { + for (i=0; i<32; i++) + data[len++] = ((uint8_t *)&pax->txid)[i]; + data[len++] = pax->vout & 0xff; + data[len++] = (pax->vout >> 8) & 0xff; + PENDING_KOMODO_TX += pax->fiatoshis; + } + else + { + len += komodo_rwapproval(1,&data[len],pax); + PENDING_KOMODO_TX += pax->komodoshis; + printf(" len.%d vout.%u DEPOSIT %.8f <- pax.%s pending ht %d %d %.8f | ",len,pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,pax->height,pax->otherheight,dstr(PENDING_KOMODO_TX)); + } + if ( numvouts++ >= 64 || sum > COIN ) + break; + } + if ( numvouts > 1 ) + { + if ( tokomodo != 0 ) + strcpy(symbol,(char *)"KMD"); + for (i=0; symbol[i]!=0; i++) + data[len++] = symbol[i]; + data[len++] = 0; + for (i=0; ivout.resize(numvouts+1); + txNew->vout[numvouts].nValue = 0; + txNew->vout[numvouts].scriptPubKey.resize(opretlen); + script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; + memcpy(script,opret,opretlen); + for (i=0; i<8; i++) + printf("%02x",opret[i]); + printf(" <- opret, MINER deposits.%d (%s) vouts.%d %.8f opretlen.%d\n",tokomodo,ASSETCHAINS_SYMBOL,numvouts,dstr(PENDING_KOMODO_TX),opretlen); + return(1); + } + return(0); +} + +const char *banned_txids[] = +{ + "78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", // vout1 only 233559 + "00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172 + "e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187 + "f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188 + "abf08be07d8f5b3a433ddcca7ef539e79a3571632efd6d0294ec0492442a0204", //234213 + "3b854b996cc982fba8c06e76cf507ae7eed52ab92663f4c0d7d10b3ed879c3b0", //234367 + "fa9e474c2cda3cb4127881a40eb3f682feaba3f3328307d518589024a6032cc4", //234635 + "ca746fa13e0113c4c0969937ea2c66de036d20274efad4ce114f6b699f1bc0f3", //234662 + "43ce88438de4973f21b1388ffe66e68fda592da38c6ef939be10bb1b86387041", //234697 + "0aeb748de82f209cd5ff7d3a06f65543904c4c17387c9d87c65fd44b14ad8f8c", //234899 + "bbd3a3d9b14730991e1066bd7c626ca270acac4127131afe25f877a5a886eb25", //235252 + "fa9943525f2e6c32cbc243294b08187e314d83a2870830180380c3c12a9fd33c", //235253 + "a01671c8775328a41304e31a6693bbd35e9acbab28ab117f729eaba9cb769461", //235265 + "2ef49d2d27946ad7c5d5e4ab5c089696762ff04e855f8ab48e83bdf0cc68726d", //235295 + "c85dcffb16d5a45bd239021ad33443414d60224760f11d535ae2063e5709efee", //235296 + // all vouts banned + "c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748 + "305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204 + //"43416a0c4da6b1a5c1d375bdbe8f7dc8d44d8f60df593d3376aa8221ec66357e", // vout0 only + //"1eb295ed54c47f35cbccd7e7e40d03041f1853581da6d41102a9d8813782b6cb", + //"db121e4012222adfc841824984a2a90b7e5b018dd71307822537d58160195e43", + //"28f95b8148ac4ae6e09c7380e34422fab41d568a411e53dc94823e36a3d6f386", + //"01d8c839463bda2f2f6400ede4611357913684927a767422a8560ead1b22557c", + //"6e4980a9e1bd669f4df04732dc6f11b7773b6de88d1abcf89a6b9007d72ef9ac", + //"6cc1d0495170bc0e11fd3925297623562e529ea1336b66ea61f8a1159041aed2", + //"250875424cece9bcd98cb226b09da7671625633d6958589e3a462bad89ad87cc", // missed + //"ea8659011de52f4dac42cda12326064b7b5013b8492f88e33159884ca299aa05", // missed + //"ce567928b5490a17244167af161b1d8dd6ff753fef222fe6855d95b2278a35b3", // missed +}; + +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; + if ( sizeof(banned_txids)/sizeof(*banned_txids) > max ) + { + fprintf(stderr,"komodo_bannedset: buffer too small %d vs %d\n",(int32_t)(sizeof(banned_txids)/sizeof(*banned_txids)),max); + StartShutdown(); + } + for (i=0; i 1 && block.vtx[txn_count-1].vout.size() > 0 && block.vtx[txn_count-1].vout[0].nValue == 5000 ) + { + /* + if ( block.vtx[txn_count-1].vin.size() == 1 && GetTransaction(block.vtx[txn_count-1].vin[0].prevout.hash,tx,hash,false) && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) + notmatched = 1; + */ + if ( block.vtx[txn_count-1].vin.size() == 1 ) { + uint256 hashNotaryProofVin = block.vtx[txn_count-1].vin[0].prevout.hash; + int fNotaryProofVinTxFound = GetTransaction(hashNotaryProofVin,tx,hash,false); + if (!fNotaryProofVinTxFound) { + // try to search in the same block + BOOST_FOREACH(const CTransaction &txInThisBlock, block.vtx) { + if (txInThisBlock.GetHash() == hashNotaryProofVin) { + fNotaryProofVinTxFound = 1; + tx = txInThisBlock; + hash = block.GetHash(); + break; + } + } + } + if ( fNotaryProofVinTxFound && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) + { + notmatched = 1; + } + } + } + n = block.vtx[i].vin.size(); + for (j=0; j= indallvouts) ) + { + printf("banned tx.%d being used at ht.%d txi.%d vini.%d\n",k,height,i,j); + return(-1); + } + } + } + } + } + // we don't want these checks in VRSC, leave it at the Sapling upgrade + if ( ASSETCHAINS_SYMBOL[0] == 0 || + ((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) || + NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) ) + { + n = block.vtx[0].vout.size(); + int64_t val,prevtotal = 0; int32_t strangeout=0,overflow = 0; + total = 0; + for (i=1; i= MAX_MONEY ) + { + overflow = 1; + break; + } + if ( i > 1 && script[0] != 0x6a && val < 5000 ) + strangeout++; + total += val; + if ( total < prevtotal || (val != 0 && total == prevtotal) ) + { + overflow = 1; + break; + } + prevtotal = total; + } + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( overflow != 0 || total > COIN/10 ) + { + if ( height >= activation ) + { + if ( height > 800000 ) + fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); + return(-1); + } + } + else if ( block.nBits == KOMODO_MINDIFF_NBITS && total > 0 ) // to deal with fee stealing + { + fprintf(stderr,"notary mined ht.%d with extra %.8f\n",height,dstr(total)); + if ( height > KOMODO_NOTARIES_HEIGHT1 ) + return(-1); + } + if ( strangeout != 0 || notmatched != 0 ) + { + if ( 0 && strcmp(NOTARY_PUBKEY.c_str(),"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828") == 0 ) + fprintf(stderr,">>>>>>>>>>>>> DUST ht.%d strangout.%d notmatched.%d <<<<<<<<<\n",height,strangeout,notmatched); + if ( height > 1000000 && strangeout != 0 ) + return(-1); + } + else if ( height > 814000 ) + { + script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; + //int32_t notary = komodo_electednotary(&num,script+1,height,0); + //if ( (-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)) < 0 ) + // fprintf(stderr, ">>>>>>> FAILED BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); + //else + // fprintf(stderr, "<<<<<<< VALID BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); + return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); + } + } + else + { + checktoshis = 0; + if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1 ) + { + if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) + { + fprintf(stderr,"ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); + return(-1); + } + } + if ( height > 1 && checktoshis == 0 ) + { + checktoshis = ((uint64_t)GetBlockSubsidy(height, Params().GetConsensus()) - block.vtx[0].vout[0].nValue); + // some pools will need to change their pool fee to be (poolfee % - txfees) + //checktoshis += txn_count * 0.001; // rely on higher level validations to prevent emitting more coins than actual txfees + } + if ( height >= 2 && (overflow != 0 || total > checktoshis || strangeout != 0) ) + { + fprintf(stderr,"checkdeposit: ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); + if ( strangeout != 0 ) + fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangeout.%d notmatched.%d <<<<<<<<<\n",ASSETCHAINS_SYMBOL,height,strangeout,notmatched); + return(-1); + } + } + } + return(0); +} + +const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) +{ + uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; + const char *typestr = "unknown"; + if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) + { + //printf("komodo_opreturn skip %s\n",ASSETCHAINS_SYMBOL); + return("assetchain"); + } + memset(baseids,0xff,sizeof(baseids)); + memset(values,0,sizeof(values)); + memset(srcvalues,0,sizeof(srcvalues)); + memset(rmd160s,0,sizeof(rmd160s)); + memset(kmdheights,0,sizeof(kmdheights)); + memset(otherheights,0,sizeof(otherheights)); + tokomodo = (komodo_is_issuer() == 0); + if ( opretbuf[0] == 'K' && opretlen != 40 ) + { + komodo_kvupdate(opretbuf,opretlen,value); + return("kv"); + } + else if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_PAX == 0 ) + return("nopax"); + if ( opretbuf[0] == 'D' ) + { + tokomodo = 0; + if ( opretlen == 38 ) // any KMD tx + { + iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); + memset(base,0,sizeof(base)); + PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis); + bitcoin_address(coinaddr,addrtype,rmd160,20); + checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,fiatoshis); + if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) != 0 ) + checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,height,base,fiatoshis); + typestr = "deposit"; + if ( 0 && strcmp("NOK",base) == 0 ) + { + printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); + printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&txid)[i]); + printf(" <- txid.v%u ",vout); + for (i=0; i<33; i++) + printf("%02x",pubkey33[i]); + printf(" checkpubkey check %.8f v %.8f dest.(%s) kmdheight.%d height.%d\n",dstr(checktoshis),dstr(value),destaddr,kmdheight,height); + } + if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 && (kmdheight > 195000 || kmdheight <= height) ) + { + didstats = 0; + if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) == 0 ) + { + if ( (pax= komodo_paxfind(txid,vout,'D')) == 0 ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->deposited += fiatoshis; + didstats = 1; + if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p deposited %s += %.8f kmdheight.%d %.8f\n",basesp,base,dstr(fiatoshis),kmdheight,dstr(value)); + } else printf("cant get stateptr.(%s)\n",base); + komodo_gateway_deposit(coinaddr,value,base,fiatoshis,rmd160,txid,vout,'D',kmdheight,height,(char *)"KMD",0); + } + if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) + { + pax->height = kmdheight; + pax->validated = value; + pax->komodoshis = value; + pax->fiatoshis = fiatoshis; + if ( didstats == 0 && pax->didstats == 0 ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->deposited += fiatoshis; + didstats = 1; + if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p depositedB %s += %.8f/%.8f kmdheight.%d/%d %.8f/%.8f\n",basesp,base,dstr(fiatoshis),dstr(pax->fiatoshis),kmdheight,pax->height,dstr(value),dstr(pax->komodoshis)); + } + } // + if ( didstats != 0 ) + pax->didstats = 1; + if ( (pax2= komodo_paxfind(txid,vout,'I')) != 0 ) + { + pax2->fiatoshis = pax->fiatoshis; + pax2->komodoshis = pax->komodoshis; + pax->marked = pax2->marked = pax->height; + pax2->height = pax->height = height; + if ( pax2->didstats == 0 ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->issued += pax2->fiatoshis; + pax2->didstats = 1; + if ( 0 && strcmp(base,"USD") == 0 ) + printf("########### %p issueda %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,base,dstr(pax2->fiatoshis),pax2->height,dstr(pax2->komodoshis),pax2->otherheight,height); + } + } + } + } + } + else + { + if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) + pax->marked = checktoshis; + if ( kmdheight > 238000 && (kmdheight > 214700 || strcmp(base,ASSETCHAINS_SYMBOL) == 0) ) //seed != 0 && + printf("pax %s deposit %.8f rejected kmdheight.%d %.8f KMD check %.8f seed.%llu\n",base,dstr(fiatoshis),kmdheight,dstr(value),dstr(checktoshis),(long long)seed); + } + } //else printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); + } //else printf("unsupported size.%d for opreturn D\n",opretlen); + } + else if ( opretbuf[0] == 'I' ) + { + tokomodo = 0; + if ( strncmp((char *)"KMD",(char *)&opretbuf[opretlen-4],3) != 0 && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 ) + { + if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,0)) > 0 ) + { + for (i=0; itype = opretbuf[0]; + strcpy(pax->source,(char *)&opretbuf[opretlen-4]); + if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 && pax2->fiatoshis != 0 && pax2->komodoshis != 0 ) + { + // realtime path? + pax->fiatoshis = pax2->fiatoshis; + pax->komodoshis = pax2->komodoshis; + pax->marked = pax2->marked = pax2->height; + if ( pax->didstats == 0 ) + { + if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->issued += pax->fiatoshis; + pax->didstats = 1; + pax->height = pax2->height; + pax->otherheight = height; + if ( 1 && strcmp(CURRENCIES[baseids[i]],"USD") == 0 ) + printf("########### %p issuedb %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,CURRENCIES[baseids[i]],dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight,height); + } + } + } + } + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'I',height)) != 0 ) + komodo_paxdelete(pax); + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'D',height)) != 0 ) + komodo_paxdelete(pax); + } + } //else printf("opreturn none issued?\n"); + } + } + else if ( height < 236000 && opretbuf[0] == 'W' && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 )//&& opretlen >= 38 ) + { + if ( komodo_baseid((char *)&opretbuf[opretlen-4]) >= 0 && strcmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4]) == 0 ) + { + for (i=0; i (%s) len.%d\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen); + didstats = 0; + //if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) + { + if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->withdrawn += value; + didstats = 1; + if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p withdrawn %s += %.8f check %.8f\n",basesp,base,dstr(value),dstr(checktoshis)); + } + if ( 0 && strcmp(base,"RUB") == 0 && (pax == 0 || pax->approved == 0) ) + printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); + } + komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); + if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) + { + pax->type = opretbuf[0]; + strcpy(pax->source,base); + strcpy(pax->symbol,"KMD"); + pax->height = kmdheight; + pax->otherheight = height; + pax->komodoshis = komodoshis; + } + } // else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis)); + // need to allocate pax + } + else if ( height < 236000 && tokomodo != 0 && opretbuf[0] == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) + { + tokomodo = 1; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + { + for (i=0; i 0 ) + { + for (i=0; isymbol); + printf("override neg1 with (%s)\n",pax->symbol); + } + if ( baseids[i] < 0 ) + continue; + } + didstats = 0; + seed = 0; + checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)values[i]); + //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)values[i]/COIN,(double)srcvalues[i]/COIN,(double)checktoshis/COIN); + if ( srcvalues[i] == checktoshis ) + { + if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) + { + bitcoin_address(coinaddr,60,&rmd160s[i*20],20); + komodo_gateway_deposit(coinaddr,srcvalues[i],CURRENCIES[baseids[i]],values[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); + if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) + printf("unexpected null pax for approve\n"); + else pax->validated = checktoshis; + if ( (pax2= komodo_paxfind(txids[i],vouts[i],'W')) != 0 ) + pax2->approved = kmdheights[i]; + komodo_paxmark(height,txids[i],vouts[i],'W',height); + //komodo_paxmark(height,txids[i],vouts[i],'A',height); + if ( values[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->approved += values[i]; + didstats = 1; + //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); + } + //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); + } + else if ( pax->didstats == 0 && srcvalues[i] != 0 ) + { + if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->approved += values[i]; + didstats = 1; + //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); + } + } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); + if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) + { + pax->type = opretbuf[0]; + pax->approved = kmdheights[i]; + pax->validated = checktoshis; + if ( didstats != 0 ) + pax->didstats = 1; + //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) + //printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); + } + } + } + } //else printf("n.%d from opreturns\n",n); + //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); + } + else if ( height < 236000 && opretbuf[0] == 'X' && ASSETCHAINS_SYMBOL[0] == 0 ) + { + tokomodo = 1; + if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 ) + { + for (i=0; itype = opretbuf[0]; + if ( height < 121842 ) // fields got switched around due to legacy issues and approves + value = srcvalues[i]; + else value = values[i]; + if ( baseids[i] >= 0 && value != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->redeemed += value; + pax->didstats = 1; + if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) + printf("ht.%d %.8f ########### %p redeemed %s += %.8f %.8f kht.%d ht.%d\n",height,dstr(value),basesp,CURRENCIES[baseids[i]],dstr(value),dstr(srcvalues[i]),kmdheights[i],otherheights[i]); + } + } + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'W',height)) != 0 ) + komodo_paxdelete(pax); + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'A',height)) != 0 ) + komodo_paxdelete(pax); + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'X',height)) != 0 ) + komodo_paxdelete(pax); + } + } //else printf("komodo_issued_opreturn returned %d\n",n); + } + return(typestr); +} + +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); + +void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest) +{ + uint8_t func; long lastK,lastT,lastN,lastV,fpos,lastfpos; int32_t i,count,doissue,iter,numn,numv,numN,numV,numR; uint32_t tmp,prevpos100,offset; + count = numR = numN = numV = numn = numv = 0; + lastK = lastT = lastN = lastV = -1; + for (iter=0; iter<2; iter++) + { + for (lastfpos=fpos=prevpos100=i=0; i> 8); + fpos = prevpos100 + offset; + if ( lastfpos >= datalen || (filedata[lastfpos] != func && func != 0) ) + printf("i.%d/n.%d lastfpos.%ld >= datalen.%ld or [%d] != func.%d\n",i,n,lastfpos,datalen,filedata[lastfpos],func); + else if ( iter == 0 ) + { + switch ( func ) + { + default: case 'P': case 'U': case 'D': + inds[i] &= 0xffffff00; + break; + case 'K': + lastK = lastfpos; + inds[i] &= 0xffffff00; + break; + case 'T': + lastT = lastfpos; + inds[i] &= 0xffffff00; + break; + case 'N': + lastN = lastfpos; + numN++; + break; + case 'V': + lastV = lastfpos; + numV++; + break; + case 'R': + numR++; + break; + } + } + else + { + doissue = 0; + if ( func == 'K' ) + { + if ( lastK == lastfpos ) + doissue = 1; + } + else if ( func == 'T' ) + { + if ( lastT == lastfpos ) + doissue = 1; + } + else if ( func == 'N' ) + { + if ( numn > numN-128 ) + doissue = 1; + numn++; + } + else if ( func == 'V' ) + { + if ( KOMODO_PAX != 0 && numv > numV-1440 ) + doissue = 1; + numv++; + } + else if ( func == 'R' ) + doissue = 1; + if ( doissue != 0 ) + { + //printf("issue %c total.%d lastfpos.%ld\n",func,count,lastfpos); + komodo_parsestatefiledata(sp,filedata,&lastfpos,datalen,symbol,dest); + count++; + } + } + } + lastfpos = fpos; + } + } + printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); + /*else if ( func == 'K' ) // KMD height: stop after 1st + else if ( func == 'T' ) // KMD height+timestamp: stop after 1st + + else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; + else if ( func == 'V' ) // price feed: can stop after 1440+ + else if ( func == 'R' ) // opreturn:*/ +} + +void *OS_loadfile(const char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +{ + FILE *fp; + long filesize,buflen = *allocsizep; + uint8_t *buf = *bufp; + *lenp = 0; + if ( (fp= fopen(fname,"rb")) != 0 ) + { + fseek(fp,0,SEEK_END); + filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *lenp = 0; + printf("OS_loadfile null size.(%s)\n",fname); + return(0); + } + if ( filesize > buflen ) + { + *allocsizep = filesize; + *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); + } + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + buf[filesize] = 0; + } + fclose(fp); + *lenp = filesize; + //printf("loaded.(%s)\n",buf); + } //else printf("OS_loadfile couldnt load.(%s)\n",fname); + return(buf); +} + +uint8_t *OS_fileptr(long *allocsizep,const char *fname) +{ + long filesize = 0; uint8_t *buf = 0; void *retptr; + *allocsizep = 0; + retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); + return((uint8_t *)retptr); +} + +long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest) +{ + FILE *fp; long fsize,lastfpos=0,fpos=0; uint8_t *inds,func; int32_t i,n; uint32_t offset,tmp,prevpos100 = 0; + *indcounterp = *prevpos100p = 0; + if ( (inds= OS_fileptr(&fsize,indfname)) != 0 ) + { + lastfpos = 0; + fprintf(stderr,"inds.%p validate %s fsize.%ld datalen.%ld n.%d lastfpos.%ld\n",inds,indfname,fsize,datalen,(int32_t)(fsize / sizeof(uint32_t)),lastfpos); + if ( (fsize % sizeof(uint32_t)) == 0 ) + { + n = (int32_t)(fsize / sizeof(uint32_t)); + for (i=0; i n-10 ) + printf("%d: tmp.%08x [%c] prevpos100.%u\n",i,tmp,tmp&0xff,prevpos100); + if ( (i % 100) == 0 ) + prevpos100 = tmp; + else + { + func = (tmp & 0xff); + offset = (tmp >> 8); + fpos = prevpos100 + offset; + if ( lastfpos >= datalen || filedata[lastfpos] != func ) + { + printf("validate.%d error (%u %d) prev100 %u -> fpos.%ld datalen.%ld [%d] (%c) vs (%c) lastfpos.%ld\n",i,offset,func,prevpos100,fpos,datalen,lastfpos < datalen ? filedata[lastfpos] : -1,func,filedata[lastfpos],lastfpos); + return(-1); + } + } + lastfpos = fpos; + } + *indcounterp = n; + *prevpos100p = prevpos100; + if ( sp != 0 ) + komodo_stateind_set(sp,(uint32_t *)inds,n,filedata,fpos,symbol,dest); + //printf("free inds.%p %s validated[%d] fpos.%ld datalen.%ld, offset %ld vs fsize.%ld\n",inds,indfname,i,fpos,datalen,i * sizeof(uint32_t),fsize); + free(inds); + return(fpos); + } else printf("wrong filesize %s %ld\n",indfname,fsize); + } + free(inds); + fprintf(stderr,"indvalidate return -1\n"); + return(-1); +} + +long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp) +{ + uint32_t tmp; + if ( indfp != 0 ) + { + tmp = ((uint32_t)(newfpos - *prevpos100p) << 8) | (func & 0xff); + if ( ftell(indfp)/sizeof(uint32_t) != *indcounterp ) + printf("indfp fpos %ld -> ind.%ld vs counter.%u\n",ftell(indfp),ftell(indfp)/sizeof(uint32_t),*indcounterp); + //fprintf(stderr,"ftell.%ld indcounter.%u lastfpos.%ld newfpos.%ld func.%02x\n",ftell(indfp),*indcounterp,lastfpos,newfpos,func); + fwrite(&tmp,1,sizeof(tmp),indfp), (*indcounterp)++; + if ( (*indcounterp % 100) == 0 ) + { + *prevpos100p = (uint32_t)newfpos; + fwrite(prevpos100p,1,sizeof(*prevpos100p),indfp), (*indcounterp)++; + } + } + return(newfpos); +} + +int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest) +{ + FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; + starttime = (uint32_t)time(NULL); + safecopy(indfname,fname,sizeof(indfname)-4); + strcat(indfname,".ind"); + if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) + { + if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) + { + lastfpos = fpos = 0; + indcounter = prevpos100 = 0; + if ( (indfp= fopen(indfname,"wb")) != 0 ) + fwrite(&prevpos100,1,sizeof(prevpos100),indfp), indcounter++; + fprintf(stderr,"processing %s %ldKB, validated.%ld\n",fname,datalen/1024,validated); + while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) + { + lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); + } + if ( indfp != 0 ) + { + fclose(indfp); + if ( (fpos= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) + printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); + else printf("%s validated fpos.%ld\n",indfname,fpos); + } + finished = 1; + fprintf(stderr,"took %d seconds to process %s %ldKB\n",(int32_t)(time(NULL)-starttime),fname,datalen/1024); + } + else if ( validated > 0 ) + { + if ( (indfp= fopen(indfname,"rb+")) != 0 ) + { + lastfpos = fpos = validated; + fprintf(stderr,"datalen.%ld validated %ld -> indcounter %u, prevpos100 %u offset.%d\n",datalen,validated,indcounter,prevpos100,(int32_t)(indcounter * sizeof(uint32_t))); + if ( fpos < datalen ) + { + fseek(indfp,indcounter * sizeof(uint32_t),SEEK_SET); + if ( ftell(indfp) == indcounter * sizeof(uint32_t) ) + { + while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) + { + lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); + if ( lastfpos != fpos ) + fprintf(stderr,"unexpected lastfpos.%ld != %ld\n",lastfpos,fpos); + } + } + fclose(indfp); + } + if ( komodo_stateind_validate(sp,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest) < 0 ) + printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); + else + { + printf("%s validated updated from validated.%ld to %ld new.[%ld] -> indcounter %u, prevpos100 %u offset.%ld | elapsed %d seconds\n",indfname,validated,fpos,fpos-validated,indcounter,prevpos100,indcounter * sizeof(uint32_t),(int32_t)(time(NULL) - starttime)); + finished = 1; + } + } + } else printf("komodo_faststateinit unexpected case\n"); + free(filedata); + return(finished == 1); + } + return(-1); +} + +uint64_t komodo_interestsum(); + +void komodo_passport_iteration() +{ + static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; + int32_t maxseconds = 10; + FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex; + expired = 0; + while ( 0 && KOMODO_INITDONE == 0 ) + { + fprintf(stderr,"[%s] PASSPORT iteration waiting for KOMODO_INITDONE\n",ASSETCHAINS_SYMBOL); + sleep(3); + } + if ( komodo_chainactive_timestamp() > lastinterest ) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + komodo_interestsum(); + //komodo_longestchain(); + lastinterest = komodo_chainactive_timestamp(); + } + refsp = komodo_stateptr(symbol,dest); + if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDCC") == 0 ) + { + refid = 33; + limit = 10000000; + jumblr_iteration(); + } + else + { + limit = 10000000; + refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 + if ( refid == 0 ) + { + KOMODO_PASSPORT_INITDONE = 1; + return; + } + } + /*if ( KOMODO_PAX == 0 ) + { + KOMODO_PASSPORT_INITDONE = 1; + return; + }*/ + starttime = (uint32_t)time(NULL); + if ( callcounter++ < 1 ) + limit = 10000; + lasttime = starttime; + for (baseid=32; baseid>=0; baseid--) + { + if ( time(NULL) >= starttime+maxseconds ) + break; + sp = 0; + isrealtime = 0; + base = (char *)CURRENCIES[baseid]; + //printf("PASSPORT %s baseid+1 %d refid.%d\n",ASSETCHAINS_SYMBOL,baseid+1,refid); + if ( baseid+1 != refid ) // only need to import state from a different coin + { + if ( baseid == 32 ) // only care about KMD's state + { + refsp->RTmask &= ~(1LL << baseid); + komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); + komodo_nameset(symbol,dest,base); + sp = komodo_stateptrget(symbol); + n = 0; + if ( lastpos[baseid] == 0 && (filedata= OS_fileptr(&datalen,fname)) != 0 ) + { + fpos = 0; + fprintf(stderr,"%s processing %s %ldKB\n",ASSETCHAINS_SYMBOL,fname,datalen/1024); + while ( komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest) >= 0 ) + lastfpos = fpos; + fprintf(stderr,"%s took %d seconds to process %s %ldKB\n",ASSETCHAINS_SYMBOL,(int32_t)(time(NULL)-starttime),fname,datalen/1024); + lastpos[baseid] = lastfpos; + free(filedata), filedata = 0; + datalen = 0; + } + else if ( (fp= fopen(fname,"rb")) != 0 && sp != 0 ) + { + fseek(fp,0,SEEK_END); + //fprintf(stderr,"couldnt OS_fileptr(%s), freading %ldKB\n",fname,ftell(fp)/1024); + if ( ftell(fp) > lastpos[baseid] ) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("%s passport refid.%d %s fname.(%s) base.%s %ld %ld\n",ASSETCHAINS_SYMBOL,refid,symbol,fname,base,ftell(fp),lastpos[baseid]); + fseek(fp,lastpos[baseid],SEEK_SET); + while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 && n < limit ) + { + if ( n == limit-1 ) + { + if ( time(NULL) < starttime+maxseconds ) + n = 0; + else + { + //printf("expire passport loop %s -> %s at %ld\n",ASSETCHAINS_SYMBOL,base,lastpos[baseid]); + expired++; + } + } + n++; + } + lastpos[baseid] = ftell(fp); + if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 ) + printf("from.(%s) lastpos[%s] %ld isrt.%d\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid],komodo_isrealtime(&ht)); + } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); + fclose(fp); + } else fprintf(stderr,"load error.(%s) %p\n",fname,sp); + komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); + if ( (fp= fopen(fname,"rb")) != 0 ) + { + if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) + { + sp->CURRENT_HEIGHT = buf[0]; + if ( buf[0] != 0 && buf[0] >= buf[1] && buf[2] > time(NULL)-60 ) + { + isrealtime = 1; + RTmask |= (1LL << baseid); + memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); + } + else if ( KOMODO_PAX != 0 && (time(NULL)-buf[2]) > 60 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"[%s]: %s not RT %u %u %d\n",ASSETCHAINS_SYMBOL,base,buf[0],buf[1],(int32_t)(time(NULL)-buf[2])); + } //else fprintf(stderr,"%s size error RT\n",base); + fclose(fp); + } //else fprintf(stderr,"%s open error RT\n",base); + } + } + else + { + refsp->RTmask &= ~(1LL << baseid); + komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + buf[0] = (uint32_t)chainActive.LastTip()->GetHeight(); + buf[1] = (uint32_t)komodo_longestchain(); + if ( buf[0] != 0 && buf[0] == buf[1] ) + { + buf[2] = (uint32_t)time(NULL); + RTmask |= (1LL << baseid); + memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); + if ( refid != 0 ) + memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); + } + if ( fwrite(buf,1,sizeof(buf),fp) != sizeof(buf) ) + fprintf(stderr,"[%s] %s error writing realtime\n",ASSETCHAINS_SYMBOL,base); + fclose(fp); + } else fprintf(stderr,"%s create error RT\n",base); + } + if ( sp != 0 && isrealtime == 0 ) + refsp->RTbufs[0][2] = 0; + } + //komodo_paxtotal(); // calls komodo_isrealtime(), which calls komodo_longestchain() + refsp->RTmask |= RTmask; + if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) + { + KOMODO_PASSPORT_INITDONE = 1; + printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); + } +} + +void komodo_PriceCache_shift() +{ + int32_t i; + for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--) + memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i])); + memcpy(PriceCache[0],Mineropret.data(),Mineropret.size()); +} + +int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block) +{ + CTransaction tx; int32_t numvouts; std::vector vopret; + tx = block->vtx[0]; + numvouts = (int32_t)tx.vout.size(); + GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); + if ( vopret.size() >= PRICES_SIZEBIT0 ) + { + if ( seedp != 0 ) + memcpy(seedp,&block->hashMerkleRoot,sizeof(*seedp)); + memcpy(heightbits,vopret.data(),vopret.size()); + return((int32_t)(vopret.size()/sizeof(uint32_t))); + } + return(-1); +} + +// komodo_heightpricebits() extracts the price data in the coinbase for nHeight +int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight) +{ + CBlockIndex *pindex; CBlock block; + if ( seedp != 0 ) + *seedp = 0; + if ( (pindex= komodo_chainactive(nHeight)) != 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + { + return(_komodo_heightpricebits(seedp,heightbits,&block)); + } + } + fprintf(stderr,"couldnt get pricebits for %d\n",nHeight); + return(-1); +} + +/* + komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit + */ +uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance) +{ + uint64_t highprice,lowprice; + if ( refprice < 2 ) + return(0); + highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price + lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest + if ( highprice == refprice ) + highprice++; + if ( lowprice == refprice ) + lowprice--; + if ( price >= highprice ) + { + //fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); + if ( price > highprice ) // return non-zero only if we violate the tolerance + { + *maxflagp = 2; + return(highprice); + } + *maxflagp = 1; + } + else if ( price <= lowprice ) + { + //fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); + if ( price < lowprice ) + { + *maxflagp = -2; + return(lowprice); + } + *maxflagp = -1; + } + return(0); +} + +// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance +int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance) +{ + int32_t i; uint32_t newprice; + for (i=1; i newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]); + return(-1); + } + } + return(0); +} + +// komodo_priceclamp() clamps any price that is beyond tolerance +int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance) +{ + int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES]; + memset(maxflags,0,sizeof(maxflags)); + for (i=1; i %u\n",i,n,refprices[i],pricebits[i],newprice); + pricebits[i] = newprice; + } + } + return(0); +} + +// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight +CScript komodo_mineropret(int32_t nHeight) +{ + CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0; + if ( Mineropret.size() >= PRICES_SIZEBIT0 ) + { + n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); + numzero = 1; + while ( numzero > 0 ) + { + memcpy(pricebits,Mineropret.data(),Mineropret.size()); + for (i=numzero=0; i 0 ) + { + memcpy(pricebits,Mineropret.data(),Mineropret.size()); + memset(maxflags,0,sizeof(maxflags)); + if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 ) + { + // if the new prices are outside tolerance, update Mineropret with clamped prices + komodo_priceclamp(n,pricebits,prevbits,PRICES_ERRORRATE); + //fprintf(stderr,"update Mineropret to clamped prices\n"); + memcpy(Mineropret.data(),pricebits,Mineropret.size()); + } + } + int32_t i; + for (i=0; i vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; + now = (uint32_t)time(NULL); + if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) + { + bhash = block->GetHash(); + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() >= PRICES_SIZEBIT0 ) + { + n = (int32_t)(vopret.size() / sizeof(uint32_t)); + memcpy(pricebits,vopret.data(),Mineropret.size()); + memset(maxflags,0,sizeof(maxflags)); + if ( nHeight > 2 ) + { + prevtime = previndex->nTime; + lag = (int32_t)(now - pricebits[0]); + lag2 = (int32_t)(pricebits[0] - prevtime); + lag3 = (int32_t)(block->nTime - pricebits[0]); + if ( lag < -60 ) // avoid data from future + { + fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); + return(-1); + } + if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp + { + fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME); + if ( nHeight > testchain_exemption ) + return(-1); + } + if ( lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME ) + { + fprintf(stderr,"C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); + if ( nHeight > testchain_exemption ) + return(-1); + } + btcusd = (double)pricebits[1]/10000; + btcgbp = (double)pricebits[2]/10000; + btceur = (double)pricebits[3]/10000; + fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2); + if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 ) + { + if ( nHeight < testchain_exemption ) + { + for (i=0; i= PRICES_SIZEBIT0 ) + { + memcpy(localbits,Mineropret.data(),Mineropret.size()); + if ( nHeight < testchain_exemption ) + { + for (i=0; i 0 && localbits[i] < prevbits[i] ) + { + if ( iter == 0 ) + break; + // second iteration checks recent prices to see if within local volatility + for (j=0; j= prevbits[i] ) + { + fprintf(stderr,"i.%d within recent localprices[%d] %u >= %u\n",i,j,PriceCache[j][i],prevbits[i]); + break; + } + if ( j == KOMODO_LOCALPRICE_CACHESIZE ) + { + komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); + break; + } + } + else if ( maxflag < 0 && localbits[i] > prevbits[i] ) + { + if ( iter == 0 ) + break; + for (j=0; jnTime,bhash,i,prevbits[i]); + break; + } + } + } + } + if ( i != n ) + { + if ( iter == 0 ) + { + fprintf(stderr,"force update prices\n"); + komodo_cbopretupdate(1); + memcpy(localbits,Mineropret.data(),Mineropret.size()); + } else return(-1); + } + } + } + } + if ( bhash == ExtremePrice.blockhash ) + { + fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime); + memset(&ExtremePrice,0,sizeof(ExtremePrice)); + } + return(0); + } else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]); + return(-1); + } + return(0); +} + +char *nonportable_path(char *str) +{ + int32_t i; + for (i=0; str[i]!=0; i++) + if ( str[i] == '/' ) + str[i] = '\\'; + return(str); +} + +char *portable_path(char *str) +{ +#ifdef _WIN32 + return(nonportable_path(str)); +#else +#ifdef __PNACL + /*int32_t i,n; + if ( str[0] == '/' ) + return(str); + else + { + n = (int32_t)strlen(str); + for (i=n; i>0; i--) + str[i] = str[i-1]; + str[0] = '/'; + str[n+1] = 0; + }*/ +#endif + return(str); +#endif +} + +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +{ + FILE *fp; + long filesize,buflen = *allocsizep; + uint8_t *buf = *bufp; + *lenp = 0; + if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) + { + fseek(fp,0,SEEK_END); + filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *lenp = 0; + //printf("loadfile null size.(%s)\n",fname); + return(0); + } + if ( filesize > buflen ) + { + *allocsizep = filesize; + *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); + } + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + buf[filesize] = 0; + } + fclose(fp); + *lenp = filesize; + //printf("loaded.(%s)\n",buf); + } //else printf("OS_loadfile couldnt load.(%s)\n",fname); + return(buf); +} + +void *filestr(long *allocsizep,char *_fname) +{ + long filesize = 0; char *fname,*buf = 0; void *retptr; + *allocsizep = 0; + fname = (char *)malloc(strlen(_fname)+1); + strcpy(fname,_fname); + retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); + free(fname); + return(retptr); +} + +cJSON *send_curl(char *url,char *fname) +{ + long fsize; char curlstr[1024],*jsonstr; cJSON *json=0; + sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname); + if ( system(curlstr) == 0 ) + { + if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 ) + { + json = cJSON_Parse(jsonstr); + free(jsonstr); + } + } + return(json); +} + +// get_urljson just returns the JSON returned by the URL using issue_curl + + +/* +const char *Techstocks[] = +{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" +}; +const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; + +const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; +*/ + +cJSON *get_urljson(char *url) +{ + char *jsonstr; cJSON *json = 0; + if ( (jsonstr= issue_curl(url)) != 0 ) + { + //fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr); + json = cJSON_Parse(jsonstr); + free(jsonstr); + } + return(json); +} + +int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols) +{ + 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()); + 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; + for (i=0; i now+60 || timestamp < now-ASSETCHAINS_BLOCKTIME ) + { + fprintf(stderr,"time error.%d (%u vs %u)\n",timestamp-now,timestamp,now); + retval = -1; + }*/ + if ( symbols[i] != symbol ) + { + retval = -1; + fprintf(stderr,"MISMATCH."); + } + fprintf(stderr,"(%s %u) ",symbol,uprice); + } + } + fprintf(stderr,"numstocks.%d\n",n); + } + //https://api.iextrading.com/1.0/tops/last?symbols=AAPL -> [{"symbol":"AAPL","price":198.63,"size":100,"time":1555092606076}] + free_json(json); + } + return(retval); +} + +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= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"dailyfx")) != 0 ) + { + if ( (rates= jobj(json,(char *)"rates")) != 0 ) + { + for (i=0; i strvec) +{ + int32_t i,errs=0; uint32_t price; char *symbol; + for (i=0; i 333 ) // for debug only! +// ASSETCHAINS_CBOPRET = 7; + size = komodo_cbopretsize(ASSETCHAINS_CBOPRET); + if ( Mineropret.size() < size ) + Mineropret.resize(size); + size = PRICES_SIZEBIT0; + if ( (forceflag != 0 || now > lastbtc+120) && get_btcusd(pricebits) == 0 ) + { + if ( flags == 0 ) + komodo_PriceCache_shift(); + memcpy(PriceCache[0],pricebits,PRICES_SIZEBIT0); + flags |= 1; + } + if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) + { + if ( now > lasttime+3600*5 || forexprices[0] == 0 ) // cant assume timestamp is valid for forex price as it is a daily weekday changing thing anyway. + { + get_dailyfx(forexprices); + if ( flags == 0 ) + komodo_PriceCache_shift(); + flags |= 2; + memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices)); + } + size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); + } + if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) + { + if ( forceflag != 0 || flags != 0 ) + { + get_cryptoprices(pricebuf,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES); + if ( flags == 0 ) + komodo_PriceCache_shift(); + memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t)); + flags |= 4; // very rarely we can see flags == 6 case + } + size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); + } + now = (uint32_t)time(NULL); + if ( (ASSETCHAINS_CBOPRET & 8) != 0 ) + { + if ( forceflag != 0 || flags != 0 ) + { + if ( get_stockprices(now,pricebuf,ASSETCHAINS_STOCKS) == ASSETCHAINS_STOCKS.size() ) + { + if ( flags == 0 ) + komodo_PriceCache_shift(); + memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,ASSETCHAINS_STOCKS.size() * sizeof(uint32_t)); + flags |= 8; // very rarely we can see flags == 10 case + } + } + size += (ASSETCHAINS_STOCKS.size()) * sizeof(uint32_t); + } + if ( flags != 0 ) + { + if ( (flags & 1) != 0 ) + lastbtc = now; + if ( (flags & 2) != 0 ) + lasttime = now; + memcpy(Mineropret.data(),PriceCache[0],size); + if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 ) + { + fprintf(stderr,"cmp dir.%d PriceCache[0][ExtremePrice.ind] %u >= %u ExtremePrice.pricebits\n",ExtremePrice.dir,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); + if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) + { + fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); + if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) + pindex->nStatus &= ~BLOCK_FAILED_MASK; + else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str()); + } + } + // high volatility still strands nodes so we need to check new prices to approve a stuck block + // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state + + //int32_t i; for (i=0; i= KOMODO_MAXPRICES ) + return(-1); + mult = komodo_pricemult(ind); + if ( nonzprices != 0 ) + memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); + //for (i=0; i= PRICES_DAYWINDOW ) + i = 0; + if ( (price= rawprices[i*rawskip]) == 0 ) + { + fprintf(stderr,"null rawprice.[%d]\n",i); + return(-1); + } + if ( price >= lowprice && price <= highprice ) + { + //fprintf(stderr,"%.1f ",(double)price/10000); + sum += price; + correlation++; + if ( correlation > (PRICES_DAYWINDOW>>1) ) + { + if ( nonzprices == 0 ) + return(refprice * mult); + //fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation); + //return(sum*mult/correlation); + n = 0; + i = (iter + seed) % PRICES_DAYWINDOW; + for (k=0; k= PRICES_DAYWINDOW ) + i = 0; + if ( n > (PRICES_DAYWINDOW>>1) ) + nonzprices[i] = 0; + else + { + price = rawprices[i*rawskip]; + if ( price < lowprice || price > highprice ) + nonzprices[i] = 0; + else + { + nonzprices[i] = price; + //fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]); + n++; + } + } + } + //fprintf(stderr,"ind.%d iter.%d j.%d i.%d n.%d correlation.%d ref %llu -> %llu\n",ind,iter,j,i,n,correlation,(long long)refprice,(long long)sum/correlation); + if ( n != correlation ) + return(-1); + sum = den = n = 0; + for (i=0; i %.8f\n",(long long)firstprice,((double)(sum*mult) / den) / COIN); + return((sum * mult) / den); + } + } + } + if ( correlation > maxcorrelation ) + maxcorrelation = correlation; + } + fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); + return(0); +} + +int64_t _pairave64(int64_t valA,int64_t valB) +{ + if ( valA != 0 && valB != 0 ) + return((valA + valB) / 2); + else if ( valA != 0 ) return(valA); + else return(valB); +} + +int64_t _pairdiff64(register int64_t valA,register int64_t valB) +{ + if ( valA != 0 && valB != 0 ) + return(valA - valB); + else return(0); +} + +int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width) +{ + register int32_t nonz,j; register int64_t sum,price; + nonz = 0; + sum = 0; + for (j=-width; j<=width; j++) + { + price = buf[i + j]; + if ( price != 0 ) + { + sum += price; + nonz++; + } + } + if ( nonz != 0 ) + sum /= nonz; + return(sum); +} + +void buf_trioave64(int64_t dest[],int64_t src[],int32_t n) +{ + register int32_t i,j,width = 3; + for (i=0; i<128; i++) + src[i] = 0; + //for (i=n-width-1; i>width; i--) + // dest[i] = balanced_ave(src,i,width); + //for (i=width; i>0; i--) + // dest[i] = balanced_ave(src,i,i); + for (i=1; i price ) // rising prices + sort64(buf,PRICES_DAYWINDOW); + else revsort64(buf,PRICES_DAYWINDOW); + decayprice = buf[0]; + for (i=0; i %.8f\n",halfave 0 && PRICES[0].fp != 0 && createflag != 0 ) + { + fseek(PRICES[0].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); + fputc(0,PRICES[0].fp); + fflush(PRICES[0].fp); + } + fprintf(stderr,"pricesinit done i.%d num.%d numprices.%d\n",i,num,(int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t))); + if ( i != num || i != komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t) ) + { + fprintf(stderr,"fatal error opening prices files, start shutdown\n"); + StartShutdown(); + } + return(0); +} + +pthread_mutex_t pricemutex; + +// PRICES file layouts +// [0] rawprice32 / timestamp +// [1] correlated +// [2] 24hr ave +// [3] to [7] reserved + +void komodo_pricesupdate(int32_t height,CBlock *pblock) +{ + static int numprices; static uint32_t *ptr32; static int64_t *ptr64,*tmpbuf; + int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[PRICES_MAXDATAPOINTS*2]; + width = PRICES_DAYWINDOW;//(2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH); + if ( numprices == 0 ) + { + pthread_mutex_init(&pricemutex,0); + numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); + ptr32 = (uint32_t *)calloc(sizeof(uint32_t),numprices * width); + ptr64 = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS); + tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW); + fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); + } + if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) + { + //for (ind=0; ind PRICES_DAYWINDOW ) + { + fseek(PRICES[0].fp,(height-width+1) * numprices * sizeof(uint32_t),SEEK_SET); + if ( fread(ptr32,sizeof(uint32_t),width*numprices,PRICES[0].fp) == width*numprices ) + { + rngval = seed; + for (ind=1; ind 0 ) + { + fseek(PRICES[ind].fp,height * sizeof(int64_t) * PRICES_MAXDATAPOINTS,SEEK_SET); + memset(buf,0,sizeof(buf)); + buf[0] = rawprices[ind]; + buf[1] = rawprices[0]; // timestamp + memcpy(&buf[2],&correlated,sizeof(correlated)); + if ( fwrite(buf,1,sizeof(buf),PRICES[ind].fp) != sizeof(buf) ) + fprintf(stderr,"error fwrite buf for ht.%d ind.%d\n",height,ind); + else if ( height > PRICES_DAYWINDOW*2 ) + { + fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); + if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS,PRICES[ind].fp) == PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS ) + { + if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[(PRICES_DAYWINDOW-1)*PRICES_MAXDATAPOINTS+1],-PRICES_MAXDATAPOINTS)) > 0 ) + { + fseek(PRICES[ind].fp,(height * PRICES_MAXDATAPOINTS + 2) * sizeof(int64_t),SEEK_SET); + if ( fwrite(&smoothed,1,sizeof(smoothed),PRICES[ind].fp) != sizeof(smoothed) ) + fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); + else fflush(PRICES[ind].fp); + } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); + } else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind); + } + } else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); + } + fprintf(stderr,"height.%d\n",height); + } else fprintf(stderr,"error reading rawprices for ht.%d\n",height); + } else fprintf(stderr,"height.%d <= width.%d\n",height,width); + pthread_mutex_unlock(&pricemutex); + } else fprintf(stderr,"null PRICES[0].fp\n"); + } else fprintf(stderr,"numprices mismatch, height.%d\n",height); +} + +int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks) +{ + FILE *fp; int32_t retval = PRICES_MAXDATAPOINTS; + pthread_mutex_lock(&pricemutex); + if ( ind < KOMODO_MAXPRICES && (fp= PRICES[ind].fp) != 0 ) + { + fseek(fp,height * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); + if ( fread(buf64,sizeof(int64_t),numblocks*PRICES_MAXDATAPOINTS,fp) != numblocks*PRICES_MAXDATAPOINTS ) + retval = -1; + } + pthread_mutex_unlock(&pricemutex); + return(retval); +} diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 318df7b15b3..783d812d065 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -12,404 +12,32 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once // paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse #include "komodo_defs.h" +#include "komodo_cJSON.h" -/*#include "secp256k1/include/secp256k1.h" -#include "secp256k1/include/secp256k1_schnorrsig.h" -#include "secp256k1/include/secp256k1_musig.h" +int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); -int32_t dummy_linker_tricker() -{ - secp256k1_context *ctx = 0; std::vector musig64; CPubKey pk; secp256k1_schnorrsig musig; secp256k1_pubkey combined_pk; - if ( secp256k1_schnorrsig_parse((const secp256k1_context *)ctx,&musig,(const uint8_t *)&musig64[0]) > 0 && secp256k1_ec_pubkey_parse(ctx,&combined_pk,pk.begin(),33) > 0 ) - return(1); -}*/ +void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type); -int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx); +struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type); -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) -{ - int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; - *available = *deposited = *issued = *withdrawn = *approved = *redeemed = 0; - if ( (baseid= komodo_baseid(base)) >= 0 ) - { - if ( (sp= komodo_stateptrget(base)) != 0 ) - { - *deposited = sp->deposited; - *issued = sp->issued; - *withdrawn = sp->withdrawn; - *approved = sp->approved; - *redeemed = sp->redeemed; - maxval = sp->approved; - if ( sp->withdrawn > maxval ) - maxval = sp->withdrawn; - netliability = (sp->issued - maxval) - sp->shorted; - maxallowed = komodo_maxallowed(baseid); - if ( netliability < maxallowed ) - *available = (maxallowed - netliability); - //printf("%llu - %llu %s %.8f %.8f %.8f %.8f %.8f\n",(long long)maxallowed,(long long)netliability,base,dstr(*deposited),dstr(*issued),dstr(*withdrawn),dstr(*approved),dstr(*redeemed)); - return(0); - } else printf("pax_fiatstatus cant get basesp.%s\n",base); - } // else printf("pax_fiatstatus illegal base.%s\n",base); - return(-1); -} +struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout); -void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type) -{ - memcpy(buf,&txid,32); - memcpy(&buf[32],&vout,2); - buf[34] = type; -} +struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout,uint8_t type,int32_t mark); -struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type) -{ - struct pax_transaction *pax; uint8_t buf[35]; - pthread_mutex_lock(&komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - pthread_mutex_unlock(&komodo_mutex); - return(pax); -} +void komodo_paxdelete(struct pax_transaction *pax); -struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout) -{ - struct pax_transaction *pax; int32_t i; uint8_t types[] = { 'I', 'D', 'X', 'A', 'W' }; - for (i=0; itxid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark); - } - if ( pax != 0 ) - { - pax->marked = mark; - //if ( height > 214700 || pax->height > 214700 ) - // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - - } - pthread_mutex_unlock(&komodo_mutex); - return(pax); -} +int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax); -void komodo_paxdelete(struct pax_transaction *pax) -{ - return; // breaks when out of order - pthread_mutex_lock(&komodo_mutex); - HASH_DELETE(hh,PAX,pax); - pthread_mutex_unlock(&komodo_mutex); -} +int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo); -void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context -{ - struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*s; - //if ( KOMODO_PAX == 0 ) - // return; - //if ( strcmp(symbol,ASSETCHAINS_SYMBOL) != 0 ) - // return; - sp = komodo_stateptr(str,dest); - pthread_mutex_lock(&komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - if ( pax == 0 ) - { - pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); - pax->txid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - addflag = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - { - int32_t i; for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&txid)[i]); - printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); - } - } - pthread_mutex_unlock(&komodo_mutex); - if ( coinaddr != 0 ) - { - strcpy(pax->coinaddr,coinaddr); - if ( value != 0 ) - pax->komodoshis = value; - if ( symbol != 0 ) - strcpy(pax->symbol,symbol); - if ( source != 0 ) - strcpy(pax->source,source); - if ( fiatoshis != 0 ) - pax->fiatoshis = fiatoshis; - if ( rmd160 != 0 ) - memcpy(pax->rmd160,rmd160,20); - if ( height != 0 ) - pax->height = height; - if ( otherheight != 0 ) - pax->otherheight = otherheight; - } - else - { - pax->marked = height; - //printf("pax.%p MARK DEPOSIT ht.%d other.%d\n",pax,height,otherheight); - } -} +int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed); -int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax) -{ - int32_t i,len = 0; - if ( rwflag == 1 ) - { - for (i=0; i<32; i++) - opretbuf[len++] = ((uint8_t *)&pax->txid)[i]; - opretbuf[len++] = pax->vout & 0xff; - opretbuf[len++] = (pax->vout >> 8) & 0xff; - } - else - { - for (i=0; i<32; i++) - ((uint8_t *)&pax->txid)[i] = opretbuf[len++]; - //for (i=0; i<32; i++) - // printf("%02x",((uint8_t *)&pax->txid)[31-i]); - pax->vout = opretbuf[len++]; - pax->vout += ((uint32_t)opretbuf[len++] << 8); - //printf(" txid v.%d\n",pax->vout); - } - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); - if ( rwflag != 0 ) - { - memcpy(&opretbuf[len],pax->rmd160,20), len += 20; - for (i=0; i<4; i++) - opretbuf[len++] = pax->source[i]; - } - else - { - memcpy(pax->rmd160,&opretbuf[len],20), len += 20; - for (i=0; i<4; i++) - pax->source[i] = opretbuf[len++]; - } - return(len); -} - -int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo) -{ - struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - //if ( KOMODO_PAX == 0 ) - // return(0); - incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); - //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 - - // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 - - //for (i=0; i>>>>>> %s: (%s) fiat %.8f kmdheight.%d other.%d -> %s %.8f\n",type=='A'?"approvedA":"issuedX",baseids[n]>=0?CURRENCIES[baseids[n]]:"???",dstr(p.fiatoshis),kmdheights[n],otherheights[n],coinaddr,dstr(values[n])); - } - } - } - else - { - for (i=0; i<4; i++) - base[i] = opretbuf[opretlen-4+i]; - for (j=0; j<32; j++) - { - ((uint8_t *)&txids[n])[j] = opretbuf[len++]; - //printf("%02x",((uint8_t *)&txids[n])[j]); - } - vouts[n] = opretbuf[len++]; - vouts[n] = (opretbuf[len++] << 8) | vouts[n]; - baseids[n] = komodo_baseid(base); - if ( (pax= komodo_paxfinds(txids[n],vouts[n])) != 0 ) - { - values[n] = (strcmp("KMD",base) == 0) ? pax->komodoshis : pax->fiatoshis; - srcvalues[n] = (strcmp("KMD",base) == 0) ? pax->fiatoshis : pax->komodoshis; - kmdheights[n] = pax->height; - otherheights[n] = pax->otherheight; - memcpy(&rmd160s[n * 20],pax->rmd160,20); - } - } - //printf(" komodo_issued_opreturn issuedtxid v%d i.%d opretlen.%d\n",vouts[n],n,opretlen); - } - } - return(n); -} - -int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) -{ - int32_t ratio; - if ( seed == 0 && checkvalue != 0 ) - { - ratio = ((value << 6) / checkvalue); - if ( ratio >= 60 && ratio <= 67 ) - return(0); - else - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); - return(-1); - } - } - else if ( checkvalue != 0 ) - { - ratio = ((value << 10) / checkvalue); - if ( ratio >= 1023 && ratio <= 1025 ) - return(0); - } - return(value != checkvalue); -} - -uint64_t komodo_paxtotal() -{ - struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp; - if ( KOMODO_PASSPORT_INITDONE == 0 ) //KOMODO_PAX == 0 || - return(0); - if ( komodo_isrealtime(&ht) == 0 ) - return(0); - else - { - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->marked != 0 ) - continue; - if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' ) - str = pax->symbol; - else str = pax->source; - basesp = komodo_stateptrget(str); - if ( basesp != 0 && pax->didstats == 0 ) - { - if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) - { - if ( pax2->fiatoshis != 0 ) - { - pax->komodoshis = pax2->komodoshis; - pax->fiatoshis = pax2->fiatoshis; - basesp->issued += pax->fiatoshis; - pax->didstats = 1; - if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p issued %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,str,dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight); - pax2->marked = pax->height; - pax->marked = pax->height; - } - } - else if ( pax->type == 'W' ) - { - //bitcoin_address(coinaddr,addrtype,rmd160,20); - if ( (checktoshis= komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis)) != 0 ) - { - if ( komodo_paxcmp(pax->source,pax->height,pax->komodoshis,checktoshis,seed) != 0 ) - { - pax->marked = pax->height; - //printf("WITHDRAW.%s mark <- %d %.8f != %.8f\n",pax->source,pax->height,dstr(checktoshis),dstr(pax->komodoshis)); - } - else if ( pax->validated == 0 ) - { - pax->validated = pax->komodoshis = checktoshis; - //int32_t j; for (j=0; j<32; j++) - // printf("%02x",((uint8_t *)&pax->txid)[j]); - //if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) - // printf(" v%d %p got WITHDRAW.%s kmd.%d ht.%d %.8f -> %.8f/%.8f\n",pax->vout,pax,pax->source,pax->height,pax->otherheight,dstr(pax->fiatoshis),dstr(pax->komodoshis),dstr(checktoshis)); - } - } - } - } - } - } - komodo_stateptr(symbol,dest); - HASH_ITER(hh,PAX,pax,tmp) - { - pax->ready = 0; - if ( 0 && pax->type == 'A' ) - printf("%p pax.%s <- %s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->symbol,pax->source,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); - if ( pax->marked != 0 ) - continue; - if ( strcmp(symbol,pax->symbol) == 0 || pax->type == 'A' ) - { - if ( pax->marked == 0 ) - { - if ( komodo_is_issuer() != 0 ) - { - if ( pax->validated != 0 && pax->type == 'D' ) - { - total += pax->fiatoshis; - pax->ready = 1; - } - } - else if ( pax->approved != 0 && pax->type == 'A' ) - { - if ( pax->validated != 0 ) - { - total += pax->komodoshis; - pax->ready = 1; - } - else - { - seed = 0; - checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); - //printf("paxtotal PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); - //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); - if ( seed != 0 && checktoshis != 0 ) - { - if ( checktoshis == pax->komodoshis ) - { - total += pax->komodoshis; - pax->validated = pax->komodoshis; - pax->ready = 1; - } else pax->marked = pax->height; - } - } - } - if ( 0 && pax->ready != 0 ) - printf("%p (%c) pax.%s marked.%d %.8f -> %.8f validated.%d approved.%d ready.%d ht.%d\n",pax,pax->type,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0,pax->ready,pax->height); - } - } - } - //printf("paxtotal %.8f\n",dstr(total)); - return(total); -} +uint64_t komodo_paxtotal(); static int _paxorder(const void *a,const void *b) { @@ -427,1167 +55,37 @@ static int _paxorder(const void *a,const void *b) #undef pax_b } -int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order -{ - struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384*4]; int32_t i,n,ht,len=0; uint64_t total = 0; - if ( KOMODO_PAX == 0 || KOMODO_PASSPORT_INITDONE == 0 ) - return(0); - if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); - n = 0; - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->type == 'W' ) - { - if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'A')) != 0 ) - { - if ( pax2->approved != 0 ) - pax->approved = pax2->approved; - } - else if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'X')) != 0 ) - pax->approved = pax->height; - //printf("pending_withdraw: pax %s marked.%u approved.%u validated.%llu\n",pax->symbol,pax->marked,pax->approved,(long long)pax->validated); - if ( pax->marked == 0 && pax->approved == 0 && pax->validated != 0 ) //strcmp((char *)"KMD",pax->symbol) == 0 && - { - if ( n < sizeof(paxes)/sizeof(*paxes) ) - { - paxes[n++] = pax; - //int32_t j; for (j=0; j<32; j++) - // printf("%02x",((uint8_t *)&pax->txid)[j]); - //printf(" %s.(kmdht.%d ht.%d marked.%u approved.%d validated %.8f) %.8f\n",pax->source,pax->height,pax->otherheight,pax->marked,pax->approved,dstr(pax->validated),dstr(pax->komodoshis)); - } - } - } - } - opretstr[0] = 0; - if ( n > 0 ) - { - opretbuf[len++] = 'A'; - qsort(paxes,n,sizeof(*paxes),_paxorder); - for (i=0; i>3)*7 ) - len += komodo_rwapproval(1,&opretbuf[len],paxes[i]); - } - if ( len > 0 ) - init_hexbytes_noT(opretstr,opretbuf,len); - } - //fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); - return(len); -} - -int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) -{ - struct pax_transaction *pax,*tmp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint8_t *script,opcode,opret[16384*4],data[16384*4]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask,sum = 0; - if ( KOMODO_PASSPORT_INITDONE == 0 )//KOMODO_PAX == 0 || - return(0); - struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); - sp = komodo_stateptr(symbol,dest); - strcpy(symbol,base); - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) - return(0); - PENDING_KOMODO_TX = 0; - for (i=0; i<3; i++) - { - if ( komodo_isrealtime(&ht) != 0 ) - break; - sleep(1); - } - if ( i == 3 ) - { - if ( tokomodo == 0 ) - printf("%s not realtime ht.%d\n",ASSETCHAINS_SYMBOL,ht); - return(0); - } - if ( tokomodo == 0 ) - { - opcode = 'I'; - } - else - { - opcode = 'X'; - if ( 1 || komodo_paxtotal() == 0 ) - return(0); - } - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->type != 'D' && pax->type != 'A' ) - continue; - { -#ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE - if ( pax->height > 236000 ) - { - if ( kmdsp != 0 && kmdsp->NOTARIZED_HEIGHT >= pax->height ) - pax->validated = pax->komodoshis; - else if ( kmdsp->CURRENT_HEIGHT > pax->height+30 ) - pax->validated = pax->ready = 0; - } - else - { - if ( kmdsp != 0 && (kmdsp->NOTARIZED_HEIGHT >= pax->height || kmdsp->CURRENT_HEIGHT > pax->height+30) ) // assumes same chain as notarize - pax->validated = pax->komodoshis; - else pax->validated = pax->ready = 0; - } -#else - pax->validated = pax->komodoshis; -#endif - } - if ( ASSETCHAINS_SYMBOL[0] != 0 && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) - { - //if ( pax->height > 214700 || strcmp(ASSETCHAINS_SYMBOL,symbol) == 0 ) - // printf("miner.[%s]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed)); - continue; - } - /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); - if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) - { - printf("reject 2\n"); - continue; - }*/ - if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) ) - { - if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 ) - printf("pax->symbol.%s != %s or null pax->validated %.8f ready.%d ht.(%d %d)\n",pax->symbol,symbol,dstr(pax->validated),pax->ready,kmdsp->CURRENT_HEIGHT,pax->height); - pax->marked = pax->height; - continue; - } - if ( pax->ready == 0 ) - continue; - if ( pax->type == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( kmdsp != 0 ) - { - if ( (baseid= komodo_baseid(pax->symbol)) < 0 || ((1LL << baseid) & sp->RTmask) == 0 ) - { - printf("not RT for (%s) %llx baseid.%d %llx\n",pax->symbol,(long long)sp->RTmask,baseid,(long long)(1LL< %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - if ( opcode == 'I' ) - { - sum += pax->fiatoshis; - if ( sum > available ) - break; - } - txNew->vout.resize(numvouts+1); - txNew->vout[numvouts].nValue = (opcode == 'I') ? pax->fiatoshis : pax->komodoshis; - txNew->vout[numvouts].scriptPubKey.resize(25); - script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; - *script++ = 0x76; - *script++ = 0xa9; - *script++ = 20; - memcpy(script,pax->rmd160,20), script += 20; - *script++ = 0x88; - *script++ = 0xac; - if ( tokomodo == 0 ) - { - for (i=0; i<32; i++) - data[len++] = ((uint8_t *)&pax->txid)[i]; - data[len++] = pax->vout & 0xff; - data[len++] = (pax->vout >> 8) & 0xff; - PENDING_KOMODO_TX += pax->fiatoshis; - } - else - { - len += komodo_rwapproval(1,&data[len],pax); - PENDING_KOMODO_TX += pax->komodoshis; - printf(" len.%d vout.%u DEPOSIT %.8f <- pax.%s pending ht %d %d %.8f | ",len,pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,pax->height,pax->otherheight,dstr(PENDING_KOMODO_TX)); - } - if ( numvouts++ >= 64 || sum > COIN ) - break; - } - if ( numvouts > 1 ) - { - if ( tokomodo != 0 ) - strcpy(symbol,(char *)"KMD"); - for (i=0; symbol[i]!=0; i++) - data[len++] = symbol[i]; - data[len++] = 0; - for (i=0; ivout.resize(numvouts+1); - txNew->vout[numvouts].nValue = 0; - txNew->vout[numvouts].scriptPubKey.resize(opretlen); - script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; - memcpy(script,opret,opretlen); - for (i=0; i<8; i++) - printf("%02x",opret[i]); - printf(" <- opret, MINER deposits.%d (%s) vouts.%d %.8f opretlen.%d\n",tokomodo,ASSETCHAINS_SYMBOL,numvouts,dstr(PENDING_KOMODO_TX),opretlen); - return(1); - } - return(0); -} +int32_t komodo_pending_withdraws(char *opretstr); -const char *banned_txids[] = -{ - "78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", // vout1 only 233559 - "00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172 - "e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187 - "f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188 - "abf08be07d8f5b3a433ddcca7ef539e79a3571632efd6d0294ec0492442a0204", //234213 - "3b854b996cc982fba8c06e76cf507ae7eed52ab92663f4c0d7d10b3ed879c3b0", //234367 - "fa9e474c2cda3cb4127881a40eb3f682feaba3f3328307d518589024a6032cc4", //234635 - "ca746fa13e0113c4c0969937ea2c66de036d20274efad4ce114f6b699f1bc0f3", //234662 - "43ce88438de4973f21b1388ffe66e68fda592da38c6ef939be10bb1b86387041", //234697 - "0aeb748de82f209cd5ff7d3a06f65543904c4c17387c9d87c65fd44b14ad8f8c", //234899 - "bbd3a3d9b14730991e1066bd7c626ca270acac4127131afe25f877a5a886eb25", //235252 - "fa9943525f2e6c32cbc243294b08187e314d83a2870830180380c3c12a9fd33c", //235253 - "a01671c8775328a41304e31a6693bbd35e9acbab28ab117f729eaba9cb769461", //235265 - "2ef49d2d27946ad7c5d5e4ab5c089696762ff04e855f8ab48e83bdf0cc68726d", //235295 - "c85dcffb16d5a45bd239021ad33443414d60224760f11d535ae2063e5709efee", //235296 - // all vouts banned - "c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748 - "305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204 - //"43416a0c4da6b1a5c1d375bdbe8f7dc8d44d8f60df593d3376aa8221ec66357e", // vout0 only - //"1eb295ed54c47f35cbccd7e7e40d03041f1853581da6d41102a9d8813782b6cb", - //"db121e4012222adfc841824984a2a90b7e5b018dd71307822537d58160195e43", - //"28f95b8148ac4ae6e09c7380e34422fab41d568a411e53dc94823e36a3d6f386", - //"01d8c839463bda2f2f6400ede4611357913684927a767422a8560ead1b22557c", - //"6e4980a9e1bd669f4df04732dc6f11b7773b6de88d1abcf89a6b9007d72ef9ac", - //"6cc1d0495170bc0e11fd3925297623562e529ea1336b66ea61f8a1159041aed2", - //"250875424cece9bcd98cb226b09da7671625633d6958589e3a462bad89ad87cc", // missed - //"ea8659011de52f4dac42cda12326064b7b5013b8492f88e33159884ca299aa05", // missed - //"ce567928b5490a17244167af161b1d8dd6ff753fef222fe6855d95b2278a35b3", // missed -}; +int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo); -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_checkvout(int32_t vout,int32_t k,int32_t indallvouts); -int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) -{ - int32_t i; - if ( sizeof(banned_txids)/sizeof(*banned_txids) > max ) - { - fprintf(stderr,"komodo_bannedset: buffer too small %d vs %d\n",(int32_t)(sizeof(banned_txids)/sizeof(*banned_txids)),max); - StartShutdown(); - } - for (i=0; i 1 && block.vtx[txn_count-1].vout.size() > 0 && block.vtx[txn_count-1].vout[0].nValue == 5000 ) - { - /* - if ( block.vtx[txn_count-1].vin.size() == 1 && GetTransaction(block.vtx[txn_count-1].vin[0].prevout.hash,tx,hash,false) && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) - notmatched = 1; - */ - if ( block.vtx[txn_count-1].vin.size() == 1 ) { - uint256 hashNotaryProofVin = block.vtx[txn_count-1].vin[0].prevout.hash; - int fNotaryProofVinTxFound = GetTransaction(hashNotaryProofVin,tx,hash,false); - if (!fNotaryProofVinTxFound) { - // try to search in the same block - BOOST_FOREACH(const CTransaction &txInThisBlock, block.vtx) { - if (txInThisBlock.GetHash() == hashNotaryProofVin) { - fNotaryProofVinTxFound = 1; - tx = txInThisBlock; - hash = block.GetHash(); - break; - } - } - } - if ( fNotaryProofVinTxFound && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) - { - notmatched = 1; - } - } - } - n = block.vtx[i].vin.size(); - for (j=0; j= indallvouts) ) - { - printf("banned tx.%d being used at ht.%d txi.%d vini.%d\n",k,height,i,j); - return(-1); - } - } - } - } - } - if ( height > 0 && ASSETCHAINS_MARMARA != 0 && (height & 1) == 0 ) - { - if ( MarmaraValidateCoinbase(height,block.vtx[0]) < 0 ) - { - fprintf(stderr,"MARMARA error ht.%d constrains even height blocks to pay 100%% to CC in vout0 with opreturn\n",height); - return(-1); - } - } - // we don't want these checks in VRSC, leave it at the Sapling upgrade - if ( ASSETCHAINS_SYMBOL[0] == 0 || - ((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) || - NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) ) - { - n = block.vtx[0].vout.size(); - int64_t val,prevtotal = 0; int32_t strangeout=0,overflow = 0; - total = 0; - for (i=1; i= MAX_MONEY ) - { - overflow = 1; - break; - } - if ( i > 1 && script[0] != 0x6a && val < 5000 ) - strangeout++; - total += val; - if ( total < prevtotal || (val != 0 && total == prevtotal) ) - { - overflow = 1; - break; - } - prevtotal = total; - } - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( overflow != 0 || total > COIN/10 ) - { - if ( height >= activation ) - { - if ( height > 800000 ) - fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); - return(-1); - } - } - else if ( block.nBits == KOMODO_MINDIFF_NBITS && total > 0 ) // to deal with fee stealing - { - fprintf(stderr,"notary mined ht.%d with extra %.8f\n",height,dstr(total)); - if ( height > KOMODO_NOTARIES_HEIGHT1 ) - return(-1); - } - if ( strangeout != 0 || notmatched != 0 ) - { - if ( 0 && strcmp(NOTARY_PUBKEY.c_str(),"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828") == 0 ) - fprintf(stderr,">>>>>>>>>>>>> DUST ht.%d strangout.%d notmatched.%d <<<<<<<<<\n",height,strangeout,notmatched); - if ( height > 1000000 && strangeout != 0 ) - return(-1); - } - else if ( height > 814000 ) - { - script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; - //int32_t notary = komodo_electednotary(&num,script+1,height,0); - //if ( (-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)) < 0 ) - // fprintf(stderr, ">>>>>>> FAILED BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); - //else - // fprintf(stderr, "<<<<<<< VALID BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); - return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); - } - } - else - { - checktoshis = 0; - if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1 ) - { - if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) - { - fprintf(stderr,"ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); - return(-1); - } - } - if ( height > 1 && checktoshis == 0 ) - { - checktoshis = ((uint64_t)GetBlockSubsidy(height, Params().GetConsensus()) - block.vtx[0].vout[0].nValue); - // some pools will need to change their pool fee to be (poolfee % - txfees) - //checktoshis += txn_count * 0.001; // rely on higher level validations to prevent emitting more coins than actual txfees - } - if ( height >= 2 && (overflow != 0 || total > checktoshis || strangeout != 0) ) - { - fprintf(stderr,"checkdeposit: ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); - if ( strangeout != 0 ) - fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangeout.%d notmatched.%d <<<<<<<<<\n",ASSETCHAINS_SYMBOL,height,strangeout,notmatched); - return(-1); - } - } - } - return(0); -} +int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); // verify above block is valid pax pricing -const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) -{ - uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; - const char *typestr = "unknown"; - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) - { - //printf("komodo_opreturn skip %s\n",ASSETCHAINS_SYMBOL); - return("assetchain"); - } - memset(baseids,0xff,sizeof(baseids)); - memset(values,0,sizeof(values)); - memset(srcvalues,0,sizeof(srcvalues)); - memset(rmd160s,0,sizeof(rmd160s)); - memset(kmdheights,0,sizeof(kmdheights)); - memset(otherheights,0,sizeof(otherheights)); - tokomodo = (komodo_is_issuer() == 0); - if ( opretbuf[0] == 'K' && opretlen != 40 ) - { - komodo_kvupdate(opretbuf,opretlen,value); - return("kv"); - } - else if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_PAX == 0 ) - return("nopax"); - if ( opretbuf[0] == 'D' ) - { - tokomodo = 0; - if ( opretlen == 38 ) // any KMD tx - { - iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); - memset(base,0,sizeof(base)); - PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis); - bitcoin_address(coinaddr,addrtype,rmd160,20); - checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,fiatoshis); - if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) != 0 ) - checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,height,base,fiatoshis); - typestr = "deposit"; - if ( 0 && strcmp("NOK",base) == 0 ) - { - printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); - printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&txid)[i]); - printf(" <- txid.v%u ",vout); - for (i=0; i<33; i++) - printf("%02x",pubkey33[i]); - printf(" checkpubkey check %.8f v %.8f dest.(%s) kmdheight.%d height.%d\n",dstr(checktoshis),dstr(value),destaddr,kmdheight,height); - } - if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 && (kmdheight > 195000 || kmdheight <= height) ) - { - didstats = 0; - if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) == 0 ) - { - if ( (pax= komodo_paxfind(txid,vout,'D')) == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->deposited += fiatoshis; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p deposited %s += %.8f kmdheight.%d %.8f\n",basesp,base,dstr(fiatoshis),kmdheight,dstr(value)); - } else printf("cant get stateptr.(%s)\n",base); - komodo_gateway_deposit(coinaddr,value,base,fiatoshis,rmd160,txid,vout,'D',kmdheight,height,(char *)"KMD",0); - } - if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) - { - pax->height = kmdheight; - pax->validated = value; - pax->komodoshis = value; - pax->fiatoshis = fiatoshis; - if ( didstats == 0 && pax->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->deposited += fiatoshis; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p depositedB %s += %.8f/%.8f kmdheight.%d/%d %.8f/%.8f\n",basesp,base,dstr(fiatoshis),dstr(pax->fiatoshis),kmdheight,pax->height,dstr(value),dstr(pax->komodoshis)); - } - } // - if ( didstats != 0 ) - pax->didstats = 1; - if ( (pax2= komodo_paxfind(txid,vout,'I')) != 0 ) - { - pax2->fiatoshis = pax->fiatoshis; - pax2->komodoshis = pax->komodoshis; - pax->marked = pax2->marked = pax->height; - pax2->height = pax->height = height; - if ( pax2->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->issued += pax2->fiatoshis; - pax2->didstats = 1; - if ( 0 && strcmp(base,"USD") == 0 ) - printf("########### %p issueda %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,base,dstr(pax2->fiatoshis),pax2->height,dstr(pax2->komodoshis),pax2->otherheight,height); - } - } - } - } - } - else - { - if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) - pax->marked = checktoshis; - if ( kmdheight > 238000 && (kmdheight > 214700 || strcmp(base,ASSETCHAINS_SYMBOL) == 0) ) //seed != 0 && - printf("pax %s deposit %.8f rejected kmdheight.%d %.8f KMD check %.8f seed.%llu\n",base,dstr(fiatoshis),kmdheight,dstr(value),dstr(checktoshis),(long long)seed); - } - } //else printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); - } //else printf("unsupported size.%d for opreturn D\n",opretlen); - } - else if ( opretbuf[0] == 'I' ) - { - tokomodo = 0; - if ( strncmp((char *)"KMD",(char *)&opretbuf[opretlen-4],3) != 0 && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 ) - { - if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,0)) > 0 ) - { - for (i=0; itype = opretbuf[0]; - strcpy(pax->source,(char *)&opretbuf[opretlen-4]); - if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 && pax2->fiatoshis != 0 && pax2->komodoshis != 0 ) - { - // realtime path? - pax->fiatoshis = pax2->fiatoshis; - pax->komodoshis = pax2->komodoshis; - pax->marked = pax2->marked = pax2->height; - if ( pax->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->issued += pax->fiatoshis; - pax->didstats = 1; - pax->height = pax2->height; - pax->otherheight = height; - if ( 1 && strcmp(CURRENCIES[baseids[i]],"USD") == 0 ) - printf("########### %p issuedb %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,CURRENCIES[baseids[i]],dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight,height); - } - } - } - } - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'I',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'D',height)) != 0 ) - komodo_paxdelete(pax); - } - } //else printf("opreturn none issued?\n"); - } - } - else if ( height < 236000 && opretbuf[0] == 'W' && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 )//&& opretlen >= 38 ) - { - if ( komodo_baseid((char *)&opretbuf[opretlen-4]) >= 0 && strcmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4]) == 0 ) - { - for (i=0; i (%s) len.%d\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen); - didstats = 0; - //if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) - { - if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->withdrawn += value; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p withdrawn %s += %.8f check %.8f\n",basesp,base,dstr(value),dstr(checktoshis)); - } - if ( 0 && strcmp(base,"RUB") == 0 && (pax == 0 || pax->approved == 0) ) - printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); - } - komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); - if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) - { - pax->type = opretbuf[0]; - strcpy(pax->source,base); - strcpy(pax->symbol,"KMD"); - pax->height = kmdheight; - pax->otherheight = height; - pax->komodoshis = komodoshis; - } - } // else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis)); - // need to allocate pax - } - else if ( height < 236000 && tokomodo != 0 && opretbuf[0] == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - tokomodo = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - for (i=0; i 0 ) - { - for (i=0; isymbol); - printf("override neg1 with (%s)\n",pax->symbol); - } - if ( baseids[i] < 0 ) - continue; - } - didstats = 0; - seed = 0; - checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)values[i]); - //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)values[i]/COIN,(double)srcvalues[i]/COIN,(double)checktoshis/COIN); - if ( srcvalues[i] == checktoshis ) - { - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - { - bitcoin_address(coinaddr,60,&rmd160s[i*20],20); - komodo_gateway_deposit(coinaddr,srcvalues[i],CURRENCIES[baseids[i]],values[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - printf("unexpected null pax for approve\n"); - else pax->validated = checktoshis; - if ( (pax2= komodo_paxfind(txids[i],vouts[i],'W')) != 0 ) - pax2->approved = kmdheights[i]; - komodo_paxmark(height,txids[i],vouts[i],'W',height); - //komodo_paxmark(height,txids[i],vouts[i],'A',height); - if ( values[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->approved += values[i]; - didstats = 1; - //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); - } - //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); - } - else if ( pax->didstats == 0 && srcvalues[i] != 0 ) - { - if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->approved += values[i]; - didstats = 1; - //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); - } - } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) - { - pax->type = opretbuf[0]; - pax->approved = kmdheights[i]; - pax->validated = checktoshis; - if ( didstats != 0 ) - pax->didstats = 1; - //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) - //printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); - } - } - } - } //else printf("n.%d from opreturns\n",n); - //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); - } - else if ( height < 236000 && opretbuf[0] == 'X' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - tokomodo = 1; - if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 ) - { - for (i=0; itype = opretbuf[0]; - if ( height < 121842 ) // fields got switched around due to legacy issues and approves - value = srcvalues[i]; - else value = values[i]; - if ( baseids[i] >= 0 && value != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->redeemed += value; - pax->didstats = 1; - if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) - printf("ht.%d %.8f ########### %p redeemed %s += %.8f %.8f kht.%d ht.%d\n",height,dstr(value),basesp,CURRENCIES[baseids[i]],dstr(value),dstr(srcvalues[i]),kmdheights[i],otherheights[i]); - } - } - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'W',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'A',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'X',height)) != 0 ) - komodo_paxdelete(pax); - } - } //else printf("komodo_issued_opreturn returned %d\n",n); - } - return(typestr); -} +const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source); int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); -void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest) -{ - uint8_t func; long lastK,lastT,lastN,lastV,fpos,lastfpos; int32_t i,count,doissue,iter,numn,numv,numN,numV,numR; uint32_t tmp,prevpos100,offset; - count = numR = numN = numV = numn = numv = 0; - lastK = lastT = lastN = lastV = -1; - for (iter=0; iter<2; iter++) - { - for (lastfpos=fpos=prevpos100=i=0; i> 8); - fpos = prevpos100 + offset; - if ( lastfpos >= datalen || (filedata[lastfpos] != func && func != 0) ) - printf("i.%d/n.%d lastfpos.%ld >= datalen.%ld or [%d] != func.%d\n",i,n,lastfpos,datalen,filedata[lastfpos],func); - else if ( iter == 0 ) - { - switch ( func ) - { - default: case 'P': case 'U': case 'D': - inds[i] &= 0xffffff00; - break; - case 'K': - lastK = lastfpos; - inds[i] &= 0xffffff00; - break; - case 'T': - lastT = lastfpos; - inds[i] &= 0xffffff00; - break; - case 'N': - lastN = lastfpos; - numN++; - break; - case 'V': - lastV = lastfpos; - numV++; - break; - case 'R': - numR++; - break; - } - } - else - { - doissue = 0; - if ( func == 'K' ) - { - if ( lastK == lastfpos ) - doissue = 1; - } - else if ( func == 'T' ) - { - if ( lastT == lastfpos ) - doissue = 1; - } - else if ( func == 'N' ) - { - if ( numn > numN-128 ) - doissue = 1; - numn++; - } - else if ( func == 'V' ) - { - if ( KOMODO_PAX != 0 && numv > numV-1440 ) - doissue = 1; - numv++; - } - else if ( func == 'R' ) - doissue = 1; - if ( doissue != 0 ) - { - //printf("issue %c total.%d lastfpos.%ld\n",func,count,lastfpos); - komodo_parsestatefiledata(sp,filedata,&lastfpos,datalen,symbol,dest); - count++; - } - } - } - lastfpos = fpos; - } - } - printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); - /*else if ( func == 'K' ) // KMD height: stop after 1st - else if ( func == 'T' ) // KMD height+timestamp: stop after 1st - - else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; - else if ( func == 'V' ) // price feed: can stop after 1440+ - else if ( func == 'R' ) // opreturn:*/ -} +void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest); -void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) -{ - FILE *fp; - long filesize,buflen = *allocsizep; - uint8_t *buf = *bufp; - *lenp = 0; - if ( (fp= fopen(fname,"rb")) != 0 ) - { - fseek(fp,0,SEEK_END); - filesize = ftell(fp); - if ( filesize == 0 ) - { - fclose(fp); - *lenp = 0; - printf("OS_loadfile null size.(%s)\n",fname); - return(0); - } - if ( filesize > buflen ) - { - *allocsizep = filesize; - *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); - } - rewind(fp); - if ( buf == 0 ) - printf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - printf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //printf("loaded.(%s)\n",buf); - } //else printf("OS_loadfile couldnt load.(%s)\n",fname); - return(buf); -} +void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -uint8_t *OS_fileptr(long *allocsizep,char *fname) -{ - long filesize = 0; uint8_t *buf = 0; void *retptr; - *allocsizep = 0; - retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); - return((uint8_t *)retptr); -} +uint8_t *OS_fileptr(long *allocsizep,const char *fname); -long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest) -{ - FILE *fp; long fsize,lastfpos=0,fpos=0; uint8_t *inds,func; int32_t i,n; uint32_t offset,tmp,prevpos100 = 0; - *indcounterp = *prevpos100p = 0; - if ( (inds= OS_fileptr(&fsize,indfname)) != 0 ) - { - lastfpos = 0; - fprintf(stderr,"inds.%p validate %s fsize.%ld datalen.%ld n.%d lastfpos.%ld\n",inds,indfname,fsize,datalen,(int32_t)(fsize / sizeof(uint32_t)),lastfpos); - if ( (fsize % sizeof(uint32_t)) == 0 ) - { - n = (int32_t)(fsize / sizeof(uint32_t)); - for (i=0; i n-10 ) - printf("%d: tmp.%08x [%c] prevpos100.%u\n",i,tmp,tmp&0xff,prevpos100); - if ( (i % 100) == 0 ) - prevpos100 = tmp; - else - { - func = (tmp & 0xff); - offset = (tmp >> 8); - fpos = prevpos100 + offset; - if ( lastfpos >= datalen || filedata[lastfpos] != func ) - { - printf("validate.%d error (%u %d) prev100 %u -> fpos.%ld datalen.%ld [%d] (%c) vs (%c) lastfpos.%ld\n",i,offset,func,prevpos100,fpos,datalen,lastfpos < datalen ? filedata[lastfpos] : -1,func,filedata[lastfpos],lastfpos); - return(-1); - } - } - lastfpos = fpos; - } - *indcounterp = n; - *prevpos100p = prevpos100; - if ( sp != 0 ) - komodo_stateind_set(sp,(uint32_t *)inds,n,filedata,fpos,symbol,dest); - //printf("free inds.%p %s validated[%d] fpos.%ld datalen.%ld, offset %ld vs fsize.%ld\n",inds,indfname,i,fpos,datalen,i * sizeof(uint32_t),fsize); - free(inds); - return(fpos); - } else printf("wrong filesize %s %ld\n",indfname,fsize); - } - free(inds); - fprintf(stderr,"indvalidate return -1\n"); - return(-1); -} +long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest); -long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp) -{ - uint32_t tmp; - if ( indfp != 0 ) - { - tmp = ((uint32_t)(newfpos - *prevpos100p) << 8) | (func & 0xff); - if ( ftell(indfp)/sizeof(uint32_t) != *indcounterp ) - printf("indfp fpos %ld -> ind.%ld vs counter.%u\n",ftell(indfp),ftell(indfp)/sizeof(uint32_t),*indcounterp); - //fprintf(stderr,"ftell.%ld indcounter.%u lastfpos.%ld newfpos.%ld func.%02x\n",ftell(indfp),*indcounterp,lastfpos,newfpos,func); - fwrite(&tmp,1,sizeof(tmp),indfp), (*indcounterp)++; - if ( (*indcounterp % 100) == 0 ) - { - *prevpos100p = (uint32_t)newfpos; - fwrite(prevpos100p,1,sizeof(*prevpos100p),indfp), (*indcounterp)++; - } - } - return(newfpos); -} +long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp); -int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) -{ - FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; - starttime = (uint32_t)time(NULL); - safecopy(indfname,fname,sizeof(indfname)-4); - strcat(indfname,".ind"); - if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) - { - if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) - { - lastfpos = fpos = 0; - indcounter = prevpos100 = 0; - if ( (indfp= fopen(indfname,"wb")) != 0 ) - fwrite(&prevpos100,1,sizeof(prevpos100),indfp), indcounter++; - fprintf(stderr,"processing %s %ldKB, validated.%ld\n",fname,datalen/1024,validated); - while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) - { - lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); - } - if ( indfp != 0 ) - { - fclose(indfp); - if ( (fpos= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) - printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); - else printf("%s validated fpos.%ld\n",indfname,fpos); - } - finished = 1; - fprintf(stderr,"took %d seconds to process %s %ldKB\n",(int32_t)(time(NULL)-starttime),fname,datalen/1024); - } - else if ( validated > 0 ) - { - if ( (indfp= fopen(indfname,"rb+")) != 0 ) - { - lastfpos = fpos = validated; - fprintf(stderr,"datalen.%ld validated %ld -> indcounter %u, prevpos100 %u offset.%d\n",datalen,validated,indcounter,prevpos100,(int32_t)(indcounter * sizeof(uint32_t))); - if ( fpos < datalen ) - { - fseek(indfp,indcounter * sizeof(uint32_t),SEEK_SET); - if ( ftell(indfp) == indcounter * sizeof(uint32_t) ) - { - while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) - { - lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); - if ( lastfpos != fpos ) - fprintf(stderr,"unexpected lastfpos.%ld != %ld\n",lastfpos,fpos); - } - } - fclose(indfp); - } - if ( komodo_stateind_validate(sp,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest) < 0 ) - printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); - else - { - printf("%s validated updated from validated.%ld to %ld new.[%ld] -> indcounter %u, prevpos100 %u offset.%ld | elapsed %d seconds\n",indfname,validated,fpos,fpos-validated,indcounter,prevpos100,indcounter * sizeof(uint32_t),(int32_t)(time(NULL) - starttime)); - finished = 1; - } - } - } else printf("komodo_faststateinit unexpected case\n"); - free(filedata); - return(finished == 1); - } - return(-1); -} +int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); uint64_t komodo_interestsum(); -void komodo_passport_iteration() -{ - static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; - int32_t maxseconds = 10; - FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex; - expired = 0; - while ( 0 && KOMODO_INITDONE == 0 ) - { - fprintf(stderr,"[%s] PASSPORT iteration waiting for KOMODO_INITDONE\n",ASSETCHAINS_SYMBOL); - sleep(3); - } - if ( komodo_chainactive_timestamp() > lastinterest ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - komodo_interestsum(); - //komodo_longestchain(); - lastinterest = komodo_chainactive_timestamp(); - } - refsp = komodo_stateptr(symbol,dest); - if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDCC") == 0 ) - { - refid = 33; - limit = 10000000; - jumblr_iteration(); - } - else - { - limit = 10000000; - refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 - if ( refid == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - } - } - /*if ( KOMODO_PAX == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - }*/ - starttime = (uint32_t)time(NULL); - if ( callcounter++ < 1 ) - limit = 10000; - lasttime = starttime; - for (baseid=32; baseid>=0; baseid--) - { - if ( time(NULL) >= starttime+maxseconds ) - break; - sp = 0; - isrealtime = 0; - base = (char *)CURRENCIES[baseid]; - //printf("PASSPORT %s baseid+1 %d refid.%d\n",ASSETCHAINS_SYMBOL,baseid+1,refid); - if ( baseid+1 != refid ) // only need to import state from a different coin - { - if ( baseid == 32 ) // only care about KMD's state - { - refsp->RTmask &= ~(1LL << baseid); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); - komodo_nameset(symbol,dest,base); - sp = komodo_stateptrget(symbol); - n = 0; - if ( lastpos[baseid] == 0 && (filedata= OS_fileptr(&datalen,fname)) != 0 ) - { - fpos = 0; - fprintf(stderr,"%s processing %s %ldKB\n",ASSETCHAINS_SYMBOL,fname,datalen/1024); - while ( komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest) >= 0 ) - lastfpos = fpos; - fprintf(stderr,"%s took %d seconds to process %s %ldKB\n",ASSETCHAINS_SYMBOL,(int32_t)(time(NULL)-starttime),fname,datalen/1024); - lastpos[baseid] = lastfpos; - free(filedata), filedata = 0; - datalen = 0; - } - else if ( (fp= fopen(fname,"rb")) != 0 && sp != 0 ) - { - fseek(fp,0,SEEK_END); - //fprintf(stderr,"couldnt OS_fileptr(%s), freading %ldKB\n",fname,ftell(fp)/1024); - if ( ftell(fp) > lastpos[baseid] ) - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("%s passport refid.%d %s fname.(%s) base.%s %ld %ld\n",ASSETCHAINS_SYMBOL,refid,symbol,fname,base,ftell(fp),lastpos[baseid]); - fseek(fp,lastpos[baseid],SEEK_SET); - while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 && n < limit ) - { - if ( n == limit-1 ) - { - if ( time(NULL) < starttime+maxseconds ) - n = 0; - else - { - //printf("expire passport loop %s -> %s at %ld\n",ASSETCHAINS_SYMBOL,base,lastpos[baseid]); - expired++; - } - } - n++; - } - lastpos[baseid] = ftell(fp); - if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 ) - printf("from.(%s) lastpos[%s] %ld isrt.%d\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid],komodo_isrealtime(&ht)); - } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); - fclose(fp); - } else fprintf(stderr,"load error.(%s) %p\n",fname,sp); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) - { - sp->CURRENT_HEIGHT = buf[0]; - if ( buf[0] != 0 && buf[0] >= buf[1] && buf[2] > time(NULL)-60 ) - { - isrealtime = 1; - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - } - else if ( KOMODO_PAX != 0 && (time(NULL)-buf[2]) > 60 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"[%s]: %s not RT %u %u %d\n",ASSETCHAINS_SYMBOL,base,buf[0],buf[1],(int32_t)(time(NULL)-buf[2])); - } //else fprintf(stderr,"%s size error RT\n",base); - fclose(fp); - } //else fprintf(stderr,"%s open error RT\n",base); - } - } - else - { - refsp->RTmask &= ~(1LL << baseid); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - buf[0] = (uint32_t)chainActive.LastTip()->GetHeight(); - buf[1] = (uint32_t)komodo_longestchain(); - if ( buf[0] != 0 && buf[0] == buf[1] ) - { - buf[2] = (uint32_t)time(NULL); - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - if ( refid != 0 ) - memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); - } - if ( fwrite(buf,1,sizeof(buf),fp) != sizeof(buf) ) - fprintf(stderr,"[%s] %s error writing realtime\n",ASSETCHAINS_SYMBOL,base); - fclose(fp); - } else fprintf(stderr,"%s create error RT\n",base); - } - if ( sp != 0 && isrealtime == 0 ) - refsp->RTbufs[0][2] = 0; - } - //komodo_paxtotal(); // calls komodo_isrealtime(), which calls komodo_longestchain() - refsp->RTmask |= RTmask; - if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); - } -} - +void komodo_passport_iteration(); extern std::vector Mineropret; // opreturn data set by the data gathering code #define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% @@ -1598,183 +96,28 @@ extern std::vector Mineropret; // opreturn data set by the data gatheri #define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) -const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) -// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" -const char *Forex[] = -{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" -}; // must be in ECB list - -struct komodo_extremeprice -{ - uint256 blockhash; - uint32_t pricebits,timestamp; - int32_t height; - int16_t dir,ind; -} ExtremePrice; - -struct komodo_priceinfo -{ - FILE *fp; - char symbol[64]; -} PRICES[KOMODO_MAXPRICES]; - -uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; -int64_t PriceMult[KOMODO_MAXPRICES]; int32_t komodo_cbopretsize(uint64_t flags); -void komodo_PriceCache_shift() -{ - int32_t i; - for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--) - memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i])); - memcpy(PriceCache[0],Mineropret.data(),Mineropret.size()); -} +void komodo_PriceCache_shift(); -int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block) -{ - CTransaction tx; int32_t numvouts; std::vector vopret; - tx = block->vtx[0]; - numvouts = (int32_t)tx.vout.size(); - GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); - if ( vopret.size() >= PRICES_SIZEBIT0 ) - { - if ( seedp != 0 ) - memcpy(seedp,&block->hashMerkleRoot,sizeof(*seedp)); - memcpy(heightbits,vopret.data(),vopret.size()); - return((int32_t)(vopret.size()/sizeof(uint32_t))); - } - return(-1); -} +int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block); // komodo_heightpricebits() extracts the price data in the coinbase for nHeight -int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight) -{ - CBlockIndex *pindex; CBlock block; - if ( seedp != 0 ) - *seedp = 0; - if ( (pindex= komodo_chainactive(nHeight)) != 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - { - return(_komodo_heightpricebits(seedp,heightbits,&block)); - } - } - fprintf(stderr,"couldnt get pricebits for %d\n",nHeight); - return(-1); -} +int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); /* komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit */ -uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance) -{ - uint64_t highprice,lowprice; - if ( refprice < 2 ) - return(0); - highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price - lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest - if ( highprice == refprice ) - highprice++; - if ( lowprice == refprice ) - lowprice--; - if ( price >= highprice ) - { - //fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); - if ( price > highprice ) // return non-zero only if we violate the tolerance - { - *maxflagp = 2; - return(highprice); - } - *maxflagp = 1; - } - else if ( price <= lowprice ) - { - //fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); - if ( price < lowprice ) - { - *maxflagp = -2; - return(lowprice); - } - *maxflagp = -1; - } - return(0); -} +uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance); // komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance -int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance) -{ - int32_t i; uint32_t newprice; - for (i=1; i newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]); - return(-1); - } - } - return(0); -} +int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance); // komodo_priceclamp() clamps any price that is beyond tolerance -int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance) -{ - int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES]; - memset(maxflags,0,sizeof(maxflags)); - for (i=1; i %u\n",i,n,refprices[i],pricebits[i],newprice); - pricebits[i] = newprice; - } - } - return(0); -} +int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance); // komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight -CScript komodo_mineropret(int32_t nHeight) -{ - CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0; - if ( Mineropret.size() >= PRICES_SIZEBIT0 ) - { - n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); - numzero = 1; - while ( numzero > 0 ) - { - memcpy(pricebits,Mineropret.data(),Mineropret.size()); - for (i=numzero=0; i 0 ) - { - memcpy(pricebits,Mineropret.data(),Mineropret.size()); - memset(maxflags,0,sizeof(maxflags)); - if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 ) - { - // if the new prices are outside tolerance, update Mineropret with clamped prices - komodo_priceclamp(n,pricebits,prevbits,PRICES_ERRORRATE); - //fprintf(stderr,"update Mineropret to clamped prices\n"); - memcpy(Mineropret.data(),pricebits,Mineropret.size()); - } - } - int32_t i; - for (i=0; i vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; - now = (uint32_t)time(NULL); - if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) - { - bhash = block->GetHash(); - GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() >= PRICES_SIZEBIT0 ) - { - n = (int32_t)(vopret.size() / sizeof(uint32_t)); - memcpy(pricebits,vopret.data(),Mineropret.size()); - memset(maxflags,0,sizeof(maxflags)); - if ( nHeight > 2 ) - { - prevtime = previndex->nTime; - lag = (int32_t)(now - pricebits[0]); - lag2 = (int32_t)(pricebits[0] - prevtime); - lag3 = (int32_t)(block->nTime - pricebits[0]); - if ( lag < -60 ) // avoid data from future - { - fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); - return(-1); - } - if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp - { - fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME); - if ( nHeight > testchain_exemption ) - return(-1); - } - if ( lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME ) - { - fprintf(stderr,"C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); - if ( nHeight > testchain_exemption ) - return(-1); - } - btcusd = (double)pricebits[1]/10000; - btcgbp = (double)pricebits[2]/10000; - btceur = (double)pricebits[3]/10000; - fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2); - if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 ) - { - if ( nHeight < testchain_exemption ) - { - for (i=0; i= PRICES_SIZEBIT0 ) - { - memcpy(localbits,Mineropret.data(),Mineropret.size()); - if ( nHeight < testchain_exemption ) - { - for (i=0; i 0 && localbits[i] < prevbits[i] ) - { - if ( iter == 0 ) - break; - // second iteration checks recent prices to see if within local volatility - for (j=0; j= prevbits[i] ) - { - fprintf(stderr,"i.%d within recent localprices[%d] %u >= %u\n",i,j,PriceCache[j][i],prevbits[i]); - break; - } - if ( j == KOMODO_LOCALPRICE_CACHESIZE ) - { - komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); - break; - } - } - else if ( maxflag < 0 && localbits[i] > prevbits[i] ) - { - if ( iter == 0 ) - break; - for (j=0; jnTime,bhash,i,prevbits[i]); - break; - } - } - } - } - if ( i != n ) - { - if ( iter == 0 ) - { - fprintf(stderr,"force update prices\n"); - komodo_cbopretupdate(1); - memcpy(localbits,Mineropret.data(),Mineropret.size()); - } else return(-1); - } - } - } - } - if ( bhash == ExtremePrice.blockhash ) - { - fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime); - memset(&ExtremePrice,0,sizeof(ExtremePrice)); - } - return(0); - } else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]); - return(-1); - } - return(0); -} +int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey); -char *nonportable_path(char *str) -{ - int32_t i; - for (i=0; str[i]!=0; i++) - if ( str[i] == '/' ) - str[i] = '\\'; - return(str); -} +char *nonportable_path(char *str); -char *portable_path(char *str) -{ -#ifdef _WIN32 - return(nonportable_path(str)); -#else -#ifdef __PNACL - /*int32_t i,n; - if ( str[0] == '/' ) - return(str); - else - { - n = (int32_t)strlen(str); - for (i=n; i>0; i--) - str[i] = str[i-1]; - str[0] = '/'; - str[n+1] = 0; - }*/ -#endif - return(str); -#endif -} +char *portable_path(char *str); -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) -{ - FILE *fp; - long filesize,buflen = *allocsizep; - uint8_t *buf = *bufp; - *lenp = 0; - if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) - { - fseek(fp,0,SEEK_END); - filesize = ftell(fp); - if ( filesize == 0 ) - { - fclose(fp); - *lenp = 0; - //printf("loadfile null size.(%s)\n",fname); - return(0); - } - if ( filesize > buflen ) - { - *allocsizep = filesize; - *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); - } - rewind(fp); - if ( buf == 0 ) - printf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - printf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //printf("loaded.(%s)\n",buf); - } //else printf("OS_loadfile couldnt load.(%s)\n",fname); - return(buf); -} +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -void *filestr(long *allocsizep,char *_fname) -{ - long filesize = 0; char *fname,*buf = 0; void *retptr; - *allocsizep = 0; - fname = (char *)malloc(strlen(_fname)+1); - strcpy(fname,_fname); - retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); - free(fname); - return(retptr); -} +void *filestr(long *allocsizep,char *_fname); -cJSON *send_curl(char *url,char *fname) -{ - long fsize; char curlstr[1024],*jsonstr; cJSON *json=0; - sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname); - if ( system(curlstr) == 0 ) - { - if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 ) - { - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - } - return(json); -} +cJSON *send_curl(char *url,char *fname); // get_urljson just returns the JSON returned by the URL using issue_curl @@ -2041,590 +154,46 @@ const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; */ -cJSON *get_urljson(char *url) -{ - char *jsonstr; cJSON *json = 0; - if ( (jsonstr= issue_curl(url)) != 0 ) - { - //fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr); - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - return(json); -} - -int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols) -{ - 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()); - 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; - for (i=0; i now+60 || timestamp < now-ASSETCHAINS_BLOCKTIME ) - { - fprintf(stderr,"time error.%d (%u vs %u)\n",timestamp-now,timestamp,now); - retval = -1; - }*/ - if ( symbols[i] != symbol ) - { - retval = -1; - fprintf(stderr,"MISMATCH."); - } - fprintf(stderr,"(%s %u) ",symbol,uprice); - } - } - fprintf(stderr,"numstocks.%d\n",n); - } - //https://api.iextrading.com/1.0/tops/last?symbols=AAPL -> [{"symbol":"AAPL","price":198.63,"size":100,"time":1555092606076}] - free_json(json); - } - return(retval); -} - -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= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"dailyfx")) != 0 ) - { - if ( (rates= jobj(json,(char *)"rates")) != 0 ) - { - for (i=0; i strvec) -{ - int32_t i,errs=0; uint32_t price; char *symbol; - for (i=0; i symbols); -/*uint32_t oldget_stockprice(const char *symbol) -{ - char url[512]; cJSON *json,*obj; uint32_t high,low,price = 0; - sprintf(url,"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=%s&interval=15min&apikey=%s",symbol,NOTARY_PUBKEY.data()+50); - if ( (json= get_urljson(url)) != 0 ) - { - if ( (obj= jobj(json,(char *)"Time Series (15min)")) != 0 ) - { - high = jdouble(jitem(obj,0),(char *)"2. high")*10000 + 0.000049; - low = jdouble(jitem(obj,0),(char *)"3. low")*10000 + 0.000049; - price = (high + low) / 2; - } - free_json(json); - } - return(price); -} +uint32_t get_dailyfx(uint32_t *prices); -uint32_t get_currencyprice(const char *symbol) -{ - char url[512]; cJSON *json,*obj; uint32_t price = 0; - sprintf(url,"https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=%s&to_currency=USD&apikey=%s",symbol,NOTARY_PUBKEY.data()+50); - if ( (json= send_curl(url,(char *)"curldata")) != 0 )//get_urljson(url)) != 0 ) - { - if ( (obj= jobj(jitem(json,0),0)) != 0 ) - price = jdouble(obj,(char *)"5. Exchange Rate")*10000 + 0.000049; - free_json(json); - } - return(price); -} +uint32_t get_binanceprice(const char *symbol); -int32_t get_stocks(const char *list[],int32_t n) -{ - int32_t i,errs=0; uint32_t price; - for (i=0; i strvec); // parse the coindesk specific data. yes, if this changes, it will require an update. However, regardless if the format from the data source changes, then the code that extracts it must be changed. One way to mitigate this is to have a large variety of data sources so that there is only a very remote chance that all of them are not available. Certainly the data gathering needs to be made more robust, but it doesnt really affect the proof of concept for the decentralized trustless oracle. The trustlessness is achieved by having all nodes get the oracle data. -int32_t get_btcusd(uint32_t pricebits[4]) -{ - cJSON *pjson,*bpi,*obj; char str[512]; double dbtcgbp,dbtcusd,dbtceur; uint64_t btcusd = 0,btcgbp = 0,btceur = 0; - if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json")) != 0 ) - { - if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 ) - { - pricebits[0] = (uint32_t)time(NULL); - if ( (obj= jobj(bpi,(char *)"USD")) != 0 ) - { - btcusd = jdouble(obj,(char *)"rate_float") * SATOSHIDEN; - pricebits[1] = ((btcusd / 10000) & 0xffffffff); - } - if ( (obj= jobj(bpi,(char *)"GBP")) != 0 ) - { - btcgbp = jdouble(obj,(char *)"rate_float") * SATOSHIDEN; - pricebits[2] = ((btcgbp / 10000) & 0xffffffff); - } - if ( (obj= jobj(bpi,(char *)"EUR")) != 0 ) - { - btceur = jdouble(obj,(char *)"rate_float") * SATOSHIDEN; - pricebits[3] = ((btceur / 10000) & 0xffffffff); - } - } - free_json(pjson); - dbtcusd = (double)pricebits[1]/10000; - dbtcgbp = (double)pricebits[2]/10000; - dbtceur = (double)pricebits[3]/10000; - fprintf(stderr,"BTC/USD %.4f, BTC/GBP %.4f, BTC/EUR %.4f GBPUSD %.6f, EURUSD %.6f EURGBP %.6f\n",dbtcusd,dbtcgbp,dbtceur,dbtcusd/dbtcgbp,dbtcusd/dbtceur,dbtcgbp/dbtceur); - return(0); - } - return(-1); -} +int32_t get_btcusd(uint32_t pricebits[4]); // komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation // save history, use new data to approve past rejection, where is the auto-reconsiderblock? -int32_t komodo_cbopretsize(uint64_t flags) -{ - int32_t size = 0; - if ( (ASSETCHAINS_CBOPRET & 1) != 0 ) - { - size = PRICES_SIZEBIT0; - if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) - size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); - if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) - size += (sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); - if ( (ASSETCHAINS_CBOPRET & 8) != 0 ) - size += (ASSETCHAINS_STOCKS.size() * sizeof(uint32_t)); - } - return(size); -} +int32_t komodo_cbopretsize(uint64_t flags); -extern uint256 Queued_reconsiderblock; +void komodo_cbopretupdate(int32_t forceflag); -void komodo_cbopretupdate(int32_t forceflag) -{ - static uint32_t lasttime,lastbtc,pending; - static uint32_t pricebits[4],pricebuf[KOMODO_MAXPRICES],forexprices[sizeof(Forex)/sizeof(*Forex)]; - int32_t size; uint32_t flags=0,now; CBlockIndex *pindex; - if ( Queued_reconsiderblock != zeroid ) - { - fprintf(stderr,"Queued_reconsiderblock %s\n",Queued_reconsiderblock.GetHex().c_str()); - komodo_reconsiderblock(Queued_reconsiderblock); - Queued_reconsiderblock = zeroid; - } - if ( forceflag != 0 && pending != 0 ) - { - while ( pending != 0 ) - fprintf(stderr,"pricewait "), sleep(1); - return; - } - pending = 1; - now = (uint32_t)time(NULL); - if ( (ASSETCHAINS_CBOPRET & 1) != 0 ) - { -//if ( komodo_nextheight() > 333 ) // for debug only! -// ASSETCHAINS_CBOPRET = 7; - size = komodo_cbopretsize(ASSETCHAINS_CBOPRET); - if ( Mineropret.size() < size ) - Mineropret.resize(size); - size = PRICES_SIZEBIT0; - if ( (forceflag != 0 || now > lastbtc+120) && get_btcusd(pricebits) == 0 ) - { - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(PriceCache[0],pricebits,PRICES_SIZEBIT0); - flags |= 1; - } - if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) - { - if ( now > lasttime+3600*5 || forexprices[0] == 0 ) // cant assume timestamp is valid for forex price as it is a daily weekday changing thing anyway. - { - get_dailyfx(forexprices); - if ( flags == 0 ) - komodo_PriceCache_shift(); - flags |= 2; - memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices)); - } - size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); - } - if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) - { - if ( forceflag != 0 || flags != 0 ) - { - get_cryptoprices(pricebuf,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES); - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t)); - flags |= 4; // very rarely we can see flags == 6 case - } - size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); - } - now = (uint32_t)time(NULL); - if ( (ASSETCHAINS_CBOPRET & 8) != 0 ) - { - if ( forceflag != 0 || flags != 0 ) - { - if ( get_stockprices(now,pricebuf,ASSETCHAINS_STOCKS) == ASSETCHAINS_STOCKS.size() ) - { - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,ASSETCHAINS_STOCKS.size() * sizeof(uint32_t)); - flags |= 8; // very rarely we can see flags == 10 case - } - } - size += (ASSETCHAINS_STOCKS.size()) * sizeof(uint32_t); - } - if ( flags != 0 ) - { - if ( (flags & 1) != 0 ) - lastbtc = now; - if ( (flags & 2) != 0 ) - lasttime = now; - memcpy(Mineropret.data(),PriceCache[0],size); - if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 ) - { - fprintf(stderr,"cmp dir.%d PriceCache[0][ExtremePrice.ind] %u >= %u ExtremePrice.pricebits\n",ExtremePrice.dir,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); - if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) - { - fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); - if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) - pindex->nStatus &= ~BLOCK_FAILED_MASK; - else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str()); - } - } - // high volatility still strands nodes so we need to check new prices to approve a stuck block - // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state - - //int32_t i; for (i=0; i= KOMODO_MAXPRICES ) - return(-1); - mult = komodo_pricemult(ind); - if ( nonzprices != 0 ) - memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); - //for (i=0; i= PRICES_DAYWINDOW ) - i = 0; - if ( (price= rawprices[i*rawskip]) == 0 ) - { - fprintf(stderr,"null rawprice.[%d]\n",i); - return(-1); - } - if ( price >= lowprice && price <= highprice ) - { - //fprintf(stderr,"%.1f ",(double)price/10000); - sum += price; - correlation++; - if ( correlation > (PRICES_DAYWINDOW>>1) ) - { - if ( nonzprices == 0 ) - return(refprice * mult); - //fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation); - //return(sum*mult/correlation); - n = 0; - i = (iter + seed) % PRICES_DAYWINDOW; - for (k=0; k= PRICES_DAYWINDOW ) - i = 0; - if ( n > (PRICES_DAYWINDOW>>1) ) - nonzprices[i] = 0; - else - { - price = rawprices[i*rawskip]; - if ( price < lowprice || price > highprice ) - nonzprices[i] = 0; - else - { - nonzprices[i] = price; - //fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]); - n++; - } - } - } - //fprintf(stderr,"ind.%d iter.%d j.%d i.%d n.%d correlation.%d ref %llu -> %llu\n",ind,iter,j,i,n,correlation,(long long)refprice,(long long)sum/correlation); - if ( n != correlation ) - return(-1); - sum = den = n = 0; - for (i=0; i %.8f\n",(long long)firstprice,((double)(sum*mult) / den) / COIN); - return((sum * mult) / den); - } - } - } - if ( correlation > maxcorrelation ) - maxcorrelation = correlation; - } - fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); - return(0); -} +int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth); -int64_t _pairave64(int64_t valA,int64_t valB) -{ - if ( valA != 0 && valB != 0 ) - return((valA + valB) / 2); - else if ( valA != 0 ) return(valA); - else return(valB); -} +int64_t _pairave64(int64_t valA,int64_t valB); -int64_t _pairdiff64(register int64_t valA,register int64_t valB) -{ - if ( valA != 0 && valB != 0 ) - return(valA - valB); - else return(0); -} +int64_t _pairdiff64(register int64_t valA,register int64_t valB); -int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width) -{ - register int32_t nonz,j; register int64_t sum,price; - nonz = 0; - sum = 0; - for (j=-width; j<=width; j++) - { - price = buf[i + j]; - if ( price != 0 ) - { - sum += price; - nonz++; - } - } - if ( nonz != 0 ) - sum /= nonz; - return(sum); -} +int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width); -void buf_trioave64(int64_t dest[],int64_t src[],int32_t n) -{ - register int32_t i,j,width = 3; - for (i=0; i<128; i++) - src[i] = 0; - //for (i=n-width-1; i>width; i--) - // dest[i] = balanced_ave(src,i,width); - //for (i=width; i>0; i--) - // dest[i] = balanced_ave(src,i,i); - for (i=1; i price ) // rising prices - sort64(buf,PRICES_DAYWINDOW); - else revsort64(buf,PRICES_DAYWINDOW); - decayprice = buf[0]; - for (i=0; i %.8f\n",halfave 0 && PRICES[0].fp != 0 && createflag != 0 ) - { - fseek(PRICES[0].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); - fputc(0,PRICES[0].fp); - fflush(PRICES[0].fp); - } - fprintf(stderr,"pricesinit done i.%d num.%d numprices.%d\n",i,num,(int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t))); - if ( i != num || i != komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t) ) - { - fprintf(stderr,"fatal error opening prices files, start shutdown\n"); - StartShutdown(); - } - return(0); -} +int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip); -pthread_mutex_t pricemutex; +int32_t komodo_pricesinit(); // PRICES file layouts // [0] rawprice32 / timestamp @@ -2756,90 +235,6 @@ pthread_mutex_t pricemutex; // [2] 24hr ave // [3] to [7] reserved -void komodo_pricesupdate(int32_t height,CBlock *pblock) -{ - static int numprices; static uint32_t *ptr32; static int64_t *ptr64,*tmpbuf; - int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[PRICES_MAXDATAPOINTS*2]; - width = PRICES_DAYWINDOW;//(2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH); - if ( numprices == 0 ) - { - pthread_mutex_init(&pricemutex,0); - numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); - ptr32 = (uint32_t *)calloc(sizeof(uint32_t),numprices * width); - ptr64 = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS); - tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW); - fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); - } - if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) - { - //for (ind=0; ind PRICES_DAYWINDOW ) - { - fseek(PRICES[0].fp,(height-width+1) * numprices * sizeof(uint32_t),SEEK_SET); - if ( fread(ptr32,sizeof(uint32_t),width*numprices,PRICES[0].fp) == width*numprices ) - { - rngval = seed; - for (ind=1; ind 0 ) - { - fseek(PRICES[ind].fp,height * sizeof(int64_t) * PRICES_MAXDATAPOINTS,SEEK_SET); - memset(buf,0,sizeof(buf)); - buf[0] = rawprices[ind]; - buf[1] = rawprices[0]; // timestamp - memcpy(&buf[2],&correlated,sizeof(correlated)); - if ( fwrite(buf,1,sizeof(buf),PRICES[ind].fp) != sizeof(buf) ) - fprintf(stderr,"error fwrite buf for ht.%d ind.%d\n",height,ind); - else if ( height > PRICES_DAYWINDOW*2 ) - { - fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); - if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS,PRICES[ind].fp) == PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS ) - { - if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[(PRICES_DAYWINDOW-1)*PRICES_MAXDATAPOINTS+1],-PRICES_MAXDATAPOINTS)) > 0 ) - { - fseek(PRICES[ind].fp,(height * PRICES_MAXDATAPOINTS + 2) * sizeof(int64_t),SEEK_SET); - if ( fwrite(&smoothed,1,sizeof(smoothed),PRICES[ind].fp) != sizeof(smoothed) ) - fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); - else fflush(PRICES[ind].fp); - } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); - } else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind); - } - } else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); - } - fprintf(stderr,"height.%d\n",height); - } else fprintf(stderr,"error reading rawprices for ht.%d\n",height); - } else fprintf(stderr,"height.%d <= width.%d\n",height,width); - pthread_mutex_unlock(&pricemutex); - } else fprintf(stderr,"null PRICES[0].fp\n"); - } else fprintf(stderr,"numprices mismatch, height.%d\n",height); -} +void komodo_pricesupdate(int32_t height,CBlock *pblock); -int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks) -{ - FILE *fp; int32_t retval = PRICES_MAXDATAPOINTS; - pthread_mutex_lock(&pricemutex); - if ( ind < KOMODO_MAXPRICES && (fp= PRICES[ind].fp) != 0 ) - { - fseek(fp,height * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); - if ( fread(buf64,sizeof(int64_t),numblocks*PRICES_MAXDATAPOINTS,fp) != numblocks*PRICES_MAXDATAPOINTS ) - retval = -1; - } - pthread_mutex_unlock(&pricemutex); - return(retval); -} +int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); diff --git a/src/komodo_globals.cpp b/src/komodo_globals.cpp new file mode 100644 index 00000000000..dffafdda929 --- /dev/null +++ b/src/komodo_globals.cpp @@ -0,0 +1,186 @@ +/****************************************************************************** + * 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 "komodo_globals.h" + +int32_t komodo_baseid(char *origbase) +{ + int32_t i; char base[64]; + for (i=0; origbase[i]!=0&&i= 0 && baseid < 32 ) + // cur_money = ASSETCHAINS_GENESISTXVAL + ASSETCHAINS_SUPPLY + nHeight * ASSETCHAINS_REWARD[0] / SATOSHIDEN; + //else + { + // figure out max_money by adding up supply to a maximum of 10,000,000 blocks + cur_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISTXVAL; + if ( ASSETCHAINS_LASTERA == 0 && ASSETCHAINS_REWARD[0] == 0 ) + { + cur_money += (nHeight * 10000);// / SATOSHIDEN; + } + else + { + for ( int j = 0; j <= ASSETCHAINS_LASTERA; j++ ) + { + // if any condition means we have no more rewards, break + if (j != 0 && (nHeight <= ASSETCHAINS_ENDSUBSIDY[j - 1] || (ASSETCHAINS_ENDSUBSIDY[j - 1] == 0 && + (ASSETCHAINS_REWARD[j] == 0 && (j == ASSETCHAINS_LASTERA || ASSETCHAINS_DECAY[j] != SATOSHIDEN))))) + break; + + // add rewards from this era, up to nHeight + int64_t reward = ASSETCHAINS_REWARD[j]; + + //fprintf(stderr,"last.%d reward %llu period %llu\n",(int32_t)ASSETCHAINS_LASTERA,(long long)reward,(long long)ASSETCHAINS_HALVING[j]); + if ( reward > 0 ) + { + uint64_t lastEnd = j == 0 ? 0 : ASSETCHAINS_ENDSUBSIDY[j - 1]; + uint64_t curEnd = ASSETCHAINS_ENDSUBSIDY[j] == 0 ? nHeight : nHeight > ASSETCHAINS_ENDSUBSIDY[j] ? ASSETCHAINS_ENDSUBSIDY[j] : nHeight; + uint64_t period = ASSETCHAINS_HALVING[j]; + if ( period == 0 ) + period = 210000; + uint32_t nSteps = (curEnd - lastEnd) / period; + uint32_t modulo = (curEnd - lastEnd) % period; + uint64_t decay = ASSETCHAINS_DECAY[j]; + + //fprintf(stderr,"period.%llu cur_money %.8f += %.8f * %d\n",(long long)period,(double)cur_money/COIN,(double)reward/COIN,nHeight); + if ( ASSETCHAINS_HALVING[j] == 0 ) + { + // no halving, straight multiply + cur_money += reward * (nHeight - 1); + //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); + } + // if exactly SATOSHIDEN, linear decay to zero or to next era, same as: + // (next_era_reward + (starting reward - next_era_reward) / 2) * num_blocks + else if ( decay == SATOSHIDEN ) + { + int64_t lowestSubsidy, subsidyDifference, stepDifference, stepTriangle; + int64_t denominator, modulo=1; + int32_t sign = 1; + + if ( j == ASSETCHAINS_LASTERA ) + { + subsidyDifference = reward; + lowestSubsidy = 0; + } + else + { + // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 + subsidyDifference = reward - ASSETCHAINS_REWARD[j + 1]; + if (subsidyDifference < 0) + { + sign = -1; + subsidyDifference *= sign; + lowestSubsidy = reward; + } + else + { + lowestSubsidy = ASSETCHAINS_REWARD[j + 1]; + } + } + + // if we have not finished the current era, we need to caluclate a total as if we are at the end, with the current + // subsidy. we will calculate the total of a linear era as follows. Each item represents an area calculation: + // a) the rectangle from 0 to the lowest reward in the era * the number of blocks + // b) the rectangle of the remainder of blocks from the lowest point of the era to the highest point of the era if any remainder + // c) the minor triangle from the start of transition from the lowest point to the start of transition to the highest point + // d) one halving triangle (half area of one full step) + // + // we also need: + // e) number of steps = (n - erastart) / halving interval + // + // the total supply from era start up to height is: + // a + b + c + (d * e) + + // calculate amount in one step's triangular protrusion over minor triangle's hypotenuse + denominator = nSteps * period; + if ( denominator == 0 ) + denominator = 1; + // difference of one step vs. total + stepDifference = (period * subsidyDifference) / denominator; + + // area == coin holding of one step triangle, protruding from minor triangle's hypotenuse + stepTriangle = (period * stepDifference) >> 1; + + // sign is negative if slope is positive (start is less than end) + if (sign < 0) + { + // use steps minus one for our calculations, and add the potentially partial rectangle + // at the end + cur_money += stepTriangle * (nSteps - 1); + cur_money += stepTriangle * (nSteps - 1) * (nSteps - 1); + + // difference times number of steps is height of rectangle above lowest subsidy + cur_money += modulo * stepDifference * nSteps; + } + else + { + // if negative slope, the minor triangle is the full number of steps, as the highest + // level step is full. lowest subsidy is just the lowest so far + lowestSubsidy = reward - (stepDifference * nSteps); + + // add the step triangles, one per step + cur_money += stepTriangle * nSteps; + + // add the minor triangle + cur_money += stepTriangle * nSteps * nSteps; + } + + // add more for the base rectangle if lowest subsidy is not 0 + cur_money += lowestSubsidy * (curEnd - lastEnd); + } + else + { + for ( int k = lastEnd; k < curEnd; k += period ) + { + cur_money += period * reward; + // if zero, we do straight halving + reward = decay ? (reward * decay) / SATOSHIDEN : reward >> 1; + } + cur_money += modulo * reward; + } + } + } + } + } + if ( KOMODO_BIT63SET(cur_money) != 0 ) + return(KOMODO_MAXNVALUE); + if ( ASSETCHAINS_COMMISSION != 0 ) + { + uint64_t newval = (cur_money + (cur_money/COIN * ASSETCHAINS_COMMISSION)); + if ( KOMODO_BIT63SET(newval) != 0 ) + return(KOMODO_MAXNVALUE); + else if ( newval < cur_money ) // check for underflow + return(KOMODO_MAXNVALUE); + return(newval); + } + //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); + return(cur_money); +} diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 063364230e5..578506f484a 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -12,18 +12,17 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once +#include #include "komodo_defs.h" +#include "komodo_structs.h" void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); -void komodo_init(int32_t height); int32_t komodo_MoMdata(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_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -void komodo_init(int32_t height); -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_isrealtime(int32_t *kmdheightp); uint64_t komodo_paxtotal(); int32_t komodo_longestchain(); @@ -31,7 +30,8 @@ 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; +std::mutex komodo_mutex; +pthread_mutex_t staked_mutex; #define KOMODO_ELECTION_GAP 2000 //((ASSETCHAINS_SYMBOL[0] == 0) ? 2000 : 100) #define KOMODO_ASSETCHAIN_MAXLEN 65 @@ -55,10 +55,13 @@ 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,ASSETCHAINS_CBMATURITY,KOMODO_NSPV; +bool IS_KOMODO_NOTARY; +bool IS_MODE_EXCHANGEWALLET; +bool IS_KOMODO_DEALERNODE; +int32_t KOMODO_MININGTHREADS = -1,STAKED_NOTARY_ID,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,KOMODO_NSPV; 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; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW; int8_t ASSETCHAINS_ADAPTIVEPOW; bool VERUS_MINTBLOCKS; std::vector Mineropret; @@ -118,10 +121,11 @@ uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REW uint32_t KOMODO_INITDONE; char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; uint64_t PENDING_KOMODO_TX; -extern int32_t KOMODO_LOADINGBLOCKS; +extern int32_t KOMODO_LOADINGBLOCKS; // defined in pow.cpp, boolean, 1 if currently loading the block index, 0 if not unsigned int MAX_BLOCK_SIGOPS = 20000; -int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL; +bool IS_KOMODO_TESTNODE; +int32_t KOMODO_SNAPSHOT_INTERVAL; CScript KOMODO_EARLYTXID_SCRIPTPUB; int32_t ASSETCHAINS_EARLYTXIDCONTRACT; int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; @@ -136,172 +140,6 @@ char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", "KMD" }; -int32_t komodo_baseid(char *origbase) -{ - int32_t i; char base[64]; - for (i=0; origbase[i]!=0&&i= 0 && baseid < 32 ) - // cur_money = ASSETCHAINS_GENESISTXVAL + ASSETCHAINS_SUPPLY + nHeight * ASSETCHAINS_REWARD[0] / SATOSHIDEN; - //else - { - // figure out max_money by adding up supply to a maximum of 10,000,000 blocks - cur_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISTXVAL; - if ( ASSETCHAINS_LASTERA == 0 && ASSETCHAINS_REWARD[0] == 0 ) - { - cur_money += (nHeight * 10000);// / SATOSHIDEN; - } - else - { - for ( int j = 0; j <= ASSETCHAINS_LASTERA; j++ ) - { - // if any condition means we have no more rewards, break - if (j != 0 && (nHeight <= ASSETCHAINS_ENDSUBSIDY[j - 1] || (ASSETCHAINS_ENDSUBSIDY[j - 1] == 0 && - (ASSETCHAINS_REWARD[j] == 0 && (j == ASSETCHAINS_LASTERA || ASSETCHAINS_DECAY[j] != SATOSHIDEN))))) - break; - - // add rewards from this era, up to nHeight - int64_t reward = ASSETCHAINS_REWARD[j]; - - //fprintf(stderr,"last.%d reward %llu period %llu\n",(int32_t)ASSETCHAINS_LASTERA,(long long)reward,(long long)ASSETCHAINS_HALVING[j]); - if ( reward > 0 ) - { - uint64_t lastEnd = j == 0 ? 0 : ASSETCHAINS_ENDSUBSIDY[j - 1]; - uint64_t curEnd = ASSETCHAINS_ENDSUBSIDY[j] == 0 ? nHeight : nHeight > ASSETCHAINS_ENDSUBSIDY[j] ? ASSETCHAINS_ENDSUBSIDY[j] : nHeight; - uint64_t period = ASSETCHAINS_HALVING[j]; - if ( period == 0 ) - period = 210000; - uint32_t nSteps = (curEnd - lastEnd) / period; - uint32_t modulo = (curEnd - lastEnd) % period; - uint64_t decay = ASSETCHAINS_DECAY[j]; - - //fprintf(stderr,"period.%llu cur_money %.8f += %.8f * %d\n",(long long)period,(double)cur_money/COIN,(double)reward/COIN,nHeight); - if ( ASSETCHAINS_HALVING[j] == 0 ) - { - // no halving, straight multiply - cur_money += reward * (nHeight - 1); - //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); - } - // if exactly SATOSHIDEN, linear decay to zero or to next era, same as: - // (next_era_reward + (starting reward - next_era_reward) / 2) * num_blocks - else if ( decay == SATOSHIDEN ) - { - int64_t lowestSubsidy, subsidyDifference, stepDifference, stepTriangle; - int64_t denominator, modulo=1; - int32_t sign = 1; - - if ( j == ASSETCHAINS_LASTERA ) - { - subsidyDifference = reward; - lowestSubsidy = 0; - } - else - { - // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 - subsidyDifference = reward - ASSETCHAINS_REWARD[j + 1]; - if (subsidyDifference < 0) - { - sign = -1; - subsidyDifference *= sign; - lowestSubsidy = reward; - } - else - { - lowestSubsidy = ASSETCHAINS_REWARD[j + 1]; - } - } - - // if we have not finished the current era, we need to caluclate a total as if we are at the end, with the current - // subsidy. we will calculate the total of a linear era as follows. Each item represents an area calculation: - // a) the rectangle from 0 to the lowest reward in the era * the number of blocks - // b) the rectangle of the remainder of blocks from the lowest point of the era to the highest point of the era if any remainder - // c) the minor triangle from the start of transition from the lowest point to the start of transition to the highest point - // d) one halving triangle (half area of one full step) - // - // we also need: - // e) number of steps = (n - erastart) / halving interval - // - // the total supply from era start up to height is: - // a + b + c + (d * e) - - // calculate amount in one step's triangular protrusion over minor triangle's hypotenuse - denominator = nSteps * period; - if ( denominator == 0 ) - denominator = 1; - // difference of one step vs. total - stepDifference = (period * subsidyDifference) / denominator; - - // area == coin holding of one step triangle, protruding from minor triangle's hypotenuse - stepTriangle = (period * stepDifference) >> 1; - - // sign is negative if slope is positive (start is less than end) - if (sign < 0) - { - // use steps minus one for our calculations, and add the potentially partial rectangle - // at the end - cur_money += stepTriangle * (nSteps - 1); - cur_money += stepTriangle * (nSteps - 1) * (nSteps - 1); - - // difference times number of steps is height of rectangle above lowest subsidy - cur_money += modulo * stepDifference * nSteps; - } - else - { - // if negative slope, the minor triangle is the full number of steps, as the highest - // level step is full. lowest subsidy is just the lowest so far - lowestSubsidy = reward - (stepDifference * nSteps); - - // add the step triangles, one per step - cur_money += stepTriangle * nSteps; - - // add the minor triangle - cur_money += stepTriangle * nSteps * nSteps; - } +int32_t komodo_baseid(char *origbase); - // add more for the base rectangle if lowest subsidy is not 0 - cur_money += lowestSubsidy * (curEnd - lastEnd); - } - else - { - for ( int k = lastEnd; k < curEnd; k += period ) - { - cur_money += period * reward; - // if zero, we do straight halving - reward = decay ? (reward * decay) / SATOSHIDEN : reward >> 1; - } - cur_money += modulo * reward; - } - } - } - } - } - if ( KOMODO_BIT63SET(cur_money) != 0 ) - return(KOMODO_MAXNVALUE); - if ( ASSETCHAINS_COMMISSION != 0 ) - { - uint64_t newval = (cur_money + (cur_money/COIN * ASSETCHAINS_COMMISSION)); - if ( KOMODO_BIT63SET(newval) != 0 ) - return(KOMODO_MAXNVALUE); - else if ( newval < cur_money ) // check for underflow - return(KOMODO_MAXNVALUE); - return(newval); - } - //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); - return(cur_money); -} +uint64_t komodo_current_supply(uint32_t nHeight); diff --git a/src/komodo_interest.cpp b/src/komodo_interest.cpp new file mode 100644 index 00000000000..b862272132b --- /dev/null +++ b/src/komodo_interest.cpp @@ -0,0 +1,137 @@ +/****************************************************************************** + * 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 "komodo_interest.h" + +uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + int32_t minutes; uint64_t interest = 0; + if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) + { + if ( minutes > 365 * 24 * 60 ) + minutes = 365 * 24 * 60; + if ( txheight >= 1000000 && minutes > 31 * 24 * 60 ) + minutes = 31 * 24 * 60; + minutes -= ((KOMODO_MAXMEMPOOLTIME/60) - 1); + interest = ((nValue / 10512000) * minutes); + } + return(interest); +} + +uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + uint64_t interest = 0; + if ( txheight < KOMODO_ENDOFERA && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && + interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + return(interest); +} + +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + int32_t minutes,exception; uint64_t interestnew,numerator,denominator,interest = 0; uint32_t activation; + activation = 1491350400; // 1491350400 5th April + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + return(0); + if ( txheight >= KOMODO_ENDOFERA ) + return(0); + if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && + { + if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) + { + if ( minutes > 365 * 24 * 60 ) + minutes = 365 * 24 * 60; + if ( txheight >= 250000 ) + minutes -= 59; + denominator = (((uint64_t)365 * 24 * 60) / minutes); + if ( denominator == 0 ) + denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually! + if ( nValue > 25000LL*COIN ) + { + exception = 0; + if ( txheight <= 155949 ) + { + if ( (txheight == 116607 && nValue == 2502721100000LL) || + (txheight == 126891 && nValue == 2879650000000LL) || + (txheight == 129510 && nValue == 3000000000000LL) || + (txheight == 141549 && nValue == 3500000000000LL) || + (txheight == 154473 && nValue == 3983399350000LL) || + (txheight == 154736 && nValue == 3983406748175LL) || + (txheight == 155013 && nValue == 3983414006565LL) || + (txheight == 155492 && nValue == 3983427592291LL) || + (txheight == 155613 && nValue == 9997409999999797LL) || + (txheight == 157927 && nValue == 9997410667451072LL) || + (txheight == 155613 && nValue == 2590000000000LL) || + (txheight == 155949 && nValue == 4000000000000LL) ) + exception = 1; + if ( exception == 0 || nValue == 4000000000000LL ) + printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); + } + //if ( nValue == 4000000000000LL ) + // printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); + if ( exception == 0 ) + { + numerator = (nValue / 20); // assumes 5%! + if ( txheight < 250000 ) + interest = (numerator / denominator); + else if ( txheight < 1000000 ) + { + interest = (numerator * minutes) / ((uint64_t)365 * 24 * 60); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + if ( interest < interestnew ) + printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + } + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + } + else if ( txheight < 1000000 ) + { + numerator = (nValue * KOMODO_INTEREST); + interest = (numerator / denominator) / COIN; + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + if ( interest < interestnew ) + printf("pathB current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + } + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + } + else + { + /* 250000 algo + numerator = (nValue * KOMODO_INTEREST); + if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) + interest = (numerator / denominator) / COIN; + else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; + */ + numerator = (nValue * KOMODO_INTEREST); + if ( txheight < 250000 || tiptime < activation ) + { + if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) + interest = (numerator / denominator) / COIN; + else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; + } + else if ( txheight < 1000000 ) + { + numerator = (nValue / 20); // assumes 5%! + interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)); + //fprintf(stderr,"interest %llu %.8f <- numerator.%llu minutes.%d\n",(long long)interest,(double)interest/COIN,(long long)numerator,(int32_t)minutes); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + if ( interest < interestnew ) + fprintf(stderr,"pathC current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + } + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + } + if ( 0 && numerator == (nValue * KOMODO_INTEREST) ) + fprintf(stderr,"komodo_interest.%d %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu) prod.%llu\n",txheight,(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator,(long long)(numerator * minutes)); + } + } + return(interest); +} diff --git a/src/komodo_interest.h b/src/komodo_interest.h index b9549d8609e..d8c7ed7859d 100644 --- a/src/komodo_interest.h +++ b/src/komodo_interest.h @@ -23,182 +23,8 @@ extern int64_t MAX_MONEY; extern uint8_t NOTARY_PUBKEY33[]; -#ifdef notanymore -uint64_t komodo_earned_interest(int32_t height,int64_t paidinterest) -{ - static uint64_t *interests; static int32_t maxheight; - uint64_t total; int32_t ind,incr = 10000; - // need to make interests persistent before 2030, or just hardfork interest/mining rewards disable after MAX_MONEY is exceeded - return(0); - if ( height >= maxheight ) - { - if ( interests == 0 ) - { - maxheight = height + incr; - interests = (uint64_t *)calloc(maxheight,sizeof(*interests) * 2); - } - else - { - interests = (uint64_t *)realloc(interests,(maxheight + incr) * sizeof(*interests) * 2); - memset(&interests[maxheight << 1],0,incr * sizeof(*interests) * 2); - maxheight += incr; - } - } - ind = (height << 1); - if ( paidinterest < 0 ) // request - { - return(interests[ind]); - } - else - { - if ( interests[ind + 1] != paidinterest ) // need to handle skips like at 80000 - { - //fprintf(stderr,"interests.%d %.8f %.8f vs paidinterest %.8f\n",height,dstr(interests[ind]),dstr(interests[ind+1]),dstr(paidinterest)); - interests[ind + 1] = paidinterest; - if ( height <= 1 ) - interests[ind] = 0; - else interests[ind] = interests[ind - 2] + interests[ind - 1]; - total = interests[ind] + paidinterest; - //fprintf(stderr,"reset interests[height.%d to maxheight.%d] <- %.8f\n",height,maxheight,dstr(total)); - for (++height; height= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) - { - if ( minutes > 365 * 24 * 60 ) - minutes = 365 * 24 * 60; - if ( txheight >= 1000000 && minutes > 31 * 24 * 60 ) - minutes = 31 * 24 * 60; - minutes -= ((KOMODO_MAXMEMPOOLTIME/60) - 1); - interest = ((nValue / 10512000) * minutes); - } - return(interest); -} - -uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) -{ - uint64_t interest = 0; - if ( txheight < KOMODO_ENDOFERA && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && - interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - return(interest); -} - -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) -{ - int32_t minutes,exception; uint64_t interestnew,numerator,denominator,interest = 0; uint32_t activation; - activation = 1491350400; // 1491350400 5th April - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); - if ( txheight >= KOMODO_ENDOFERA ) - return(0); - if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && - { - if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) - { - if ( minutes > 365 * 24 * 60 ) - minutes = 365 * 24 * 60; - if ( txheight >= 250000 ) - minutes -= 59; - denominator = (((uint64_t)365 * 24 * 60) / minutes); - if ( denominator == 0 ) - denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually! - if ( nValue > 25000LL*COIN ) - { - exception = 0; - if ( txheight <= 155949 ) - { - if ( (txheight == 116607 && nValue == 2502721100000LL) || - (txheight == 126891 && nValue == 2879650000000LL) || - (txheight == 129510 && nValue == 3000000000000LL) || - (txheight == 141549 && nValue == 3500000000000LL) || - (txheight == 154473 && nValue == 3983399350000LL) || - (txheight == 154736 && nValue == 3983406748175LL) || - (txheight == 155013 && nValue == 3983414006565LL) || - (txheight == 155492 && nValue == 3983427592291LL) || - (txheight == 155613 && nValue == 9997409999999797LL) || - (txheight == 157927 && nValue == 9997410667451072LL) || - (txheight == 155613 && nValue == 2590000000000LL) || - (txheight == 155949 && nValue == 4000000000000LL) ) - exception = 1; - if ( exception == 0 || nValue == 4000000000000LL ) - printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); - } - //if ( nValue == 4000000000000LL ) - // printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); - if ( exception == 0 ) - { - numerator = (nValue / 20); // assumes 5%! - if ( txheight < 250000 ) - interest = (numerator / denominator); - else if ( txheight < 1000000 ) - { - interest = (numerator * minutes) / ((uint64_t)365 * 24 * 60); - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - if ( interest < interestnew ) - printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); - } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - } - else if ( txheight < 1000000 ) - { - numerator = (nValue * KOMODO_INTEREST); - interest = (numerator / denominator) / COIN; - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - if ( interest < interestnew ) - printf("pathB current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); - } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - } - else - { - /* 250000 algo - numerator = (nValue * KOMODO_INTEREST); - if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) - interest = (numerator / denominator) / COIN; - else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; - */ - numerator = (nValue * KOMODO_INTEREST); - if ( txheight < 250000 || tiptime < activation ) - { - if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) - interest = (numerator / denominator) / COIN; - else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; - } - else if ( txheight < 1000000 ) - { - numerator = (nValue / 20); // assumes 5%! - interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)); - //fprintf(stderr,"interest %llu %.8f <- numerator.%llu minutes.%d\n",(long long)interest,(double)interest/COIN,(long long)numerator,(int32_t)minutes); - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - if ( interest < interestnew ) - fprintf(stderr,"pathC current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); - } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - } - if ( 0 && numerator == (nValue * KOMODO_INTEREST) ) - fprintf(stderr,"komodo_interest.%d %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu) prod.%llu\n",txheight,(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator,(long long)(numerator * minutes)); - } - } - return(interest); -} +uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); diff --git a/src/komodo_jumblr.cpp b/src/komodo_jumblr.cpp new file mode 100644 index 00000000000..f82d3152757 --- /dev/null +++ b/src/komodo_jumblr.cpp @@ -0,0 +1,764 @@ +/****************************************************************************** + * 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 "komodo_jumblr.h" +#include "komodo_extern_globals.h" +#include "komodo_bitcoind.h" // komodo_issuemethod +#include "komodo_utils.h" // clonestr + +char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; +int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode +jumblr_item *Jumblrs; + +char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) +{ + cJSON *retjson,*resjson = 0; char *retstr; + if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,(char *)"result") != 0 ) + resjson = jduplicate(jobj(retjson,(char *)"result")); + else if ( jobj(retjson,(char *)"error") != 0 ) + resjson = jduplicate(jobj(retjson,(char *)"error")); + else + { + resjson = cJSON_CreateObject(); + jaddstr(resjson,(char *)"error",(char *)"cant parse return"); + } + free_json(retjson); + } + free(retstr); + } + if ( resjson != 0 ) + return(jprint(resjson,1)); + else return(clonestr((char *)"{\"error\":\"unknown error\"}")); +} + +char *jumblr_importaddress(char *address) +{ + char params[1024]; + sprintf(params,"[\"%s\", \"%s\", false]",address,address); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_validateaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\"]",addr); + printf("validateaddress.%s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); +} + +int32_t Jumblr_secretaddrfind(char *searchaddr) +{ + int32_t i; + for (i=0; i 0 ) + { + OS_randombytes((uint8_t *)&r,sizeof(r)); + r %= Jumblr_numsecretaddrs; + safecopy(secretaddr,Jumblr_secretaddrs[r],64); + } + return(r); +} + +int32_t jumblr_addresstype(char *addr) +{ + if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) + { + addr[strlen(addr)-1] = 0; + addr++; + } + if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) + return('z'); + else if ( strlen(addr) < 40 ) + return('t'); + printf("strange.(%s)\n",addr); + return(-1); +} + +struct jumblr_item *jumblr_opidfind(char *opid) +{ + struct jumblr_item *ptr; + HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); + return(ptr); +} + +struct jumblr_item *jumblr_opidadd(char *opid) +{ + struct jumblr_item *ptr = 0; + if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) + { + ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); + safecopy(ptr->opid,opid,sizeof(ptr->opid)); + HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); + if ( ptr != jumblr_opidfind(opid) ) + printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); + } + return(ptr); +} + +char *jumblr_zgetnewaddress() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistoperationids() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetoperationresult(char *opid) +{ + char params[1024]; + sprintf(params,"[[\"%s\"]]",opid); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetoperationstatus(char *opid) +{ + char params[1024]; + sprintf(params,"[[\"%s\"]]",opid); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) +{ + char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; + if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) + return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + printf("t -> z: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) +{ + char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; + if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) + return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); + //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); + printf("z -> z: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) +{ + char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; + if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) + return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + printf("z -> t: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistaddresses() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistreceivedbyaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_getreceivedbyaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_importprivkey(char *wifstr) +{ + char params[1024]; + sprintf(params,"[\"%s\", \"\", false]",wifstr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetbalance(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); +} + +char *jumblr_listunspent(char *coinaddr) +{ + char params[1024]; + sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); +} + +char *jumblr_gettransaction(char *txidstr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",txidstr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); +} + +int32_t jumblr_numvins(bits256 txid) +{ + char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; + bits256_str(txidstr,txid); + if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) + { + numvins = n; + //printf("numvins.%d\n",n); + } //else printf("no vin.(%s)\n",retstr); + free_json(retjson); + } + free(retstr); + } + return(numvins); +} + +int64_t jumblr_receivedby(char *addr) +{ + char *retstr; int64_t total = 0; + if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) + { + total = atof(retstr) * SATOSHIDEN; + free(retstr); + } + return(total); +} + +int64_t jumblr_balance(char *addr) +{ + char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; + /*if ( jumblr_addresstype(addr) == 't' ) + { + if ( (retstr= jumblr_listunspent(addr)) != 0 ) + { + //printf("jumblr.[%s].(%s)\n","KMD",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) + for (i=0; i SMALLVAL ) + balance = val * SATOSHIDEN; + free(retstr); + } + return(balance); +} + +int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) +{ + cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; + /*"params" : { + "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", + "amounts" : [ + { + "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", + "amount" : 3.00000000 + } + ], + "minconf" : 1, + "fee" : 0.00010000 + }*/ + if ( (params= jobj(item,(char *)"params")) != 0 ) + { + //printf("params.(%s)\n",jprint(params,0)); + if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) + { + safecopy(ptr->src,from,sizeof(ptr->src)); + } + if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) + { + for (i=0; i 0 ) + { + if ( strcmp(addr,JUMBLR_ADDR) == 0 ) + ptr->fee = amount; + else + { + ptr->amount = amount; + safecopy(ptr->dest,addr,sizeof(ptr->dest)); + } + } + } + } + ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; + } + return(1); +} + +void jumblr_opidupdate(struct jumblr_item *ptr) +{ + char *retstr,*status; cJSON *retjson,*item; + if ( ptr->status == 0 ) + { + if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) + { + item = jitem(retjson,0); + //printf("%s\n",jprint(item,0)); + if ( (status= jstr(item,(char *)"status")) != 0 ) + { + if ( strcmp(status,(char *)"success") == 0 ) + { + ptr->status = jumblr_itemset(ptr,item,status); + if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) + { + printf("a non-jumblr t->z pruned\n"); + free(jumblr_zgetoperationresult(ptr->opid)); + ptr->status = -1; + } + + } + else if ( strcmp(status,(char *)"failed") == 0 ) + { + printf("jumblr_opidupdate %s failed\n",ptr->opid); + free(jumblr_zgetoperationresult(ptr->opid)); + ptr->status = -1; + } + } + } + free_json(retjson); + } + free(retstr); + } + } +} + +void jumblr_prune(struct jumblr_item *ptr) +{ + struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; + if ( is_hexstr(ptr->opid,0) == 64 ) + return; + printf("jumblr_prune %s\n",ptr->opid); + strcpy(oldsrc,ptr->src); + free(jumblr_zgetoperationresult(ptr->opid)); + while ( flag != 0 ) + { + flag = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + if ( strcmp(oldsrc,ptr->dest) == 0 ) + { + if ( is_hexstr(ptr->opid,0) != 64 ) + { + printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); + free(jumblr_zgetoperationresult(ptr->opid)); + strcpy(oldsrc,ptr->src); + flag = 1; + break; + } + } + } + } +} + + +bits256 jbits256(cJSON *json,char *field); + + +void jumblr_zaddrinit(char *zaddr) +{ + struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; + if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) + { + if ( (total= atof(totalstr)) > SMALLVAL ) + { + if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + t_z = z_z = 0; + if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) + { + item = jitem(array,0); + if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) + { + txid = jbits256(item,(char *)"txid"); + bits256_str(txidstr,txid); + if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) + { + ptr->amount = (total * SATOSHIDEN); + ptr->status = 1; + strcpy(ptr->dest,zaddr); + if ( jumblr_addresstype(ptr->dest) != 'z' ) + printf("error setting dest type to Z: %s\n",jprint(item,0)); + if ( jumblr_numvins(txid) == 0 ) + { + z_z = 1; + strcpy(ptr->src,zaddr); + ptr->src[3] = '0'; + ptr->src[4] = '0'; + ptr->src[5] = '0'; + if ( jumblr_addresstype(ptr->src) != 'z' ) + printf("error setting address type to Z: %s\n",jprint(item,0)); + } + else + { + t_z = 1; + strcpy(ptr->src,"taddr"); + if ( jumblr_addresstype(ptr->src) != 't' ) + printf("error setting address type to T: %s\n",jprint(item,0)); + } + printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend + } + } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); + } + free_json(array); + } + free(retstr); + } + } + free(totalstr); + } +} + +void jumblr_opidsupdate() +{ + char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; + if ( (retstr= jumblr_zlistoperationids()) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) + { + //printf("%s -> n%d\n",retstr,n); + for (i=0; istatus == 0 ) + jumblr_opidupdate(ptr); + //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); + if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) + jumblr_prune(ptr); + } + } + } + free_json(array); + } + free(retstr); + } +} + +uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) +{ + int32_t i,n; uint64_t incrs[1000],remains = total; + height /= JUMBLR_SYNCHRONIZED_BLOCKS; + if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) + { + if ( total >= biggest ) + return(biggest); + else if ( total >= medium ) + return(medium); + else if ( total >= smallest ) + return(smallest); + else return(0); + } + else + { + n = 0; + while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) + { + if ( remains >= biggest ) + incrs[n] = biggest; + else if ( remains >= medium ) + incrs[n] = medium; + else if ( remains >= smallest ) + incrs[n] = smallest; + else break; + remains -= incrs[n]; + n++; + } + if ( n > 0 ) + { + r %= n; + for (i=0; i %.8f\n",n,r,dstr(incrs[r])); + return(incrs[r]); + } + } + return(0); +} + +void jumblr_iteration() +{ + static int32_t lastheight; static uint32_t lasttime; + char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; + acpublic = ASSETCHAINS_PUBLIC; + if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) + acpublic = 1; + if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) + return; + if ( lasttime == 0 ) + { + if ( (retstr= jumblr_zlistaddresses()) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) + { + for (i=0; iGetHeight(); + if ( time(NULL) < lasttime+40 ) + return; + lasttime = (uint32_t)time(NULL); + if ( lastheight == height ) + return; + lastheight = height; + if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) + return; + fee = JUMBLR_INCR * JUMBLR_FEE; + smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); + medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); + biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); + OS_randombytes((uint8_t *)&r,sizeof(r)); + s = (r % 3); + //printf("jumblr_iteration r.%u s.%u\n",r,s); + switch ( s ) + { + case 0: // t -> z + default: + if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) + { + if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) + { + if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) + { + zaddr[strlen(zaddr)-1] = 0; + addr = zaddr+1; + } else addr = zaddr; + amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); + /* + amount = 0; + if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); + else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); + else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ + if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) + { + printf("sendt_to_z.(%s)\n",retstr); + free(retstr), retstr = 0; + } + free(zaddr); + } else printf("no zaddr from jumblr_zgetnewaddress\n"); + } + else if ( Jumblr_deposit[0] != 0 ) + printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); + break; + case 1: // z -> z + jumblr_opidsupdate(); + chosen_one = -1; + for (iter=counter=0; iter<2; iter++) + { + counter = n = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) + { + if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + { + if ( iter == 1 && counter == chosen_one ) + { + if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) + { + if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) + { + zaddr[strlen(zaddr)-1] = 0; + addr = zaddr+1; + } else addr = zaddr; + if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) + { + printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); + free(retstr), retstr = 0; + } + ptr->spent = (uint32_t)time(NULL); + free(zaddr); + break; + } + } + counter++; + } + } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); + } + } + break; + case 2: // z -> t + if ( Jumblr_numsecretaddrs > 0 ) + { + jumblr_opidsupdate(); + chosen_one = -1; + for (iter=0; iter<2; iter++) + { + counter = n = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); + if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) + { + if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + { + if ( iter == 1 && counter == chosen_one ) + { + Jumblr_secretaddr(secretaddr); + if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) + { + printf("%s send z_to_t.(%s)\n",secretaddr,retstr); + free(retstr), retstr = 0; + } else printf("null return from jumblr_sendz_to_t\n"); + ptr->spent = (uint32_t)time(NULL); + break; + } + counter++; + } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); + } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); + } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); + } + } + break; + } +} diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h index fca7395e5d3..0ddd99b3403 100644 --- a/src/komodo_jumblr.h +++ b/src/komodo_jumblr.h @@ -12,22 +12,14 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -/* - z_exportkey "zaddr" - z_exportwallet "filename" - z_getoperationstatus (["operationid", ... ]) - z_gettotalbalance ( minconf ) - z_importkey "zkey" ( rescan ) - z_importwallet "filename" - z_listaddresses - z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":""},...] ( minconf ) ( fee ) - */ +#pragma once +#include "uthash.h" // UT_hash_handle +#include "komodo_cJSON.h" +#include "komodo_defs.h" #ifdef _WIN32 #include #endif -#include "komodo_defs.h" #define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" #define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" @@ -49,747 +41,72 @@ struct jumblr_item int64_t amount,fee,txfee; // fee and txfee not really used (yet) uint32_t spent,pad; char opid[66],src[128],dest[128],status; -} *Jumblrs; +}; -char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; -int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode +char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port); -char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - cJSON *retjson,*resjson = 0; char *retstr; - if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"result") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"result")); - else if ( jobj(retjson,(char *)"error") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"error")); - else - { - resjson = cJSON_CreateObject(); - jaddstr(resjson,(char *)"error",(char *)"cant parse return"); - } - free_json(retjson); - } - free(retstr); - } - if ( resjson != 0 ) - return(jprint(resjson,1)); - else return(clonestr((char *)"{\"error\":\"unknown error\"}")); -} - -char *jumblr_importaddress(char *address) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"%s\", false]",address,address); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_importaddress(char *address); -char *jumblr_validateaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\"]",addr); - printf("validateaddress.%s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_validateaddress(char *addr); -int32_t Jumblr_secretaddrfind(char *searchaddr) -{ - int32_t i; - for (i=0; i 0 ) - { - OS_randombytes((uint8_t *)&r,sizeof(r)); - r %= Jumblr_numsecretaddrs; - safecopy(secretaddr,Jumblr_secretaddrs[r],64); - } - return(r); -} - -int32_t jumblr_addresstype(char *addr) -{ - if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) - { - addr[strlen(addr)-1] = 0; - addr++; - } - if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) - return('z'); - else if ( strlen(addr) < 40 ) - return('t'); - printf("strange.(%s)\n",addr); - return(-1); -} - -struct jumblr_item *jumblr_opidfind(char *opid) -{ - struct jumblr_item *ptr; - HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); - return(ptr); -} +int32_t Jumblr_depositaddradd(char *depositaddr); // external -struct jumblr_item *jumblr_opidadd(char *opid) -{ - struct jumblr_item *ptr = 0; - if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) - { - ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); - safecopy(ptr->opid,opid,sizeof(ptr->opid)); - HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); - if ( ptr != jumblr_opidfind(opid) ) - printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); - } - return(ptr); -} - -char *jumblr_zgetnewaddress() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); -} +int32_t Jumblr_secretaddr(char *secretaddr); -char *jumblr_zlistoperationids() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); -} +int32_t jumblr_addresstype(char *addr); -char *jumblr_zgetoperationresult(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); -} +struct jumblr_item *jumblr_opidfind(char *opid); -char *jumblr_zgetoperationstatus(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); -} +struct jumblr_item *jumblr_opidadd(char *opid); -char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) -{ - char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("t -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) -{ - char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; - if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); - //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); - printf("z -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) -{ - char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("z -> t: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistaddresses() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); -} +char *jumblr_zgetnewaddress(); -char *jumblr_zlistreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_zlistoperationids(); -char *jumblr_getreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_zgetoperationresult(char *opid); -char *jumblr_importprivkey(char *wifstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"\", false]",wifstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); -} +char *jumblr_zgetoperationstatus(char *opid); -char *jumblr_zgetbalance(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); -} +char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount); -char *jumblr_listunspent(char *coinaddr) -{ - char params[1024]; - sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); -} +char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount); -char *jumblr_gettransaction(char *txidstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",txidstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); -} +char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount); -int32_t jumblr_numvins(bits256 txid) -{ - char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; - bits256_str(txidstr,txid); - if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) - { - numvins = n; - //printf("numvins.%d\n",n); - } //else printf("no vin.(%s)\n",retstr); - free_json(retjson); - } - free(retstr); - } - return(numvins); -} - -int64_t jumblr_receivedby(char *addr) -{ - char *retstr; int64_t total = 0; - if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) - { - total = atof(retstr) * SATOSHIDEN; - free(retstr); - } - return(total); -} - -int64_t jumblr_balance(char *addr) -{ - char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; - /*if ( jumblr_addresstype(addr) == 't' ) - { - if ( (retstr= jumblr_listunspent(addr)) != 0 ) - { - //printf("jumblr.[%s].(%s)\n","KMD",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) - for (i=0; i SMALLVAL ) - balance = val * SATOSHIDEN; - free(retstr); - } - return(balance); -} - -int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) -{ - cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; - /*"params" : { - "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", - "amounts" : [ - { - "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", - "amount" : 3.00000000 - } - ], - "minconf" : 1, - "fee" : 0.00010000 - }*/ - if ( (params= jobj(item,(char *)"params")) != 0 ) - { - //printf("params.(%s)\n",jprint(params,0)); - if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) - { - safecopy(ptr->src,from,sizeof(ptr->src)); - } - if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) - { - for (i=0; i 0 ) - { - if ( strcmp(addr,JUMBLR_ADDR) == 0 ) - ptr->fee = amount; - else - { - ptr->amount = amount; - safecopy(ptr->dest,addr,sizeof(ptr->dest)); - } - } - } - } - ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; - } - return(1); -} - -void jumblr_opidupdate(struct jumblr_item *ptr) -{ - char *retstr,*status; cJSON *retjson,*item; - if ( ptr->status == 0 ) - { - if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) - { - item = jitem(retjson,0); - //printf("%s\n",jprint(item,0)); - if ( (status= jstr(item,(char *)"status")) != 0 ) - { - if ( strcmp(status,(char *)"success") == 0 ) - { - ptr->status = jumblr_itemset(ptr,item,status); - if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) - { - printf("a non-jumblr t->z pruned\n"); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - - } - else if ( strcmp(status,(char *)"failed") == 0 ) - { - printf("jumblr_opidupdate %s failed\n",ptr->opid); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - } - } - free_json(retjson); - } - free(retstr); - } - } -} - -void jumblr_prune(struct jumblr_item *ptr) -{ - struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; - if ( is_hexstr(ptr->opid,0) == 64 ) - return; - printf("jumblr_prune %s\n",ptr->opid); - strcpy(oldsrc,ptr->src); - free(jumblr_zgetoperationresult(ptr->opid)); - while ( flag != 0 ) - { - flag = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( strcmp(oldsrc,ptr->dest) == 0 ) - { - if ( is_hexstr(ptr->opid,0) != 64 ) - { - printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); - free(jumblr_zgetoperationresult(ptr->opid)); - strcpy(oldsrc,ptr->src); - flag = 1; - break; - } - } - } - } -} - - -bits256 jbits256(cJSON *json,char *field); - - -void jumblr_zaddrinit(char *zaddr) -{ - struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; - if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) - { - if ( (total= atof(totalstr)) > SMALLVAL ) - { - if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - t_z = z_z = 0; - if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) - { - item = jitem(array,0); - if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) - { - txid = jbits256(item,(char *)"txid"); - bits256_str(txidstr,txid); - if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) - { - ptr->amount = (total * SATOSHIDEN); - ptr->status = 1; - strcpy(ptr->dest,zaddr); - if ( jumblr_addresstype(ptr->dest) != 'z' ) - printf("error setting dest type to Z: %s\n",jprint(item,0)); - if ( jumblr_numvins(txid) == 0 ) - { - z_z = 1; - strcpy(ptr->src,zaddr); - ptr->src[3] = '0'; - ptr->src[4] = '0'; - ptr->src[5] = '0'; - if ( jumblr_addresstype(ptr->src) != 'z' ) - printf("error setting address type to Z: %s\n",jprint(item,0)); - } - else - { - t_z = 1; - strcpy(ptr->src,"taddr"); - if ( jumblr_addresstype(ptr->src) != 't' ) - printf("error setting address type to T: %s\n",jprint(item,0)); - } - printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend - } - } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); - } - free_json(array); - } - free(retstr); - } - } - free(totalstr); - } -} - -void jumblr_opidsupdate() -{ - char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; - if ( (retstr= jumblr_zlistoperationids()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - //printf("%s -> n%d\n",retstr,n); - for (i=0; istatus == 0 ) - jumblr_opidupdate(ptr); - //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); - if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) - jumblr_prune(ptr); - } - } - } - free_json(array); - } - free(retstr); - } -} - -uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) -{ - int32_t i,n; uint64_t incrs[1000],remains = total; - height /= JUMBLR_SYNCHRONIZED_BLOCKS; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) - { - if ( total >= biggest ) - return(biggest); - else if ( total >= medium ) - return(medium); - else if ( total >= smallest ) - return(smallest); - else return(0); - } - else - { - n = 0; - while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) - { - if ( remains >= biggest ) - incrs[n] = biggest; - else if ( remains >= medium ) - incrs[n] = medium; - else if ( remains >= smallest ) - incrs[n] = smallest; - else break; - remains -= incrs[n]; - n++; - } - if ( n > 0 ) - { - r %= n; - for (i=0; i %.8f\n",n,r,dstr(incrs[r])); - return(incrs[r]); - } - } - return(0); -} - -void jumblr_iteration() -{ - static int32_t lastheight; static uint32_t lasttime; - char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; - acpublic = ASSETCHAINS_PUBLIC; - if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) - return; - if ( lasttime == 0 ) - { - if ( (retstr= jumblr_zlistaddresses()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - for (i=0; iGetHeight(); - if ( time(NULL) < lasttime+40 ) - return; - lasttime = (uint32_t)time(NULL); - if ( lastheight == height ) - return; - lastheight = height; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) - return; - fee = JUMBLR_INCR * JUMBLR_FEE; - smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); - medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); - OS_randombytes((uint8_t *)&r,sizeof(r)); - s = (r % 3); - //printf("jumblr_iteration r.%u s.%u\n",r,s); - switch ( s ) - { - case 0: // t -> z - default: - if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); - /* - amount = 0; - if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); - else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ - if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) - { - printf("sendt_to_z.(%s)\n",retstr); - free(retstr), retstr = 0; - } - free(zaddr); - } else printf("no zaddr from jumblr_zgetnewaddress\n"); - } - else if ( Jumblr_deposit[0] != 0 ) - printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); - break; - case 1: // z -> z - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=counter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) - { - printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); - free(retstr), retstr = 0; - } - ptr->spent = (uint32_t)time(NULL); - free(zaddr); - break; - } - } - counter++; - } - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } - } - break; - case 2: // z -> t - if ( Jumblr_numsecretaddrs > 0 ) - { - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - Jumblr_secretaddr(secretaddr); - if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) - { - printf("%s send z_to_t.(%s)\n",secretaddr,retstr); - free(retstr), retstr = 0; - } else printf("null return from jumblr_sendz_to_t\n"); - ptr->spent = (uint32_t)time(NULL); - break; - } - counter++; - } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); - } - } - break; - } -} +char *jumblr_zlistaddresses(); + +char *jumblr_zlistreceivedbyaddress(char *addr); + +char *jumblr_getreceivedbyaddress(char *addr); + +char *jumblr_importprivkey(char *wifstr); + +char *jumblr_zgetbalance(char *addr); + +char *jumblr_listunspent(char *coinaddr); + +char *jumblr_gettransaction(char *txidstr); + +int32_t jumblr_numvins(bits256 txid); + +int64_t jumblr_receivedby(char *addr); + +int64_t jumblr_balance(char *addr); + +int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status); + +void jumblr_opidupdate(struct jumblr_item *ptr); + +void jumblr_prune(struct jumblr_item *ptr); + +void jumblr_zaddrinit(char *zaddr); + +void jumblr_opidsupdate(); + +uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest); + +void jumblr_iteration(); diff --git a/src/komodo_kv.cpp b/src/komodo_kv.cpp new file mode 100644 index 00000000000..0e51ef969d9 --- /dev/null +++ b/src/komodo_kv.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * 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 "komodo_kv.h" +#include "komodo_extern_globals.h" +#include "komodo_utils.h" // portable_mutex_lock +#include "komodo_curve25519.h" // komodo_kvsigverify + +int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize) +{ + if ( refvalue == 0 && value == 0 ) + return(0); + else if ( refvalue == 0 || value == 0 ) + return(-1); + else if ( refvaluesize != valuesize ) + return(-1); + else return(memcmp(refvalue,value,valuesize)); +} + +int32_t komodo_kvnumdays(uint32_t flags) +{ + int32_t numdays; + if ( (numdays= ((flags>>2)&0x3ff)+1) > 365 ) + numdays = 365; + return(numdays); +} + +int32_t komodo_kvduration(uint32_t flags) +{ + return(komodo_kvnumdays(flags) * KOMODO_KVDURATION); +} + +uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen) +{ + int32_t numdays,k; uint64_t fee; + if ( (k= keylen) > 32 ) + k = 32; + numdays = komodo_kvnumdays(flags); + if ( (fee= (numdays*(opretlen * opretlen / k))) < 100000 ) + fee = 100000; + return(fee); +} + +int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen) +{ + struct komodo_kv *ptr; int32_t duration,retval = -1; + *heightp = -1; + *flagsp = 0; + memset(pubkeyp,0,sizeof(*pubkeyp)); + portable_mutex_lock(&KOMODO_KV_mutex); + HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); + if ( ptr != 0 ) + { + duration = komodo_kvduration(ptr->flags); + //fprintf(stderr,"duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); + if ( current_height > (ptr->height + duration) ) + { + HASH_DELETE(hh,KOMODO_KV,ptr); + if ( ptr->value != 0 ) + free(ptr->value); + if ( ptr->key != 0 ) + free(ptr->key); + free(ptr); + } + else + { + *heightp = ptr->height; + *flagsp = ptr->flags; + int32_t i; for (i=0; i<32; i++) + { + //printf("%02x",((uint8_t *)&ptr->pubkey)[31-i]); + ((uint8_t *)pubkeyp)[i] = ((uint8_t *)&ptr->pubkey)[31-i]; + } + //printf(" ptr->pubkey\n"); + memcpy(pubkeyp,&ptr->pubkey,sizeof(*pubkeyp)); + if ( (retval= ptr->valuesize) > 0 ) + memcpy(value,ptr->value,retval); + } + } //else fprintf(stderr,"couldnt find (%s)\n",(char *)key); + portable_mutex_unlock(&KOMODO_KV_mutex); + if ( retval < 0 ) + { + // search rawmempool + } + return(retval); +} + +void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) +{ + static uint256 zeroes; + uint32_t flags; uint256 pubkey,refpubkey,sig; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[IGUANA_MAXSCRIPTSIZE*8]; struct komodo_kv *ptr; char *transferpubstr,*tstr; uint64_t fee; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) // disable KV for KMD + return; + iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); + iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); + iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); + iguana_rwnum(0,&opretbuf[9],sizeof(flags),&flags); + key = &opretbuf[13]; + if ( keylen+13 > opretlen ) + { + static uint32_t counter; + if ( ++counter < 1 ) + fprintf(stderr,"komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); + return; + } + valueptr = &key[keylen]; + fee = komodo_kvfee(flags,opretlen,keylen); + //fprintf(stderr,"fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); + if ( value >= fee ) + { + coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(keylen)+sizeof(valuesize)+keylen+valuesize+1); + if ( opretlen == coresize || opretlen == coresize+sizeof(uint256) || opretlen == coresize+2*sizeof(uint256) ) + { + memset(&pubkey,0,sizeof(pubkey)); + memset(&sig,0,sizeof(sig)); + if ( (haspubkey= (opretlen >= coresize+sizeof(uint256))) != 0 ) + { + for (i=0; i<32; i++) + ((uint8_t *)&pubkey)[i] = opretbuf[coresize+i]; + } + if ( (hassig= (opretlen == coresize+sizeof(uint256)*2)) != 0 ) + { + for (i=0; i<32; i++) + ((uint8_t *)&sig)[i] = opretbuf[coresize+sizeof(uint256)+i]; + } + memcpy(keyvalue,key,keylen); + if ( (refvaluesize= komodo_kvsearch((uint256 *)&refpubkey,height,&flags,&kvheight,&keyvalue[keylen],key,keylen)) >= 0 ) + { + if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) + { + if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 ) + { + //fprintf(stderr,"komodo_kvsigverify error [%d]\n",coresize-13); + return; + } + } + } + portable_mutex_lock(&KOMODO_KV_mutex); + HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); + if ( ptr != 0 ) + { + //fprintf(stderr,"(%s) already there\n",(char *)key); + //if ( (ptr->flags & KOMODO_KVPROTECTED) != 0 ) + { + tstr = (char *)"transfer:"; + transferpubstr = (char *)&valueptr[strlen(tstr)]; + if ( strncmp(tstr,(char *)valueptr,strlen(tstr)) == 0 && is_hexstr(transferpubstr,0) == 64 ) + { + printf("transfer.(%s) to [%s]? ishex.%d\n",key,transferpubstr,is_hexstr(transferpubstr,0)); + for (i=0; i<32; i++) + ((uint8_t *)&pubkey)[31-i] = _decode_hex(&transferpubstr[i*2]); + } + } + } + else if ( ptr == 0 ) + { + ptr = (struct komodo_kv *)calloc(1,sizeof(*ptr)); + ptr->key = (uint8_t *)calloc(1,keylen); + ptr->keylen = keylen; + memcpy(ptr->key,key,keylen); + newflag = 1; + HASH_ADD_KEYPTR(hh,KOMODO_KV,ptr->key,ptr->keylen,ptr); + //fprintf(stderr,"KV add.(%s) (%s)\n",ptr->key,valueptr); + } + if ( newflag != 0 || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) + { + if ( ptr->value != 0 ) + free(ptr->value), ptr->value = 0; + if ( (ptr->valuesize= valuesize) != 0 ) + { + ptr->value = (uint8_t *)calloc(1,valuesize); + memcpy(ptr->value,valueptr,valuesize); + } + } else fprintf(stderr,"newflag.%d zero or protected %d\n",newflag,(ptr->flags & KOMODO_KVPROTECTED)); + /*for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&ptr->pubkey)[i]); + printf(" <- "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&pubkey)[i]); + printf(" new pubkey\n");*/ + memcpy(&ptr->pubkey,&pubkey,sizeof(ptr->pubkey)); + ptr->height = height; + ptr->flags = flags; // jl777 used to or in KVPROTECTED + portable_mutex_unlock(&KOMODO_KV_mutex); + } else fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); + } else fprintf(stderr,"not enough fee\n"); +} diff --git a/src/komodo_kv.h b/src/komodo_kv.h index a879340ffea..86c6904392a 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -12,190 +12,19 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef H_KOMODOKV_H -#define H_KOMODOKV_H +#pragma once #include "komodo_defs.h" +#include "hex.h" -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize) -{ - if ( refvalue == 0 && value == 0 ) - return(0); - else if ( refvalue == 0 || value == 0 ) - return(-1); - else if ( refvaluesize != valuesize ) - return(-1); - else return(memcmp(refvalue,value,valuesize)); -} - -int32_t komodo_kvnumdays(uint32_t flags) -{ - int32_t numdays; - if ( (numdays= ((flags>>2)&0x3ff)+1) > 365 ) - numdays = 365; - return(numdays); -} +int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); -int32_t komodo_kvduration(uint32_t flags) -{ - return(komodo_kvnumdays(flags) * KOMODO_KVDURATION); -} +int32_t komodo_kvnumdays(uint32_t flags); -uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen) -{ - int32_t numdays,k; uint64_t fee; - if ( (k= keylen) > 32 ) - k = 32; - numdays = komodo_kvnumdays(flags); - if ( (fee= (numdays*(opretlen * opretlen / k))) < 100000 ) - fee = 100000; - return(fee); -} +int32_t komodo_kvduration(uint32_t flags); -int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen) -{ - struct komodo_kv *ptr; int32_t duration,retval = -1; - *heightp = -1; - *flagsp = 0; - memset(pubkeyp,0,sizeof(*pubkeyp)); - portable_mutex_lock(&KOMODO_KV_mutex); - HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); - if ( ptr != 0 ) - { - duration = komodo_kvduration(ptr->flags); - //fprintf(stderr,"duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); - if ( current_height > (ptr->height + duration) ) - { - HASH_DELETE(hh,KOMODO_KV,ptr); - if ( ptr->value != 0 ) - free(ptr->value); - if ( ptr->key != 0 ) - free(ptr->key); - free(ptr); - } - else - { - *heightp = ptr->height; - *flagsp = ptr->flags; - int32_t i; for (i=0; i<32; i++) - { - //printf("%02x",((uint8_t *)&ptr->pubkey)[31-i]); - ((uint8_t *)pubkeyp)[i] = ((uint8_t *)&ptr->pubkey)[31-i]; - } - //printf(" ptr->pubkey\n"); - memcpy(pubkeyp,&ptr->pubkey,sizeof(*pubkeyp)); - if ( (retval= ptr->valuesize) > 0 ) - memcpy(value,ptr->value,retval); - } - } //else fprintf(stderr,"couldnt find (%s)\n",(char *)key); - portable_mutex_unlock(&KOMODO_KV_mutex); - if ( retval < 0 ) - { - // search rawmempool - } - return(retval); -} +uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); -void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) -{ - static uint256 zeroes; - uint32_t flags; uint256 pubkey,refpubkey,sig; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[IGUANA_MAXSCRIPTSIZE*8]; struct komodo_kv *ptr; char *transferpubstr,*tstr; uint64_t fee; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) // disable KV for KMD - return; - iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); - iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); - iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); - iguana_rwnum(0,&opretbuf[9],sizeof(flags),&flags); - key = &opretbuf[13]; - if ( keylen+13 > opretlen ) - { - static uint32_t counter; - if ( ++counter < 1 ) - fprintf(stderr,"komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); - return; - } - valueptr = &key[keylen]; - fee = komodo_kvfee(flags,opretlen,keylen); - //fprintf(stderr,"fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); - if ( value >= fee ) - { - coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(keylen)+sizeof(valuesize)+keylen+valuesize+1); - if ( opretlen == coresize || opretlen == coresize+sizeof(uint256) || opretlen == coresize+2*sizeof(uint256) ) - { - memset(&pubkey,0,sizeof(pubkey)); - memset(&sig,0,sizeof(sig)); - if ( (haspubkey= (opretlen >= coresize+sizeof(uint256))) != 0 ) - { - for (i=0; i<32; i++) - ((uint8_t *)&pubkey)[i] = opretbuf[coresize+i]; - } - if ( (hassig= (opretlen == coresize+sizeof(uint256)*2)) != 0 ) - { - for (i=0; i<32; i++) - ((uint8_t *)&sig)[i] = opretbuf[coresize+sizeof(uint256)+i]; - } - memcpy(keyvalue,key,keylen); - if ( (refvaluesize= komodo_kvsearch((uint256 *)&refpubkey,height,&flags,&kvheight,&keyvalue[keylen],key,keylen)) >= 0 ) - { - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) - { - if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 ) - { - //fprintf(stderr,"komodo_kvsigverify error [%d]\n",coresize-13); - return; - } - } - } - portable_mutex_lock(&KOMODO_KV_mutex); - HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); - if ( ptr != 0 ) - { - //fprintf(stderr,"(%s) already there\n",(char *)key); - //if ( (ptr->flags & KOMODO_KVPROTECTED) != 0 ) - { - tstr = (char *)"transfer:"; - transferpubstr = (char *)&valueptr[strlen(tstr)]; - if ( strncmp(tstr,(char *)valueptr,strlen(tstr)) == 0 && is_hexstr(transferpubstr,0) == 64 ) - { - printf("transfer.(%s) to [%s]? ishex.%d\n",key,transferpubstr,is_hexstr(transferpubstr,0)); - for (i=0; i<32; i++) - ((uint8_t *)&pubkey)[31-i] = _decode_hex(&transferpubstr[i*2]); - } - } - } - else if ( ptr == 0 ) - { - ptr = (struct komodo_kv *)calloc(1,sizeof(*ptr)); - ptr->key = (uint8_t *)calloc(1,keylen); - ptr->keylen = keylen; - memcpy(ptr->key,key,keylen); - newflag = 1; - HASH_ADD_KEYPTR(hh,KOMODO_KV,ptr->key,ptr->keylen,ptr); - //fprintf(stderr,"KV add.(%s) (%s)\n",ptr->key,valueptr); - } - if ( newflag != 0 || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) - { - if ( ptr->value != 0 ) - free(ptr->value), ptr->value = 0; - if ( (ptr->valuesize= valuesize) != 0 ) - { - ptr->value = (uint8_t *)calloc(1,valuesize); - memcpy(ptr->value,valueptr,valuesize); - } - } else fprintf(stderr,"newflag.%d zero or protected %d\n",newflag,(ptr->flags & KOMODO_KVPROTECTED)); - /*for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&ptr->pubkey)[i]); - printf(" <- "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" new pubkey\n");*/ - memcpy(&ptr->pubkey,&pubkey,sizeof(ptr->pubkey)); - ptr->height = height; - ptr->flags = flags; // jl777 used to or in KVPROTECTED - portable_mutex_unlock(&KOMODO_KV_mutex); - } else fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); - } else fprintf(stderr,"not enough fee\n"); -} +int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -#endif +void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value); diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index b17c7b104da..ea6156a5b2c 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -729,7 +729,7 @@ uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint2 if ( *txlenp > 0 ) { rawtx = (uint8_t *)calloc(1,*txlenp); - decode_hex(rawtx,*txlenp,(char *)strHex.c_str()); + decode_hex(rawtx,*txlenp,strHex.c_str()); } } return(rawtx); diff --git a/src/komodo_notary.cpp b/src/komodo_notary.cpp new file mode 100644 index 00000000000..e6605bc0b80 --- /dev/null +++ b/src/komodo_notary.cpp @@ -0,0 +1,505 @@ +/****************************************************************************** + * 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 "komodo_notary.h" +#include "komodo_extern_globals.h" +#include "komodo.h" // komodo_stateupdate() +#include "komodo_structs.h" // KOMODO_NOTARIES_HARDCODED +#include "komodo_utils.h" // komodo_stateptr + +const char *Notaries_genesis[][2] = +{ + { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "crackers_EU", "0340c66cf2c41c41efb420af57867baa765e8468c12aa996bfd816e1e07e410728" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "locomb_EU", "025c6d26649b9d397e63323d96db42a9d3caad82e1d6076970efe5056c00c0779b" }, + { "fullmoon_AE", "0204a908350b8142698fdb6fabefc97fe0e04f537adc7522ba7a1e8f3bec003d4a" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "crackers_NA", "029e1c01131974f4cd3f564cc0c00eb87a0f9721043fbc1ca60f9bd0a1f73f64a1" }, + { "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" }, // 10 + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "traderbill_EU", "03196e8de3e2e5d872f31d79d6a859c8704a2198baf0af9c7b21e29656a7eb455f" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 15 + { "titomane_EU", "03517fcac101fed480ae4f2caf775560065957930d8c1facc83e30077e45bdd199" }, + { "supernet_AE", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, + { "supernet_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "supernet_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "yassin_EU", "033fb7231bb66484081952890d9a03f91164fb27d392d9152ec41336b71b15fbd0" }, // 20 + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "rnr_EU", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "crackers_SH", "02313d72f9a16055737e14cfc528dcd5d0ef094cfce23d0348fe974b6b1a32e5f0" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "polycryptoblock_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "titomane_NA", "0387046d9745414fb58a0fa3599078af5073e10347e4657ef7259a99cb4f10ad47" }, + { "titomane_AE", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "kolo_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "eclips_EU", "0339369c1f5a2028d44be7be6f8ec3b907fdec814f87d2dead97cab4edb71a42e9" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, +}; + +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) +{ + 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 ) + { + int32_t kmd_season = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + // This is KMD, use block heights to determine the KMD notary season.. + if ( height >= KOMODO_NOTARIES_HARDCODED ) + kmd_season = getkmdseason(height); + } + else + { + // 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 ) + { + for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + if ( Pubkeys == 0 ) + { + komodo_init(height); + //printf("Pubkeys.%p htind.%d vs max.%d\n",Pubkeys,htind,KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP); + } + { + std::lock_guard lock(komodo_mutex); + n = Pubkeys[htind].numnotaries; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); + HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) + { + if ( kp->notaryid < n ) + { + mask |= (1LL << kp->notaryid); + memcpy(pubkeys[kp->notaryid],kp->pubkey,33); + } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); + } + } + if ( (n < 64 && mask == ((1LL << n)-1)) || (n == 64 && mask == 0xffffffffffffffffLL) ) + return(n); + printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); + return(-1); +} + +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp) +{ + int32_t i,n; uint8_t pubkeys[64][33]; + n = komodo_notaries(pubkeys,height,timestamp); + *numnotariesp = n; + for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + numnotaries = Pubkeys[htind].numnotaries; + for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 1) != 0) ) + return(1); + else return(0); +} + +void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num) +{ + static int32_t hwmheight; + int32_t k,i,htind,height; struct knotary_entry *kp; struct knotaries_entry N; + if ( Pubkeys == 0 ) + Pubkeys = (struct knotaries_entry *)calloc(1 + (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP),sizeof(*Pubkeys)); + memset(&N,0,sizeof(N)); + if ( origheight > 0 ) + { + height = (origheight + KOMODO_ELECTION_GAP/2); + height /= KOMODO_ELECTION_GAP; + height = ((height + 1) * KOMODO_ELECTION_GAP); + htind = (height / KOMODO_ELECTION_GAP); + if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + //printf("htind.%d activation %d from %d vs %d | hwmheight.%d %s\n",htind,height,origheight,(((origheight+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,hwmheight,ASSETCHAINS_SYMBOL); + } else htind = 0; + { + std::lock_guard lock(komodo_mutex); + for (k=0; kpubkey,pubkeys[k],33); + kp->notaryid = k; + HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp); + if ( 0 && height > 10000 ) + { + for (i=0; i<33; i++) + printf("%02x",pubkeys[k][i]); + printf(" notarypubs.[%d] ht.%d active at %d\n",k,origheight,htind*KOMODO_ELECTION_GAP); + } + } + N.numnotaries = num; + for (i=htind; i hwmheight ) + hwmheight = origheight; +} + +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp) +{ + // -1 if not notary, 0 if notary, 1 if special notary + struct knotary_entry *kp; int32_t numnotaries=0,htind,modval = -1; + *notaryidp = -1; + if ( height < 0 )//|| height >= KOMODO_MAXBLOCKS ) + { + printf("komodo_chosennotary ht.%d illegal\n",height); + return(-1); + } + if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 ) + { + if ( (*notaryidp= komodo_electednotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) + { + modval = ((height % numnotaries) == *notaryidp); + return(modval); + } + } + if ( height >= 250000 ) + return(-1); + if ( Pubkeys == 0 ) + komodo_init(0); + htind = height / KOMODO_ELECTION_GAP; + if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + { + std::lock_guard lock(komodo_mutex); + HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); + } + if ( kp != 0 ) + { + if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) + { + *notaryidp = kp->notaryid; + modval = ((height % numnotaries) == kp->notaryid); + //printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval); + } else printf("unexpected zero notaries at height.%d\n",height); + } //else printf("cant find kp at htind.%d ht.%d\n",htind,height); + //int32_t i; for (i=0; i<33; i++) + // printf("%02x",pubkey33[i]); + //printf(" ht.%d notary.%d special.%d htind.%d num.%d\n",height,*notaryidp,modval,htind,numnotaries); + return(modval); +} + +//struct komodo_state *komodo_stateptr(char *symbol,char *dest); + +struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + for (i=sp->NUM_NPOINTS-1; i>=0; i--) + { + *idx = i; + np = &sp->NPOINTS[i]; + if ( np->MoMdepth != 0 && height > np->notarized_height-(np->MoMdepth&0xffff) && height <= np->notarized_height ) + return(np); + } + } + *idx = -1; + return(0); +} + +struct notarized_checkpoint *komodo_npptr(int32_t height) +{ + int idx; + return komodo_npptr_for_height(height, &idx); +} + +struct notarized_checkpoint *komodo_npptr_at(int idx) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + if (idx < sp->NUM_NPOINTS) + return &sp->NPOINTS[idx]; + return(0); +} + +int32_t komodo_prevMoMheight() +{ + static uint256 zero; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + for (i=sp->NUM_NPOINTS-1; i>=0; i--) + { + np = &sp->NPOINTS[i]; + if ( np->MoM != zero ) + return(np->notarized_height); + } + } + return(0); +} + +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + *prevMoMheightp = 0; + memset(hashp,0,sizeof(*hashp)); + memset(txidp,0,sizeof(*txidp)); + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + CBlockIndex *pindex; + if ( (pindex= komodo_blockindex(sp->NOTARIZED_HASH)) == 0 || pindex->GetHeight() < 0 ) + { + //fprintf(stderr,"found orphaned notarization at ht.%d pindex.%p\n",sp->NOTARIZED_HEIGHT,(void *)pindex); + memset(&sp->NOTARIZED_HASH,0,sizeof(sp->NOTARIZED_HASH)); + memset(&sp->NOTARIZED_DESTTXID,0,sizeof(sp->NOTARIZED_DESTTXID)); + sp->NOTARIZED_HEIGHT = 0; + } + else + { + *hashp = sp->NOTARIZED_HASH; + *txidp = sp->NOTARIZED_DESTTXID; + *prevMoMheightp = komodo_prevMoMheight(); + } + return(sp->NOTARIZED_HEIGHT); + } else return(0); +} + +int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs) +{ + static int32_t hadnotarization; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( KOMODO_DPOWCONFS != 0 && txheight > 0 && numconfs > 0 && (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + if ( sp->NOTARIZED_HEIGHT > 0 ) + { + hadnotarization = 1; + if ( txheight < sp->NOTARIZED_HEIGHT ) + return(numconfs); + else return(1); + } + else if ( hadnotarization != 0 ) + return(1); + } + return(numconfs); +} + +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) +{ + struct notarized_checkpoint *np = 0; + if ( (np= komodo_npptr(height)) != 0 ) + { + *notarized_htp = np->notarized_height; + *MoMp = np->MoM; + *kmdtxidp = np->notarized_desttxid; + *MoMoMp = np->MoMoM; + *MoMoMoffsetp = np->MoMoMoffset; + *MoMoMdepthp = np->MoMoMdepth; + *kmdstartip = np->kmdstarti; + *kmdendip = np->kmdendi; + return(np->MoMdepth & 0xffff); + } + *notarized_htp = *MoMoMoffsetp = *MoMoMdepthp = *kmdstartip = *kmdendip = 0; + memset(MoMp,0,sizeof(*MoMp)); + memset(MoMoMp,0,sizeof(*MoMoMp)); + memset(kmdtxidp,0,sizeof(*kmdtxidp)); + return(0); +} + +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) +{ + struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + if ( sp->NUM_NPOINTS > 0 ) + { + flag = 0; + if ( sp->last_NPOINTSi < sp->NUM_NPOINTS && sp->last_NPOINTSi > 0 ) + { + np = &sp->NPOINTS[sp->last_NPOINTSi-1]; + if ( np->nHeight < nHeight ) + { + for (i=sp->last_NPOINTSi; iNUM_NPOINTS; i++) + { + if ( sp->NPOINTS[i].nHeight >= nHeight ) + { + //printf("flag.1 i.%d np->ht %d [%d].ht %d >= nHeight.%d, last.%d num.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight,sp->last_NPOINTSi,sp->NUM_NPOINTS); + flag = 1; + break; + } + np = &sp->NPOINTS[i]; + sp->last_NPOINTSi = i; + } + } + } + if ( flag == 0 ) + { + np = 0; + for (i=0; iNUM_NPOINTS; i++) + { + if ( sp->NPOINTS[i].nHeight >= nHeight ) + { + //printf("i.%d np->ht %d [%d].ht %d >= nHeight.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight); + break; + } + np = &sp->NPOINTS[i]; + sp->last_NPOINTSi = i; + } + } + } + if ( np != 0 ) + { + //char str[65],str2[65]; printf("[%s] notarized_ht.%d\n",ASSETCHAINS_SYMBOL,np->notarized_height); + if ( np->nHeight >= nHeight || (i < sp->NUM_NPOINTS && np[1].nHeight < nHeight) ) + printf("warning: flag.%d i.%d np->ht %d [1].ht %d >= nHeight.%d\n",flag,i,np->nHeight,np[1].nHeight,nHeight); + *notarized_hashp = np->notarized_hash; + *notarized_desttxidp = np->notarized_desttxid; + return(np->notarized_height); + } + } + memset(notarized_hashp,0,sizeof(*notarized_hashp)); + memset(notarized_desttxidp,0,sizeof(*notarized_desttxidp)); + return(0); +} + +void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth) +{ + struct notarized_checkpoint *np; + if ( notarized_height >= nHeight ) + { + fprintf(stderr,"komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight); + return; + } + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + std::lock_guard lock(komodo_mutex); + sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); + np = &sp->NPOINTS[sp->NUM_NPOINTS++]; + memset(np,0,sizeof(*np)); + np->nHeight = nHeight; + sp->NOTARIZED_HEIGHT = np->notarized_height = notarized_height; + sp->NOTARIZED_HASH = np->notarized_hash = notarized_hash; + sp->NOTARIZED_DESTTXID = np->notarized_desttxid = notarized_desttxid; + sp->MoM = np->MoM = MoM; + sp->MoMdepth = np->MoMdepth = MoMdepth; +} + +void komodo_init(int32_t height) +{ + static int didinit; + uint256 zero; + int32_t k,n; + uint8_t pubkeys[64][33]; + memset(&zero,0,sizeof(zero)); + if ( didinit == 0 ) + { + decode_hex(NOTARY_PUBKEY33,33,NOTARY_PUBKEY.c_str()); + if ( height >= 0 ) + { + n = (int32_t)(sizeof(Notaries_genesis)/sizeof(*Notaries_genesis)); + for (k=0; k 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) -{ - 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 ) - { - int32_t kmd_season = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - // This is KMD, use block heights to determine the KMD notary season.. - if ( height >= KOMODO_NOTARIES_HARDCODED ) - kmd_season = getkmdseason(height); - } - else - { - // 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 ) - { - for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - if ( Pubkeys == 0 ) - { - komodo_init(height); - //printf("Pubkeys.%p htind.%d vs max.%d\n",Pubkeys,htind,KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP); - } - pthread_mutex_lock(&komodo_mutex); - n = Pubkeys[htind].numnotaries; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); - HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) - { - if ( kp->notaryid < n ) - { - mask |= (1LL << kp->notaryid); - memcpy(pubkeys[kp->notaryid],kp->pubkey,33); - } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); - } - pthread_mutex_unlock(&komodo_mutex); - if ( (n < 64 && mask == ((1LL << n)-1)) || (n == 64 && mask == 0xffffffffffffffffLL) ) - return(n); - printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); - return(-1); -} +int32_t getacseason(uint32_t timestamp); -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp) -{ - int32_t i,n; uint8_t pubkeys[64][33]; - n = komodo_notaries(pubkeys,height,timestamp); - *numnotariesp = n; - for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - numnotaries = Pubkeys[htind].numnotaries; - for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 1) != 0) ) - return(1); - else return(0); -} +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); -void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num) -{ - static int32_t hwmheight; - int32_t k,i,htind,height; struct knotary_entry *kp; struct knotaries_entry N; - if ( Pubkeys == 0 ) - Pubkeys = (struct knotaries_entry *)calloc(1 + (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP),sizeof(*Pubkeys)); - memset(&N,0,sizeof(N)); - if ( origheight > 0 ) - { - height = (origheight + KOMODO_ELECTION_GAP/2); - height /= KOMODO_ELECTION_GAP; - height = ((height + 1) * KOMODO_ELECTION_GAP); - htind = (height / KOMODO_ELECTION_GAP); - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - //printf("htind.%d activation %d from %d vs %d | hwmheight.%d %s\n",htind,height,origheight,(((origheight+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,hwmheight,ASSETCHAINS_SYMBOL); - } else htind = 0; - pthread_mutex_lock(&komodo_mutex); - for (k=0; kpubkey,pubkeys[k],33); - kp->notaryid = k; - HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp); - if ( 0 && height > 10000 ) - { - for (i=0; i<33; i++) - printf("%02x",pubkeys[k][i]); - printf(" notarypubs.[%d] ht.%d active at %d\n",k,origheight,htind*KOMODO_ELECTION_GAP); - } - } - N.numnotaries = num; - for (i=htind; i hwmheight ) - hwmheight = origheight; -} +int32_t komodo_ratify_threshold(int32_t height,uint64_t signedmask); -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp) -{ - // -1 if not notary, 0 if notary, 1 if special notary - struct knotary_entry *kp; int32_t numnotaries=0,htind,modval = -1; - *notaryidp = -1; - if ( height < 0 )//|| height >= KOMODO_MAXBLOCKS ) - { - printf("komodo_chosennotary ht.%d illegal\n",height); - return(-1); - } - if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 ) - { - if ( (*notaryidp= komodo_electednotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) - { - modval = ((height % numnotaries) == *notaryidp); - return(modval); - } - } - if ( height >= 250000 ) - return(-1); - if ( Pubkeys == 0 ) - komodo_init(0); - htind = height / KOMODO_ELECTION_GAP; - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - pthread_mutex_lock(&komodo_mutex); - HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); - pthread_mutex_unlock(&komodo_mutex); - if ( kp != 0 ) - { - if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) - { - *notaryidp = kp->notaryid; - modval = ((height % numnotaries) == kp->notaryid); - //printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval); - } else printf("unexpected zero notaries at height.%d\n",height); - } //else printf("cant find kp at htind.%d ht.%d\n",htind,height); - //int32_t i; for (i=0; i<33; i++) - // printf("%02x",pubkey33[i]); - //printf(" ht.%d notary.%d special.%d htind.%d num.%d\n",height,*notaryidp,modval,htind,numnotaries); - return(modval); -} +void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num); -//struct komodo_state *komodo_stateptr(char *symbol,char *dest); +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - for (i=sp->NUM_NPOINTS-1; i>=0; i--) - { - *idx = i; - np = &sp->NPOINTS[i]; - if ( np->MoMdepth != 0 && height > np->notarized_height-(np->MoMdepth&0xffff) && height <= np->notarized_height ) - return(np); - } - } - *idx = -1; - return(0); -} +struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx); -struct notarized_checkpoint *komodo_npptr(int32_t height) -{ - int idx; - return komodo_npptr_for_height(height, &idx); -} +struct notarized_checkpoint *komodo_npptr(int32_t height); -struct notarized_checkpoint *komodo_npptr_at(int idx) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - if (idx < sp->NUM_NPOINTS) - return &sp->NPOINTS[idx]; - return(0); -} +struct notarized_checkpoint *komodo_npptr_at(int idx); -int32_t komodo_prevMoMheight() -{ - static uint256 zero; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - for (i=sp->NUM_NPOINTS-1; i>=0; i--) - { - np = &sp->NPOINTS[i]; - if ( np->MoM != zero ) - return(np->notarized_height); - } - } - return(0); -} +int32_t komodo_prevMoMheight(); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - *prevMoMheightp = 0; - memset(hashp,0,sizeof(*hashp)); - memset(txidp,0,sizeof(*txidp)); - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - CBlockIndex *pindex; - if ( (pindex= komodo_blockindex(sp->NOTARIZED_HASH)) == 0 || pindex->GetHeight() < 0 ) - { - //fprintf(stderr,"found orphaned notarization at ht.%d pindex.%p\n",sp->NOTARIZED_HEIGHT,(void *)pindex); - memset(&sp->NOTARIZED_HASH,0,sizeof(sp->NOTARIZED_HASH)); - memset(&sp->NOTARIZED_DESTTXID,0,sizeof(sp->NOTARIZED_DESTTXID)); - sp->NOTARIZED_HEIGHT = 0; - } - else - { - *hashp = sp->NOTARIZED_HASH; - *txidp = sp->NOTARIZED_DESTTXID; - *prevMoMheightp = komodo_prevMoMheight(); - } - return(sp->NOTARIZED_HEIGHT); - } else return(0); -} +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); -int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs) -{ - static int32_t hadnotarization; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( KOMODO_DPOWCONFS != 0 && txheight > 0 && numconfs > 0 && (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - if ( sp->NOTARIZED_HEIGHT > 0 ) - { - hadnotarization = 1; - if ( txheight < sp->NOTARIZED_HEIGHT ) - return(numconfs); - else return(1); - } - else if ( hadnotarization != 0 ) - return(1); - } - return(numconfs); -} +int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs); -int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) -{ - struct notarized_checkpoint *np = 0; - if ( (np= komodo_npptr(height)) != 0 ) - { - *notarized_htp = np->notarized_height; - *MoMp = np->MoM; - *kmdtxidp = np->notarized_desttxid; - *MoMoMp = np->MoMoM; - *MoMoMoffsetp = np->MoMoMoffset; - *MoMoMdepthp = np->MoMoMdepth; - *kmdstartip = np->kmdstarti; - *kmdendip = np->kmdendi; - return(np->MoMdepth & 0xffff); - } - *notarized_htp = *MoMoMoffsetp = *MoMoMdepthp = *kmdstartip = *kmdendip = 0; - memset(MoMp,0,sizeof(*MoMp)); - memset(MoMoMp,0,sizeof(*MoMoMp)); - memset(kmdtxidp,0,sizeof(*kmdtxidp)); - return(0); -} +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) -{ - struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - if ( sp->NUM_NPOINTS > 0 ) - { - flag = 0; - if ( sp->last_NPOINTSi < sp->NUM_NPOINTS && sp->last_NPOINTSi > 0 ) - { - np = &sp->NPOINTS[sp->last_NPOINTSi-1]; - if ( np->nHeight < nHeight ) - { - for (i=sp->last_NPOINTSi; iNUM_NPOINTS; i++) - { - if ( sp->NPOINTS[i].nHeight >= nHeight ) - { - //printf("flag.1 i.%d np->ht %d [%d].ht %d >= nHeight.%d, last.%d num.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight,sp->last_NPOINTSi,sp->NUM_NPOINTS); - flag = 1; - break; - } - np = &sp->NPOINTS[i]; - sp->last_NPOINTSi = i; - } - } - } - if ( flag == 0 ) - { - np = 0; - for (i=0; iNUM_NPOINTS; i++) - { - if ( sp->NPOINTS[i].nHeight >= nHeight ) - { - //printf("i.%d np->ht %d [%d].ht %d >= nHeight.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight); - break; - } - np = &sp->NPOINTS[i]; - sp->last_NPOINTSi = i; - } - } - } - if ( np != 0 ) - { - //char str[65],str2[65]; printf("[%s] notarized_ht.%d\n",ASSETCHAINS_SYMBOL,np->notarized_height); - if ( np->nHeight >= nHeight || (i < sp->NUM_NPOINTS && np[1].nHeight < nHeight) ) - printf("warning: flag.%d i.%d np->ht %d [1].ht %d >= nHeight.%d\n",flag,i,np->nHeight,np[1].nHeight,nHeight); - *notarized_hashp = np->notarized_hash; - *notarized_desttxidp = np->notarized_desttxid; - return(np->notarized_height); - } - } - memset(notarized_hashp,0,sizeof(*notarized_hashp)); - memset(notarized_desttxidp,0,sizeof(*notarized_desttxidp)); - return(0); -} +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); -void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth) -{ - struct notarized_checkpoint *np; - if ( notarized_height >= nHeight ) - { - fprintf(stderr,"komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight); - return; - } - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - portable_mutex_lock(&komodo_mutex); - sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); - np = &sp->NPOINTS[sp->NUM_NPOINTS++]; - memset(np,0,sizeof(*np)); - np->nHeight = nHeight; - sp->NOTARIZED_HEIGHT = np->notarized_height = notarized_height; - sp->NOTARIZED_HASH = np->notarized_hash = notarized_hash; - sp->NOTARIZED_DESTTXID = np->notarized_desttxid = notarized_desttxid; - sp->MoM = np->MoM = MoM; - sp->MoMdepth = np->MoMdepth = MoMdepth; - portable_mutex_unlock(&komodo_mutex); -} +void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth); -void komodo_init(int32_t height) -{ - static int didinit; uint256 zero; int32_t k,n; uint8_t pubkeys[64][33]; - if ( 0 && height != 0 ) - printf("komodo_init ht.%d didinit.%d\n",height,didinit); - memset(&zero,0,sizeof(zero)); - if ( didinit == 0 ) - { - pthread_mutex_init(&komodo_mutex,NULL); - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); - if ( height >= 0 ) - { - n = (int32_t)(sizeof(Notaries_genesis)/sizeof(*Notaries_genesis)); - for (k=0; k= 32 ) + return(0); + if ( baseid < 10 ) + val *= 4; + mult = MINDENOMS[baseid] / MIND; + return(mult * val); +} + +uint64_t komodo_paxvol(uint64_t volume,uint64_t price) +{ + if ( volume < 10000000000 ) + return((volume * price) / 1000000000); + else if ( volume < (uint64_t)10 * 10000000000 ) + return((volume * (price / 10)) / 100000000); + else if ( volume < (uint64_t)100 * 10000000000 ) + return(((volume / 10) * (price / 10)) / 10000000); + else if ( volume < (uint64_t)1000 * 10000000000 ) + return(((volume / 10) * (price / 100)) / 1000000); + else if ( volume < (uint64_t)10000 * 10000000000 ) + return(((volume / 100) * (price / 100)) / 100000); + else if ( volume < (uint64_t)100000 * 10000000000 ) + return(((volume / 100) * (price / 1000)) / 10000); + else if ( volume < (uint64_t)1000000 * 10000000000 ) + return(((volume / 1000) * (price / 1000)) / 1000); + else if ( volume < (uint64_t)10000000 * 10000000000 ) + return(((volume / 1000) * (price / 10000)) / 100); + else return(((volume / 10000) * (price / 10000)) / 10); +} + +void pax_rank(uint64_t *ranked,uint32_t *pvals) +{ + int32_t i; uint64_t vals[32],sum = 0; + for (i=0; i<32; i++) + { + vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]); + sum += vals[i]; + } + for (i=0; i<32; i++) + { + ranked[i] = (vals[i] * 1000000000) / sum; + //printf("%.6f ",(double)ranked[i]/1000000000.); + } + //printf("sum %llu\n",(long long)sum); +}; + +#define BTCFACTOR_HEIGHT 466266 + +double PAX_BTCUSD(int32_t height,uint32_t btcusd) +{ + double btcfactor,BTCUSD; + if ( height >= BTCFACTOR_HEIGHT ) + btcfactor = 100000.; + else btcfactor = 1000.; + BTCUSD = ((double)btcusd / (1000000000. / btcfactor)); + if ( height >= BTCFACTOR_HEIGHT && height < 500000 && BTCUSD > 20000 && btcfactor == 100000. ) + BTCUSD /= 100; + return(BTCUSD); +} + +int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals) +{ + uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; + if ( data[0] == 'P' && data[5] == 35 ) + data++; + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); + if ( n != 35 ) + { + printf("dpow_readprices illegal n.%d\n",n); + return(-1); + } + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); + *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); + *BTCUSDp = PAX_BTCUSD(height,btcusd); + *CNYUSDp = ((double)cnyusd / 1000000000.); + for (i=nonz=0; i sizeof(crc32) ) + { + if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) + { + len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); + check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); + if ( check == crc32 ) + { + double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128]; + if ( dpow_readprices(height,&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 ) + { + if ( 0 && lastcrc != crc32 ) + { + for (i=0; i<32; i++) + printf("%u ",pvals[i]); + printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0); + } + if ( timestamp > time(NULL)-600 ) + { + n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); + if ( 0 && lastcrc != crc32 ) + { + for (i=0; i maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data)); + fclose(fp); + } //else printf("couldnt open %s\n",fname); + return(n); +} + +int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp) +{ + if ( rwflag != 0 ) + { + memset(pubkey33,0,33); + pubkey33[0] = 0x02 | (*shortflagp != 0); + memcpy(&pubkey33[1],fiat,3); + iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); + pubkey33[12] = *addrtypep; + memcpy(&pubkey33[13],rmd160,20); + } + else + { + *shortflagp = (pubkey33[0] == 0x03); + memcpy(fiat,&pubkey33[1],3); + fiat[3] = 0; + iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); + if ( *shortflagp != 0 ) + *fiatoshisp = -(*fiatoshisp); + *addrtypep = pubkey33[12]; + memcpy(rmd160,&pubkey33[13],20); + } + return(33); +} + +double PAX_val(uint32_t pval,int32_t baseid) +{ + //printf("PAX_val baseid.%d pval.%u\n",baseid,pval); + if ( baseid >= 0 && baseid < MAX_CURRENCIES ) + return(((double)pval / 1000000000.) / MINDENOMS[baseid]); + return(0.); +} + +void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) +{ + int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD; + if ( numpvals >= 35 ) + { + for (nonz=i=0; i<32; i++) + { + if ( pvals[i] != 0 ) + nonz++; + //printf("%u ",pvals[i]); + } + if ( nonz == 32 ) + { + kmdbtc = pvals[i++]; + btcusd = pvals[i++]; + cnyusd = pvals[i++]; + KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); + BTCUSD = PAX_BTCUSD(height,btcusd); + CNYUSD = ((double)cnyusd / 1000000000.); + std::lock_guard lock(komodo_mutex); + PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); + PVALS[36 * NUM_PRICES] = height; + memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); + NUM_PRICES++; + } + } +} + +uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed) +{ + int32_t i,j,k,ind,zeroes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0; + for (sum=i=zeroes=nonz=0; i> 2) ) + return(0); + sum /= nonz; + lastprice = sum; + for (i=0; i (numvotes >> 1) ) + break; + } + } + } + } + if ( wt > (numvotes >> 1) ) + { + ind = i; + for (densum=sum=j=0; j KOMODO_PAXMAX ) + { + printf("paxcalc overflow %.8f\n",dstr(basevolume)); + return(0); + } + if ( (pvalb= pvals[baseid]) != 0 ) + { + if ( relid == MAX_CURRENCIES ) + { + if ( height < 236000 ) + { + if ( kmdbtc == 0 ) + kmdbtc = pvals[MAX_CURRENCIES]; + if ( btcusd == 0 ) + btcusd = pvals[MAX_CURRENCIES + 1]; + } + else + { + if ( (kmdbtc= pvals[MAX_CURRENCIES]) == 0 ) + kmdbtc = refkmdbtc; + if ( (btcusd= pvals[MAX_CURRENCIES + 1]) == 0 ) + btcusd = refbtcusd; + } + if ( kmdbtc < 25000000 ) + kmdbtc = 25000000; + if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 ) + { + baseusd = (((uint64_t)pvalb * 1000000000) / pvals[USD]); + usdvol = komodo_paxvol(basevolume,baseusd); + usdkmd = ((uint64_t)kmdbtc * 1000000000) / btcusd; + if ( height >= 236000-10 ) + { + BTCUSD = PAX_BTCUSD(height,btcusd); + if ( height < BTCFACTOR_HEIGHT || (height < 500000 && BTCUSD > 20000) ) + usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; + else usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; + ///if ( height >= BTCFACTOR_HEIGHT && BTCUSD >= 43 ) + // usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; + //else usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; + price = ((uint64_t)10000000000 * MINDENOMS[USD] / MINDENOMS[baseid]) / komodo_paxvol(usdvol,usdkmd); + //fprintf(stderr,"ht.%d %.3f kmdbtc.%llu btcusd.%llu base -> USD %llu, usdkmd %llu usdvol %llu -> %llu\n",height,BTCUSD,(long long)kmdbtc,(long long)btcusd,(long long)baseusd,(long long)usdkmd,(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); + //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)),(long long)price); + //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); + } else price = (MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)); + return(price); + } //else printf("zero val in KMD conv %llu %llu %llu\n",(long long)pvals[USD],(long long)kmdbtc,(long long)btcusd); + } + else if ( baseid == relid ) + { + if ( baseid != MAX_CURRENCIES ) + { + pax_rank(ranked,pvals); + //printf("%s M1 percentage %.8f\n",CURRENCIES[baseid],dstr(10 * ranked[baseid])); + return(10 * ranked[baseid]); // scaled percentage of M1 total + } else return(basevolume); + } + else if ( (pvalr= pvals[relid]) != 0 ) + { + baserel = ((uint64_t)pvalb * 1000000000) / pvalr; + //printf("baserel.%lld %lld %lld %.8f %.8f\n",(long long)baserel,(long long)MINDENOMS[baseid],(long long)MINDENOMS[relid],dstr(MINDENOMS[baseid]/MINDENOMS[relid]),dstr(MINDENOMS[relid]/MINDENOMS[baseid])); + if ( MINDENOMS[baseid] > MINDENOMS[relid] ) + basevolume /= (MINDENOMS[baseid] / MINDENOMS[relid]); + else if ( MINDENOMS[baseid] < MINDENOMS[relid] ) + basevolume *= (MINDENOMS[relid] / MINDENOMS[baseid]); + return(komodo_paxvol(basevolume,baserel)); + } + else printf("null pval for %s\n",CURRENCIES[relid]); + } else printf("null pval for %s\n",CURRENCIES[baseid]); + return(0); +} + +uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd) +{ + int32_t baseid=-1,relid=-1,i; uint32_t *ptr,*pvals; + if ( height > 10 ) + height -= 10; + if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) + { + for (i=NUM_PRICES-1; i>=0; i--) + { + ptr = &PVALS[36 * i]; + if ( *ptr < height ) + { + pvals = &ptr[1]; + if ( kmdbtcp != 0 && btcusdp != 0 ) + { + *kmdbtcp = pvals[MAX_CURRENCIES] / 539; + *btcusdp = pvals[MAX_CURRENCIES + 1] / 539; + } + if ( kmdbtc != 0 && btcusd != 0 ) + return(komodo_paxcalc(height,pvals,baseid,relid,basevolume,kmdbtc,btcusd)); + else return(0); + } + } + } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); + return(0); +} + +int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height) +{ + static uint64_t *KMDBTCS,*BTCUSDS; static int32_t maxheight = 0; int32_t incr = 10000; + if ( height >= maxheight ) + { + //printf("height.%d maxheight.%d incr.%d\n",height,maxheight,incr); + if ( height >= maxheight+incr ) + incr = (height - (maxheight+incr) + 1000); + KMDBTCS = (uint64_t *)realloc(KMDBTCS,((incr + maxheight) * sizeof(*KMDBTCS))); + memset(&KMDBTCS[maxheight],0,(incr * sizeof(*KMDBTCS))); + BTCUSDS = (uint64_t *)realloc(BTCUSDS,((incr + maxheight) * sizeof(*BTCUSDS))); + memset(&BTCUSDS[maxheight],0,(incr * sizeof(*BTCUSDS))); + maxheight += incr; + } + if ( rwflag == 0 ) + { + *kmdbtcp = KMDBTCS[height]; + *btcusdp = BTCUSDS[height]; + } + else + { + KMDBTCS[height] = *kmdbtcp; + BTCUSDS[height] = *btcusdp; + } + if ( *kmdbtcp != 0 && *btcusdp != 0 ) + return(0); + else return(-1); +} + +uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) +{ + int32_t i,j,k,ind,zeroes,numvotes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0,votes[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],btcusds[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtcs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtc,btcusd; + if ( basevolume > KOMODO_PAXMAX ) + { + printf("komodo_paxprice overflow %.8f\n",dstr(basevolume)); + return(0); + } + if ( strcmp(base,"KMD") == 0 || strcmp(base,"kmd") == 0 ) + { + printf("kmd cannot be base currency\n"); + return(0); + } + numvotes = (int32_t)(sizeof(Peggy_inds)/sizeof(*Peggy_inds)); + memset(votes,0,sizeof(votes)); + //if ( komodo_kmdbtcusd(0,&kmdbtc,&btcusd,height) < 0 ) crashes when via passthru GUI use + { + memset(btcusds,0,sizeof(btcusds)); + memset(kmdbtcs,0,sizeof(kmdbtcs)); + for (i=0; i> 1) ) + { + return(0); + } + return(komodo_paxcorrelation(votes,numvotes,seed) * basevolume / 100000); +} + +uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) +{ + uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); + if ( height >= 236000 && strcmp(rel,"kmd") == 0 ) + { + usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); + if ( strcmp("usd",base) == 0 ) + return(komodo_paxvol(basevolume,usdkmd) * 10); + baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); + basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; + //if ( strcmp("KMD",base) == 0 ) + // printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); + return(basekmd); + } else return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); +} + +uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume) +{ + int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->GetHeight() ) + { + if ( height < 100000000 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->GetHeight()); + } + return(0); + } + *seedp = komodo_seed(height); + { + std::lock_guard lock(komodo_mutex); + for (i=0; i<17; i++) + { + if ( (price= komodo_paxpriceB(*seedp,height-i,base,rel,basevolume)) != 0 ) + { + sum += price; + nonz++; + if ( 0 && i == 1 && nonz == 2 ) + { + diff = (((int64_t)price - (sum >> 1)) * 10000); + if ( diff < 0 ) + diff = -diff; + diff /= price; + printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>1),(long long)(((int64_t)price - (sum >> 1)) * 10000),(long long)diff); + if ( diff < 33 ) + break; + } + else if ( 0 && i == 3 && nonz == 4 ) + { + diff = (((int64_t)price - (sum >> 2)) * 10000); + if ( diff < 0 ) + diff = -diff; + diff /= price; + printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>2),(long long) (((int64_t)price - (sum >> 2)) * 10000),(long long)diff); + if ( diff < 20 ) + break; + } + } + if ( height < 165000 || height > 236000 ) + break; + } + } + if ( nonz != 0 ) + sum /= nonz; + //printf("-> %lld %s/%s i.%d ht.%d\n",(long long)sum,base,rel,i,height); + return(sum); +} + +int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel) +{ + int32_t baseid=-1,relid=-1,i,num = 0; uint32_t *ptr; + if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) + { + for (i=NUM_PRICES-1; i>=0; i--) + { + ptr = &PVALS[36 * i]; + heights[num] = *ptr; + prices[num] = komodo_paxcalc(*ptr,&ptr[1],baseid,relid,COIN,0,0); + num++; + if ( num >= max ) + return(num); + } + } + return(num); +} + +void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen) +{ + double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero; + numpvals = dpow_readprices(height,pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals); + memset(&zero,0,sizeof(zero)); + komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0,0,0,zero,0); + if ( 0 ) + { + int32_t i; + for (i=0; i KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); + if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) + { + PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); + bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33); + } + return(komodoshis); +} diff --git a/src/komodo_pax.h b/src/komodo_pax.h index 9935f34637a..830688d2932 100644 --- a/src/komodo_pax.h +++ b/src/komodo_pax.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once #include "komodo_defs.h" #define USD 0 @@ -54,692 +54,40 @@ #define MAX_CURRENCIES 32 extern char CURRENCIES[][8]; -uint64_t M1SUPPLY[] = { 3317900000000, 6991604000000, 667780000000000, 1616854000000, 331000000000, 861909000000, 584629000000, 46530000000, // major currencies - 45434000000000, 16827000000000, 3473357229000, 306435000000, 27139000000000, 2150641000000, 347724099000, 1469583000000, 749543000000, 1826110000000, 2400434000000, 1123925000000, 3125276000000, 13975000000000, 317657000000, 759706000000000, 354902000000, 2797061000000, 162189000000, 163745000000, 1712000000000, 39093000000, 1135490000000000, 80317000000, - 100000000 }; - -#define MIND 1000 -uint32_t MINDENOMS[] = { MIND, MIND, 100*MIND, MIND, MIND, MIND, MIND, MIND, // major currencies - 10*MIND, 100*MIND, 10*MIND, MIND, 100*MIND, 10*MIND, MIND, 10*MIND, MIND, 10*MIND, 10*MIND, 10*MIND, 10*MIND, 100*MIND, MIND, 1000*MIND, MIND, 10*MIND, MIND, MIND, 10*MIND, MIND, 10000*MIND, 10*MIND, // end of currencies -10*MIND, -}; - -int32_t Peggy_inds[539] = {289, 404, 50, 490, 59, 208, 87, 508, 366, 288, 13, 38, 159, 440, 120, 480, 361, 104, 534, 195, 300, 362, 489, 108, 143, 220, 131, 244, 133, 473, 315, 439, 210, 456, 219, 352, 153, 444, 397, 491, 286, 479, 519, 384, 126, 369, 155, 427, 373, 360, 135, 297, 256, 506, 322, 425, 501, 251, 75, 18, 420, 537, 443, 438, 407, 145, 173, 78, 340, 240, 422, 160, 329, 32, 127, 128, 415, 495, 372, 522, 60, 238, 129, 364, 471, 140, 171, 215, 378, 292, 432, 526, 252, 389, 459, 350, 233, 408, 433, 51, 423, 19, 62, 115, 211, 22, 247, 197, 530, 7, 492, 5, 53, 318, 313, 283, 169, 464, 224, 282, 514, 385, 228, 175, 494, 237, 446, 105, 150, 338, 346, 510, 6, 348, 89, 63, 536, 442, 414, 209, 216, 227, 380, 72, 319, 259, 305, 334, 236, 103, 400, 176, 267, 355, 429, 134, 257, 527, 111, 287, 386, 15, 392, 535, 405, 23, 447, 399, 291, 112, 74, 36, 435, 434, 330, 520, 335, 201, 478, 17, 162, 483, 33, 130, 436, 395, 93, 298, 498, 511, 66, 487, 218, 65, 309, 419, 48, 214, 377, 409, 462, 139, 349, 4, 513, 497, 394, 170, 307, 241, 185, 454, 29, 367, 465, 194, 398, 301, 229, 212, 477, 303, 39, 524, 451, 116, 532, 30, 344, 85, 186, 202, 517, 531, 515, 230, 331, 466, 147, 426, 234, 304, 64, 100, 416, 336, 199, 383, 200, 166, 258, 95, 188, 246, 136, 90, 68, 45, 312, 354, 184, 314, 518, 326, 401, 269, 217, 512, 81, 88, 272, 14, 413, 328, 393, 198, 226, 381, 161, 474, 353, 337, 294, 295, 302, 505, 137, 207, 249, 46, 98, 27, 458, 482, 262, 253, 71, 25, 0, 40, 525, 122, 341, 107, 80, 165, 243, 168, 250, 375, 151, 503, 124, 52, 343, 371, 206, 178, 528, 232, 424, 163, 273, 191, 149, 493, 177, 144, 193, 388, 1, 412, 265, 457, 255, 475, 223, 41, 430, 76, 102, 132, 96, 97, 316, 472, 213, 263, 3, 317, 324, 274, 396, 486, 254, 205, 285, 101, 21, 279, 58, 467, 271, 92, 538, 516, 235, 332, 117, 500, 529, 113, 445, 390, 358, 79, 34, 488, 245, 83, 509, 203, 476, 496, 347, 280, 12, 84, 485, 323, 452, 10, 146, 391, 293, 86, 94, 523, 299, 91, 164, 363, 402, 110, 321, 181, 138, 192, 469, 351, 276, 308, 277, 428, 182, 260, 55, 152, 157, 382, 121, 507, 225, 61, 431, 31, 106, 327, 154, 16, 49, 499, 73, 70, 449, 460, 187, 24, 248, 311, 275, 158, 387, 125, 67, 284, 35, 463, 190, 179, 266, 376, 221, 42, 26, 290, 357, 268, 43, 167, 99, 374, 242, 156, 239, 403, 339, 183, 320, 180, 306, 379, 441, 20, 481, 141, 77, 484, 69, 410, 502, 172, 417, 118, 461, 261, 47, 333, 450, 296, 453, 368, 359, 437, 421, 264, 504, 281, 270, 114, 278, 56, 406, 448, 411, 521, 418, 470, 123, 455, 148, 356, 468, 109, 204, 533, 365, 8, 345, 174, 370, 28, 57, 11, 2, 231, 310, 196, 119, 82, 325, 44, 342, 37, 189, 142, 222, 9, 54, }; - -uint64_t peggy_smooth_coeffs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)] = // numprimes.13 -{ - 962714545, 962506087, 962158759, 961672710, 961048151, 960285354, 959384649, 958346426, 957171134, // x.8 - 955859283, 954411438, 952828225, 951110328, 949258485, 947273493, 945156207, 942907532, 940528434, // x.17 - 938019929, 935383089, 932619036, 929728945, 926714044, 923575608, 920314964, 916933485, 913432593, // x.26 - 909813756, 906078486, 902228342, 898264923, 894189872, 890004874, 885711650, 881311964, 876807614, // x.35 - 872200436, 867492300, 862685110, 857780804, 852781347, 847688737, 842505000, 837232189, 831872382, // x.44 - 826427681, 820900212, 815292123, 809605581, 803842772, 798005901, 792097186, 786118864, 780073180, // x.53 - 773962395, 767788778, 761554609, 755262175, 748913768, 742511686, 736058231, 729555707, 723006417, // x.62 - 716412665, 709776755, 703100984, 696387648, 689639036, 682857428, 676045100, 669204315, 662337327, // x.71 - 655446378, 648533696, 641601496, 634651978, 627687325, 620709702, 613721256, 606724115, 599720386, // x.80 - 592712154, 585701482, 578690411, 571680955, 564675105, 557674825, 550682053, 543698699, 536726645, // x.89 - 529767743, 522823816, 515896658, 508988029, 502099660, 495233249, 488390461, 481572928, 474782249, // x.98 - 468019988, 461287675, 454586804, 447918836, 441285195, 434687268, 428126409, 421603932, 415121117, // x.107 - 408679208, 402279408, 395922888, 389610779, 383344175, 377124134, 370951677, 364827785, 358753406, // x.116 - 352729449, 346756785, 340836251, 334968645, 329154729, 323395230, 317690838, 312042206, 306449955, // x.125 - 300914667, 295436891, 290017141, 284655897, 279353604, 274110676, 268927490, 263804394, 258741701, // x.134 - 253739694, 248798623, 243918709, 239100140, 234343077, 229647649, 225013957, 220442073, 215932043, // x.143 - 211483883, 207097585, 202773112, 198510404, 194309373, 190169909, 186091877, 182075118, 178119452, // x.152 - 174224676, 170390565, 166616873, 162903335, 159249664, 155655556, 152120688, 148644718, 145227287, // x.161 - 141868021, 138566528, 135322401, 132135218, 129004542, 125929924, 122910901, 119946997, 117037723, // x.170 - 114182582, 111381062, 108632643, 105936795, 103292978, 100700645, 98159238, 95668194, 93226942, // x.179 - 90834903, 88491495, 86196126, 83948203, 81747126, 79592292, 77483092, 75418916, 73399150, // x.188 - 71423178, 69490383, 67600142, 65751837, 63944844, 62178541, 60452305, 58765515, 57117547, // x.197 - 55507781, 53935597, 52400377, 50901505, 49438366, 48010349, 46616844, 45257246, 43930951, // x.206 - 42637360, 41375878, 40145912, 38946876, 37778185, 36639262, 35529533, 34448428, 33395384, // x.215 - 32369842, 31371249, 30399057, 29452725, 28531717, 27635503, 26763558, 25915365, 25090413, // x.224 - 24288196, 23508216, 22749980, 22013003, 21296806, 20600917, 19924870, 19268206, 18630475, // x.233 - 18011231, 17410035, 16826458, 16260073, 15710466, 15177224, 14659944, 14158231, 13671694, // x.242 - 13199950, 12742625, 12299348, 11869759, 11453500, 11050225, 10659590, 10281262, 9914910, // x.251 - 9560213, 9216856, 8884529, 8562931, 8251764, 7950739, 7659571, 7377984, 7105706, // x.260 - 6842471, 6588020, 6342099, 6104460, 5874861, 5653066, 5438844, 5231969, 5032221, // x.269 - 4839386, 4653254, 4473620, 4300287, 4133059, 3971747, 3816167, 3666139, 3521488, // x.278 - 3382043, 3247640, 3118115, 2993313, 2873079, 2757266, 2645728, 2538325, 2434919, // x.287 - 2335380, 2239575, 2147382, 2058677, 1973342, 1891262, 1812325, 1736424, 1663453, // x.296 - 1593311, 1525898, 1461118, 1398879, 1339091, 1281666, 1226519, 1173569, 1122736, // x.305 - 1073944, 1027117, 982185, 939076, 897725, 858065, 820033, 783568, 748612, // x.314 - 715108, 682999, 652233, 622759, 594527, 567488, 541597, 516808, 493079, // x.323 - 470368, 448635, 427841, 407948, 388921, 370725, 353326, 336692, 320792, // x.332 - 305596, 291075, 277202, 263950, 251292, 239204, 227663, 216646, 206130, // x.341 - 196094, 186517, 177381, 168667, 160356, 152430, 144874, 137671, 130806, // x.350 - 124264, 118031, 112093, 106437, 101050, 95921, 91039, 86391, 81968, // x.359 - 77759, 73755, 69945, 66322, 62877, 59602, 56488, 53528, 50716, // x.368 - 48043, 45505, 43093, 40803, 38629, 36564, 34604, 32745, 30980, // x.377 - 29305, 27717, 26211, 24782, 23428, 22144, 20927, 19774, 18681, // x.386 - 17646, 16665, 15737, 14857, 14025, 13237, 12491, 11786, 11118, // x.395 - 10487, 9890, 9325, 8791, 8287, 7810, 7359, 6933, 6531, // x.404 - 6151, 5792, 5453, 5133, 4831, 4547, 4278, 4024, 3785, // x.413 - 3560, 3347, 3147, 2958, 2779, 2612, 2454, 2305, 2164, // x.422 - 2032, 1908, 1791, 1681, 1577, 1480, 1388, 1302, 1221, // x.431 - 1145, 1073, 1006, 942, 883, 827, 775, 725, 679, // x.440 - 636, 595, 557, 521, 487, 456, 426, 399, 373, // x.449 - 348, 325, 304, 284, 265, 248, 231, 216, 202, // x.458 - 188, 175, 164, 153, 142, 133, 124, 115, 107, // x.467 - 100, 93, 87, 81, 75, 70, 65, 61, 56, // x.476 - 53, 49, 45, 42, 39, 36, 34, 31, 29, // x.485 - 27, 25, 23, 22, 20, 19, 17, 16, 15, // x.494 - 14, 13, 12, 11, 10, 9, 9, 8, 7, // x.503 - 7, 6, 6, 5, 5, 5, 4, 4, 4, // x.512 - 3, 3, 3, 3, 2, 2, 2, 2, 2, // x.521 - 2, 2, 1, 1, 1, 1, 1, 1, 1, // x.530 - 1, 1, 1, 1, 1, 1, 0, 0, // isum 100000000000 -}; - -uint64_t komodo_maxallowed(int32_t baseid) -{ - uint64_t mult,val = COIN * (uint64_t)10000; - if ( baseid < 0 || baseid >= 32 ) - return(0); - if ( baseid < 10 ) - val *= 4; - mult = MINDENOMS[baseid] / MIND; - return(mult * val); -} - -uint64_t komodo_paxvol(uint64_t volume,uint64_t price) -{ - if ( volume < 10000000000 ) - return((volume * price) / 1000000000); - else if ( volume < (uint64_t)10 * 10000000000 ) - return((volume * (price / 10)) / 100000000); - else if ( volume < (uint64_t)100 * 10000000000 ) - return(((volume / 10) * (price / 10)) / 10000000); - else if ( volume < (uint64_t)1000 * 10000000000 ) - return(((volume / 10) * (price / 100)) / 1000000); - else if ( volume < (uint64_t)10000 * 10000000000 ) - return(((volume / 100) * (price / 100)) / 100000); - else if ( volume < (uint64_t)100000 * 10000000000 ) - return(((volume / 100) * (price / 1000)) / 10000); - else if ( volume < (uint64_t)1000000 * 10000000000 ) - return(((volume / 1000) * (price / 1000)) / 1000); - else if ( volume < (uint64_t)10000000 * 10000000000 ) - return(((volume / 1000) * (price / 10000)) / 100); - else return(((volume / 10000) * (price / 10000)) / 10); -} - -void pax_rank(uint64_t *ranked,uint32_t *pvals) -{ - int32_t i; uint64_t vals[32],sum = 0; - for (i=0; i<32; i++) - { - vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]); - sum += vals[i]; - } - for (i=0; i<32; i++) - { - ranked[i] = (vals[i] * 1000000000) / sum; - //printf("%.6f ",(double)ranked[i]/1000000000.); - } - //printf("sum %llu\n",(long long)sum); -}; - -#define BTCFACTOR_HEIGHT 466266 +uint64_t komodo_maxallowed(int32_t baseid); -double PAX_BTCUSD(int32_t height,uint32_t btcusd) -{ - double btcfactor,BTCUSD; - if ( height >= BTCFACTOR_HEIGHT ) - btcfactor = 100000.; - else btcfactor = 1000.; - BTCUSD = ((double)btcusd / (1000000000. / btcfactor)); - if ( height >= BTCFACTOR_HEIGHT && height < 500000 && BTCUSD > 20000 && btcfactor == 100000. ) - BTCUSD /= 100; - return(BTCUSD); -} +uint64_t komodo_paxvol(uint64_t volume,uint64_t price); -int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals) -{ - uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; - if ( data[0] == 'P' && data[5] == 35 ) - data++; - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); - if ( n != 35 ) - { - printf("dpow_readprices illegal n.%d\n",n); - return(-1); - } - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); - *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); - *BTCUSDp = PAX_BTCUSD(height,btcusd); - *CNYUSDp = ((double)cnyusd / 1000000000.); - for (i=nonz=0; i sizeof(crc32) ) - { - if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) - { - len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); - check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); - if ( check == crc32 ) - { - double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128]; - if ( dpow_readprices(height,&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 ) - { - if ( 0 && lastcrc != crc32 ) - { - for (i=0; i<32; i++) - printf("%u ",pvals[i]); - printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0); - } - if ( timestamp > time(NULL)-600 ) - { - n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); - if ( 0 && lastcrc != crc32 ) - { - for (i=0; i maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data)); - fclose(fp); - } //else printf("couldnt open %s\n",fname); - return(n); -} +double PAX_BTCUSD(int32_t height,uint32_t btcusd); -/*uint32_t PAX_val32(double val) - { - uint32_t val32 = 0; struct price_resolution price; - if ( (price.Pval= val*1000000000) != 0 ) - { - if ( price.Pval > 0xffffffff ) - printf("Pval overflow error %lld\n",(long long)price.Pval); - else val32 = (uint32_t)price.Pval; - } - return(val32); - }*/ +int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals); -int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp) -{ - if ( rwflag != 0 ) - { - memset(pubkey33,0,33); - pubkey33[0] = 0x02 | (*shortflagp != 0); - memcpy(&pubkey33[1],fiat,3); - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); - pubkey33[12] = *addrtypep; - memcpy(&pubkey33[13],rmd160,20); - } - else - { - *shortflagp = (pubkey33[0] == 0x03); - memcpy(fiat,&pubkey33[1],3); - fiat[3] = 0; - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); - if ( *shortflagp != 0 ) - *fiatoshisp = -(*fiatoshisp); - *addrtypep = pubkey33[12]; - memcpy(rmd160,&pubkey33[13],20); - } - return(33); -} +int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); -double PAX_val(uint32_t pval,int32_t baseid) -{ - //printf("PAX_val baseid.%d pval.%u\n",baseid,pval); - if ( baseid >= 0 && baseid < MAX_CURRENCIES ) - return(((double)pval / 1000000000.) / MINDENOMS[baseid]); - return(0.); -} +int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp); -void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) -{ - int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD; - if ( numpvals >= 35 ) - { - for (nonz=i=0; i<32; i++) - { - if ( pvals[i] != 0 ) - nonz++; - //printf("%u ",pvals[i]); - } - if ( nonz == 32 ) - { - kmdbtc = pvals[i++]; - btcusd = pvals[i++]; - cnyusd = pvals[i++]; - KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); - BTCUSD = PAX_BTCUSD(height,btcusd); - CNYUSD = ((double)cnyusd / 1000000000.); - portable_mutex_lock(&komodo_mutex); - PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); - PVALS[36 * NUM_PRICES] = height; - memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); - NUM_PRICES++; - portable_mutex_unlock(&komodo_mutex); - if ( 0 ) - printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d (%llu %llu %llu)\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES,(long long)kmdbtc,(long long)btcusd,(long long)cnyusd); - } - } -} +double PAX_val(uint32_t pval,int32_t baseid); -uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed) -{ - int32_t i,j,k,ind,zeroes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0; - for (sum=i=zeroes=nonz=0; i> 2) ) - return(0); - sum /= nonz; - lastprice = sum; - for (i=0; i (numvotes >> 1) ) - break; - } - } - } - } - if ( wt > (numvotes >> 1) ) - { - ind = i; - for (densum=sum=j=0; j KOMODO_PAXMAX ) - { - printf("paxcalc overflow %.8f\n",dstr(basevolume)); - return(0); - } - if ( (pvalb= pvals[baseid]) != 0 ) - { - if ( relid == MAX_CURRENCIES ) - { - if ( height < 236000 ) - { - if ( kmdbtc == 0 ) - kmdbtc = pvals[MAX_CURRENCIES]; - if ( btcusd == 0 ) - btcusd = pvals[MAX_CURRENCIES + 1]; - } - else - { - if ( (kmdbtc= pvals[MAX_CURRENCIES]) == 0 ) - kmdbtc = refkmdbtc; - if ( (btcusd= pvals[MAX_CURRENCIES + 1]) == 0 ) - btcusd = refbtcusd; - } - if ( kmdbtc < 25000000 ) - kmdbtc = 25000000; - if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 ) - { - baseusd = (((uint64_t)pvalb * 1000000000) / pvals[USD]); - usdvol = komodo_paxvol(basevolume,baseusd); - usdkmd = ((uint64_t)kmdbtc * 1000000000) / btcusd; - if ( height >= 236000-10 ) - { - BTCUSD = PAX_BTCUSD(height,btcusd); - if ( height < BTCFACTOR_HEIGHT || (height < 500000 && BTCUSD > 20000) ) - usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; - else usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; - ///if ( height >= BTCFACTOR_HEIGHT && BTCUSD >= 43 ) - // usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; - //else usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; - price = ((uint64_t)10000000000 * MINDENOMS[USD] / MINDENOMS[baseid]) / komodo_paxvol(usdvol,usdkmd); - //fprintf(stderr,"ht.%d %.3f kmdbtc.%llu btcusd.%llu base -> USD %llu, usdkmd %llu usdvol %llu -> %llu\n",height,BTCUSD,(long long)kmdbtc,(long long)btcusd,(long long)baseusd,(long long)usdkmd,(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); - //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)),(long long)price); - //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); - } else price = (MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)); - return(price); - } //else printf("zero val in KMD conv %llu %llu %llu\n",(long long)pvals[USD],(long long)kmdbtc,(long long)btcusd); - } - else if ( baseid == relid ) - { - if ( baseid != MAX_CURRENCIES ) - { - pax_rank(ranked,pvals); - //printf("%s M1 percentage %.8f\n",CURRENCIES[baseid],dstr(10 * ranked[baseid])); - return(10 * ranked[baseid]); // scaled percentage of M1 total - } else return(basevolume); - } - else if ( (pvalr= pvals[relid]) != 0 ) - { - baserel = ((uint64_t)pvalb * 1000000000) / pvalr; - //printf("baserel.%lld %lld %lld %.8f %.8f\n",(long long)baserel,(long long)MINDENOMS[baseid],(long long)MINDENOMS[relid],dstr(MINDENOMS[baseid]/MINDENOMS[relid]),dstr(MINDENOMS[relid]/MINDENOMS[baseid])); - if ( MINDENOMS[baseid] > MINDENOMS[relid] ) - basevolume /= (MINDENOMS[baseid] / MINDENOMS[relid]); - else if ( MINDENOMS[baseid] < MINDENOMS[relid] ) - basevolume *= (MINDENOMS[relid] / MINDENOMS[baseid]); - return(komodo_paxvol(basevolume,baserel)); - } - else printf("null pval for %s\n",CURRENCIES[relid]); - } else printf("null pval for %s\n",CURRENCIES[baseid]); - return(0); -} +uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed); -uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd) -{ - int32_t baseid=-1,relid=-1,i; uint32_t *ptr,*pvals; - if ( height > 10 ) - height -= 10; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { - //portable_mutex_lock(&komodo_mutex); - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; - if ( *ptr < height ) - { - pvals = &ptr[1]; - if ( kmdbtcp != 0 && btcusdp != 0 ) - { - *kmdbtcp = pvals[MAX_CURRENCIES] / 539; - *btcusdp = pvals[MAX_CURRENCIES + 1] / 539; - } - //portable_mutex_unlock(&komodo_mutex); - if ( kmdbtc != 0 && btcusd != 0 ) - return(komodo_paxcalc(height,pvals,baseid,relid,basevolume,kmdbtc,btcusd)); - else return(0); - } - } - //portable_mutex_unlock(&komodo_mutex); - } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); - return(0); -} +uint64_t komodo_paxcalc(int32_t height,uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t basevolume,uint64_t refkmdbtc,uint64_t refbtcusd); -int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height) -{ - static uint64_t *KMDBTCS,*BTCUSDS; static int32_t maxheight = 0; int32_t incr = 10000; - if ( height >= maxheight ) - { - //printf("height.%d maxheight.%d incr.%d\n",height,maxheight,incr); - if ( height >= maxheight+incr ) - incr = (height - (maxheight+incr) + 1000); - KMDBTCS = (uint64_t *)realloc(KMDBTCS,((incr + maxheight) * sizeof(*KMDBTCS))); - memset(&KMDBTCS[maxheight],0,(incr * sizeof(*KMDBTCS))); - BTCUSDS = (uint64_t *)realloc(BTCUSDS,((incr + maxheight) * sizeof(*BTCUSDS))); - memset(&BTCUSDS[maxheight],0,(incr * sizeof(*BTCUSDS))); - maxheight += incr; - } - if ( rwflag == 0 ) - { - *kmdbtcp = KMDBTCS[height]; - *btcusdp = BTCUSDS[height]; - } - else - { - KMDBTCS[height] = *kmdbtcp; - BTCUSDS[height] = *btcusdp; - } - if ( *kmdbtcp != 0 && *btcusdp != 0 ) - return(0); - else return(-1); -} +uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd); -uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - int32_t i,j,k,ind,zeroes,numvotes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0,votes[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],btcusds[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtcs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtc,btcusd; - if ( basevolume > KOMODO_PAXMAX ) - { - printf("komodo_paxprice overflow %.8f\n",dstr(basevolume)); - return(0); - } - if ( strcmp(base,"KMD") == 0 || strcmp(base,"kmd") == 0 ) - { - printf("kmd cannot be base currency\n"); - return(0); - } - numvotes = (int32_t)(sizeof(Peggy_inds)/sizeof(*Peggy_inds)); - memset(votes,0,sizeof(votes)); - //if ( komodo_kmdbtcusd(0,&kmdbtc,&btcusd,height) < 0 ) crashes when via passthru GUI use - { - memset(btcusds,0,sizeof(btcusds)); - memset(kmdbtcs,0,sizeof(kmdbtcs)); - for (i=0; i> 1) ) - { - return(0); - } - return(komodo_paxcorrelation(votes,numvotes,seed) * basevolume / 100000); -} +int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height); -uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); - if ( height >= 236000 && strcmp(rel,"kmd") == 0 ) - { - usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); - if ( strcmp("usd",base) == 0 ) - return(komodo_paxvol(basevolume,usdkmd) * 10); - baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); - basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; - //if ( strcmp("KMD",base) == 0 ) - // printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); - return(basekmd); - } else return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); -} +uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume); -/*uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); - //if ( strcmp(rel,"KMD") != 0 || baseid < 0 || MINDENOMS[baseid] == MINDENOMS[USD] ) - // return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); - //else - { - baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); - usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); - basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; - if ( strcmp("KMD",base) == 0 ) - printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); - return(basekmd); - } -}*/ +uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume); -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->GetHeight() ) - { - if ( height < 100000000 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->GetHeight()); - } - return(0); - } - *seedp = komodo_seed(height); - portable_mutex_lock(&komodo_mutex); - for (i=0; i<17; i++) - { - if ( (price= komodo_paxpriceB(*seedp,height-i,base,rel,basevolume)) != 0 ) - { - sum += price; - nonz++; - if ( 0 && i == 1 && nonz == 2 ) - { - diff = (((int64_t)price - (sum >> 1)) * 10000); - if ( diff < 0 ) - diff = -diff; - diff /= price; - printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>1),(long long)(((int64_t)price - (sum >> 1)) * 10000),(long long)diff); - if ( diff < 33 ) - break; - } - else if ( 0 && i == 3 && nonz == 4 ) - { - diff = (((int64_t)price - (sum >> 2)) * 10000); - if ( diff < 0 ) - diff = -diff; - diff /= price; - printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>2),(long long) (((int64_t)price - (sum >> 2)) * 10000),(long long)diff); - if ( diff < 20 ) - break; - } - } - if ( height < 165000 || height > 236000 ) - break; - } - portable_mutex_unlock(&komodo_mutex); - if ( nonz != 0 ) - sum /= nonz; - //printf("-> %lld %s/%s i.%d ht.%d\n",(long long)sum,base,rel,i,height); - return(sum); -} +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 baseid=-1,relid=-1,i,num = 0; uint32_t *ptr; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; - heights[num] = *ptr; - prices[num] = komodo_paxcalc(*ptr,&ptr[1],baseid,relid,COIN,0,0); - num++; - if ( num >= max ) - return(num); - } - } - return(num); -} +int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); -void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen) -{ - double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero; - numpvals = dpow_readprices(height,pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals); - memset(&zero,0,sizeof(zero)); - komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0,0,0,zero,0); - if ( 0 ) - { - int32_t i; - for (i=0; i KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); - if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) - { - PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); - bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33); - } - return(komodoshis); -} +uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis); diff --git a/src/komodo_port.c b/src/komodo_port.c index fd68db881dd..f19018eebcc 100644 --- a/src/komodo_port.c +++ b/src/komodo_port.c @@ -17,6 +17,7 @@ #include #include #include +#include "bits256.h" uint64_t ASSETCHAINS_COMMISSION; uint32_t ASSETCHAINS_MAGIC = 2387029918; @@ -24,8 +25,6 @@ uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; }; struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; }; -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; // following is ported from libtom diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp new file mode 100644 index 00000000000..4bd4de3a746 --- /dev/null +++ b/src/komodo_structs.cpp @@ -0,0 +1,347 @@ +/****************************************************************************** + * Copyright © 2021 Komodo Core Deveelopers * + * * + * 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 "komodo_structs.h" +#include "mem_read.h" +#include + +extern std::mutex komodo_mutex; + +/*** + * komodo_state + */ + +bool komodo_state::add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in) +{ + if (ASSETCHAINS_SYMBOL[0] != 0) + { + std::lock_guard lock(komodo_mutex); + events.push_back( in ); + return true; + } + return false; +} + +namespace komodo { + +/*** + * Helps serialize integrals + */ +template +class serializable +{ +public: + serializable(const T& in) : value(in) {} + T value; +}; + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + os << (uint8_t) (in.value & 0x000000ff) + << (uint8_t) ((in.value & 0x0000ff00) >> 8) + << (uint8_t) ((in.value & 0x00ff0000) >> 16) + << (uint8_t) ((in.value & 0xff000000) >> 24); + return os; +} + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + os << (uint8_t) (in.value & 0x00ff) + << (uint8_t) ((in.value & 0xff00) >> 8); + return os; +} + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + in.value.Serialize(os); + return os; +} + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + os << (uint8_t) (in.value & 0x00000000000000ff) + << (uint8_t) ((in.value & 0x000000000000ff00) >> 8) + << (uint8_t) ((in.value & 0x0000000000ff0000) >> 16) + << (uint8_t) ((in.value & 0x00000000ff000000) >> 24) + << (uint8_t) ((in.value & 0x000000ff00000000) >> 32) + << (uint8_t) ((in.value & 0x0000ff0000000000) >> 40) + << (uint8_t) ((in.value & 0x00ff000000000000) >> 48) + << (uint8_t) ((in.value & 0xff00000000000000) >> 56); + return os; +} + +/**** + * This serializes the 5 byte header of an event + * @param os the stream + * @param in the event + * @returns the stream + */ +std::ostream& operator<<(std::ostream& os, const event& in) +{ + switch (in.type) + { + case(EVENT_PUBKEYS): + os << "P"; + break; + case(EVENT_NOTARIZED): + { + event_notarized* tmp = dynamic_cast(const_cast(&in)); + if (tmp->MoMdepth == 0) + os << "N"; + else + os << "M"; + break; + } + case(EVENT_U): + os << "U"; + break; + case(EVENT_KMDHEIGHT): + { + event_kmdheight* tmp = dynamic_cast(const_cast(&in)); + if (tmp->timestamp == 0) + os << "K"; + else + os << "T"; + break; + } + case(EVENT_OPRETURN): + os << "R"; + break; + case(EVENT_PRICEFEED): + os << "V"; + break; + case(EVENT_REWIND): + os << "B"; + break; + } + os << serializable(in.height); + return os; +} + +/*** + * ctor from data stream + * @param data the data stream + * @param pos the starting position (will advance) + * @param data_len full length of data + */ +event_pubkeys::event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t height) : event(EVENT_PUBKEYS, height) +{ + num = data[pos++]; + if (num > 64) + throw parse_error("Illegal number of keys: " + std::to_string(num)); + mem_nread(pubkeys, num, data, pos, data_len); +} + +event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event(EVENT_PUBKEYS, height) +{ + num = fgetc(fp); + if ( fread(pubkeys,33,num,fp) != num ) + throw parse_error("Illegal number of keys: " + std::to_string(num)); +} + +std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) +{ + const event& e = dynamic_cast(in); + os << e; + os << in.num; + for(uint8_t i = 0; i < in.num-1; ++i) + os << in.pubkeys[i]; + return os; +} + +event_rewind::event_rewind(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_REWIND, height) +{ + // nothing to do +} +std::ostream& operator<<(std::ostream& os, const event_rewind& in) +{ + const event& e = dynamic_cast(in); + os << e; + return os; +} + +event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, bool includeMoM) + : event(EVENT_NOTARIZED, height), MoMdepth(0) +{ + MoM.SetNull(); + mem_read(this->notarizedheight, data, pos, data_len); + mem_read(this->blockhash, data, pos, data_len); + mem_read(this->desttxid, data, pos, data_len); + if (includeMoM) + { + mem_read(this->MoM, data, pos, data_len); + mem_read(this->MoMdepth, data, pos, data_len); + } +} + +event_notarized::event_notarized(FILE* fp, int32_t height, bool includeMoM) + : event(EVENT_NOTARIZED, height), MoMdepth(0) +{ + MoM.SetNull(); + if ( fread(¬arizedheight,1,sizeof(notarizedheight),fp) != sizeof(notarizedheight) ) + throw parse_error("Invalid notarization height"); + if ( fread(&blockhash,1,sizeof(blockhash),fp) != sizeof(blockhash) ) + throw parse_error("Invalid block hash"); + if ( fread(&desttxid,1,sizeof(desttxid),fp) != sizeof(desttxid) ) + throw parse_error("Invalid Destination TXID"); + if ( includeMoM ) + { + if ( fread(&MoM,1,sizeof(MoM),fp) != sizeof(MoM) ) + throw parse_error("Invalid MoM"); + if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) + throw parse_error("Invalid MoMdepth"); + } +} + +std::ostream& operator<<(std::ostream& os, const event_notarized& in) +{ + const event& e = dynamic_cast(in); + os << e; + os << serializable(in.notarizedheight); + os << serializable(in.blockhash); + os << serializable(in.desttxid); + if (in.MoMdepth > 0) + { + os << serializable(in.MoM); + os << serializable(in.MoMdepth); + } + return os; +} + +event_u::event_u(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_U, height) +{ + mem_read(this->n, data, pos, data_len); + mem_read(this->nid, data, pos, data_len); + mem_read(this->mask, data, pos, data_len); + mem_read(this->hash, data, pos, data_len); +} + +event_u::event_u(FILE *fp, int32_t height) : event(EVENT_U, height) +{ + if (fread(&n, 1, sizeof(n), fp) != sizeof(n)) + throw parse_error("Unable to read n of event U from file"); + if (fread(&nid, 1, sizeof(nid), fp) != sizeof(n)) + throw parse_error("Unable to read nid of event U from file"); + if (fread(&mask, 1, sizeof(mask), fp) != sizeof(mask)) + throw parse_error("Unable to read mask of event U from file"); + if (fread(&hash, 1, sizeof(hash), fp) != sizeof(hash)) + throw parse_error("Unable to read hash of event U from file"); +} + +std::ostream& operator<<(std::ostream& os, const event_u& in) +{ + const event& e = dynamic_cast(in); + os << e; + os << in.n << in.nid; + os.write((const char*)in.mask, 8); + os.write((const char*)in.hash, 32); + return os; +} + +event_kmdheight::event_kmdheight(uint8_t* data, long &pos, long data_len, int32_t height, bool includeTimestamp) : event(EVENT_KMDHEIGHT, height) +{ + mem_read(this->kheight, data, pos, data_len); + if (includeTimestamp) + mem_read(this->timestamp, data, pos, data_len); +} + +event_kmdheight::event_kmdheight(FILE *fp, int32_t height, bool includeTimestamp) : event(EVENT_KMDHEIGHT, height) +{ + if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) + throw parse_error("Unable to parse KMD height"); + if (includeTimestamp) + { + if ( fread( ×tamp, 1, sizeof(timestamp), fp) != sizeof(timestamp) ) + throw parse_error("Unable to parse timestamp of KMD height"); + } +} + +std::ostream& operator<<(std::ostream& os, const event_kmdheight& in) +{ + const event& e = dynamic_cast(in); + os << e << serializable(in.kheight); + if (in.timestamp > 0) + os << serializable(in.timestamp); + return os; +} + +event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_OPRETURN, height) +{ + mem_read(this->txid, data, pos, data_len); + mem_read(this->vout, data, pos, data_len); + mem_read(this->value, data, pos, data_len); + uint16_t oplen; + mem_read(oplen, data, pos, data_len); + if (oplen <= data_len - pos) + { + this->opret = std::vector( &data[pos], &data[pos] + oplen); + pos += oplen; + } +} + +event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, height) +{ + if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) + throw parse_error("Unable to parse txid of opreturn record"); + if ( fread(&vout,1,sizeof(vout),fp) != sizeof(vout) ) + throw parse_error("Unable to parse vout of opreturn record"); + if ( fread(&value,1,sizeof(value),fp) != sizeof(value) ) + throw parse_error("Unable to parse value of opreturn record"); + uint16_t oplen; + if ( fread(&oplen,1,sizeof(oplen),fp) != sizeof(oplen) ) + throw parse_error("Unable to parse length of opreturn record"); + this->opret.resize(oplen); + if ( fread(this->opret.data(), 1, oplen, fp) != oplen) + throw parse_error("Unable to parse binary data of opreturn"); +} + +std::ostream& operator<<(std::ostream& os, const event_opreturn& in) +{ + const event& e = dynamic_cast(in); + os << e + << serializable(in.txid) + << serializable(in.vout) + << serializable(in.value) + << serializable(in.opret.size()); + os.write( (const char*)in.opret.data(), in.opret.size()); + return os; +} + +event_pricefeed::event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_PRICEFEED, height) +{ + mem_read(this->num, data, pos, data_len); + // we're only interested if there are 35 prices. + // If there is any other amount, advance the pointer, but don't save it + if (this->num == 35) + mem_nread(this->prices, this->num, data, pos, data_len); + else + pos += num * sizeof(uint32_t); +} + +event_pricefeed::event_pricefeed(FILE* fp, int32_t height) : event(EVENT_PRICEFEED, height) +{ + num = fgetc(fp); + if ( num * sizeof(uint32_t) <= sizeof(prices) && fread(prices,sizeof(uint32_t),num,fp) != num ) + throw parse_error("Unable to parse price feed"); +} + +std::ostream& operator<<(std::ostream& os, const event_pricefeed& in) +{ + const event& e = dynamic_cast(in); + os << e << (uint8_t)in.num; + os.write((const char*)in.prices, in.num * sizeof(uint32_t)); + return os; +} + +} // namespace komodo \ No newline at end of file diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 6b7c316b6b9..ba2055956e8 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -12,6 +12,10 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once +#include +#include +#include #include "komodo_defs.h" @@ -48,15 +52,9 @@ #define KOMODO_KVDURATION 1440 #define KOMODO_ASSETCHAIN_MAXLEN 65 -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif - -union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; -typedef union _bits320 bits320; +#include "bits256.h" +// structs prior to refactor struct komodo_kv { UT_hash_handle hh; bits256 pubkey; uint8_t *key,*value; int32_t height; uint32_t flags; uint16_t keylen,valuesize; }; struct komodo_event_notarized { uint256 blockhash,desttxid,MoM; int32_t notarizedheight,MoMdepth; char dest[16]; }; @@ -74,6 +72,160 @@ struct komodo_event uint8_t space[]; }; +namespace komodo { + +enum komodo_event_type +{ + EVENT_PUBKEYS, + EVENT_NOTARIZED, + EVENT_U, + EVENT_KMDHEIGHT, + EVENT_OPRETURN, + EVENT_PRICEFEED, + EVENT_REWIND +}; + +/*** + * Thrown by event constructors when it finds a problem with the input data + */ +class parse_error : public std::logic_error +{ +public: + parse_error(const std::string& in) : std::logic_error(in) {} +}; + +/*** + * base class for events + */ +class event +{ +public: + event(komodo_event_type t, int32_t height) : type(t), height(height) {} + virtual ~event() = default; + komodo_event_type type; + int32_t height; +}; +std::ostream& operator<<(std::ostream& os, const event& in); + +struct event_rewind : public event +{ + event_rewind() : event(komodo_event_type::EVENT_REWIND, 0) {} + event_rewind(int32_t ht) : event(EVENT_REWIND, ht) {} + event_rewind(uint8_t* data, long &pos, long data_len, int32_t height); +}; +std::ostream& operator<<(std::ostream& os, const event_rewind& in); + +struct event_notarized : public event +{ + event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) {} + event_notarized(int32_t ht) : event(EVENT_NOTARIZED, ht), notarizedheight(0), MoMdepth(0) {} + event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, bool includeMoM = false); + event_notarized(FILE* fp, int32_t ht, bool includeMoM = false); + uint256 blockhash; + uint256 desttxid; + uint256 MoM; + int32_t notarizedheight; + int32_t MoMdepth; + char dest[16]; +}; +std::ostream& operator<<(std::ostream& os, const event_notarized& in); + +struct event_pubkeys : public event +{ + /*** + * Default ctor + */ + event_pubkeys() : event(EVENT_PUBKEYS, 0), num(0) + { + memset(pubkeys, 0, 64 * 33); + } + event_pubkeys(int32_t ht) : event(EVENT_PUBKEYS, ht), num(0) + { + memset(pubkeys, 0, 64 * 33); + } + /*** + * ctor from data stream + * @param data the data stream + * @param pos the starting position (will advance) + * @param data_len full length of data + */ + event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); + event_pubkeys(FILE* fp, int32_t height); + uint8_t num = 0; + uint8_t pubkeys[64][33]; +}; +std::ostream& operator<<(std::ostream& os, const event_pubkeys& in); + +struct event_u : public event +{ + event_u() : event(EVENT_U, 0) + { + memset(mask, 0, 8); + memset(hash, 0, 32); + } + event_u(int32_t ht) : event(EVENT_U, ht) + { + memset(mask, 0, 8); + memset(hash, 0, 32); + } + event_u(uint8_t *data, long &pos, long data_len, int32_t height); + event_u(FILE* fp, int32_t height); + uint8_t n = 0; + uint8_t nid = 0; + uint8_t mask[8]; + uint8_t hash[32]; +}; +std::ostream& operator<<(std::ostream& os, const event_u& in); + +struct event_kmdheight : public event +{ + event_kmdheight() : event(EVENT_KMDHEIGHT, 0) {} + event_kmdheight(int32_t ht) : event(EVENT_KMDHEIGHT, ht) {} + event_kmdheight(uint8_t *data, long &pos, long data_len, int32_t height, bool includeTimestamp = false); + event_kmdheight(FILE* fp, int32_t height, bool includeTimestamp = false); + int32_t kheight = 0; + uint32_t timestamp = 0; +}; +std::ostream& operator<<(std::ostream& os, const event_kmdheight& in); + +struct event_opreturn : public event +{ + event_opreturn() : event(EVENT_OPRETURN, 0) + { + txid.SetNull(); + } + event_opreturn(int32_t ht) : event(EVENT_OPRETURN, ht) + { + txid.SetNull(); + } + event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height); + event_opreturn(FILE* fp, int32_t height); + uint256 txid; + uint16_t vout = 0; + uint64_t value = 0; + std::vector opret; +}; +std::ostream& operator<<(std::ostream& os, const event_opreturn& in); + +struct event_pricefeed : public event +{ + event_pricefeed() : event(EVENT_PRICEFEED, 0), num(0) + { + memset(prices, 0, 35); + } + event_pricefeed(int32_t ht) : event(EVENT_PRICEFEED, ht) + { + memset(prices, 0, 35); + } + event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height); + event_pricefeed(FILE* fp, int32_t height); + uint8_t num = 0; + uint32_t prices[35]; +}; +std::ostream& operator<<(std::ostream& os, const event_pricefeed& in); + +} // namespace komodo + struct pax_transaction { UT_hash_handle hh; @@ -122,9 +274,11 @@ struct komodo_state int32_t SAVEDHEIGHT,CURRENT_HEIGHT,NOTARIZED_HEIGHT,MoMdepth; uint32_t SAVEDTIMESTAMP; uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; - struct notarized_checkpoint *NPOINTS; int32_t NUM_NPOINTS,last_NPOINTSi; - struct komodo_event **Komodo_events; int32_t Komodo_numevents; + struct notarized_checkpoint *NPOINTS; + int32_t NUM_NPOINTS,last_NPOINTSi; + std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; + bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); }; #endif /* KOMODO_STRUCTS_H */ diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp new file mode 100644 index 00000000000..36d600c38fb --- /dev/null +++ b/src/komodo_utils.cpp @@ -0,0 +1,2075 @@ +/****************************************************************************** + * 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 "komodo_utils.h" +#include "komodo_extern_globals.h" +#include "komodo_notary.h" + +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) +{ + struct sha256_vstate md; + sha256_vinit(&md); + sha256_vprocess(&md,src,len); + sha256_vdone(&md,hash); +} + +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) +{ + bits256 hash,hash2; int32_t i; + vcalc_sha256(0,hash.bytes,data,datalen); + vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); + for (i=0; i>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) \ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define GG(a, b, c, d, e, x, s) \ +(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define HH(a, b, c, d, e, x, s) \ +(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define II(a, b, c, d, e, x, s) \ +(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define JJ(a, b, c, d, e, x, s) \ +(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define FFF(a, b, c, d, e, x, s) \ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define GGG(a, b, c, d, e, x, s) \ +(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define HHH(a, b, c, d, e, x, s) \ +(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define III(a, b, c, d, e, x, s) \ +(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define JJJ(a, b, c, d, e, x, s) \ +(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) +{ + uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->state[0]; + bb = bbb = md->state[1]; + cc = ccc = md->state[2]; + dd = ddd = md->state[3]; + ee = eee = md->state[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + md->state[1]; /* final result for md->state[0] */ + md->state[1] = md->state[2] + dd + eee; + md->state[2] = md->state[3] + ee + aaa; + md->state[3] = md->state[4] + aa + bbb; + md->state[4] = md->state[0] + bb + ccc; + md->state[0] = ddd; + + return 0; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return 0 if successful + */ +int rmd160_vinit(struct rmd160_vstate * md) +{ + md->state[0] = 0x67452301UL; + md->state[1] = 0xefcdab89UL; + md->state[2] = 0x98badcfeUL; + md->state[3] = 0x10325476UL; + md->state[4] = 0xc3d2e1f0UL; + md->curlen = 0; + md->length = 0; + return 0; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return 0 if successful + */ +int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + int err; + if (md->curlen > sizeof(md->buf)) { + return -1; + } + while (inlen > 0) { + if (md->curlen == 0 && inlen >= 64) { + if ((err = rmd160_vcompress (md, (unsigned char *)in)) != 0) { + return err; + } + md->length += 64 * 8; + in += 64; + inlen -= 64; + } else { + n = MIN(inlen, (64 - md->curlen)); + memcpy(md->buf + md->curlen, in, (size_t)n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == 64) { + if ((err = rmd160_vcompress (md, md->buf)) != 0) { + return err; + } + md->length += 8*64; + md->curlen = 0; + } + } + } + return 0; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return 0 if successful + */ +int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) +{ + int i; + if (md->curlen >= sizeof(md->buf)) { + return -1; + } + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + rmd160_vcompress(md, md->buf); + md->curlen = 0; + } + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + /* store length */ + STORE64L(md->length, md->buf+56); + rmd160_vcompress(md, md->buf); + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32L(md->state[i], out+(4*i)); + } + return 0; +} + +void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) +{ + struct rmd160_vstate md; + rmd160_vinit(&md); + rmd160_vprocess(&md,msg,len); + rmd160_vdone(&md, buf); +} +#undef F +#undef G +#undef H +#undef I +#undef J +#undef ROLc +#undef FF +#undef GG +#undef HH +#undef II +#undef JJ +#undef FFF +#undef GGG +#undef HHH +#undef III +#undef JJJ + +static const uint32_t crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size) +{ + const uint8_t *p; + + p = (const uint8_t *)buf; + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} + +void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) +{ + bits256 hash; + vcalc_sha256(0,hash.bytes,data,datalen); + calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); +} + +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) +{ + bits256 hash; uint8_t *buf,_buf[25]; int32_t len; + memset(rmd160,0,20); + *addrtypep = 0; + buf = _buf; + if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) + { + // validate with trailing hash, then remove hash + hash = bits256_doublesha256(0,buf,21); + *addrtypep = *buf; + memcpy(rmd160,buf+1,20); + if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] ) + { + //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep); + return(20); + } + else + { + int32_t i; + if ( len > 20 ) + { + hash = bits256_doublesha256(0,buf,len); + } + for (i=0; i= 0 ) + return(1); + else return(0); +} + +int32_t bitweight(uint64_t x) +{ + int i,wt = 0; + for (i=0; i<64; i++) + if ( (1LL << i) & x ) + wt++; + return(wt); +} + +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) +{ + int32_t i; uint64_t x; + if ( rwflag == 0 ) + { + x = 0; + for (i=len-1; i>=0; i--) + { + x <<= 8; + x |= serialized[i]; + } + switch ( len ) + { + case 1: *(uint8_t *)endianedp = (uint8_t)x; break; + case 2: *(uint16_t *)endianedp = (uint16_t)x; break; + case 4: *(uint32_t *)endianedp = (uint32_t)x; break; + case 8: *(uint64_t *)endianedp = (uint64_t)x; break; + } + } + else + { + x = 0; + switch ( len ) + { + case 1: x = *(uint8_t *)endianedp; break; + case 2: x = *(uint16_t *)endianedp; break; + case 4: x = *(uint32_t *)endianedp; break; + case 8: x = *(uint64_t *)endianedp; break; + } + for (i=0; i>= 8) + serialized[i] = (uint8_t)(x & 0xff); + } + return(len); +} + +int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) +{ + int32_t i; + if ( rwflag == 0 ) + { + for (i=0; i= 0x4c ) + { + if ( opretlen == 0x4c ) + opretlen = script[len++]; + else if ( opretlen == 0x4d ) + { + opretlen = script[len] + (script[len+1] << 8); + len += 2; + //opretlen = script[len++]; + //opretlen = (opretlen << 8) | script[len++]; + } + } + *opretlenp = opretlen; + return(len); +} + +int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen) +{ + int32_t offset = 0; + script[offset++] = 0x6a; + opretlen++; + if ( opretlen >= 0x4c ) + { + if ( opretlen > 0xff ) + { + script[offset++] = 0x4d; + script[offset++] = opretlen & 0xff; + script[offset++] = (opretlen >> 8) & 0xff; + } + else + { + script[offset++] = 0x4c; + script[offset++] = opretlen; + } + } else script[offset++] = opretlen; + script[offset++] = type; // covered by opretlen + memcpy(&script[offset],opret,opretlen-1); + return(offset + opretlen - 1); +} + +// get a pseudo random number that is the same for each block individually at all times and different +// from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain +uint64_t komodo_block_prg(uint32_t nHeight) +{ + if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) + { + uint64_t i, result = 0, hashSrc64 = ((uint64_t)ASSETCHAINS_MAGIC << 32) | (uint64_t)nHeight; + uint8_t hashSrc[8]; + bits256 hashResult; + + for ( i = 0; i < sizeof(hashSrc); i++ ) + { + uint64_t x = hashSrc64 >> (i * 8); + hashSrc[i] = (uint8_t)(x & 0xff); + } + verus_hash(hashResult.bytes, hashSrc, sizeof(hashSrc)); + for ( i = 0; i < 8; i++ ) + { + result = (result << 8) | hashResult.bytes[i]; + } + return result; + } + else + { + int i; + uint8_t hashSrc[8]; + uint64_t result=0, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight; + bits256 hashResult; + + for ( i = 0; i < sizeof(hashSrc); i++ ) + { + hashSrc[i] = hashSrc64 & 0xff; + hashSrc64 >>= 8; + int8_t b = hashSrc[i]; + } + + vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc)); + for ( i = 0; i < 8; i++ ) + { + result = (result << 8) + hashResult.bytes[i]; + } + return result; + } +} + +// given a block height, this returns the unlock time for that block height, derived from +// the ASSETCHAINS_MAGIC number as well as the block height, providing different random numbers +// for corresponding blocks across chains, but the same sequence in each chain +int64_t komodo_block_unlocktime(uint32_t nHeight) +{ + uint64_t fromTime, toTime, unlocktime; + + if ( ASSETCHAINS_TIMEUNLOCKFROM == ASSETCHAINS_TIMEUNLOCKTO ) + unlocktime = ASSETCHAINS_TIMEUNLOCKTO; + else + { + if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) + { + unlocktime = komodo_block_prg(nHeight) % (ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM); + unlocktime += ASSETCHAINS_TIMEUNLOCKFROM; + } + else + { + unlocktime = komodo_block_prg(nHeight) / (0xffffffffffffffff / ((ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM) + 1)); + // boundary and power of 2 can make it exceed to time by 1 + unlocktime = unlocktime + ASSETCHAINS_TIMEUNLOCKFROM; + if (unlocktime > ASSETCHAINS_TIMEUNLOCKTO) + unlocktime--; + } + } + return ((int64_t)unlocktime); +} + +char *parse_conf_line(char *line,char *field) +{ + line += strlen(field); + for (; *line!='='&&*line!=0; line++) + break; + if ( *line == 0 ) + return(0); + if ( *line == '=' ) + line++; + while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' ) + line[strlen(line)-1] = 0; + //printf("LINE.(%s)\n",line); + _stripwhite(line,0); + return(clonestr(line)); +} + +double OS_milliseconds() +{ + struct timeval tv; double millis; + gettimeofday(&tv,NULL); + millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.); + //printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis); + return(millis); +} + +#ifndef _WIN32 +void OS_randombytes(unsigned char *x,long xlen) +{ + static int fd = -1; + int32_t i; + if (fd == -1) { + for (;;) { + fd = open("/dev/urandom",O_RDONLY); + if (fd != -1) break; + sleep(1); + } + } + while (xlen > 0) { + if (xlen < 1048576) i = (int32_t)xlen; else i = 1048576; + i = (int32_t)read(fd,x,i); + if (i < 1) { + sleep(1); + continue; + } + if ( 0 ) + { + int32_t j; + for (j=0; j %p\n",x); + } + x += i; + xlen -= i; + } +} +#endif + +void lock_queue(queue_t *queue) +{ + if ( queue->initflag == 0 ) + { + portable_mutex_init(&queue->mutex); + queue->initflag = 1; + } + portable_mutex_lock(&queue->mutex); +} + +void queue_enqueue(char *name,queue_t *queue,struct queueitem *item) +{ + if ( queue->name[0] == 0 && name != 0 && name[0] != 0 ) + strcpy(queue->name,name); + if ( item == 0 ) + { + printf("FATAL type error: queueing empty value\n"); + return; + } + lock_queue(queue); + DL_APPEND(queue->list,item); + portable_mutex_unlock(&queue->mutex); +} + +struct queueitem *queue_dequeue(queue_t *queue) +{ + struct queueitem *item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + item = queue->list; + DL_DELETE(queue->list,item); + } + portable_mutex_unlock(&queue->mutex); + return(item); +} + +void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize) +{ + struct queueitem *item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + DL_FOREACH(queue->list,item) + { + #ifdef _WIN32 + if ( item == copy || (item->allocsize == copysize && memcmp((void *)((intptr_t)item + sizeof(struct queueitem)),(void *)((intptr_t)copy + sizeof(struct queueitem)),copysize) == 0) ) + #else + if ( item == copy || (item->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)copy + sizeof(struct queueitem)),copysize) == 0) ) + #endif + { + DL_DELETE(queue->list,item); + portable_mutex_unlock(&queue->mutex); + printf("name.(%s) deleted item.%p list.%p\n",queue->name,item,queue->list); + return(item); + } + } + } + portable_mutex_unlock(&queue->mutex); + return(0); +} + +void *queue_free(queue_t *queue) +{ + struct queueitem *item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + DL_FOREACH(queue->list,item) + { + DL_DELETE(queue->list,item); + free(item); + } + //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); + } + portable_mutex_unlock(&queue->mutex); + return(0); +} + +void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) +{ + struct queueitem *ptr,*item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + DL_FOREACH(queue->list,item) + { + ptr = (struct queueitem *)calloc(1,sizeof(*ptr)); + memcpy(ptr,item,size); + queue_enqueue(queue->name,clone,ptr); + } + //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); + } + portable_mutex_unlock(&queue->mutex); + return(0); +} + +int32_t queue_size(queue_t *queue) +{ + int32_t count = 0; + struct queueitem *tmp; + lock_queue(queue); + DL_COUNT(queue->list,tmp,count); + portable_mutex_unlock(&queue->mutex); + return count; +} + +void iguana_initQ(queue_t *Q,char *name) +{ + struct queueitem *item,*I; + memset(Q,0,sizeof(*Q)); + I = (struct queueitem *)calloc(1,sizeof(*I)); + strcpy(Q->name,name); + queue_enqueue(name,Q,I); + if ( (item= queue_dequeue(Q)) != 0 ) + free(item); +} + +uint16_t _komodo_userpass(char *username,char *password,FILE *fp) +{ + char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0; + rpcuser = rpcpassword = 0; + username[0] = password[0] = 0; + while ( fgets(line,sizeof(line),fp) != 0 ) + { + if ( line[0] == '#' ) + continue; + //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); + if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) + rpcuser = parse_conf_line(str,(char *)"rpcuser"); + else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) + rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); + else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) + { + port = atoi(parse_conf_line(str,(char *)"rpcport")); + //fprintf(stderr,"rpcport.%u in file\n",port); + } + } + if ( rpcuser != 0 && rpcpassword != 0 ) + { + strcpy(username,rpcuser); + strcpy(password,rpcpassword); + } + //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); + if ( rpcuser != 0 ) + free(rpcuser); + if ( rpcpassword != 0 ) + free(rpcpassword); + return(port); +} + +void komodo_statefname(char *fname,char *symbol,char *str) +{ + int32_t n,len; + sprintf(fname,"%s",GetDataDir(false).string().c_str()); + if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 ) + { + len = (int32_t)strlen(fname); + if ( !mapArgs.count("-datadir") && strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 ) + fname[len - n] = 0; + else if(mapArgs.count("-datadir")) printf("DEBUG - komodo_utils:1363: custom datadir\n"); + else + { + if ( strcmp(symbol,"REGTEST") != 0 ) + printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]); + return; + } + } + else + { +#ifdef _WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + } + if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 ) + { + if(!mapArgs.count("-datadir")) strcat(fname,symbol); + //printf("statefname.(%s) -> (%s)\n",symbol,fname); +#ifdef _WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + } + strcat(fname,str); + //printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); +} + +void komodo_configfile(char *symbol,uint16_t rpcport) +{ + static char myusername[512],mypassword[8192]; + FILE *fp; uint16_t kmdport; uint8_t buf2[33]; char fname[512],buf[128],username[512],password[8192]; uint32_t crc,r,r2,i; + if ( symbol != 0 && rpcport != 0 ) + { + r = (uint32_t)time(NULL); + r2 = OS_milliseconds(); + memcpy(buf,&r,sizeof(r)); + memcpy(&buf[sizeof(r)],&r2,sizeof(r2)); + memcpy(&buf[sizeof(r)+sizeof(r2)],symbol,strlen(symbol)); + crc = calc_crc32(0,(uint8_t *)buf,(int32_t)(sizeof(r)+sizeof(r2)+strlen(symbol))); + #ifdef _WIN32 + randombytes_buf(buf2,sizeof(buf2)); + #else + OS_randombytes(buf2,sizeof(buf2)); + #endif + for (i=0; i userpass.(%s)\n",fname,KMDUSERPASS); + } //else printf("couldnt open.(%s)\n",fname); +} + +uint16_t komodo_userpass(char *userpass,char *symbol) +{ + FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; + userpass[0] = 0; + if ( strcmp("KMD",symbol) == 0 ) + { +#ifdef __APPLE__ + sprintf(confname,"Komodo.conf"); +#else + sprintf(confname,"komodo.conf"); +#endif + } + else if(!mapArgs.count("-conf")) { + sprintf(confname,"%s.conf",symbol); + komodo_statefname(fname,symbol,confname); + } else sprintf(fname,"%s",GetDataDir().string().c_str()); + + if ( (fp= fopen(fname,"rb")) != 0 ) + { + port = _komodo_userpass(username,password,fp); + sprintf(userpass,"%s:%s",username,password); + if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) + strcpy(ASSETCHAINS_USERPASS,userpass); + fclose(fp); + } + return(port); +} + +uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) +{ + uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; + if ( strcmp(symbol,"KMD") == 0 ) + return(0x8de4eef9); + len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); + strcpy((char *)&buf[len],symbol); + len += strlen(symbol); + if ( extraptr != 0 && extralen != 0 ) + { + vcalc_sha256(0,hash.bytes,extraptr,extralen); + crc0 = hash.uints[0]; + int32_t i; for (i=0; i nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 ) + break; + } + } + if ( curEra <= ASSETCHAINS_LASTERA ) + { + int64_t nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0; + subsidy = (int64_t)ASSETCHAINS_REWARD[curEra]; + if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) ) + { + if ( ASSETCHAINS_HALVING[curEra] != 0 ) + { + if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) + { + if ( ASSETCHAINS_DECAY[curEra] == 0 ) + subsidy >>= numhalvings; + else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) + { + if ( curEra == ASSETCHAINS_LASTERA ) + { + subsidyDifference = subsidy; + } + else + { + // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 + subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1]; + if (subsidyDifference < 0) + { + sign = -1; + subsidyDifference *= sign; + } + } + denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart; + numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra])); + subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator); + } + else + { + if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings ) + subsidy = cached_subsidy; + else + { + for (int i=0; i < numhalvings && subsidy != 0; i++) + subsidy = (subsidy * ASSETCHAINS_DECAY[curEra]) / 100000000; + cached_subsidy = subsidy; + cached_numhalvings = numhalvings; + cached_era = curEra; + } + } + } + } + } + } + } + uint32_t magicExtra = ASSETCHAINS_STAKED ? ASSETCHAINS_MAGIC : (ASSETCHAINS_MAGIC & 0xffffff); + if ( ASSETCHAINS_SUPPLY > 10000000000 ) // over 10 billion? + { + if ( nHeight <= ASSETCHAINS_SUPPLY/1000000000 ) + { + subsidy += (uint64_t)1000000000 * COIN; + if ( nHeight == 1 ) + subsidy += (ASSETCHAINS_SUPPLY % 1000000000)*COIN + magicExtra; + } + } + else if ( nHeight == 1 ) + { + if ( ASSETCHAINS_LASTERA == 0 ) + subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; + else + subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; + } + else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) + return(0); + // LABS fungible chains, cannot have any block reward! + return(subsidy); +} + +extern int64_t MAX_MONEY; +void komodo_cbopretupdate(int32_t forceflag); +void SplitStr(const std::string& strVal, std::vector &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) +{ + 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, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; + + std::string ntz_dest_path; + ntz_dest_path = GetArg("-notary", ""); + IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; + + + STAKED_NOTARY_ID = GetArg("-stakednotary", -1); + KOMODO_NSPV = GetArg("-nSPV",0); + memset(ccenables,0,sizeof(ccenables)); + memset(disablebits,0,sizeof(disablebits)); + memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); + if ( GetBoolArg("-gen", false) != 0 ) + { + KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); + } + DONATION_PUBKEY = GetArg("-donation", ""); + NOTARY_PUBKEY = GetArg("-pubkey", ""); + IS_KOMODO_DEALERNODE = GetArg("-dealer",0); + IS_KOMODO_TESTNODE = GetArg("-testnode",0); + ASSETCHAINS_STAKED_SPLIT_PERCENTAGE = GetArg("-splitperc",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 ) + { + // 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_elected[kmd_season-1][i][1]) == 0 ) + { + IS_KOMODO_NOTARY = true; + KOMODO_MININGTHREADS = 1; + mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); + STAKED_NOTARY_ID = -1; + fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[kmd_season-1][i][0]); + break; + } + } + } + } + if ( STAKED_NOTARY_ID != -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 ) + { + len = (int32_t)strlen(argv0); + for (i=0; i matches suffix (%s) -> ac_name.(%s)\n",argv0,argv0suffix[i],argv0names[i]); + name = argv0names[i]; + break; + } + } + } + KOMODO_STOPAT = GetArg("-stopat",0); + MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); + WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; + ASSETCHAINS_CC = GetArg("-ac_cc",0); + KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); + 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",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); + + // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... + Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), 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 ( i > 1 && ccEnablesHeight[i-2] == ecode ) + break; + if ( ecode > 255 || ecode < 0 ) + 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])); + + for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) + { + if (std::string(ASSETCHAINS_ALGORITHMS[i]) == selectedAlgo) + { + ASSETCHAINS_ALGO = i; + STAKING_MIN_DIFF = ASSETCHAINS_MINDIFF[i]; + // only worth mentioning if it's not equihash + if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH) + printf("ASSETCHAINS_ALGO, algorithm set to %s\n", selectedAlgo.c_str()); + 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()); + } + + ASSETCHAINS_LASTERA = GetArg("-ac_eras", 1); + if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS ) + { + ASSETCHAINS_LASTERA = 1; + printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA); + } + ASSETCHAINS_LASTERA -= 1; + + ASSETCHAINS_TIMELOCKGTE = (uint64_t)GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF); + ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0); + ASSETCHAINS_TIMEUNLOCKTO = GetArg("-ac_timeunlockto", 0); + if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO ) + { + printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n"); + ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; + ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; + } + + Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); + Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); + Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); + Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); + Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); + + for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) + { + if ( ASSETCHAINS_DECAY[i] == 100000000 && ASSETCHAINS_ENDSUBSIDY == 0 ) + { + ASSETCHAINS_DECAY[i] = 0; + printf("ERA%u: ASSETCHAINS_DECAY of 100000000 means linear and that needs ASSETCHAINS_ENDSUBSIDY\n", i); + } + else if ( ASSETCHAINS_DECAY[i] > 100000000 ) + { + ASSETCHAINS_DECAY[i] = 0; + printf("ERA%u: ASSETCHAINS_DECAY cant be more than 100000000\n", i); + } + } + + MAX_BLOCK_SIGOPS = 60000; + ASSETCHAINS_TXPOW = GetArg("-ac_txpow",0) & 3; + ASSETCHAINS_FOUNDERS = GetArg("-ac_founders",0);// & 1; + ASSETCHAINS_FOUNDERS_REWARD = GetArg("-ac_founders_reward",0); + ASSETCHAINS_SUPPLY = GetArg("-ac_supply",10); + if ( ASSETCHAINS_SUPPLY > (uint64_t)90*1000*1000000 ) + { + fprintf(stderr,"-ac_supply must be less than 90 billion\n"); + StartShutdown(); + } + fprintf(stderr,"ASSETCHAINS_SUPPLY %llu\n",(long long)ASSETCHAINS_SUPPLY); + + ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0); + ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); + ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); + ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); + ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); + ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0); + ASSETCHAINS_CBMATURITY = GetArg("-ac_cbmaturity",0); + ASSETCHAINS_ADAPTIVEPOW = GetArg("-ac_adaptivepow",0); + //fprintf(stderr,"ASSETCHAINS_CBOPRET.%llx\n",(long long)ASSETCHAINS_CBOPRET); + if ( ASSETCHAINS_CBOPRET != 0 ) + { + SplitStr(GetArg("-ac_prices",""), ASSETCHAINS_PRICES); + if ( ASSETCHAINS_PRICES.size() > 0 ) + ASSETCHAINS_CBOPRET |= 4; + SplitStr(GetArg("-ac_stocks",""), ASSETCHAINS_STOCKS); + if ( ASSETCHAINS_STOCKS.size() > 0 ) + ASSETCHAINS_CBOPRET |= 8; + for (i=0; i 0 ) + { + for (i=0; i<256; i++) + { + ASSETCHAINS_CCDISABLES[i] = 1; + SETBIT(disablebits,i); + } + for (i=0; i 0 ) + { + for (i=first; i<=last; i++) + { + CLEARBIT(disablebits,i); + ASSETCHAINS_CCDISABLES[i] = 0; + } + }*/ + } + if ( ASSETCHAINS_BEAMPORT != 0 ) + { + fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); + StartShutdown(); + } + ASSETCHAINS_SELFIMPORT = GetArg("-ac_import",""); // BEAM, CODA, PUBKEY, GATEWAY + if ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) + { + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) != 66 ) + { + fprintf(stderr,"invalid -ac_pubkey for -ac_import=PUBKEY\n"); + StartShutdown(); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "BEAM" ) + { + if (ASSETCHAINS_BEAMPORT == 0) + { + fprintf(stderr,"missing -ac_beam for BEAM rpcport\n"); + StartShutdown(); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "CODA" ) + { + if (ASSETCHAINS_CODAPORT == 0) + { + fprintf(stderr,"missing -ac_coda for CODA rpcport\n"); + StartShutdown(); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") + { + Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); + if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) + { + fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); + StartShutdown(); + } + } + // else it can be gateway coin + else if (!ASSETCHAINS_SELFIMPORT.empty() && (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_SUPPLY>0 || 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; + + // for now, we only support 50% PoS due to other parts of the algorithm needing adjustment for + // other values + if ( (ASSETCHAINS_LWMAPOS = GetArg("-ac_veruspos",0)) != 0 ) + { + ASSETCHAINS_LWMAPOS = 50; + } + ASSETCHAINS_SAPLING = GetArg("-ac_sapling", -1); + if (ASSETCHAINS_SAPLING == -1) + { + ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", -1); + } + else + { + ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", ASSETCHAINS_SAPLING); + } + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + if ( ASSETCHAINS_SUPPLY > 10000000000 ) + { + printf("ac_pubkey or ac_script wont work with ac_supply over 10 billion\n"); + StartShutdown(); + } + if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) + { + printf("Assetchains NOTARY PAY cannot be used with ac_pubkey or ac_script.\n"); + StartShutdown(); + } + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 ) + { + decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str()); + calc_rmd160_sha256(ASSETCHAINS_OVERRIDE_PUBKEYHASH,ASSETCHAINS_OVERRIDE_PUBKEY33,33); + } + if ( ASSETCHAINS_COMMISSION == 0 && ASSETCHAINS_FOUNDERS != 0 ) + { + if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) + { + ASSETCHAINS_COMMISSION = 53846154; // maps to 35% + printf("ASSETCHAINS_COMMISSION defaulted to 35%% when founders reward active\n"); + } + else + { + printf("ASSETCHAINS_FOUNDERS_REWARD set to %ld\n", ASSETCHAINS_FOUNDERS_REWARD); + } + /*else if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) + { + //ASSETCHAINS_OVERRIDE_PUBKEY.clear(); + printf("-ac_perc must be set with -ac_pubkey\n"); + }*/ + } + } + else + { + if ( ASSETCHAINS_COMMISSION != 0 ) + { + ASSETCHAINS_COMMISSION = 0; + printf("ASSETCHAINS_COMMISSION needs an ASSETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); + } + if ( ASSETCHAINS_FOUNDERS != 0 ) + { + ASSETCHAINS_FOUNDERS = 0; + printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); + } + } + 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 || 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 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 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; + memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; + + // if we have one era, this should create the same data structure as it used to, same if we increase _MAX_ERAS + for ( int i = 0; i <= ASSETCHAINS_LASTERA; i++ ) + { + printf("ERA%u: end.%llu reward.%llu halving.%llu decay.%llu notarypay.%llu\n", i, + (long long)ASSETCHAINS_ENDSUBSIDY[i], + (long long)ASSETCHAINS_REWARD[i], + (long long)ASSETCHAINS_HALVING[i], + (long long)ASSETCHAINS_DECAY[i], + (long long)ASSETCHAINS_NOTARY_PAY[i]); + + // TODO: Verify that we don't overrun extrabuf here, which is a 256 byte buffer + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]); + if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]); + } + + if (ASSETCHAINS_LASTERA > 0) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LASTERA),(void *)&ASSETCHAINS_LASTERA); + } + + // hash in lock above for time locked coinbase transactions above a certain reward value only if the lock above + // param was specified, otherwise, for compatibility, do nothing + if ( ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF ) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMELOCKGTE),(void *)&ASSETCHAINS_TIMELOCKGTE); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKFROM),(void *)&ASSETCHAINS_TIMEUNLOCKFROM); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKTO),(void *)&ASSETCHAINS_TIMEUNLOCKTO); + } + + if ( ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH ) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); + } + + if ( ASSETCHAINS_LWMAPOS != 0 ) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); + } + + val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); + + if ( ASSETCHAINS_FOUNDERS != 0 ) + { + uint8_t tmp = 1; + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp); + if ( ASSETCHAINS_FOUNDERS > 1 ) + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS); + if ( ASSETCHAINS_FOUNDERS_REWARD != 0 ) + { + fprintf(stderr, "set founders reward.%lld\n",(long long)ASSETCHAINS_FOUNDERS_REWARD); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD); + } + } + if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + extralen += ASSETCHAINS_SCRIPTPUB.size()/2; + //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); + fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); + } + if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) + { + memcpy(&extraptr[extralen],(char *)ASSETCHAINS_SELFIMPORT.c_str(),ASSETCHAINS_SELFIMPORT.size()); + for (i=0; i 0 ) + { + memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); + extralen += sizeof(disablebits); + } + if ( ASSETCHAINS_CCLIB.size() > 1 ) + { + for (i=0; i 0 ) + ASSETCHAINS_SEED = 1; + + strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); + + MAX_MONEY = komodo_max_money(); + + if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) + { + //komodo_maxallowed(baseid); + printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); + } + + if ( ASSETCHAINS_CC >= KOMODO_FIRSTFUNGIBLEID && MAX_MONEY < 1000000LL*SATOSHIDEN ) + MAX_MONEY = 1000000LL*SATOSHIDEN; + if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) + MAX_MONEY = KOMODO_MAXNVALUE; + fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); + //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); + uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); + if ( GetArg("-port",0) != 0 ) + { + ASSETCHAINS_P2PPORT = GetArg("-port",0); + fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); + } else ASSETCHAINS_P2PPORT = tmpport; + + while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) + { + fprintf(stderr,"waiting for datadir (%s)\n",dirname); +#ifndef _WIN32 + sleep(3); +#else + boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); +#endif + } + //fprintf(stderr,"Got datadir.(%s)\n",dirname); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + int32_t komodo_baseid(char *origbase); + extern int COINBASE_MATURITY; + if ( strcmp(ASSETCHAINS_SYMBOL,"KMD") == 0 ) + { + fprintf(stderr,"cant have assetchain named KMD\n"); + StartShutdown(); + } + if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) + ASSETCHAINS_RPCPORT = port; + else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); + + if (ASSETCHAINS_CBMATURITY != 0) + COINBASE_MATURITY = ASSETCHAINS_CBMATURITY; + else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0) + COINBASE_MATURITY = 1; + if (COINBASE_MATURITY < 1) + { + fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); + StartShutdown(); + } + //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); + } + if ( ASSETCHAINS_RPCPORT == 0 ) + ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; + //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); + //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); + iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); + for (i=0; i<4; i++) + sprintf(&magicstr[i<<1],"%02x",magic[i]); + magicstr[8] = 0; +#ifndef FROM_CLI + sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + 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); +#endif + if ( ASSETCHAINS_CC < 2 ) + { + if ( KOMODO_CCACTIVATE != 0 ) + { + ASSETCHAINS_CC = 2; + fprintf(stderr,"smart utxo CC contracts will activate at height.%d\n",KOMODO_CCACTIVATE); + } + else if ( ccEnablesHeight[0] != 0 ) + { + ASSETCHAINS_CC = 2; + fprintf(stderr,"smart utxo CC contract %d will activate at height.%d\n",(int32_t)ccEnablesHeight[0],(int32_t)ccEnablesHeight[1]); + } + } + } + else + { + char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; + ASSETCHAINS_P2PPORT = 7770; + ASSETCHAINS_RPCPORT = 7771; + for (iter=0; iter<2; iter++) + { + strcpy(fname,GetDataDir().string().c_str()); +#ifdef _WIN32 + while ( fname[strlen(fname)-1] != '\\' ) + fname[strlen(fname)-1] = 0; + if ( iter == 0 ) + strcat(fname,"Komodo\\komodo.conf"); + else strcat(fname,ntz_dest_path.c_str()); +#else + while ( fname[strlen(fname)-1] != '/' ) + fname[strlen(fname)-1] = 0; +#ifdef __APPLE__ + if ( iter == 0 ) + strcat(fname,"Komodo/Komodo.conf"); + else strcat(fname,ntz_dest_path.c_str()); +#else + if ( iter == 0 ) + strcat(fname,".komodo/komodo.conf"); + else strcat(fname,ntz_dest_path.c_str()); +#endif +#endif + if ( (fp= fopen(fname,"rb")) != 0 ) + { + dest_rpc_port = _komodo_userpass(username,password,fp); + DEST_PORT = iter == 1 ? dest_rpc_port : 0; + sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); + fclose(fp); + } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); + if ( !IS_KOMODO_NOTARY ) + break; + } + } + int32_t dpowconfs = KOMODO_DPOWCONFS; + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); + //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); + if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) + { + ASSETCHAINS_HALVING[0] *= 5; + fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%llu\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,(long long)ASSETCHAINS_LASTERA); + } + else if ( strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 ) + dpowconfs = 0; + else if ( ASSETCHAINS_PRIVATE != 0 ) + { + 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; + CCENABLE(EVAL_TOKENS); + CCENABLE(EVAL_HEIR); + } + 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 ) + KOMODO_EXTRASATOSHI = 1; +} + +void komodo_nameset(char *symbol,char *dest,char *source) +{ + if ( source[0] == 0 ) + { + strcpy(symbol,(char *)"KMD"); + strcpy(dest,(char *)"BTC"); + } + else + { + strcpy(symbol,source); + strcpy(dest,(char *)"KMD"); + } +} + +struct komodo_state *komodo_stateptrget(char *base) +{ + int32_t baseid; + if ( base == 0 || base[0] == 0 || strcmp(base,(char *)"KMD") == 0 ) + return(&KOMODO_STATES[33]); + else if ( (baseid= komodo_baseid(base)) >= 0 ) + return(&KOMODO_STATES[baseid+1]); + else return(&KOMODO_STATES[0]); +} + +struct komodo_state *komodo_stateptr(char *symbol,char *dest) +{ + int32_t baseid; + komodo_nameset(symbol,dest,ASSETCHAINS_SYMBOL); + return(komodo_stateptrget(symbol)); +} + +void komodo_prefetch(FILE *fp) +{ + long fsize,fpos; int32_t incr = 16*1024*1024; + fpos = ftell(fp); + fseek(fp,0,SEEK_END); + fsize = ftell(fp); + if ( fsize > incr ) + { + char *ignore = (char *)malloc(incr); + if ( ignore != 0 ) + { + rewind(fp); + while ( fread(ignore,1,incr,fp) == incr ) // prefetch + fprintf(stderr,"."); + free(ignore); + } + } + fseek(fp,fpos,SEEK_SET); +} + +// check if block timestamp is more than S5 activation time +// this function is to activate the ExtractDestination fix +bool komodo_is_vSolutionsFixActive() +{ + return GetLatestTimestamp(komodo_currentheight()) > nS5Timestamp; +} diff --git a/src/komodo_utils.h b/src/komodo_utils.h index f21241cccc2..6e3053b34a4 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -12,7 +12,9 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once #include "komodo_defs.h" +#include "hex.h" #include "key_io.h" #include "cc/CCinclude.h" #include @@ -42,7 +44,7 @@ typedef struct queue char name[64],initflag; } queue_t; -#include "mini-gmp.c" +#include "mini-gmp.h" #define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" @@ -275,341 +277,16 @@ static inline int32_t sha256_vdone(struct sha256_vstate *md,uint8_t *out) return(0); } -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) -{ - struct sha256_vstate md; - sha256_vinit(&md); - sha256_vprocess(&md,src,len); - sha256_vdone(&md,hash); -} - -bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) -{ - bits256 hash,hash2; int32_t i; - vcalc_sha256(0,hash.bytes,data,datalen); - vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); - for (i=0; i>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define II(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define FFF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GGG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HHH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define III(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) -{ - uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; - int i; +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = aaa = md->state[0]; - bb = bbb = md->state[1]; - cc = ccc = md->state[2]; - dd = ddd = md->state[3]; - ee = eee = md->state[4]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); - - /* combine results */ - ddd += cc + md->state[1]; /* final result for md->state[0] */ - md->state[1] = md->state[2] + dd + eee; - md->state[2] = md->state[3] + ee + aaa; - md->state[3] = md->state[4] + aa + bbb; - md->state[4] = md->state[0] + bb + ccc; - md->state[0] = ddd; - - return 0; -} +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); /** Initialize the hash state @param md The hash state you wish to initialize @return 0 if successful */ -int rmd160_vinit(struct rmd160_vstate * md) -{ - md->state[0] = 0x67452301UL; - md->state[1] = 0xefcdab89UL; - md->state[2] = 0x98badcfeUL; - md->state[3] = 0x10325476UL; - md->state[4] = 0xc3d2e1f0UL; - md->curlen = 0; - md->length = 0; - return 0; -} -#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ -int func_name (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) \ -{ \ -unsigned long n; \ -int err; \ -if (md->curlen > sizeof(md->buf)) { \ -return -1; \ -} \ -while (inlen > 0) { \ -if (md->curlen == 0 && inlen >= block_size) { \ -if ((err = compress_name (md, (unsigned char *)in)) != 0) { \ -return err; \ -} \ -md->length += block_size * 8; \ -in += block_size; \ -inlen -= block_size; \ -} else { \ -n = MIN(inlen, (block_size - md->curlen)); \ -memcpy(md->buf + md->curlen, in, (size_t)n); \ -md->curlen += n; \ -in += n; \ -inlen -= n; \ -if (md->curlen == block_size) { \ -if ((err = compress_name (md, md->buf)) != 0) { \ -return err; \ -} \ -md->length += 8*block_size; \ -md->curlen = 0; \ -} \ -} \ -} \ -return 0; \ -} +int rmd160_vinit(struct rmd160_vstate * md); /** Process a block of memory though the hash @@ -618,7 +295,7 @@ return 0; @param inlen The length of the data (octets) @return 0 if successful */ -HASH_PROCESS(rmd160_vprocess, rmd160_vcompress, rmd160, 64) +int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen); /** Terminate the hash to get the digest @@ -626,1881 +303,93 @@ HASH_PROCESS(rmd160_vprocess, rmd160_vcompress, rmd160, 64) @param out [out] The destination of the hash (20 bytes) @return 0 if successful */ -int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) -{ - int i; - if (md->curlen >= sizeof(md->buf)) { - return -1; - } - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char)0; - } - rmd160_vcompress(md, md->buf); - md->curlen = 0; - } - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char)0; - } - /* store length */ - STORE64L(md->length, md->buf+56); - rmd160_vcompress(md, md->buf); - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32L(md->state[i], out+(4*i)); - } - return 0; -} - -void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) -{ - struct rmd160_vstate md; - rmd160_vinit(&md); - rmd160_vprocess(&md,msg,len); - rmd160_vdone(&md, buf); -} -#undef F -#undef G -#undef H -#undef I -#undef J -#undef ROLc -#undef FF -#undef GG -#undef HH -#undef II -#undef JJ -#undef FFF -#undef GGG -#undef HHH -#undef III -#undef JJJ - -static const uint32_t crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size) -{ - const uint8_t *p; - - p = (const uint8_t *)buf; - crc = crc ^ ~0U; - - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); +int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out); - return crc ^ ~0U; -} +void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len); -void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) -{ - bits256 hash; - vcalc_sha256(0,hash.bytes,data,datalen); - calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); -} +uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size); -int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) -{ - bits256 hash; uint8_t *buf,_buf[25]; int32_t len; - memset(rmd160,0,20); - *addrtypep = 0; - buf = _buf; - if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) - { - // validate with trailing hash, then remove hash - hash = bits256_doublesha256(0,buf,21); - *addrtypep = *buf; - memcpy(rmd160,buf+1,20); - if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] ) - { - //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep); - return(20); - } - else - { - int32_t i; - if ( len > 20 ) - { - hash = bits256_doublesha256(0,buf,len); - } - for (i=0; i= 0 ) - return(1); - else return(0); -} +char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -int32_t bitweight(uint64_t x) -{ - int i,wt = 0; - for (i=0; i<64; i++) - if ( (1LL << i) & x ) - wt++; - return(wt); -} +int32_t komodo_is_issuer(); -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} +int32_t bitweight(uint64_t x); -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} +char *bits256_str(char hexstr[65],bits256 x); -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } +int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} +// get a pseudo random number that is the same for each block individually at all times and different +// from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain +uint64_t komodo_block_prg(uint32_t nHeight); -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} +// given a block height, this returns the unlock time for that block height, derived from +// the ASSETCHAINS_MAGIC number as well as the block height, providing different random numbers +// for corresponding blocks across chains, but the same sequence in each chain +int64_t komodo_block_unlocktime(uint32_t nHeight); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) -{ - int32_t i; uint64_t x; - if ( rwflag == 0 ) - { - x = 0; - for (i=len-1; i>=0; i--) - { - x <<= 8; - x |= serialized[i]; - } - switch ( len ) - { - case 1: *(uint8_t *)endianedp = (uint8_t)x; break; - case 2: *(uint16_t *)endianedp = (uint16_t)x; break; - case 4: *(uint32_t *)endianedp = (uint32_t)x; break; - case 8: *(uint64_t *)endianedp = (uint64_t)x; break; - } - } - else - { - x = 0; - switch ( len ) - { - case 1: x = *(uint8_t *)endianedp; break; - case 2: x = *(uint16_t *)endianedp; break; - case 4: x = *(uint32_t *)endianedp; break; - case 8: x = *(uint64_t *)endianedp; break; - } - for (i=0; i>= 8) - serialized[i] = (uint8_t)(x & 0xff); - } - return(len); -} +char *parse_conf_line(char *line,char *field); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) -{ - int32_t i; - if ( rwflag == 0 ) - { - for (i=0; i= 0x4c ) - { - if ( opretlen == 0x4c ) - opretlen = script[len++]; - else if ( opretlen == 0x4d ) - { - opretlen = script[len] + (script[len+1] << 8); - len += 2; - //opretlen = script[len++]; - //opretlen = (opretlen << 8) | script[len++]; - } - } - *opretlenp = opretlen; - return(len); -} +void lock_queue(queue_t *queue); -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen) -{ - int32_t offset = 0; - script[offset++] = 0x6a; - opretlen++; - if ( opretlen >= 0x4c ) - { - if ( opretlen > 0xff ) - { - script[offset++] = 0x4d; - script[offset++] = opretlen & 0xff; - script[offset++] = (opretlen >> 8) & 0xff; - } - else - { - script[offset++] = 0x4c; - script[offset++] = opretlen; - } - } else script[offset++] = opretlen; - script[offset++] = type; // covered by opretlen - memcpy(&script[offset],opret,opretlen-1); - return(offset + opretlen - 1); -} +void queue_enqueue(char *name,queue_t *queue,struct queueitem *item); -// get a pseudo random number that is the same for each block individually at all times and different -// from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain -uint64_t komodo_block_prg(uint32_t nHeight) -{ - if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) - { - uint64_t i, result = 0, hashSrc64 = ((uint64_t)ASSETCHAINS_MAGIC << 32) | (uint64_t)nHeight; - uint8_t hashSrc[8]; - bits256 hashResult; +struct queueitem *queue_dequeue(queue_t *queue); - for ( i = 0; i < sizeof(hashSrc); i++ ) - { - uint64_t x = hashSrc64 >> (i * 8); - hashSrc[i] = (uint8_t)(x & 0xff); - } - verus_hash(hashResult.bytes, hashSrc, sizeof(hashSrc)); - for ( i = 0; i < 8; i++ ) - { - result = (result << 8) | hashResult.bytes[i]; - } - return result; - } - else - { - int i; - uint8_t hashSrc[8]; - uint64_t result=0, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight; - bits256 hashResult; +void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize); - for ( i = 0; i < sizeof(hashSrc); i++ ) - { - hashSrc[i] = hashSrc64 & 0xff; - hashSrc64 >>= 8; - int8_t b = hashSrc[i]; - } +void *queue_free(queue_t *queue); - vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc)); - for ( i = 0; i < 8; i++ ) - { - result = (result << 8) + hashResult.bytes[i]; - } - return result; - } -} +void *queue_clone(queue_t *clone,queue_t *queue,int32_t size); -// given a block height, this returns the unlock time for that block height, derived from -// the ASSETCHAINS_MAGIC number as well as the block height, providing different random numbers -// for corresponding blocks across chains, but the same sequence in each chain -int64_t komodo_block_unlocktime(uint32_t nHeight) -{ - uint64_t fromTime, toTime, unlocktime; +int32_t queue_size(queue_t *queue); - if ( ASSETCHAINS_TIMEUNLOCKFROM == ASSETCHAINS_TIMEUNLOCKTO ) - unlocktime = ASSETCHAINS_TIMEUNLOCKTO; - else - { - if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) - { - unlocktime = komodo_block_prg(nHeight) % (ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM); - unlocktime += ASSETCHAINS_TIMEUNLOCKFROM; - } - else - { - unlocktime = komodo_block_prg(nHeight) / (0xffffffffffffffff / ((ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM) + 1)); - // boundary and power of 2 can make it exceed to time by 1 - unlocktime = unlocktime + ASSETCHAINS_TIMEUNLOCKFROM; - if (unlocktime > ASSETCHAINS_TIMEUNLOCKTO) - unlocktime--; - } - } - return ((int64_t)unlocktime); -} +void iguana_initQ(queue_t *Q,char *name); -long _stripwhite(char *buf,int accept) -{ - int32_t i,j,c; - if ( buf == 0 || buf[0] == 0 ) - return(0); - for (i=j=0; buf[i]!=0; i++) - { - buf[j] = c = buf[i]; - if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) - j++; - } - buf[j] = 0; - return(j); -} +uint16_t _komodo_userpass(char *username,char *password,FILE *fp); -char *clonestr(char *str) -{ - char *clone; - if ( str == 0 || str[0] == 0 ) - { - printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif - str = (char *)""; - } - clone = (char *)malloc(strlen(str)+16); - strcpy(clone,str); - return(clone); -} +void komodo_statefname(char *fname,char *symbol,char *str); -int32_t safecopy(char *dest,char *src,long len) -{ - int32_t i = -1; - if ( src != 0 && dest != 0 && src != dest ) - { - if ( dest != 0 ) - memset(dest,0,len); - for (i=0; i 0) { - if (xlen < 1048576) i = (int32_t)xlen; else i = 1048576; - i = (int32_t)read(fd,x,i); - if (i < 1) { - sleep(1); - continue; - } - if ( 0 ) - { - int32_t j; - for (j=0; j %p\n",x); - } - x += i; - xlen -= i; - } -} -#endif +uint16_t komodo_assetport(uint32_t magic,int32_t extralen); -void lock_queue(queue_t *queue) -{ - if ( queue->initflag == 0 ) - { - portable_mutex_init(&queue->mutex); - queue->initflag = 1; - } - portable_mutex_lock(&queue->mutex); -} +uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extraptr,int32_t extralen); -void queue_enqueue(char *name,queue_t *queue,struct queueitem *item) -{ - if ( queue->name[0] == 0 && name != 0 && name[0] != 0 ) - strcpy(queue->name,name); - if ( item == 0 ) - { - printf("FATAL type error: queueing empty value\n"); - return; - } - lock_queue(queue); - DL_APPEND(queue->list,item); - portable_mutex_unlock(&queue->mutex); -} +int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -struct queueitem *queue_dequeue(queue_t *queue) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - item = queue->list; - DL_DELETE(queue->list,item); - } - portable_mutex_unlock(&queue->mutex); - return(item); -} +uint64_t komodo_max_money(); -void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - #ifdef _WIN32 - if ( item == copy || (item->allocsize == copysize && memcmp((void *)((intptr_t)item + sizeof(struct queueitem)),(void *)((intptr_t)copy + sizeof(struct queueitem)),copysize) == 0) ) - #else - if ( item == copy || (item->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)copy + sizeof(struct queueitem)),copysize) == 0) ) - #endif - { - DL_DELETE(queue->list,item); - portable_mutex_unlock(&queue->mutex); - printf("name.(%s) deleted item.%p list.%p\n",queue->name,item,queue->list); - return(item); - } - } - } - portable_mutex_unlock(&queue->mutex); - return(0); -} +uint64_t komodo_ac_block_subsidy(int nHeight); -void *queue_free(queue_t *queue) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - DL_DELETE(queue->list,item); - free(item); - } - //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); - } - portable_mutex_unlock(&queue->mutex); - return(0); -} +int8_t equihash_params_possible(uint64_t n, uint64_t k); -void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) -{ - struct queueitem *ptr,*item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - ptr = (struct queueitem *)calloc(1,sizeof(*ptr)); - memcpy(ptr,item,size); - queue_enqueue(queue->name,clone,ptr); - } - //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); - } - portable_mutex_unlock(&queue->mutex); - return(0); -} +void komodo_args(char *argv0); -int32_t queue_size(queue_t *queue) -{ - int32_t count = 0; - struct queueitem *tmp; - lock_queue(queue); - DL_COUNT(queue->list,tmp,count); - portable_mutex_unlock(&queue->mutex); - return count; -} +void komodo_nameset(char *symbol,char *dest,char *source); -void iguana_initQ(queue_t *Q,char *name) -{ - struct queueitem *item,*I; - memset(Q,0,sizeof(*Q)); - I = (struct queueitem *)calloc(1,sizeof(*I)); - strcpy(Q->name,name); - queue_enqueue(name,Q,I); - if ( (item= queue_dequeue(Q)) != 0 ) - free(item); -} +struct komodo_state *komodo_stateptrget(char *base); -uint16_t _komodo_userpass(char *username,char *password,FILE *fp) -{ - char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0; - rpcuser = rpcpassword = 0; - username[0] = password[0] = 0; - while ( fgets(line,sizeof(line),fp) != 0 ) - { - if ( line[0] == '#' ) - continue; - //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); - if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) - rpcuser = parse_conf_line(str,(char *)"rpcuser"); - else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) - rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); - else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) - { - port = atoi(parse_conf_line(str,(char *)"rpcport")); - //fprintf(stderr,"rpcport.%u in file\n",port); - } - } - if ( rpcuser != 0 && rpcpassword != 0 ) - { - strcpy(username,rpcuser); - strcpy(password,rpcpassword); - } - //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); - if ( rpcuser != 0 ) - free(rpcuser); - if ( rpcpassword != 0 ) - free(rpcpassword); - return(port); -} +struct komodo_state *komodo_stateptr(char *symbol,char *dest); -void komodo_statefname(char *fname,char *symbol,char *str) -{ - int32_t n,len; - sprintf(fname,"%s",GetDataDir(false).string().c_str()); - if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 ) - { - len = (int32_t)strlen(fname); - if ( !mapArgs.count("-datadir") && strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 ) - fname[len - n] = 0; - else if(mapArgs.count("-datadir")) printf("DEBUG - komodo_utils:1363: custom datadir\n"); - else - { - if ( strcmp(symbol,"REGTEST") != 0 ) - printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]); - return; - } - } - else - { -#ifdef _WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - } - if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 ) - { - if(!mapArgs.count("-datadir")) strcat(fname,symbol); - //printf("statefname.(%s) -> (%s)\n",symbol,fname); -#ifdef _WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - } - strcat(fname,str); - //printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); -} - -void komodo_configfile(char *symbol,uint16_t rpcport) -{ - static char myusername[512],mypassword[8192]; - FILE *fp; uint16_t kmdport; uint8_t buf2[33]; char fname[512],buf[128],username[512],password[8192]; uint32_t crc,r,r2,i; - if ( symbol != 0 && rpcport != 0 ) - { - r = (uint32_t)time(NULL); - r2 = OS_milliseconds(); - memcpy(buf,&r,sizeof(r)); - memcpy(&buf[sizeof(r)],&r2,sizeof(r2)); - memcpy(&buf[sizeof(r)+sizeof(r2)],symbol,strlen(symbol)); - crc = calc_crc32(0,(uint8_t *)buf,(int32_t)(sizeof(r)+sizeof(r2)+strlen(symbol))); - #ifdef _WIN32 - randombytes_buf(buf2,sizeof(buf2)); - #else - OS_randombytes(buf2,sizeof(buf2)); - #endif - for (i=0; i userpass.(%s)\n",fname,KMDUSERPASS); - } //else printf("couldnt open.(%s)\n",fname); -} - -uint16_t komodo_userpass(char *userpass,char *symbol) -{ - FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; - userpass[0] = 0; - if ( strcmp("KMD",symbol) == 0 ) - { -#ifdef __APPLE__ - sprintf(confname,"Komodo.conf"); -#else - sprintf(confname,"komodo.conf"); -#endif - } - else if(!mapArgs.count("-conf")) { - sprintf(confname,"%s.conf",symbol); - komodo_statefname(fname,symbol,confname); - } else sprintf(fname,"%s",GetDataDir().string().c_str()); - - if ( (fp= fopen(fname,"rb")) != 0 ) - { - port = _komodo_userpass(username,password,fp); - sprintf(userpass,"%s:%s",username,password); - if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) - strcpy(ASSETCHAINS_USERPASS,userpass); - fclose(fp); - } - return(port); -} - -uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) -{ - uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; - if ( strcmp(symbol,"KMD") == 0 ) - return(0x8de4eef9); - len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); - strcpy((char *)&buf[len],symbol); - len += strlen(symbol); - if ( extraptr != 0 && extralen != 0 ) - { - vcalc_sha256(0,hash.bytes,extraptr,extralen); - crc0 = hash.uints[0]; - int32_t i; for (i=0; i nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 ) - break; - } - } - if ( curEra <= ASSETCHAINS_LASTERA ) - { - int64_t nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0; - subsidy = (int64_t)ASSETCHAINS_REWARD[curEra]; - if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) ) - { - if ( ASSETCHAINS_HALVING[curEra] != 0 ) - { - if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) - { - if ( ASSETCHAINS_DECAY[curEra] == 0 ) - subsidy >>= numhalvings; - else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) - { - if ( curEra == ASSETCHAINS_LASTERA ) - { - subsidyDifference = subsidy; - } - else - { - // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 - subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1]; - if (subsidyDifference < 0) - { - sign = -1; - subsidyDifference *= sign; - } - } - denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart; - numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra])); - subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator); - } - else - { - if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings ) - subsidy = cached_subsidy; - else - { - for (int i=0; i < numhalvings && subsidy != 0; i++) - subsidy = (subsidy * ASSETCHAINS_DECAY[curEra]) / 100000000; - cached_subsidy = subsidy; - cached_numhalvings = numhalvings; - cached_era = curEra; - } - } - } - } - } - } - } - uint32_t magicExtra = ASSETCHAINS_STAKED ? ASSETCHAINS_MAGIC : (ASSETCHAINS_MAGIC & 0xffffff); - if ( ASSETCHAINS_SUPPLY > 10000000000 ) // over 10 billion? - { - if ( nHeight <= ASSETCHAINS_SUPPLY/1000000000 ) - { - subsidy += (uint64_t)1000000000 * COIN; - if ( nHeight == 1 ) - subsidy += (ASSETCHAINS_SUPPLY % 1000000000)*COIN + magicExtra; - } - } - else if ( nHeight == 1 ) - { - if ( ASSETCHAINS_LASTERA == 0 ) - subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; - else - subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; - } - else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) - return(0); - // LABS fungible chains, cannot have any block reward! - return(subsidy); -} - -extern int64_t MAX_MONEY; -void komodo_cbopretupdate(int32_t forceflag); -void SplitStr(const std::string& strVal, std::vector &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) -{ - 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, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; - - std::string ntz_dest_path; - ntz_dest_path = GetArg("-notary", ""); - IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; - - - IS_STAKED_NOTARY = GetArg("-stakednotary", -1); - KOMODO_NSPV = GetArg("-nSPV",0); - memset(ccenables,0,sizeof(ccenables)); - memset(disablebits,0,sizeof(disablebits)); - memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); - if ( GetBoolArg("-gen", false) != 0 ) - { - KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); - } - if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 ) - fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n"); - DONATION_PUBKEY = GetArg("-donation", ""); - NOTARY_PUBKEY = GetArg("-pubkey", ""); - KOMODO_DEALERNODE = GetArg("-dealer",0); - KOMODO_TESTNODE = GetArg("-testnode",0); - ASSETCHAINS_STAKED_SPLIT_PERCENTAGE = GetArg("-splitperc",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_elected[kmd_season-1][i][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_elected[kmd_season-1][i][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 ) - { - len = (int32_t)strlen(argv0); - for (i=0; i matches suffix (%s) -> ac_name.(%s)\n",argv0,argv0suffix[i],argv0names[i]); - name = argv0names[i]; - break; - } - } - } - KOMODO_STOPAT = GetArg("-stopat",0); - MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); - WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; - ASSETCHAINS_CC = GetArg("-ac_cc",0); - KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); - 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",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); - - // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... - Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), 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 ( i > 1 && ccEnablesHeight[i-2] == ecode ) - break; - if ( ecode > 255 || ecode < 0 ) - 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])); - - for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) - { - if (std::string(ASSETCHAINS_ALGORITHMS[i]) == selectedAlgo) - { - ASSETCHAINS_ALGO = i; - STAKING_MIN_DIFF = ASSETCHAINS_MINDIFF[i]; - // only worth mentioning if it's not equihash - if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH) - printf("ASSETCHAINS_ALGO, algorithm set to %s\n", selectedAlgo.c_str()); - 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()); - } - - ASSETCHAINS_LASTERA = GetArg("-ac_eras", 1); - if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS ) - { - ASSETCHAINS_LASTERA = 1; - printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA); - } - ASSETCHAINS_LASTERA -= 1; - - ASSETCHAINS_TIMELOCKGTE = (uint64_t)GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF); - ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0); - ASSETCHAINS_TIMEUNLOCKTO = GetArg("-ac_timeunlockto", 0); - if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO ) - { - printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n"); - ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; - ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; - } - - Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); - Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); - Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); - Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); - Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); - - for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) - { - if ( ASSETCHAINS_DECAY[i] == 100000000 && ASSETCHAINS_ENDSUBSIDY == 0 ) - { - ASSETCHAINS_DECAY[i] = 0; - printf("ERA%u: ASSETCHAINS_DECAY of 100000000 means linear and that needs ASSETCHAINS_ENDSUBSIDY\n", i); - } - else if ( ASSETCHAINS_DECAY[i] > 100000000 ) - { - ASSETCHAINS_DECAY[i] = 0; - printf("ERA%u: ASSETCHAINS_DECAY cant be more than 100000000\n", i); - } - } - - MAX_BLOCK_SIGOPS = 60000; - ASSETCHAINS_TXPOW = GetArg("-ac_txpow",0) & 3; - ASSETCHAINS_FOUNDERS = GetArg("-ac_founders",0);// & 1; - ASSETCHAINS_FOUNDERS_REWARD = GetArg("-ac_founders_reward",0); - ASSETCHAINS_SUPPLY = GetArg("-ac_supply",10); - if ( ASSETCHAINS_SUPPLY > (uint64_t)90*1000*1000000 ) - { - fprintf(stderr,"-ac_supply must be less than 90 billion\n"); - StartShutdown(); - } - fprintf(stderr,"ASSETCHAINS_SUPPLY %llu\n",(long long)ASSETCHAINS_SUPPLY); - - ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0); - ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); - ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); - ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); - ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); - ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0); - ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0); - ASSETCHAINS_CBMATURITY = GetArg("-ac_cbmaturity",0); - ASSETCHAINS_ADAPTIVEPOW = GetArg("-ac_adaptivepow",0); - //fprintf(stderr,"ASSETCHAINS_CBOPRET.%llx\n",(long long)ASSETCHAINS_CBOPRET); - if ( ASSETCHAINS_CBOPRET != 0 ) - { - SplitStr(GetArg("-ac_prices",""), ASSETCHAINS_PRICES); - if ( ASSETCHAINS_PRICES.size() > 0 ) - ASSETCHAINS_CBOPRET |= 4; - SplitStr(GetArg("-ac_stocks",""), ASSETCHAINS_STOCKS); - if ( ASSETCHAINS_STOCKS.size() > 0 ) - ASSETCHAINS_CBOPRET |= 8; - for (i=0; i 0 ) - { - for (i=0; i<256; i++) - { - ASSETCHAINS_CCDISABLES[i] = 1; - SETBIT(disablebits,i); - } - for (i=0; i 0 ) - { - for (i=first; i<=last; i++) - { - CLEARBIT(disablebits,i); - ASSETCHAINS_CCDISABLES[i] = 0; - } - }*/ - } - if ( ASSETCHAINS_BEAMPORT != 0 ) - { - fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); - StartShutdown(); - } - ASSETCHAINS_SELFIMPORT = GetArg("-ac_import",""); // BEAM, CODA, PUBKEY, GATEWAY - if ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) - { - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) != 66 ) - { - fprintf(stderr,"invalid -ac_pubkey for -ac_import=PUBKEY\n"); - StartShutdown(); - } - } - else if ( ASSETCHAINS_SELFIMPORT == "BEAM" ) - { - if (ASSETCHAINS_BEAMPORT == 0) - { - fprintf(stderr,"missing -ac_beam for BEAM rpcport\n"); - StartShutdown(); - } - } - else if ( ASSETCHAINS_SELFIMPORT == "CODA" ) - { - if (ASSETCHAINS_CODAPORT == 0) - { - fprintf(stderr,"missing -ac_coda for CODA rpcport\n"); - StartShutdown(); - } - } - else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") - { - Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); - if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) - { - fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); - StartShutdown(); - } - } - // else it can be gateway coin - else if (!ASSETCHAINS_SELFIMPORT.empty() && (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_SUPPLY>0 || 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; - - // for now, we only support 50% PoS due to other parts of the algorithm needing adjustment for - // other values - if ( (ASSETCHAINS_LWMAPOS = GetArg("-ac_veruspos",0)) != 0 ) - { - ASSETCHAINS_LWMAPOS = 50; - } - ASSETCHAINS_SAPLING = GetArg("-ac_sapling", -1); - if (ASSETCHAINS_SAPLING == -1) - { - ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", -1); - } - else - { - ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", ASSETCHAINS_SAPLING); - } - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - if ( ASSETCHAINS_SUPPLY > 10000000000 ) - { - printf("ac_pubkey or ac_script wont work with ac_supply over 10 billion\n"); - StartShutdown(); - } - if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) - { - printf("Assetchains NOTARY PAY cannot be used with ac_pubkey or ac_script.\n"); - StartShutdown(); - } - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 ) - { - decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str()); - calc_rmd160_sha256(ASSETCHAINS_OVERRIDE_PUBKEYHASH,ASSETCHAINS_OVERRIDE_PUBKEY33,33); - } - if ( ASSETCHAINS_COMMISSION == 0 && ASSETCHAINS_FOUNDERS != 0 ) - { - if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) - { - ASSETCHAINS_COMMISSION = 53846154; // maps to 35% - printf("ASSETCHAINS_COMMISSION defaulted to 35%% when founders reward active\n"); - } - else - { - printf("ASSETCHAINS_FOUNDERS_REWARD set to %ld\n", ASSETCHAINS_FOUNDERS_REWARD); - } - /*else if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) - { - //ASSETCHAINS_OVERRIDE_PUBKEY.clear(); - printf("-ac_perc must be set with -ac_pubkey\n"); - }*/ - } - } - else - { - if ( ASSETCHAINS_COMMISSION != 0 ) - { - ASSETCHAINS_COMMISSION = 0; - printf("ASSETCHAINS_COMMISSION needs an ASSETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); - } - if ( ASSETCHAINS_FOUNDERS != 0 ) - { - ASSETCHAINS_FOUNDERS = 0; - printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); - } - } - if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_MARMARA != 0 ) - { - 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 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 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; - memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; - - // if we have one era, this should create the same data structure as it used to, same if we increase _MAX_ERAS - for ( int i = 0; i <= ASSETCHAINS_LASTERA; i++ ) - { - printf("ERA%u: end.%llu reward.%llu halving.%llu decay.%llu notarypay.%llu\n", i, - (long long)ASSETCHAINS_ENDSUBSIDY[i], - (long long)ASSETCHAINS_REWARD[i], - (long long)ASSETCHAINS_HALVING[i], - (long long)ASSETCHAINS_DECAY[i], - (long long)ASSETCHAINS_NOTARY_PAY[i]); - - // TODO: Verify that we don't overrun extrabuf here, which is a 256 byte buffer - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]); - if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]); - } - - if (ASSETCHAINS_LASTERA > 0) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LASTERA),(void *)&ASSETCHAINS_LASTERA); - } - - // hash in lock above for time locked coinbase transactions above a certain reward value only if the lock above - // param was specified, otherwise, for compatibility, do nothing - if ( ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF ) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMELOCKGTE),(void *)&ASSETCHAINS_TIMELOCKGTE); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKFROM),(void *)&ASSETCHAINS_TIMEUNLOCKFROM); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKTO),(void *)&ASSETCHAINS_TIMEUNLOCKTO); - } - - if ( ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH ) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); - } - - if ( ASSETCHAINS_LWMAPOS != 0 ) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); - } - - val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); - - if ( ASSETCHAINS_FOUNDERS != 0 ) - { - uint8_t tmp = 1; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp); - if ( ASSETCHAINS_FOUNDERS > 1 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS); - if ( ASSETCHAINS_FOUNDERS_REWARD != 0 ) - { - fprintf(stderr, "set founders reward.%lld\n",(long long)ASSETCHAINS_FOUNDERS_REWARD); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD); - } - } - if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); - extralen += ASSETCHAINS_SCRIPTPUB.size()/2; - //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); - fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); - } - if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) - { - memcpy(&extraptr[extralen],(char *)ASSETCHAINS_SELFIMPORT.c_str(),ASSETCHAINS_SELFIMPORT.size()); - for (i=0; i 0 ) - { - memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); - extralen += sizeof(disablebits); - } - if ( ASSETCHAINS_CCLIB.size() > 1 ) - { - for (i=0; i 0 ) - ASSETCHAINS_SEED = 1; - - strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); - - MAX_MONEY = komodo_max_money(); - - if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) - { - //komodo_maxallowed(baseid); - printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - } - - if ( ASSETCHAINS_CC >= KOMODO_FIRSTFUNGIBLEID && MAX_MONEY < 1000000LL*SATOSHIDEN ) - MAX_MONEY = 1000000LL*SATOSHIDEN; - if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) - MAX_MONEY = KOMODO_MAXNVALUE; - fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); - //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); - if ( GetArg("-port",0) != 0 ) - { - ASSETCHAINS_P2PPORT = GetArg("-port",0); - fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); - } else ASSETCHAINS_P2PPORT = tmpport; - - while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) - { - fprintf(stderr,"waiting for datadir (%s)\n",dirname); -#ifndef _WIN32 - sleep(3); -#else - boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); -#endif - } - //fprintf(stderr,"Got datadir.(%s)\n",dirname); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - int32_t komodo_baseid(char *origbase); - extern int COINBASE_MATURITY; - if ( strcmp(ASSETCHAINS_SYMBOL,"KMD") == 0 ) - { - fprintf(stderr,"cant have assetchain named KMD\n"); - StartShutdown(); - } - if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) - ASSETCHAINS_RPCPORT = port; - else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); - - if (ASSETCHAINS_CBMATURITY != 0) - COINBASE_MATURITY = ASSETCHAINS_CBMATURITY; - else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0) - COINBASE_MATURITY = 1; - if (COINBASE_MATURITY < 1) - { - fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); - StartShutdown(); - } - //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); - } - if ( ASSETCHAINS_RPCPORT == 0 ) - ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; - //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); - //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); - iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); - for (i=0; i<4; i++) - sprintf(&magicstr[i<<1],"%02x",magic[i]); - magicstr[8] = 0; -#ifndef FROM_CLI - sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - 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); -#endif - if ( ASSETCHAINS_CC < 2 ) - { - if ( KOMODO_CCACTIVATE != 0 ) - { - ASSETCHAINS_CC = 2; - fprintf(stderr,"smart utxo CC contracts will activate at height.%d\n",KOMODO_CCACTIVATE); - } - else if ( ccEnablesHeight[0] != 0 ) - { - ASSETCHAINS_CC = 2; - fprintf(stderr,"smart utxo CC contract %d will activate at height.%d\n",(int32_t)ccEnablesHeight[0],(int32_t)ccEnablesHeight[1]); - } - } - } - else - { - char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; - ASSETCHAINS_P2PPORT = 7770; - ASSETCHAINS_RPCPORT = 7771; - for (iter=0; iter<2; iter++) - { - strcpy(fname,GetDataDir().string().c_str()); -#ifdef _WIN32 - while ( fname[strlen(fname)-1] != '\\' ) - fname[strlen(fname)-1] = 0; - if ( iter == 0 ) - strcat(fname,"Komodo\\komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - while ( fname[strlen(fname)-1] != '/' ) - fname[strlen(fname)-1] = 0; -#ifdef __APPLE__ - if ( iter == 0 ) - strcat(fname,"Komodo/Komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - if ( iter == 0 ) - strcat(fname,".komodo/komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#endif -#endif - if ( (fp= fopen(fname,"rb")) != 0 ) - { - dest_rpc_port = _komodo_userpass(username,password,fp); - DEST_PORT = iter == 1 ? dest_rpc_port : 0; - sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); - fclose(fp); - } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); - if ( IS_KOMODO_NOTARY == 0 ) - break; - } - } - int32_t dpowconfs = KOMODO_DPOWCONFS; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); - //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); - if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) - { - ASSETCHAINS_HALVING[0] *= 5; - fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%llu\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,(long long)ASSETCHAINS_LASTERA); - } - else if ( strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 ) - dpowconfs = 0; - else if ( ASSETCHAINS_PRIVATE != 0 ) - { - 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; - CCENABLE(EVAL_TOKENS); - CCENABLE(EVAL_HEIR); - } - 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 ) - KOMODO_EXTRASATOSHI = 1; -} - -void komodo_nameset(char *symbol,char *dest,char *source) -{ - if ( source[0] == 0 ) - { - strcpy(symbol,(char *)"KMD"); - strcpy(dest,(char *)"BTC"); - } - else - { - strcpy(symbol,source); - strcpy(dest,(char *)"KMD"); - } -} - -struct komodo_state *komodo_stateptrget(char *base) -{ - int32_t baseid; - if ( base == 0 || base[0] == 0 || strcmp(base,(char *)"KMD") == 0 ) - return(&KOMODO_STATES[33]); - else if ( (baseid= komodo_baseid(base)) >= 0 ) - return(&KOMODO_STATES[baseid+1]); - else return(&KOMODO_STATES[0]); -} - -struct komodo_state *komodo_stateptr(char *symbol,char *dest) -{ - int32_t baseid; - komodo_nameset(symbol,dest,ASSETCHAINS_SYMBOL); - return(komodo_stateptrget(symbol)); -} - -void komodo_prefetch(FILE *fp) -{ - long fsize,fpos; int32_t incr = 16*1024*1024; - fpos = ftell(fp); - fseek(fp,0,SEEK_END); - fsize = ftell(fp); - if ( fsize > incr ) - { - char *ignore = (char *)malloc(incr); - if ( ignore != 0 ) - { - rewind(fp); - while ( fread(ignore,1,incr,fp) == incr ) // prefetch - fprintf(stderr,"."); - free(ignore); - } - } - fseek(fp,fpos,SEEK_SET); -} +void komodo_prefetch(FILE *fp); // check if block timestamp is more than S5 activation time // this function is to activate the ExtractDestination fix -bool komodo_is_vSolutionsFixActive() -{ - return GetLatestTimestamp(komodo_currentheight()) > nS5Timestamp; -} +bool komodo_is_vSolutionsFixActive(); diff --git a/src/main.cpp b/src/main.cpp index 7d0d52424ed..de26d1a6057 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,6 +50,7 @@ #include "wallet/asyncrpcoperation_sendmany.h" #include "wallet/asyncrpcoperation_shieldcoinbase.h" #include "notaries_staked.h" +#include "komodo_extern_globals.h" #include #include @@ -646,7 +647,6 @@ CBlockTreeDB *pblocktree = NULL; // Komodo globals -#define KOMODO_ZCASH #include "komodo.h" UniValue komodo_snapshot(int top) @@ -1158,10 +1158,6 @@ bool ContextualCheckCoinbaseTransaction(int32_t slowflag,const CBlock *block,CBl } } return(false); - } - else if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) - { - } else if ( slowflag != 0 && ASSETCHAINS_CBOPRET != 0 && validateprices != 0 && nHeight > 0 && tx.vout.size() > 0 ) { @@ -3777,6 +3773,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001); blockReward += nFees + sum; + if ( ASSETCHAINS_SYMBOL[0] == 0 && pindex->GetHeight() >= KOMODO_NOTARIES_HEIGHT2) + blockReward -= sum; + if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && { uint64_t checktoshis; @@ -3803,7 +3802,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), blockReward), REJECT_INVALID, "bad-cb-amount"); - } else if ( IS_KOMODO_NOTARY != 0 ) + } else if ( IS_KOMODO_NOTARY ) fprintf(stderr,"allow nHeight.%d coinbase %.8f vs %.8f interest %.8f\n",(int32_t)pindex->GetHeight(),dstr(block.vtx[0].GetValueOut()),dstr(blockReward),dstr(sum)); } if (!control.Wait()) @@ -6014,6 +6013,13 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) return true; } +/**** + * Open a file + * @param pos where to position for the next read + * @param prefix the type of file (i.e. "blk", "rev", etc. + * @param fReadOnly open in read only mode + * @returns the file pointer or NULL on error + */ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { static int32_t didinit[256]; @@ -6021,9 +6027,9 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) return NULL; boost::filesystem::path path = GetBlockPosFilename(pos, prefix); boost::filesystem::create_directories(path.parent_path()); - FILE* file = fopen(path.string().c_str(), "rb+"); + FILE* file = fopen(path.string().c_str(), "rb+"); // open existing file for reading and writing if (!file && !fReadOnly) - file = fopen(path.string().c_str(), "wb+"); + file = fopen(path.string().c_str(), "wb+"); // create an empty file for reading and writing if (!file) { LogPrintf("Unable to open file %s\n", path.string()); return NULL; @@ -6043,14 +6049,32 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) return file; } +/*** + * Open a block file + * @param pos where to position for the next read + * @param fReadOnly true to open the file in read only mode + * @returns the file pointer or NULL on error + */ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "blk", fReadOnly); } +/*** + * Open an undo ("rev") file + * @param pos where to position for the next read + * @param fReadOnly true to open the file in read only mode + * @returns the file pointer or NULL on error + */ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "rev", fReadOnly); } +/*** + * Get the full filename (including path) or a specific .dat file + * @param pos the block position + * @param prefix the prefix (i.e. "blk" or "rev") + * @returns the filename with the complete path + */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) { return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile); @@ -6543,6 +6567,10 @@ void UnloadBlockIndex() fHavePruned = false; } +/*** + * Load block index + * @returns true on success + */ bool LoadBlockIndex() { // Load block index from databases @@ -7728,12 +7756,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } pfrom->PushMessage("headers", vHeaders); } - /*else if ( IS_KOMODO_NOTARY != 0 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->GetHeight() : -1),pfrom->lasthdrsreq); - }*/ } diff --git a/src/mem_read.h b/src/mem_read.h new file mode 100644 index 00000000000..be041607c66 --- /dev/null +++ b/src/mem_read.h @@ -0,0 +1,65 @@ +#pragma once +/****************************************************************************** + * Copyright © 2021 Komodo Core Deveelopers * + * * + * 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 "komodo_structs.h" // for parse_error + +#include +#include + +/*** + * These read a chunk of memory with some built-in type safety + */ + +template +std::size_t mem_read(T& dest, uint8_t *filedata, long &fpos, long datalen) +{ + if (fpos + sizeof(T) <= datalen) + { + memcpy( &dest, &filedata[fpos], sizeof(T) ); + fpos += sizeof(T); + return sizeof(T); + } + throw komodo::parse_error("Invalid size: " + std::to_string(sizeof(T)) ); +} + +template +std::size_t mem_read(T(&dest)[N], uint8_t *filedata, long& fpos, long datalen) +{ + std::size_t sz = sizeof(T) * N; + if (fpos + sz <= datalen) + { + memcpy( &dest, &filedata[fpos], sz ); + fpos += sz; + return sz; + } + throw komodo::parse_error("Invalid size: " + std::to_string( sz ) ); +} + +/**** + * Read a size that is less than the array length + */ +template +std::size_t mem_nread(T(&dest)[N], size_t num_elements, uint8_t *filedata, long& fpos, long datalen) +{ + std::size_t sz = sizeof(T) * num_elements; + if (fpos + sz <= datalen) + { + memcpy( &dest, &filedata[fpos], sz ); + fpos += sz; + return sz; + } + throw komodo::parse_error("Invalid size: " + std::to_string(sz)); +} \ No newline at end of file diff --git a/src/miner.cpp b/src/miner.cpp index 95f1f166fe3..e9e12019643 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -46,6 +46,8 @@ #include "ui_interface.h" #include "util.h" #include "utilmoneystr.h" +#include "hex.h" + #ifdef ENABLE_WALLET #include "wallet/wallet.h" #endif @@ -56,6 +58,7 @@ #include "sodium.h" #include "notaries_staked.h" +#include "komodo_notary.h" #include #include @@ -141,7 +144,6 @@ void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uin uint32_t Mining_start,Mining_height; int32_t My_notaryid = -1; -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); int32_t komodo_baseid(char *origbase); int32_t komodo_longestchain(); @@ -153,10 +155,7 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void* ptr); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); int32_t komodo_is_notarytx(const CTransaction& tx); -CScript Marmara_scriptPubKey(int32_t height,CPubKey pk); -CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk); uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); 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); @@ -204,7 +203,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } } else pk = _pk; - uint64_t deposits,voutsum=0; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); + uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); bool fNotarisationBlock = false; std::vector NotarisationNotaries; //fprintf(stderr,"create new block\n"); @@ -268,7 +267,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); uint32_t proposedTime = GetTime(); - voutsum = GetBlockSubsidy(nHeight,consensusParams) + 10000*COIN; // approx fees if (proposedTime == nMedianTimePast) { @@ -325,9 +323,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 txvalue = tx.GetValueOut(); if ( KOMODO_VALUETOOBIG(txvalue) != 0 ) continue; - //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 txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString().c_str(),nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime); @@ -724,20 +719,11 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetTime()); else txNew.nLockTime = std::max((int64_t)(pindexPrev->nTime+1), GetTime()); - if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY && My_notaryid >= 0 ) txNew.vout[0].nValue += 5000; pblock->vtx[0] = txNew; - if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) - { - char checkaddr[64]; - Getscriptaddress(checkaddr,txNew.vout[0].scriptPubKey); - //`fprintf(stderr,"set mining coinbase -> %s\n",checkaddr); - txNew.vout.resize(2); - txNew.vout[1].nValue = 0; - txNew.vout[1].scriptPubKey = MarmaraCoinbaseOpret('C',nHeight,pk); - } - else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0) && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) + if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0) && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) { int32_t i; uint8_t *ptr; txNew.vout.resize(2); @@ -756,7 +742,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 len >>= 1; txNew.vout[1].scriptPubKey.resize(len); ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; - decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + decode_hex(ptr,len,ASSETCHAINS_SCRIPTPUB.c_str()); } else { @@ -857,7 +843,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); - if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY && My_notaryid >= 0 ) { uint32_t r; CScript opret; void **ptr=0; CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); @@ -904,7 +890,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } if ( ptr!=0 ) free(ptr); } - else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) ) + else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || !IS_KOMODO_NOTARY || My_notaryid < 0) ) { CValidationState state; //fprintf(stderr,"check validity\n"); @@ -1021,7 +1007,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, len >>= 1; scriptPubKey.resize(len); ptr = (uint8_t *)&scriptPubKey[0]; - decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + decode_hex(ptr,len,ASSETCHAINS_SCRIPTPUB.c_str()); } } else if ( USE_EXTERNAL_PUBKEY != 0 ) @@ -1052,8 +1038,6 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, } } } - if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) - scriptPubKey = Marmara_scriptPubKey(nHeight,pubkey); return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake); } @@ -1126,7 +1110,7 @@ static bool ProcessBlockFound(CBlock* pblock) #ifdef ENABLE_WALLET // Remove key from key pool - if ( IS_KOMODO_NOTARY == 0 ) + if ( !IS_KOMODO_NOTARY ) { if (GetArg("-mineraddress", "").empty()) { // Remove key from key pool @@ -1153,7 +1137,6 @@ static bool ProcessBlockFound(CBlock* pblock) return true; } -int32_t komodo_baseid(char *origbase); int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; @@ -1871,7 +1854,7 @@ void static BitcoinMiner() if ( i == 33 ) externalflag = 1; else externalflag = 0; - if ( IS_KOMODO_NOTARY != 0 ) + if ( IS_KOMODO_NOTARY ) { for (i=1; i<66; i++) if ( memcmp(pubkeys[i],pubkeys[0],33) == 0 ) @@ -1980,7 +1963,7 @@ void static BitcoinMiner() // MilliSleep(30); return false; } - if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetTime() ) + if ( IS_KOMODO_NOTARY && B.nTime > GetTime() ) { //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime())); while ( GetTime() < B.nTime-2 ) @@ -1995,7 +1978,7 @@ void static BitcoinMiner() } if ( ASSETCHAINS_STAKED == 0 ) { - if ( IS_KOMODO_NOTARY != 0 ) + if ( IS_KOMODO_NOTARY ) { int32_t r; if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 ) diff --git a/src/mini-gmp.h b/src/mini-gmp.h index 56647ee773f..8d9d7733f97 100644 --- a/src/mini-gmp.h +++ b/src/mini-gmp.h @@ -62,6 +62,12 @@ see https://www.gnu.org/licenses/. */ extern "C" { #endif +#include "bits256.h" + +char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); + +int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); + void mp_set_memory_functions (void *(*) (size_t), void *(*) (void *, size_t, size_t), void (*) (void *, size_t)); diff --git a/src/net.cpp b/src/net.cpp index 5fe1660254f..111e7acdf90 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -467,13 +467,8 @@ void CNode::PushVersion() LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, strSubVersion, nBestHeight, true); -//fprintf(stderr,"KOMODO_NSPV.%d PUSH services.%llx\n",KOMODO_NSPV,(long long)nLocalServices); } - - - - std::map CNode::setBanned; CCriticalSection CNode::cs_setBanned; diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index db1696ed5ec..14b86cbc8a9 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -3,6 +3,7 @@ #include "crosschain.h" #include "cc/CCinclude.h" #include "komodo_defs.h" +#include "hex.h" #include extern pthread_mutex_t staked_mutex; @@ -81,7 +82,7 @@ int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era) { if ( didinit[era-1] == 0 ) { for (i=0; i +#include +#include +#include +#include +#include + +int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); +struct komodo_state *komodo_stateptrget(char *base); +extern int32_t KOMODO_EXTERNAL_NOTARIES; + +namespace TestEvents { + +void write_p_record(std::FILE* fp) +{ + // a pubkey record with 2 keys + char data[5+1+(33*2)] = {'P', 1, 0, 0, 0, 2}; // public key record identifier with height of 1 plus number of keys plus keys themselves + memset(&data[6], 1, 33); // 1st key is all 1s + memset(&data[39], 2, 33); // 2nd key is all 2s + std::fwrite(data, sizeof(data), 1, fp); +} +void write_n_record(std::FILE* fp) +{ + // a notarized record has + // 5 byte header + // 4 bytes notarized_height + // 32 bytes notarized hash( blockhash) + // 32 bytes desttxid + char data[73] = {'N', 1, 0, 0, 0, 2, 0, 0, 0}; + memset(&data[9], 1, 32); // notarized hash + memset(&data[41], 2, 32); // desttxid + std::fwrite(data, sizeof(data), 1, fp); +} +void write_m_record(std::FILE* fp) +{ + // a notarized M record has + // 5 byte header + // 4 bytes notarized_height + // 32 bytes notarized hash( blockhash) + // 32 bytes desttxid + // 32 bytes MoM + // 4 bytes MoMdepth + char data[109] = {'M', 1, 0, 0, 0, 3, 0, 0, 0}; + memset(&data[9], 1, 32); // notarized hash + memset(&data[41], 2, 32); // desttxid + memset(&data[73], 3, 32); // MoM + memset(&data[105], 4, 4); // MoMdepth + std::fwrite(data, sizeof(data), 1, fp); +} +void write_u_record(std::FILE* fp) +{ + // a U record has + // 5 byte header + // 1 byte n and 1 byte nid + // 8 bytes mask + // 32 bytes hash + char data[47] = {'U', 1, 0, 0, 0, 'N', 'I'}; + memset(&data[7], 1, 8); // mask + memset(&data[15], 2, 32); // hash + std::fwrite(data, sizeof(data), 1, fp); +} +void write_k_record(std::FILE* fp) +{ + // a K record has + // 5 byte header + // 4 bytes height + char data[9] = {'K', 1, 0, 0, 0 }; + memset(&data[5], 1, 4); // height + std::fwrite(data, sizeof(data), 1, fp); +} +void write_t_record(std::FILE* fp) +{ + // a T record has + // 5 byte header + // 4 bytes height + // 4 bytes timestamp + char data[13] = {'T', 1, 0, 0, 0 }; + memset(&data[5], 1, 4); // height + memset(&data[9], 2, 4); // timestamp + std::fwrite(data, sizeof(data), 1, fp); +} +void write_r_record(std::FILE* fp) +{ + // an R record has + // 5 byte header + // 32 byte txid + // 2 byte v + // 8 byte ovalue + // 2 byte olen + // olen bytes of data + char data[50] = {'R', 1, 0, 0, 0 }; + memset(&data[5], 1, 32); // txid + memset(&data[37], 2, 2); // v + memset(&data[39], 3, 8); // ovalue + unsigned char olen[2] = {1,0}; // 1 + memcpy(&data[47], olen, 2); + memset(&data[49], 4, 1); + std::fwrite(data, sizeof(data), 1, fp); +} +void write_v_record(std::FILE* fp) +{ + // a V record has + // 5 byte header + // 1 byte counter + // counter * 4 bytes of data + char data[146] = {'V', 1, 0, 0, 0}; + memset(&data[5], 35, 1); // counter + memset(&data[6], 1, 140); // data + std::fwrite(data, sizeof(data), 1, fp); +} +void write_b_record(std::FILE* fp) +{ + char data[] = {'B', 1, 0, 0, 0}; + std::fwrite(data, sizeof(data), 1, fp); +} +template +bool compare_serialization(const std::string& filename, std::shared_ptr in) +{ + // read contents of file + std::ifstream s(filename, std::ios::binary); + std::vector file_contents((std::istreambuf_iterator(s)), std::istreambuf_iterator()); + // get contents of in + std::stringstream ss; + ss << *(in.get()); + std::vector in_contents( (std::istreambuf_iterator(ss)), std::istreambuf_iterator()); + bool retval = file_contents == in_contents; + if (!retval) + { + if (file_contents.size() != in_contents.size()) + { + std::cout << "File has " << std::to_string( file_contents.size() ) << " bytes but serialized data has " << in_contents.size() << "\n"; + } + else + { + for(size_t i = 0; i < file_contents.size(); ++i) + { + if (file_contents[i] != in_contents[i]) + { + std::cout << "Difference at position " << std::to_string(i) + << " " << std::hex << std::setfill('0') << std::setw(2) << (int)file_contents[i] + << " " << std::hex << std::setfill('0') << std::setw(2) << (int)in_contents[i] << "\n"; + break; + } + } + } + } + return retval; +} + +/**** + * The main purpose of this test is to verify that + * state files created continue to be readable despite logic + * changes. Files need to be readable. The record format should + * not change without hardfork protection + */ +TEST(TestEvents, komodo_faststateinit_test) +{ + char symbol[] = "TST"; + strcpy(ASSETCHAINS_SYMBOL, symbol); + KOMODO_EXTERNAL_NOTARIES = 1; + + boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + try + { + // NOTE: header contains a 5 byte header that is make up of + // an 8 bit identifier (i.e. 'P', 'N', etc.) + // plus a 32 bit height. Everything else is record specific + // pubkey record + { + // create a binary file that should be readable by komodo + const std::string full_filename = (temp / "kstate.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = nullptr; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + // The first and second event should be pub keys + EXPECT_EQ(state->Komodo_numevents, 1); + komodo_event* ev1 = state->Komodo_events[0]; + EXPECT_EQ(ev1->height, 1); + EXPECT_EQ(ev1->type, 'P'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 1); + std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // notarized record + { + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_n_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 2); + komodo_event* ev = state->Komodo_events[1]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'N'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 2); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // notarized M record + { + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_m_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 3); + komodo_event* ev = state->Komodo_events[2]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'N'); // code converts "M" to "N" + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 3); + auto itr = state->events.begin(); + std::advance(itr, 2); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type "U" (deprecated) + { + const std::string full_filename = (temp / "type_u.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_u_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 3); // does not get added to state + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 3); + auto itr = state->events.begin(); + // this does not get added to state, so we need to serialize the object just + // to verify serialization works as expected + std::shared_ptr ev2 = std::make_shared(); + ev2->height = 1; + ev2->n = 'N'; + ev2->nid = 'I'; + memset(ev2->mask, 1, 8); + memset(ev2->hash, 2, 32); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type K (KMD height) + { + const std::string full_filename = (temp / "kmdtype.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_k_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 4); + komodo_event* ev = state->Komodo_events[3]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'K'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 4); + auto itr = state->events.begin(); + std::advance(itr, 3); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type T (KMD height with timestamp) + { + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_t_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 5); + komodo_event* ev = state->Komodo_events[4]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'K'); // changed from T to K + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 5); + auto itr = state->events.begin(); + std::advance(itr, 4); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type R (opreturn) + { + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_r_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 6); + komodo_event* ev = state->Komodo_events[5]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'R'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 6); + auto itr = state->events.begin(); + std::advance(itr, 5); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type V + { + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_v_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 7); + komodo_event* ev = state->Komodo_events[6]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'V'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 7); + auto itr = state->events.begin(); + std::advance(itr, 6); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type B (rewind) + { + const std::string full_filename = (temp / "kmdtypeb.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_b_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + // NOTE: B records are not read in. Unsure if this is on purpose or an oversight + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 7); + komodo_event* ev = state->Komodo_events[6]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'B'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 7); + /* + auto itr = state->events.begin(); + std::advance(itr, 6); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_NE(ev2, nullptr); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_REWIND); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + */ + } + // all together in 1 file + { + const std::string full_filename = (temp / "combined_state.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + write_n_record(fp); + write_m_record(fp); + write_u_record(fp); + write_k_record(fp); + write_t_record(fp); + write_r_record(fp); + write_v_record(fp); + std::fclose(fp); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 14); + komodo_event* ev1 = state->Komodo_events[7]; + EXPECT_EQ(ev1->height, 1); + EXPECT_EQ(ev1->type, 'P'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 14); + auto itr = state->events.begin(); + std::advance(itr, 7); + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); + itr++; + } + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); +} + +TEST(TestEvents, komodo_faststateinit_test_kmd) +{ + // Nothing should be added to events if this is the komodo chain + + char symbol[] = "KMD"; + ASSETCHAINS_SYMBOL[0] = 0; + KOMODO_EXTERNAL_NOTARIES = 0; + + boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + try + { + // NOTE: header contains a 5 byte header that is make up of + // an 8 bit identifier (i.e. 'P', 'N', etc.) + // plus a 32 bit height. Everything else is record specific + // pubkey record + { + // create a binary file that should be readable by komodo + const std::string full_filename = (temp / "kstate.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = nullptr; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // notarized record + { + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_n_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // notarized M record + { + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_m_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // record type "U" (deprecated) + { + const std::string full_filename = (temp / "type_u.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_u_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // record type K (KMD height) + { + const std::string full_filename = (temp / "kmdtype.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_k_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // record type T (KMD height with timestamp) + { + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_t_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // record type R (opreturn) + { + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_r_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // record type V + { + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_v_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // record type B (rewind) + { + const std::string full_filename = (temp / "kmdtypeb.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_b_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + // NOTE: B records are not read in. Unsure if this is on purpose or an oversight + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + // all together in 1 file + { + const std::string full_filename = (temp / "combined_state.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + write_n_record(fp); + write_m_record(fp); + write_u_record(fp); + write_k_record(fp); + write_t_record(fp); + write_r_record(fp); + write_v_record(fp); + std::fclose(fp); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + EXPECT_EQ(state->events.size(), 0); + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); +} + +} // namespace TestEvents \ No newline at end of file diff --git a/src/test-komodo/test_hex.cpp b/src/test-komodo/test_hex.cpp new file mode 100644 index 00000000000..c7237eca4ec --- /dev/null +++ b/src/test-komodo/test_hex.cpp @@ -0,0 +1,41 @@ +#include +#include "hex.h" + +namespace TestHex { + + TEST(TestHex, decodehex) + { + { + // n = 0 + char* in = (char*) "01"; + uint8_t bytes[2] = {0}; + ASSERT_EQ(decode_hex(bytes, 0, in), 0); + ASSERT_EQ(bytes[0], 0x00); + } + { + // happy path + char* in = (char*) "01"; + uint8_t bytes[1] = {0}; + ASSERT_EQ(decode_hex(bytes, 1, in), 1); + ASSERT_EQ(bytes[0], 0x01); + } + { + // cr/lf + char* in = (char*) "01\r\n"; + uint8_t bytes[1] = {0}; + ASSERT_EQ(decode_hex(bytes, 1, in), 1); + ASSERT_EQ(bytes[0], 0x01); + } + { + // string longer than what we say by 1 + // evidently a special case that we handle by treating + // the 1st char as a complete byte + char* in = (char*) "010"; + uint8_t bytes[2] = {0}; + ASSERT_EQ(decode_hex(bytes, 1, in), 2); + ASSERT_EQ(bytes[0], 0); + ASSERT_EQ(bytes[1], 16); + } + } + +} // namespace TestHex diff --git a/src/uthash.h b/src/uthash.h index 7b99c0133c0..2f1f15b76ca 100644 --- a/src/uthash.h +++ b/src/uthash.h @@ -27,6 +27,7 @@ #include /* memcmp,strlen */ #include /* ptrdiff_t */ #include /* exit() */ +#include /* These macros use decltype or the earlier __typeof GNU extension. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ diff --git a/src/wallet-utility.cpp b/src/wallet-utility.cpp index f7717affa9c..a310adeb067 100644 --- a/src/wallet-utility.cpp +++ b/src/wallet-utility.cpp @@ -24,7 +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; +bool IS_KOMODO_TESTNODE = false; unsigned int MAX_BLOCK_SIGOPS = 20000; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0d2e027b986..fe861948563 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -60,6 +60,7 @@ #include #include "komodo_defs.h" +#include "hex.h" #include using namespace std; @@ -5489,7 +5490,6 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& m #include "script/sign.h" -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); extern std::string NOTARY_PUBKEY; int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr) @@ -5538,7 +5538,6 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void * continue; } utxovalue = (uint64_t)nValue; - //decode_hex((uint8_t *)&utxotxid,32,(char *)out.tx->GetHash().GetHex().c_str()); utxotxid = out.tx->GetHash(); utxovout = out.i; best_scriptPubKey = out.tx->vout[out.i].scriptPubKey; @@ -5596,14 +5595,13 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits #include "../cc/CCGateways.h" #include "../cc/CCPrices.h" #include "../cc/CCHeir.h" -#include "../cc/CCMarmara.h" #include "../cc/CCPayments.h" #include "../cc/CCPegs.h" int32_t ensure_CCrequirements(uint8_t evalcode) { CCerror = ""; - if ( ASSETCHAINS_CCDISABLES[evalcode] != 0 || (evalcode == EVAL_MARMARA && ASSETCHAINS_MARMARA == 0) ) + if ( ASSETCHAINS_CCDISABLES[evalcode] != 0 ) { // check if a height activation has been set. fprintf(stderr, "evalcode.%i activates at height. %i current height.%i\n", evalcode, mapHeightEvalActivate[evalcode], komodo_currentheight()); @@ -5729,7 +5727,7 @@ UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (strlen(params[0].get_str().c_str()) == 66) { - decode_hex(pubkey33,33,(char *)params[0].get_str().c_str()); + decode_hex(pubkey33,33,params[0].get_str().c_str()); pubkey2addr((char *)Raddress,(uint8_t *)pubkey33); CBitcoinAddress address(Raddress); bool isValid = address.IsValid(); @@ -5743,14 +5741,14 @@ UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { result.push_back(Pair("ismine", "true")); std::string notaryname; - if ( (IS_STAKED_NOTARY= StakedNotaryID(notaryname, Raddress)) > -1 ) + if ( (STAKED_NOTARY_ID= StakedNotaryID(notaryname, Raddress)) > -1 ) { result.push_back(Pair("IsNotary", notaryname)); - IS_KOMODO_NOTARY = 0; + IS_KOMODO_NOTARY = false; } } NOTARY_PUBKEY = params[0].get_str(); - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + decode_hex(NOTARY_PUBKEY33,33,NOTARY_PUBKEY.c_str()); USE_EXTERNAL_PUBKEY = 1; NOTARY_ADDRESS = address.ToString(); } @@ -6071,19 +6069,6 @@ UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return(CCaddress(cp,(char *)"Pegs",pubkey)); } -UniValue marmaraaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - struct CCcontract_info *cp,C; std::vector pubkey; - cp = CCinit(&C,EVAL_MARMARA); - if ( fHelp || params.size() > 1 ) - throw runtime_error("Marmaraaddress [pubkey]\n"); - if ( ensure_CCrequirements(cp->evalcode) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - if ( params.size() == 1 ) - pubkey = ParseHex(params[0].get_str().c_str()); - return(CCaddress(cp,(char *)"Marmara",pubkey)); -} - UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; std::vector pubkey; @@ -6241,192 +6226,6 @@ UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& return(CCaddress(cp,(char *)"ImportGateway", pubkey)); } -UniValue marmara_poolpayout(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t firstheight; double perc; char *jsonstr; - if ( fHelp || params.size() != 3 ) - { - // marmarapoolpayout 0.5 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000],["02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92",100]]'; - //marmarapoolpayout 0 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000]]' - throw runtime_error("marmarapoolpayout perc firstheight \"[[\\\"pubkey\\\":shares], ...]\"\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - perc = atof(params[0].get_str().c_str()) / 100.; - firstheight = atol(params[1].get_str().c_str()); - jsonstr = (char *)params[2].get_str().c_str(); - return(MarmaraPoolPayout(0,firstheight,perc,jsonstr)); // [[pk0, shares0], [pk1, shares1], ...] -} - -UniValue marmara_receive(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 batontxid; std::vector senderpub; int64_t amount; int32_t matures; std::string currency; - if ( fHelp || (params.size() != 5 && params.size() != 4) ) - { - // automatic flag -> lsb of matures - // 1st marmarareceive 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1440 - // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 d72d87aa0d50436de695c93e2bf3d7273c63c92ef6307913aa01a6ee6a16548b - throw runtime_error("marmarareceive senderpk amount currency matures batontxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - memset(&batontxid,0,sizeof(batontxid)); - senderpub = ParseHex(params[0].get_str().c_str()); - if (senderpub.size()!= 33) - { - ERR_RESULT("invalid sender pubkey"); - return result; - } - amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - currency = params[2].get_str(); - if ( params.size() == 5 ) - { - matures = atol(params[3].get_str().c_str()); - batontxid = Parseuint256((char *)params[4].get_str().c_str()); - } else matures = atol(params[3].get_str().c_str()) + chainActive.LastTip()->GetHeight() + 1; - return(MarmaraReceive(0,pubkey2pk(senderpub),amount,currency,matures,batontxid,true)); -} - -UniValue marmara_issue(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 approvaltxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; - if ( fHelp || params.size() != 5 ) - { - // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 32da4cb3e886ee42de90b4a15042d71169077306badf909099c5c5c692df3f27 - // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 700 MARMARA 2629 11fe8bf1de80c2ef69124d08907f259aef7f41e3a632ca2d48ad072a8c8f3078 -> 335df3a5dd6b92a3d020c9465d4d76e0d8242126106b83756dcecbad9813fdf3 - - throw runtime_error("marmaraissue receiverpk amount currency matures approvaltxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - receiverpub = ParseHex(params[0].get_str().c_str()); - if (receiverpub.size()!= 33) - { - ERR_RESULT("invalid receiverpub pubkey"); - return result; - } - amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - currency = params[2].get_str(); - matures = atol(params[3].get_str().c_str()); - approvaltxid = Parseuint256((char *)params[4].get_str().c_str()); - return(MarmaraIssue(0,'I',pubkey2pk(receiverpub),amount,currency,matures,approvaltxid,zeroid)); -} - -UniValue marmara_transfer(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 approvaltxid,batontxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; std::vector creditloop; - if ( fHelp || params.size() != 5 ) - { - // marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1168 1506c774e4b2804a6e25260920840f4cfca8d1fb400e69fe6b74b8e593dbedc5 - throw runtime_error("marmaratransfer receiverpk amount currency matures approvaltxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - receiverpub = ParseHex(params[0].get_str().c_str()); - if (receiverpub.size()!= 33) - { - ERR_RESULT("invalid receiverpub pubkey"); - return result; - } - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - currency = params[2].get_str(); - matures = atol(params[3].get_str().c_str()); - approvaltxid = Parseuint256((char *)params[4].get_str().c_str()); - if ( MarmaraGetbatontxid(creditloop,batontxid,approvaltxid) < 0 ) - throw runtime_error("couldnt find batontxid\n"); - return(MarmaraIssue(0,'T',pubkey2pk(receiverpub),amount,currency,matures,approvaltxid,batontxid)); -} - -UniValue marmara_info(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); CPubKey issuerpk; std::vector issuerpub; int64_t minamount,maxamount; int32_t firstheight,lastheight; std::string currency; - if ( fHelp || params.size() < 4 || params.size() > 6 ) - { - throw runtime_error("marmarainfo firstheight lastheight minamount maxamount [currency issuerpk]\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - firstheight = atol(params[0].get_str().c_str()); - lastheight = atol(params[1].get_str().c_str()); - minamount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; - maxamount = atof(params[3].get_str().c_str()) * COIN + 0.00000000499999; - if ( params.size() >= 5 ) - currency = params[4].get_str(); - if ( params.size() == 6 ) - { - issuerpub = ParseHex(params[5].get_str().c_str()); - if ( issuerpub.size()!= 33 ) - { - ERR_RESULT("invalid issuer pubkey"); - return result; - } - issuerpk = pubkey2pk(issuerpub); - } - result = MarmaraInfo(issuerpk,firstheight,lastheight,minamount,maxamount,currency); - return(result); -} - -UniValue marmara_creditloop(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 txid; - if ( fHelp || params.size() != 1 ) - { - // marmaracreditloop 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be - throw runtime_error("marmaracreditloop txid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - txid = Parseuint256((char *)params[0].get_str().c_str()); - result = MarmaraCreditloop(txid); - return(result); -} - -UniValue marmara_settlement(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 batontxid; - if ( fHelp || params.size() != 1 ) - { - // marmarasettlement 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be - // marmarasettlement ff3e259869196f3da9b5ea3f9e088a76c4fc063cf36ab586b652e121d441a603 - throw runtime_error("marmarasettlement batontxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - batontxid = Parseuint256((char *)params[0].get_str().c_str()); - result = MarmaraSettlement(0,batontxid); - return(result); -} - -UniValue marmara_lock(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); int64_t amount; int32_t height; - if ( fHelp || params.size() > 2 || params.size() == 0 ) - { - throw runtime_error("marmaralock amount unlockht\n"); - } - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - amount = atof(params[0].get_str().c_str()) * COIN + 0.00000000499999; - if ( params.size() == 2 ) - height = atol(params[1].get_str().c_str()); - else height = chainActive.LastTip()->GetHeight() + 1; - return(MarmaraLock(0,amount,height)); -} - UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk) { if ( fHelp || params.size() > 0 ) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index db66de052c4..b37669b5dbb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3423,7 +3423,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) { - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) { uint32_t locktime; int32_t txheight; CBlockIndex *tipindex; if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->GetHeight() >= 60000 ) @@ -3550,30 +3550,20 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(coin.second); nValueRet += coin.first; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += pcoin->vout[i].interest; return true; } else if (n < nTargetValue + CENT) { vValue.push_back(coin); nTotalLower += n; - //if ( KOMODO_EXCHANGEWALLET == 0 && count < sizeof(interests)/sizeof(*interests) ) - //{ - //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN); - //interests[count++] = pcoin->vout[i].interest; - //} if ( nTotalLower > 4*nTargetValue + CENT ) { - //fprintf(stderr,"why bother with all the utxo if we have double what is needed?\n"); break; } } else if (n < coinLowestLarger.first) { coinLowestLarger = coin; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // lowest_interest = pcoin->vout[i].interest; } } @@ -3583,8 +3573,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(vValue[i].second); nValueRet += vValue[i].first; - //if ( KOMODO_EXCHANGEWALLET == 0 && i < count ) - // *interestp += interests[i]; } return true; } @@ -3595,8 +3583,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return false; setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += lowest_interest; return true; } @@ -3616,8 +3602,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += lowest_interest; } else { for (unsigned int i = 0; i < vValue.size(); i++) @@ -3625,8 +3609,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(vValue[i].second); nValueRet += vValue[i].first; - //if ( KOMODO_EXCHANGEWALLET == 0 && i < count ) - // *interestp += interests[i]; } LogPrint("selectcoins", "SelectCoins() best subset: "); @@ -3643,11 +3625,6 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set vCoinsNoCoinbase, vCoinsWithCoinbase; AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false); AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true); @@ -3665,7 +3642,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) value += out.tx->vout[out.i].interest; } if (value <= nTargetValue) { @@ -3675,7 +3652,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) valueWithCoinbase += out.tx->vout[out.i].interest; } fNeedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue); @@ -3689,8 +3666,6 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += out.tx->vout[out.i].interest; setCoinsRet.insert(make_pair(out.tx, out.i)); } return (nValueRet >= nTargetValue); @@ -3712,7 +3687,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout.size() <= outpoint.n) return false; nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue; - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) nValueFromPresetInputs += pcoin->vout[outpoint.n].interest; setPresetCoins.insert(make_pair(pcoin, outpoint.n)); } else @@ -3929,7 +3904,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt //a chance at a free transaction. //But mempool inputs might still be in the mempool, so their age stays 0 //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN); - if ( KOMODO_EXCHANGEWALLET == 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( !IS_MODE_EXCHANGEWALLET && ASSETCHAINS_SYMBOL[0] == 0 ) { interest2 += pcoin.first->vout[pcoin.second].interest; //fprintf(stderr,"%.8f ",(double)pcoin.first->vout[pcoin.second].interest/COIN); @@ -3939,11 +3914,6 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt age += 1; dPriority += (double)nCredit * age; } - //if ( KOMODO_EXCHANGEWALLET != 0 ) - //{ - //fprintf(stderr,"KOMODO_EXCHANGEWALLET disable interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN); - //interest = 0; // interest2 also - //} if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 ) { CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG;