Merge branch 'master' into dave-dev

This commit is contained in:
Asher Dawes
2018-08-04 16:42:55 -07:00
23 changed files with 359 additions and 87 deletions

View File

@@ -4,7 +4,7 @@ stages:
- deploy - deploy
variables: variables:
VERSION: 0.3.10 VERSION: 0.3.11
AGAMA_ARTIFACTS_LINUX: linux64.tar.gz AGAMA_ARTIFACTS_LINUX: linux64.tar.gz
AGAMA_ARTIFACTS_MACOS: osx.tar.gz AGAMA_ARTIFACTS_MACOS: osx.tar.gz
AGAMA_ARTIFACTS_WINDOWS: win64.zip AGAMA_ARTIFACTS_WINDOWS: win64.zip

View File

@@ -1,4 +1,4 @@
First off you need Apple's Xcode (at least version 7, preferably 8.x) and the Xcode Command Line Tools: You will need Apple's Xcode (at least version 7, preferably 8.x) and the Xcode Command Line Tools:
https://itunes.apple.com/us/app/xcode/id497799835?mt=12 https://itunes.apple.com/us/app/xcode/id497799835?mt=12
@@ -6,7 +6,7 @@ And Homebrew:
http://brew.sh/ http://brew.sh/
then use the brewfile to install the necessary packages: Use the brewfile to install the necessary packages:
```shell ```shell
brew bundle brew bundle

View File

