Browse Source

Delete Verus junk, which breaks ARMv8/aarch64 builds

pull/43/head
Duke Leto 5 years ago
parent
commit
f39cd2a473
  1. 5
      DEVELOPING.md
  2. 43
      src/Makefile.am
  3. 11
      src/chain.h
  4. 91
      src/hash.h
  5. 19
      src/init.cpp
  6. 176
      src/komodo_bitcoind.h
  7. 51
      src/komodo_utils.h
  8. 2
      src/main.cpp
  9. 490
      src/miner.cpp
  10. 8
      src/pow.cpp
  11. 84
      src/primitives/block.cpp
  12. 48
      src/primitives/block.h
  13. 63
      src/primitives/nonce.cpp
  14. 52
      src/primitives/nonce.h
  15. 36
      src/primitives/transaction.h
  16. 2
      src/rpc/blockchain.cpp
  17. 6
      src/wallet/rpcwallet.cpp
  18. 114
      src/wallet/wallet.cpp
  19. 3
      src/wallet/wallet.h

5
DEVELOPING.md

@ -29,6 +29,11 @@ When in doubt, if you run into a compile error, especially if it mentions
`OCTET_STRING`, run `build.sh` again. Running `make clean` before switching
branches can often prevent those problems.
```
cryptoconditions/src/asn/SimpleSha256Condition.h:14:10: fatal error: OCTET_STRING.h: No such file or directory
```
## Partial compiles
At any point, you can modify hush source code and then use `make` or `build.sh`

43
src/Makefile.am

@ -46,8 +46,6 @@ LIBBITCOIN_COMMON=libbitcoin_common.a
LIBBITCOIN_CLI=libbitcoin_cli.a
LIBBITCOIN_UTIL=libbitcoin_util.a
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
LIBVERUS_CRYPTO=crypto/libverus_crypto.a
LIBVERUS_PORTABLE_CRYPTO=crypto/libverus_portable_crypto.a
LIBSECP256K1=secp256k1/libsecp256k1.la
LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la
LIBSNARK=snark/libsnark.a
@ -95,8 +93,6 @@ $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptocond
# But to build the less dependent modules first, we manually select their order here:
EXTRA_LIBRARIES += \
$(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_SERVER) \
@ -183,9 +179,6 @@ BITCOIN_CORE_H = \
consensus/validation.h \
core_io.h \
core_memusage.h \
crypto/haraka.h \
crypto/haraka_portable.h \
crypto/verus_hash.h \
deprecation.h \
hash.h \
httprpc.h \
@ -316,8 +309,6 @@ libbitcoin_server_a_SOURCES = \
crosschain_authority.cpp \
crypto/haraka.h \
crypto/haraka_portable.h \
crypto/verus_hash.h \
crypto/verus_hash.cpp \
deprecation.cpp \
httprpc.cpp \
httpserver.cpp \
@ -420,11 +411,7 @@ crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha256.cpp \
crypto/sha256.h \
crypto/sha512.cpp \
crypto/sha512.h \
crypto/haraka.h \
crypto/haraka_portable.h \
crypto/verus_hash.h \
crypto/verus_hash.cpp
crypto/sha512.h
if ENABLE_MINING
EQUIHASH_TROMP_SOURCES = \
@ -438,20 +425,6 @@ crypto_libbitcoin_crypto_a_SOURCES += \
${EQUIHASH_TROMP_SOURCES}
endif
# Verus hash specific library - optimized
crypto_libverus_crypto_a_CPPFLAGS = -O3 -Wint-conversion -march=x86-64 -msse4 -msse4.1 -msse4.2 -mssse3 -mavx -maes -g -funroll-loops -fomit-frame-pointer -fPIC $(AM_CPPFLAGS)
crypto_libverus_crypto_a_CXXFLAGS = -O3 -Wint-conversion -march=x86-64 -msse4 -msse4.1 -msse4.2 -mssse3 -mavx -maes -g -funroll-loops -fomit-frame-pointer -fPIC $(AM_CXXFLAGS)
crypto_libverus_crypto_a_SOURCES = \
crypto/haraka.h \
crypto/haraka.c
# Verus hash specific library - portable
crypto_libverus_portable_crypto_a_CPPFLAGS = -O3 -Wint-conversion -march=x86-64 -g -funroll-loops -fomit-frame-pointer -fPIC $(AM_CPPFLAGS)
crypto_libverus_portable_crypto_a_CXXFLAGS = -O3 -Wint-conversion -march=x86-64 -g -funroll-loops -fomit-frame-pointer -fPIC $(AM_CXXFLAGS)
crypto_libverus_portable_crypto_a_SOURCES = \
crypto/haraka_portable.h \
crypto/haraka_portable.c
# common: shared between zcashd and non-server tools
libbitcoin_common_a_CPPFLAGS = -fPIC $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_common_a_CXXFLAGS = -fPIC $(AM_CXXFLAGS) $(PIE_FLAGS)
@ -468,8 +441,6 @@ libbitcoin_common_a_SOURCES = \
core_write.cpp \
crypto/haraka.h \
crypto/haraka_portable.h \
crypto/verus_hash.h \
crypto/verus_hash.cpp \
hash.cpp \
importcoin.cpp \
key.cpp \
@ -558,8 +529,6 @@ komodod_LDADD = \
$(LIBBITCOIN_ZMQ) \
$(LIBBITCOIN_PROTON) \
$(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBZCASH) \
$(LIBSNARK) \
$(LIBLEVELDB) \
@ -581,8 +550,6 @@ komodod_LDADD += \
$(ZMQ_LIBS) \
$(PROTON_LIBS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBZCASH_LIBS)
if TARGET_DARWIN
@ -635,8 +602,6 @@ komodo_cli_LDADD = \
$(EVENT_LIBS) \
$(LIBZCASH) \
$(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBZCASH_LIBS)
if ENABLE_WALLET
@ -644,8 +609,6 @@ wallet_utility_LDADD = \
libbitcoin_wallet.a \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBSECP256K1) \
$(LIBBITCOIN_UTIL) \
$(BOOST_LIBS) \
@ -667,7 +630,7 @@ if TARGET_WINDOWS
komodo_tx_SOURCES += bitcoin-tx-res.rc
endif
# FIXME: Is libzcash needed for zcash_tx?
# FIXME: Is libzcash needed for hush-tx ?
komodo_tx_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_COMMON) \
@ -676,8 +639,6 @@ komodo_tx_LDADD = \
$(LIBZCASH) \
$(LIBSNARK) \
$(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBZCASH_LIBS) \
$(LIBCRYPTOCONDITIONS)

