diff --git a/README.md b/README.md index b84e577b8..86ce58ff7 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,11 @@ ![Logo](doc/hush/hush.png "Logo") -HUSH (formerly Zdash) is a code fork of [ZCash](https://z.cash/) which has it's -own genesis block. Based on Bitcoin's code, it intends to offer a far higher -standard of privacy through a sophisticated zero-knowledge proving scheme that -preserves confidentiality of transaction metadata. +HUSH (originally Zdash) is a code fork of [ZCash](https://z.cash/) which has +it's own genesis block. It is not a fork of another network. Based on +Bitcoin's code, it intends to offer a far higher standard of privacy through a +sophisticated zero-knowledge proving scheme that preserves confidentiality of +transaction metadata. This software is the HUSH node and command-line client. It downloads and stores the entire history of HUSH transactions; depending on the speed of your @@ -84,6 +85,8 @@ you can see your funds with this command: ./src/hush-cli getwalletinfo +NOTE: Do not use this wallet except to send funds to a new wallet! + ### Private Keys You can also transport funds one address at a time via private keys. diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index f9b066fcf..cbbc5a667 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -1,5 +1,5 @@ -build_darwin_CC = gcc-6 -build_darwin_CXX = g++-6 +build_darwin_CC = gcc-8 +build_darwin_CXX = g++-8 build_darwin_AR: = $(shell xcrun -f ar) build_darwin_RANLIB: = $(shell xcrun -f ranlib) build_darwin_STRIP: = $(shell xcrun -f strip) @@ -10,8 +10,8 @@ build_darwin_SHA256SUM = shasum -a 256 build_darwin_DOWNLOAD = curl --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -L -f -o #darwin host on darwin builder. overrides darwin host preferences. -darwin_CC= gcc-6 -darwin_CXX= g++-6 +darwin_CC= gcc-8 +darwin_CXX= g++-8 darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) diff --git a/src/Makefile.am b/src/Makefile.am index e6c1fbb14..a7dd21be8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -599,11 +599,19 @@ if ENABLE_PROTON komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) endif +# [+] Decker: use static linking for libstdc++.6.dylib, libgomp.1.dylib, libgcc_s.1.dylib +if TARGET_DARWIN +komodod_LDFLAGS += -static-libgcc +endif + # bitcoin-cli binary # komodo_cli_SOURCES = bitcoin-cli.cpp komodo_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) komodo_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) komodo_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +if TARGET_DARWIN +komodo_cli_LDFLAGS += -static-libgcc +endif # wallet-utility binary # if ENABLE_WALLET diff --git a/src/ac/k64 b/src/ac/k64 new file mode 100755 index 000000000..a3b3bc835 --- /dev/null +++ b/src/ac/k64 @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=K64 $1 $2 $3 $4 $5 $6 diff --git a/src/ac/zex b/src/ac/zex deleted file mode 100755 index f4573c093..000000000 --- a/src/ac/zex +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ZEX $1 $2 $3 $4 $5 $6 diff --git a/src/ac/zexo b/src/ac/zexo new file mode 100755 index 000000000..b6fd508f2 --- /dev/null +++ b/src/ac/zexo @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=ZEXO $1 $2 $3 $4 $5 $6 diff --git a/src/assetchains.json b/src/assetchains.json index 99c6557b6..86dc77565 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -159,18 +159,6 @@ "136.243.102.225" ] }, - { - "ac_name": "MGNX", - "ac_supply": "12465003", - "ac_staked": "90", - "ac_reward": "2000000000", - "ac_halving": "525960", - "ac_cc": "2", - "ac_end": "2629800", - "addnode": [ - "142.93.27.180" - ] - }, { "ac_name": "PGT", "ac_supply": "10000000", @@ -202,17 +190,6 @@ "144.76.217.232" ] }, - { - "ac_name": "ZEX", - "ac_founders": "1", - "ac_reward": "13000000000", - "ac_halving": "525600", - "ac_cc": "2", - "ac_pubkey": "039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af", - "addnode": [ - "5.9.102.210" - ] - }, { "ac_name": "KSB", "ac_supply": "1000000000", @@ -268,5 +245,28 @@ "ac_name": "KOIN", "ac_supply": "125000000", "addnode": ["3.0.32.10"] + }, + { + "ac_name": "ZEXO", + "ac_reward": "1478310502", + "ac_halving": "525600", + "ac_cc": "42", + "ac_ccenable": "236", + "ac_supply": "100000000", + "ac_perc": "77700", + "ac_staked": "93", + "ac_pubkey": "02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc", + "ac_public": "1", + "addnode": [ + "195.201.20.230", + "80.240.17.222" + ] + }, + { + "ac_name": "K64", + "ac_reward": "0", + "ac_supply": "64000777", + "ac_staked": "10", + "addnode": ["18.197.20.21"] } ] diff --git a/src/assetchains.old b/src/assetchains.old index fd472eff9..4cf427c4d 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -39,11 +39,10 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=SEC -ac_cc=333 -ac_supply=1000000000 -addnode=185.148.145.43 & ./komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 & ./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=178.63.77.56 & -./komodod -pubkey=$pubkey -ac_name=MGNX -ac_supply=12465003 -ac_staked=90 -ac_reward=2000000000 -ac_halving=525960 -ac_cc=2 -ac_end=2629800 -addnode=142.93.27.180 & +#./komodod -pubkey=$pubkey -ac_name=MGNX -ac_supply=12465003 -ac_staked=90 -ac_reward=2000000000 -ac_halving=525960 -ac_cc=2 -ac_end=2629800 -addnode=142.93.27.180 & ./komodod -pubkey=$pubkey -ac_name=PGT -ac_supply=10000000 -ac_end=1 -addnode=190.114.254.104 & ./komodod -pubkey=$pubkey -ac_name=KMDICE -ac_supply=10500000 -ac_reward=2500000000 -ac_halving=210000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=144.76.217.232 & ./komodod -pubkey=$pubkey -ac_name=DION -ac_supply=3900000000 -ac_reward=22260000000 -ac_staked=100 -ac_cc=1 -ac_end=4300000000 -addnode=51.75.124.34 & -./komodod -pubkey=$pubkey -ac_name=ZEX -ac_cc=2 -ac_founders=1 -ac_halving=525600 -ac_reward=13000000000 -ac_pubkey=039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af -addnode=5.9.102.210 & ./komodod -pubkey=$pubkey -ac_name=KSB -ac_supply=1000000000 -ac_end=1 -ac_public=1 -addnode=37.187.225.231 & ./komodod -pubkey=$pubkey -ac_name=OUR -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_supply=100000000 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c -ac_public=1 -addnode=51.255.195.65 -addnode=217.182.129.38 -addnode=37.187.225.231 & ./komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 & @@ -51,4 +50,5 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -addnode=138.201.136.145 & ./komodod -pubkey=$pubkey -ac_name=VOTE2019 -ac_supply=123651638 -ac_public=1 -addnode=95.213.238.98 & ./komodod -pubkey=$pubkey -ac_name=KOIN -ac_supply=125000000 -addnode=3.0.32.10 & -~/hush3/src/komodod -pubkey=$pubkey -ac_name=HUSH3 -ac_sapling=1 -ac_reward=0,1125000000,562500000 -ac_halving=129,340000,840000 -ac_end=128,340000,5422111 -ac_eras=3 -ac_blocktime=150 -ac_cc=2 -ac_ccenable=228,234,235,236,241 -ac_founders=1 -ac_supply=6178674 -ac_perc=11111111 -clientname=GoldenSandtrout -addnode=188.165.212.101 -ac_cclib=hush3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac & +./komodod -pubkey=$pubkey -ac_name=ZEXO -ac_supply=100000000 -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_ccenable=236 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc -ac_public=1 -addnode=80.240.17.222 & +./komodod -pubkey=$pubkey -ac_name=K64 -ac_supply=64000777 -ac_reward=0 -ac_staked=10 -addnode=18.197.20.211 & diff --git a/src/cc/CCPrices.h b/src/cc/CCPrices.h index 238131d59..3779111a6 100644 --- a/src/cc/CCPrices.h +++ b/src/cc/CCPrices.h @@ -38,8 +38,12 @@ extern CScript KOMODO_EARLYTXID_SCRIPTPUB; #define PRICES_MMM (KOMODO_MAXPRICES * 7) // 0011 1000 0000 0000 #define PRICES_DDD (KOMODO_MAXPRICES * 8) // 0100 0000 0000 0000 -#define PRICES_NORMFACTOR (int64_t)(SATOSHIDEN) -#define PRICES_POINTFACTOR (int64_t)10000 +//#define PRICES_NORMFACTOR (int64_t)(SATOSHIDEN) +//#define PRICES_POINTFACTOR (int64_t)10000 + +#define PRICES_REVSHAREDUST 10000 +#define PRICES_SUBREVSHAREFEE(amount) ((amount) * 199 / 200) // revshare fee percentage == 0.005 +#define PRICES_MINAVAILFUNDFRACTION 0.1 // leveraged bet limit < fund fraction bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); @@ -52,6 +56,7 @@ UniValue PricesCashout(int64_t txfee,uint256 bettxid); UniValue PricesInfo(uint256 bettxid,int32_t refheight); UniValue PricesList(uint32_t filter, CPubKey mypk); UniValue PricesGetOrderbook(); +UniValue PricesRefillFund(int64_t amount); #endif diff --git a/src/cc/makecclib b/src/cc/makecclib index e4816c55c..5241ea675 100755 --- a/src/cc/makecclib +++ b/src/cc/makecclib @@ -7,6 +7,8 @@ make -f Makefile_rogue rm ../libcc.so cp librogue.so ../libcc.so +#exit 0 + echo sudoku/musig/dilithium gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index a5d61d404..7cd429182 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -924,14 +924,13 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector da UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatlen) { - UniValue obj(UniValue::VARR); uint256 hash; int32_t i,j=0; int64_t val; char str[IGUANA_MAXSCRIPTSIZE*2+1]; + uint256 hash; int32_t i,j=0; int64_t val; char str[IGUANA_MAXSCRIPTSIZE*2+1]; for (i=0; i= datalen ) break; } @@ -954,9 +953,9 @@ UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num) { if ( (formatstr= (char *)format.c_str()) == 0 ) formatstr = (char *)""; - UniValue a(UniValue::VARR); - a.push_back(OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size())); - a.push_back(uint256_str(str,batontxid)); + UniValue a(UniValue::VOBJ); + a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); + a.push_back(Pair("txid",uint256_str(str,batontxid))); b.push_back(a); batontxid = btxid; if ( ++n >= num && num != 0) diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 0ea339f3a..b6e85480c 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -326,11 +326,6 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return(eval->Invalid("negative values")); if ( minimum < 10000 ) return(eval->Invalid("minimum must be over 10000")); - if ( amountReleased < minrelease*COIN ) - { - fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amountReleased, (int64_t)minrelease*COIN); - return(eval->Invalid("amount is too small")); - } Paymentspk = GetUnspendable(cp,0); txidpk = CCtxidaddr(txidaddr,createtxid); GetCCaddress1of2(cp,txidaddr,Paymentspk,txidpk); @@ -343,6 +338,11 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ( !fIsMerge ) { + if ( amountReleased < minrelease*COIN ) + { + fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amountReleased, (int64_t)minrelease*COIN); + return(eval->Invalid("amount is too small")); + } // Get all the script pubkeys and allocations std::vector allocations; std::vector scriptPubKeys; @@ -406,6 +406,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & { // token snapshot // payments_gettokenallocations(top, bottom, excludeScriptPubKeys, tokenid, mpzTotalAllocations, scriptPubKeys, allocations); + return(eval->Invalid("tokens not yet implemented")); } } // sanity check to make sure we got all the required info, skip for merge type tx @@ -519,8 +520,8 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & else if ( i == dust+1 ) return(eval->Invalid("cannot merge only dust")); } - } else return(eval->Invalid("create transaction cannot decode")); - } else return(eval->Invalid("Could not get contract transaction")); + } else return(eval->Invalid("cannot decode create transaction")); + } else return(eval->Invalid("could not get contract transaction")); return(true); } // end of consensus code @@ -556,7 +557,7 @@ int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract txid = it->first.txhash; vout = (int32_t)it->first.index; //fprintf(stderr,"iter.%d %s/v%d %s\n",iter,txid.GetHex().c_str(),vout,coinaddr); - if ( (vout == 0 || vout == 1) && GetTransaction(txid,vintx,hashBlock,false) != 0 ) + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { if ( (nValue= IsPaymentsvout(cp,vintx,vout,coinaddr,ccopret)) > PAYMENTS_TXFEE && nValue >= threshold && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) { @@ -1067,15 +1068,27 @@ UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr) UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ); CPubKey mypk; std::string rawtx; - std::vector scriptPubKey,opret; int32_t n,retval0,retval1=0; int64_t allocation; + std::vector scriptPubKey,opret; int32_t n,retval0,retval1=0; int64_t allocation; CScript test; txnouttype whichType; cJSON *params = payments_reparse(&n,jsonstr); mypk = pubkey2pk(Mypubkey()); if ( params != 0 && n > 1 && n <= 3 ) { allocation = (int64_t)jint(jitem(params,0),0); - retval0 = payments_parsehexdata(scriptPubKey,jitem(params,1),0); - CScript test = CScript(scriptPubKey.begin(),scriptPubKey.end()); - txnouttype whichType; + std::string address; + address.append(jstri(params,1)); + CTxDestination destination = DecodeDestination(address); + if ( IsValidDestination(destination) ) + { + // its an address + test = GetScriptForDestination(destination); + scriptPubKey = std::vector (test.begin(),test.end()); + } + else + { + // its a scriptpubkey + retval0 = payments_parsehexdata(scriptPubKey,jitem(params,1),0); + test = CScript(scriptPubKey.begin(),scriptPubKey.end()); + } if (!::IsStandard(test, whichType)) { result.push_back(Pair("result","error")); @@ -1279,7 +1292,8 @@ UniValue PaymentsAirdropTokens(struct CCcontract_info *cp,char *jsonstr) uint256 hashBlock, tokenid = zeroid; CTransaction tx; CPubKey Paymentspk,mypk; char markeraddr[64]; std::string rawtx; int32_t lockedblocks,minrelease,top,bottom,n,i,minimum=10000; std::vector> excludeScriptPubKeys; int8_t fixedAmount; cJSON *params = payments_reparse(&n,jsonstr); - if ( params != 0 && n >= 6 ) + // disable for now. Need token snapshot function. + if ( 0 ) //params != 0 && n >= 6 ) { tokenid = payments_juint256(jitem(params,0)); lockedblocks = juint(jitem(params,1),0); @@ -1346,7 +1360,8 @@ UniValue PaymentsAirdropTokens(struct CCcontract_info *cp,char *jsonstr) else { result.push_back(Pair("result","error")); - result.push_back(Pair("error","parameters error")); + //result.push_back(Pair("error","parameters error")); + result.push_back(Pair("error","tokens airdrop not yet impmlemented")); } if ( params != 0 ) free_json(params); diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 2116f2e8e..2c0a33b20 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -11,7 +11,34 @@ * * * Removal or modification of this copyright notice is prohibited. * * * - ***************************************************************************** + *****************************************************************************/ + + /* + CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices; + + 0.5% fee based on betamount, NOT leveraged betamount!! + 0.1% collected by price basis determinant + 0.2% collected by rekt tx + + PricesBet -> +/-leverage, amount, synthetic -> opreturn includes current price + funds are locked into 1of2 global CC address + for first day, long basis is MAX(correlated,smoothed), short is MIN() + reference price is the smoothed of the previous block + if synthetic value + amount goes negative, then anybody can rekt it to collect a rektfee, proof of rekt must be included to show cost basis, rekt price + original creator can liquidate at anytime and collect (synthetic value + amount) from globalfund + 0.5% of bet -> globalfund + + PricesStatus -> bettxid maxsamples returns initial params, cost basis, amount left, rekt:true/false, rektheight, initial synthetic price, current synthetic price, net gain + + PricesRekt -> bettxid height -> 0.1% to miner, rest to global CC + + PricesClose -> bettxid returns (synthetic value + amount) + + PricesList -> all bettxid -> list [bettxid, netgain] + + */ + +/* To create payments plan start a chain with the following ac_params: -ac_snapshot=1440 (or for test chain something smaller, if you like.) - this enables the payments airdrop cc to work. @@ -45,6 +72,7 @@ GetKomodoEarlytxidScriptPub is on line #2080 of komodo_bitcoind.h #include "CCassets.h" #include "CCPrices.h" +#include #include #define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) @@ -62,53 +90,50 @@ typedef struct OneBetData { } onebetdata; typedef struct BetInfo { + uint256 txid; int64_t averageCostbasis, firstprice, lastprice, liquidationprice, equity; - int64_t rektfee; + int64_t exitfee; int32_t lastheight; int16_t leverage; bool isOpen, isRekt; uint256 tokenid; - std::vector parsed; + std::vector vecparsed; std::vector bets; CPubKey pk; + bool isUp; + BetInfo() { averageCostbasis = firstprice = lastprice = liquidationprice = equity = 0; lastheight = 0; leverage = 0; - rektfee = 0; - isOpen = isRekt = false; + exitfee = 0; + isOpen = isRekt = isUp = false; } } BetInfo; -/* -CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices; - - 0.5% fee based on betamount, NOT leveraged betamount!! - 0.1% collected by price basis determinant - 0.2% collected by rekt tx - - PricesBet -> +/-leverage, amount, synthetic -> opreturn includes current price - funds are locked into 1of2 global CC address - for first day, long basis is MAX(correlated,smoothed), short is MIN() - reference price is the smoothed of the previous block - if synthetic value + amount goes negative, then anybody can rekt it to collect a rektfee, proof of rekt must be included to show cost basis, rekt price - original creator can liquidate at anytime and collect (synthetic value + amount) from globalfund - 0.5% of bet -> globalfund - - PricesStatus -> bettxid maxsamples returns initial params, cost basis, amount left, rekt:true/false, rektheight, initial synthetic price, current synthetic price, net gain - - PricesRekt -> bettxid height -> 0.1% to miner, rest to global CC - - PricesClose -> bettxid returns (synthetic value + amount) - - PricesList -> all bettxid -> list [bettxid, netgain] - - -*/ +typedef struct MatchedBookTotal { + + int64_t diffLeveragedPosition; + +} MatchedBookTotal; + +typedef struct TotalFund { + int64_t totalFund; + int64_t totalActiveBets; + int64_t totalCashout; + int64_t totalRekt; + int64_t totalEquity; + + TotalFund() { + totalFund = totalActiveBets = totalCashout = totalRekt = totalEquity = 0; + } + +} TotalFund; int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t height, int16_t leverage, std::vector vec, int64_t positionsize, int64_t &profits, int64_t &outprice); +static bool prices_isacceptableamount(const std::vector &vecparsed, int64_t amount, int16_t leverage); // helpers: @@ -177,18 +202,20 @@ uint8_t prices_costbasisopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKe return(0); } -CScript prices_finalopret(uint256 bettxid,int64_t profits,int32_t height,CPubKey mypk,int64_t firstprice,int64_t costbasis,int64_t addedbets,int64_t positionsize,int16_t leverage) +CScript prices_finalopret(bool isRekt, uint256 bettxid, CPubKey pk, int32_t lastheight, int64_t costbasis, int64_t lastprice, int64_t liquidationprice, int64_t equity, int64_t exitfee, uint32_t nonce) { CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'F' << bettxid << profits << height << mypk << firstprice << costbasis << addedbets << positionsize << leverage); + opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << (isRekt ? 'R' : 'F') << bettxid << pk << lastheight << costbasis << lastprice << liquidationprice << equity << exitfee << nonce); return(opret); } -uint8_t prices_finalopretdecode(CScript scriptPubKey,uint256 &bettxid,int64_t &profits,int32_t &height,CPubKey &pk,int64_t &firstprice,int64_t &costbasis,int64_t &addedbets,int64_t &positionsize,int16_t &leverage) +uint8_t prices_finalopretdecode(CScript scriptPubKey, uint256 &bettxid, CPubKey &pk, int32_t &lastheight, int64_t &costbasis, int64_t &lastprice, int64_t &liquidationprice, int64_t &equity, int64_t &exitfee) { std::vector vopret; uint8_t e,f; + uint32_t nonce; + GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bettxid; ss >> profits; ss >> height; ss >> pk; ss >> firstprice; ss >> costbasis; ss >> addedbets; ss >> positionsize; ss >> leverage) != 0 && e == EVAL_PRICES && f == 'F' ) + if (vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> bettxid; ss >> pk; ss >> lastheight; ss >> costbasis; ss >> lastprice; ss >> liquidationprice; ss >> equity; ss >> exitfee; if (!ss.eof()) ss >> nonce; ) != 0 && e == EVAL_PRICES && (f == 'F' || f == 'R')) { return(f); } @@ -198,7 +225,7 @@ uint8_t prices_finalopretdecode(CScript scriptPubKey,uint256 &bettxid,int64_t &p // price opret basic validation and retrieval static uint8_t PricesCheckOpret(const CTransaction & tx, vscript_t &opret) { - if (tx.vout.size() > 0 && GetOpReturnData(tx.vout.back().scriptPubKey, opret) && opret.size() > 2 && opret.begin()[0] == EVAL_PRICES && IS_CHARINSTR(opret.begin()[1], "BACF")) + if (tx.vout.size() > 0 && GetOpReturnData(tx.vout.back().scriptPubKey, opret) && opret.size() > 2 && opret.begin()[0] == EVAL_PRICES && IS_CHARINSTR(opret.begin()[1], "BACFR")) return opret.begin()[1]; else return (uint8_t)0; @@ -213,9 +240,12 @@ static bool ValidateBetTx(struct CCcontract_info *cp, Eval *eval, const CTransac int16_t leverage; CPubKey pk, pricespk; std::vector vec; + + // check payment cc config: if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0 ) GetKomodoEarlytxidScriptPub(); - if (bettx.vout.size() < 5 || bettx.vout.size() > 6) + + if (bettx.vout.size() < 6 || bettx.vout.size() > 7) return eval->Invalid("incorrect vout number for bet tx"); vscript_t opret; @@ -235,7 +265,7 @@ static bool ValidateBetTx(struct CCcontract_info *cp, Eval *eval, const CTransac return eval->Invalid("the fee was paid to wrong address."); int64_t betamount = bettx.vout[2].nValue; - if (betamount != (positionsize * 199) / 200) { + if (betamount != PRICES_SUBREVSHAREFEE(positionsize)) { return eval->Invalid("invalid position size in the opreturn"); } @@ -264,7 +294,11 @@ static bool ValidateAddFundingTx(struct CCcontract_info *cp, Eval *eval, const C CPubKey pk, pricespk; vscript_t vintxOpret; - if (addfundingtx.vout.size() < 3 || addfundingtx.vout.size() > 4) + // check payment cc config: + if (ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0) + GetKomodoEarlytxidScriptPub(); + + if (addfundingtx.vout.size() < 4 || addfundingtx.vout.size() > 5) return eval->Invalid("incorrect vout number for add funding tx"); vscript_t opret; @@ -286,10 +320,20 @@ static bool ValidateAddFundingTx(struct CCcontract_info *cp, Eval *eval, const C if (MakeCC1vout(cp->evalcode, addfundingtx.vout[1].nValue, pricespk) != addfundingtx.vout[1]) return eval->Invalid("cannot validate vout1 in add funding tx with global pk"); + // This should be all you need to verify it, maybe also check amount? + if (addfundingtx.vout[2].scriptPubKey != KOMODO_EARLYTXID_SCRIPTPUB) + return eval->Invalid("the fee was paid to wrong address."); + + int64_t betamount = addfundingtx.vout[1].nValue; + if (betamount != PRICES_SUBREVSHAREFEE(amount)) { + return eval->Invalid("invalid bet position size in the opreturn"); + } + return true; } -// validate costbasis tx helper +// validate costbasis tx helper (deprecated) +/* static bool ValidateCostbasisTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & costbasistx, const CTransaction & bettx) { uint256 bettxid; @@ -349,6 +393,7 @@ static bool ValidateCostbasisTx(struct CCcontract_info *cp, Eval *eval, const CT return true; } +*/ // validate final tx helper static bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & finaltx, const CTransaction & bettx) @@ -357,8 +402,8 @@ static bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTrans int64_t amount; CPubKey pk, pricespk; int64_t profits; - int32_t height; - int64_t firstprice, costbasis, addedbets, positionsize; + int32_t lastheight; + int64_t firstprice, costbasis, lastprice, liquidationprice, equity, fee; int16_t leverage; if (finaltx.vout.size() < 3 || finaltx.vout.size() > 4) { @@ -367,9 +412,14 @@ static bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTrans } vscript_t opret; - if (prices_finalopretdecode(finaltx.vout.back().scriptPubKey, bettxid, profits, height, pk, firstprice, costbasis, addedbets, positionsize, leverage) != 'F') + uint8_t funcId; + if ((funcId = prices_finalopretdecode(finaltx.vout.back().scriptPubKey, bettxid, pk, lastheight, costbasis, lastprice, liquidationprice, equity, fee)) == 0) return eval->Invalid("cannot decode opreturn for final tx"); + // check rekt txid mining: +// if( funcId == 'R' && (finaltx.GetHash().begin()[0] != 0 || finaltx.GetHash().begin()[31] != 0) ) +// return eval->Invalid("incorrect rekt txid"); + if (bettx.GetHash() != bettxid) return eval->Invalid("incorrect bettx id"); @@ -381,6 +431,9 @@ static bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTrans if( finaltx.vout.size() == 3 && MakeCC1vout(cp->evalcode, finaltx.vout[1].nValue, pricespk) != finaltx.vout[1] ) return eval->Invalid("cannot validate vout1 in final tx with global pk"); + // TODO: validate exitfee for 'R' + // TODO: validate amount for 'F' + return true; } @@ -404,7 +457,7 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx { vscript_t vopret; - if (strcmp(ASSETCHAINS_SYMBOL, "REKT0") == 0 && chainActive.Height() < 2965) + if (strcmp(ASSETCHAINS_SYMBOL, "REKT0") == 0 && chainActive.Height() < 5851) return true; // check basic opret rules: if (PricesCheckOpret(tx, vopret) == 0) @@ -416,7 +469,7 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx vscript_t firstVinTxOpret; bool foundFirst = false; int32_t ccVinCount = 0; - uint32_t prevoutN = 0; + uint32_t prevCCoutN = 0; // check basic rules: @@ -435,13 +488,13 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx std::cerr << "PricesValidate() " << "cannot find prices opret in vintx" << std::endl; } - if (funcId != 'F' && vintxOpret.begin()[1] == 'B' && prevoutN == 1) { + if (!IS_CHARINSTR(funcId, "FR") && vintxOpret.begin()[1] == 'B' && prevCCoutN == 1) { //return eval->Invalid("cannot spend bet marker"); - std::cerr << "PricesValidate() " << " non-final tx cannot spend cc marker vout=" << prevoutN << std::endl; + std::cerr << "PricesValidate() " << " non-final tx cannot spend cc marker vout=" << prevCCoutN << std::endl; } if (!foundFirst) { - prevoutN = vin.prevout.n; + prevCCoutN = vin.prevout.n; firstVinTx = vintx; firstVinTxOpret = vintxOpret; foundFirst = true; @@ -452,7 +505,7 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx if (!foundFirst) return eval->Invalid("prices cc vin not found"); - if (funcId != 'F' && ccVinCount > 1) {// for all prices tx except final tx only one cc vin is allowed + if (!IS_CHARINSTR(funcId, "FR") && ccVinCount > 1) {// for all prices tx except final tx only one cc vin is allowed //return eval->Invalid("only one prices cc vin allowed for this tx"); std::cerr << "PricesValidate() " << "only one prices cc vin allowed for this tx" << std::endl; } @@ -464,26 +517,24 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx case 'A': // add funding // check tx structure: if (!ValidateAddFundingTx(cp, eval, tx, firstVinTx)) { - //return false; // invalid state is already set in the func std::cerr << "PricesValidate() " << "ValidateAddFundingTx = false " << eval->state.GetRejectReason() << std::endl; + return false; // invalid state is already set in the func } if (firstVinTxOpret.begin()[1] == 'B') { if (!ValidateBetTx(cp, eval, firstVinTx)) {// check tx structure - // return false; std::cerr << "PricesValidate() " << "funcId=A ValidatebetTx = false " << eval->state.GetRejectReason() << std::endl; + return false; // invalid state is already set in the func } } - else if (firstVinTxOpret.begin()[1] == 'A') { - // no need to validate the previous addfunding tx (it was validated when added) - } - if (prevoutN != 0) { // check spending rules - // return eval->Invalid("incorrect vintx vout to spend"); - std::cerr << "PricesValidate() " << "add fund tx incorrect vout to spend=" << prevoutN << std::endl; + if (prevCCoutN != 0) { // check spending rules + std::cerr << "PricesValidate() " << "addfunding tx incorrect vout to spend=" << prevCCoutN << std::endl; + return eval->Invalid("incorrect vintx vout to spend"); } break; + /* not used: case 'C': // set costbasis if (!ValidateCostbasisTx(cp, eval, tx, firstVinTx)) { //return false; @@ -498,20 +549,21 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx std::cerr << "PricesValidate() " << "costbasis tx incorrect vout to spend=" << prevoutN << std::endl; } //return eval->Invalid("test: costbasis is good"); - break; + break; */ case 'F': // final tx + case 'R': if (!ValidateFinalTx(cp, eval, tx, firstVinTx)) { - ///return false; std::cerr << "PricesValidate() " << "ValidateFinalTx=false " << eval->state.GetRejectReason() << std::endl; + return false; } if (!ValidateBetTx(cp, eval, firstVinTx)) { - // return false; std::cerr << "PricesValidate() " << "ValidateBetTx=false " << eval->state.GetRejectReason() << std::endl; + return false; } - if (prevoutN != 1) { // check spending rules - // return eval->Invalid("incorrect vout to spend"); - std::cerr << "PricesValidate() "<< "final tx incorrect vout to spend=" << prevoutN << std::endl; + if (prevCCoutN != 1) { // check spending rules + std::cerr << "PricesValidate() "<< "final tx incorrect vout to spend=" << prevCCoutN << std::endl; + return eval->Invalid("incorrect vout to spend"); } break; @@ -560,6 +612,19 @@ int64_t AddPricesInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, ch return(totalinputs); } +// return min equity percentage depending on leverage value +// for lev=1 2% +// for lev>=100 10% +double prices_minmarginpercent(int16_t leverage) +{ + int16_t absleverage = std::abs(leverage); + if (absleverage < 100) + return (absleverage * 0.080808 + 1.9191919) / 100.0; + else + return 0.1; +} + + UniValue prices_rawtxresult(UniValue &result, std::string rawtx, int32_t broadcastflag) { CTransaction tx; @@ -881,10 +946,10 @@ int32_t prices_syntheticvec(std::vector &vec, std::vector return(-3); } depth -= need; - std::cerr << "prices_syntheticvec() opcode=" << opcode << " opstr=" << opstr << " need=" << need << " depth=" << depth << std::endl; + ///std::cerr << "prices_syntheticvec() opcode=" << opcode << " opstr=" << opstr << " need=" << need << " depth=" << depth << std::endl; if ((opcode & KOMODO_PRICEMASK) != PRICES_WEIGHT) { // skip weight depth++; // increase operands count - std::cerr << "depth++=" << depth << std::endl; + ///std::cerr << "depth++=" << depth << std::endl; } if (depth > 3) { std::cerr << "prices_syntheticvec() too many operands, last=" << opstr << std::endl; @@ -930,14 +995,14 @@ int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t mpz_set_ui(mpzResult, 0); // clear result to test overflow (see below) - std::cerr << "prices_syntheticprice" << " i=" << i << " mpzTotalPrice=" << mpz_get_si(mpzTotalPrice) << " value=" << value << " depth=" << depth << " opcode&KOMODO_PRICEMASK=" << (opcode & KOMODO_PRICEMASK) < 0 ) + // std::cerr << "prices_syntheticprice top pricestack[depth-1=" << depth-1 << "]=" << pricestack[depth-1] << std::endl; + // else + // std::cerr << "prices_syntheticprice pricestack empty" << std::endl; } free(pricedata); @@ -1134,14 +1199,22 @@ int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t mpz_clear(mpzTotalPrice); mpz_clear(mpzPriceValue); - if (errcode != 0) + if (errcode != 0) std::cerr << "prices_syntheticprice errcode in switch=" << errcode << std::endl; + + if( errcode == -1 ) { + std::cerr << "prices_syntheticprice error getting price (could be end of chain)" << std::endl; + return errcode; + } if (errcode == -13) { std::cerr << "prices_syntheticprice overflow in price" << std::endl; return errcode; } - + if (errcode == -14) { + std::cerr << "prices_syntheticprice price is zero, not enough historic data yet" << std::endl; + return errcode; + } if (den == 0) { std::cerr << "prices_syntheticprice den==0 return err=-11" << std::endl; return(-11); @@ -1154,7 +1227,7 @@ int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t std::cerr << "prices_syntheticprice err=" << errcode << std::endl; return(errcode); } - std::cerr << "prices_syntheticprice priceIndex=" << priceIndex << " den=" << den << std::endl; +// std::cerr << "prices_syntheticprice priceIndex=totalprice/den=" << priceIndex << " den=" << den << std::endl; return priceIndex; } @@ -1191,24 +1264,24 @@ int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t if (minmax) { // if we are within day window, set temp costbasis to max (or min) price value if (leverage > 0 && price > costbasis) { costbasis = price; // set temp costbasis - std::cerr << "prices_syntheticprofits() minmax costbasis=" << costbasis << std::endl; + //std::cerr << "prices_syntheticprofits() minmax costbasis=" << costbasis << std::endl; } else if (leverage < 0 && (costbasis == 0 || price < costbasis)) { costbasis = price; - std::cerr << "prices_syntheticprofits() minmax costbasis=" << costbasis << std::endl; + //std::cerr << "prices_syntheticprofits() minmax costbasis=" << costbasis << std::endl; } //else { //-> use the previous value // std::cerr << "prices_syntheticprofits() unchanged costbasis=" << costbasis << " price=" << price << " leverage=" << leverage << std::endl; //} } else { - if (height == firstheight + COSTBASIS_PERIOD) { + //if (height == firstheight + COSTBASIS_PERIOD) { // if costbasis not set, just set it //costbasis = price; // use calculated minmax costbasis - std::cerr << "prices_syntheticprofits() use permanent costbasis=" << costbasis << " at height=" << height << std::endl; - } + //std::cerr << "prices_syntheticprofits() use permanent costbasis=" << costbasis << " at height=" << height << std::endl; + //} } // normalize to 10,000,000 to prevent underflow @@ -1265,7 +1338,7 @@ int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t else profits = 0; - std::cerr << "prices_syntheticprofits() profits=" << profits << std::endl; + //std::cerr << "prices_syntheticprofits() profits=" << profits << std::endl; return 0; // (positionsize + addedbets + profits); } @@ -1274,7 +1347,7 @@ void prices_betjson(UniValue &result, std::vector bets, int16_t leve { UniValue resultbets(UniValue::VARR); - int64_t totalbets = 0; + int64_t totalposition = 0; int64_t totalprofits = 0; for (auto b : bets) { @@ -1284,14 +1357,14 @@ void prices_betjson(UniValue &result, std::vector bets, int16_t leve entry.push_back(Pair("costbasis", ValueFromAmount(b.costbasis))); entry.push_back(Pair("firstheight", b.firstheight)); resultbets.push_back(entry); - totalbets += b.positionsize; + totalposition += b.positionsize; totalprofits += b.profits; } - int64_t equity = totalbets + totalprofits; + int64_t equity = totalposition + totalprofits; result.push_back(Pair("bets", resultbets)); result.push_back(Pair("leverage", (int64_t)leverage)); - result.push_back(Pair("TotalPositionSize", ValueFromAmount(totalbets))); + result.push_back(Pair("TotalPositionSize", ValueFromAmount(totalposition))); result.push_back(Pair("TotalProfits", ValueFromAmount(totalprofits))); result.push_back(Pair("equity", ValueFromAmount(equity))); result.push_back(Pair("LastPrice", ValueFromAmount(lastprice))); @@ -1363,9 +1436,9 @@ int64_t prices_enumaddedbets(uint256 &batontxid, std::vector &bets, addedBetsTotal += amount; added.positionsize = amount; - added.firstheight = blockIdx.GetHeight(); + added.firstheight = blockIdx.GetHeight(); //TODO: check if this is correct (to get height from the block not from the opret) bets.push_back(added); - std::cerr << "prices_batontxid() added amount=" << amount << std::endl; + //std::cerr << "prices_batontxid() added amount=" << amount << std::endl; } else { std::cerr << "prices_batontxid() cannot load or decode add bet tx, isLoaded=" << isLoaded << " funcId=" << (int)funcId << std::endl; @@ -1407,9 +1480,24 @@ UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector< result.push_back(Pair("error", "invalid synthetic")); return(result); } + + if (!prices_isacceptableamount(vec, amount, leverage)) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "too big amount and leverage")); + return(result); + } + if (AddNormalinputs(mtx, mypk, amount + 4 * txfee, 64) >= amount + 4 * txfee) { - betamount = (amount * 199) / 200; + betamount = PRICES_SUBREVSHAREFEE(amount); + + /*if( amount - betamount < PRICES_REVSHAREDUST) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "bet amount too small")); + return(result); + }*/ + + mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, mypk)); // vout0 baton for total funding // mtx.vout.push_back(MakeCC1vout(cp->evalcode, (amount - betamount) + 2 * txfee, pricespk)); // vout1, when spent, costbasis is set mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, pricespk)); // vout1 cc marker (NVOUT_CCMARKER) @@ -1422,7 +1510,8 @@ UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector< LOCK(cs_main); GetKomodoEarlytxidScriptPub(); } - mtx.vout.push_back(CTxOut(amount-betamount, KOMODO_EARLYTXID_SCRIPTPUB)); + mtx.vout.push_back(CTxOut(amount-betamount, KOMODO_EARLYTXID_SCRIPTPUB)); + //test: mtx.vout.push_back(CTxOut(amount - betamount, CScript() << ParseHex("037c803ec82d12da939ac04379bbc1130a9065c53d8244a61eece1db942cf0efa7") << OP_CHECKSIG)); // vout4 test revshare fee rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_betopret(mypk, nextheight - 1, amount, leverage, firstprice, vec, zeroid)); return(prices_rawtxresult(result, rawtx, 0)); @@ -1437,11 +1526,14 @@ UniValue PricesAddFunding(int64_t txfee, uint256 bettxid, int64_t amount) { int32_t nextheight = komodo_nextheight(); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; CTransaction bettx; - CPubKey pricespk, mypk; - //int64_t addedbets = 0, betamount, firstprice; - std::vector vec; - uint256 batontxid; + struct CCcontract_info *cp, C; + CTransaction bettx; + CPubKey pricespk, mypk, pk; + int64_t positionsize, betamount, firstprice; + int32_t firstheight; + std::vector vecparsed; + uint256 batontxid, tokenid, hashBlock; + int16_t leverage = 0; std::string rawtx; //char myaddr[64]; @@ -1450,15 +1542,48 @@ UniValue PricesAddFunding(int64_t txfee, uint256 bettxid, int64_t amount) txfee = PRICES_TXFEE; mypk = pubkey2pk(Mypubkey()); pricespk = GetUnspendable(cp, 0); - //GetCCaddress(cp, myaddr, mypk); + + if (!myGetTransaction(bettxid, bettx, hashBlock) || + bettx.vout.size() <= 3 || + hashBlock.IsNull() || + prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vecparsed, tokenid) != 'B') { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid bet tx")); + return(result); + } + + if (!prices_isacceptableamount(vecparsed, amount, leverage)) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "too big amount and leverage")); + return(result); + } + if (AddNormalinputs(mtx, mypk, amount + 2*txfee, 64) >= amount + 2*txfee) { + betamount = PRICES_SUBREVSHAREFEE(amount); + /*if (amount - betamount < PRICES_REVSHAREDUST) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "bet amount too small")); + return(result); + }*/ + std::vector bets; if (prices_enumaddedbets(batontxid, bets, bettxid) >= 0) { mtx.vin.push_back(CTxIn(batontxid, 0, CScript())); mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, mypk)); // vout0 baton for total funding - mtx.vout.push_back(MakeCC1vout(cp->evalcode, amount, pricespk)); // vout1 added amount + mtx.vout.push_back(MakeCC1vout(cp->evalcode, betamount, pricespk)); // vout1 added amount + + if (ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0) + { + // Lock here, as in validation we cannot call lock in the function itself. + // may not be needed as the validation call to update the global, is called in a LOCK already, and it can only update there and here. + LOCK(cs_main); + GetKomodoEarlytxidScriptPub(); + } + mtx.vout.push_back(CTxOut(amount - betamount, KOMODO_EARLYTXID_SCRIPTPUB)); + // test: mtx.vout.push_back(CTxOut(amount - betamount, CScript() << ParseHex("037c803ec82d12da939ac04379bbc1130a9065c53d8244a61eece1db942cf0efa7") << OP_CHECKSIG)); //vout2 test revshare fee + rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_addopret(bettxid, mypk, amount)); return(prices_rawtxresult(result, rawtx, 0)); } @@ -1481,9 +1606,9 @@ int32_t prices_scanchain(std::vector &bets, int16_t leverage, std::v return -1; bool stop = false; - for (int32_t height = bets[0].firstheight; ; height++) // the last datum for 24h is the costbasis value + for (int32_t height = bets[0].firstheight+1; ; height++) // the last datum for 24h is the costbasis value { - int64_t totalbets = 0; + int64_t totalposition = 0; int64_t totalprofits = 0; // scan upto the chain tip @@ -1493,11 +1618,11 @@ int32_t prices_scanchain(std::vector &bets, int16_t leverage, std::v int32_t retcode = prices_syntheticprofits(bets[i].costbasis, bets[i].firstheight, height, leverage, vec, bets[i].positionsize, bets[i].profits, lastprice); if (retcode < 0) { - std::cerr << "prices_scanchain() prices_syntheticprofits returned -1, breaking" << std::endl; + std::cerr << "prices_scanchain() prices_syntheticprofits returned -1, finishing..." << std::endl; stop = true; break; } - totalbets += bets[i].positionsize; + totalposition += bets[i].positionsize; totalprofits += bets[i].profits; } } @@ -1506,8 +1631,8 @@ int32_t prices_scanchain(std::vector &bets, int16_t leverage, std::v break; endheight = height; - int64_t equity = totalbets + totalprofits; - if (equity < 0) + int64_t equity = totalposition + totalprofits; + if (equity <= (int64_t)((double)totalposition * prices_minmarginpercent(leverage))) { // we are in loss break; } @@ -1588,6 +1713,34 @@ UniValue PricesSetcostbasis(int64_t txfee, uint256 bettxid) } +// pricesaddfunding rpc impl: add yet another bet +UniValue PricesRefillFund(int64_t amount) +{ + int32_t nextheight = komodo_nextheight(); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); + struct CCcontract_info *cp, C; + CPubKey pricespk, mypk, pk; + std::string rawtx; + //char myaddr[64]; + + cp = CCinit(&C, EVAL_PRICES); + const int64_t txfee = PRICES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp, 0); + + if (AddNormalinputs(mtx, mypk, amount + txfee, 64) >= amount + txfee) + { + mtx.vout.push_back(MakeCC1vout(cp->evalcode, amount, pricespk)); // vout1 added amount + rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, CScript()); + return(prices_rawtxresult(result, rawtx, 0)); + + } + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "not enough funds")); + return(result); +} + + int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo) { CTransaction bettx; @@ -1598,39 +1751,64 @@ int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo) if (hashBlock.IsNull()) return -2; + + // TODO: forget old tx + //CBlockIndex *bi = komodo_getblockindex(hashBlock); + //if (bi && bi->GetHeight() < 5342) + // return -5; + OneBetData bet1; - if (prices_betopretdecode(bettx.vout.back().scriptPubKey, betinfo.pk, bet1.firstheight, bet1.positionsize, betinfo.leverage, betinfo.firstprice, betinfo.parsed, betinfo.tokenid) == 'B') + if (prices_betopretdecode(bettx.vout.back().scriptPubKey, betinfo.pk, bet1.firstheight, bet1.positionsize, betinfo.leverage, betinfo.firstprice, betinfo.vecparsed, betinfo.tokenid) == 'B') { uint256 finaltxid; int32_t vini; int32_t finaltxheight; //, endheight; //std::vector bets; - + betinfo.txid = bettxid; if (CCgetspenttxid(finaltxid, vini, finaltxheight, bettxid, NVOUT_CCMARKER) == 0) betinfo.isOpen = false; else betinfo.isOpen = true; - //bet1.amount = betinfo.positionsize; - //bet1.firstheight = firstheight; + // override with real amount (TODO: check this) + //bet1.positionsize = bettx.vout[2].nValue; + betinfo.bets.push_back(bet1); prices_enumaddedbets(batontxid, betinfo.bets, bettxid); - if (prices_scanchain(betinfo.bets, betinfo.leverage, betinfo.parsed, betinfo.lastprice, betinfo.lastheight) < 0) { + if (!betinfo.isOpen) { + CTransaction finaltx; + uint256 hashBlock; + vscript_t vopret; + if (myGetTransaction(finaltxid, finaltx, hashBlock) && finaltx.vout.size() > 0 && PricesCheckOpret(finaltx, vopret) != 0) { + uint8_t funcId = prices_finalopretdecode(finaltx.vout.back().scriptPubKey, betinfo.txid, betinfo.pk, betinfo.lastheight, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, betinfo.exitfee); + if (funcId == 0) + return -3; + + betinfo.isRekt = (funcId == 'R'); + + // return 0; + } + else + return -6; + } + + + if (prices_scanchain(betinfo.bets, betinfo.leverage, betinfo.vecparsed, betinfo.lastprice, betinfo.lastheight) < 0) { return -4; } - mpz_t mpzTotalbets; + mpz_t mpzTotalPosition; mpz_t mpzTotalprofits; mpz_t mpzTotalcostbasis; - mpz_init(mpzTotalbets); + mpz_init(mpzTotalPosition); mpz_init(mpzTotalprofits); mpz_init(mpzTotalcostbasis); - int64_t totalbets = 0; + int64_t totalposition = 0; int64_t totalprofits = 0; for (auto b : betinfo.bets) { @@ -1649,26 +1827,26 @@ int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo) mpz_mul_ui(mpzProduct, mpzProduct, (uint64_t)b.positionsize); // b.costbasis * b.amount mpz_add(mpzTotalcostbasis, mpzTotalcostbasis, mpzProduct); //averageCostbasis += b.costbasis * b.amount; - mpz_add_ui(mpzTotalbets, mpzTotalbets, (uint64_t)b.positionsize); //totalbets += b.amount; + mpz_add_ui(mpzTotalPosition, mpzTotalPosition, (uint64_t)b.positionsize); //totalposition += b.amount; mpz_add(mpzTotalprofits, mpzTotalprofits, mpzProfits); //totalprofits += b.profits; - totalbets += b.positionsize; + totalposition += b.positionsize; totalprofits += b.profits; mpz_clear(mpzProduct); mpz_clear(mpzProfits); } - betinfo.equity = totalbets + totalprofits; + betinfo.equity = totalposition + totalprofits; //int64_t averageCostbasis = 0; - if (mpz_get_ui(mpzTotalbets) != 0) { //prevent zero div + if (mpz_get_ui(mpzTotalPosition) != 0) { //prevent zero div mpz_t mpzAverageCostbasis; mpz_init(mpzAverageCostbasis); - //averageCostbasis = totalcostbasis / totalbets; + //averageCostbasis = totalcostbasis / totalposition; mpz_mul_ui(mpzTotalcostbasis, mpzTotalcostbasis, SATOSHIDEN); // profits *= SATOSHIDEN normalization to prevent loss of significance while division - mpz_tdiv_q(mpzAverageCostbasis, mpzTotalcostbasis, mpzTotalbets); + mpz_tdiv_q(mpzAverageCostbasis, mpzTotalcostbasis, mpzTotalPosition); mpz_tdiv_q_ui(mpzAverageCostbasis, mpzAverageCostbasis, SATOSHIDEN); // profits /= SATOSHIDEN de-normalization @@ -1678,18 +1856,21 @@ int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo) betinfo.liquidationprice = 0; if (betinfo.leverage != 0) {// prevent zero div - betinfo.liquidationprice = betinfo.averageCostbasis - betinfo.averageCostbasis / betinfo.leverage; + betinfo.liquidationprice = betinfo.averageCostbasis - (betinfo.averageCostbasis * (1 - prices_minmarginpercent(betinfo.leverage))) / betinfo.leverage; } - if (betinfo.equity >= 0) - betinfo.isRekt = false; - else - { - betinfo.isRekt = true; - betinfo.rektfee = totalbets / 500; + if (!betinfo.isRekt) { // not set by check for final tx + + if (betinfo.equity > (int64_t)((double)totalposition * prices_minmarginpercent(betinfo.leverage))) + betinfo.isRekt = false; + else + { + betinfo.isRekt = true; + betinfo.exitfee = (int64_t)(((double)totalposition * prices_minmarginpercent(betinfo.leverage)) / 10); // was: totalposition / 500 + } } - mpz_clear(mpzTotalbets); + mpz_clear(mpzTotalPosition); mpz_clear(mpzTotalprofits); mpz_clear(mpzTotalcostbasis); return 0; @@ -1706,18 +1887,13 @@ UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); struct CCcontract_info *cp, C; CTransaction bettx; -/* uint256 hashBlock, tokenid, batontxid; - int64_t firstprice, lastprice = 0, positionsize; - int32_t firstheight; - int16_t leverage; - std::vector vec; */ int64_t myfee = 0; CPubKey pk, mypk, pricespk; std::string rawtx; char destaddr[64]; cp = CCinit(&C, EVAL_PRICES); - if (txfee == 0) // TODO: what did we want tot do with txfee in prices? + if (txfee == 0) // TODO: what did we want to do with txfee in prices? txfee = PRICES_TXFEE; mypk = pubkey2pk(Mypubkey()); pricespk = GetUnspendable(cp, 0); @@ -1746,11 +1922,11 @@ UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) return(result); } - int64_t totalbets = 0; + int64_t totalposition = 0; int64_t totalprofits = 0; for (auto b : betinfo.bets) { - totalbets += b.positionsize; + totalposition += b.positionsize; totalprofits += b.profits; } @@ -1764,7 +1940,7 @@ UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice); // fill output if (betinfo.isRekt) { - myfee = betinfo.rektfee; // consolation fee for loss + myfee = betinfo.exitfee; // consolation fee for loss } if (myfee != 0) { @@ -1778,8 +1954,37 @@ UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk)); /// mtx.vout.push_back(MakeCC1vout(cp->evalcode, bettx.vout[2].nValue - myfee - txfee, pricespk)); // change - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(bettxid, totalprofits, rektheight, mypk, betinfo.firstprice, 0, totalbets /*- positionsize*/, 0/*positionsize*/, betinfo.leverage)); - return(prices_rawtxresult(result, rawtx, 0)); + + // make some PoW to get txid=0x00.....00 to 'faucet' rekts + fprintf(stderr, "start PoW at %u\n", (uint32_t)time(NULL)); + uint32_t nonce = rand() & 0xfffffff; + 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]); + //} + } + fprintf(stderr, "couldnt generate valid txid %u\n", (uint32_t)time(NULL)); + + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not generate valid txid")); + return(result); } else { @@ -1796,12 +2001,6 @@ UniValue PricesCashout(int64_t txfee, uint256 bettxid) CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); struct CCcontract_info *cp, C; char destaddr[64]; -/* CTransaction bettx; - uint256 hashBlock, batontxid, tokenid; - int64_t positionsize, firstprice, lastprice = 0; - int32_t firstheight; - int16_t leverage; - std::vector vec;*/ int64_t CCchange = 0, inputsum; CPubKey pk, mypk, pricespk; std::string rawtx; @@ -1837,11 +2036,11 @@ UniValue PricesCashout(int64_t txfee, uint256 bettxid) return(result); } - int64_t totalbets = 0; + int64_t totalposition = 0; int64_t totalprofits = 0; for (auto b : betinfo.bets) { - totalbets += b.positionsize; + totalposition += b.positionsize; totalprofits += b.profits; } @@ -1862,20 +2061,18 @@ UniValue PricesCashout(int64_t txfee, uint256 bettxid) } mtx.vin.push_back(CTxIn(bettxid, NVOUT_CCMARKER, CScript())); // spend cc marker - if ((inputsum = AddPricesInputs(cp, mtx, destaddr, betinfo.equity + txfee, 64)) > betinfo.equity + txfee) + if ((inputsum = AddPricesInputs(cp, mtx, destaddr, betinfo.equity + txfee, 64)) > betinfo.equity + txfee) // TODO: why txfee from the fund? CCchange = (inputsum - betinfo.equity); mtx.vout.push_back(CTxOut(betinfo.equity, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); if (CCchange >= txfee) mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk)); // TODO: what should the opret param be: - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(bettxid, totalprofits, nextheight - 1, mypk, betinfo.firstprice, 0, totalbets/*- betinfo.positionsize*/, 0/*betinfo.positionsize*/, betinfo.leverage)); + rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(false, bettxid, mypk, nextheight-1, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, txfee, 0)); return(prices_rawtxresult(result, rawtx, 0)); } - - // pricesinfo rpc impl UniValue PricesInfo(uint256 bettxid, int32_t refheight) { @@ -1908,6 +2105,10 @@ UniValue PricesInfo(uint256 bettxid, int32_t refheight) else if (retcode == -4) { result.push_back(Pair("result", "error")); result.push_back(Pair("error", "error scanning chain")); + } + else { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", retcode)); } return(result); } @@ -1917,11 +2118,13 @@ UniValue PricesInfo(uint256 bettxid, int32_t refheight) else { result.push_back(Pair("rekt", (int64_t)1)); - result.push_back(Pair("rektfee", betinfo.rektfee)); + result.push_back(Pair("rektfee", betinfo.exitfee)); result.push_back(Pair("rektheight", betinfo.lastheight)); } - std::string expr = prices_getsourceexpression(betinfo.parsed); + result.push_back(Pair("open", betinfo.isOpen ? 1 : 0 )); + + std::string expr = prices_getsourceexpression(betinfo.vecparsed); result.push_back(Pair("expression", expr)); result.push_back(Pair("reduced", prices_getreducedexpr(expr))); // result.push_back(Pair("batontxid", batontxid.GetHex())); @@ -1960,6 +2163,12 @@ UniValue PricesList(uint32_t filter, CPubKey mypk) if (GetTransaction(txid, vintx, hashBlock, false) != 0) { + + // TODO: forget old tx + //CBlockIndex *bi = komodo_getblockindex(hashBlock); + //if (bi && bi->GetHeight() < 5342) + // return; + bool bAppend = false; if (vintx.vout.size() > 0 && prices_betopretdecode(vintx.vout.back().scriptPubKey, pk, height, amount, leverage, firstprice, vec, tokenid) == 'B' && (mypk == CPubKey() || mypk == pk)) // if only mypubkey to list @@ -1987,7 +2196,7 @@ UniValue PricesList(uint32_t filter, CPubKey mypk) SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) { - if( it->first.txindex == NVOUT_NORMALMARKER ) + if( it->first.index == NVOUT_NORMALMARKER ) AddBetToList(it->first.txhash); } @@ -2002,12 +2211,244 @@ UniValue PricesList(uint32_t filter, CPubKey mypk) } -void prices_addbookentry(uint256 txid) +static bool prices_addbookentry(uint256 txid, std::vector &book) { BetInfo betinfo; - //if( prices_getbetinfo(txid, betinfo) == 0 ) + if (prices_getbetinfo(txid, betinfo) == 0) { + book.push_back(betinfo); + return true; + } + return false; } + +static bool prices_ispositionup(const std::vector &vecparsed, int16_t leverage) { + if (vecparsed.size() > 1 && vecparsed.size() <= 3) { + uint16_t opcode = vecparsed[0]; + + int32_t value = (opcode & (KOMODO_MAXPRICES - 1)); // filter index or weight = opcode & (2048-1) + + if ((opcode & KOMODO_PRICEMASK) == 0) { + char name[65]; + if (komodo_pricename(name, value)) { + std::string upperquote, bottomquote; + prices_splitpair(std::string(name), upperquote, bottomquote); + + uint16_t opcode1 = vecparsed[1]; + bool isInverted = ((opcode1 & KOMODO_PRICEMASK) == PRICES_INV); + + //std::cerr << "prices_ispositionup upperquote=" << upperquote << " bottomquote=" << bottomquote << " opcode1=" << opcode1 << " (opcode1 & KOMODO_PRICEMASK)=" << (opcode1 & KOMODO_PRICEMASK) << std::endl; + + if (upperquote == "BTC" || bottomquote == "BTC") { // it is relatively btc + if (upperquote == "BTC" && (leverage > 0 && !isInverted || leverage < 0 && isInverted) || + bottomquote == "BTC" && (leverage < 0 && !isInverted || leverage > 0 && isInverted)) { + std::cerr << "prices_ispositionup returns true for BTC for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; + return true; + } + else { + std::cerr << "prices_ispositionup returns false for BTC for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; + return false; + } + } + + if (upperquote == "USD" || bottomquote == "USD") { // it is relatively usd + if (upperquote == "USD" && (leverage > 0 && !isInverted || leverage < 0 && isInverted) || + bottomquote == "USD" && (leverage < 0 && !isInverted || leverage > 0 && isInverted)) { + std::cerr << "prices_ispositionup returns true for USD for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; + return true; + } + else { + std::cerr << "prices_ispositionup returns false for USD for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; + return false; + } + } + } + } + } + std::cerr << "prices_ispositionup returns false for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; + return false; +} + +static bool prices_isopposite(BetInfo p1, BetInfo p2) { + if (p1.vecparsed.size() <= 3 && p2.vecparsed.size() <= 3) { // simple synthetic exp + + uint16_t opcode1 = p1.vecparsed[0]; + uint16_t opcode2 = p2.vecparsed[0]; + + int32_t value1 = (opcode1 & (KOMODO_MAXPRICES - 1)); // index or weight + int32_t value2 = (opcode2 & (KOMODO_MAXPRICES - 1)); // index or weight + + if ( (opcode1 & KOMODO_PRICEMASK) == 0 && (opcode2 & KOMODO_PRICEMASK) == 0 ) { + char name1[65]; + char name2[65]; + if (komodo_pricename(name1, value1) && komodo_pricename(name2, value2)) { + + uint16_t opcode1 = p1.vecparsed[1]; + uint16_t opcode2 = p2.vecparsed[1]; + + std::string upperquote1, bottomquote1, upperquote2, bottomquote2; + prices_splitpair(std::string(name1), upperquote1, bottomquote1); + prices_splitpair(std::string(name2), upperquote2, bottomquote2); + + bool isInverted1 = ((opcode1 & KOMODO_PRICEMASK) != PRICES_INV); + bool isInverted2 = ((opcode2 & KOMODO_PRICEMASK) != PRICES_INV); + + if (/*upperquote1 == bottomquote2 && bottomquote1 == upperquote2 && (p1.leverage > 0 == p2.leverage > 0 || (opcode1 & KOMODO_PRICEMASK) == PRICES_INV == (opcode2 & KOMODO_PRICEMASK) == PRICES_INV) ||*/ + upperquote1 == upperquote2 && bottomquote1 == bottomquote2 && ((p1.leverage > 0) != (p2.leverage > 0) || isInverted1 != isInverted2) ) + return true; + } + } + } + return false; +} + + + +static std::string findMatchedBook(const std::vector &vecparsed, const std::map > & bookmatched) { + + if (vecparsed.size() > 1 && vecparsed.size() <= 3) { + uint16_t opcode = vecparsed[0]; + + int32_t value = (opcode & (KOMODO_MAXPRICES - 1)); // filter index or weight = opcode & (2048-1) + + if ((opcode & KOMODO_PRICEMASK) == 0) { + char name[65]; + if (komodo_pricename(name, value)) { + auto it = bookmatched.find(std::string(name)); + if (it != bookmatched.end()) + return it->first; + } + } + } + return std::string(""); +} + + +void prices_getorderbook(std::map > & bookmatched, std::map &matchedTotals, TotalFund &fundTotals) +{ + std::vector book; + std::vector > addressIndex; + struct CCcontract_info *cp, C; + + cp = CCinit(&C, EVAL_PRICES); + + // add all bets: + SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker + for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) + { + if (it->first.index == NVOUT_NORMALMARKER) + prices_addbookentry(it->first.txhash, book); + } + + + // calc total fund amount + fundTotals.totalFund = 0; + fundTotals.totalRekt = 0; + fundTotals.totalEquity = 0; + fundTotals.totalActiveBets = 0; + + std::vector > addressCCunspents; + SetCCunspents(addressCCunspents, cp->unspendableCCaddr, true); // cc marker + for (std::vector >::const_iterator it = addressCCunspents.begin(); it != addressCCunspents.end(); it++) + { + //std::cerr << "totalfund calc txid=" << it->first.txhash.GetHex() << " nvout=" << it->first.index << " satoshis=" << it->second.satoshis << std::endl; + fundTotals.totalFund += it->second.satoshis; + } + + // extract out opposite bets: + while (book.size() > 0) { + + int64_t totalPos = 0; + for (auto bet : book[0].bets) totalPos += bet.positionsize; + + if (book[0].isOpen) { + + fundTotals.totalActiveBets += totalPos; + fundTotals.totalEquity += book[0].equity; + + if (book[0].vecparsed.size() <= 3) { // only short expr check for match: "BTC_USD,1" or "BTC_USD,!,1" + char name[65]; + komodo_pricename(name, (book[0].vecparsed[0] & (KOMODO_MAXPRICES - 1))); + std::string sname = name; + bookmatched[sname].push_back(book[0]); + + for (int j = 1; j < book.size(); j++) { + if (book[0].isOpen && book[j].isOpen) { + if (prices_isopposite(book[0], book[j])) { + + bookmatched[sname].push_back(book[j]); + book.erase(book.begin() + j); + } + } + } + } + else { + // store as is + std::string sname = prices_getsourceexpression(book[0].vecparsed); + bookmatched[sname].push_back(book[0]); + } + } + else { + if( book[0].isRekt ) + fundTotals.totalRekt += (totalPos - book[0].exitfee); + else + fundTotals.totalCashout += (totalPos - book[0].exitfee); + + //TODO: store rekt + } + book.erase(book.begin()); + } + + // calculate cancelling amount + for (auto &m : bookmatched) { // note: use reference &m otherwise isUp will be changed only in a copy + int64_t totalLeveragedPositionUp = 0; + int64_t totalLeveragedPositionDown = 0; + + for (int i = 0; i < m.second.size(); i++) { + int64_t totalPos = 0; + for (auto bet : m.second[i].bets) totalPos += bet.positionsize; + m.second[i].isUp = prices_ispositionup(m.second[i].vecparsed, m.second[i].leverage); + if (m.second[i].isUp) + totalLeveragedPositionUp += totalPos * abs(m.second[i].leverage); + else + totalLeveragedPositionDown += totalPos * abs(m.second[i].leverage); + //std::cerr << "PricesGetOrderbook 0 m.second[i].isUp=" << m.second[i].isUp << " i=" << i << std::endl; + + } + matchedTotals[m.first].diffLeveragedPosition = totalLeveragedPositionUp - totalLeveragedPositionDown; + } +} + +static bool prices_isacceptableamount(const std::vector &vecparsed, int64_t amount, int16_t leverage) { + + std::map > matchedBook; + std::map matchedTotals; + TotalFund fundTotals; + + prices_getorderbook(matchedBook, matchedTotals, fundTotals); + std::string pricename = findMatchedBook(vecparsed, matchedBook); + if (!pricename.empty()) { + std::cerr << "prices_isacceptableamount() found matched book=" << pricename << " diffLeveragedPosition=" << matchedTotals[pricename].diffLeveragedPosition << " expr=" << prices_getsourceexpression(vecparsed) << std::endl; + // could fit into leveraged amount + if (prices_ispositionup(vecparsed, leverage) && amount*abs(leverage) + matchedTotals[pricename].diffLeveragedPosition <= 0) { + std::cerr << "prices_isacceptableamount() could fit into opposite negative lev amount" << std::endl; + return true; + } + if (!prices_ispositionup(vecparsed, leverage) && -amount*abs(leverage) + matchedTotals[pricename].diffLeveragedPosition >= 0) { + std::cerr << "prices_isacceptableamount() could fit into opposite positive lev amount" << std::endl; + return true; + } + } + + std::cerr << "prices_isacceptableamount() amount=" << amount << " leverage=" << leverage << " fundTotals.totalFund=" << fundTotals.totalFund << " fundTotals.totalEquity=" << fundTotals.totalEquity << std::endl; + // if not fit to matched = allow to bet for leveraged amount no more than 10% from free fund + if (amount * leverage < (fundTotals.totalFund - fundTotals.totalEquity) * PRICES_MINAVAILFUNDFRACTION) + return true; + + return false; +} + + // walk through uxtos on the global address // calculate the balance: // + rekt positions @@ -2015,17 +2456,65 @@ void prices_addbookentry(uint256 txid) // - unbalanced positions UniValue PricesGetOrderbook() { - UniValue result(UniValue::VARR); - std::vector > addressIndex, addressIndexCC; - struct CCcontract_info *cp, C; + UniValue result(UniValue::VOBJ); + std::map > matchedBook; + std::map matchedTotals; + TotalFund fundTotals; - cp = CCinit(&C, EVAL_PRICES); + prices_getorderbook(matchedBook, matchedTotals, fundTotals); - SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker - for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) - { - if (it->first.txindex == NVOUT_NORMALMARKER) - prices_addbookentry(it->first.txhash); + /*UniValue resbook (UniValue::VARR); + for (int i = 0; i < book.size(); i++) { + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("expression", prices_getsourceexpression(book[i].vecparsed))); + entry.push_back(Pair("costbasis", book[i].averageCostbasis)); + entry.push_back(Pair("leverage", book[i].leverage)); + entry.push_back(Pair("equity", book[i].equity)); + resbook.push_back(entry); } + result.push_back(Pair("unmatched", resbook)); */ + + // copy to rpc UniResult + for (auto &m : matchedBook) { + UniValue resheader(UniValue::VOBJ); + UniValue resbook(UniValue::VARR); + for (int i = 0; i < m.second.size(); i++) { + UniValue entry(UniValue::VOBJ); + + int64_t totalPos = 0; + for (auto bet : m.second[i].bets) totalPos += bet.positionsize; + entry.push_back(Pair("isOpen", (m.second[i].isOpen ? 1 : 0 ))); + entry.push_back(Pair("expression", prices_getsourceexpression(m.second[i].vecparsed))); + entry.push_back(Pair("positionsize", totalPos)); + entry.push_back(Pair("leverage", m.second[i].leverage)); + entry.push_back(Pair("costbasis", m.second[i].averageCostbasis)); + entry.push_back(Pair("lastprice", m.second[i].lastprice)); + entry.push_back(Pair("equity", m.second[i].equity)); + entry.push_back(Pair("isUpPosition", (m.second[i].isUp ? 1 : 0))); + resbook.push_back(entry); + } + resheader.push_back(Pair("positions", resbook)); + resheader.push_back(Pair("DiffLeveragedPosition", matchedTotals[m.first].diffLeveragedPosition)); + result.push_back(Pair(m.first, resheader)); + } + + //int64_t totalLiabilities = 0; + /* empty + for (int i = 0; i < book.size(); i++) { + if (book[i].isOpen) { + int64_t t = 0; + for (auto b : book[i].bets) t += b.positionsize; + std::cerr << "book[i].txid=" << book[i].txid.GetHex() << " exp=" << prices_getsourceexpression(book[i].vecparsed) << " totalpos=" << t << " equity=" << book[i].equity << std::endl; + totalLiabilities += book[i].equity; + } + } */ + + result.push_back(Pair("TotalFund", ValueFromAmount(fundTotals.totalFund))); + result.push_back(Pair("TotalEquity", ValueFromAmount(fundTotals.totalEquity))); + result.push_back(Pair("TotalRekt", ValueFromAmount(fundTotals.totalRekt))); + result.push_back(Pair("TotalBets", ValueFromAmount(fundTotals.totalActiveBets))); + result.push_back(Pair("TotalCashoutBets", ValueFromAmount(fundTotals.totalCashout))); + +// result.push_back(Pair("TotalLiabilities", ValueFromAmount(totalLiabilities))); return result; } diff --git a/src/crypto/verus_hash.h b/src/crypto/verus_hash.h index 2f1f2cd26..63ff1aaaa 100644 --- a/src/crypto/verus_hash.h +++ b/src/crypto/verus_hash.h @@ -1,134 +1,134 @@ -// (C) 2018 Michael Toutonghi -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/* -This provides the PoW hash function for Verus, enabling CPU mining. -*/ -#ifndef VERUS_HASH_H_ -#define VERUS_HASH_H_ - -#include -#include - -#include - -extern "C" -{ -#include "crypto/haraka.h" -#include "crypto/haraka_portable.h" -} - -class CVerusHash -{ - public: - static void Hash(void *result, const void *data, size_t len); - static void (*haraka512Function)(unsigned char *out, const unsigned char *in); - - static void init(); - - CVerusHash() { } - - CVerusHash &Write(const unsigned char *data, size_t len); - - CVerusHash &Reset() - { - curBuf = buf1; - result = buf2; - curPos = 0; - std::fill(buf1, buf1 + sizeof(buf1), 0); - return *this; - } - - int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } - void ClearExtra() - { - if (curPos) - { - std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - } - } - void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } - - void Finalize(unsigned char hash[32]) - { - if (curPos) - { - std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - (*haraka512Function)(hash, curBuf); - } - else - std::memcpy(hash, curBuf, 32); - } - - private: - // only buf1, the first source, needs to be zero initialized - unsigned char buf1[64] = {0}, buf2[64]; - unsigned char *curBuf = buf1, *result = buf2; - size_t curPos = 0; -}; - -class CVerusHashV2 -{ - public: - static void Hash(void *result, const void *data, size_t len); - static void (*haraka512Function)(unsigned char *out, const unsigned char *in); - - static void init(); - - CVerusHashV2() {} - - CVerusHashV2 &Write(const unsigned char *data, size_t len); - - CVerusHashV2 &Reset() - { - curBuf = buf1; - result = buf2; - curPos = 0; - std::fill(buf1, buf1 + sizeof(buf1), 0); - return *this; - } - - int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } - void ClearExtra() - { - if (curPos) - { - std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - } - } - void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } - - void Finalize(unsigned char hash[32]) - { - if (curPos) - { - std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - (*haraka512Function)(hash, curBuf); - } - else - std::memcpy(hash, curBuf, 32); - } - - private: - // only buf1, the first source, needs to be zero initialized - unsigned char buf1[64] = {0}, buf2[64]; - unsigned char *curBuf = buf1, *result = buf2; - size_t curPos = 0; -}; - -extern void verus_hash(void *result, const void *data, size_t len); -extern void verus_hash_v2(void *result, const void *data, size_t len); - -inline bool IsCPUVerusOptimized() -{ - unsigned int eax,ebx,ecx,edx; - - if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx)) - { - return false; - } - return ((ecx & (bit_AVX | bit_AES)) == (bit_AVX | bit_AES)); -}; - -#endif +// (C) 2018 Michael Toutonghi +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/* +This provides the PoW hash function for Verus, enabling CPU mining. +*/ +#ifndef VERUS_HASH_H_ +#define VERUS_HASH_H_ + +#include +#include + +#include + +extern "C" +{ +#include "crypto/haraka.h" +#include "crypto/haraka_portable.h" +} + +class CVerusHash +{ + public: + static void Hash(void *result, const void *data, size_t len); + static void (*haraka512Function)(unsigned char *out, const unsigned char *in); + + static void init(); + + CVerusHash() { } + + CVerusHash &Write(const unsigned char *data, size_t len); + + CVerusHash &Reset() + { + curBuf = buf1; + result = buf2; + curPos = 0; + std::fill(buf1, buf1 + sizeof(buf1), 0); + return *this; + } + + int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } + void ClearExtra() + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + } + } + void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } + + void Finalize(unsigned char hash[32]) + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + (*haraka512Function)(hash, curBuf); + } + else + std::memcpy(hash, curBuf, 32); + } + + private: + // only buf1, the first source, needs to be zero initialized + unsigned char buf1[64] = {0}, buf2[64]; + unsigned char *curBuf = buf1, *result = buf2; + size_t curPos = 0; +}; + +class CVerusHashV2 +{ + public: + static void Hash(void *result, const void *data, size_t len); + static void (*haraka512Function)(unsigned char *out, const unsigned char *in); + + static void init(); + + CVerusHashV2() {} + + CVerusHashV2 &Write(const unsigned char *data, size_t len); + + CVerusHashV2 &Reset() + { + curBuf = buf1; + result = buf2; + curPos = 0; + std::fill(buf1, buf1 + sizeof(buf1), 0); + return *this; + } + + int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } + void ClearExtra() + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + } + } + void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } + + void Finalize(unsigned char hash[32]) + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + (*haraka512Function)(hash, curBuf); + } + else + std::memcpy(hash, curBuf, 32); + } + + private: + // only buf1, the first source, needs to be zero initialized + unsigned char buf1[64] = {0}, buf2[64]; + unsigned char *curBuf = buf1, *result = buf2; + size_t curPos = 0; +}; + +extern void verus_hash(void *result, const void *data, size_t len); +extern void verus_hash_v2(void *result, const void *data, size_t len); + +inline bool IsCPUVerusOptimized() +{ + unsigned int eax,ebx,ecx,edx; + + if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx)) + { + return false; + } + return ((ecx & (bit_AVX | bit_AES)) == (bit_AVX | bit_AES)); +}; + +#endif diff --git a/src/deprecation.h b/src/deprecation.h index 427234b4a..dde45e22c 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -24,7 +24,7 @@ // * Shut down WEEKS_UNTIL_DEPRECATION weeks' worth of blocks after the estimated release block height. // * A warning is shown during the DEPRECATION_WARN_LIMIT worth of blocks prior to shut down. static const int WEEKS_UNTIL_DEPRECATION = 52; -static const int DEPRECATION_HEIGHT = 1600000; +static const int DEPRECATION_HEIGHT = 2200000; static const int APPROX_RELEASE_HEIGHT = DEPRECATION_HEIGHT - (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 60); // Number of blocks before deprecation to warn users diff --git a/src/fiat/k64 b/src/fiat/k64 new file mode 100755 index 000000000..a3b3bc835 --- /dev/null +++ b/src/fiat/k64 @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=K64 $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/zex b/src/fiat/zex deleted file mode 100755 index f4573c093..000000000 --- a/src/fiat/zex +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ZEX $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/zexo b/src/fiat/zexo new file mode 100755 index 000000000..b6fd508f2 --- /dev/null +++ b/src/fiat/zexo @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=ZEXO $1 $2 $3 $4 $5 $6 diff --git a/src/komodo.h b/src/komodo.h index b4c7d12bf..cd7c6573a 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -713,9 +713,9 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar sp->MoMdepth = MoMdepth; } komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + //if ( ASSETCHAINS_SYMBOL[0] != 0 ) printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); - + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { if ( signedfp == 0 ) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index bc7328af4..f9d2e1fd3 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -682,11 +682,32 @@ int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout) bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx); -int32_t komodo_isPoS(CBlock *pblock,int32_t height) +int32_t komodo_isPoS2(CBlock *pblock) { - int32_t n,vout,numvouts; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret; + CBlockIndex *pindex = komodo_blockindex(pblock->GetHash()); + if ( pindex != 0 && pindex->segid >= -1 ) + { + //fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid); + if ( pindex->segid == -1 ) + return(0); + else return(1); + } + return (-1); +} + +int32_t komodo_isPoS(CBlock *pblock,int32_t height,bool fJustCheck) +{ + int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret; if ( ASSETCHAINS_STAKED != 0 ) { + if ( fJustCheck ) + { + // check pindex first, if that does not work, continue with slow check. + if ( (ret= komodo_isPoS2(pblock)) == 1 ) + return (1); + else if ( ret == 0 ) + return (0); + } n = pblock->vtx.size(); //fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size()); if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+(ASSETCHAINS_MARMARA!=0) ) @@ -1441,10 +1462,6 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) percPoS = (percPoS*100) / (m+n); else - // This seems to be inverse. The actual PoS % is backwards in the first 100 blocks. - // I dont't understand the math here, or why its backwards, so I am just disabling it for VerusHash. - // No doubt this is probably wrong for equihash aswell, we may need to test an equihash chain with the rule above. - // Need to ask james what the deal is here! Seems to be causeing ALL the problems. percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; } if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) @@ -1625,7 +1642,7 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash) { - CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; arith_uint256 POWTarget; + CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; arith_uint256 POWTarget; if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) return(1); BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); @@ -1652,7 +1669,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ vout = pblock->vtx[txn_count-1].vin[0].prevout.n; if ( slowflag != 0 && prevtime != 0 ) { - if ( komodo_isPoS(pblock,height) != 0 ) + if ( komodo_isPoS(pblock,height,false) != 0 ) { eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"",PoSperc); } @@ -1684,7 +1701,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ } else if ( slowflag == 0 ) // previous blocks are not seen yet, do the best approx { - if ( komodo_isPoS(pblock,height) != 0 ) + if ( komodo_isPoS(pblock,height,false) != 0 ) isPoS = 1; } if ( slowflag != 0 && isPoS != 0 ) @@ -2543,7 +2560,6 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt komodo_segids(hashbuf,nHeight-101,100); if ( *blocktimep < tipindex->nTime+60) *blocktimep = tipindex->nTime+60; -//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight); bool resetstaker = false; if ( array != 0 ) @@ -2628,9 +2644,8 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt } } lasttime = (uint32_t)time(NULL); -//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); + //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); } -//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep); block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57; for (i=winners=0; itxid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address,PoSperc); - //fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible); if ( eligible > 0 ) { - besttime = m = 0; + besttime = 0; if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address,PoSperc) ) { - while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address,PoSperc) ) + // have elegible utxo to stake with. + if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) { - besttime = eligible; - eligible--; - if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier - break; - m++; -//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); + // is better than the previous best, so use it instead. + earliest = eligible; + best_scriptPubKey = kp->scriptPubKey; + *utxovaluep = (uint64_t)kp->nValue; + decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); + *utxovoutp = kp->vout; + *txtimep = kp->txtime; } - } - else - { - //fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); - continue; - } - eligible = besttime; - winners++; -//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible); - if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) - { - earliest = eligible; - best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey; - *utxovaluep = (uint64_t)kp->nValue; - //decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str()); - decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); - *utxovoutp = kp->vout; - *txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime; - //fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners); - } - } //else fprintf(stderr,"utxo not eligible\n"); + if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier + break; + } else continue; + } } - if ( numkp < 1000 && array != 0 ) + if ( numkp < 500 && array != 0 ) { free(array); array = 0; @@ -2699,7 +2698,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i]; txNew.vin[0].prevout.hash = revtxid; txNew.vin[0].prevout.n = *utxovoutp; - txNew.vout[0].scriptPubKey = best_scriptPubKey;// CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; + txNew.vout[0].scriptPubKey = best_scriptPubKey; txNew.vout[0].nValue = *utxovaluep - txfee; txNew.nLockTime = earliest; CTransaction txNewConst(txNew); @@ -2710,7 +2709,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt ptr = (uint8_t *)&sigdata.scriptSig[0]; siglen = sigdata.scriptSig.size(); for (i=0; i estimated height 1444000 +// 3: 3rd season ending isnt known, so use very far times in future. + // 1751328000 = dummy timestamp, 1 July 2025! + // 7113400 = 5x current KMD blockheight. +// to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. +#define NUM_KMD_SEASONS 3 +#define NUM_KMD_NOTARIES 64 +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, 1751328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, 7113400}; + +// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. +static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = +{ + { + { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 + { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, + { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 + { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, + { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, + { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, + { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, + { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 + { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, + { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, + { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 + { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, + { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, + { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, + { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, + { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, + { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 + { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 + { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, + { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, + { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, + { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, + { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, + { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 + { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, + { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } + }, + { + {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, + {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, + {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, + {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 + {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, + {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, + {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, + {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, + {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, + {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, + {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 + {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, + {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, + {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, + {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, + {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, + {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, + {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, + {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, + {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, + {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, + {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, + {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, + {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 + {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, + {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, + {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, + {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, + {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, + {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 + {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, + {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, + {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, + {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, + {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, + {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, + {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, + {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, + {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 + {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, + {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, + {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + }, + { + {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" } + } +}; + #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) #define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) #define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7))) @@ -82,7 +234,8 @@ extern int32_t VERUS_MIN_STAKEAGE; extern std::string DONATION_PUBKEY; extern uint8_t ASSETCHAINS_PRIVATE; extern int32_t USE_EXTERNAL_PUBKEY; -extern char NOTARYADDRS[64][64]; +extern char NOTARYADDRS[64][64]; // should be depreciated later. Only affects labs. +extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; extern int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL; extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT; int tx_height( const uint256 &hash ); diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 1fafcc856..1455c34b3 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2017,8 +2017,10 @@ int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector s { char url[32768],*symbol,*timestr; cJSON *json,*obj; int32_t i,n=0,retval=-1; uint32_t uprice,timestamp; sprintf(url,"https://api.iextrading.com/1.0/tops/last?symbols=%s",GetArg("-ac_stocks","").c_str()); + 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; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 08c633ee7..099cddd4b 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -53,6 +53,7 @@ bool VERUS_MINTBLOCKS; std::vector Mineropret; std::vector vWhiteListAddress; char NOTARYADDRS[64][64]; +char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT; diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 5cdbf237d..e2c7dfb4c 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -20,6 +20,7 @@ #include "notaries_staked.h" #define KOMODO_MAINNET_START 178999 +#define KOMODO_NOTARIES_HEIGHT1 814000 const char *Notaries_genesis[][2] = { @@ -60,194 +61,80 @@ const char *Notaries_genesis[][2] = { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, }; -const char *Notaries_elected0[][2] = -{ - { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, - { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, - { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, - { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, - { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 - { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, - { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, - { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, - { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, - { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 - { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, - { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, - { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, - { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, - { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 - { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, - { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, - { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, - { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 - { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, - { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, - { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, - { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, - { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, - { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, - { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, - { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 - { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, - { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, - { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, - { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, - { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, - { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, - { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, - { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 - { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, - { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, - { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, - { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, - { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, - { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, - { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, - { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, - { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, - { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 - { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, - { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } -}; - -#define KOMODO_NOTARIES_TIMESTAMP1 1525132800 // May 1st 2018 1530921600 // 7/7/2017 -#define KOMODO_NOTARIES_HEIGHT1 ((814000 / KOMODO_ELECTION_GAP) * KOMODO_ELECTION_GAP) - -const char *Notaries_elected1[][2] = -{ - {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, - {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, - {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, - {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 - {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, - {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, - {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, - {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, - {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, - {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, - {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 - {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, - {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, - {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, - {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, - {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, - {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, - {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, - {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, - {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, - {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, - {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, - {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, - {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 - {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, - {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, - {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, - {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, - {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, - {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 - {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, - {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, - {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, - {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, - {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, - {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, - {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, - {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, - {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 - {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, - {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, - {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, -}; #define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" +int32_t getkmdseason(int32_t height) +{ + int8_t season = 0; + 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(int32_t timestamp) +{ + int8_t season = 0; + if ( timestamp <= KMD_SEASON_TIMESTAMPS[0] ) + return(1); + for (int32_t i = 1; i < NUM_KMD_SEASONS; i++) + { + if ( timestamp <= KMD_SEASON_TIMESTAMPS[i] && timestamp >= KMD_SEASON_TIMESTAMPS[i-1] ) + return(i+1); + } + return(0); +}; + int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) { - static uint8_t elected_pubkeys0[64][33],elected_pubkeys1[64][33],did0,did1; static int32_t n0,n1; int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; - + static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33],didinit[NUM_KMD_SEASONS]; + if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 ) timestamp = komodo_heightstamp(height); else if ( ASSETCHAINS_SYMBOL[0] == 0 ) timestamp = 0; // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW. - if (is_STAKED(ASSETCHAINS_SYMBOL) == 0) + if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) { - if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 ) - timestamp = 0; - if ( (timestamp != 0 && timestamp <= KOMODO_NOTARIES_TIMESTAMP1) || (ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_NOTARIES_HEIGHT1) ) + int32_t kmd_season = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - if ( did0 == 0 ) - { - n0 = (int32_t)(sizeof(Notaries_elected0)/sizeof(*Notaries_elected0)); - for (i=0; i= KOMODO_NOTARIES_HARDCODED ) + kmd_season = getkmdseason(height); } - else //if ( (timestamp != 0 && timestamp <= KOMODO_NOTARIES_TIMESTAMP2) || height <= KOMODO_NOTARIES_HEIGHT2 ) + else { - if ( did1 == 0 ) + // This is a non LABS assetchain, use timestamp to detemine notary pubkeys. + kmd_season = getacseason(timestamp); + } + if ( kmd_season != 0 ) + { + if ( didinit[kmd_season-1] == 0 ) { - n1 = (int32_t)(sizeof(Notaries_elected1)/sizeof(*Notaries_elected1)); - for (i=0; i &outVals); int8_t equihash_params_possible(uint64_t n, uint64_t k) @@ -1691,14 +1692,9 @@ int8_t equihash_params_possible(uint64_t n, uint64_t k) void komodo_args(char *argv0) { - extern const char *Notaries_elected1[][2]; std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256]; IS_KOMODO_NOTARY = GetBoolArg("-notary", false); IS_STAKED_NOTARY = GetArg("-stakednotary", -1); - if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) { - fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); - StartShutdown(); - } memset(ccenables,0,sizeof(ccenables)); memset(disablebits,0,sizeof(disablebits)); if ( GetBoolArg("-gen", false) != 0 ) @@ -1717,17 +1713,24 @@ void komodo_args(char *argv0) USE_EXTERNAL_PUBKEY = 1; if ( IS_KOMODO_NOTARY == 0 ) { + // We dont have any chain data yet, so use system clock to guess. + // I think on season change should reccomend notaries to use -notary to avoid needing this. + int32_t kmd_season = getacseason(time(NULL)); for (i=0; i<64; i++) - if ( strcmp(NOTARY_PUBKEY.c_str(),Notaries_elected1[i][1]) == 0 ) + if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[kmd_season][NUM_KMD_NOTARIES][1]) == 0 ) { IS_KOMODO_NOTARY = 1; KOMODO_MININGTHREADS = 1; mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); IS_STAKED_NOTARY = -1; - fprintf(stderr,"running as notary.%d %s\n",i,Notaries_elected1[i][0]); + fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[kmd_season][NUM_KMD_NOTARIES][0]); break; } } + } + if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) { + fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); + StartShutdown(); } name = GetArg("-ac_name",""); if ( argv0 != 0 ) @@ -1760,7 +1763,6 @@ void komodo_args(char *argv0) } KOMODO_EARLYTXID = Parseuint256(GetArg("-earlytxid","0").c_str()); ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0); - fprintf(stderr, "ASSETCHAINS_EARLYTXIDCONTRACT.%i\n", ASSETCHAINS_EARLYTXIDCONTRACT); if ( name.c_str()[0] != 0 ) { std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0])); diff --git a/src/main.cpp b/src/main.cpp index 7198fe7e6..c14e4351d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1373,25 +1373,26 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState } } -int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only +extern int32_t getacseason(int32_t timestamp); + +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private chains only { - static int32_t didinit; static char notaryaddrs[sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) + 1][64]; - int32_t i; - if ( didinit == 0 ) + int32_t season = getacseason(tiptime); + if ( NOTARY_ADDRESSES[season-1][0][0] == 0 ) { - uint8_t pubkey33[33]; - for (i=0; i<=sizeof(Notaries_elected1)/sizeof(*Notaries_elected1); i++) - { - if ( i < sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) ) - decode_hex(pubkey33,33,(char *)Notaries_elected1[i][1]); - else decode_hex(pubkey33,33,(char *)CRYPTO777_PUBSECPSTR); - pubkey2addr((char *)notaryaddrs[i],(uint8_t *)pubkey33); - } - didinit = 1; + uint8_t pubkeys[64][33]; + komodo_notaries(pubkeys,0,tiptime); } - for (i=0; i<=sizeof(Notaries_elected1)/sizeof(*Notaries_elected1); i++) - if ( strcmp(coinaddr,notaryaddrs[i]) == 0 ) + if ( strcmp(coinaddr,CRYPTO777_KMDADDR) == 0 ) return(1); + for (int32_t i = 0; i < NUM_KMD_NOTARIES; i++) + { + if ( strcmp(coinaddr,NOTARY_ADDRESSES[season-1][i]) == 0 ) + { + //fprintf(stderr, "coinaddr.%s notaryaddress[%i].%s\n",coinaddr,i,NOTARY_ADDRESSES[season-1][i]); + return(1); + } + } return(0); } @@ -1484,7 +1485,7 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio // char destaddr[65]; Getscriptaddress(destaddr,txout.scriptPubKey); - if ( komodo_isnotaryvout(destaddr) == 0 ) + if ( komodo_isnotaryvout(destaddr,tiptime) == 0 ) { invalid_private_taddr = 1; //return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain"); @@ -3103,7 +3104,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex *pfClean = false; bool fClean = true; - komodo_disconnect(pindex,block); + //komodo_disconnect(pindex,block); does nothing? CBlockUndo blockUndo; CDiskBlockPos pos = pindex->GetUndoPos(); if (pos.IsNull()) @@ -4049,7 +4050,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { CValidationState stateDummy; // don't keep staking or invalid transactions - if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) + if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight(),true) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) { mempool.remove(tx, removed, true); } @@ -4081,11 +4082,11 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { { CTransaction &tx = block.vtx[i]; //if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0)))) - if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0))) + if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight(),true) != 0))) { #ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->EraseFromWallet(tx.GetHash()); + if ( !GetBoolArg("-disablewallet", false) ) + pwalletMain->EraseFromWallet(tx.GetHash()); #endif } else @@ -4266,7 +4267,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * { uint64_t start = time(NULL); if ( !komodo_dailysnapshot(pindexNew->GetHeight()) ) - fprintf(stderr, "daily snapshot failed, please reindex your chain\n"); // maybe force shutdown here? + { + fprintf(stderr, "daily snapshot failed, please reindex your chain\n"); + StartShutdown(); + } fprintf(stderr, "snapshot completed in: %lu seconds\n", time(NULL)-start); } return true; @@ -5093,7 +5097,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C CValidationState state; CTransaction Tx; const CTransaction &tx = (CTransaction)block.vtx[i]; - if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height) != 0))) + if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height,true) != 0))) continue; Tx = tx; if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync @@ -6500,15 +6504,15 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) } try { // read block + CBlock block; uint64_t nBlockPos = blkdat.GetPos(); if (dbp) dbp->nPos = nBlockPos; blkdat.SetLimit(nBlockPos + nSize); blkdat.SetPos(nBlockPos); - CBlock block; blkdat >> block; - nRewind = blkdat.GetPos(); - + + nRewind = blkdat.GetPos(); // detect out of order blocks, and store them for later uint256 hash = block.GetHash(); if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) { @@ -6539,6 +6543,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); while (range.first != range.second) { std::multimap::iterator it = range.first; + if (ReadBlockFromDisk(mapBlockIndex.count(hash)!=0?mapBlockIndex[hash]->GetHeight():0,block, it->second,1)) { LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), diff --git a/src/miner.cpp b/src/miner.cpp index 8fc658fa9..9976909fa 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -810,12 +810,17 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 //fprintf(stderr,"check validity\n"); if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) // invokes CC checks { + if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + { + LEAVE_CRITICAL_SECTION(cs_main); + LEAVE_CRITICAL_SECTION(mempool.cs); + } throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed"); } //fprintf(stderr,"valid\n"); } } - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); @@ -1051,7 +1056,7 @@ int32_t roundrobin_delay; arith_uint256 HASHTarget,HASHTarget_POW; // wait for peers to connect -int32_t waitForPeers(const CChainParams &chainparams) +void waitForPeers(const CChainParams &chainparams) { if (chainparams.MiningRequiresPeers()) { diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index bb1518262..d3281127e 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -18,7 +18,7 @@ int8_t is_STAKED(const char *chain_name) if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0) return(STAKED); else STAKED = 0; - if ( (strcmp(chain_name, "LABS") == 0) || (strcmp(chain_name, "LABSRCTEST") == 0) ) + if ( (strcmp(chain_name, "LABS") == 0) ) STAKED = 1; // These chains are allowed coin emissions. else if ( (strncmp(chain_name, "LABS", 4) == 0) ) STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed. @@ -113,7 +113,14 @@ void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) { // staked era is set. pthread_mutex_lock(&staked_mutex); for (int i = 0; i 3) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 21ae07810..c95d7b891 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1051,6 +1051,7 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp) return result; } + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index e280b1a0b..56f221a37 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -219,7 +219,6 @@ int32_t komodo_longestchain() depth--; if ( num > (n >> 1) ) { - extern char ASSETCHAINS_SYMBOL[]; if ( 0 && height != KOMODO_LONGESTCHAIN ) fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); KOMODO_LONGESTCHAIN = height; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 1c3cb96f2..578c2f9ad 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -48,6 +48,8 @@ #include +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); + using namespace std; extern char ASSETCHAINS_SYMBOL[]; @@ -185,10 +187,13 @@ int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout) void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, int nHeight = 0, int nConfirmations = 0, int nBlockTime = 0) { + uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height; + notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid); uint256 txid = tx.GetHash(); entry.push_back(Pair("txid", txid.GetHex())); entry.push_back(Pair("overwintered", tx.fOverwintered)); entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("last_notarized_height", notarized_height)); if (tx.fOverwintered) { entry.push_back(Pair("versiongroupid", HexInt(tx.nVersionGroupId))); } diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index b3fe27fba..e36e8b4c9 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -473,7 +473,7 @@ static const CRPCCommand vRPCCommands[] = { "prices", "pricesrekt", &pricesrekt, true }, { "prices", "pricesaddfunding", &pricesaddfunding, true }, { "prices", "pricesgetorderbook", &pricesgetorderbook, true }, - + { "prices", "pricesrefillfund", &pricesrefillfund, true }, // Pegs { "pegs", "pegsaddress", &pegsaddress, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index c61f62dc3..b9fb33198 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -510,6 +510,7 @@ extern UniValue pricescashout(const UniValue& params, bool fHelp); extern UniValue pricesrekt(const UniValue& params, bool fHelp); extern UniValue pricesaddfunding(const UniValue& params, bool fHelp); extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp); +extern UniValue pricesrefillfund(const UniValue& params, bool fHelp); diff --git a/src/script/script_ext.cpp b/src/script/script_ext.cpp index 532e39d6c..f1d903946 100644 --- a/src/script/script_ext.cpp +++ b/src/script/script_ext.cpp @@ -85,6 +85,7 @@ const CScriptExt &CScriptExt::AddCheckLockTimeVerify(int64_t unlocktime) const *((CScript *)this) << OP_DROP; return *this; } + return *this; } // combined CLTV script and P2PKH diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1055214a3..e9a9e38c6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -73,7 +73,7 @@ extern UniValue TxJoinSplitToJSON(const CTransaction& tx); extern int32_t KOMODO_INSYNC; uint32_t komodo_segid32(char *coinaddr); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int32_t komodo_isnotaryvout(char *coinaddr); // from ac_private chains only +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); // from ac_private chains only CBlockIndex *komodo_getblockindex(uint256 hash); int64_t nWalletUnlockTime; @@ -463,7 +463,6 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); } -int32_t komodo_isnotaryvout(char *coinaddr); UniValue sendtoaddress(const UniValue& params, bool fHelp) { @@ -496,7 +495,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) if ( ASSETCHAINS_PRIVATE != 0 && AmountFromValue(params[1]) > 0 ) { - if ( komodo_isnotaryvout((char *)params[0].get_str().c_str()) == 0 ) + if ( komodo_isnotaryvout((char *)params[0].get_str().c_str(),chainActive.LastTip()->nTime) == 0 ) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address"); } @@ -5668,7 +5667,7 @@ UniValue payments_airdroptokens(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; if ( fHelp || params.size() != 1 ) - throw runtime_error("paymentsairdrop \"[%22tokenid%22,lockedblocks,minamount,mintoaddress,top,bottom,fixedFlag,%22excludePubKey%22,...,%22excludePubKeyN%22]\"\n"); + throw runtime_error("payments_airdroptokens \"[%22tokenid%22,lockedblocks,minamount,mintoaddress,top,bottom,fixedFlag,%22excludePubKey%22,...,%22excludePubKeyN%22]\"\n"); if ( ensure_CCrequirements(EVAL_PAYMENTS) < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); const CKeyStore& keystore = *pwalletMain; @@ -8029,9 +8028,9 @@ UniValue opreturn_burn(const UniValue& params, bool fHelp) if (fHelp || (params.size() != 2)) throw runtime_error("amount to burn, hexstring to send\n"); struct CCcontract_info *cp, C; UniValue ret(UniValue::VOBJ); - if (ensure_CCrequirements(EVAL_PAYMENTS) < 0) + if (ensure_CCrequirements(EVAL_ORACLES) < 0) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - cp = CCinit(&C, EVAL_PAYMENTS); + cp = CCinit(&C, EVAL_ORACLES); CAmount nAmount = AmountFromValue(params[0]); if (nAmount <= 10000) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fa39d204a..4d834ccee 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2874,21 +2874,18 @@ void CWallet::ReacceptWalletTransactions() bool invalid = state.IsInvalid(nDoS); // log rejection and deletion - // printf("ERROR reaccepting wallet transaction %s to mempool, reason: %s, DoS: %d\n", wtx.GetHash().ToString().c_str(), state.GetRejectReason().c_str(), nDoS); + //printf("ERROR reaccepting wallet transaction %s to mempool, reason: %s, DoS: %d\n", wtx.GetHash().ToString().c_str(), state.GetRejectReason().c_str(), nDoS); - if (!wtx.IsCoinBase() && invalid && nDoS > 0) + if (!wtx.IsCoinBase() && invalid && nDoS > 0 && state.GetRejectReason() != "tx-overwinter-expired") { LogPrintf("erasing transaction %s\n", wtx.GetHash().GetHex().c_str()); vwtxh.push_back(wtx.GetHash()); } } } - if ( IsInitialBlockDownload() == 0 ) + for (auto hash : vwtxh) { - for (auto hash : vwtxh) - { - EraseFromWallet(hash); - } + EraseFromWallet(hash); } } @@ -2896,7 +2893,7 @@ bool CWalletTx::RelayWalletTransaction() { if ( pwallet == 0 ) { - fprintf(stderr,"unexpected null pwallet in RelayWalletTransaction\n"); + //fprintf(stderr,"unexpected null pwallet in RelayWalletTransaction\n"); return(false); } assert(pwallet->GetBroadcastTransactions()); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index efba38d9e..e81eba03d 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -41,6 +41,7 @@ using namespace std; static uint64_t nAccountingEntryNumber = 0; static list deadTxns; +extern CBlockIndex *komodo_blockindex(uint256 hash); // // CWalletDB @@ -964,21 +965,20 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) // staking chains with vin-empty error is a failed staking tx. // we remove then re add the tx here to stop needing a full rescan, which does not actually fix the problem. int32_t reAdded = 0; - CWalletDB walletdb(pwallet->strWalletFile, "r+", false); BOOST_FOREACH (uint256& hash, deadTxns) { - fprintf(stderr, "Removing corrupt tx from wallet.%s\n", hash.ToString().c_str()); + fprintf(stderr, "Removing possible orphaned staking transaction from wallet.%s\n", hash.ToString().c_str()); if (!EraseTx(hash)) fprintf(stderr, "could not delete tx.%s\n",hash.ToString().c_str()); - uint256 blockhash; CTransaction tx; - if (GetTransaction(hash,tx,blockhash,true)) + uint256 blockhash; CTransaction tx; CBlockIndex* pindex; + if ( GetTransaction(hash,tx,blockhash,false) && (pindex= komodo_blockindex(blockhash)) != 0 && chainActive.Contains(pindex) ) { CWalletTx wtx(pwallet,tx); - pwallet->AddToWallet(wtx, false, &walletdb); + pwallet->AddToWallet(wtx, true, NULL); reAdded++; } } - fprintf(stderr, "Cleared %li corrupted transactions from wallet. Readded %i known transactions.\n",deadTxns.size(),reAdded); + fprintf(stderr, "Cleared %li orphaned staking transactions from wallet. Readded %i real transactions.\n",deadTxns.size(),reAdded); fNoncriticalErrors = false; deadTxns.clear(); } diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index df4efd05f..5f1817e9e 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -52,7 +52,7 @@ cd $WD ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Werror -g -Wl,-undefined -Wl,dynamic_lookup' \ +CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -g -Wl,-undefined -Wl,dynamic_lookup' \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" make "$@" V=1 NO_GTEST=1 STATIC=1