diff --git a/COPYING b/COPYING index c84bfb7aa..eecf5ccc8 100644 --- a/COPYING +++ b/COPYING @@ -1,3 +1,4 @@ +Copyright (c) 2016-2018 The Komodo developers Copyright (c) 2016-2017 The Zcash developers Copyright (c) 2009-2017 The Bitcoin Core developers diff --git a/README.md b/README.md index 5d85d013d..788635536 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ It downloads and stores the entire history of Komodo transactions; depending on - Support: [https://support.komodoplatform.com/support/home](https://support.komodoplatform.com/support/home) - Knowledgebase & How-to: [https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages](https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages) - API references: [http://docs.supernet.org/](http://docs.supernet.org/) #Not up to date. -- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/wp-content/uploads/2018/03/2018-03-12-Komodo-White-Paper-Full.pdf) +- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/wp-content/uploads/2018/06/Komodo-Whitepaper-June-3.pdf) - Komodo Platform public material: [Komodo Platform public material](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0) ## List of Komodo Platform Technologies diff --git a/contrib/debian/examples/komodo.conf b/contrib/debian/examples/komodo.conf new file mode 100644 index 000000000..656a43533 --- /dev/null +++ b/contrib/debian/examples/komodo.conf @@ -0,0 +1,140 @@ +## +## komodo.conf configuration file. Lines beginning with # are comments. +## + +# Network-related settings: + +# Run a regression test network +#regtest=0 + +# Connect via a SOCKS5 proxy +#proxy=127.0.0.1:9050 + +# Bind to given address and always listen on it. Use [host]:port notation for IPv6 +#bind= + +# Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6 +#whitebind= + +############################################################## +## Quick Primer on addnode vs connect ## +## Let's say for instance you use addnode=4.2.2.4 ## +## addnode will connect you to and tell you about the ## +## nodes connected to 4.2.2.4. In addition it will tell ## +## the other nodes connected to it that you exist so ## +## they can connect to you. ## +## connect will not do the above when you 'connect' to it. ## +## It will *only* connect you to 4.2.2.4 and no one else.## +## ## +## So if you're behind a firewall, or have other problems ## +## finding nodes, add some using 'addnode'. ## +## ## +## If you want to stay private, use 'connect' to only ## +## connect to "trusted" nodes. ## +## ## +## If you run multiple nodes on a LAN, there's no need for ## +## all of them to open lots of connections. Instead ## +## 'connect' them all to one node that is port forwarded ## +## and has lots of connections. ## +## Thanks goes to [Noodle] on Freenode. ## +############################################################## + +# Use as many addnode= settings as you like to connect to specific peers +#addnode=69.164.218.197 +#addnode=10.0.0.2:8233 + +# Alternatively use as many connect= settings as you like to connect ONLY to specific peers +#connect=69.164.218.197 +#connect=10.0.0.1:8233 + +# Listening mode, enabled by default except when 'connect' is being used +#listen=1 + +# Maximum number of inbound+outbound connections. +#maxconnections= + +# +# JSON-RPC options (for controlling a running Komodo/komodod process) +# + +# server=1 tells komodod to accept JSON-RPC commands (set as default if not specified) +#server=1 + +# Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. +# This option can be specified multiple times (default: bind to all interfaces) +#rpcbind= + +# You must set rpcuser and rpcpassword to secure the JSON-RPC api +#rpcuser=Ulysses +#rpcpassword=YourSuperGreatPasswordNumber_DO_NOT_USE_THIS_OR_YOU_WILL_GET_ROBBED_385593 + +# How many seconds komodo will wait for a complete RPC HTTP request. +# after the HTTP connection is established. +#rpcclienttimeout=30 + +# By default, only RPC connections from localhost are allowed. +# Specify as many rpcallowip= settings as you like to allow connections from other hosts, +# either as a single IPv4/IPv6 or with a subnet specification. + +# NOTE: opening up the RPC port to hosts outside your local trusted network is NOT RECOMMENDED, +# because the rpcpassword is transmitted over the network unencrypted and also because anyone +# that can authenticate on the RPC port can steal your keys + take over the account running komodod +# For more information see https://github.com/zcash/zcash/issues/1497 + +#rpcallowip=10.1.1.34/255.255.255.0 +#rpcallowip=1.2.3.4/24 +#rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96 + +# Listen for RPC connections on this TCP port: +#rpcport=8232 + +# You can use Komodo or komodod to send commands to Komodo/komodod +# running on another host using this option: +#rpcconnect=127.0.0.1 + +# Transaction Fee + +# Send transactions as zero-fee transactions if possible (default: 0) +#sendfreetransactions=0 + +# Create transactions that have enough fees (or priority) so they are likely to # begin confirmation within n blocks (default: 1). +# This setting is overridden by the -paytxfee option. +#txconfirmtarget=n + +# Miscellaneous options + +# Enable attempt to mine komodo. +#gen=0 + +# Set the number of threads to be used for mining komodo (-1 = all cores). +#genproclimit=1 + +# Specify a different Equihash solver (e.g. "tromp") to try to mine komodo +# faster when gen=1. +#equihashsolver=default + +# Pre-generate this many public/private key pairs, so wallet backups will be valid for +# both prior transactions and several dozen future transactions. +#keypool=100 + +# Pay an optional transaction fee every time you send komodo. Transactions with fees +# are more likely than free transactions to be included in generated blocks, so may +# be validated sooner. This setting does not affect private transactions created with +# 'z_sendmany'. +#paytxfee=0.00 + +#Rewind the chain to specific block height. This is useful for creating snapshots at a given block height. +#rewind=777777 + +#Stop the chain a specific block height. This is useful for creating snapshots at a given block height. +#stopat=1000000 + +#Set an address to use as change address for all transactions. This value must be set to a 33 byte pubkey. All mined coins will also be sent to this address. +#pubkey=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392 + +#Forfeit all user rewards to miners. Set this to explicitly not claim user rewards. +#exchange=1 + +#Donate all user rewards to a a specific address. This value must be set to a 33 byte pubkey. +#donation=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392 + diff --git a/src/Makefile.test.include b/src/Makefile.test.include index ff270bd6a..a52b66335 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -45,7 +45,6 @@ BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ test/bignum.h \ test/addrman_tests.cpp \ - test/alert_tests.cpp \ test/allocator_tests.cpp \ test/base32_tests.cpp \ test/base58_tests.cpp \ diff --git a/src/assetchains b/src/assetchains index 4029dc039..661dd710a 100755 --- a/src/assetchains +++ b/src/assetchains @@ -66,7 +66,7 @@ komodo_asset BNTN 500000000 komodo_asset CHAIN 999999 komodo_asset PRLPAY 500000000 komodo_asset DSEC 7000000 -komodo_asset GLXT 100000000 +komodo_asset GLXT 10000000000 komodo_asset EQL 500000000 komodo_asset ZILLA 11000000 komodo_asset RFOX 1000000000 100000000 diff --git a/src/assetchains.old b/src/assetchains.old index b8658ab24..dd5c5d813 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -32,7 +32,7 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=CHAIN -ac_supply=999999 -addnode=78.47.146.222 & ./komodod -pubkey=$pubkey -ac_name=PRLPAY -ac_supply=500000000 -addnode=13.250.226.125 & ./komodod -pubkey=$pubkey -ac_name=DSEC -ac_supply=7000000 -addnode=185.148.147.30 & -./komodod -pubkey=$pubkey -ac_name=GLXT -ac_supply=100000000 -addnode=13.230.224.15 & +./komodod -pubkey=$pubkey -ac_name=GLXT -ac_supply=10000000000 -addnode=13.230.224.15 & ./komodod -pubkey=$pubkey -ac_name=EQL -ac_supply=500000000 -addnode=46.101.124.153 & ./komodod -pubkey=$pubkey -ac_name=ZILLA -ac_supply=11000000 -addnode=54.39.23.248 & ./komodod -pubkey=$pubkey -ac_name=RFOX -ac_supply=1000000000 -ac_reward=100000000 -addnode=78.47.196.146 & diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 5c12cfa2f..36fea57bf 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -144,21 +144,21 @@ bool AppInit(int argc, char* argv[]) ReadConfigFile(mapArgs, mapMultiArgs); } catch (const missing_zcash_conf& e) { fprintf(stderr, - (_("Before starting zcashd, you need to create a configuration file:\n" + (_("Before starting komodod, you need to create a configuration file:\n" "%s\n" "It can be completely empty! That indicates you are happy with the default\n" - "configuration of zcashd. But requiring a configuration file to start ensures\n" - "that zcashd won't accidentally compromise your privacy if there was a default\n" + "configuration of komodod. But requiring a configuration file to start ensures\n" + "that komodod won't accidentally compromise your privacy if there was a default\n" "option you needed to change.\n" "\n" "You can look at the example configuration file for suggestions of default\n" "options that you may want to change. It should be in one of these locations,\n" - "depending on how you installed Zcash:\n") + + "depending on how you installed Komodo:\n") + _("- Source code: %s\n" "- .deb package: %s\n")).c_str(), GetConfigFile().string().c_str(), - "contrib/debian/examples/zcash.conf", - "/usr/share/doc/zcash/examples/zcash.conf"); + "contrib/debian/examples/komodo.conf", + "/usr/share/doc/komodo/examples/komodo.conf"); return false; } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); diff --git a/src/chain.cpp b/src/chain.cpp index 7bb72d5d3..d79a66f9a 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -11,6 +11,7 @@ using namespace std; * CChain implementation */ void CChain::SetTip(CBlockIndex *pindex) { + lastTip = pindex; if (pindex == NULL) { vChain.clear(); return; diff --git a/src/chain.h b/src/chain.h index a28e4e44a..d882083e6 100644 --- a/src/chain.h +++ b/src/chain.h @@ -121,7 +121,7 @@ public: //! height of the entry in the chain. The genesis block has height 0 int nHeight; - + int64_t newcoins,zfunds; //! Which # file this block is stored in (blk?????.dat) int nFile; @@ -181,6 +181,7 @@ public: void SetNull() { phashBlock = NULL; + newcoins = zfunds = 0; pprev = NULL; pskip = NULL; nHeight = 0; @@ -321,6 +322,7 @@ public: //! Efficiently find an ancestor of this block. CBlockIndex* GetAncestor(int height); const CBlockIndex* GetAncestor(int height) const; + }; /** Used to marshal pointers into hashes for db storage. */ @@ -414,6 +416,7 @@ public: class CChain { private: std::vector vChain; + CBlockIndex *lastTip; public: /** Returns the index entry for the genesis block of this chain, or NULL if none. */ @@ -425,6 +428,11 @@ public: CBlockIndex *Tip() const { return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL; } + + /** Returns the last tip of the chain, or NULL if none. */ + CBlockIndex *LastTip() const { + return vChain.size() > 0 ? lastTip : NULL; + } /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */ CBlockIndex *operator[](int nHeight) const { diff --git a/src/coins.cpp b/src/coins.cpp index b2d838506..38b105e9d 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -466,7 +466,7 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const const COutPoint &prevout = tx.vin[i].prevout; const CCoins* coins = AccessCoins(prevout.hash); if (!coins || !coins->IsAvailable(prevout.n)) { - fprintf(stderr,"HaveInputs missing input %s/v%d\n",prevout.hash.ToString().c_str(),prevout.n); + //fprintf(stderr,"HaveInputs missing input %s/v%d\n",prevout.hash.ToString().c_str(),prevout.n); return false; } } diff --git a/src/deprecation.h b/src/deprecation.h index 78ed8ebda..11eb69ef4 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -6,11 +6,11 @@ #define ZCASH_DEPRECATION_H // Deprecation policy: -// * Shut down 16 weeks' worth of blocks after the estimated release block height. -// * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 800000; +// * 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 = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); +static const int DEPRECATION_HEIGHT = 1400000; +static const int APPROX_RELEASE_HEIGHT = DEPRECATION_HEIGHT - (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 60); // Number of blocks before deprecation to warn users static const int DEPRECATION_WARN_LIMIT = 60 * 24 * 60; // 2 months diff --git a/src/init.cpp b/src/init.cpp index 1b8018b56..a9bdc6151 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1756,11 +1756,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) StartNode(threadGroup, scheduler); - // Monitor the chain, and alert if we get blocks much quicker or slower than expected - int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing; - CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); - scheduler.scheduleEvery(f, nPowTargetSpacing); #ifdef ENABLE_MINING // Generate coins in the background diff --git a/src/komodo.h b/src/komodo.h index ae0898ed3..e89dea2e4 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -823,7 +823,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) komodo_event_rewind(sp,symbol,pindex->nHeight); komodo_stateupdate(pindex->nHeight,0,0,0,zero,0,0,0,0,-pindex->nHeight,pindex->nTime,0,0,0,0,zero,0); } - komodo_currentheight_set(chainActive.Tip()->nHeight); + komodo_currentheight_set(chainActive.LastTip()->nHeight); if ( pindex != 0 ) { height = pindex->nHeight; @@ -907,7 +907,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) #else memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); #endif - notaryid = komodo_voutupdate(&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.Tip()->GetBlockTime()); + notaryid = komodo_voutupdate(&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); if ( 0 && i > 0 ) { for (k=0; knTime; + else txtime = tx.nLockTime; + //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); + if ( n < tx.vout.size() ) + { + *valuep = tx.vout[n].nValue; + if (ExtractDestination(tx.vout[n].scriptPubKey, address)) + strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); + } + return(txtime); +} + +int32_t komodo_isPoS(CBlock *pblock) +{ + int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; + if ( ASSETCHAINS_STAKED != 0 ) + { + if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 ) + { + txid = pblock->vtx[n-1].vin[0].prevout.hash; + vout = pblock->vtx[n-1].vin[0].prevout.n; + txtime = komodo_txtime(&value,txid,vout,destaddr); + if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value ) + { + //fprintf(stderr,"is PoS block!\n"); + return(1); + } + } + } + } + return(0); +} + void komodo_disconnect(CBlockIndex *pindex,CBlock& block) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -701,8 +751,8 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) uint32_t komodo_chainactive_timestamp() { - if ( chainActive.Tip() != 0 ) - return((uint32_t)chainActive.Tip()->GetBlockTime()); + if ( chainActive.LastTip() != 0 ) + return((uint32_t)chainActive.LastTip()->GetBlockTime()); else return(0); } @@ -710,11 +760,11 @@ CBlockIndex *komodo_chainactive(int32_t height) { if ( chainActive.Tip() != 0 ) { - if ( height <= chainActive.Tip()->nHeight ) + if ( height <= chainActive.LastTip()->nHeight ) return(chainActive[height]); - // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight); + // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->nHeight); } - //fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height); + //fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height); return(0); } @@ -944,7 +994,7 @@ int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,in int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash) { int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex; - if ( (pindex= chainActive.Tip()) == 0 ) + if ( (pindex= chainActive.LastTip()) == 0 ) return(-1); notarized_height = komodo_notarizeddata(pindex->nHeight,¬arized_hash,¬arized_desttxid); *notarized_heightp = notarized_height; @@ -986,7 +1036,7 @@ uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_ *valuep = tx.vout[n].nValue; *txheightp = pindex->nHeight; *txheighttimep = pindex->nTime; - if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 ) + if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 ) *tiptimep = (uint32_t)tipindex->nTime; locktime = tx.nLockTime; //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); @@ -1019,18 +1069,18 @@ int32_t komodo_isrealtime(int32_t *kmdheightp) if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) *kmdheightp = sp->CURRENT_HEIGHT; else *kmdheightp = 0; - if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() ) + if ( (pindex= chainActive.LastTip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() ) return(1); else return(0); } int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) { - if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) + if ( KOMODO_REWIND == 0 && (ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED != 0) && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) { - if ( txheight > 246748 ) + if ( txheight > 246748 || ASSETCHAINS_STAKED != 0 ) { - if ( txheight < 247205 ) + if ( txheight < 247205 && ASSETCHAINS_STAKED == 0 ) cmptime -= 16000; if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) { @@ -1054,9 +1104,8 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_ commission must be in coinbase.vout[1] and must be >= 10000 sats PoS stake must be without txfee and in the last tx in the block at vout[0] - PoW mining on PoS chain must solve a harder diff that adjusts, but never less than KOMODO_POWMINMULT */ -#define KOMODO_POWMINMULT 16 +//#define KOMODO_POWMINMULT 16 uint64_t komodo_commission(const CBlock *pblock) { @@ -1086,76 +1135,152 @@ uint32_t komodo_segid32(char *coinaddr) return(addrhash.uints[0]); } -uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr) +int8_t komodo_segid(int32_t height) { - CBlockIndex *pindex; bool fNegative,fOverflow; uint8_t hashbuf[128]; char address[64]; bits256 addrhash; arith_uint256 hashval; uint256 hash,pasthash; int64_t diff=0; int32_t segid,minage,i,iter=0; uint32_t txtime,winner = 0; arith_uint256 bnMaxPoSdiff; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN; - txtime = komodo_txtime(&value,txid,vout,address); - if ( blocktime < prevtime+57 ) - blocktime = prevtime+57; - if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 ) + CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; int8_t segid = -1; + if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) { - fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime); - return(0); - } - bnMaxPoSdiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - bnMaxPoSdiff = (bnMaxPoSdiff / arith_uint256(4)); - if ( bnTarget < bnMaxPoSdiff ) - bnTarget = bnMaxPoSdiff; - if ( (minage= nHeight*3) > 6000 ) // about 100 blocks - minage = 6000; - pindex = 0; - if ( (pindex= komodo_chainactive(nHeight>50?nHeight-50:1)) != 0 ) - { - vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address)); - segid = ((nHeight + addrhash.uints[0]) & 0x3f); - pasthash = pindex->GetBlockHash(); - memcpy(hashbuf,&pasthash,sizeof(pasthash)); - memcpy(&hashbuf[sizeof(pasthash)],&addrhash,sizeof(addrhash)); - vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*2); - //fprintf(stderr,"(%s) vs. (%s) %s %.8f txtime.%u\n",address,destaddr,hash.ToString().c_str(),dstr(value),txtime); - for (iter=0; iter<3600; iter++) + if ( komodo_blockload(block,pindex) == 0 ) { - diff = (iter + blocktime - txtime - minage); - if ( iter > 0 ) - diff += iter + segid*2; - //if ( diff > 3600*24 ) - // break; - if ( blocktime+iter+segid*2 < txtime+minage ) - continue; - coinage = (value * diff) * ((diff >> 16) + 1); - hashval = arith_uint256(supply * 64) * (UintToArith256(hash) / arith_uint256(coinage+1)); - if ( hashval <= bnTarget ) + txn_count = block.vtx.size(); + if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1 ) { - winner = 1; - if ( validateflag == 0 ) + txid = block.vtx[txn_count-1].vin[0].prevout.hash; + vout = block.vtx[txn_count-1].vin[0].prevout.n; + txtime = komodo_txtime(&value,txid,vout,destaddr); + if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) { - blocktime += iter; - blocktime += segid * 2; - } - break; - } - if ( validateflag != 0 ) - { - /*for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - fprintf(stderr," vs target "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d gap.%d %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,(int32_t)(blocktime - prevtime),dstr(value),(int32_t)diff);*/ - break; + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value ) + { + segid = komodo_segid32(voutaddr) & 0x3f; + } + } else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); } } - //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); - if ( 0 ) + } + return(segid); +} + +int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) +{ + static uint8_t prevhashbuf[100]; static int32_t prevheight; + int32_t i; + if ( height == prevheight && n == 100 ) + memcpy(hashbuf,prevhashbuf,100); + else + { + memset(hashbuf,0xff,n); + for (i=0; i=24; i--) + hashbuf[i] = (uint8_t)komodo_segid(height+i); + //fprintf(stderr,"%02x ",hashbuf[i]); + } + if ( n == 100 ) + { + memcpy(prevhashbuf,hashbuf,100); + prevheight = height; + //fprintf(stderr,"prevsegids.%d\n",height+n); + } + } +} + +uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout) +{ + bits256 addrhash; + vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address)); + memcpy(&hashbuf[100],&addrhash,sizeof(addrhash)); + memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid)); + memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout)); + vcalc_sha256(0,(uint8_t *)hashp,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout)); + return(addrhash.uints[0]); +} + +uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr) +{ + bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t diff=0,segid,minage,i,iter=0; uint32_t txtime,winner = 0 ; uint64_t value,coinage; + txtime = komodo_txtime2(&value,txid,vout,address); + if ( validateflag == 0 ) + { + //fprintf(stderr,"blocktime.%u -> ",blocktime); + if ( blocktime < prevtime+3 ) + blocktime = prevtime+3; + if ( blocktime < GetAdjustedTime()-60 ) + blocktime = GetAdjustedTime()+30; + //fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime); + } + if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 ) + { + //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime); + return(0); + } + if ( value < SATOSHIDEN ) + return(0); + value /= SATOSHIDEN; + mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + ratio = (mindiff / bnTarget); + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address)); + segid = ((nHeight + addrhash.uints[0]) & 0x3f); + komodo_segids(hashbuf,nHeight-101,100); + memcpy(&hashbuf[100],&addrhash,sizeof(addrhash)); + memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid)); + memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout)); + vcalc_sha256(0,(uint8_t *)&hash,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout)); + for (iter=0; iter<180; iter++) + { + if ( blocktime+iter+segid*2 < txtime+minage ) + continue; + diff = (iter + blocktime - txtime - minage); + if ( diff < 0 ) + diff = 60; + else if ( diff > 3600*24*30 ) + { + //printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage); + diff = 3600*24*30; + } + if ( iter > 0 ) + diff += segid*2; + coinage = (value * diff); + if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 ) + coinage *= ((blocktime+iter+segid*2) - (prevtime+60)); + coinage256 = arith_uint256(coinage+1); + hashval = ratio * (UintToArith256(hash) / coinage256); + if ( nHeight >= 900 && nHeight < 916 ) + hashval = (hashval / coinage256); + if ( hashval <= bnTarget ) + { + winner = 1; + if ( validateflag == 0 ) + { + //fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid); + blocktime += iter; + blocktime += segid * 2; + } + break; + } + if ( validateflag != 0 ) + { + /*for (i=31; i>=24; i--) fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); fprintf(stderr," vs "); for (i=31; i>=24; i--) fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,dstr(value),(int32_t)diff); + fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff);*/ + break; } - } //else fprintf(stderr,"skip PoS scan: diff %d blocktime %u > %u txtime+minage %u pindex.%p\n",(int32_t)(blocktime - (txtime+minage)),blocktime,txtime,minage,pindex); + } + //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); + if ( 0 && validateflag != 0 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d ht.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff,nHeight); + } if ( nHeight < 10 ) return(blocktime); return(blocktime * winner); @@ -1163,18 +1288,36 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc) { - CBlockIndex *pindex; arith_uint256 bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,ht,percPoS,diff,val; + CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val; *percPoSp = percPoS = 0; if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) return(target); sum = arith_uint256(0); ave = sum; - for (i=n=0; i<100; i++) + easydiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + for (i=n=m=0; i<100; i++) { ht = height - 100 + i; if ( ht <= 1 ) continue; if ( (pindex= komodo_chainactive(ht)) != 0 ) + { + if ( komodo_segid(ht) >= 0 ) + { + n++; + percPoS++; + if ( ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"0"); + } + else + { + if ( ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"1"); + sum += UintToArith256(pindex->GetBlockHash()); + m++; + } + } + /*if ( (pindex= komodo_chainactive(ht)) != 0 ) { bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow); bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); @@ -1188,26 +1331,27 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he } else { + n++; percPoS++; if ( ASSETCHAINS_STAKED < 100 ) fprintf(stderr,"0"); } - if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) - fprintf(stderr," %d, ",percPoS); - } + }*/ + if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) + fprintf(stderr," %d, ",percPoS); } - if ( n < 100 ) + if ( m+n < 100 ) percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; if ( ASSETCHAINS_STAKED < 100 ) fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); *percPoSp = percPoS; - target = (target / arith_uint256(KOMODO_POWMINMULT)); - if ( n > 0 ) + //target = (target / arith_uint256(KOMODO_POWMINMULT)); + if ( m > 0 ) { - ave = (sum / arith_uint256(n)); + ave = (sum / arith_uint256(m)); if ( ave > target ) ave = target; - } else return(target); + } else ave = easydiff; //else return(target); if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget { bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc); @@ -1226,7 +1370,15 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he } else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget { - bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); + bnTarget = (ave * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc); + if ( bnTarget > easydiff ) + bnTarget = easydiff; + else if ( bnTarget < ave ) // overflow + { + bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); + if ( bnTarget < ave ) + bnTarget = ave; + } if ( 1 ) { for (i=31; i>=24; i--) @@ -1246,9 +1398,11 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget) { - CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible,isPoS = 0; uint64_t value; CTxDestination voutaddress; + CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible=0,isPoS = 0; uint64_t value; CTxDestination voutaddress; + if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) + return(1); txn_count = pblock->vtx.size(); - if ( txn_count > 1 ) + if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 ) { if ( prevtime == 0 ) { @@ -1259,24 +1413,29 @@ 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 ( prevtime != 0 ) { - eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime,(char *)""); + if ( komodo_isPoS(pblock) != 0 ) + eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)""); if ( eligible == 0 || eligible > pblock->nTime ) { - fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime)); + if ( ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime)); } else isPoS = 1; } - else if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx + if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx { - txtime = komodo_txtime(&value,txid,vout,destaddr); + if ( komodo_isPoS(pblock) != 0 ) + isPoS = 1; + /*txtime = komodo_txtime(&value,txid,vout,destaddr); if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) { strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value ) isPoS = 1; // close enough for a pre-filter - else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue)); - } else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height); - } else return(-1); + //else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue)); + } else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);*/ + } //else return(-1); } + //fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS); return(isPoS); } @@ -1344,23 +1503,24 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) } else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) { - if (KOMODO_TEST_ASSETCHAIN_SKIP_POW) return(0); - fprintf(stderr,"pow violation and no chance it is notary ht.%d %s\n",height,hash.ToString().c_str()); - return(-1); + if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW ) + return(0); + if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget + return(-1); } } - else if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW + if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW { if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 ) { - if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! + if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 return(-1); else { + if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target + return(0); if ( slowflag != 0 ) bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED); - else if ( height > 100 ) - bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); // lower bound if ( bhash > bnTarget ) { for (i=31; i>=16; i--) @@ -1395,3 +1555,79 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) else return(0); } +int64_t komodo_newcoins(int64_t *zfundsp,int32_t nHeight,CBlock *pblock) +{ + CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0; + n = pblock->vtx.size(); + for (i=0; ivtx[i]; + zfunds += (tx.GetJoinSplitValueOut() - tx.GetJoinSplitValueIn()); + if ( (m= tx.vin.size()) > 0 ) + { + for (j=0; j= vintx.vout.size() ) + { + fprintf(stderr,"ERROR: %s/v%d cant find\n",txid.ToString().c_str(),vout); + return(0); + } + vinsum += vintx.vout[vout].nValue; + } + } + if ( (m= tx.vout.size()) > 0 ) + { + for (j=0; j %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str()); + } + script = (uint8_t *)tx.vout[j].scriptPubKey.data(); + if ( script == 0 || script[0] != 0x6a ) + { + if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 ) + voutsum += tx.vout[j].nValue; + } + } + } + *zfundsp = zfunds; + if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times + return(3 * SATOSHIDEN); + //if ( voutsum-vinsum+zfunds > 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 ) + //. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds)); + return(voutsum - vinsum); +} + +int64_t komodo_coinsupply(int64_t *zfundsp,int32_t height) +{ + CBlockIndex *pindex; CBlock block; int64_t zfunds=0,supply = 0; + //fprintf(stderr,"coinsupply %d\n",height); + *zfundsp = 0; + if ( (pindex= komodo_chainactive(height)) != 0 ) + { + while ( pindex != 0 && pindex->nHeight > 0 ) + { + if ( pindex->newcoins == 0 && pindex->zfunds == 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + pindex->newcoins = komodo_newcoins(&pindex->zfunds,pindex->nHeight,&block); + else + { + fprintf(stderr,"error loading block.%d\n",pindex->nHeight); + return(0); + } + } + supply += pindex->newcoins; + zfunds += pindex->zfunds; + //printf("start ht.%d new %.8f -> supply %.8f zfunds %.8f -> %.8f\n",pindex->nHeight,dstr(pindex->newcoins),dstr(supply),dstr(pindex->zfunds),dstr(zfunds)); + pindex = pindex->pprev; + } + } + *zfundsp = zfunds; + return(supply); +} diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 9de6b4fc9..6a8ef310b 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1490,7 +1490,7 @@ void komodo_passport_iteration() komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); if ( (fp= fopen(fname,"wb")) != 0 ) { - buf[0] = (uint32_t)chainActive.Tip()->nHeight; + buf[0] = (uint32_t)chainActive.LastTip()->nHeight; buf[1] = (uint32_t)komodo_longestchain(); if ( buf[0] != 0 && buf[0] == buf[1] ) { diff --git a/src/komodo_globals.h b/src/komodo_globals.h index b4f886e4b..8dfc7108c 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -48,11 +48,11 @@ int COINBASE_MATURITY = _COINBASE_MATURITY;//100; int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND; int32_t KOMODO_LASTMINED,prevKOMODO_LASTMINED,JUMBLR_PAUSE = 1; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; -uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC; +uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT; uint32_t ASSETCHAINS_MAGIC = 2387029918; uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h index f36bb441a..fa44425fd 100755 --- a/src/komodo_jumblr.h +++ b/src/komodo_jumblr.h @@ -648,7 +648,7 @@ void jumblr_iteration() free(retstr); } } - height = (int32_t)chainActive.Tip()->nHeight; + height = (int32_t)chainActive.LastTip()->nHeight; if ( time(NULL) < lasttime+40 ) return; lasttime = (uint32_t)time(NULL); diff --git a/src/komodo_pax.h b/src/komodo_pax.h index d0bad0e14..35d226fc3 100644 --- a/src/komodo_pax.h +++ b/src/komodo_pax.h @@ -637,13 +637,13 @@ uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume) { int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && height > chainActive.Tip()->nHeight ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->nHeight ) { if ( height < 100000000 ) { static uint32_t counter; if ( counter++ < 3 ) - printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.Tip()->nHeight); + printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->nHeight); } return(0); } diff --git a/src/komodo_utils.h b/src/komodo_utils.h index c8c2e35b1..8188a6154 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1539,8 +1539,10 @@ void komodo_args(char *argv0) } } } + KOMODO_STOPAT = GetArg("-stopat",0); ASSETCHAINS_CC = GetArg("-ac_cc",0); ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); + ASSETCHAINS_PRIVATE = GetArg("-ac_private",0); if ( (KOMODO_REWIND= GetArg("-rewind",0)) != 0 ) { printf("KOMODO_REWIND %d\n",KOMODO_REWIND); @@ -1557,6 +1559,11 @@ void komodo_args(char *argv0) ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 ) ASSETCHAINS_STAKED = 100; + if ( ASSETCHAINS_STAKED != 0 && ASSETCHAINS_PRIVATE != 0 ) + { + printf("-ac_private chains cant have any PoS\n"); + exit(0); + } if ( ASSETCHAINS_HALVING != 0 && ASSETCHAINS_HALVING < 1440 ) { ASSETCHAINS_HALVING = 1440; @@ -1579,7 +1586,7 @@ void komodo_args(char *argv0) ASSETCHAINS_COMMISSION = 0; printf("ASSETCHAINS_COMMISSION needs an ASETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); } - if ( ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 ) + if ( ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 ) { fprintf(stderr,"end.%llu blocks, reward %.8f halving.%llu blocks, decay.%llu perc %.4f%% ac_pub=[%02x...]\n",(long long)ASSETCHAINS_ENDSUBSIDY,dstr(ASSETCHAINS_REWARD),(long long)ASSETCHAINS_HALVING,(long long)ASSETCHAINS_DECAY,dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0]); extraptr = extrabuf; @@ -1588,7 +1595,7 @@ void komodo_args(char *argv0) extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD),(void *)&ASSETCHAINS_REWARD); extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING),(void *)&ASSETCHAINS_HALVING); extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY),(void *)&ASSETCHAINS_DECAY); - val = ASSETCHAINS_COMMISSION | (((uint64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | (ASSETCHAINS_PUBLIC & 0xff); + val = ASSETCHAINS_COMMISSION | (((uint64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6); extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); } addn = GetArg("-seednode",""); diff --git a/src/main.cpp b/src/main.cpp index a7565e0ab..330bf6ad1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1090,6 +1090,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio // Check for negative or overflow output values CAmount nValueOut = 0; + int32_t iscoinbase = tx.IsCoinBase(); BOOST_FOREACH(const CTxOut& txout, tx.vout) { if (txout.nValue < 0) @@ -1100,6 +1101,12 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio fprintf(stderr,"%.8f > max %.8f\n",(double)txout.nValue/COIN,(double)MAX_MONEY/COIN); return state.DoS(100, error("CheckTransaction(): txout.nValue too high"),REJECT_INVALID, "bad-txns-vout-toolarge"); } + if ( ASSETCHAINS_PRIVATE != 0 ) + { + fprintf(stderr,"private chain nValue %.8f iscoinbase.%d\n",(double)txout.nValue/COIN,iscoinbase); + if ( (txout.nValue > 0 && iscoinbase == 0) || tx.GetJoinSplitValueOut() > 0 ) + return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain"); + } nValueOut += txout.nValue; if (!MoneyRange(nValueOut)) return state.DoS(100, error("CheckTransaction(): txout total out of range"), @@ -1262,7 +1269,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } auto verifier = libzcash::ProofVerifier::Strict(); - if ( komodo_validate_interest(tx,chainActive.Tip()->nHeight+1,chainActive.Tip()->GetMedianTimePast() + 777,0) < 0 ) + if ( komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) { //fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n"); return error("AcceptToMemoryPool: komodo_validate_interest failed"); @@ -1304,7 +1311,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa uint256 hash = tx.GetHash(); if (pool.exists(hash)) { - fprintf(stderr,"already in mempool\n"); + //fprintf(stderr,"already in mempool\n"); return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } @@ -1392,7 +1399,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Bring the best block into scope view.GetBestBlock(); - nValueIn = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime); + nValueIn = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime); if ( 0 && interest != 0 ) fprintf(stderr,"add interest %.8f\n",(double)interest/COIN); // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool @@ -1742,7 +1749,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern uint32_t ASSETCHAINS_MAGIC; extern uint64_t ASSETCHAINS_STAKED,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; -extern uint8_t ASSETCHAINS_PUBLIC; +extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { @@ -1884,7 +1891,7 @@ void CheckForkWarningConditions() if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 288) pindexBestForkTip = NULL; - if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6))) + if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.LastTip()->nChainWork + (GetBlockProof(*chainActive.LastTip()) * 6))) { if (!fLargeWorkForkFound && pindexBestForkBase) { @@ -1919,7 +1926,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) AssertLockHeld(cs_main); // If we are on a fork that is sufficiently large, set a warning flag CBlockIndex* pfork = pindexNewForkTip; - CBlockIndex* plonger = chainActive.Tip(); + CBlockIndex* plonger = chainActive.LastTip(); while (pfork && pfork != plonger) { while (plonger && plonger->nHeight > pfork->nHeight) @@ -1976,7 +1983,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime())); - CBlockIndex *tip = chainActive.Tip(); + CBlockIndex *tip = chainActive.LastTip(); assert (tip); LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__, tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0), @@ -2104,14 +2111,14 @@ namespace Consensus { // Check for negative or overflow input values nValueIn += coins->vout[prevout.n].nValue; #ifdef KOMODO_ENABLE_INTEREST - if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 ) { if ( coins->vout[prevout.n].nValue >= 10*COIN ) { int64_t interest; int32_t txheight; uint32_t locktime; if ( (interest= komodo_accrued_interest(&txheight,&locktime,prevout.hash,prevout.n,0,coins->vout[prevout.n].nValue,(int32_t)nSpendHeight-1)) != 0 ) { - //fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.Tip()->nTime); + //fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.LastTip()->nTime); nValueIn += interest; } } @@ -2684,7 +2691,8 @@ static int64_t nTimeTotal = 0; bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW) { const CChainParams& chainparams = Params(); - + if ( KOMODO_STOPAT != 0 && pindex->nHeight > KOMODO_STOPAT ) + return(false); //fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->nHeight); AssertLockHeld(cs_main); bool fExpensiveChecks = true; @@ -2860,7 +2868,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!tx.IsCoinBase()) { - nFees += view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime) - tx.GetValueOut(); + nFees += view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime) - tx.GetValueOut(); sum += interest; std::vector vChecks; @@ -3187,10 +3195,19 @@ void static UpdateTip(CBlockIndex *pindexNew) { nTimeBestReceived = GetTime(); mempool.AddTransactionsUpdated(1); KOMODO_NEWBLOCKS++; + double progress; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip()); + } else { + int32_t longestchain = komodo_longestchain(); + progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; + } + LogPrintf("%s: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); + chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(), + log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.LastTip()->nChainTx, + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), progress, + pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); cvBlockChange.notify_all(); @@ -3245,13 +3262,17 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; - if (!fBare) { + if (!fBare) + { // Resurrect mempool transactions from the disconnected block. - BOOST_FOREACH(const CTransaction &tx, block.vtx) { + //BOOST_FOREACH(const CTransaction &tx, block.vtx) { + for (int i = 0; i < block.vtx.size(); i++) + { + CTransaction &tx = block.vtx[i]; // ignore validation errors in resurrected transactions list removed; CValidationState stateDummy; - if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) + if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) mempool.remove(tx, removed, true); } if (anchorBeforeDisconnect != anchorAfterDisconnect) { @@ -3268,11 +3289,23 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), newTree)); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - SyncWithWallets(tx, NULL); - } + //BOOST_FOREACH(const CTransaction &tx, block.vtx) { + // SyncWithWallets(tx, NULL); + //} // Update cached incremental witnesses //fprintf(stderr,"chaintip false\n"); + for (int i = 0; i < block.vtx.size(); i++) + { + CTransaction &tx = block.vtx[i]; + if ( (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 ) + { + EraseFromWallets(tx.GetHash()); + } + else + { + SyncWithWallets(tx, NULL); + } + } GetMainSignals().ChainTip(pindexDelete, &block, newTree, false); return true; } @@ -3422,7 +3455,7 @@ static void PruneBlockIndexCandidates() { // Note that we can't delete the current block itself, as we may need to return to it later in case a // reorganization to a better block fails. std::set::iterator it = setBlockIndexCandidates.begin(); - while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) { + while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.LastTip())) { setBlockIndexCandidates.erase(it++); } // Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates. @@ -3474,8 +3507,8 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo if ( KOMODO_REWIND != 0 ) { CBlockIndex *tipindex; - fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.Tip()->nHeight,KOMODO_REWIND); - while ( KOMODO_REWIND > 0 && (tipindex= chainActive.Tip()) != 0 && tipindex->nHeight > KOMODO_REWIND ) + fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.LastTip()->nHeight,KOMODO_REWIND); + while ( KOMODO_REWIND > 0 && (tipindex= chainActive.LastTip()) != 0 && tipindex->nHeight > KOMODO_REWIND ) { fBlocksDisconnected = true; fprintf(stderr,"%d ",(int32_t)tipindex->nHeight); @@ -3889,9 +3922,9 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- CheckBlockHeader\n"); - if ( chainActive.Tip() != 0 ) + if ( chainActive.LastTip() != 0 ) { - hash = chainActive.Tip()->GetBlockHash(); + hash = chainActive.LastTip()->GetBlockHash(); for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- chainTip\n"); @@ -4070,8 +4103,13 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta // Don't accept any forks from the main chain prior to last checkpoint CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints()); int32_t notarized_height; - if ( nHeight == 1 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight > 1 ) - return(false); + if ( nHeight == 1 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight > 1 ) + { + CBlockIndex *heightblock = chainActive[nHeight]; + if ( heightblock != 0 && heightblock->GetBlockHash() == hash ) + return true; + return state.DoS(1, error("%s: trying to change height 1 forbidden", __func__)); + } if ( nHeight != 0 ) { if ( pcheckpoint != 0 && nHeight < pcheckpoint->nHeight ) @@ -4402,8 +4440,8 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo auto verifier = libzcash::ProofVerifier::Disabled(); hash = pblock->GetHash(); - if ( chainActive.Tip() != 0 ) - komodo_currentheight_set(chainActive.Tip()->nHeight); + if ( chainActive.LastTip() != 0 ) + komodo_currentheight_set(chainActive.LastTip()->nHeight); checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0); { LOCK(cs_main); @@ -4821,11 +4859,21 @@ bool static LoadBlockIndexDB() it->second->hashAnchorEnd = pcoinsTip->GetBestAnchor(); PruneBlockIndexCandidates(); + + double progress; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + progress = Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip()); + } else { + int32_t longestchain = komodo_longestchain(); + // TODO: komodo_longestchain does not have the data it needs at the time LoadBlockIndexDB + // runs, which makes it return 0, so we guess 50% for now + progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 0.5; + } LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip())); + chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(), + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), + progress); EnforceNodeDeprecation(chainActive.Height(), true); diff --git a/src/metrics.cpp b/src/metrics.cpp index 6c8f80fe5..cb9fe245c 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -211,7 +211,7 @@ int printStats(bool mining) { LOCK2(cs_main, cs_vNodes); height = chainActive.Height(); - tipmediantime = chainActive.Tip()->GetMedianTimePast(); + tipmediantime = chainActive.LastTip()->GetMedianTimePast(); connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } diff --git a/src/miner.cpp b/src/miner.cpp index 5ed1c5af7..0c458a985 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -117,11 +117,7 @@ uint32_t Mining_start,Mining_height; int32_t My_notaryid = -1; int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); -//uint64_t komodo_paxtotal(); int32_t komodo_baseid(char *origbase); -//int32_t komodo_is_issuer(); -//int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo); -//int32_t komodo_isrealtime(int32_t *kmdheightp); int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); uint64_t komodo_commission(const CBlock *block); int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig); @@ -140,29 +136,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) return NULL; } CBlock *pblock = &pblocktemplate->block; // pointer for convenience - /*if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && chainActive.Tip()->nHeight >= ASSETCHAINS_MINHEIGHT ) - { - isrealtime = komodo_isrealtime(&kmdheight); - deposits = komodo_paxtotal(); - while ( KOMODO_ON_DEMAND == 0 && deposits == 0 && (int32_t)mempool.GetTotalTxSize() == 0 ) - { - deposits = komodo_paxtotal(); - if ( KOMODO_PASSPORT_INITDONE == 0 || KOMODO_INITDONE == 0 || (komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && (isrealtime= komodo_isrealtime(&kmdheight)) == 0) ) - { - //fprintf(stderr,"INITDONE.%d RT.%d deposits %.8f ht.%d\n",KOMODO_INITDONE,isrealtime,(double)deposits/COIN,kmdheight); - } - else if ( komodo_isrealtime(&kmdheight) != 0 && (deposits != 0 || (int32_t)mempool.GetTotalTxSize() > 0) ) - { - fprintf(stderr,"start CreateNewBlock %s initdone.%d deposit %.8f mempool.%d RT.%u KOMODO_ON_DEMAND.%d\n",ASSETCHAINS_SYMBOL,KOMODO_INITDONE,(double)komodo_paxtotal()/COIN,(int32_t)mempool.GetTotalTxSize(),isrealtime,KOMODO_ON_DEMAND); - break; - } - sleep(10); - } - KOMODO_ON_DEMAND = 0; - if ( 0 && deposits != 0 ) - printf("miner KOMODO_DEPOSIT %llu pblock->nHeight %d mempool.GetTotalTxSize(%d)\n",(long long)komodo_paxtotal(),(int32_t)chainActive.Tip()->nHeight,(int32_t)mempool.GetTotalTxSize()); - }*/ - // -regtest only: allow overriding block.nVersion with + // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios if (Params().MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); @@ -192,7 +166,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) { LOCK2(cs_main, mempool.cs); - CBlockIndex* pindexPrev = chainActive.Tip(); + CBlockIndex* pindexPrev = chainActive.LastTip(); const int nHeight = pindexPrev->nHeight + 1; uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus()); pblock->nTime = GetAdjustedTime(); @@ -360,7 +334,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) //fprintf(stderr,"dont have inputs\n"); continue; } - CAmount nTxFees = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime)-tx.GetValueOut(); + CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) @@ -422,17 +396,18 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) { uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid,revtxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr; CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); + sleep(1); if ( (siglen= komodo_staked(txStaked,pblock->nBits,&blocktime,&txtime,&utxotxid,&utxovout,&utxovalue,utxosig)) > 0 ) { CAmount txfees = 0; - if ( (int32_t)chainActive.Tip()->nHeight+1 > 100 && GetAdjustedTime() < blocktime-13 ) - return(0); + //if ( (int32_t)chainActive.LastTip()->nHeight+1 > 100 && GetAdjustedTime() < blocktime-157 ) + // return(0); pblock->vtx.push_back(txStaked); pblocktemplate->vTxFees.push_back(txfees); pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); nFees += txfees; pblock->nTime = blocktime; - printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.Tip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); + //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } @@ -517,7 +492,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) return(0); } } - else + else if ( ASSETCHAINS_STAKED == 0 ) { CValidationState state; if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) @@ -665,19 +640,19 @@ static bool ProcessBlockFound(CBlock* pblock) #endif // ENABLE_WALLET { LogPrintf("%s\n", pblock->ToString()); - LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1); + LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.LastTip()->nHeight+1); // Found a solution { LOCK(cs_main); - if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) + if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash()) { uint256 hash; int32_t i; hash = pblock->hashPrevBlock; for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- prev (stale)\n"); - hash = chainActive.Tip()->GetBlockHash(); + hash = chainActive.LastTip()->GetBlockHash(); for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- chainTip (stale)\n"); @@ -705,7 +680,7 @@ static bool ProcessBlockFound(CBlock* pblock) // Process this block the same as if we had received it from another node CValidationState state; - if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) return error("KomodoMiner: ProcessNewBlock, block not accepted"); TrackMinedBlock(pblock->GetHash()); @@ -743,13 +718,13 @@ void static BitcoinMiner() unsigned int n = chainparams.EquihashN(); unsigned int k = chainparams.EquihashK(); uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1; - while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->nHeight != 235300 && + while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.LastTip()->nHeight != 235300 && { sleep(1); if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) break; } - komodo_chosennotary(¬aryid,chainActive.Tip()->nHeight,NOTARY_PUBKEY33,(uint32_t)chainActive.Tip()->GetBlockTime()); + komodo_chosennotary(¬aryid,chainActive.LastTip()->nHeight,NOTARY_PUBKEY33,(uint32_t)chainActive.LastTip()->GetBlockTime()); if ( notaryid != My_notaryid ) My_notaryid = notaryid; std::string solver; @@ -775,9 +750,9 @@ void static BitcoinMiner() fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str()); while (true) { - if (chainparams.MiningRequiresPeers()) //chainActive.Tip()->nHeight != 235300 && + if (chainparams.MiningRequiresPeers()) //chainActive.LastTip()->nHeight != 235300 && { - //if ( ASSETCHAINS_SEED != 0 && chainActive.Tip()->nHeight < 100 ) + //if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->nHeight < 100 ) // break; // Busy-wait for the network to come online so we don't waste time mining // on an obsolete chain. In regtest mode we expect to fly solo. @@ -801,7 +776,7 @@ void static BitcoinMiner() // Create new block // unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); + CBlockIndex* pindexPrev = chainActive.LastTip(); if ( Mining_height != pindexPrev->nHeight+1 ) { Mining_height = pindexPrev->nHeight+1; @@ -810,7 +785,7 @@ void static BitcoinMiner() if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED == 0 ) { //fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height); - sleep(3); + //sleep(3); } #ifdef ENABLE_WALLET CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey,pindexPrev->nHeight+1,gpucount); @@ -856,9 +831,10 @@ void static BitcoinMiner() // // Search // - uint8_t pubkeys[66][33]; uint32_t blocktimes[66]; int mids[256],nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime(); + uint8_t pubkeys[66][33]; arith_uint256 bnMaxPoSdiff; uint32_t blocktimes[66]; int mids[256],nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime(); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); savebits = pblock->nBits; - HASHTarget = arith_uint256().SetCompact(pblock->nBits); + HASHTarget = arith_uint256().SetCompact(savebits); roundrobin_delay = ROUNDROBIN_DELAY; if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 ) { @@ -911,15 +887,11 @@ void static BitcoinMiner() } //else fprintf(stderr,"duplicate at j.%d\n",j); } else Mining_start = 0; } else Mining_start = 0; - if ( ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 ) + if ( ASSETCHAINS_STAKED != 0 ) { - int32_t percPoS,z; - /*if ( Mining_height <= 100 ) - { - sleep(60); - continue; - }*/ + int32_t percPoS,z; bool fNegative,fOverflow; HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); + HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); if ( ASSETCHAINS_STAKED < 100 ) { for (z=31; z>=0; z--) @@ -979,14 +951,18 @@ void static BitcoinMiner() fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]); fprintf(stderr," POW\n");*/ if ( h > hashTarget ) - return false; - if ( B.nTime > GetAdjustedTime() ) { - fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime())); + //if ( ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 ) + // sleep(1); + return false; + } + if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetAdjustedTime() ) + { + //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime())); while ( GetAdjustedTime() < B.nTime-2 ) { sleep(1); - if ( chainActive.Tip()->nHeight >= Mining_height ) + if ( chainActive.LastTip()->nHeight >= Mining_height ) { fprintf(stderr,"new block arrived\n"); return(false); @@ -1004,15 +980,19 @@ void static BitcoinMiner() } else { - while ( GetAdjustedTime() < B.nTime ) + while ( B.nTime-57 > GetAdjustedTime() ) + { sleep(1); + if ( chainActive.LastTip()->nHeight >= Mining_height ) + return(false); + } uint256 tmp = B.GetHash(); int32_t z; for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]); - fprintf(stderr," mined block!\n"); + fprintf(stderr," mined %s block %d!\n",ASSETCHAINS_SYMBOL,Mining_height); } CValidationState state; - if ( !TestBlockValidity(state,B, chainActive.Tip(), true, false)) + if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false)) { h = UintToArith256(B.GetHash()); for (z=31; z>=0; z--) @@ -1132,7 +1112,7 @@ void static BitcoinMiner() fprintf(stderr,"timeout, break\n"); break; } - if ( pindexPrev != chainActive.Tip() ) + if ( pindexPrev != chainActive.LastTip() ) { if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"Tip advanced, break\n"); @@ -1190,7 +1170,7 @@ void static BitcoinMiner() delete minerThreads; minerThreads = NULL; } - fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate); + //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate); if ( nThreads == 0 ) nThreads = 1; if (nThreads == 0 || !fGenerate) diff --git a/src/pow.cpp b/src/pow.cpp index 2e525e8cb..6d218ef13 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -190,6 +190,11 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash,unsigned int } if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) return error("CheckProofOfWork(): nBits below minimum work"); + if ( ASSETCHAINS_STAKED != 0 ) + { + arith_uint256 bnMaxPoSdiff; + bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + } // Check proof of work matches claimed amount if ( UintToArith256(hash) > bnTarget ) { diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index d6ad31c3a..04222e854 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -232,11 +232,26 @@ CAmount CTransaction::GetJoinSplitValueIn() const { // NB: vpub_new "gives" money to the value pool just as inputs do nValue += it->vpub_new; - + if (!MoneyRange(it->vpub_new) || !MoneyRange(nValue)) throw std::runtime_error("CTransaction::GetJoinSplitValueIn(): value out of range"); } + + return nValue; +} +CAmount CTransaction::GetJoinSplitValueOut() const +{ + CAmount nValue = 0; + for (std::vector::const_iterator it(vjoinsplit.begin()); it != vjoinsplit.end(); ++it) + { + // NB: vpub_new "gives" money to the value pool just as inputs do + nValue += it->vpub_old; + + if (!MoneyRange(it->vpub_old) || !MoneyRange(nValue)) + throw std::runtime_error("CTransaction::GetJoinSplitValueOut(): value out of range"); + } + return nValue; } diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 88ee9a312..e3615c120 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -445,6 +445,8 @@ public: // Return sum of JoinSplit vpub_new CAmount GetJoinSplitValueIn() const; + // Return sum of JoinSplit vpub_old + CAmount GetJoinSplitValueOut() const; // Compute priority, given priority of inputs and (optionally) tx size double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const; diff --git a/src/rest.cpp b/src/rest.cpp index 8e2e4d1e6..38cc38466 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -530,7 +530,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // serialize data // use exact same output as mentioned in Bip64 CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); - ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs; + ssGetUTXOResponse << chainActive.Height() << chainActive.LastTip()->GetBlockHash() << bitmap << outs; string ssGetUTXOResponseString = ssGetUTXOResponse.str(); req->WriteHeader("Content-Type", "application/octet-stream"); @@ -540,7 +540,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) case RF_HEX: { CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); - ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs; + ssGetUTXOResponse << chainActive.Height() << chainActive.LastTip()->GetBlockHash() << bitmap << outs; string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n"; req->WriteHeader("Content-Type", "text/plain"); @@ -554,7 +554,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // pack in some essentials // use more or less the same output as mentioned in Bip64 objGetUTXOResponse.push_back(Pair("chainHeight", chainActive.Height())); - objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.Tip()->GetBlockHash().GetHex())); + objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.LastTip()->GetBlockHash().GetHex())); objGetUTXOResponse.push_back(Pair("bitmap", bitmapStringRepresentation)); UniValue utxos(UniValue::VARR); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 42cf7f2b0..7f8984c63 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -38,10 +38,10 @@ double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficul // minimum difficulty = 1.0. if (blockindex == NULL) { - if (chainActive.Tip() == NULL) + if (chainActive.LastTip() == NULL) return 1.0; else - blockindex = chainActive.Tip(); + blockindex = chainActive.LastTip(); } uint32_t bits; @@ -326,7 +326,7 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp) ); LOCK(cs_main); - return chainActive.Tip()->GetBlockHash().GetHex(); + return chainActive.LastTip()->GetBlockHash().GetHex(); } UniValue getdifficulty(const UniValue& params, bool fHelp) @@ -803,13 +803,13 @@ UniValue kvsearch(const UniValue& params, bool fHelp) if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) { ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("currentheight", (int64_t)chainActive.Tip()->nHeight)); + ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); ret.push_back(Pair("key",params[0].get_str())); ret.push_back(Pair("keylen",keylen)); if ( keylen < sizeof(key) ) { memcpy(key,params[0].get_str().c_str(),keylen); - if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) + if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) { std::string val; char *valuestr; val.resize(valuesize); @@ -837,7 +837,7 @@ UniValue minerids(const UniValue& params, bool fHelp) LOCK(cs_main); int32_t height = atoi(params[0].get_str().c_str()); if ( height <= 0 ) - height = chainActive.Tip()->nHeight; + height = chainActive.LastTip()->nHeight; else { CBlockIndex *pblockindex = chainActive[height]; @@ -899,8 +899,8 @@ UniValue notaries(const UniValue& params, bool fHelp) else timestamp = (uint32_t)time(NULL); if ( height < 0 ) { - height = chainActive.Tip()->nHeight; - timestamp = chainActive.Tip()->GetBlockTime(); + height = chainActive.LastTip()->nHeight; + timestamp = chainActive.LastTip()->GetBlockTime(); } else if ( params.size() < 2 ) { @@ -988,7 +988,7 @@ UniValue paxprice(const UniValue& params, bool fHelp) std::string rel = params[1].get_str(); int32_t height; if ( params.size() == 2 ) - height = chainActive.Tip()->nHeight; + height = chainActive.LastTip()->nHeight; else height = atoi(params[2].get_str().c_str()); //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) basevolume = 100000; @@ -1280,10 +1280,10 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) obj.push_back(Pair("chain", Params().NetworkIDString())); obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); - obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex())); + obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()))); - obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); + obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()))); + obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); ZCIncrementalMerkleTree tree; @@ -1294,7 +1294,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) obj.push_back(Pair("commitments", tree.size())); #endif - CBlockIndex* tip = chainActive.Tip(); + CBlockIndex* tip = chainActive.LastTip(); UniValue valuePools(UniValue::VARR); valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); obj.push_back(Pair("valuePools", valuePools)); @@ -1319,7 +1319,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) if (fPruneMode) { - CBlockIndex *block = chainActive.Tip(); + CBlockIndex *block = chainActive.LastTip(); while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) block = block->pprev; @@ -1394,7 +1394,7 @@ UniValue getchaintips(const UniValue& params, bool fHelp) } // Always report the currently active tip. - setTips.insert(chainActive.Tip()); + setTips.insert(chainActive.LastTip()); /* Construct the output array. */ UniValue res(UniValue::VARR); const CBlockIndex *forked; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index afe4e5a33..47fbeec30 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -39,7 +39,7 @@ using namespace std; * If 'height' is nonnegative, compute the estimate at the time when a given block was found. */ int64_t GetNetworkHashPS(int lookup, int height) { - CBlockIndex *pb = chainActive.Tip(); + CBlockIndex *pb = chainActive.LastTip(); if (height >= 0 && height < chainActive.Height()) pb = chainActive[height]; @@ -224,7 +224,7 @@ UniValue generate(const UniValue& params, bool fHelp) CBlock *pblock = &pblocktemplate->block; { LOCK(cs_main); - IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); + IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce); } // Hash state @@ -268,7 +268,7 @@ UniValue generate(const UniValue& params, bool fHelp) } endloop: CValidationState state; - if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -550,7 +550,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) return "duplicate-inconclusive"; } - CBlockIndex* const pindexPrev = chainActive.Tip(); + CBlockIndex* const pindexPrev = chainActive.LastTip(); // TestBlockValidity only supports blocks built on the current Tip if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; @@ -589,7 +589,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) else { // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier - hashWatchedChain = chainActive.Tip()->GetBlockHash(); + hashWatchedChain = chainActive.LastTip()->GetBlockHash(); nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; } @@ -599,7 +599,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) checktxtime = boost::get_system_time() + boost::posix_time::minutes(1); boost::unique_lock lock(csBestBlock); - while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) + while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) { if (!cvBlockChange.timed_wait(lock, checktxtime)) { @@ -621,7 +621,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) static CBlockIndex* pindexPrev; static int64_t nStart; static CBlockTemplate* pblocktemplate; - if (pindexPrev != chainActive.Tip() || + if (pindexPrev != chainActive.LastTip() || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on @@ -629,7 +629,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) // Store the pindexBest used before CreateNewBlockWithKey, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrevNew = chainActive.Tip(); + CBlockIndex* pindexPrevNew = chainActive.LastTip(); nStart = GetTime(); // Create new block @@ -640,7 +640,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) } #ifdef ENABLE_WALLET CReserveKey reservekey(pwalletMain); - pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.Tip()->nHeight+1,KOMODO_MAXGPUCOUNT); + pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->nHeight+1,KOMODO_MAXGPUCOUNT); #else pblocktemplate = CreateNewBlockWithKey(); #endif @@ -693,7 +693,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) // Correct this if GetBlockTemplate changes the order // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); //} - CAmount nReward = GetBlockSubsidy(chainActive.Tip()->nHeight+1, Params().GetConsensus()); + CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->nHeight+1, Params().GetConsensus()); entry.push_back(Pair("coinbasevalue", nReward)); entry.push_back(Pair("required", true)); txCoinbase = entry; @@ -726,7 +726,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) result.push_back(Pair("coinbaseaux", aux)); result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); } - result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); + result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); result.push_back(Pair("target", hashTarget.GetHex())); result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("mutable", aMutable)); @@ -809,7 +809,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL); + bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, &block, true, NULL); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 065739a9a..4405a407d 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -53,6 +53,7 @@ extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t komodo_segid32(char *coinaddr); +int64_t komodo_coinsupply(int64_t *zfundsp,int32_t height); int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); #define KOMODO_VERSION "0.1.1" extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; @@ -132,8 +133,8 @@ UniValue getinfo(const UniValue& params, bool fHelp) //fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL)); obj.push_back(Pair("longestchain", longestchain)); obj.push_back(Pair("timeoffset", GetTimeOffset())); - if ( chainActive.Tip() != 0 ) - obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime)); + if ( chainActive.LastTip() != 0 ) + obj.push_back(Pair("tiptime", (int)chainActive.LastTip()->nTime)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); @@ -151,7 +152,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("errors", GetWarnings("statusbar"))); { char pubkeystr[65]; int32_t notaryid; - if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.Tip()->nHeight,komodo_chainactive_timestamp())) >= 0 ) + if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.LastTip()->nHeight,komodo_chainactive_timestamp())) >= 0 ) { obj.push_back(Pair("notaryid", notaryid)); obj.push_back(Pair("pubkey", pubkeystr)); @@ -226,6 +227,26 @@ public: }; #endif +UniValue coinsupply(const UniValue& params, bool fHelp) +{ + int32_t height = 0; int64_t zfunds,supply = 0; UniValue result(UniValue::VOBJ); + if (fHelp || params.size() > 1) + throw runtime_error("coinsupply \n"); + if ( params.size() == 0 ) + height = chainActive.Height(); + else height = atoi(params[0].get_str()); + if ( (supply= komodo_coinsupply(&zfunds,height)) > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("coin", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); + result.push_back(Pair("height", (int)height)); + result.push_back(Pair("supply", ValueFromAmount(supply))); + result.push_back(Pair("zfunds", ValueFromAmount(zfunds))); + result.push_back(Pair("total", ValueFromAmount(zfunds + supply))); + } else result.push_back(Pair("error", "couldnt calculate supply")); + return(result); +} + UniValue jumblr_deposit(const UniValue& params, bool fHelp) { int32_t retval; UniValue result(UniValue::VOBJ); @@ -805,7 +826,7 @@ UniValue getaddressutxos(const UniValue& params, bool fHelp) result.push_back(Pair("utxos", utxos)); LOCK(cs_main); - result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex())); + result.push_back(Pair("hash", chainActive.LastTip()->GetBlockHash().GetHex())); result.push_back(Pair("height", (int)chainActive.Height())); return result; } else { diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index a9aff1b7f..525c35ca4 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -179,7 +179,7 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& const CTxOut& txout = tx.vout[i]; UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - if ( pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.Tip()) != 0 ) + if ( pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.LastTip()) != 0 ) { int64_t interest; int32_t txheight; uint32_t locktime; interest = komodo_accrued_interest(&txheight,&locktime,tx.GetHash(),i,0,txout.nValue,(int32_t)tipindex->nHeight); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index ed5110114..f37124d0c 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -280,6 +280,7 @@ static const CRPCCommand vRPCCommands[] = { "network", "clearbanned", &clearbanned, true }, /* Block chain and UTXO */ + { "blockchain", "coinsupply", &coinsupply, true }, { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, { "blockchain", "getbestblockhash", &getbestblockhash, true }, { "blockchain", "getblockcount", &getblockcount, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 5bb949299..586d79a88 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -207,6 +207,7 @@ extern UniValue getblocktemplate(const UniValue& params, bool fHelp); extern UniValue submitblock(const UniValue& params, bool fHelp); extern UniValue estimatefee(const UniValue& params, bool fHelp); extern UniValue estimatepriority(const UniValue& params, bool fHelp); +extern UniValue coinsupply(const UniValue& params, bool fHelp); extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp //extern UniValue getnewaddress64(const UniValue& params, bool fHelp); // in rpcwallet.cpp diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp deleted file mode 100644 index ef607dacc..000000000 --- a/src/test/alert_tests.cpp +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright (c) 2013 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -// -// Unit tests for alert system -// - -#include "alert.h" -#include "chain.h" -#include "chainparams.h" -#include "clientversion.h" -#include "data/alertTests.raw.h" - -#include "main.h" -#include "rpcprotocol.h" -#include "rpcserver.h" -#include "serialize.h" -#include "streams.h" -#include "util.h" -#include "utilstrencodings.h" - -#include "test/test_bitcoin.h" - -#include - -#include -#include -#include - -#include "key.h" -#include "alertkeys.h" -#include - -/* - * If the alert key pairs have changed, the test suite will fail as the - * test data is now invalid. To create valid test data, signed with a - * new alert private key, follow these steps: - * - * 1. Copy your private key into alertkeys.h. Don't commit this file! - * See sendalert.cpp for more info. - * - * 2. Set the GENERATE_ALERTS_FLAG to true. - * - * 3. Build and run: - * test_bitcoin -t Generate_Alert_Test_Data - * - * 4. Test data is saved in your current directory as alertTests.raw.NEW - * Copy this file to: src/test/data/alertTests.raw - * - * For debugging purposes, terminal output can be copied into: - * src/test/data/alertTests.raw.h - * - * 5. Clean up... - * - Set GENERATE_ALERTS_FLAG back to false. - * - Remove your private key from alertkeys.h - * - * 6. Build and verify the new test data: - * test_bitcoin -t Alert_tests - * - */ -#define GENERATE_ALERTS_FLAG false - -#if GENERATE_ALERTS_FLAG - -// NOTE: -// A function SignAndSave() was used by Bitcoin Core to create alert test data -// but it has not been made publicly available. So instead, we have adapted -// some publicly available code which achieves the intended result: -// https://gist.github.com/lukem512/9b272bd35e2cdefbf386 - - -// Code to output a C-style array of values -template -std::string HexStrArray(const T itbegin, const T itend, int lineLength) -{ - std::string rv; - static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - rv.reserve((itend-itbegin)*3); - int i = 0; - for(T it = itbegin; it < itend; ++it) - { - unsigned char val = (unsigned char)(*it); - if(it != itbegin) - { - if (i % lineLength == 0) - rv.push_back('\n'); - else - rv.push_back(' '); - } - rv.push_back('0'); - rv.push_back('x'); - rv.push_back(hexmap[val>>4]); - rv.push_back(hexmap[val&15]); - rv.push_back(','); - i++; - } - - return rv; -} - -template -inline std::string HexStrArray(const T& vch, int lineLength) -{ - return HexStrArray(vch.begin(), vch.end(), lineLength); -} - - -// Sign CAlert with alert private key -bool SignAlert(CAlert &alert) -{ - // serialize alert data - CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); - sMsg << *(CUnsignedAlert*)&alert; - alert.vchMsg = std::vector(sMsg.begin(), sMsg.end()); - - // sign alert - std::vector vchTmp(ParseHex(pszPrivKey)); - CPrivKey vchPrivKey(vchTmp.begin(), vchTmp.end()); - CKey key; - if (!key.SetPrivKey(vchPrivKey, false)) - { - printf("key.SetPrivKey failed\n"); - return false; - } - if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) - { - printf("SignAlert() : key.Sign failed\n"); - return false; - } - return true; -} - -// Sign a CAlert and serialize it -bool SignAndSerialize(CAlert &alert, CDataStream &buffer) -{ - // Sign - if(!SignAlert(alert)) - { - printf("SignAndSerialize() : could not sign alert\n"); - return false; - } - // ...and save! - buffer << alert; - return true; -} - -void GenerateAlertTests() -{ - CDataStream sBuffer(SER_DISK, CLIENT_VERSION); - - CAlert alert; - alert.nRelayUntil = 60; - alert.nExpiration = 24 * 60 * 60; - alert.nID = 1; - alert.nCancel = 0; // cancels previous messages up to this ID number - alert.nMinVer = 0; // These versions are protocol versions - alert.nMaxVer = 999001; - alert.nPriority = 1; - alert.strComment = "Alert comment"; - alert.strStatusBar = "Alert 1"; - - // Replace SignAndSave with SignAndSerialize - SignAndSerialize(alert, sBuffer); - - // More tests go here ... - alert.setSubVer.insert(std::string("/MagicBean:0.1.0/")); - alert.strStatusBar = "Alert 1 for MagicBean 0.1.0"; - SignAndSerialize(alert, sBuffer); - - alert.setSubVer.insert(std::string("/MagicBean:0.2.0/")); - alert.strStatusBar = "Alert 1 for MagicBean 0.1.0, 0.2.0"; - SignAndSerialize(alert, sBuffer); - - alert.setSubVer.clear(); - ++alert.nID; - alert.nCancel = 1; - alert.nPriority = 100; - alert.strStatusBar = "Alert 2, cancels 1"; - SignAndSerialize(alert, sBuffer); - - alert.nExpiration += 60; - ++alert.nID; - SignAndSerialize(alert, sBuffer); - - ++alert.nID; - alert.nPriority = 5000; - alert.strStatusBar = "Alert 3, disables RPC"; - alert.strRPCError = "RPC disabled"; - SignAndSerialize(alert, sBuffer); - - ++alert.nID; - alert.nPriority = 5000; - alert.strStatusBar = "Alert 4, re-enables RPC"; - alert.strRPCError = ""; - SignAndSerialize(alert, sBuffer); - - ++alert.nID; - alert.nMinVer = 11; - alert.nMaxVer = 22; - alert.nPriority = 100; - SignAndSerialize(alert, sBuffer); - - ++alert.nID; - alert.strStatusBar = "Alert 2 for MagicBean 0.1.0"; - alert.setSubVer.insert(std::string("/MagicBean:0.1.0/")); - SignAndSerialize(alert, sBuffer); - - ++alert.nID; - alert.nMinVer = 0; - alert.nMaxVer = 999999; - alert.strStatusBar = "Evil Alert'; /bin/ls; echo '"; - alert.setSubVer.clear(); - bool b = SignAndSerialize(alert, sBuffer); - - if (b) { - // Print the hex array, which will become the contents of alertTest.raw.h - std::vector vch = std::vector(sBuffer.begin(), sBuffer.end()); - printf("%s\n", HexStrArray(vch, 8).c_str()); - - // Write the data to alertTests.raw.NEW, to be copied to src/test/data/alertTests.raw - std::ofstream outfile("alertTests.raw.NEW", std::ios::out | std::ios::binary); - outfile.write((const char*)&vch[0], vch.size()); - outfile.close(); - } -} - - - -struct GenerateAlertTestsFixture : public TestingSetup { - GenerateAlertTestsFixture() {} - ~GenerateAlertTestsFixture() {} -}; - -BOOST_FIXTURE_TEST_SUITE(Generate_Alert_Test_Data, GenerateAlertTestsFixture); -BOOST_AUTO_TEST_CASE(GenerateTheAlertTests) -{ - GenerateAlertTests(); -} -BOOST_AUTO_TEST_SUITE_END() - - -#else - - -struct ReadAlerts : public TestingSetup -{ - ReadAlerts() - { - std::vector vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests)); - CDataStream stream(vch, SER_DISK, CLIENT_VERSION); - try { - while (!stream.eof()) - { - CAlert alert; - stream >> alert; - alerts.push_back(alert); - } - } - catch (const std::exception&) { } - } - ~ReadAlerts() { } - - static std::vector read_lines(boost::filesystem::path filepath) - { - std::vector result; - - std::ifstream f(filepath.string().c_str()); - std::string line; - while (std::getline(f,line)) - result.push_back(line); - - return result; - } - - std::vector alerts; -}; - -BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts) - - -BOOST_AUTO_TEST_CASE(AlertApplies) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - BOOST_FOREACH(const CAlert& alert, alerts) - { - BOOST_CHECK(alert.CheckSignature(alertKey)); - } - - BOOST_CHECK(alerts.size() >= 3); - - // Matches: - BOOST_CHECK(alerts[0].AppliesTo(1, "")); - BOOST_CHECK(alerts[0].AppliesTo(999001, "")); - BOOST_CHECK(alerts[0].AppliesTo(1, "/MagicBean:11.11.11/")); - - BOOST_CHECK(alerts[1].AppliesTo(1, "/MagicBean:0.1.0/")); - BOOST_CHECK(alerts[1].AppliesTo(999001, "/MagicBean:0.1.0/")); - - BOOST_CHECK(alerts[2].AppliesTo(1, "/MagicBean:0.1.0/")); - BOOST_CHECK(alerts[2].AppliesTo(1, "/MagicBean:0.2.0/")); - - // Don't match: - BOOST_CHECK(!alerts[0].AppliesTo(-1, "")); - BOOST_CHECK(!alerts[0].AppliesTo(999002, "")); - - BOOST_CHECK(!alerts[1].AppliesTo(1, "")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "MagicBean:0.1.0")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "/MagicBean:0.1.0")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "MagicBean:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(-1, "/MagicBean:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(999002, "/MagicBean:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "/MagicBean:0.2.0/")); - - BOOST_CHECK(!alerts[2].AppliesTo(1, "/MagicBean:0.3.0/")); - - SetMockTime(0); -} - - -BOOST_AUTO_TEST_CASE(AlertNotify) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - boost::filesystem::path temp = GetTempPath() / - boost::filesystem::unique_path("alertnotify-%%%%.txt"); - - mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); - - BOOST_FOREACH(CAlert alert, alerts) - alert.ProcessAlert(alertKey, false); - - std::vector r = read_lines(temp); - BOOST_CHECK_EQUAL(r.size(), 6u); - -// Windows built-in echo semantics are different than posixy shells. Quotes and -// whitespace are printed literally. - -#ifndef _WIN32 - BOOST_CHECK_EQUAL(r[0], "Alert 1"); - BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1"); - BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1"); - BOOST_CHECK_EQUAL(r[3], "Alert 3, disables RPC"); - BOOST_CHECK_EQUAL(r[4], "Alert 4, reenables RPC"); // dashes should be removed - BOOST_CHECK_EQUAL(r[5], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed -#else - BOOST_CHECK_EQUAL(r[0], "'Alert 1' "); - BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' "); - BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' "); - BOOST_CHECK_EQUAL(r[3], "'Alert 3, disables RPC' "); - BOOST_CHECK_EQUAL(r[4], "'Alert 4, reenables RPC' "); // dashes should be removed - BOOST_CHECK_EQUAL(r[5], "'Evil Alert; /bin/ls; echo ' "); -#endif - boost::filesystem::remove(temp); - - SetMockTime(0); - mapAlerts.clear(); -} - -BOOST_AUTO_TEST_CASE(AlertDisablesRPC) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - // Command should work before alerts - BOOST_CHECK_EQUAL(GetWarnings("rpc"), ""); - - // First alert should disable RPC - alerts[5].ProcessAlert(alertKey, false); - BOOST_CHECK_EQUAL(alerts[5].strRPCError, "RPC disabled"); - BOOST_CHECK_EQUAL(GetWarnings("rpc"), "RPC disabled"); - - // Second alert should re-enable RPC - alerts[6].ProcessAlert(alertKey, false); - BOOST_CHECK_EQUAL(alerts[6].strRPCError, ""); - BOOST_CHECK_EQUAL(GetWarnings("rpc"), ""); - - SetMockTime(0); - mapAlerts.clear(); -} - -static bool falseFunc() { return false; } - -BOOST_AUTO_TEST_CASE(PartitionAlert) -{ - // Test PartitionCheck - CCriticalSection csDummy; - CBlockIndex indexDummy[400]; - CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; - - // Generate fake blockchain timestamps relative to - // an arbitrary time: - int64_t now = 1427379054; - SetMockTime(now); - for (int i = 0; i < 400; i++) - { - indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; - indexDummy[i].nHeight = i; - indexDummy[i].nTime = now - (400-i)*nPowTargetSpacing; - // Other members don't matter, the partition check code doesn't - // use them - } - - // Test 1: chain with blocks every nPowTargetSpacing seconds, - // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); - - // Test 2: go 3.5 hours without a block, expect a warning: - now += 3*60*60+30*60; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - // Test 3: test the "partition alerts only go off once per day" - // code: - now += 60*10; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); - - // Test 4: get 2.5 times as many blocks as expected: - now += 60*60*24; // Pretend it is a day later - SetMockTime(now); - int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 400; i++) // Tweak chain timestamps: - indexDummy[i].nTime = now - (400-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - SetMockTime(0); -} - -BOOST_AUTO_TEST_SUITE_END() - -#endif diff --git a/src/txdb.cpp b/src/txdb.cpp index a0f764962..31af362ac 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -400,9 +400,9 @@ bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &addr int64_t CBlockTreeDB::Snapshot() { - char chType; int64_t total = -1; std::string address; + char chType; int64_t total = 0; std::string address; boost::scoped_ptr pcursor(NewIterator()); - pcursor->SeekToFirst(); + pcursor->SeekToLast(); fprintf(stderr,"pcursor iterate\n"); while (pcursor->Valid()) { @@ -428,7 +428,6 @@ int64_t CBlockTreeDB::Snapshot() total = (int64_t)nValue; else total += (int64_t)nValue; //addressIndex.push_back(make_pair(indexKey, nValue)); - pcursor->Next(); } catch (const std::exception& e) { return error("failed to get address index value"); } @@ -436,6 +435,7 @@ int64_t CBlockTreeDB::Snapshot() } catch (const std::exception& e) { break; } + pcursor->Prev(); } return(total); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 51ed1103e..e96f0d975 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -437,7 +437,7 @@ void CTxMemPool::removeExpired(unsigned int nBlockHeight) for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { const CTransaction& tx = it->GetTx(); - tipindex = chainActive.Tip(); + tipindex = chainActive.LastTip(); if (IsExpiredTx(tx, nBlockHeight) || (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->nHeight+1,tipindex->GetMedianTimePast() + 777,0)) < 0) { transactionsToRemove.push_back(tx); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index cd3e30f3d..a8e15db99 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -51,3 +51,7 @@ void UnregisterAllValidationInterfaces() { void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) { g_signals.SyncTransaction(tx, pblock); } + +void EraseFromWallets(const uint256 &hash) { + g_signals.EraseTransaction(hash); +} diff --git a/src/validationinterface.h b/src/validationinterface.h index 1855dacd7..a1f111753 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -28,6 +28,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn); void UnregisterAllValidationInterfaces(); /** Push an updated transaction to all registered wallets */ void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL); +void EraseFromWallets(const uint256 &hash); class CValidationInterface { protected: diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 15caad846..c8dc7aa5b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -278,7 +278,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys if (!file.is_open()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); - int64_t nTimeBegin = chainActive.Tip()->GetBlockTime(); + int64_t nTimeBegin = chainActive.LastTip()->GetBlockTime(); bool fGood = true; @@ -364,7 +364,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys file.close(); pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI - CBlockIndex *pindex = chainActive.Tip(); + CBlockIndex *pindex = chainActive.LastTip(); while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200) pindex = pindex->pprev; @@ -509,8 +509,8 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) // produce output file << strprintf("# Wallet dump created by Komodo %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); - file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); - file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); + file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.LastTip()->GetBlockHash().ToString()); + file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.LastTip()->GetBlockTime())); file << "\n"; for (std::vector >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) { const CKeyID &keyid = it->second; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 22fe7fba1..084a4f752 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -44,6 +44,7 @@ using namespace libzcash; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern UniValue TxJoinSplitToJSON(const CTransaction& tx); +extern uint8_t ASSETCHAINS_PRIVATE; uint32_t komodo_segid32(char *coinaddr); int64_t nWalletUnlockTime; @@ -453,6 +454,9 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) + HelpExampleRpc("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.1, \"donation\", \"seans outpost\"") ); + if ( ASSETCHAINS_PRIVATE != 0 && AmountFromValue(params[1]) > 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address"); + LOCK2(cs_main, pwalletMain->cs_wallet); CBitcoinAddress address(params[0].get_str()); @@ -570,7 +574,7 @@ UniValue kvupdate(const UniValue& params, bool fHelp) valuesize = (int32_t)strlen(params[1].get_str().c_str()); } memcpy(keyvalue,key,keylen); - if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 ) + if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 ) { if ( (tmpflags & KOMODO_KVPROTECTED) != 0 ) { @@ -595,7 +599,7 @@ UniValue kvupdate(const UniValue& params, bool fHelp) // printf("%02x",((uint8_t *)&sig)[i]); //printf(" sig for keylen.%d + valuesize.%d\n",keylen,refvaluesize); ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - height = chainActive.Tip()->nHeight; + height = chainActive.LastTip()->nHeight; if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) ret.push_back(Pair("owner",refpubkey.GetHex())); ret.push_back(Pair("height", (int64_t)height)); @@ -667,7 +671,7 @@ UniValue paxdeposit(const UniValue& params, bool fHelp) int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN; std::string base = params[2].get_str(); std::string dest; - height = chainActive.Tip()->nHeight; + height = chainActive.LastTip()->nHeight; if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,(char *)base.c_str()) != 0 || available < fiatoshis ) { fprintf(stderr,"available %llu vs fiatoshis %llu\n",(long long)available,(long long)fiatoshis); @@ -1094,6 +1098,8 @@ UniValue movecmd(const UniValue& params, bool fHelp) "\nAs a json rpc call\n" + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"") ); + if ( ASSETCHAINS_PRIVATE != 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain"); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1173,6 +1179,8 @@ UniValue sendfrom(const UniValue& params, bool fHelp) "\nAs a json rpc call\n" + HelpExampleRpc("sendfrom", "\"tabby\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.01, 6, \"donation\", \"seans outpost\"") ); + if ( ASSETCHAINS_PRIVATE != 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain"); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1247,6 +1255,8 @@ UniValue sendmany(const UniValue& params, bool fHelp) "\nAs a json rpc call\n" + HelpExampleRpc("sendmany", "\"\", \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\", 6, \"testing\"") ); + if ( ASSETCHAINS_PRIVATE != 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain"); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -2703,13 +2713,13 @@ UniValue listunspent(const UniValue& params, bool fHelp) BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); CBlockIndex *tipindex,*pindex = it->second; uint64_t interest; uint32_t locktime; int32_t txheight; - if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 ) + if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 ) { interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight); //interest = komodo_interest(txheight,nValue,out.tx->nLockTime,tipindex->nTime); entry.push_back(Pair("interest",ValueFromAmount(interest))); } - //fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.Tip(),locktime,txheight,pindex->nHeight); + //fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.LastTip(),locktime,txheight,pindex->nHeight); } entry.push_back(Pair("confirmations",out.nDepth)); entry.push_back(Pair("spendable", out.fSpendable)); @@ -2736,7 +2746,7 @@ uint64_t komodo_interestsum() { BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); CBlockIndex *tipindex,*pindex = it->second; - if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 ) + if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 ) { interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight); //interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,tipindex->nTime); @@ -3762,7 +3772,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) string address = find_value(o, "address").get_str(); bool isZaddr = false; CBitcoinAddress taddr(address); - if (!taddr.IsValid()) { + if (!taddr.IsValid()) + { try { CZCPaymentAddress zaddr(address); zaddr.Get(); @@ -3771,6 +3782,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address ); } } + else if ( ASSETCHAINS_PRIVATE != 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain"); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address); @@ -4229,6 +4242,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); } } + else if ( ASSETCHAINS_PRIVATE != 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain"); // Convert fee from currency format to zatoshis CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE; @@ -4498,6 +4513,8 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp) int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); extern std::string NOTARY_PUBKEY; uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 hash,int32_t n,uint32_t blocktime,uint32_t prevtime,char *destaddr); +int8_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout); +int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33) { @@ -4575,10 +4592,96 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33) return(siglen); } +struct komodo_staking +{ + char address[64]; + uint256 txid; + arith_uint256 hashval; + uint64_t nValue; + uint32_t segid32,txtime; + int32_t vout; + CScript scriptPubKey; +}; + +struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) +{ + uint256 hash; uint32_t segid32; struct komodo_staking *kp; + segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); + if ( *numkp >= *maxkp ) + { + *maxkp += 1000; + array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); + } + kp = &array[(*numkp)++]; + memset(kp,0,sizeof(*kp)); + strcpy(kp->address,address); + kp->txid = txid; + kp->vout = vout; + kp->hashval = UintToArith256(hash); + kp->txtime = txtime; + kp->segid32 = segid32; + kp->nValue = nValue; + kp->scriptPubKey = pk; + return(array); +} + +arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uint32_t blocktime,int32_t iter,int32_t minage,int32_t segid,int32_t nHeight,uint32_t prevtime) +{ + int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval; + diff = (iter + blocktime - kp->txtime - minage); + if ( diff < 0 ) + diff = 60; + else if ( diff > 3600*24*30 ) + diff = 3600*24*30; + if ( iter > 0 ) + diff += segid*2; + coinage = ((uint64_t)kp->nValue/COIN * diff); + if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 ) + coinage *= ((blocktime+iter+segid*2) - (prevtime+60)); + coinage256 = arith_uint256(coinage+1); + hashval = ratio * (kp->hashval / coinage256); + if ( nHeight >= 900 && nHeight < 916 ) + hashval = (hashval / coinage256); + return(hashval); +} + +uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komodo_staking *kp,int32_t nHeight,uint32_t blocktime,uint32_t prevtime,int32_t minage,uint8_t *hashbuf) +{ + int32_t maxiters = 180; uint256 hash; + int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256; + komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout); + kp->hashval = UintToArith256(hash); + segid = ((nHeight + kp->segid32) & 0x3f); + hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime); + //for (int i=32; i>=0; i--) + // fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + //fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime); + if ( hashval <= bnTarget ) + { + for (iter=0; itertxtime+minage ) + continue; + hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime); + if ( hashval <= bnTarget ) + { + //fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid); + blocktime += iter; + blocktime += segid * 2; + return(blocktime); + } + } + } + return(0); +} + int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig) { - set setAddress; int32_t i,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 bnTarget; bool fNegative,fOverflow; + static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; + set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t besttime,eligible,eligible2,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + ratio = (mindiff / bnTarget); assert(pwalletMain != NULL); LOCK2(cs_main, pwalletMain->cs_wallet); *utxovaluep = 0; @@ -4586,60 +4689,108 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt memset(utxovoutp,0,sizeof(*utxovoutp)); memset(utxosig,0,72); pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); - BOOST_FOREACH(const COutput& out, vecOutputs) + if ( (tipindex= chainActive.Tip()) == 0 ) + return(0); + nHeight = tipindex->nHeight + 1; + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + 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); + if ( time(NULL) > lasttime+600 ) { - if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) + if ( array != 0 ) { - fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + BOOST_FOREACH(const COutput& out, vecOutputs) + { + if ( (tipindex= chainActive.Tip()) == 0 || tipindex->nHeight+1 > nHeight ) + { + fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); + return(0); + } + counter++; + if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) + { + //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); + continue; + } + CAmount nValue = out.tx->vout[out.i].nValue; + if ( nValue < COIN || !out.fSpendable ) + continue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + if ( ExtractDestination(pk,address) != 0 ) + { + if ( IsMine(*pwalletMain,address) == 0 ) + continue; + if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= mapBlockIndex[hashBlock]) != 0 ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); + } + } + } + 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); + } + for (i=winners=0; inHeight+1 > nHeight ) + { + fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); + return(0); + } + kp = &array[i]; + if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 ) continue; - } - if ( setAddress.size() ) + eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address); + //fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible); + if ( eligible > 0 ) { - CTxDestination address; - if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + besttime = m = 0; + if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) ) { - fprintf(stderr,"komodo_staked ExtractDestination error\n"); + while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) ) + { + besttime = eligible; + eligible--; + if ( eligible < (uint32_t)tipindex->nTime-63 ) + 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); + } + } + else + { + fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); continue; } - if (!setAddress.count(address)) + 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)) ) { - fprintf(stderr,"komodo_staked setAddress.count error\n"); - continue; + 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); } - } - CAmount nValue = out.tx->vout[out.i].nValue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; - //entry.push_back(Pair("generated", out.tx->IsCoinBase())); - CTxDestination address; - if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) - { - //entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); - //if (pwalletMain->mapAddressBook.count(address)) - // entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name)); - } - //BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *tipindex; - if ( (tipindex= chainActive.Tip()) != 0 ) - { - eligible = komodo_stake(0,bnTarget,(uint32_t)tipindex->nHeight+1,out.tx->GetHash(),out.i,0,(uint32_t)tipindex->nTime,(char *)CBitcoinAddress(address).ToString().c_str()); - if ( eligible > 0 ) - { - if ( eligible != komodo_stake(1,bnTarget,(uint32_t)tipindex->nHeight+1,out.tx->GetHash(),out.i,eligible,(uint32_t)tipindex->nTime,(char *)CBitcoinAddress(address).ToString().c_str()) ) - { - //fprintf(stderr,"tip.%d validation of winning blocktime failed %u -> eligible.%u\n",(uint32_t)tipindex->nHeight,*blocktimep,eligible); - } - else if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || nValue < *utxovaluep)) ) - { - earliest = eligible; - best_scriptPubKey = out.tx->vout[out.i].scriptPubKey; - *utxovaluep = (uint64_t)nValue; - decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str()); - *utxovoutp = out.i; - *txtimep = (uint32_t)out.tx->nLockTime; - //fprintf(stderr,"earliest.%u [%d] (%s) nValue %.8f locktime.%u\n",earliest,(int32_t)(earliest- *blocktimep),CBitcoinAddress(address).ToString().c_str(),(double)nValue/COIN,*txtimep); - } - } //else fprintf(stderr,"utxo not eligible\n"); - } //else fprintf(stderr,"no tipindex\n"); + } //else fprintf(stderr,"utxo not eligible\n"); + } //else fprintf(stderr,"no tipindex\n"); + if ( numkp < 10000 && array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; } if ( earliest != 0 ) { @@ -4671,7 +4822,8 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt //fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep)); *blocktimep = earliest; } - } else fprintf(stderr,"no earliest utxo for staking\n"); + } //else fprintf(stderr,"no earliest utxo for staking\n"); + //fprintf(stderr,"end scan of utxo for staking t.%u counter.%d numkp.%d winners.%d\n",(uint32_t)time(NULL),counter,numkp,winners); return(siglen); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 10bf93598..ce5630fb6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1819,7 +1819,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false); - double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip(), false); + double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip(), false); while (pindex) { if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) @@ -2112,7 +2112,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) // Don't rebroadcast if newer than nTime: if (wtx.nTimeReceived > nTime) continue; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + //if ( ASSETCHAINS_SYMBOL[0] == 0 ) { if ( wtx.nLockTime >= LOCKTIME_THRESHOLD && wtx.nLockTime < now-KOMODO_MAXMEMPOOLTIME ) { @@ -2299,20 +2299,20 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const if ( KOMODO_EXCHANGEWALLET == 0 ) { uint32_t locktime; int32_t txheight; CBlockIndex *tipindex; - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 ) { if ( pcoin->vout[i].nValue >= 10*COIN ) { - if ( (tipindex= chainActive.Tip()) != 0 ) + if ( (tipindex= chainActive.LastTip()) != 0 ) { komodo_accrued_interest(&txheight,&locktime,wtxid,i,0,pcoin->vout[i].nValue,(int32_t)tipindex->nHeight); interest = komodo_interestnew(txheight,pcoin->vout[i].nValue,locktime,tipindex->nTime); } else interest = 0; - //interest = komodo_interestnew(chainActive.Tip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.Tip()->nTime); + //interest = komodo_interestnew(chainActive.LastTip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.LastTip()->nTime); if ( interest != 0 ) { //printf("wallet nValueRet %.8f += interest %.8f ht.%d lock.%u/%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,txheight,locktime,pcoin->nLockTime,tipindex->nTime); - //fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.Tip()->nHeight+1,pcoin->nLockTime,chainActive.Tip()->nTime); + //fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.LastTip()->nHeight+1,pcoin->nLockTime,chainActive.LastTip()->nTime); //ptr = (uint64_t *)&pcoin->vout[i].nValue; //(*ptr) += interest; ptr = (uint64_t *)&pcoin->vout[i].interest; @@ -2687,7 +2687,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt int nextBlockHeight = chainActive.Height() + 1; CMutableTransaction txNew = CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); - txNew.nLockTime = (uint32_t)chainActive.Tip()->nTime + 1; // set to a time close to now + txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now // Activates after Overwinter network upgrade // Set nExpiryHeight to expiryDelta (default 20) blocks past current block height diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f77a55a04..0c6a90840 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -995,9 +995,9 @@ public: bool UpdateNullifierNoteMap(); void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); + void EraseFromWallet(const uint256 &hash); void SyncTransaction(const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); - void EraseFromWallet(const uint256 &hash); void WitnessNoteCommitment( std::vector commitments, std::vector>& witnesses,