11
src/chain.h

@ -470,17 +470,6 @@ public:
CBlockIndex* GetAncestor(int height);
const CBlockIndex* GetAncestor(int height) const;
int32_t GetVerusPOSTarget() const
{
return GetBlockHeader().GetVerusPOSTarget();
}
bool IsVerusPOSBlock() const
{
if ( ASSETCHAINS_LWMAPOS != 0 )
return GetBlockHeader().IsVerusPOSBlock();
else return(0);
}
};
/** Used to marshal pointers into hashes for db storage. */

91
src/hash.h

@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin Core developers
// Copyright (c) 2019 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -221,78 +222,6 @@ public:
}
};
/** A writer stream (for serialization) that computes a 256-bit Verus hash. */
class CVerusHashWriter
{
private:
CVerusHash state;
public:
int nType;
int nVersion;
CVerusHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() { }
void Reset() { state.Reset(); }
CVerusHashWriter& write(const char *pch, size_t size) {
state.Write((const unsigned char*)pch, size);
return (*this);
}
// invalidates the object for further writing
uint256 GetHash() {
uint256 result;
state.Finalize((unsigned char*)&result);
return result;
}
int64_t *xI64p() { return state.ExtraI64Ptr(); }
CVerusHash &GetState() { return state; }
template<typename T>
CVerusHashWriter& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj);
return (*this);
}
};
/** A writer stream (for serialization) that computes a 256-bit Verus hash with key initialized to Haraka standard. */
class CVerusHashV2Writer
{
private:
CVerusHashV2 state;
public:
int nType;
int nVersion;
CVerusHashV2Writer(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {}
void Reset() { state.Reset(); }
CVerusHashV2Writer& write(const char *pch, size_t size) {
state.Write((const unsigned char*)pch, size);
return (*this);
}
// invalidates the object for further writing
uint256 GetHash() {
uint256 result;
state.Finalize((unsigned char*)&result);
return result;
}
int64_t *xI64p() { return state.ExtraI64Ptr(); }
CVerusHashV2 &GetState() { return state; }
template<typename T>
CVerusHashV2Writer& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj);
return (*this);
}
};
/** Compute the 256-bit hash of an object's serialization. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
@ -302,24 +231,6 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
return ss.GetHash();
}
/** Compute the 256-bit Verus hash of an object's serialization. */
template<typename T>
uint256 SerializeVerusHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
CVerusHashWriter ss(nType, nVersion);
ss << obj;
return ss.GetHash();
}
/** Compute the 256-bit Verus hash of an object's serialization. */
template<typename T>
uint256 SerializeVerusHashV2(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
CVerusHashV2Writer ss(nType, nVersion);
ss << obj;
return ss.GetHash();
}
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);

19
src/init.cpp

@ -608,7 +608,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-ac_timelockgte", _("Timelocked coinbase minimum amount to be locked"));
strUsage += HelpMessageOpt("-ac_timelockto", _("Timelocked coinbase stop height"));
strUsage += HelpMessageOpt("-ac_txpow", _("Enforce transaction-rate limit, default 0"));
strUsage += HelpMessageOpt("-ac_veruspos", _("Use Verus Proof-Of-Stake (-ac_veruspos=50) default 0"));
return strUsage;
}
@ -1329,24 +1328,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
ECC_Start();
globalVerifyHandle.reset(new ECCVerifyHandle());
/*
// set the hash algorithm to use for this chain
// Again likely better solution here, than using long IF ELSE.
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1;
CVerusHash::init();
CVerusHashV2::init();
if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
{
// initialize VerusHash
CBlockHeader::SetVerusHash();
}
else if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1)
{
// initialize VerusHashV2
CBlockHeader::SetVerusHashV2();
}
*/
//fprintf(stderr,"%s tik10\n", __FUNCTION__);
// Sanity check
if (!InitSanityCheck())

176
src/komodo_bitcoind.h

