Merge pull request #42 from jl777/dev

update dev
This commit is contained in:
ca333
2018-07-19 15:40:06 +02:00
committed by GitHub
41 changed files with 946 additions and 776 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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=<addr>
# Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6
#whitebind=<addr>
##############################################################
## 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=<addr>
# 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

View File

@@ -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 \

View File

@@ -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

View File

@@ -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 &

View File

@@ -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());

View File

@@ -11,6 +11,7 @@ using namespace std;
* CChain implementation
*/
void CChain::SetTip(CBlockIndex *pindex) {
lastTip = pindex;
if (pindex == NULL) {
vChain.clear();
return;

View File

@@ -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<CBlockIndex*> 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 {

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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,&notarizedheight,(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,&notarizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime());
if ( 0 && i > 0 )
{
for (k=0; k<len; k++)

View File

@@ -567,7 +567,7 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
#endif
hashBlock, true))
{
fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0);
}
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
@@ -580,6 +580,56 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
return(tx.nLockTime);
}
uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
{
CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0;
*valuep = 0;
if (!GetTransaction(hash, tx,
#ifndef KOMODO_ZCASH
Params().GetConsensus(),
#endif
hashBlock, true))
{
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0);
}
if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
txtime = pindex->nTime;
else txtime = tx.nLockTime;
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
if ( n < tx.vout.size() )
{
*valuep = tx.vout[n].nValue;
if (ExtractDestination(tx.vout[n].scriptPubKey, address))
strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
}
return(txtime);
}
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,&notarized_hash,&notarized_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<n; i++)
{
for (i=31; 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; i<n; i++)
{
CTransaction vintx,&tx = pblock->vtx[i];
zfunds += (tx.GetJoinSplitValueOut() - tx.GetJoinSplitValueIn());
if ( (m= tx.vin.size()) > 0 )
{
for (j=0; j<m; j++)
{
if ( i == 0 )
continue;
txid = tx.vin[j].prevout.hash;
vout = tx.vin[j].prevout.n;
if ( !GetTransaction(txid,vintx,hashBlock, false) || vout >= 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<m-1; j++)
{
if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 )
voutsum += tx.vout[j].nValue;
else printf("skip %.8f -> %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);
}

View File

@@ -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] )
{

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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","");

View File

@@ -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<CScriptCheck> 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<CTransaction> 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<CBlockIndex*, CBlockIndexWorkComparator>::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);

View File

@@ -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);
}

View File

@@ -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(&notaryid,chainActive.Tip()->nHeight,NOTARY_PUBKEY33,(uint32_t)chainActive.Tip()->GetBlockTime());
komodo_chosennotary(&notaryid,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)

View File

@@ -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 )
{

View File

@@ -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<JSDescription>::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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<boost::mutex> 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)
{

View File

@@ -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 <height>\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 {

View File

@@ -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);

View File

@@ -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 },

View File

@@ -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

View File

@@ -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 <fstream>
#include <boost/filesystem/operations.hpp>
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "key.h"
#include "alertkeys.h"
#include <iostream>
/*
* 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<typename T>
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<typename T>
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<unsigned char>(sMsg.begin(), sMsg.end());
// sign alert
std::vector<unsigned char> 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<unsigned char> vch = std::vector<unsigned char>(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<unsigned char> 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<std::string> read_lines(boost::filesystem::path filepath)
{
std::vector<std::string> result;
std::ifstream f(filepath.string().c_str());
std::string line;
while (std::getline(f,line))
result.push_back(line);
return result;
}
std::vector<CAlert> alerts;
};
BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
BOOST_AUTO_TEST_CASE(AlertApplies)
{
SetMockTime(11);
const std::vector<unsigned char>& 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<unsigned char>& 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<std::string> 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<unsigned char>& 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

View File

@@ -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<leveldb::Iterator> 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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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:

View File

@@ -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<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;

View File

@@ -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; iter<maxiters; iter++)
{
if ( blocktime+iter+segid*2 < kp->txtime+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<CBitcoinAddress> setAddress; int32_t i,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> 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<CBitcoinAddress> setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> 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; i<numkp; i++)
{
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);
}
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);
}

View File

@@ -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<uint256> 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<COutput>& 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<CRecipient>& 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

View File

@@ -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<uint256> commitments,
std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,