Algo change update. Implemented - 192/7 Param Change, LWMA-1 Diff Adjustment, Configurable Block Maturity, Updated version
This commit is contained in:
parent
f247a95b40
commit
2a7543f90b
|
@ -1,7 +1,7 @@
|
|||
Bitcoin Private
|
||||
----------------
|
||||
|
||||
**Bitcoin Private v1.0.14**
|
||||
**Bitcoin Private v1.0.15**
|
||||
|
||||
P2P Port: 7933
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
|||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 1)
|
||||
define(_CLIENT_VERSION_MINOR, 0)
|
||||
define(_CLIENT_VERSION_REVISION, 14)
|
||||
define(_CLIENT_VERSION_REVISION, 15)
|
||||
define(_CLIENT_VERSION_BUILD, 50)
|
||||
define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
|
||||
define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
name: "BTCP-1.0.14"
|
||||
name: "BTCP-1.0.15"
|
||||
enable_cache: true
|
||||
distro: "debian"
|
||||
suites:
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
CMainParams() {
|
||||
strNetworkID = "main";
|
||||
strCurrencyUnits = "BTCP";
|
||||
consensus.coinbaseMaturity = 100;
|
||||
|
||||
consensus.fCoinbaseMustBeProtected = true;
|
||||
consensus.nSubsidySlowStartInterval = 2;
|
||||
consensus.nSubsidyHalvingInterval = 840000;
|
||||
|
@ -51,7 +53,6 @@ public:
|
|||
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
|
||||
consensus.nPowTargetSpacing = 2.5 * 60;
|
||||
consensus.fPowAllowMinDifficultyBlocks = false;
|
||||
|
||||
consensus.nPowDifficultyBombHeight = 600000;
|
||||
consensus.nHeightDiffBombRemoved = 599999;
|
||||
|
||||
|
@ -154,8 +155,20 @@ public:
|
|||
// total number of tx / (checkpoint block height / (24 * 24))
|
||||
};
|
||||
|
||||
// ZCL + BTC -> BTCP
|
||||
nForkStartHeight = 272991;
|
||||
nForkHeightRange = 5467;
|
||||
|
||||
|
||||
// Equihash 192,7
|
||||
nEquihashParamsUpdate = 615500;
|
||||
nEquihashNnew = 192;
|
||||
nEquihashKnew = 7;
|
||||
|
||||
// LWMA-1
|
||||
lwmaActivationHeight = 615518;
|
||||
lwmaAveragingWindow = 120;
|
||||
|
||||
}
|
||||
};
|
||||
static CMainParams mainParams;
|
||||
|
@ -168,13 +181,19 @@ public:
|
|||
CTestNetParams() {
|
||||
strNetworkID = "test";
|
||||
strCurrencyUnits = "BTCPT";
|
||||
consensus.coinbaseMaturity = 10;
|
||||
|
||||
consensus.fCoinbaseMustBeProtected = true;
|
||||
consensus.nMajorityEnforceBlockUpgrade = 51;
|
||||
consensus.nMajorityRejectBlockOutdated = 75;
|
||||
consensus.nMajorityWindow = 400;
|
||||
consensus.powLimit = uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.powLimit = uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.prePowLimit = consensus.powLimit;
|
||||
assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow);
|
||||
consensus.nPowAveragingWindow = 17;
|
||||
//assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow);
|
||||
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
|
||||
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
|
||||
consensus.nPowTargetSpacing = 2.5 * 60;
|
||||
consensus.fPowAllowMinDifficultyBlocks = true;
|
||||
|
||||
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
|
||||
|
@ -184,8 +203,8 @@ public:
|
|||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
|
||||
|
||||
consensus.nPowDifficultyBombHeight = 600000;
|
||||
consensus.nHeightDiffBombRemoved = 599999;
|
||||
consensus.nPowDifficultyBombHeight = 102;
|
||||
consensus.nHeightDiffBombRemoved = 101;
|
||||
|
||||
consensus.nUnmovedBurnHeight = 480000;
|
||||
consensus.zResetHeight = 455500;
|
||||
|
@ -200,17 +219,15 @@ public:
|
|||
nPruneAfterHeight = 1000;
|
||||
|
||||
//! Modify the testnet genesis block so the timestamp is valid for a later start.
|
||||
genesis.nTime = 1479443947;
|
||||
genesis.nTime = 1527600786;
|
||||
genesis.nBits = 0x2007ffff;
|
||||
genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000013");
|
||||
genesis.nSolution = ParseHex("002b24e10a5d2ab32b053a20ca6ebed779be1d935b1500eeea5c87aec684c6f934196fdfca6539de0cf1141544bffc5c0d1d4bab815fb5d8c2b195ccdf0755599ee492b9d98e3b79a178949f45485ad80dba38ec0461102adaa369b757ebb2bf8d75b5f67a341d666406d862a102c69800f20a7075be360a7eb2d315d78e4ce32c741f3baf7bf3e1e651976f734f367b1f126f62503b34d06d6e99b3659b2a47f5cfcf71c87e24e5023151d4af87454e7638a19b846350dd5fbc53e4ce1cce2597992b36cbcae0c24717e412c8df9ddca3e90c7629bd8c157c66d8906486943cf78e24d55dd4152f45eff49acf9fb9fddef81f2ee55892b38db940c404eaacf819588b83f0f761f1ba5b31a0ea1f8f4c5210638bbb59a2d8ddff9535f546b42a7eac5f3ee87616a075bddc3118b7f2c041f4b1e8dbcd11eea95835403066b5bb50cd23122dcb12166d75aafcfc1ca8f30580b4d48a5aa305657a06b4b650ed4633f2fa496235082feff65f70e19871f41b70632b53e57ddf38c207d631e5a56fa50bb71150f99427f73d82a439a5f70dfc7d8bbfc39d330ca7924527a5deb8950b9fa7020cfde5e07b84546e96764519ef6dd3fdc3a974abd342bdc7e4ee76bc11d5519541015afba1a0517fd347196aa326b0905a5916b83515c16f8f13105479c29f1eff3bc024ddbb07dcc672247cedc0d4ba32332ead0f13c58f50170642e16e076c34f5e75e3e8f5ac7f5238d67564fd385efecf972b0abf939a99bc7ef8f3a21cac21d2168706bbad3f4af66bb01cf61cfbc352a23797b62dcb5480bf2b7b277af233f5ce42a144d47119a89e1d114fa0bec2f13475b6b1df907bc3a429f1771afa3857bf16bfca3f76a5df14da62dc157fff4225bda73c3cfefa989edc24673bf932a024593da4c38b1a4628dd77ad919f4f7b7fb76976e696db69c89016ab30d9aa2d509f78d913d00ca9ac881aa759fc019b8c5e3eac6fddb4e0f044595e10d4997e29c79800f77cf1d97583d534db0f2726cba3739e7371eeffa2aca12b0d290ac45f44973f32f7675a5b49c94c4b608da2926555d16b7eb3670e12345a63f88797e5a5e21252c2c9463d7896001031a81bac0354336b35c5a10c93d9ae3054f6f6e4492f7c1f09a9d75034d5d0b220a9bb231e583659d5b6923a4e879326194de5c9805a02cb648508a8f9b6cd26dc17d322a478c1c599e1ec3adf2da6ce7a7e3a073b55cf30cf6b124f7700409abe14af8c60ab178579623916f165dbfd26f37056bf33c34f3af30939e1277376e4c5cba339f36381a05ef6481db033fb4c07a19e8655f8b12f9ab3c602e127b4ab1ee48e1c6a91382b54ed36ef9bb21b3bfa80a9107864dcb594dcad250e402b312607e648639631a3d1aeb17cfe3370202720ca8a46db15af92e8b46062b5bd035b24c35a592e5620d632faf1bf19a86df179fe52dd4cdbecd3cb7a336ca7489e4d1dc9433f1163c89d88c5eac36fc562496dc7583fe67c559c9a71cf89e9a0a59d5a14764926852d44a88d2ddb361d612ec06f9de874473eaf1d36b3a41911ac072b7826e6acea3d8425dc271833dba2ec17d1a270e49becbf21330ba2f0edc4b05f4df01623f3c82246ae23ea2c022434ef09611aa19ba35c3ecbad965af3ad9bc6c9b0d3b059c239ffbf9272d0150c151b4510d659cbd0e4a9c32945c612681b70ee4dcbeefeacde630b127115fd9af16cef4afefe611c9dfcc63e6833bf4dab79a7e1ae3f70321429557ab9da48bf93647830b5eb5780f23476d3d4d06a39ae532da5b2f30f151587eb5df19ec1acf099e1ac506e071eb52c3c3cc88ccf6622b2913acf07f1b772b5012e39173211e51773f3eb42d667fff1d902c5c87bd507837b3fd993e70ac9706a0");
|
||||
genesis.nNonce = uint256S("0000000000000000000000000000000000000000000000000000000000000006");
|
||||
genesis.nSolution = ParseHex("00596d6b34675ec5b6cde00c8c6149cd57b1159aa7401864f4812f83c5ef10f6a41645890dab4bfb97bf208c5eea90106c62e2d353f4844f1a2587a4da14e327f54e910c9eaf27057d8541cdd0cc6e8281b9a9830492b85e2c49c6c34228f140b157417d7a1e6e489c0ad515a96c50466bd6b184b631c9ae162b86d2c02b1f6e2cdc0727daabb07dc2d7fb3bce35d16699984a50a69f736196077b4c65e60b25e2f81efcc83f20db0130237474c79359126d218fc3a0d97109dbbb72733a67421964202fbb907e53d0256e70e9021e086ba802609b07f52ff0cba0f840acedcd5b0e4a9b78988102a743a4a4662aefb5e8c93a5f72d9273ff5ffd98602ed491eb812930bfdc5305eca05f7d55a91d30aa50f0ea6a4ef03efc2e4904825ff6fd08e1d73dee68031a147a745dbe26be0bf9425c757a78d27ff365d8b711a879bcf2b010deb6f19310270bd6b1ef31d27ab0183d0c712ce07f77fc475897f6a3f89c68bdea23a2a1844e0ed732c0ff1ea033ec235d4dd6a3176019202ccc418e7d4103ab8c35509733d88eab8bd7b81621910ee0d4f6c0a5d6fcc55c679de391a46ee33c7e70264ec677c4605bcfb75928e99c8392110a72cd5350c93fd68f5556e78f764815656706dc9517e4f73b216eb6c0c7048dce0724482678b501339b0b3171ead3e63d7abaa6fc1b7ecb564e16fd1c3426bd27de21203e5f49b13470342a676d11317c92add495dae964b31484265498f677dccc7a33986c17635b6c55929320fee4635aa8c2637cfa693dc723bcb37ad57bfbf1434e9ac7db0d5fb5be71314ac2cb21d5f61db1ff12703f889031396ed8d75a3a95dd86415dfd263ff1131091f07bfa9ca1aea9e46b84be070abeab0fb7d333f05b5509e74ed6bb58b8e624087d71710cb651f6a9a13ddc217354ba8219e08c4e48536e7e1c065d9da950096a655dce913878ec4e53093cf5701578f2bde402d94eb2e639f55bf07efd3cdeca23a29b38fd19e121f347bf1a05578ff4d24635d4bb702691838f2cca42bda0768e59727f94648d49cdda8de424a0398f3650d47155dac50da21dad9820feac063a99a33174462296cc7375735cfd9c7c1d484c938e299c7dc3ee288143131bbab60af230d4a4187d1ebfafa2c91f29a66392509fafea3042b97c965982140eb2219773469030159a0986f1a157fb64a25aaf9c0688973e79b45dc042e52c25ea5009d90c805f04572074335c2be9547159dbc1e15859eee935165f2b7c5b3dd89acbfd3c744d56b34afe18a734ee81894a168330ec99898e2ad042a036cccd1a36ece9c724cf476d404a65c4d8b1e2cbbe52c905b12abb5db83be05efe15723001c7a031e7e65230e2e4e4590df79e816e12fc684f51b04dc56e9d7c27da9a2cd9ead17ac1e58ae6798651f2cd80369547a0bd24f43fec3613784c0cc17bef71e4af22a2384a6728cc7fec4982c568671f12f63b0dbed8d11c0f5edcbc851991334b12da00d9cb5334f18a4f71915713cde326b93c31bd5d9c1501eb22d99b4650e087676d72ecd09dd45586561a050628365937fafa52b158cf81adce6e3cdee46e9626c85f28e0f59397f435e529ac4965d30d0afb9812d72407ec5239cfb3d56d8b6077866befb41f427c7dd7ee782c34e3d983d047edb71e48befcf582262bec7670298c66e690d5112760944486fdac7be99296e047be9369f7e555f5b06587123f541f6451cfd71e57f71173c87b51c08e80b2397f8c69dc3c7528576551ccfc6f2c7501f4df00a331855ee03e9f4ed9f021626ee3d6e36793b650336e5054904ebffedf83e367082381aee40c43422d81c0f0e4a00478673864dc31086ecb661e9dafac47e3b8697f4f52aeeefaccda3fd42f6e4194ab5186b7e");
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
assert(consensus.hashGenesisBlock == uint256S("0x03e1c4bb705c871bf9bfda3e74b7f8f86bff267993c215a89d5795e3708e5e1f"));
|
||||
assert(consensus.hashGenesisBlock == uint256S("0x05098b06c3be62b6b7ebcb2ffee3dad6989c4b613cb0be3e09f8df0e4ec65d2e"));
|
||||
|
||||
vFixedSeeds.clear();
|
||||
vSeeds.clear();
|
||||
vSeeds.push_back(CDNSSeedData("btcprivate.org", "dnsseed.testnet.btcprivate.org"));
|
||||
vSeeds.push_back(CDNSSeedData("btcprivate.co", "dnsseed.testnet1.btcprivate.co"));
|
||||
|
||||
// guarantees the first 2 characters, when base58 encoded, are "n1"
|
||||
base58Prefixes[PUBKEY_ADDRESS] = {0x19,0x57};
|
||||
|
@ -228,7 +245,7 @@ public:
|
|||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));
|
||||
|
||||
fMiningRequiresPeers = true;
|
||||
fMiningRequiresPeers = false;
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = true;
|
||||
fMineBlocksOnDemand = false;
|
||||
|
@ -242,8 +259,19 @@ public:
|
|||
0
|
||||
};
|
||||
|
||||
// ZCL + BTC -> BTCP
|
||||
nForkStartHeight = 10;
|
||||
nForkHeightRange = 300;
|
||||
nForkHeightRange = 0;
|
||||
|
||||
// Equihash 192,7
|
||||
nEquihashParamsUpdate = 30;
|
||||
nEquihashNnew = 192;
|
||||
nEquihashKnew = 7;
|
||||
|
||||
// LWMA-1
|
||||
lwmaActivationHeight = 48;
|
||||
lwmaAveragingWindow = 120;
|
||||
|
||||
}
|
||||
};
|
||||
static CTestNetParams testNetParams;
|
||||
|
@ -256,6 +284,8 @@ public:
|
|||
CRegTestParams() {
|
||||
strNetworkID = "regtest";
|
||||
strCurrencyUnits = "REG";
|
||||
consensus.coinbaseMaturity = 10;
|
||||
|
||||
consensus.fCoinbaseMustBeProtected = false;
|
||||
consensus.nSubsidySlowStartInterval = 0;
|
||||
consensus.nSubsidyHalvingInterval = 840000;
|
||||
|
@ -274,8 +304,8 @@ public:
|
|||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL;
|
||||
|
||||
consensus.nPowDifficultyBombHeight = 600000;
|
||||
consensus.nHeightDiffBombRemoved = 599999;
|
||||
consensus.nPowDifficultyBombHeight = 152;
|
||||
consensus.nHeightDiffBombRemoved = 151;
|
||||
|
||||
consensus.nUnmovedBurnHeight = 480000;
|
||||
consensus.zResetHeight = 455500;
|
||||
|
@ -315,8 +345,20 @@ public:
|
|||
0
|
||||
};
|
||||
|
||||
|
||||
// ZCL + BTC -> BTCP
|
||||
nForkStartHeight = 50;
|
||||
nForkHeightRange = 0;
|
||||
|
||||
// Equihash 192,7
|
||||
nEquihashParamsUpdate = 100;
|
||||
nEquihashNnew = 192;
|
||||
nEquihashKnew = 7;
|
||||
|
||||
// LWMA-1
|
||||
lwmaActivationHeight = 168;
|
||||
lwmaAveragingWindow = 120;
|
||||
|
||||
}
|
||||
};
|
||||
static CRegTestParams regTestParams;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "chainparamsbase.h"
|
||||
#include "checkpoints.h"
|
||||
#include "consensus/params.h"
|
||||
#include "crypto/equihash.h"
|
||||
#include "primitives/block.h"
|
||||
#include "protocol.h"
|
||||
|
||||
|
@ -62,8 +63,28 @@ public:
|
|||
bool RequireStandard() const { return fRequireStandard; }
|
||||
int64_t MaxTipAge() const { return nMaxTipAge; }
|
||||
int64_t PruneAfterHeight() const { return nPruneAfterHeight; }
|
||||
unsigned int EquihashN() const { return nEquihashN; }
|
||||
unsigned int EquihashK() const { return nEquihashK; }
|
||||
|
||||
unsigned int EquihashN(int height) const
|
||||
{
|
||||
if(height >= nEquihashParamsUpdate)
|
||||
return nEquihashNnew;
|
||||
|
||||
return nEquihashN;
|
||||
}
|
||||
|
||||
unsigned int EquihashK(int height) const
|
||||
{
|
||||
if(height >= nEquihashParamsUpdate)
|
||||
return nEquihashKnew;
|
||||
|
||||
return nEquihashK;
|
||||
}
|
||||
|
||||
unsigned int EquihashSolutionWidth(int height) const
|
||||
{
|
||||
return EhSolutionWidth(EquihashN(height), EquihashK(height));
|
||||
}
|
||||
|
||||
std::string CurrencyUnits() const { return strCurrencyUnits; }
|
||||
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
|
||||
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
|
||||
|
@ -81,6 +102,10 @@ public:
|
|||
uint64_t ForkStartHeight() const { return nForkStartHeight; };
|
||||
uint64_t ForkHeightRange() const { return nForkHeightRange; };
|
||||
|
||||
uint64_t EquihashParamsUpdate() const { return nEquihashParamsUpdate; };
|
||||
uint64_t LwmaHeight() const { return lwmaActivationHeight; };
|
||||
uint64_t LwmaAveragingWin() const { return lwmaAveragingWindow; };
|
||||
|
||||
protected:
|
||||
CChainParams() {}
|
||||
|
||||
|
@ -109,6 +134,15 @@ protected:
|
|||
|
||||
uint64_t nForkStartHeight;
|
||||
uint64_t nForkHeightRange;
|
||||
|
||||
uint64_t nEquihashParamsUpdate;
|
||||
unsigned int nEquihashNnew;
|
||||
unsigned int nEquihashKnew;
|
||||
|
||||
// LWMA-1
|
||||
uint64_t lwmaActivationHeight;
|
||||
int64_t lwmaAveragingWindow;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
|
||||
#define CLIENT_VERSION_MAJOR 1
|
||||
#define CLIENT_VERSION_MINOR 0
|
||||
#define CLIENT_VERSION_REVISION 14
|
||||
#define CLIENT_VERSION_REVISION 15
|
||||
#define CLIENT_VERSION_BUILD 50
|
||||
|
||||
//! Set to true for release, false for prerelease or test build
|
||||
|
|
|
@ -17,7 +17,7 @@ static const unsigned int MAX_BLOCK_SIGOPS = 50000;
|
|||
/** The maximum size of a transaction (network rule) */
|
||||
static const unsigned int MAX_TX_SIZE = 100000;
|
||||
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
|
||||
static const int COINBASE_MATURITY = 100;
|
||||
/** (Moved to Consensus Params) */
|
||||
|
||||
/** Flags for LockTime() */
|
||||
enum {
|
||||
|
|
|
@ -32,6 +32,8 @@ struct BIP9Deployment {
|
|||
* Parameters that influence chain consensus.
|
||||
*/
|
||||
struct Params {
|
||||
int coinbaseMaturity;
|
||||
|
||||
uint256 hashGenesisBlock;
|
||||
|
||||
bool fCoinbaseMustBeProtected;
|
||||
|
|
|
@ -35,7 +35,11 @@ int Equihash<N,K>::InitialiseState(eh_HashState& base_state)
|
|||
uint32_t le_N = htole32(N);
|
||||
uint32_t le_K = htole32(K);
|
||||
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
|
||||
memcpy(personalization, "ZcashPoW", 8);
|
||||
|
||||
if(N==192 && K==7)
|
||||
memcpy(personalization, "BTCP_PoW", 8);
|
||||
else
|
||||
memcpy(personalization, "ZcashPoW", 8);
|
||||
memcpy(personalization+8, &le_N, 4);
|
||||
memcpy(personalization+12, &le_K, 4);
|
||||
return crypto_generichash_blake2b_init_salt_personal(&base_state,
|
||||
|
@ -792,6 +796,31 @@ template bool Equihash<200,9>::OptimisedSolve(const eh_HashState& base_state,
|
|||
#endif
|
||||
template bool Equihash<200,9>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);
|
||||
|
||||
// Explicit instantiations for Equihash<192,7>
|
||||
template int Equihash<192,7>::InitialiseState(eh_HashState& base_state);
|
||||
#ifdef ENABLE_MINING
|
||||
template bool Equihash<192,7>::BasicSolve(const eh_HashState& base_state,
|
||||
const std::function<bool(std::vector<unsigned char>)> validBlock,
|
||||
const std::function<bool(EhSolverCancelCheck)> cancelled);
|
||||
template bool Equihash<192,7>::OptimisedSolve(const eh_HashState& base_state,
|
||||
const std::function<bool(std::vector<unsigned char>)> validBlock,
|
||||
const std::function<bool(EhSolverCancelCheck)> cancelled);
|
||||
#endif
|
||||
template bool Equihash<192,7>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);
|
||||
|
||||
// Explicit instantiations for Equihash<144,5>
|
||||
template int Equihash<144,5>::InitialiseState(eh_HashState& base_state);
|
||||
#ifdef ENABLE_MINING
|
||||
template bool Equihash<144,5>::BasicSolve(const eh_HashState& base_state,
|
||||
const std::function<bool(std::vector<unsigned char>)> validBlock,
|
||||
const std::function<bool(EhSolverCancelCheck)> cancelled);
|
||||
template bool Equihash<144,5>::OptimisedSolve(const eh_HashState& base_state,
|
||||
const std::function<bool(std::vector<unsigned char>)> validBlock,
|
||||
const std::function<bool(EhSolverCancelCheck)> cancelled);
|
||||
#endif
|
||||
template bool Equihash<144,5>::IsValidSolution(const eh_HashState& base_state, std::vector<unsigned char> soln);
|
||||
|
||||
|
||||
// Explicit instantiations for Equihash<96,5>
|
||||
template int Equihash<96,5>::InitialiseState(eh_HashState& base_state);
|
||||
#ifdef ENABLE_MINING
|
||||
|
|
|
@ -199,12 +199,19 @@ static Equihash<96,3> Eh96_3;
|
|||
static Equihash<200,9> Eh200_9;
|
||||
static Equihash<96,5> Eh96_5;
|
||||
static Equihash<48,5> Eh48_5;
|
||||
static Equihash<144,5> Eh144_5;
|
||||
static Equihash<192,7> Eh192_7;
|
||||
|
||||
|
||||
#define EhInitialiseState(n, k, base_state) \
|
||||
if (n == 96 && k == 3) { \
|
||||
Eh96_3.InitialiseState(base_state); \
|
||||
} else if (n == 200 && k == 9) { \
|
||||
Eh200_9.InitialiseState(base_state); \
|
||||
} else if (n == 192 && k == 7) { \
|
||||
Eh192_7.InitialiseState(base_state); \
|
||||
} else if (n == 144 && k == 5) { \
|
||||
Eh144_5.InitialiseState(base_state); \
|
||||
} else if (n == 96 && k == 5) { \
|
||||
Eh96_5.InitialiseState(base_state); \
|
||||
} else if (n == 48 && k == 5) { \
|
||||
|
@ -222,6 +229,10 @@ inline bool EhBasicSolve(unsigned int n, unsigned int k, const eh_HashState& bas
|
|||
return Eh96_3.BasicSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 200 && k == 9) {
|
||||
return Eh200_9.BasicSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 192 && k == 7) {
|
||||
return Eh192_7.BasicSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 144 && k == 5) {
|
||||
return Eh144_5.BasicSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 96 && k == 5) {
|
||||
return Eh96_5.BasicSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 48 && k == 5) {
|
||||
|
@ -246,6 +257,10 @@ inline bool EhOptimisedSolve(unsigned int n, unsigned int k, const eh_HashState&
|
|||
return Eh96_3.OptimisedSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 200 && k == 9) {
|
||||
return Eh200_9.OptimisedSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 192 && k == 7) {
|
||||
return Eh192_7.OptimisedSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 144 && k == 5) {
|
||||
return Eh144_5.OptimisedSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 96 && k == 5) {
|
||||
return Eh96_5.OptimisedSolve(base_state, validBlock, cancelled);
|
||||
} else if (n == 48 && k == 5) {
|
||||
|
@ -268,6 +283,10 @@ inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const
|
|||
ret = Eh96_3.IsValidSolution(base_state, soln); \
|
||||
} else if (n == 200 && k == 9) { \
|
||||
ret = Eh200_9.IsValidSolution(base_state, soln); \
|
||||
} else if (n == 192 && k == 7) { \
|
||||
ret = Eh192_7.IsValidSolution(base_state, soln); \
|
||||
} else if (n == 144 && k == 5) { \
|
||||
ret = Eh144_5.IsValidSolution(base_state, soln); \
|
||||
} else if (n == 96 && k == 5) { \
|
||||
ret = Eh96_5.IsValidSolution(base_state, soln); \
|
||||
} else if (n == 48 && k == 5) { \
|
||||
|
@ -276,4 +295,26 @@ inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const
|
|||
throw std::invalid_argument("Unsupported Equihash parameters"); \
|
||||
}
|
||||
|
||||
inline unsigned int EhSolutionWidth(int n, int k)
|
||||
{
|
||||
unsigned int ret;
|
||||
if (n == 96 && k == 3) {
|
||||
ret = Eh96_3.SolutionWidth;
|
||||
} else if (n == 200 && k == 9) {
|
||||
ret = Eh200_9.SolutionWidth;
|
||||
} else if (n == 192 && k == 7) {
|
||||
ret = Eh192_7.SolutionWidth;
|
||||
} else if (n == 144 && k == 5) {
|
||||
ret = Eh144_5.SolutionWidth;
|
||||
} else if (n == 96 && k == 5) {
|
||||
ret = Eh96_5.SolutionWidth;
|
||||
} else if (n == 48 && k == 5) {
|
||||
ret = Eh48_5.SolutionWidth;
|
||||
} else {
|
||||
throw std::invalid_argument("Unsupported Equihash parameters");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // BITCOIN_EQUIHASH_H
|
||||
|
|
33
src/main.cpp
33
src/main.cpp
|
@ -1695,7 +1695,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
|
|||
|
||||
if (coins->IsCoinBase()) {
|
||||
// Ensure that coinbases are matured
|
||||
if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) {
|
||||
if (nSpendHeight - coins->nHeight < consensusParams.coinbaseMaturity) {
|
||||
return state.Invalid(
|
||||
error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
|
||||
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
|
||||
|
@ -3128,9 +3128,21 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
|
|||
REJECT_INVALID, "version-too-low");
|
||||
|
||||
// Check Equihash solution is valid
|
||||
if (fCheckPOW && !CheckEquihashSolution(&block, Params()))
|
||||
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
|
||||
REJECT_INVALID, "invalid-solution");
|
||||
if (fCheckPOW) {
|
||||
const CChainParams& chainparams = Params();
|
||||
|
||||
int oldSize = chainparams.EquihashSolutionWidth(chainparams.EquihashParamsUpdate() - 1);
|
||||
int newSize = chainparams.EquihashSolutionWidth(chainparams.EquihashParamsUpdate());
|
||||
|
||||
if (block.nSolution.size() != oldSize && block.nSolution.size() != newSize)
|
||||
return state.DoS(100, error("CheckBlockHeader(): Equihash solution has invalid size have %d need [%d, %d]",
|
||||
block.nSolution.size(), oldSize, newSize),
|
||||
REJECT_INVALID, "invalid-solution-size");
|
||||
|
||||
if (!CheckEquihashSolution(&block, chainparams))
|
||||
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
|
||||
REJECT_INVALID, "invalid-solution");
|
||||
}
|
||||
|
||||
// Check proof of work matches claimed amount
|
||||
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))
|
||||
|
@ -3138,6 +3150,7 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
|
|||
REJECT_INVALID, "high-hash");
|
||||
|
||||
// Check timestamp
|
||||
const CChainParams& chainparams = Params();
|
||||
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
|
||||
return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),
|
||||
REJECT_INVALID, "time-too-new");
|
||||
|
@ -3220,7 +3233,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev)
|
||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev, bool fCheckPow)
|
||||
{
|
||||
const CChainParams& chainParams = Params();
|
||||
const Consensus::Params& consensusParams = chainParams.GetConsensus();
|
||||
|
@ -3245,7 +3258,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
|||
|
||||
// Check proof of work
|
||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
|
||||
return state.DoS(100, error("%s: incorrect proof of work", __func__),
|
||||
return state.DoS(100, error("%s: incorrect proof of work (nHeight: %d, hash: %s)", __func__, nHeight, hash.ToString()),
|
||||
REJECT_INVALID, "bad-diffbits");
|
||||
|
||||
// Check timestamp against prev
|
||||
|
@ -3253,6 +3266,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
|||
return state.Invalid(error("%s: block's timestamp is too early", __func__),
|
||||
REJECT_INVALID, "time-too-old");
|
||||
|
||||
// Check that equihash solution has the proper length
|
||||
if (fCheckPow && block.nSolution.size() != chainParams.EquihashSolutionWidth(nHeight))
|
||||
return state.Invalid(error("%s: incorrect equihash solution size have %d need %d",
|
||||
__func__, block.nSolution.size(), chainParams.EquihashSolutionWidth(nHeight)),
|
||||
REJECT_INVALID, "equihash-solution-size");
|
||||
|
||||
if (fCheckpointsEnabled)
|
||||
{
|
||||
// Don't accept any forks from the main chain prior to last checkpoint
|
||||
|
@ -3567,7 +3586,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
|
|||
auto verifier = libzcash::ProofVerifier::Disabled();
|
||||
|
||||
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||
if (!ContextualCheckBlockHeader(block, state, pindexPrev))
|
||||
if (!ContextualCheckBlockHeader(block, state, pindexPrev, fCheckPOW))
|
||||
return false;
|
||||
|
||||
if (!CheckBlock(block, state, verifier, fCheckPOW, fCheckMerkleRoot))
|
||||
|
|
|
@ -429,7 +429,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
|||
bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
||||
/** Context-dependent validity checks */
|
||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev);
|
||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev, bool fCheckPow = true);
|
||||
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev);
|
||||
|
||||
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
|
||||
|
@ -587,7 +587,7 @@ std::string GetUTXOFileName(int nHeight);
|
|||
//
|
||||
inline bool isForkBlock(int nHeight)
|
||||
{
|
||||
return (nHeight > forkStartHeight && nHeight <= forkStartHeight + forkHeightRange);
|
||||
return (forkHeightRange > 0 && nHeight > forkStartHeight && nHeight <= forkStartHeight + forkHeightRange);
|
||||
}
|
||||
|
||||
inline bool looksLikeForkBlockHeader(const CBlockHeader& header)
|
||||
|
|
|
@ -298,7 +298,7 @@ int printMetrics(size_t cols, bool mining)
|
|||
if ((height > 0) && (height <= consensusParams.GetLastFoundersRewardBlockHeight())) {
|
||||
subsidy -= subsidy/5;
|
||||
}
|
||||
if (std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) {
|
||||
if (std::max(0, consensusParams.coinbaseMaturity - (tipHeight - height)) > 0) {
|
||||
immature += subsidy;
|
||||
} else {
|
||||
mature += subsidy;
|
||||
|
|
|
@ -692,11 +692,17 @@ void static BitcoinMiner()
|
|||
// Each thread has its own counter
|
||||
unsigned int nExtraNonce = 0;
|
||||
|
||||
unsigned int n = chainparams.EquihashN();
|
||||
unsigned int k = chainparams.EquihashK();
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
|
||||
unsigned int n = chainparams.EquihashN(pindexPrev->nHeight + 1);
|
||||
unsigned int k = chainparams.EquihashK(pindexPrev->nHeight + 1);
|
||||
|
||||
std::string solver = GetArg("-equihashsolver", "default");
|
||||
// TODO: parameterize n & k tromp solver and remove temporary workaround below
|
||||
if (n == 200 && k == 9) solver = "default";
|
||||
if (n == 192 && k == 7) solver = "tromp";
|
||||
assert(solver == "tromp" || solver == "default");
|
||||
|
||||
LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k);
|
||||
|
||||
std::mutex m_cs;
|
||||
|
@ -731,7 +737,7 @@ void static BitcoinMiner()
|
|||
miningTimer.start();
|
||||
}
|
||||
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
pindexPrev = chainActive.Tip();
|
||||
CBlock *pblock = nullptr;
|
||||
unsigned int nTransactionsUpdatedLast = 0;
|
||||
|
||||
|
@ -740,6 +746,9 @@ void static BitcoinMiner()
|
|||
//
|
||||
unique_ptr<CBlockTemplate> pblocktemplate;
|
||||
|
||||
n = chainparams.EquihashN(pindexPrev->nHeight + 1);
|
||||
k = chainparams.EquihashK(pindexPrev->nHeight + 1);
|
||||
|
||||
bool isNextBlockFork = isForkBlock(pindexPrev->nHeight+1);
|
||||
|
||||
if (isNextBlockFork) {
|
||||
|
@ -827,8 +836,8 @@ void static BitcoinMiner()
|
|||
pblock->nNonce.size());
|
||||
|
||||
// (x_1, x_2, ...) = A(I, V, n, k)
|
||||
LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",
|
||||
solver, pblock->nNonce.ToString());
|
||||
LogPrint("pow", "Running Equihash solver \"%s\" (%u,%u) with nNonce = %s\n",
|
||||
solver,n, k, pblock->nNonce.ToString());
|
||||
|
||||
std::function<bool(std::vector<unsigned char>)> validBlock =
|
||||
[&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams
|
||||
|
@ -877,6 +886,13 @@ void static BitcoinMiner()
|
|||
return cancelSolver;
|
||||
};
|
||||
|
||||
|
||||
// TODO: parameterize n & k tromp solver and remove temporary workaround below
|
||||
if (n == 200 && k == 9) solver = "default";
|
||||
if (n == 192 && k == 7) solver = "tromp";
|
||||
assert(solver == "tromp" || solver == "default");
|
||||
|
||||
|
||||
// TODO: factor this out into a function with the same API for each solver.
|
||||
if (solver == "tromp") {
|
||||
// Create solver and initialize it.
|
||||
|
|
150
src/pow.cpp
150
src/pow.cpp
|
@ -21,12 +21,30 @@
|
|||
#include "librustzcash.h"
|
||||
#endif // ENABLE_RUST
|
||||
|
||||
/**
|
||||
* Manually increase difficulty by a multiplier. Note that because of the use of compact bits, this will
|
||||
* only be an approx increase, not a 100% precise increase.
|
||||
*/
|
||||
unsigned int IncreaseDifficultyBy(unsigned int nBits, int64_t multiplier, const Consensus::Params& params) {
|
||||
arith_uint256 target;
|
||||
target.SetCompact(nBits);
|
||||
target /= multiplier;
|
||||
const arith_uint256 pow_limit = UintToArith256(params.powLimit);
|
||||
if (target > pow_limit) {
|
||||
target = pow_limit;
|
||||
}
|
||||
return target.GetCompact();
|
||||
}
|
||||
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
|
||||
{
|
||||
|
||||
const CChainParams& chainparams = Params();
|
||||
|
||||
int nHeight = pindexLast->nHeight + 1;
|
||||
|
||||
arith_uint256 proofOfWorkLimit;
|
||||
if(!isForkEnabled(nHeight))
|
||||
if (!isForkEnabled(nHeight))
|
||||
proofOfWorkLimit = UintToArith256(params.prePowLimit);
|
||||
else
|
||||
proofOfWorkLimit = UintToArith256(params.powLimit);
|
||||
|
@ -37,14 +55,41 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||
if (pindexLast == NULL)
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
// right at fork
|
||||
else if(isForkBlock(nHeight) && !isForkBlock(nHeight - params.nPowAveragingWindow))
|
||||
return nProofOfWorkLimit;
|
||||
// For upgrade mainnet forks, we'll adjust the difficulty down for the first nPowAveragingWindow blocks
|
||||
if (nHeight >= chainparams.EquihashParamsUpdate() &&
|
||||
nHeight < chainparams.EquihashParamsUpdate() + params.nPowAveragingWindow) {
|
||||
|
||||
if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 12) {
|
||||
// If > 30 mins, allow min difficulty
|
||||
LogPrintf("HC Returning level 1 difficulty %i at height %i\n", nProofOfWorkLimit, nHeight);
|
||||
return nProofOfWorkLimit;
|
||||
} else if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 6) {
|
||||
// If > 15 mins, allow low estimate difficulty
|
||||
unsigned int difficulty = IncreaseDifficultyBy(nProofOfWorkLimit, 128, params);
|
||||
LogPrintf("HC Returning level 2 difficulty %i at height %i\n", nProofOfWorkLimit, nHeight);
|
||||
return difficulty;
|
||||
} else if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 2) {
|
||||
// If > 5 mins, allow high estimate difficulty
|
||||
unsigned int difficulty = IncreaseDifficultyBy(nProofOfWorkLimit, 256, params);
|
||||
LogPrintf("HC Returning level 3 difficulty %i at height %i\n", nProofOfWorkLimit, nHeight);
|
||||
return difficulty;
|
||||
} else {
|
||||
// If < 5 mins, fall through, and return the normal difficulty.
|
||||
LogPrintf("HC Falling through at height %i\n", nHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// LWMA-1 activated
|
||||
if (pindexLast->nHeight > chainparams.LwmaHeight())
|
||||
return LwmaCalculateNextWorkRequired(pindexLast, params);
|
||||
|
||||
// right post fork
|
||||
else if(!isForkBlock(nHeight) && isForkBlock(nHeight - params.nPowAveragingWindow))
|
||||
if (!isForkBlock(nHeight) && isForkBlock(nHeight - params.nPowAveragingWindow))
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
// right at fork
|
||||
if (isForkBlock(nHeight) && !isForkBlock(nHeight - params.nPowAveragingWindow))
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
|
||||
// Find the first block in the averaging interval
|
||||
const CBlockIndex* pindexFirst = pindexLast;
|
||||
|
@ -66,6 +111,83 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||
return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params, proofOfWorkLimit, isFork);
|
||||
}
|
||||
|
||||
// LWMA-1 for BTC/Zcash clones
|
||||
// LWMA has the best response*stability. It rises slowly & drops fast when needed.
|
||||
// Copyright (c) 2017-2018 The Bitcoin Gold developers
|
||||
// Copyright (c) 2018-2019 Zawy
|
||||
// Copyright (c) 2018 iamstenman (Microbitcoin)
|
||||
// MIT License
|
||||
// Algorithm by Zawy, a modification of WT-144 by Tom Harding
|
||||
// For any changes, patches, updates, etc see
|
||||
// https://github.com/zawy12/difficulty-algorithms/issues/3#issuecomment-442129791
|
||||
// FTL should be lowered to about N*T/20.
|
||||
// FTL in BTC clones is MAX_FUTURE_BLOCK_TIME in chain.h.
|
||||
// FTL in Zcash & Dash clones need to change the 2*60*60 here:
|
||||
// if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60)
|
||||
// which is around line 3700 in main.cpp in ZEC and validation.cpp in Dash
|
||||
// If your coin uses network time instead of node local time, lowering FTL < about 125% of the
|
||||
// "revert to node time" rule (70 minutes in BCH, ZEC, & BTC) allows 33% Sybil attack,
|
||||
// so revert rule must be ~ FTL/2 instead of 70 minutes. See:
|
||||
// https://github.com/zcash/zcash/issues/4021
|
||||
|
||||
unsigned int LwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
// For T=600, 300, 150 (ie 10, 5, 2.5min blocks) use approximately N=60, 90, 120
|
||||
const int64_t T = params.nPowTargetSpacing;
|
||||
const int64_t N = chainparams.LwmaAveragingWin();
|
||||
|
||||
// Define a k that will be used to get a proper average after weighting the solvetimes.
|
||||
const int64_t k = N * (N + 1) * T / 2;
|
||||
|
||||
const int64_t height = pindexLast->nHeight;
|
||||
const arith_uint256 powLimit = UintToArith256(params.powLimit);
|
||||
|
||||
// 'New' coins should just give away first N blocks before using this algorithm.
|
||||
if (height > chainparams.LwmaHeight() && height <= chainparams.LwmaHeight() + N) { return powLimit.GetCompact(); }
|
||||
|
||||
arith_uint256 avgTarget, nextTarget;
|
||||
int64_t thisTimestamp, previousTimestamp;
|
||||
int64_t sumWeightedSolvetimes = 0, j = 0;
|
||||
|
||||
const CBlockIndex* blockPreviousTimestamp = pindexLast->GetAncestor(height - N);
|
||||
previousTimestamp = blockPreviousTimestamp->GetBlockTime();
|
||||
|
||||
// Loop through N most recent blocks.
|
||||
for (int64_t i = height - N + 1; i <= height; i++) {
|
||||
const CBlockIndex* block = pindexLast->GetAncestor(i);
|
||||
|
||||
// Prevent solvetimes from being negative in a safe way. It must be done like this.
|
||||
// In particular, do not attempt anything like if(solvetime < 0) {solvetime=0;}
|
||||
// The +1 ensures new coins do not calculate nextTarget = 0.
|
||||
thisTimestamp = (block->GetBlockTime() > previousTimestamp) ?
|
||||
block->GetBlockTime() : previousTimestamp + 1;
|
||||
|
||||
// A 6*T limit will prevent large drops in difficulty from long solvetimes.
|
||||
int64_t solvetime = std::min(6 * T, thisTimestamp - previousTimestamp);
|
||||
|
||||
// The following is part of "preventing negative solvetimes".
|
||||
previousTimestamp = thisTimestamp;
|
||||
|
||||
// Give linearly higher weight to more recent solvetimes.
|
||||
j++;
|
||||
sumWeightedSolvetimes += solvetime * j;
|
||||
|
||||
arith_uint256 target;
|
||||
target.SetCompact(block->nBits);
|
||||
avgTarget += target / N / k; // Dividing by k here prevents an overflow below.
|
||||
}
|
||||
// Desired equation in next line was nextTarget = avgTarget * sumWeightSolvetimes / k
|
||||
// but 1/k was moved to line above to prevent overflow in new coins
|
||||
|
||||
nextTarget = avgTarget * sumWeightedSolvetimes;
|
||||
|
||||
if (nextTarget > powLimit) { nextTarget = powLimit; }
|
||||
|
||||
return nextTarget.GetCompact();
|
||||
}
|
||||
|
||||
// (Original)
|
||||
unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
||||
int64_t nLastBlockTime, int64_t nFirstBlockTime,
|
||||
const Consensus::Params& params, const arith_uint256 bnPowLimit, bool isFork)
|
||||
|
@ -101,8 +223,20 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
|||
|
||||
bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
|
||||
{
|
||||
unsigned int n = params.EquihashN();
|
||||
unsigned int k = params.EquihashK();
|
||||
uint64_t forkHeight = params.EquihashParamsUpdate();
|
||||
unsigned int solution_size = pblock->nSolution.size();
|
||||
|
||||
unsigned int n;
|
||||
unsigned int k;
|
||||
if (solution_size == params.EquihashSolutionWidth(forkHeight)) {
|
||||
n = params.EquihashN(forkHeight);
|
||||
k = params.EquihashK(forkHeight);
|
||||
} else if (forkHeight > 0 && solution_size == params.EquihashSolutionWidth(forkHeight - 1)) {
|
||||
n = params.EquihashN(forkHeight - 1);
|
||||
k = params.EquihashK(forkHeight - 1);
|
||||
} else {
|
||||
return error("CheckEquihashsolution(): invalid solution size");
|
||||
}
|
||||
|
||||
// Hash state
|
||||
crypto_generichash_blake2b_state state;
|
||||
|
|
|
@ -16,7 +16,10 @@ class CChainParams;
|
|||
class uint256;
|
||||
class arith_uint256;
|
||||
|
||||
unsigned int IncreaseDifficultyBy(unsigned int nBits, int64_t multiplier, const Consensus::Params& params);
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params&);
|
||||
unsigned int LwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
|
||||
|
||||
unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
||||
int64_t nLastBlockTime, int64_t nFirstBlockTime,
|
||||
const Consensus::Params&, const arith_uint256, bool isFork = false);
|
||||
|
|
|
@ -17,11 +17,11 @@ typedef unsigned char uchar;
|
|||
// algorithm parameters, prefixed with W to reduce include file conflicts
|
||||
|
||||
#ifndef WN
|
||||
#define WN 200
|
||||
#define WN 192
|
||||
#endif
|
||||
|
||||
#ifndef WK
|
||||
#define WK 9
|
||||
#define WK 7
|
||||
#endif
|
||||
|
||||
#define NDIGITS (WK+1)
|
||||
|
@ -65,7 +65,7 @@ int verifyrec(const crypto_generichash_blake2b_state *ctx, u32 *indices, uchar *
|
|||
return vrf1;
|
||||
for (int i=0; i < WN/8; i++)
|
||||
hash[i] = hash0[i] ^ hash1[i];
|
||||
int i, b = r * DIGITBITS;
|
||||
int i, b = r < WK ? r * DIGITBITS : WN;
|
||||
for (i = 0; i < b/8; i++)
|
||||
if (hash[i])
|
||||
return POW_NONZERO_XOR;
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef u32 au32;
|
|||
#endif
|
||||
|
||||
#ifndef RESTBITS
|
||||
#define RESTBITS 8
|
||||
#define RESTBITS 4
|
||||
#endif
|
||||
|
||||
// 2_log of number of buckets
|
||||
|
@ -57,7 +57,6 @@ static const u32 NBUCKETS = 1<<BUCKBITS;
|
|||
// 2_log of number of slots per bucket
|
||||
static const u32 SLOTBITS = RESTBITS+1+1;
|
||||
static const u32 SLOTRANGE = 1<<SLOTBITS;
|
||||
static const u32 SLOTMSB = 1<<(SLOTBITS-1);
|
||||
// number of slots per bucket
|
||||
static const u32 NSLOTS = SLOTRANGE * SAVEMEM;
|
||||
// number of per-xhash slots
|
||||
|
@ -74,52 +73,31 @@ static const u32 MAXSOLS = 8;
|
|||
// tree node identifying its children as two different slots in
|
||||
// a bucket on previous layer with the same rest bits (x-tra hash)
|
||||
struct tree {
|
||||
u32 bid_s0_s1; // manual bitfields
|
||||
u32 bid_s0_s1; // manual bitfields
|
||||
|
||||
tree(const u32 idx) {
|
||||
bid_s0_s1 = idx;
|
||||
}
|
||||
tree(const u32 bid, const u32 s0, const u32 s1) {
|
||||
#ifdef SLOTDIFF
|
||||
u32 ds10 = (s1 - s0) & SLOTMASK;
|
||||
if (ds10 & SLOTMSB) {
|
||||
bid_s0_s1 = (((bid << SLOTBITS) | s1) << (SLOTBITS-1)) | (SLOTMASK & ~ds10);
|
||||
} else {
|
||||
bid_s0_s1 = (((bid << SLOTBITS) | s0) << (SLOTBITS-1)) | (ds10 - 1);
|
||||
tree(const u32 idx) {
|
||||
bid_s0_s1 = idx;
|
||||
}
|
||||
tree(const u32 bid, const u32 s0, const u32 s1) {
|
||||
bid_s0_s1 = (((bid << SLOTBITS) | s0) << SLOTBITS) | s1;
|
||||
}
|
||||
u32 getindex() const {
|
||||
return bid_s0_s1;
|
||||
}
|
||||
u32 bucketid() const {
|
||||
return bid_s0_s1 >> (2 * SLOTBITS);
|
||||
}
|
||||
u32 slotid0() const {
|
||||
return (bid_s0_s1 >> SLOTBITS) & SLOTMASK;
|
||||
}
|
||||
u32 slotid1() const {
|
||||
return bid_s0_s1 & SLOTMASK;
|
||||
}
|
||||
#else
|
||||
bid_s0_s1 = (((bid << SLOTBITS) | s0) << SLOTBITS) | s1;
|
||||
#endif
|
||||
}
|
||||
u32 getindex() const {
|
||||
return bid_s0_s1;
|
||||
}
|
||||
u32 bucketid() const {
|
||||
#ifdef SLOTDIFF
|
||||
return bid_s0_s1 >> (2 * SLOTBITS - 1);
|
||||
#else
|
||||
return bid_s0_s1 >> (2 * SLOTBITS);
|
||||
#endif
|
||||
}
|
||||
u32 slotid0() const {
|
||||
#ifdef SLOTDIFF
|
||||
return (bid_s0_s1 >> (SLOTBITS-1)) & SLOTMASK;
|
||||
#else
|
||||
return (bid_s0_s1 >> SLOTBITS) & SLOTMASK;
|
||||
#endif
|
||||
}
|
||||
u32 slotid1() const {
|
||||
#ifdef SLOTDIFF
|
||||
return (slotid0() + 1 + (bid_s0_s1 & (SLOTMASK>>1))) & SLOTMASK;
|
||||
#else
|
||||
return bid_s0_s1 & SLOTMASK;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
union hashunit {
|
||||
u32 word;
|
||||
uchar bytes[sizeof(u32)];
|
||||
u32 word;
|
||||
uchar bytes[sizeof(u32)];
|
||||
};
|
||||
|
||||
#define WORDS(bits) ((bits + 31) / 32)
|
||||
|
@ -127,13 +105,13 @@ union hashunit {
|
|||
#define HASHWORDS1 WORDS(WN - 2*DIGITBITS + RESTBITS)
|
||||
|
||||
struct slot0 {
|
||||
tree attr;
|
||||
hashunit hash[HASHWORDS0];
|
||||
tree attr;
|
||||
hashunit hash[HASHWORDS0];
|
||||
};
|
||||
|
||||
struct slot1 {
|
||||
tree attr;
|
||||
hashunit hash[HASHWORDS1];
|
||||
tree attr;
|
||||
hashunit hash[HASHWORDS1];
|
||||
};
|
||||
|
||||
// a bucket is NSLOTS treenodes
|
||||
|
@ -146,25 +124,25 @@ typedef bucket1 digit1[NBUCKETS];
|
|||
|
||||
// size (in bytes) of hash in round 0 <= r < WK
|
||||
u32 hashsize(const u32 r) {
|
||||
const u32 hashbits = WN - (r+1) * DIGITBITS + RESTBITS;
|
||||
return (hashbits + 7) / 8;
|
||||
const u32 hashbits = WN - (r+1) * DIGITBITS + RESTBITS;
|
||||
return (hashbits + 7) / 8;
|
||||
}
|
||||
|
||||
u32 hashwords(u32 bytes) {
|
||||
return (bytes + 3) / 4;
|
||||
return (bytes + 3) / 4;
|
||||
}
|
||||
|
||||
// manages hash and tree data
|
||||
struct htalloc {
|
||||
u32 *heap0;
|
||||
u32 *heap1;
|
||||
bucket0 *trees0[(WK+1)/2];
|
||||
bucket1 *trees1[WK/2];
|
||||
u32 alloced;
|
||||
htalloc() {
|
||||
alloced = 0;
|
||||
}
|
||||
void alloctrees() {
|
||||
u32 *heap0;
|
||||
u32 *heap1;
|
||||
bucket0 *trees0[(WK+1)/2];
|
||||
bucket1 *trees1[WK/2];
|
||||
u32 alloced;
|
||||
htalloc() {
|
||||
alloced = 0;
|
||||
}
|
||||
void alloctrees() {
|
||||
// optimize xenoncat's fixed memory layout, avoiding any waste
|
||||
// digit trees hashes trees hashes
|
||||
// 0 0 A A A A A A . . . . . .
|
||||
|
@ -176,123 +154,123 @@ struct htalloc {
|
|||
// 6 0 2 4 6 . G G 1 3 5 F F F
|
||||
// 7 0 2 4 6 . G G 1 3 5 7 H H
|
||||
// 8 0 2 4 6 8 . I 1 3 5 7 H H
|
||||
assert(DIGITBITS >= 16); // ensures hashes shorten by 1 unit every 2 digits
|
||||
heap0 = (u32 *)alloc(1, sizeof(digit0));
|
||||
heap1 = (u32 *)alloc(1, sizeof(digit1));
|
||||
for (int r=0; r<WK; r++)
|
||||
if ((r&1) == 0)
|
||||
trees0[r/2] = (bucket0 *)(heap0 + r/2);
|
||||
else
|
||||
trees1[r/2] = (bucket1 *)(heap1 + r/2);
|
||||
}
|
||||
void dealloctrees() {
|
||||
free(heap0);
|
||||
free(heap1);
|
||||
}
|
||||
void *alloc(const u32 n, const u32 sz) {
|
||||
void *mem = calloc(n, sz);
|
||||
assert(mem);
|
||||
alloced += n * sz;
|
||||
return mem;
|
||||
}
|
||||
assert(DIGITBITS >= 16); // ensures hashes shorten by 1 unit every 2 digits
|
||||
heap0 = (u32 *)alloc(1, sizeof(digit0));
|
||||
heap1 = (u32 *)alloc(1, sizeof(digit1));
|
||||
for (int r=0; r<WK; r++)
|
||||
if ((r&1) == 0)
|
||||
trees0[r/2] = (bucket0 *)(heap0 + r/2);
|
||||
else
|
||||
trees1[r/2] = (bucket1 *)(heap1 + r/2);
|
||||
}
|
||||
void dealloctrees() {
|
||||
free(heap0);
|
||||
free(heap1);
|
||||
}
|
||||
void *alloc(const u32 n, const u32 sz) {
|
||||
void *mem = calloc(n, sz);
|
||||
assert(mem);
|
||||
alloced += n * sz;
|
||||
return mem;
|
||||
}
|
||||
};
|
||||
|
||||
typedef au32 bsizes[NBUCKETS];
|
||||
|
||||
u32 min(const u32 a, const u32 b) {
|
||||
return a < b ? a : b;
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
struct equi {
|
||||
crypto_generichash_blake2b_state blake_ctx;
|
||||
htalloc hta;
|
||||
bsizes *nslots; // PUT IN BUCKET STRUCT
|
||||
proof *sols;
|
||||
au32 nsols;
|
||||
u32 nthreads;
|
||||
u32 xfull;
|
||||
u32 hfull;
|
||||
u32 bfull;
|
||||
pthread_barrier_t barry;
|
||||
equi(const u32 n_threads) {
|
||||
assert(sizeof(hashunit) == 4);
|
||||
nthreads = n_threads;
|
||||
const int err = pthread_barrier_init(&barry, NULL, nthreads);
|
||||
assert(!err);
|
||||
hta.alloctrees();
|
||||
nslots = (bsizes *)hta.alloc(2 * NBUCKETS, sizeof(au32));
|
||||
sols = (proof *)hta.alloc(MAXSOLS, sizeof(proof));
|
||||
}
|
||||
~equi() {
|
||||
hta.dealloctrees();
|
||||
free(nslots);
|
||||
free(sols);
|
||||
}
|
||||
void setstate(const crypto_generichash_blake2b_state *ctx) {
|
||||
blake_ctx = *ctx;
|
||||
memset(nslots, 0, NBUCKETS * sizeof(au32)); // only nslots[0] needs zeroing
|
||||
nsols = 0;
|
||||
}
|
||||
u32 getslot(const u32 r, const u32 bucketi) {
|
||||
#ifdef EQUIHASH_TROMP_ATOMIC
|
||||
return std::atomic_fetch_add_explicit(&nslots[r&1][bucketi], 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
return nslots[r&1][bucketi]++;
|
||||
#endif
|
||||
}
|
||||
u32 getnslots(const u32 r, const u32 bid) { // SHOULD BE METHOD IN BUCKET STRUCT
|
||||
au32 &nslot = nslots[r&1][bid];
|
||||
const u32 n = min(nslot, NSLOTS);
|
||||
nslot = 0;
|
||||
return n;
|
||||
}
|
||||
void orderindices(u32 *indices, u32 size) {
|
||||
if (indices[0] > indices[size]) {
|
||||
for (u32 i=0; i < size; i++) {
|
||||
const u32 tmp = indices[i];
|
||||
indices[i] = indices[size+i];
|
||||
indices[size+i] = tmp;
|
||||
}
|
||||
crypto_generichash_blake2b_state blake_ctx;
|
||||
htalloc hta;
|
||||
bsizes *nslots; // PUT IN BUCKET STRUCT
|
||||
proof *sols;
|
||||
au32 nsols;
|
||||
u32 nthreads;
|
||||
u32 xfull;
|
||||
u32 hfull;
|
||||
u32 bfull;
|
||||
pthread_barrier_t barry;
|
||||
equi(const u32 n_threads) {
|
||||
assert(sizeof(hashunit) == 4);
|
||||
nthreads = n_threads;
|
||||
const int err = pthread_barrier_init(&barry, NULL, nthreads);
|
||||
assert(!err);
|
||||
hta.alloctrees();
|
||||
nslots = (bsizes *)hta.alloc(2 * NBUCKETS, sizeof(au32));
|
||||
sols = (proof *)hta.alloc(MAXSOLS, sizeof(proof));
|
||||
}
|
||||
}
|
||||
void listindices0(u32 r, const tree t, u32 *indices) {
|
||||
if (r == 0) {
|
||||
*indices = t.getindex();
|
||||
return;
|
||||
~equi() {
|
||||
hta.dealloctrees();
|
||||
free(nslots);
|
||||
free(sols);
|
||||
}
|
||||
const bucket1 &buck = hta.trees1[--r/2][t.bucketid()];
|
||||
const u32 size = 1 << r;
|
||||
u32 *indices1 = indices + size;
|
||||
listindices1(r, buck[t.slotid0()].attr, indices);
|
||||
listindices1(r, buck[t.slotid1()].attr, indices1);
|
||||
orderindices(indices, size);
|
||||
}
|
||||
void listindices1(u32 r, const tree t, u32 *indices) {
|
||||
const bucket0 &buck = hta.trees0[--r/2][t.bucketid()];
|
||||
const u32 size = 1 << r;
|
||||
u32 *indices1 = indices + size;
|
||||
listindices0(r, buck[t.slotid0()].attr, indices);
|
||||
listindices0(r, buck[t.slotid1()].attr, indices1);
|
||||
orderindices(indices, size);
|
||||
}
|
||||
void candidate(const tree t) {
|
||||
proof prf;
|
||||
listindices1(WK, t, prf); // assume WK odd
|
||||
qsort(prf, PROOFSIZE, sizeof(u32), &compu32);
|
||||
for (u32 i=1; i<PROOFSIZE; i++)
|
||||
if (prf[i] <= prf[i-1])
|
||||
return;
|
||||
void setstate(const crypto_generichash_blake2b_state *ctx) {
|
||||
blake_ctx = *ctx;
|
||||
memset(nslots, 0, NBUCKETS * sizeof(au32)); // only nslots[0] needs zeroing
|
||||
nsols = 0;
|
||||
}
|
||||
u32 getslot(const u32 r, const u32 bucketi) {
|
||||
#ifdef EQUIHASH_TROMP_ATOMIC
|
||||
u32 soli = std::atomic_fetch_add_explicit(&nsols, 1U, std::memory_order_relaxed);
|
||||
return std::atomic_fetch_add_explicit(&nslots[r&1][bucketi], 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
u32 soli = nsols++;
|
||||
return nslots[r&1][bucketi]++;
|
||||
#endif
|
||||
if (soli < MAXSOLS)
|
||||
listindices1(WK, t, sols[soli]); // assume WK odd
|
||||
}
|
||||
void showbsizes(u32 r) {
|
||||
}
|
||||
u32 getnslots(const u32 r, const u32 bid) { // SHOULD BE METHOD IN BUCKET STRUCT
|
||||
au32 &nslot = nslots[r&1][bid];
|
||||
const u32 n = min(nslot, NSLOTS);
|
||||
nslot = 0;
|
||||
return n;
|
||||
}
|
||||
void orderindices(u32 *indices, u32 size) {
|
||||
if (indices[0] > indices[size]) {
|
||||
for (u32 i=0; i < size; i++) {
|
||||
const u32 tmp = indices[i];
|
||||
indices[i] = indices[size+i];
|
||||
indices[size+i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
void listindices0(u32 r, const tree t, u32 *indices) {
|
||||
if (r == 0) {
|
||||
*indices = t.getindex();
|
||||
return;
|
||||
}
|
||||
const bucket1 &buck = hta.trees1[--r/2][t.bucketid()];
|
||||
const u32 size = 1 << r;
|
||||
u32 *indices1 = indices + size;
|
||||
listindices1(r, buck[t.slotid0()].attr, indices);
|
||||
listindices1(r, buck[t.slotid1()].attr, indices1);
|
||||
orderindices(indices, size);
|
||||
}
|
||||
void listindices1(u32 r, const tree t, u32 *indices) {
|
||||
const bucket0 &buck = hta.trees0[--r/2][t.bucketid()];
|
||||
const u32 size = 1 << r;
|
||||
u32 *indices1 = indices + size;
|
||||
listindices0(r, buck[t.slotid0()].attr, indices);
|
||||
listindices0(r, buck[t.slotid1()].attr, indices1);
|
||||
orderindices(indices, size);
|
||||
}
|
||||
void candidate(const tree t) {
|
||||
proof prf;
|
||||
listindices1(WK, t, prf); // assume WK odd
|
||||
qsort(prf, PROOFSIZE, sizeof(u32), &compu32);
|
||||
for (u32 i=1; i<PROOFSIZE; i++)
|
||||
if (prf[i] <= prf[i-1])
|
||||
return;
|
||||
#ifdef EQUIHASH_TROMP_ATOMIC
|
||||
u32 soli = std::atomic_fetch_add_explicit(&nsols, 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
u32 soli = nsols++;
|
||||
#endif
|
||||
if (soli < MAXSOLS)
|
||||
listindices1(WK, t, sols[soli]); // assume WK odd
|
||||
}
|
||||
void showbsizes(u32 r) {
|
||||
#if defined(HIST) || defined(SPARK) || defined(LOGSPARK)
|
||||
u32 binsizes[65];
|
||||
u32 binsizes[65];
|
||||
memset(binsizes, 0, 65 * sizeof(u32));
|
||||
for (u32 bucketid = 0; bucketid < NBUCKETS; bucketid++) {
|
||||
u32 bsize = min(nslots[r&1][bucketid], NSLOTS) >> (SLOTBITS-6);
|
||||
|
@ -314,331 +292,317 @@ struct equi {
|
|||
}
|
||||
// printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
struct htlayout {
|
||||
htalloc hta;
|
||||
u32 prevhashunits;
|
||||
u32 nexthashunits;
|
||||
u32 dunits;
|
||||
u32 prevbo;
|
||||
u32 nextbo;
|
||||
|
||||
htlayout(equi *eq, u32 r): hta(eq->hta), prevhashunits(0), dunits(0) {
|
||||
u32 nexthashbytes = hashsize(r);
|
||||
nexthashunits = hashwords(nexthashbytes);
|
||||
prevbo = 0;
|
||||
nextbo = nexthashunits * sizeof(hashunit) - nexthashbytes; // 0-3
|
||||
if (r) {
|
||||
u32 prevhashbytes = hashsize(r-1);
|
||||
prevhashunits = hashwords(prevhashbytes);
|
||||
prevbo = prevhashunits * sizeof(hashunit) - prevhashbytes; // 0-3
|
||||
dunits = prevhashunits - nexthashunits;
|
||||
}
|
||||
}
|
||||
u32 getxhash0(const slot0* pslot) const {
|
||||
|
||||
struct htlayout {
|
||||
htalloc hta;
|
||||
u32 prevhashunits;
|
||||
u32 nexthashunits;
|
||||
u32 dunits;
|
||||
u32 prevbo;
|
||||
u32 nextbo;
|
||||
|
||||
htlayout(equi *eq, u32 r): hta(eq->hta), prevhashunits(0), dunits(0) {
|
||||
u32 nexthashbytes = hashsize(r);
|
||||
nexthashunits = hashwords(nexthashbytes);
|
||||
prevbo = 0;
|
||||
nextbo = nexthashunits * sizeof(hashunit) - nexthashbytes; // 0-3
|
||||
if (r) {
|
||||
u32 prevhashbytes = hashsize(r-1);
|
||||
prevhashunits = hashwords(prevhashbytes);
|
||||
prevbo = prevhashunits * sizeof(hashunit) - prevhashbytes; // 0-3
|
||||
dunits = prevhashunits - nexthashunits;
|
||||
}
|
||||
}
|
||||
u32 getxhash0(const slot0* pslot) const {
|
||||
#if WN == 200 && RESTBITS == 4
|
||||
return pslot->hash->bytes[prevbo] >> 4;
|
||||
return pslot->hash->bytes[prevbo] >> 4;
|
||||
#elif WN == 200 && RESTBITS == 8
|
||||
return (pslot->hash->bytes[prevbo] & 0xf) << 4 | pslot->hash->bytes[prevbo+1] >> 4;
|
||||
return (pslot->hash->bytes[prevbo] & 0xf) << 4 | pslot->hash->bytes[prevbo+1] >> 4;
|
||||
#elif WN == 200 && RESTBITS == 9
|
||||
return (pslot->hash->bytes[prevbo] & 0x1f) << 4 | pslot->hash->bytes[prevbo+1] >> 4;
|
||||
return (pslot->hash->bytes[prevbo] & 0x1f) << 4 | pslot->hash->bytes[prevbo+1] >> 4;
|
||||
#elif WN == 144 && RESTBITS == 4
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
#elif WN == 192 && RESTBITS == 4
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
#else
|
||||
#error non implemented
|
||||
#endif
|
||||
}
|
||||
u32 getxhash1(const slot1* pslot) const {
|
||||
}
|
||||
u32 getxhash1(const slot1* pslot) const {
|
||||
#if WN == 200 && RESTBITS == 4
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
#elif WN == 200 && RESTBITS == 8
|
||||
return pslot->hash->bytes[prevbo];
|
||||
return pslot->hash->bytes[prevbo];
|
||||
#elif WN == 200 && RESTBITS == 9
|
||||
return (pslot->hash->bytes[prevbo]&1) << 8 | pslot->hash->bytes[prevbo+1];
|
||||
return (pslot->hash->bytes[prevbo]&1) << 8 | pslot->hash->bytes[prevbo+1];
|
||||
#elif WN == 144 && RESTBITS == 4
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
#elif WN == 192 && RESTBITS == 4
|
||||
return pslot->hash->bytes[prevbo] & 0xf;
|
||||
#else
|
||||
#error non implemented
|
||||
#endif
|
||||
}
|
||||
bool equal(const hashunit *hash0, const hashunit *hash1) const {
|
||||
return hash0[prevhashunits-1].word == hash1[prevhashunits-1].word;
|
||||
}
|
||||
};
|
||||
}
|
||||
bool equal(const hashunit *hash0, const hashunit *hash1) const {
|
||||
return hash0[prevhashunits-1].word == hash1[prevhashunits-1].word;
|
||||
}
|
||||
};
|
||||
|
||||
struct collisiondata {
|
||||
|
||||
struct collisiondata {
|
||||
#ifdef XBITMAP
|
||||
#if NSLOTS > 64
|
||||
#error cant use XBITMAP with more than 64 slots
|
||||
#endif
|
||||
u64 xhashmap[NRESTS];
|
||||
u64 xmap;
|
||||
#else
|
||||
#if RESTBITS <= 6
|
||||
typedef uchar xslot;
|
||||
typedef uchar xslot;
|
||||
#else
|
||||
typedef u16 xslot;
|
||||
typedef u16 xslot;
|
||||
#endif
|
||||
xslot nxhashslots[NRESTS];
|
||||
xslot xhashslots[NRESTS][XFULL];
|
||||
xslot *xx;
|
||||
u32 n0;
|
||||
u32 n1;
|
||||
#endif
|
||||
u32 s0;
|
||||
xslot nxhashslots[NRESTS];
|
||||
xslot xhashslots[NRESTS][XFULL];
|
||||
xslot *xx;
|
||||
u32 n0;
|
||||
u32 n1;
|
||||
u32 s0;
|
||||
|
||||
void clear() {
|
||||
#ifdef XBITMAP
|
||||
memset(xhashmap, 0, NRESTS * sizeof(u64));
|
||||
#else
|
||||
memset(nxhashslots, 0, NRESTS * sizeof(xslot));
|
||||
#endif
|
||||
}
|
||||
bool addslot(u32 s1, u32 xh) {
|
||||
#ifdef XBITMAP
|
||||
xmap = xhashmap[xh];
|
||||
xhashmap[xh] |= (u64)1 << s1;
|
||||
s0 = -1;
|
||||
return true;
|
||||
#else
|
||||
n1 = (u32)nxhashslots[xh]++;
|
||||
if (n1 >= XFULL)
|
||||
return false;
|
||||
xx = xhashslots[xh];
|
||||
xx[n1] = s1;
|
||||
n0 = 0;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
bool nextcollision() const {
|
||||
#ifdef XBITMAP
|
||||
return xmap != 0;
|
||||
#else
|
||||
return n0 < n1;
|
||||
#endif
|
||||
}
|
||||
u32 slot() {
|
||||
#ifdef XBITMAP
|
||||
const u32 ffs = __builtin_ffsll(xmap);
|
||||
s0 += ffs; xmap >>= ffs;
|
||||
return s0;
|
||||
#else
|
||||
return (u32)xx[n0++];
|
||||
#endif
|
||||
}
|
||||
};
|
||||
void clear() {
|
||||
memset(nxhashslots, 0, NRESTS * sizeof(xslot));
|
||||
}
|
||||
bool addslot(u32 s1, u32 xh) {
|
||||
n1 = (u32)nxhashslots[xh]++;
|
||||
if (n1 >= XFULL)
|
||||
return false;
|
||||
xx = xhashslots[xh];
|
||||
xx[n1] = s1;
|
||||
n0 = 0;
|
||||
return true;
|
||||
}
|
||||
bool nextcollision() const {
|
||||
return n0 < n1;
|
||||
}
|
||||
u32 slot() {
|
||||
return (u32)xx[n0++];
|
||||
}
|
||||
};
|
||||
|
||||
void digit0(const u32 id) {
|
||||
uchar hash[HASHOUT];
|
||||
crypto_generichash_blake2b_state state;
|
||||
htlayout htl(this, 0);
|
||||
const u32 hashbytes = hashsize(0);
|
||||
for (u32 block = id; block < NBLOCKS; block += nthreads) {
|
||||
state = blake_ctx;
|
||||
u32 leb = htole32(block);
|
||||
crypto_generichash_blake2b_update(&state, (uchar *)&leb, sizeof(u32));
|
||||
crypto_generichash_blake2b_final(&state, hash, HASHOUT);
|
||||
for (u32 i = 0; i<HASHESPERBLAKE; i++) {
|
||||
const uchar *ph = hash + i * WN/8;
|
||||
void digit0(const u32 id) {
|
||||
uchar hash[HASHOUT];
|
||||
crypto_generichash_blake2b_state state;
|
||||
htlayout htl(this, 0);
|
||||
const u32 hashbytes = hashsize(0);
|
||||
for (u32 block = id; block < NBLOCKS; block += nthreads) {
|
||||
state = blake_ctx;
|
||||
u32 leb = htole32(block);
|
||||
crypto_generichash_blake2b_update(&state, (uchar *)&leb, sizeof(u32));
|
||||
crypto_generichash_blake2b_final(&state, hash, HASHOUT);
|
||||
for (u32 i = 0; i<HASHESPERBLAKE; i++) {
|
||||
const uchar *ph = hash + i * WN/8;
|
||||
#if BUCKBITS == 16 && RESTBITS == 4
|
||||
const u32 bucketid = ((u32)ph[0] << 8) | ph[1];
|
||||
const u32 bucketid = ((u32)ph[0] << 8) | ph[1];
|
||||
#elif BUCKBITS == 12 && RESTBITS == 8
|
||||
const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4;
|
||||
const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4;
|
||||
#elif BUCKBITS == 11 && RESTBITS == 9
|
||||
const u32 bucketid = ((u32)ph[0] << 3) | ph[1] >> 5;
|
||||
const u32 bucketid = ((u32)ph[0] << 3) | ph[1] >> 5;
|
||||
#elif BUCKBITS == 20 && RESTBITS == 4
|
||||
const u32 bucketid = ((((u32)ph[0] << 8) | ph[1]) << 4) | ph[2] >> 4;
|
||||
const u32 bucketid = ((((u32)ph[0] << 8) | ph[1]) << 4) | ph[2] >> 4;
|
||||
#elif BUCKBITS == 12 && RESTBITS == 4
|
||||
const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4;
|
||||
const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4;
|
||||
const u32 xhash = ph[1] & 0xf;
|
||||
#elif BUCKBITS == 20 && RESTBITS == 4
|
||||
const u32 bucketid = ((((u32)ph[0] << 8) | ph[1]) << 4) | ph[2] >> 4;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
const u32 slot = getslot(0, bucketid);
|
||||
if (slot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
const u32 slot = getslot(0, bucketid);
|
||||
if (slot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
slot0 &s = hta.trees0[0][bucketid][slot];
|
||||
s.attr = tree(block * HASHESPERBLAKE + i);
|
||||
memcpy(s.hash->bytes+htl.nextbo, ph+WN/8-hashbytes, hashbytes);
|
||||
}
|
||||
}
|
||||
slot0 &s = hta.trees0[0][bucketid][slot];
|
||||
s.attr = tree(block * HASHESPERBLAKE + i);
|
||||
memcpy(s.hash->bytes+htl.nextbo, ph+WN/8-hashbytes, hashbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void digitodd(const u32 r, const u32 id) {
|
||||
htlayout htl(this, r);
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = htl.hta.trees0[(r-1)/2][bucketid]; // optimize by updating previous buck?!
|
||||
u32 bsize = getnslots(r-1, bucketid); // optimize by putting bucketsize with block?!
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot0 *pslot1 = buck + s1; // optimize by updating previous pslot1?!
|
||||
if (!cd.addslot(s1, htl.getxhash0(pslot1))) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const slot0 *pslot0 = buck + s0;
|
||||
if (htl.equal(pslot0->hash, pslot1->hash)) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid;
|
||||
const uchar *bytes0 = pslot0->hash->bytes, *bytes1 = pslot1->hash->bytes;
|
||||
|
||||
void digitodd(const u32 r, const u32 id) {
|
||||
htlayout htl(this, r);
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = htl.hta.trees0[(r-1)/2][bucketid]; // optimize by updating previous buck?!
|
||||
u32 bsize = getnslots(r-1, bucketid); // optimize by putting bucketsize with block?!
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot0 *pslot1 = buck + s1; // optimize by updating previous pslot1?!
|
||||
if (!cd.addslot(s1, htl.getxhash0(pslot1))) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const slot0 *pslot0 = buck + s0;
|
||||
if (htl.equal(pslot0->hash, pslot1->hash)) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid;
|
||||
const uchar *bytes0 = pslot0->hash->bytes, *bytes1 = pslot1->hash->bytes;
|
||||
#if WN == 200 && BUCKBITS == 12 && RESTBITS == 8
|
||||
xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 8)
|
||||
xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]);
|
||||
#elif WN == 200 && BUCKBITS == 11 && RESTBITS == 9
|
||||
xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 7)
|
||||
xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 7)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 1;
|
||||
#elif WN == 144 && BUCKBITS == 20 && RESTBITS == 4
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 4;
|
||||
#elif WN == 96 && BUCKBITS == 12 && RESTBITS == 4
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4;
|
||||
#elif WN == 192 && BUCKBITS == 20 && RESTBITS == 4
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 4;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
const u32 xorslot = getslot(r, xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
slot1 &xs = htl.hta.trees1[r/2][xorbucketid][xorslot];
|
||||
xs.attr = tree(bucketid, s0, s1);
|
||||
for (u32 i=htl.dunits; i < htl.prevhashunits; i++)
|
||||
xs.hash[i-htl.dunits].word = pslot0->hash[i].word ^ pslot1->hash[i].word;
|
||||
const u32 xorslot = getslot(r, xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
slot1 &xs = htl.hta.trees1[r/2][xorbucketid][xorslot];
|
||||
xs.attr = tree(bucketid, s0, s1);
|
||||
for (u32 i=htl.dunits; i < htl.prevhashunits; i++)
|
||||
xs.hash[i-htl.dunits].word = pslot0->hash[i].word ^ pslot1->hash[i].word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void digiteven(const u32 r, const u32 id) {
|
||||
htlayout htl(this, r);
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot1 *buck = htl.hta.trees1[(r-1)/2][bucketid]; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
u32 bsize = getnslots(r-1, bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot1 *pslot1 = buck + s1; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
if (!cd.addslot(s1, htl.getxhash1(pslot1))) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const slot1 *pslot0 = buck + s0;
|
||||
if (htl.equal(pslot0->hash, pslot1->hash)) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid;
|
||||
const uchar *bytes0 = pslot0->hash->bytes, *bytes1 = pslot1->hash->bytes;
|
||||
|
||||
void digiteven(const u32 r, const u32 id) {
|
||||
htlayout htl(this, r);
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot1 *buck = htl.hta.trees1[(r-1)/2][bucketid]; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
u32 bsize = getnslots(r-1, bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot1 *pslot1 = buck + s1; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
if (!cd.addslot(s1, htl.getxhash1(pslot1))) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const slot1 *pslot0 = buck + s0;
|
||||
if (htl.equal(pslot0->hash, pslot1->hash)) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid;
|
||||
const uchar *bytes0 = pslot0->hash->bytes, *bytes1 = pslot1->hash->bytes;
|
||||
#if WN == 200 && BUCKBITS == 12 && RESTBITS == 8
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4;
|
||||
#elif WN == 200 && BUCKBITS == 11 && RESTBITS == 9
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) << 3)
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) << 3)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 5;
|
||||
#elif WN == 144 && BUCKBITS == 20 && RESTBITS == 4
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 4;
|
||||
#elif WN == 96 && BUCKBITS == 12 && RESTBITS == 4
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4;
|
||||
#elif WN == 192 && BUCKBITS == 20 && RESTBITS == 4
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 4;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
const u32 xorslot = getslot(r, xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
slot0 &xs = htl.hta.trees0[r/2][xorbucketid][xorslot];
|
||||
xs.attr = tree(bucketid, s0, s1);
|
||||
for (u32 i=htl.dunits; i < htl.prevhashunits; i++)
|
||||
xs.hash[i-htl.dunits].word = pslot0->hash[i].word ^ pslot1->hash[i].word;
|
||||
const u32 xorslot = getslot(r, xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
slot0 &xs = htl.hta.trees0[r/2][xorbucketid][xorslot];
|
||||
xs.attr = tree(bucketid, s0, s1);
|
||||
for (u32 i=htl.dunits; i < htl.prevhashunits; i++)
|
||||
xs.hash[i-htl.dunits].word = pslot0->hash[i].word ^ pslot1->hash[i].word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void digitK(const u32 id) {
|
||||
collisiondata cd;
|
||||
htlayout htl(this, WK);
|
||||
u32 nc = 0;
|
||||
for (u32 bucketid = id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = htl.hta.trees0[(WK-1)/2][bucketid];
|
||||
u32 bsize = getnslots(WK-1, bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot0 *pslot1 = buck + s1;
|
||||
if (!cd.addslot(s1, htl.getxhash0(pslot1))) // assume WK odd
|
||||
continue;
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
if (htl.equal(buck[s0].hash, pslot1->hash))
|
||||
nc++, candidate(tree(bucketid, s0, s1));
|
||||
|
||||
void digitK(const u32 id) {
|
||||
collisiondata cd;
|
||||
htlayout htl(this, WK);
|
||||
u32 nc = 0;
|
||||
for (u32 bucketid = id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = htl.hta.trees0[(WK-1)/2][bucketid];
|
||||
u32 bsize = getnslots(WK-1, bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot0 *pslot1 = buck + s1;
|
||||
if (!cd.addslot(s1, htl.getxhash0(pslot1))) // assume WK odd
|
||||
continue;
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
if (htl.equal(buck[s0].hash, pslot1->hash))
|
||||
nc++, candidate(tree(bucketid, s0, s1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf(" %d candidates ", nc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u32 id;
|
||||
pthread_t thread;
|
||||
equi *eq;
|
||||
u32 id;
|
||||
pthread_t thread;
|
||||
equi *eq;
|
||||
} thread_ctx;
|
||||
|
||||
void barrier(pthread_barrier_t *barry) {
|
||||
const int rc = pthread_barrier_wait(barry);
|
||||
if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
|
||||
const int rc = pthread_barrier_wait(barry);
|
||||
if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
|
||||
// printf("Could not wait on barrier\n");
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void *worker(void *vp) {
|
||||
thread_ctx *tp = (thread_ctx *)vp;
|
||||
equi *eq = tp->eq;
|
||||
thread_ctx *tp = (thread_ctx *)vp;
|
||||
equi *eq = tp->eq;
|
||||
|
||||
if (tp->id == 0)
|
||||
// printf("Digit 0\n");
|
||||
barrier(&eq->barry);
|
||||
eq->digit0(tp->id);
|
||||
barrier(&eq->barry);
|
||||
if (tp->id == 0) {
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
eq->showbsizes(0);
|
||||
}
|
||||
barrier(&eq->barry);
|
||||
for (u32 r = 1; r < WK; r++) {
|
||||
if (tp->id == 0)
|
||||
// printf("Digit %d", r);
|
||||
barrier(&eq->barry);
|
||||
r&1 ? eq->digitodd(r, tp->id) : eq->digiteven(r, tp->id);
|
||||
// printf("Digit 0\n");
|
||||
barrier(&eq->barry);
|
||||
eq->digit0(tp->id);
|
||||
barrier(&eq->barry);
|
||||
if (tp->id == 0) {
|
||||
// printf(" x%d b%d h%d\n", eq->xfull, eq->bfull, eq->hfull);
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
eq->showbsizes(r);
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
eq->showbsizes(0);
|
||||
}
|
||||
barrier(&eq->barry);
|
||||
}
|
||||
if (tp->id == 0)
|
||||
for (u32 r = 1; r < WK; r++) {
|
||||
if (tp->id == 0)
|
||||
// printf("Digit %d", r);
|
||||
barrier(&eq->barry);
|
||||
r&1 ? eq->digitodd(r, tp->id) : eq->digiteven(r, tp->id);
|
||||
barrier(&eq->barry);
|
||||
if (tp->id == 0) {
|
||||
// printf(" x%d b%d h%d\n", eq->xfull, eq->bfull, eq->hfull);
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
eq->showbsizes(r);
|
||||
}
|
||||
barrier(&eq->barry);
|
||||
}
|
||||
if (tp->id == 0)
|
||||
// printf("Digit %d\n", WK);
|
||||
eq->digitK(tp->id);
|
||||
barrier(&eq->barry);
|
||||
pthread_exit(NULL);
|
||||
return 0;
|
||||
}
|
||||
eq->digitK(tp->id);
|
||||
barrier(&eq->barry);
|
||||
pthread_exit(NULL);
|
||||
return 0;
|
||||
}
|
|
@ -202,10 +202,13 @@ UniValue generate(const UniValue& params, bool fHelp)
|
|||
}
|
||||
unsigned int nExtraNonce = 0;
|
||||
UniValue blockHashes(UniValue::VARR);
|
||||
unsigned int n = Params().EquihashN();
|
||||
unsigned int k = Params().EquihashK();
|
||||
const CChainParams& chainparams = Params();
|
||||
unsigned int n;
|
||||
unsigned int k;
|
||||
while (nHeight < nHeightEnd)
|
||||
{
|
||||
n = chainparams.EquihashN(nHeight + 1);
|
||||
k = chainparams.EquihashK(nHeight + 1);
|
||||
#ifdef ENABLE_WALLET
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
|
||||
#else
|
||||
|
@ -250,7 +253,7 @@ UniValue generate(const UniValue& params, bool fHelp)
|
|||
solutionTargetChecks.increment();
|
||||
return CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus());
|
||||
};
|
||||
bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock);
|
||||
bool found = EhOptimisedSolveUncancellable(n, k, curr_state, validBlock);
|
||||
ehSolverRuns.increment();
|
||||
if (found) {
|
||||
goto endloop;
|
||||
|
|
|
@ -79,7 +79,7 @@ void ThreadSendAlert()
|
|||
// These versions are protocol versions
|
||||
// 170002 : 1.0.0
|
||||
alert.nMinVer = 170005;
|
||||
alert.nMaxVer = 180005;
|
||||
alert.nMaxVer = 180006;
|
||||
|
||||
//
|
||||
// main.cpp:
|
||||
|
|
|
@ -755,8 +755,9 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends)
|
|||
mtx2.vin[0].nSequence = 0;
|
||||
|
||||
{
|
||||
auto consensus = Params().GetConsensus();
|
||||
CTransaction tx2(mtx2);
|
||||
BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus()));
|
||||
BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+consensus.coinbaseMaturity, consensus));
|
||||
}
|
||||
|
||||
mtx2.vout.resize(1);
|
||||
|
@ -768,10 +769,10 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends)
|
|||
CTransaction tx2(mtx2);
|
||||
|
||||
if(consensus.fCoinbaseMustBeProtected) {
|
||||
BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, consensus));
|
||||
BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+consensus.coinbaseMaturity, consensus));
|
||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs");
|
||||
} else {
|
||||
BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, consensus));
|
||||
BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+consensus.coinbaseMaturity, consensus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned in
|
|||
continue;
|
||||
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
|
||||
if (fSanityCheck) assert(coins);
|
||||
if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
|
||||
if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < Params().GetConsensus().coinbaseMaturity)) {
|
||||
transactionsToRemove.push_back(tx);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* network protocol versioning
|
||||
*/
|
||||
|
||||
static const int PROTOCOL_VERSION = 180005;
|
||||
static const int PROTOCOL_VERSION = 180006;
|
||||
|
||||
//! initial proto version, to be increased after version/verack negotiation
|
||||
static const int INIT_PROTO_VERSION = 209;
|
||||
|
|
|
@ -748,7 +748,8 @@ TEST(wallet_tests, CachedWitnessesCleanIndex) {
|
|||
wallet.AddSpendingKey(sk);
|
||||
|
||||
// Generate a chain
|
||||
size_t numBlocks = WITNESS_CACHE_SIZE + 10;
|
||||
// Uses mainnet maturity. Otherwise, SelectParams(CBaseChainParams::TESTNET); coinbaseMaturity = 10;
|
||||
size_t numBlocks = 100 + 10;
|
||||
blocks.resize(numBlocks);
|
||||
indices.resize(numBlocks);
|
||||
for (size_t i = 0; i < numBlocks; i++) {
|
||||
|
|
|
@ -640,6 +640,8 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
|
|||
const CBlock* pblockIn,
|
||||
ZCIncrementalMerkleTree& tree)
|
||||
{
|
||||
const unsigned int maxWitnessCacheSize = Params().GetConsensus().coinbaseMaturity;
|
||||
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
|
||||
|
@ -661,13 +663,13 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
|
|||
if (nd->witnesses.size() > 0) {
|
||||
nd->witnesses.push_front(nd->witnesses.front());
|
||||
}
|
||||
if (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
|
||||
if (nd->witnesses.size() > maxWitnessCacheSize) {
|
||||
nd->witnesses.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nWitnessCacheSize < WITNESS_CACHE_SIZE) {
|
||||
if (nWitnessCacheSize < maxWitnessCacheSize) {
|
||||
nWitnessCacheSize += 1;
|
||||
}
|
||||
|
||||
|
@ -3631,7 +3633,8 @@ int CMerkleTx::GetBlocksToMaturity() const
|
|||
{
|
||||
if (!IsCoinBase())
|
||||
return 0;
|
||||
return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
|
||||
auto params = Params().GetConsensus();
|
||||
return max(0, (params.coinbaseMaturity+1) - GetDepthInMainChain());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
|
|||
//! Size of witness cache
|
||||
// Should be large enough that we can expect not to reorg beyond our cache
|
||||
// unless there is some exceptional network disruption.
|
||||
static const unsigned int WITNESS_CACHE_SIZE = COINBASE_MATURITY;
|
||||
// (Inlined, see `IncrementNoteWitnesses`)
|
||||
|
||||
class CAccountingEntry;
|
||||
class CBlockIndex;
|
||||
|
|
|
@ -138,8 +138,9 @@ double benchmark_solve_equihash()
|
|||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << I;
|
||||
|
||||
unsigned int n = Params(CBaseChainParams::MAIN).EquihashN();
|
||||
unsigned int k = Params(CBaseChainParams::MAIN).EquihashK();
|
||||
const CChainParams& params = Params(CBaseChainParams::MAIN);
|
||||
unsigned int n = params.EquihashN(params.EquihashParamsUpdate());
|
||||
unsigned int k = params.EquihashK(params.EquihashParamsUpdate());
|
||||
crypto_generichash_blake2b_state eh_state;
|
||||
EhInitialiseState(n, k, eh_state);
|
||||
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
|
||||
|
|
Loading…
Reference in New Issue