@ -17,8 +17,8 @@
#include <curl/curl.h>
#include <curl/easy.h>
#include "primitives/nonce.h"
#include "consensus/params.h"
#include "primitives/nonce.h"
#include "komodo_defs.h"
#include "script/standard.h"
#include "cc/CCinclude.h"
@ -1755,177 +1755,7 @@ bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTr
// for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes
bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
{
CBlockIndex *pastBlockIndex;
uint256 txid, blkHash;
int32_t txn_count;
uint32_t voutNum;
CAmount value;
bool isPOS = false;
CTxDestination voutaddress, destaddress, cbaddress;
arith_uint256 target, hash;
CTransaction tx;
if (!pblock->IsVerusPOSBlock())
{
printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height);
//pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget());
//printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str());
return false;
}
char voutaddr[64], destaddr[64], cbaddr[64];
txn_count = pblock->vtx.size();
if ( txn_count > 1 )
{
target.SetCompact(pblock->GetVerusPOSTarget());
txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n;
value = pblock->vtx[txn_count-1].vout[0].nValue;
{
bool validHash = (value != 0);
bool enablePOSNonce = CPOSNonce::NewPOSActive(height);
uint256 rawHash;
arith_uint256 posHash;
if (validHash && enablePOSNonce)
{
validHash = pblock->GetRawVerusPOSHash(rawHash, height);
posHash = UintToArith256(rawHash) / value;
if (!validHash || posHash > target)
{
validHash = false;
printf("ERROR: invalid nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n",
pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value);
}
}
if (validHash)
{
if (slowflag == 0)
{
isPOS = true;
}
else if (!(pastBlockIndex = komodo_chainactive(height - 100)))
{
fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str());
}
else
#ifndef KOMODO_ZCASH
if (!GetTransaction(txid, tx, Params().GetConsensus(), blkHash, true))
#else
if (!GetTransaction(txid, tx, blkHash, true))
#endif
{
fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str());
}
else
{
CBlockHeader bh = pastBlockIndex->GetBlockHeader();
uint256 pastHash = bh.GetVerusEntropyHash(height - 100);
// if height is over when Nonce is required to be the new format, we check that the new format is correct
// if over when we have the new POS hash function, we validate that as well
// they are 100 blocks apart
CPOSNonce nonce = pblock->nNonce;
//printf("before nNonce: %s, height: %d\n", pblock->nNonce.GetHex().c_str(), height);
//validHash = pblock->GetRawVerusPOSHash(rawHash, height);
//hash = UintToArith256(rawHash) / tx.vout[voutNum].nValue;
//printf("Raw POShash: %s\n", hash.GetHex().c_str());
hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash));
//printf("after nNonce: %s, height: %d\n", nonce.GetHex().c_str(), height);
//printf("POShash: %s\n\n", hash.GetHex().c_str());
if (posHash == hash && hash <= target)
{
BlockMap::const_iterator it = mapBlockIndex.find(blkHash);
if ((it == mapBlockIndex.end()) ||
!(pastBlockIndex = it->second) ||
(height - pastBlockIndex->GetHeight()) < VERUS_MIN_STAKEAGE)
{
fprintf(stderr,"ERROR: invalid PoS block %s - stake source too new or not found\n",blkHash.ToString().c_str());
}
else
{
// make sure we have the right target
CBlockIndex *previndex;
it = mapBlockIndex.find(pblock->hashPrevBlock);
if (it == mapBlockIndex.end() || !(previndex = it->second))
{
fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str());
}
else
{
arith_uint256 cTarget;
uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus());
cTarget.SetCompact(nBits);
bool nonceOK = true;
// check to see how many fail
//if (nonce != pblock->nNonce)
// printf("Mismatched nNonce: %s\nblkHash: %s, height: %d\n", nonce.GetHex().c_str(), pblock->GetHash().GetHex().c_str(), height);
if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum))
{
fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str());
nonceOK = false;
}
else
{
if (cTarget != target)
{
fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str());
nonceOK = false;
}
}
if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) &&
ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) )
{
strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str());
strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str());
if ( !strcmp(destaddr,voutaddr) )
{
isPOS = true;
CTransaction &cbtx = pblock->vtx[0];
for (int i = 0; i < cbtx.vout.size(); i++)
{
if (CScriptExt::ExtractVoutDestination(cbtx, i, cbaddress))
{
strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str());
if (!strcmp(destaddr,cbaddr))
continue;
}
else
{
if (cbtx.vout[i].scriptPubKey.IsOpReturn())
continue;
isPOS = false;
break;
}
}
}
else
{
fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake or coinbase destination\n",blkHash.ToString().c_str());
}
}
}
}
}
else
{
printf("ERROR: malformed nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n",
pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value);
}
}
}
}
}
return(isPOS);
return false;
}
uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount)
@ -2290,11 +2120,13 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
// bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime);
if ( ASSETCHAINS_LWMAPOS != 0 && bhash > bnTarget )
{
/*
// if proof of stake is active, check if this is a valid PoS block before we fail
if (verusCheckPOSBlock(slowflag, pblock, height))
{
return(0);
}
*/
}
if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget )
{

51
src/komodo_utils.h

@ -30,8 +30,6 @@
#define portable_mutex_lock pthread_mutex_lock
#define portable_mutex_unlock pthread_mutex_unlock
extern void verus_hash(void *result, const void *data, size_t len);
struct allocitem { uint32_t allocsize,type; };
struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; };
@ -1026,45 +1024,24 @@ int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_
// from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain
uint64_t komodo_block_prg(uint32_t nHeight)
{
if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800)
{
uint64_t i, result = 0, hashSrc64 = ((uint64_t)ASSETCHAINS_MAGIC << 32) | (uint64_t)nHeight;
uint8_t hashSrc[8];
bits256 hashResult;
int i;
uint8_t hashSrc[8];
uint64_t result=0, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight;
bits256 hashResult;
for ( i = 0; i < sizeof(hashSrc); i++ )
{
uint64_t x = hashSrc64 >> (i * 8);
hashSrc[i] = (uint8_t)(x & 0xff);
}
verus_hash(hashResult.bytes, hashSrc, sizeof(hashSrc));
for ( i = 0; i < 8; i++ )
{
result = (result << 8) | hashResult.bytes[i];
}
return result;
}
else
for ( i = 0; i < sizeof(hashSrc); i++ )
{
int i;
uint8_t hashSrc[8];
uint64_t result=0, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight;
bits256 hashResult;
for ( i = 0; i < sizeof(hashSrc); i++ )
{
hashSrc[i] = hashSrc64 & 0xff;
hashSrc64 >>= 8;
int8_t b = hashSrc[i];
}
hashSrc[i] = hashSrc64 & 0xff;
hashSrc64 >>= 8;
int8_t b = hashSrc[i];
}
vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc));
for ( i = 0; i < 8; i++ )
{
result = (result << 8) + hashResult.bytes[i];
}
return result;
vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc));
for ( i = 0; i < 8; i++ )
{
result = (result << 8) + hashResult.bytes[i];
}
return result;
}
// given a block height, this returns the unlock time for that block height, derived from