@@ -1,8 +1,10 @@
## VerusCoin version 0.3.10-beta ## VerusCoin version 0.3.12-beta
VerusCoin is a new, mineable and stakeable cryptocurrency. It is a live fork of Komodo that retains its Zcash lineage and improves it. VerusCoin will leverage the Komodo platform and dPoW notarization for enhanced security and cross-chain interoperability. We have added a variation of a zawy12, lwma difficulty algorithm, a new CPU-optimized hash algorithm and a new algorithm for fair proof of stake. We describe these changes and vision going forward in a [our Phase I white paper](http://185.25.51.16/papers/VerusPhaseI.pdf) and [our Vision](http://185.25.51.16/papers/VerusVision.pdf). VerusCoin is a new, mineable and stakeable cryptocurrency. It is a live fork of Komodo that retains its Zcash lineage and improves it. VerusCoin will leverage the Komodo platform and dPoW notarization for enhanced security and cross-chain interoperability. We have added a variation of a zawy12, lwma difficulty algorithm, a new CPU-optimized hash algorithm and a new algorithm for fair proof of stake. We describe these changes and vision going forward in a [our Phase I white paper](http://185.25.51.16/papers/VerusPhaseI.pdf) and [our Vision](http://185.25.51.16/papers/VerusVision.pdf).
- [VerusCoin web site https://veruscoin.io/ Wallets and CLI tools](https://veruscoin.io/) - [VerusCoin web site https://veruscoin.io/ Wallets and CLI tools](https://veruscoin.io/)
- [VerusCoin Explorer](https://explorer.veruscoin.io/) - [VerusCoin Explorer](https://explorer.veruscoin.io/)
Version 0.3.12-beta has portable mining working.
## Komodo with Bitcore ## Komodo with Bitcore
This version of Komodo contains Bitcore support for komodo and all its assetchains. This version of Komodo contains Bitcore support for komodo and all its assetchains.

View File

@@ -1,4 +1,4 @@
VerusCoin Command Line Tools v0.3.10-beta VerusCoin Command Line Tools v0.3.12-beta
Contents: Contents:
komodod - VerusCoin's enhanced Komodo daemon komodod - VerusCoin's enhanced Komodo daemon
komodo-cli - VerusCoin's Komodo command line utility komodo-cli - VerusCoin's Komodo command line utility

View File

@@ -1,4 +1,4 @@
VerusCoin Command Line Tools v0.3.9-beta VerusCoin Command Line Tools v0.3.12-beta
Contents: Contents:
komodod - VerusCoin's enhanced Komodo daemon. komodod - VerusCoin's enhanced Komodo daemon.
komodo-cli - VerusCoin's enhanced Komodo command line utility. komodo-cli - VerusCoin's enhanced Komodo command line utility.

View File

@@ -1,4 +1,4 @@
VerusCoin Command Line Tools v0.3.10-beta VerusCoin Command Line Tools v0.3.12-beta
Contents: Contents:
komodod.exe - VerusCoin's enhanced Komodo daemon komodod.exe - VerusCoin's enhanced Komodo daemon
komodo-cli.exe - VerusCoin's Komodo command line utility komodo-cli.exe - VerusCoin's Komodo command line utility

View File

@@ -191,6 +191,7 @@ BITCOIN_CORE_H = \
pow.h \ pow.h \
primitives/block.h \ primitives/block.h \
primitives/transaction.h \ primitives/transaction.h \
primitives/nonce.h \
protocol.h \ protocol.h \
pubkey.h \ pubkey.h \
random.h \ random.h \
@@ -270,6 +271,7 @@ libbitcoin_server_a_SOURCES = \
crypto/haraka.h \ crypto/haraka.h \
crypto/haraka_portable.h \ crypto/haraka_portable.h \
crypto/verus_hash.h \ crypto/verus_hash.h \
crypto/verus_hash.cpp \
deprecation.cpp \ deprecation.cpp \
httprpc.cpp \ httprpc.cpp \
httpserver.cpp \ httpserver.cpp \
@@ -409,12 +411,14 @@ libbitcoin_common_a_SOURCES = \
crypto/haraka.h \ crypto/haraka.h \
crypto/haraka_portable.h \ crypto/haraka_portable.h \
crypto/verus_hash.h \ crypto/verus_hash.h \
crypto/verus_hash.cpp \
hash.cpp \ hash.cpp \
key.cpp \ key.cpp \
keystore.cpp \ keystore.cpp \
netbase.cpp \ netbase.cpp \
primitives/block.cpp \ primitives/block.cpp \
primitives/transaction.cpp \ primitives/transaction.cpp \
primitives/nonce.cpp \
protocol.cpp \ protocol.cpp \
pubkey.cpp \ pubkey.cpp \
scheduler.cpp \ scheduler.cpp \
@@ -624,6 +628,7 @@ libzcashconsensus_la_SOURCES = \
crypto/sha512.cpp \ crypto/sha512.cpp \
hash.cpp \ hash.cpp \
primitives/transaction.cpp \ primitives/transaction.cpp \
primitives/nonce.cpp \
pubkey.cpp \ pubkey.cpp \
script/zcashconsensus.cpp \ script/zcashconsensus.cpp \
script/interpreter.cpp \ script/interpreter.cpp \

View File

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

View File

@@ -424,6 +424,7 @@ public:
class CChain { class CChain {
private: private:
std::vector<CBlockIndex*> vChain; std::vector<CBlockIndex*> vChain;
CBlockIndex *lastTip;
public: public:
/** Returns the index entry for the genesis block of this chain, or NULL if none. */ /** Returns the index entry for the genesis block of this chain, or NULL if none. */
@@ -436,6 +437,11 @@ public:
return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL; 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. */ /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
CBlockIndex *operator[](int nHeight) const { CBlockIndex *operator[](int nHeight) const {
if (nHeight < 0 || nHeight >= (int)vChain.size()) if (nHeight < 0 || nHeight >= (int)vChain.size())

View File

@@ -253,7 +253,16 @@ bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
uint256 CCoinsViewCache::GetBestBlock() const { uint256 CCoinsViewCache::GetBestBlock() const {
if (hashBlock.IsNull()) if (hashBlock.IsNull())
hashBlock = base->GetBestBlock(); {
if (base)
{
hashBlock = base->GetBestBlock();
}
else
{
hashBlock = uint256();
}
}
return hashBlock; return hashBlock;
} }

View File

@@ -27,7 +27,7 @@ class CVerusHash
static void init(); static void init();
CVerusHash() {} CVerusHash() { }
CVerusHash &Write(const unsigned char *data, size_t len); CVerusHash &Write(const unsigned char *data, size_t len);
@@ -37,6 +37,7 @@ class CVerusHash
result = buf2; result = buf2;
curPos = 0; curPos = 0;
std::fill(buf1, buf1 + sizeof(buf1), 0); std::fill(buf1, buf1 + sizeof(buf1), 0);
return *this;
} }
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }

View File

@@ -203,7 +203,8 @@ public:
int nType; int nType;
int nVersion; int nVersion;
CVerusHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {} CVerusHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() { }
void Reset() { state.Reset(); }
CVerusHashWriter& write(const char *pch, size_t size) { CVerusHashWriter& write(const char *pch, size_t size) {
state.Write((const unsigned char*)pch, size); state.Write((const unsigned char*)pch, size);
@@ -239,6 +240,7 @@ public:
int nVersion; int nVersion;
CVerusHashV2Writer(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {} CVerusHashV2Writer(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {}
void Reset() { state.Reset(); }
CVerusHashV2Writer& write(const char *pch, size_t size) { CVerusHashV2Writer& write(const char *pch, size_t size) {
state.Write((const unsigned char*)pch, size); state.Write((const unsigned char*)pch, size);

View File

@@ -1258,7 +1258,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
return(isPoS); return(isPoS);
} }
// if slow flag is 1, this does a slower check that checks the target with consensus, otherwise quick, insecure check for internal integrity // for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes
bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
{ {
CBlockIndex *pastBlockIndex; CBlockIndex *pastBlockIndex;
@@ -1271,15 +1271,20 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
CTransaction tx; CTransaction tx;
if (!pblock->IsVerusPOSBlock()) if (!pblock->IsVerusPOSBlock())
{
printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height);
pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget());
printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str());
return false; return false;
}
char voutaddr[64], destaddr[64], cbaddr[64]; char voutaddr[64], destaddr[64], cbaddr[64];
target.SetCompact(pblock->GetVerusPOSTarget());
txn_count = pblock->vtx.size(); txn_count = pblock->vtx.size();
if ( txn_count > 1 ) if ( txn_count > 1 )
{ {
target.SetCompact(pblock->GetVerusPOSTarget());
txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n; voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n;
@@ -1291,20 +1296,28 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
{ {
fprintf(stderr,"ERROR: invalid PoS block %s - no transaction\n",blkHash.ToString().c_str()); fprintf(stderr,"ERROR: invalid PoS block %s - no transaction\n",blkHash.ToString().c_str());
} }
else if (!(pastBlockIndex = komodo_chainactive(height - COINBASE_MATURITY))) else if (!(pastBlockIndex = komodo_chainactive(height - 100)))
{ {
fprintf(stderr,"ERROR: invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); fprintf(stderr,"WARNING: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str());
} }
else else
{ {
hash = UintToArith256(tx.GetVerusPOSHash(voutNum, height, pastBlockIndex->GetBlockHash())); CBlockHeader bh = pastBlockIndex->GetBlockHeader();
uint256 pastHash = bh.GetVerusEntropyHash(height - 100);
// if height is over when Nonce is required to be the new format, we check that the new format is correct
// if over when we have the new POS hash function, we validate that as well
// they are 100 blocks apart
CPOSNonce nonce = pblock->nNonce;
hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash));
if (hash <= target) if (hash <= target)
{ {
if ((mapBlockIndex.count(blkHash) == 0) || if ((mapBlockIndex.count(blkHash) == 0) ||
!(pastBlockIndex = mapBlockIndex[blkHash]) || !(pastBlockIndex = mapBlockIndex[blkHash]) ||
(height - pastBlockIndex->nHeight) < VERUS_MIN_STAKEAGE) (height - pastBlockIndex->nHeight) < VERUS_MIN_STAKEAGE)
{ {
fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str()); fprintf(stderr,"ERROR: invalid PoS block %s - stake transaction too new\n",blkHash.ToString().c_str());
} }
else if ( slowflag != 0 ) else if ( slowflag != 0 )
{ {
@@ -1317,13 +1330,24 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
else else
{ {
arith_uint256 cTarget; arith_uint256 cTarget;
cTarget.SetCompact(lwmaGetNextPOSRequired(previndex, Params().GetConsensus())); uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus());
cTarget.SetCompact(nBits);
if (cTarget != target) bool nonceOK = true;
if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum))
{ {
fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str());
nonceOK = false;
} }
else if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && else
{
if (cTarget != target)
{
fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str());
nonceOK = false;
}
}
if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) &&
ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) && ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) &&
CScriptExt::ExtractVoutDestination(pblock->vtx[0], 0, cbaddress) ) CScriptExt::ExtractVoutDestination(pblock->vtx[0], 0, cbaddress) )
{ {

View File

@@ -3149,7 +3149,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
list<CTransaction> removed; list<CTransaction> removed;
CValidationState stateDummy; CValidationState stateDummy;
// don't keep staking or invalid transactions // don't keep staking or invalid transactions
if (tx.IsCoinBase() || (block.IsVerusPOSBlock() && (i == (block.vtx.size() - 1))) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && block.IsVerusPOSBlock()) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
{ {
mempool.remove(tx, removed, true); mempool.remove(tx, removed, true);
} }
@@ -3171,7 +3171,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
for (int i = 0; i < block.vtx.size(); i++) for (int i = 0; i < block.vtx.size(); i++)
{ {
CTransaction &tx = block.vtx[i]; CTransaction &tx = block.vtx[i];
if (block.IsVerusPOSBlock() && (i == (block.vtx.size() - 1))) if ((i == (block.vtx.size() - 1) && block.IsVerusPOSBlock()))
{ {
EraseFromWallets(tx.GetHash()); EraseFromWallets(tx.GetHash());
} }

View File

@@ -128,7 +128,7 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
int64_t komodo_block_unlocktime(uint32_t nHeight); int64_t komodo_block_unlocktime(uint32_t nHeight);
uint64_t komodo_commission(const CBlock *block); uint64_t komodo_commission(const CBlock *block);
int32_t komodo_staked(CPubKey &pubkey, CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig); int32_t komodo_staked(CPubKey &pubkey, CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig);
int32_t verus_staked(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig); int32_t verus_staked(CBlock *pBlock, CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig);
int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, bool isStake) CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, bool isStake)
@@ -370,7 +370,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, bool isStake)
//fprintf(stderr,"dont have inputs\n"); //fprintf(stderr,"dont have inputs\n");
continue; 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); nTxSigOps += GetP2SHSigOpCount(tx, view);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
@@ -462,9 +462,9 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, bool isStake)
{ {
uint32_t nBitsPOS; uint32_t nBitsPOS;
arith_uint256 posHash; arith_uint256 posHash;
siglen = verus_staked(key, txStaked, nBitsPOS, posHash, utxosig);
siglen = verus_staked(pblock, key, txStaked, nBitsPOS, posHash, utxosig);
blocktime = GetAdjustedTime(); blocktime = GetAdjustedTime();
pblock->SetVerusPOSTarget(nBitsPOS);
// change the scriptPubKeyIn to the same output script exactly as the staking transaction // change the scriptPubKeyIn to the same output script exactly as the staking transaction
if (siglen > 0) if (siglen > 0)
@@ -485,7 +485,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, bool isStake)
pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
nFees += txfees; nFees += txfees;
pblock->nTime = blocktime; pblock->nTime = blocktime;
//printf("PoS ht.%d t%u\n",(int32_t)chainActive.Tip()->nHeight+1,blocktime); //printf("PoS ht.%d t%u\n",(int32_t)chainActive.LastTip()->nHeight+1,blocktime);
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
} }
@@ -723,11 +723,11 @@ static bool ProcessBlockFound(CBlock* pblock)
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
{ {
LogPrintf("%s\n", pblock->ToString()); LogPrintf("%s\n", pblock->ToString());
LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1);
// Found a solution // Found a solution
{ {
LOCK(cs_main); LOCK(cs_main);
LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1);
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
{ {
uint256 hash; int32_t i; uint256 hash; int32_t i;
@@ -763,7 +763,7 @@ static bool ProcessBlockFound(CBlock* pblock)
// Process this block the same as if we had received it from another node // Process this block the same as if we had received it from another node
CValidationState state; 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"); return error("KomodoMiner: ProcessNewBlock, block not accepted");
TrackMinedBlock(pblock->GetHash()); TrackMinedBlock(pblock->GetHash());
@@ -804,6 +804,18 @@ int32_t waitForPeers(const CChainParams &chainparams)
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
CBlockIndex *get_chainactive(int32_t height)
{
if ( chainActive.Tip() != 0 )
{
if ( height <= chainActive.Tip()->nHeight )
return(chainActive[height]);
// else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight);
}
//fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height);
return(0);
}
/* /*
* A separate thread to stake, while the miner threads mine. * A separate thread to stake, while the miner threads mine.
*/ */
@@ -852,9 +864,10 @@ void static VerusStaker(CWallet *pwallet)
sleep(5); sleep(5);
{ {
LOCK(cs_main);
printf("Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); printf("Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL);
//fprintf(stderr,"Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL);
} }
//fprintf(stderr,"Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL);
miningTimer.start(); miningTimer.start();
@@ -867,7 +880,7 @@ void static VerusStaker(CWallet *pwallet)
// Create new block // Create new block
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.LastTip();
if ( Mining_height != pindexPrev->nHeight+1 ) if ( Mining_height != pindexPrev->nHeight+1 )
{ {
Mining_height = pindexPrev->nHeight+1; Mining_height = pindexPrev->nHeight+1;
@@ -885,8 +898,8 @@ void static VerusStaker(CWallet *pwallet)
if ( ptr == 0 ) if ( ptr == 0 )
{ {
// wait to try another staking block until after the tip moves again // wait to try another staking block until after the tip moves again
while ( chainActive.Tip() == pindexPrev ) while ( chainActive.LastTip() == pindexPrev )
sleep(5); sleep(1);
continue; continue;
} }
@@ -932,9 +945,9 @@ void static VerusStaker(CWallet *pwallet)
continue; continue;
} }
if ( pindexPrev != chainActive.Tip() ) if ( pindexPrev != chainActive.LastTip() )
{ {
printf("Block %d added to chain\n", chainActive.Tip()->nHeight); printf("Block %d added to chain\n", chainActive.LastTip()->nHeight);
MilliSleep(250); MilliSleep(250);
continue; continue;
} }
@@ -958,7 +971,9 @@ void static VerusStaker(CWallet *pwallet)
printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL); printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
arith_uint256 post; arith_uint256 post;
post.SetCompact(pblock->GetVerusPOSTarget()); post.SetCompact(pblock->GetVerusPOSTarget());
printf(" hash: %s \ntarget: %s\n", pblock->vtx[pblock->vtx.size()-1].GetVerusPOSHash(0, Mining_height, pindexPrev->GetBlockHash()).GetHex().c_str(), ArithToUint256(post).GetHex().c_str()); pindexPrev = get_chainactive(Mining_height - 100);
printf(" hash: %s \ntarget: %s\n",
CTransaction::_GetVerusPOSHash(&(pblock->nNonce), pblock->vtx[pblock->vtx.size()-1].vin[0].prevout.hash, 0, Mining_height, pindexPrev->GetBlockHeader().GetVerusEntropyHash(Mining_height - 100), pblock->vtx[pblock->vtx.size()-1].vout[0].nValue).GetHex().c_str(), ArithToUint256(post).GetHex().c_str());
if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE) if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
printf("- timelocked until block %i\n", unlockTime); printf("- timelocked until block %i\n", unlockTime);
else else
@@ -1024,9 +1039,9 @@ void static BitcoinMiner_noeq()
waitForPeers(chainparams); waitForPeers(chainparams);
CBlockIndex *pindexPrev, *pindexCur; CBlockIndex *pindexPrev, *pindexCur;
do { do {
pindexPrev = chainActive.Tip(); pindexPrev = chainActive.LastTip();
MilliSleep(5000 + rand() % 5000); MilliSleep(5000 + rand() % 5000);
pindexCur = chainActive.Tip(); pindexCur = chainActive.LastTip();
} while (pindexPrev != pindexCur); } while (pindexPrev != pindexCur);
// this will not stop printing more than once in all cases, but it will allow us to print in all cases // this will not stop printing more than once in all cases, but it will allow us to print in all cases
@@ -1042,16 +1057,16 @@ void static BitcoinMiner_noeq()
miningTimer.stop(); miningTimer.stop();
waitForPeers(chainparams); waitForPeers(chainparams);
pindexPrev = chainActive.Tip(); pindexPrev = chainActive.LastTip();
sleep(1); sleep(1);
// prevent forking on startup before the diff algorithm kicks in // prevent forking on startup before the diff algorithm kicks in
if (pindexPrev->nHeight < 50 || pindexPrev != chainActive.Tip()) if (pindexPrev->nHeight < 50 || pindexPrev != chainActive.LastTip())
{ {
do { do {
pindexPrev = chainActive.Tip(); pindexPrev = chainActive.LastTip();
MilliSleep(5000 + rand() % 5000); MilliSleep(5000 + rand() % 5000);
} while (pindexPrev != chainActive.Tip()); } while (pindexPrev != chainActive.LastTip());
} }
// Create new block // Create new block
@@ -1125,11 +1140,11 @@ void static BitcoinMiner_noeq()
Mining_start = 0; Mining_start = 0;
if ( pindexPrev != chainActive.Tip() ) if ( pindexPrev != chainActive.LastTip() )
{ {
if (lastChainTipPrinted != chainActive.Tip()) if (lastChainTipPrinted != chainActive.LastTip())
{ {
lastChainTipPrinted = chainActive.Tip(); lastChainTipPrinted = chainActive.LastTip();
printf("Block %d added to chain\n", lastChainTipPrinted->nHeight); printf("Block %d added to chain\n", lastChainTipPrinted->nHeight);
} }
MilliSleep(250); MilliSleep(250);
@@ -1200,11 +1215,11 @@ void static BitcoinMiner_noeq()
// check periodically if we're stale // check periodically if we're stale
if (!--hashesToGo) if (!--hashesToGo)
{ {
if ( pindexPrev != chainActive.Tip() ) if ( pindexPrev != chainActive.LastTip() )
{ {
if (lastChainTipPrinted != chainActive.Tip()) if (lastChainTipPrinted != chainActive.LastTip())
{ {
lastChainTipPrinted = chainActive.Tip(); lastChainTipPrinted = chainActive.LastTip();
printf("Block %d added to chain\n", lastChainTipPrinted->nHeight); printf("Block %d added to chain\n", lastChainTipPrinted->nHeight);
} }
break; break;
@@ -1236,11 +1251,11 @@ void static BitcoinMiner_noeq()
break; break;
} }
if ( pindexPrev != chainActive.Tip() ) if ( pindexPrev != chainActive.LastTip() )
{ {
if (lastChainTipPrinted != chainActive.Tip()) if (lastChainTipPrinted != chainActive.LastTip())
{ {
lastChainTipPrinted = chainActive.Tip(); lastChainTipPrinted = chainActive.LastTip();
printf("Block %d added to chain\n", lastChainTipPrinted->nHeight); printf("Block %d added to chain\n", lastChainTipPrinted->nHeight);
} }
break; break;

View File

@@ -10,6 +10,8 @@
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "crypto/common.h" #include "crypto/common.h"
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
// default hash algorithm for block // default hash algorithm for block
uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash; uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash;
@@ -43,6 +45,48 @@ void CBlockHeader::SetVerusHash()
CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash; CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash;
} }
// returns false if unable to fast calculate the VerusPOSHash from the header. it can still be calculated from the block
// in that case. the only difference between this and the POS hash for the contest is that it is not divided by the value out
// this is used as a source of entropy
bool CBlockHeader::GetRawVerusPOSHash(uint256 &value, int32_t nHeight) const
{
// if below the required height or no storage space in the solution, we can't get
// a cached txid value to calculate the POSHash from the header
if (!(CPOSNonce::NewNonceActive(nHeight) && IsVerusPOSBlock()))
return false;
// if we can calculate, this assumes the protocol that the POSHash calculation is:
// hashWriter << ASSETCHAINS_MAGIC;
// hashWriter << nNonce; (nNonce is:
// (high 128 bits == low 128 bits of verus hash of low 128 bits of nonce)
// (low 32 bits == compact PoS difficult)
// (mid 96 bits == low 96 bits of HASH(pastHash, txid, voutnum)
// pastHash is hash of height - 100, either PoW hash of block or PoS hash, if new PoS
// )
// hashWriter << height;
// return hashWriter.GetHash();
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hashWriter << ASSETCHAINS_MAGIC;
hashWriter << nNonce;
hashWriter << nHeight;
value = hashWriter.GetHash();
return true;
}
// depending on the height of the block and its type, this returns the POS hash or the POW hash
uint256 CBlockHeader::GetVerusEntropyHash(int32_t height) const
{
uint256 retVal;
// if we qualify as PoW, use PoW hash, regardless of PoS state
if (GetRawVerusPOSHash(retVal, height))
{
// POS hash
return retVal;
}
return GetHash();
}
uint256 CBlock::BuildMerkleTree(bool* fMutated) const uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{ {
/* WARNING! If you're reading this because you're learning about crypto /* WARNING! If you're reading this because you're learning about crypto

View File

@@ -7,6 +7,7 @@
#define BITCOIN_PRIMITIVES_BLOCK_H #define BITCOIN_PRIMITIVES_BLOCK_H
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "primitives/nonce.h"
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
#include "arith_uint256.h" #include "arith_uint256.h"
@@ -33,7 +34,7 @@ public:
uint256 hashReserved; uint256 hashReserved;
uint32_t nTime; uint32_t nTime;
uint32_t nBits; uint32_t nBits;
uint256 nNonce; CPOSNonce nNonce;
std::vector<unsigned char> nSolution; std::vector<unsigned char> nSolution;
CBlockHeader() CBlockHeader()
@@ -84,6 +85,9 @@ public:
uint256 GetVerusHash() const; uint256 GetVerusHash() const;
static void SetVerusHash(); static void SetVerusHash();
bool GetRawVerusPOSHash(uint256 &value, int32_t nHeight) const;
uint256 GetVerusEntropyHash(int32_t nHeight) const;
uint256 GetVerusV2Hash() const; uint256 GetVerusV2Hash() const;
int64_t GetBlockTime() const int64_t GetBlockTime() const
@@ -91,7 +95,7 @@ public:
return (int64_t)nTime; return (int64_t)nTime;
} }
int32_t GetVerusPOSTarget() const uint32_t GetVerusPOSTarget() const
{ {
uint32_t nBits = 0; uint32_t nBits = 0;
@@ -105,26 +109,25 @@ public:
bool IsVerusPOSBlock() const bool IsVerusPOSBlock() const
{ {
arith_uint256 arNonce = UintToArith256(nNonce); return nNonce.IsPOSNonce();
arith_uint256 tmpNonce = ((arNonce << 128) >> 128);
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hashWriter << ArithToUint256(tmpNonce);
return (nNonce == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce));
} }
void SetVerusPOSTarget(int32_t nBits) void SetVerusPOSTarget(uint32_t nBits)
{ {
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
uint256 hash;
arith_uint256 tmpNonce;
arith_uint256 arNonce = UintToArith256(nNonce); arith_uint256 arNonce = UintToArith256(nNonce);
arNonce = ((arNonce >> 32) << 32) | nBits;
tmpNonce = ((arNonce << 128) >> 128); // printf("before svpt: %s\n", ArithToUint256(arNonce).GetHex().c_str());
hashWriter << ArithToUint256(tmpNonce);
nNonce = ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce); arNonce = (arNonce & CPOSNonce::entropyMask) | nBits;
// printf("after clear: %s\n", ArithToUint256(arNonce).GetHex().c_str());
hashWriter << ArithToUint256(arNonce);
nNonce = CPOSNonce(ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce));
// printf(" after svpt: %s\n", nNonce.GetHex().c_str());
} }
}; };

75
src/primitives/nonce.cpp Normal file
View File

@@ -0,0 +1,75 @@
// Copyright (c) 2018 Michael Toutonghi
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "hash.h"
#include "nonce.h"
#include <cstring>
extern char ASSETCHAINS_SYMBOL[65];
arith_uint256 CPOSNonce::entropyMask = UintToArith256(uint256S("00000000000000000000000000000000ffffffffffffffffffffffff00000000"));
arith_uint256 CPOSNonce::posDiffMask = UintToArith256(uint256S("00000000000000000000000000000000000000000000000000000000ffffffff"));
bool CPOSNonce::NewPOSActive(int32_t height)
{
if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) && (height < (96480 + 100)))
return false;
else if ((strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0) && (height < (1000 + 100)))
return false;
else
return true;
}
bool CPOSNonce::NewNonceActive(int32_t height)
{
if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) && (height < 96480))
return false;
else if ((strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0) && (height < 1000))
return false;
else
return true;
}
void CPOSNonce::SetPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum)
{
// get low 96 bits of past hash and put it in top 96 bits of low 128 bits of nonce
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
// first hash the pastHash, txid, and voutNum, to create a combined 96 bits, which will be used in the nonce
hashWriter << pastHash;
hashWriter << txid;
hashWriter << voutNum;
arith_uint256 arNonce = (UintToArith256(*this) & posDiffMask) |
(UintToArith256(hashWriter.GetHash()) & entropyMask);
// printf("before %s\n", ArithToUint256(arNonce).GetHex().c_str());
hashWriter.Reset();
hashWriter << ArithToUint256(arNonce);
*this = CPOSNonce(ArithToUint256((UintToArith256(hashWriter.GetHash()) << 128) | arNonce));
// printf("after %s\n", this->GetHex().c_str());
}
bool CPOSNonce::CheckPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum)
{
// get low 96 bits of past hash and put it in top 96 bits of low 128 bits of nonce
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
// first hash the pastHash, txid, and voutNum, to create a combined 96 bits, which will be used in the nonce
hashWriter << pastHash;
hashWriter << txid;
hashWriter << voutNum;
arith_uint256 arNonce = (UintToArith256(*this) & posDiffMask) |
(UintToArith256(hashWriter.GetHash()) & entropyMask);
hashWriter.Reset();
hashWriter << ArithToUint256(arNonce);
return UintToArith256(*this) == (UintToArith256(hashWriter.GetHash()) << 128 | arNonce);
}

64
src/primitives/nonce.h Normal file
View File

@@ -0,0 +1,64 @@
// Copyright (c) 2018 Michael Toutonghi
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_PRIMITIVES_NONCE_H
#define BITCOIN_PRIMITIVES_NONCE_H
#include "serialize.h"
#include "uint256.h"
#include "arith_uint256.h"
/** For POS blocks, the nNonce of a block header holds the entropy source for the POS contest
* in the latest VerusHash protocol
* */
class CPOSNonce : public uint256
{
public:
static bool NewPOSActive(int32_t height);
static bool NewNonceActive(int32_t height);
static arith_uint256 entropyMask;
static arith_uint256 posDiffMask;
CPOSNonce() : uint256() { }
CPOSNonce(const base_blob<256> &b) : uint256(b) { }
CPOSNonce(const std::vector<unsigned char> &vch) : uint256(vch) { }
int32_t GetPOSTarget() const
{
uint32_t nBits = 0;
for (const unsigned char *p = begin() + 3; p >= begin(); p--)
{
nBits <<= 8;
nBits += *p;
}
return nBits;
}
bool IsPOSNonce() const
{
arith_uint256 arNonce = UintToArith256(*this);
arith_uint256 tmpNonce = ((arNonce << 128) >> 128);
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hashWriter << ArithToUint256(tmpNonce);
return (*this == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce));
}
void SetPOSTarget(uint32_t nBits)
{
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
arith_uint256 arNonce = (UintToArith256(*this) & entropyMask) | nBits;
hashWriter << ArithToUint256(arNonce);
(uint256 &)(*this) = ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce);
}
void SetPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum);
bool CheckPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum);
};
#endif // BITCOIN_PRIMITIVES_NONCE_H

View File

@@ -14,6 +14,7 @@
#include "arith_uint256.h" #include "arith_uint256.h"
#include "consensus/consensus.h" #include "consensus/consensus.h"
#include "hash.h" #include "hash.h"
#include "nonce.h"
#ifndef __APPLE__ #ifndef __APPLE__
#include <stdint.h> #include <stdint.h>
@@ -474,25 +475,39 @@ public:
} }
// verus hash will be the same for a given txid, output number, block height, and blockhash of 100 blocks past // verus hash will be the same for a given txid, output number, block height, and blockhash of 100 blocks past
static uint256 _GetVerusPOSHash(const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value) static uint256 _GetVerusPOSHash(CPOSNonce *pNonce, const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value)
{ {
pNonce->SetPOSEntropy(pastHash, txid, voutNum);
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hashWriter << ASSETCHAINS_MAGIC; hashWriter << ASSETCHAINS_MAGIC;
hashWriter << pastHash;
hashWriter << height; // we only use the new style of POS hash after changeover and 100 blocks of enforced proper nonce updating
hashWriter << txid; if (CPOSNonce::NewPOSActive(height))
hashWriter << voutNum; {
return hashWriter.GetHash(); hashWriter << *pNonce;
hashWriter << height;
return ArithToUint256(UintToArith256(hashWriter.GetHash()) / value);
}
else
{
hashWriter << pastHash;
hashWriter << height;
hashWriter << txid;
hashWriter << voutNum;
return ArithToUint256(UintToArith256(hashWriter.GetHash()) / value);
}
} }
uint256 GetVerusPOSHash(int32_t voutNum, int32_t height, const uint256 &pastHash) const // Nonce is modified to include the transaction information
uint256 GetVerusPOSHash(CPOSNonce *pNonce, int32_t voutNum, int32_t height, const uint256 &pastHash) const
{ {
uint256 txid = GetHash(); uint256 txid = GetHash();
if (voutNum >= vout.size()) if (voutNum >= vout.size())
return uint256S("ff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); return uint256S("ff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
return ArithToUint256(UintToArith256(_GetVerusPOSHash(txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue)) / vout[voutNum].nValue); return _GetVerusPOSHash(pNonce, txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue);
} }
std::string ToString() const; std::string ToString() const;

View File

@@ -4667,7 +4667,7 @@ int32_t komodo_staked(CPubKey &pubkey, CMutableTransaction &txNew,uint32_t nBits
return(siglen); return(siglen);
} }
int32_t verus_staked(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig) int32_t verus_staked(CBlock *pBlock, CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig)
{ {
return pwalletMain->VerusStakeTransaction(txNew, nBits, hashResult, utxosig); return pwalletMain->VerusStakeTransaction(pBlock, txNew, nBits, hashResult, utxosig);
} }

View File

@@ -998,8 +998,9 @@ CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries,
// UTXO with the smallest coin age if there is more than one, as larger coin age will win more often and is worth saving // UTXO with the smallest coin age if there is more than one, as larger coin age will win more often and is worth saving
// each attempt consists of taking a VerusHash of the following values: // each attempt consists of taking a VerusHash of the following values:
// ASSETCHAINS_MAGIC, nHeight, txid, voutNum // ASSETCHAINS_MAGIC, nHeight, txid, voutNum
bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, const arith_uint256 &target) const bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const
{ {
arith_uint256 target;
arith_uint256 curHash; arith_uint256 curHash;
vector<COutput> vecOutputs; vector<COutput> vecOutputs;
COutput *pwinner = NULL; COutput *pwinner = NULL;
@@ -1007,35 +1008,41 @@ bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &st
txnouttype whichType; txnouttype whichType;
std:vector<std::vector<unsigned char>> vSolutions; std:vector<std::vector<unsigned char>> vSolutions;
pBlock->nNonce.SetPOSTarget(bnTarget);
target.SetCompact(bnTarget);
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false); pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
if (pastBlockIndex = komodo_chainactive(nHeight - COINBASE_MATURITY)) if (pastBlockIndex = komodo_chainactive(nHeight - 100))
{ {
uint256 pastHash = pastBlockIndex->GetBlockHash(); CBlockHeader bh = pastBlockIndex->GetBlockHeader();
uint256 pastHash = bh.GetVerusEntropyHash(nHeight - 100);
CPOSNonce curNonce;
BOOST_FOREACH(COutput &txout, vecOutputs) BOOST_FOREACH(COutput &txout, vecOutputs)
{ {
if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE)) if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(&(pBlock->nNonce), txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE))
{ {
// get the smallest winner // get the smallest winner
if (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) && if (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) &&
(!pwinner || pwinner->tx->vout[pwinner->i].nValue > txout.tx->vout[txout.i].nValue)) (!pwinner || pwinner->tx->vout[pwinner->i].nValue > txout.tx->vout[txout.i].nValue))
pwinner = &txout; pwinner = &txout;
curNonce = pBlock->nNonce;
} }
} }
if (pwinner) if (pwinner)
{ {
stakeSource = *(pwinner->tx); stakeSource = *(pwinner->tx);
voutNum = pwinner->i; voutNum = pwinner->i;
pBlock->nNonce = curNonce;
return true; return true;
} }
} }
return false; return false;
} }
int32_t CWallet::VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const
{ {
arith_uint256 target;
CTransaction stakeSource; CTransaction stakeSource;
int32_t voutNum, siglen = 0; int32_t voutNum, siglen = 0;
int64_t nValue; int64_t nValue;
@@ -1048,12 +1055,11 @@ int32_t CWallet::VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnT
tipindex = chainActive.Tip(); tipindex = chainActive.Tip();
} }
bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus()); bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus());
target.SetCompact(bnTarget);
if (!VerusSelectStakeOutput(hashResult, stakeSource, voutNum, tipindex->nHeight + 1, target) || if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, tipindex->nHeight + 1, bnTarget) ||
!Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions)) !Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions))
{ {
LogPrintf("No eligible staking transaction found\n"); LogPrintf("Searched for eligible staking transactions, no winners found\n");
return 0; return 0;
} }

View File

@@ -1149,8 +1149,8 @@ public:
bool ignoreUnspendable=true); bool ignoreUnspendable=true);
// staking functions // staking functions
bool VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, const arith_uint256 &target) const; bool VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const;
int32_t VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const; int32_t VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const;
}; };
/** A key allocated from the key pool. */ /** A key allocated from the key pool. */