2
src/main.cpp

@ -5229,7 +5229,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
//LogPrintf("Rejected by mempool, reason: .%s.\n", state.GetRejectReason().c_str());
// take advantage of other checks, but if we were only rejected because it is a valid staking
// transaction, sync with wallets and don't mark as a reject
if (i == (block.vtx.size() - 1) && ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock() && state.GetRejectReason() == "staking")
if (i == (block.vtx.size() - 1) && ASSETCHAINS_LWMAPOS && state.GetRejectReason() == "staking")
{
sTx = Tx;
ptx = &sTx;

490
src/miner.cpp

@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2019 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -32,7 +33,6 @@
#include "consensus/validation.h"
#ifdef ENABLE_MINING
#include "crypto/equihash.h"
#include "crypto/verus_hash.h"
#endif
#include "hash.h"
#include "key_io.h"
@ -149,7 +149,6 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
int64_t komodo_block_unlocktime(uint32_t nHeight);
uint64_t komodo_commission(const CBlock *block,int32_t height);
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);
int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk);
int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
int32_t komodo_is_notarytx(const CTransaction& tx);
@ -588,15 +587,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
if (ASSETCHAINS_LWMAPOS != 0)
{
uint32_t nBitsPOS;
arith_uint256 posHash;
siglen = verus_staked(pblock, txStaked, nBitsPOS, posHash, utxosig, pk);
blocktime = GetAdjustedTime();
// change the scriptPubKeyIn to the same output script exactly as the staking transaction
if (siglen > 0)
scriptPubKeyIn = CScript(txStaked.vout[0].scriptPubKey);
}
else
{
@ -1135,477 +1125,8 @@ CBlockIndex *get_chainactive(int32_t height)
return(0);
}
/*
* A separate thread to stake, while the miner threads mine.
*/
void static VerusStaker(CWallet *pwallet)
{
LogPrintf("Verus staker thread started\n");
RenameThread("verus-staker");
const CChainParams& chainparams = Params();
auto consensusParams = chainparams.GetConsensus();
// Each thread has its own key
CReserveKey reservekey(pwallet);
// Each thread has its own counter
unsigned int nExtraNonce = 0;
std::vector<unsigned char> solnPlaceholder = std::vector<unsigned char>();
solnPlaceholder.resize(Eh200_9.SolutionWidth);
uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
{
sleep(1);
if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
break;
}
// try a nice clean peer connection to start
CBlockIndex *pindexPrev, *pindexCur;
do {
pindexPrev = chainActive.LastTip();
MilliSleep(5000 + rand() % 5000);
waitForPeers(chainparams);
pindexCur = chainActive.LastTip();
} while (pindexPrev != pindexCur);
try {
while (true)
{
waitForPeers(chainparams);
CBlockIndex* pindexPrev = chainActive.LastTip();
printf("Staking height %d for %s\n", pindexPrev->GetHeight() + 1, ASSETCHAINS_SYMBOL);
// Create new block
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
if ( Mining_height != pindexPrev->GetHeight()+1 )
{
Mining_height = pindexPrev->GetHeight()+1;
Mining_start = (uint32_t)time(NULL);
}
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
// try to stake a block
CBlockTemplate *ptr = NULL;
if (Mining_height > VERUS_MIN_STAKEAGE)
ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0, true);
if ( ptr == 0 )
{
// wait to try another staking block until after the tip moves again
while ( chainActive.LastTip() == pindexPrev )
sleep(1);
continue;
}
unique_ptr<CBlockTemplate> pblocktemplate(ptr);
if (!pblocktemplate.get())
{
if (GetArg("-mineraddress", "").empty()) {
LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
} else {
// Should never reach here, because -mineraddress validity is checked in init.cpp
LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
}
return;
}
CBlock *pblock = &pblocktemplate->block;
LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
//
// Search
//
int64_t nStart = GetTime();
// take up the necessary space for alignment
pblock->nSolution = solnPlaceholder;
// we don't use this, but IncrementExtraNonce is the function that builds the merkle tree
unsigned int nExtraNonce = 0;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
if (vNodes.empty() && chainparams.MiningRequiresPeers())
{
if ( Mining_height > ASSETCHAINS_MINHEIGHT )
{
fprintf(stderr,"no nodes, attempting reconnect\n");
continue;
}
}
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
{
fprintf(stderr,"timeout, retrying\n");
continue;
}
if ( pindexPrev != chainActive.LastTip() )
{
printf("Block %d added to chain\n", chainActive.LastTip()->GetHeight());
MilliSleep(250);
continue;
}
int32_t unlockTime = komodo_block_unlocktime(Mining_height);
int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits));
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
UpdateTime(pblock, consensusParams, pindexPrev);
ProcessBlockFound(pblock, *pwallet, reservekey);
LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
printf("Found block %d \n", Mining_height );
printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
arith_uint256 post;
post.SetCompact(pblock->GetVerusPOSTarget());
pindexPrev = get_chainactive(Mining_height - 100);
CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1];
printf("POS hash: %s \ntarget: %s\n",
CTransaction::_GetVerusPOSHash(&(pblock->nNonce), sTx.vin[0].prevout.hash, sTx.vin[0].prevout.n, Mining_height, pindexPrev->GetBlockHeader().GetVerusEntropyHash(Mining_height - 100), sTx.vout[0].nValue).GetHex().c_str(), ArithToUint256(post).GetHex().c_str());
if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
printf("- timelocked until block %i\n", unlockTime);
else
printf("\n");
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
sleep(3);
// In regression test mode, stop mining after a block is found.
if (chainparams.MineBlocksOnDemand()) {
throw boost::thread_interrupted();
}
}
}
catch (const boost::thread_interrupted&)
{
LogPrintf("VerusStaker terminated\n");
throw;
}
catch (const std::runtime_error &e)
{
LogPrintf("VerusStaker runtime error: %s\n", e.what());
return;
}
}
void static BitcoinMiner_noeq(CWallet *pwallet)
#else
void static BitcoinMiner_noeq()
#endif
{
LogPrintf("%s miner started\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
RenameThread("verushash-miner");
#ifdef ENABLE_WALLET
// Each thread has its own key
CReserveKey reservekey(pwallet);
#endif
const CChainParams& chainparams = Params();
// Each thread has its own counter
unsigned int nExtraNonce = 0;
std::vector<unsigned char> solnPlaceholder = std::vector<unsigned char>();
solnPlaceholder.resize(Eh200_9.SolutionWidth);
uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
{
sleep(1);
if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
break;
}
SetThreadPriority(THREAD_PRIORITY_LOWEST);
// try a nice clean peer connection to start
CBlockIndex *pindexPrev, *pindexCur;
do {
pindexPrev = chainActive.LastTip();
MilliSleep(5000 + rand() % 5000);
waitForPeers(chainparams);
pindexCur = chainActive.LastTip();
} while (pindexPrev != pindexCur);
// this will not stop printing more than once in all cases, but it will allow us to print in all cases
// and print duplicates rarely without having to synchronize
static CBlockIndex *lastChainTipPrinted;
miningTimer.start();
try {
printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
while (true)
{
miningTimer.stop();
waitForPeers(chainparams);
pindexPrev = chainActive.LastTip();
sleep(1);
// prevent forking on startup before the diff algorithm kicks in
if (pindexPrev->GetHeight() < 50 || pindexPrev != chainActive.LastTip())
{
do {
pindexPrev = chainActive.LastTip();
MilliSleep(5000 + rand() % 5000);
} while (pindexPrev != chainActive.LastTip());
}
// Create new block
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
if ( Mining_height != pindexPrev->GetHeight()+1 )
{
Mining_height = pindexPrev->GetHeight()+1;
Mining_start = (uint32_t)time(NULL);
}
if (lastChainTipPrinted != pindexPrev)
{
printf("Mining height %d\n", Mining_height);
lastChainTipPrinted = pindexPrev;
}
miningTimer.start();
#ifdef ENABLE_WALLET
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0);
#else
CBlockTemplate *ptr = CreateNewBlockWithKey();
#endif
if ( ptr == 0 )
{
static uint32_t counter;
if ( ASSETCHAINS_STAKED == 0 && counter++ < 10 )
fprintf(stderr,"created illegal block, retry\n");
continue;
}
unique_ptr<CBlockTemplate> pblocktemplate(ptr);
if (!pblocktemplate.get())
{
if (GetArg("-mineraddress", "").empty()) {
LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
} else {
// Should never reach here, because -mineraddress validity is checked in init.cpp
LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
}
return;
}
CBlock *pblock = &pblocktemplate->block;
if ( ASSETCHAINS_SYMBOL[0] != 0 )
{
if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
{
if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
{
static uint32_t counter;
if ( counter++ < 10 )
fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
sleep(10);
continue;
} else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
}
}
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO],
pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
//
// Search
//
uint32_t savebits; int64_t nStart = GetTime();
pblock->nSolution = solnPlaceholder;
savebits = pblock->nBits;
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
HASHTarget = arith_uint256().SetCompact(savebits);
arith_uint256 mask(ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO]);
Mining_start = 0;
if ( pindexPrev != chainActive.LastTip() )
{
if (lastChainTipPrinted != chainActive.LastTip())
{
lastChainTipPrinted = chainActive.LastTip();
printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
}
MilliSleep(250);
continue;
}
if ( ASSETCHAINS_STAKED != 0 )
{
int32_t percPoS,z; bool fNegative,fOverflow;
HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
LogPrintf("Block %d : PoS %d%% vs target %d%%\n", Mining_height, percPoS, (int32_t)ASSETCHAINS_STAKED);
}
//else if ( ASSETCHAINS_ADAPTIVEPOW > 0 && ASSETCHAINS_STAKED == 0 )
// HASHTarget_POW = komodo_adaptivepow_target(Mining_height,HASHTarget,pblock->nTime);
while (true)
{
arith_uint256 arNonce = UintToArith256(pblock->nNonce);
int64_t *extraPtr;
// This seems to be a really bad way to do this, but its better than copy pasting the entire miner function at this stage.
CVerusHashWriter ss = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
ss << *((CBlockHeader *)pblock);
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH )
extraPtr = ss.xI64p();
CVerusHash &vh = ss.GetState();
uint256 hashResult = uint256();
vh.ClearExtra();
CVerusHashV2Writer ss2 = CVerusHashV2Writer(SER_GETHASH, PROTOCOL_VERSION);
ss2 << *((CBlockHeader *)pblock);
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
extraPtr = ss2.xI64p();
CVerusHashV2 &vh2 = ss2.GetState();
vh2.ClearExtra();
int64_t i, count = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1;
int64_t hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
if ( ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 )
{
if ( KOMODO_MININGTHREADS > 0 )
hashTarget = HASHTarget_POW;
else
hashTarget = HASHTarget;
}
else if ( ASSETCHAINS_STAKED == 100 && Mining_height > 100 )
hashTarget = HASHTarget;
//else if ( ASSETCHAINS_ADAPTIVEPOW > 0 && ASSETCHAINS_STAKED == 0 )
// hashTarget = HASHTarget_POW;
// for speed check NONCEMASK at a time
for (i = 0; i < count; i++)
{
*extraPtr = i;
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH )
vh.ExtraHash((unsigned char *)&hashResult);
else if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
vh2.ExtraHash((unsigned char *)&hashResult);
if ( UintToArith256(hashResult) <= hashTarget )
{
if (pblock->nSolution.size() != 1344)
{
LogPrintf("ERROR: Block solution is not 1344 bytes as it should be");
sleep(5);
break;
}
SetThreadPriority(THREAD_PRIORITY_NORMAL);
*((int64_t *)&(pblock->nSolution.data()[pblock->nSolution.size() - 15])) = i;
int32_t unlockTime = komodo_block_unlocktime(Mining_height);
int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
printf("Found block %d \n", Mining_height );
printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
printf(" hash: %s \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str());
if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
printf("- timelocked until block %i\n", unlockTime);
else
printf("\n");
#ifdef ENABLE_WALLET
ProcessBlockFound(pblock, *pwallet, reservekey);
#else
ProcessBlockFound(pblock));
#endif
SetThreadPriority(THREAD_PRIORITY_LOWEST);
break;
}
// check periodically if we're stale
if (!--hashesToGo)
{
if ( pindexPrev != chainActive.LastTip() )
{
if (lastChainTipPrinted != chainActive.LastTip())
{
lastChainTipPrinted = chainActive.LastTip();
printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
}
break;
}
hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
}
}
{
LOCK(cs_metrics);
nHashCount += i;
}
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
if (vNodes.empty() && chainparams.MiningRequiresPeers())
{
if ( Mining_height > ASSETCHAINS_MINHEIGHT )
{
fprintf(stderr,"no nodes, attempting reconnect\n");
break;
}
}
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
{
fprintf(stderr,"timeout, retrying\n");
break;
}
if ( pindexPrev != chainActive.LastTip() )
{
if (lastChainTipPrinted != chainActive.LastTip())
{
lastChainTipPrinted = chainActive.LastTip();
printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
}
break;
}
#ifdef _WIN32
printf("%llu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
#else
printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
#endif
pblock->nBits = savebits;
break;
}
}
}
catch (const boost::thread_interrupted&)
{
miningTimer.stop();
LogPrintf("%s miner terminated\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
throw;
}
catch (const std::runtime_error &e)
{
miningTimer.stop();
LogPrintf("%s miner runtime error: %s\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], e.what());
return;
}
miningTimer.stop();
}
int32_t gotinvalid;
@ -1617,7 +1138,7 @@ void static BitcoinMiner()
{
LogPrintf("HushMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("komodo-miner");
RenameThread("hush-miner");
const CChainParams& chainparams = Params();
#ifdef ENABLE_WALLET
@ -2119,9 +1640,8 @@ void static BitcoinMiner()
minerThreads = new boost::thread_group();
#ifdef ENABLE_WALLET
if (ASSETCHAINS_LWMAPOS != 0 && VERUS_MINTBLOCKS)
if (ASSETCHAINS_LWMAPOS != 0)
{
minerThreads->create_thread(boost::bind(&VerusStaker, pwallet));
}
#endif
@ -2130,13 +1650,9 @@ void static BitcoinMiner()
#ifdef ENABLE_WALLET
if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH )
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
else
minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
#else
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH )
minerThreads->create_thread(&BitcoinMiner);
else
minerThreads->create_thread(&BitcoinMiner_noeq);
#endif
}
}

8
src/pow.cpp

@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2019 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -650,11 +651,13 @@ uint32_t lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::
CBlockHeader hdr = pindexFirst->GetBlockHeader();
/*
if (hdr.IsVerusPOSBlock())
{
nBits = hdr.GetVerusPOSTarget();
break;
}
*/
pindexFirst = pindexFirst->pprev;
}
@ -675,11 +678,13 @@ uint32_t lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::
return nProofOfStakeLimit;
CBlockHeader hdr = pindexFirst->GetBlockHeader();
/*
if (hdr.IsVerusPOSBlock())
{
nBits = hdr.GetVerusPOSTarget();
break;
}
*/
}
if (x)
@ -870,7 +875,8 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t
//else if ( ASSETCHAINS_ADAPTIVEPOW > 0 && ASSETCHAINS_STAKED == 0 )
// bnTarget = komodo_adaptivepow_target(height,bnTarget,blkHeader.nTime);
// Check proof of work matches claimed amount
if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget && !blkHeader.IsVerusPOSBlock() )
//if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget && !blkHeader.IsVerusPOSBlock() )
if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget )
{
if ( KOMODO_LOADINGBLOCKS != 0 )
return true;

84
src/primitives/block.cpp

@ -35,96 +35,12 @@ uint256 CBlockHeader::GetSHA256DHash() const
return SerializeHash(*this);
}
uint256 CBlockHeader::GetVerusHash() const
{
if (hashPrevBlock.IsNull())
// always use SHA256D for genesis block
return SerializeHash(*this);
else
return SerializeVerusHash(*this);
}
uint256 CBlockHeader::GetVerusV2Hash() const
{
if (hashPrevBlock.IsNull())
// always use SHA256D for genesis block
return SerializeHash(*this);
else
return SerializeVerusHashV2(*this);
}
void CBlockHeader::SetSHA256DHash()
{
CBlockHeader::hashFunction = &CBlockHeader::GetSHA256DHash;
}
void CBlockHeader::SetVerusHash()
{
CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash;
}
void CBlockHeader::SetVerusHashV2()
{
CBlockHeader::hashFunction = &CBlockHeader::GetVerusV2Hash;
}
// returns false if unable to fast calculate the VerusPOSHash from the header.
// if it returns false, value is set to 0, but it can still be calculated from the full 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 &ret, 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()))
{
ret = uint256();
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;
ret = hashWriter.GetHash();
return true;
}
bool CBlockHeader::GetVerusPOSHash(arith_uint256 &ret, int32_t nHeight, CAmount value) const
{
uint256 raw;
if (GetRawVerusPOSHash(raw, nHeight))
{
ret = UintToArith256(raw) / value;
return true;
}
return false;
}
// 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 BuildMerkleTree(bool* fMutated, const std::vector<uint256> leaves,
std::vector<uint256> &vMerkleTree)
{

48
src/primitives/block.h

@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin Core developers
// Copyright (c) 2019 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -51,7 +52,9 @@ public:
uint256 hashFinalSaplingRoot;
uint32_t nTime;
uint32_t nBits;
CPOSNonce nNonce;
//CPOSNonce nNonce;
uint256 nNonce;
std::vector<unsigned char> nSolution;
CBlockHeader()
@ -98,57 +101,14 @@ public:
uint256 GetSHA256DHash() const;
static void SetSHA256DHash();
uint256 GetVerusHash() const;
static void SetVerusHash();
bool GetRawVerusPOSHash(uint256 &ret, int32_t nHeight) const;
bool GetVerusPOSHash(arith_uint256 &ret, int32_t nHeight, CAmount value) const; // value is amount of stake tx
uint256 GetVerusEntropyHash(int32_t nHeight) const;
uint256 GetVerusV2Hash() const;
static void SetVerusHashV2();
int64_t GetBlockTime() const
{
return (int64_t)nTime;
}
uint32_t GetVerusPOSTarget() const
{
uint32_t nBits = 0;
for (const unsigned char *p = nNonce.begin() + 3; p >= nNonce.begin(); p--)
{
nBits <<= 8;
nBits += *p;
}
return nBits;
}
bool IsVerusPOSBlock() const
{
if ( ASSETCHAINS_LWMAPOS != 0 )
return nNonce.IsPOSNonce();
else return(0);
}
void SetVerusPOSTarget(uint32_t nBits)
{
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
arith_uint256 arNonce = UintToArith256(nNonce);
// printf("before svpt: %s\n", ArithToUint256(arNonce).GetHex().c_str());
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());
}
};
// this class is used to address the type mismatch that existed between nodes, where block headers

63
src/primitives/nonce.cpp

@ -21,66 +21,3 @@
#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
return true;
}
bool CPOSNonce::NewNonceActive(int32_t height)
{
if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) && (height < 96480))
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);
}

52
src/primitives/nonce.h

@ -1,3 +1,4 @@
// Copyright (c) 2019 Hush Developers
// 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.
@ -25,55 +26,4 @@
#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

36
src/primitives/transaction.h

@ -30,7 +30,6 @@
#include "arith_uint256.h"
#include "consensus/consensus.h"
#include "hash.h"
#include "nonce.h"
#ifndef __APPLE__
#include <stdint.h>
@ -727,41 +726,6 @@ public:
return a.hash != b.hash;
}
// verus hash will be the same for a given txid, output number, block height, and blockhash of 100 blocks past
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);
hashWriter << ASSETCHAINS_MAGIC;
// we only use the new style of POS hash after changeover and 100 blocks of enforced proper nonce updating
if (CPOSNonce::NewPOSActive(height))
{
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);
}
}
// 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();
if (voutNum >= vout.size())
return uint256S("ff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
return _GetVerusPOSHash(pNonce, txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue);
}
std::string ToString() const;
};

2
src/rpc/blockchain.cpp

@ -326,7 +326,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
result.push_back(Pair("chainwork", blockindex->chainPower.chainWork.GetHex()));
result.push_back(Pair("anchor", blockindex->hashFinalSproutRoot.GetHex()));
result.push_back(Pair("blocktype", block.IsVerusPOSBlock() ? "minted" : "mined"));
result.push_back(Pair("blocktype", "mined"));
UniValue valuePools(UniValue::VARR);
valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue));

6
src/wallet/rpcwallet.cpp

@ -5464,12 +5464,6 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
return(siglen);
}
int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk)
{
return pwalletMain->VerusStakeTransaction(pBlock, txNew, nBits, hashResult, utxosig, pk);
}
#include "../cc/CCfaucet.h"
#include "../cc/CCassets.h"
#include "../cc/CCrewards.h"

114
src/wallet/wallet.cpp

@ -1338,120 +1338,6 @@ CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries,
return txOrdered;
}
// looks through all wallet UTXOs and checks to see if any qualify to stake the block at the current height. it always returns the qualified
// 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:
// ASSETCHAINS_MAGIC, nHeight, txid, voutNum
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;
vector<COutput> vecOutputs;
COutput *pwinner = NULL;
CBlockIndex *pastBlockIndex;
txnouttype whichType;
std:vector<std::vector<unsigned char>> vSolutions;
pBlock->nNonce.SetPOSTarget(bnTarget);
target.SetCompact(bnTarget);
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
if (pastBlockIndex = komodo_chainactive(nHeight - 100))
{
CBlockHeader bh = pastBlockIndex->GetBlockHeader();
uint256 pastHash = bh.GetVerusEntropyHash(nHeight - 100);
CPOSNonce curNonce;
BOOST_FOREACH(COutput &txout, vecOutputs)
{
if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(&(pBlock->nNonce), txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE))
{
if ((!pwinner || UintToArith256(curNonce) > UintToArith256(pBlock->nNonce)) &&
(Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH)))
{
//printf("Found PoS block\nnNonce: %s\n", pBlock->nNonce.GetHex().c_str());
pwinner = &txout;
curNonce = pBlock->nNonce;
}
}
}
if (pwinner)
{
stakeSource = *(pwinner->tx);
voutNum = pwinner->i;
pBlock->nNonce = curNonce;
return true;
}
}
return false;
}
int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey pk) const
{
CTransaction stakeSource;
int32_t voutNum, siglen = 0;
int64_t nValue;
txnouttype whichType;
std::vector<std::vector<unsigned char>> vSolutions;
CBlockIndex *tipindex = chainActive.LastTip();
uint32_t stakeHeight = tipindex->GetHeight() + 1;
pk = CPubKey();
bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus());
if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, tipindex->GetHeight() + 1, bnTarget) ||
!Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions))
{
LogPrintf("Searched for eligible staking transactions, no winners found\n");
return 0;
}
bool signSuccess;
SignatureData sigdata;
uint64_t txfee;
auto consensusBranchId = CurrentEpochBranchId(stakeHeight, Params().GetConsensus());
const CKeyStore& keystore = *pwalletMain;
txNew.vin.resize(1);
txNew.vout.resize(1);
txfee = 0;
txNew.vin[0].prevout.hash = stakeSource.GetHash();
txNew.vin[0].prevout.n = voutNum;
if (whichType == TX_PUBKEY)
{
txNew.vout[0].scriptPubKey << ToByteVector(vSolutions[0]) << OP_CHECKSIG;
if (!pk.IsValid())
pk = CPubKey(vSolutions[0]);
}
else if (whichType == TX_PUBKEYHASH)
{
txNew.vout[0].scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(vSolutions[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
}
else
return 0;
nValue = txNew.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
txNew.nLockTime = 0;
CTransaction txNewConst(txNew);
signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, sigdata, consensusBranchId);
if (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
{
uint8_t *ptr;
UpdateTransaction(txNew,0,sigdata);
ptr = (uint8_t *)&sigdata.scriptSig[0];
siglen = sigdata.scriptSig.size();
for (int i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
}
return(siglen);
}
void CWallet::MarkDirty()
{

3
src/wallet/wallet.h

@ -1330,9 +1330,6 @@ public:
bool requireSpendingKey=true,
bool ignoreLocked=true);
// staking functions
bool VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const;
int32_t VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey pk) const;
};
/** A key allocated from the key pool. */

Loading…
Cancel
Save