Bug fixes in hash algorithm, parameters, and time lock support

This commit is contained in:
miketout
2018-04-28 15:05:20 -07:00
parent c71dcc712e
commit a0dd01bc50
8 changed files with 68 additions and 31 deletions

View File

@@ -49,7 +49,7 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len)
unsigned char *tmp; unsigned char *tmp;
// digest up to 32 bytes at a time // digest up to 32 bytes at a time
for ( int pos = 0; pos < len; pos += 32) for ( int pos = 0; pos < len; )
{ {
int room = 32 - curPos; int room = 32 - curPos;
@@ -66,7 +66,7 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len)
else else
{ {
memcpy(curBuf + 32 + curPos, data + pos, len - pos); memcpy(curBuf + 32 + curPos, data + pos, len - pos);
curPos = 32 - (len - pos); curPos += len - pos;
pos = len; pos = len;
} }
} }

View File

@@ -46,7 +46,8 @@ class CVerusHash
} }
private: private:
unsigned char buf1[64], buf2[64]; // only buf1, the first source, needs to be zero initialized
unsigned char buf1[64] = {0}, buf2[64];
unsigned char *curBuf = buf1, *result = buf2; unsigned char *curBuf = buf1, *result = buf2;
size_t curPos = 0; size_t curPos = 0;
}; };

View File

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

View File

@@ -56,7 +56,7 @@ uint32_t ASSETCHAIN_INIT;
uint32_t ASSETCHAINS_MAGIC = 2387029918; uint32_t ASSETCHAINS_MAGIC = 2387029918;
uint64_t ASSETCHAINS_SUPPLY = 10; uint64_t ASSETCHAINS_SUPPLY = 10;
uint64_t ASSETCHAINS_COMMISSION; uint64_t ASSETCHAINS_COMMISSION;
int64_t ASSETCHAINS_GENESISPREMINE = 5000000000; int64_t ASSETCHAINS_GENESISTXVAL = 5000000000;
// consensus variables for coinbase timelock control and timelock transaction support // consensus variables for coinbase timelock control and timelock transaction support
// time locks are specified enough to enable their use initially to lock specific coinbase transactions for emission control // time locks are specified enough to enable their use initially to lock specific coinbase transactions for emission control

View File

@@ -1042,8 +1042,7 @@ uint64_t blockPRG(uint32_t nHeight)
{ {
int i; int i;
uint8_t hashSrc[8]; uint8_t hashSrc[8];
uint32_t result = 0; uint64_t result, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight;
uint64_t hashSrc64 = ASSETCHAINS_MAGIC << 32 + nHeight;
bits256 hashResult; bits256 hashResult;
for ( i = 0; i < sizeof(hashSrc); i++ ) for ( i = 0; i < sizeof(hashSrc); i++ )
@@ -1051,11 +1050,11 @@ uint64_t blockPRG(uint32_t nHeight)
hashSrc[i] = hashSrc64 & 0xff; hashSrc[i] = hashSrc64 & 0xff;
hashSrc64 >>= 8; hashSrc64 >>= 8;
} }
vcalc_sha256(0,hashResult.bytes,hashSrc,sizeof(hashSrc)); vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc));
for ( i = 0; i < sizeof(hashResult.uints) >> 2; i++ ) for ( i = 0; i < 8; i++ )
{ {
result ^= hashResult.uints[i]; result = (result << 8) + hashResult.bytes[i];
} }
return(result); return(result);
} }
@@ -1552,8 +1551,13 @@ int64_t komodo_max_money()
max_money = komodo_maxallowed(baseid); max_money = komodo_maxallowed(baseid);
else else
{ {
// figure out max_money by adding up supply and future block rewards, if no ac_END, max_money uses arbitrary 10,000,000 block end // figure out max_money by adding up supply to a maximum of 10,000,000 blocks
max_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISPREMINE; max_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISTXVAL;
if ( ASSETCHAINS_LASTERA == 0 && ASSETCHAINS_REWARD[0] == 0 )
{
max_money += 10000 * 10000000LL;
return((int64_t)max_money);
}
for ( int j = 0; j <= ASSETCHAINS_LASTERA && (j == 0 || ASSETCHAINS_ENDSUBSIDY[j - 1] != 0); j++ ) for ( int j = 0; j <= ASSETCHAINS_LASTERA && (j == 0 || ASSETCHAINS_ENDSUBSIDY[j - 1] != 0); j++ )
{ {
@@ -1604,9 +1608,9 @@ int64_t komodo_max_money()
uint64_t komodo_ac_block_subsidy(int nHeight) uint64_t komodo_ac_block_subsidy(int nHeight)
{ {
// we have to find our era, start from beginning reward, and determine current subsidy // we have to find our era, start from beginning reward, and determine current subsidy
int64_t numerator, subsidy = 0; int64_t numerator, denominator, subsidy = 0;
int64_t subsidyDifference; int64_t subsidyDifference;
int32_t numhalvings, curEra = 0; int32_t numhalvings, curEra = 0, sign = 1;
static uint64_t cached_subsidy; static int32_t cached_numhalvings; static int cached_era; static uint64_t cached_subsidy; static int32_t cached_numhalvings; static int cached_era;
// check for backwards compat, older chains with no explicit rewards had 0.0001 block reward // check for backwards compat, older chains with no explicit rewards had 0.0001 block reward
@@ -1627,7 +1631,7 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
{ {
int nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0; int nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0;
subsidy = (int64_t)ASSETCHAINS_REWARD[curEra]; subsidy = (int64_t)ASSETCHAINS_REWARD[curEra];
if ( subsidy ) if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) )
{ {
if ( ASSETCHAINS_HALVING[curEra] != 0 ) if ( ASSETCHAINS_HALVING[curEra] != 0 )
{ {
@@ -1645,9 +1649,15 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
{ {
// Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0
subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1]; subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1];
if (subsidyDifference < 0)
{
sign = -1;
subsidyDifference *= sign;
}
} }
numerator = (ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight); denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart;
subsidy = subsidy - (subsidyDifference * numerator) / (ASSETCHAINS_ENDSUBSIDY[curEra] - nStart); numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra]));
subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator);
} }
else else
{ {
@@ -1732,6 +1742,13 @@ void komodo_args(char *argv0)
ASSETCHAINS_TIMELOCKGTE = GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF); ASSETCHAINS_TIMELOCKGTE = GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF);
ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0); ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0);
ASSETCHAINS_TIMEUNLOCKTO = GetArg("-ac_timeunlockto", 0); ASSETCHAINS_TIMEUNLOCKTO = GetArg("-ac_timeunlockto", 0);
if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO ||
ASSETCHAINS_TIMEUNLOCKTO == 0 )
{
printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n");
ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0;
}
Split(GetArg("-ac_end",""), ASSETCHAINS_ENDSUBSIDY, 0); Split(GetArg("-ac_end",""), ASSETCHAINS_ENDSUBSIDY, 0);
Split(GetArg("-ac_reward",""), ASSETCHAINS_REWARD, 0); Split(GetArg("-ac_reward",""), ASSETCHAINS_REWARD, 0);

View File

@@ -901,14 +901,14 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeight) bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeight)
{ {
// if time locks are on, ensure that this coin base is time locked exactly as it should be // if time locks are on, ensure that this coin base is time locked exactly as it should be
if (tx.GetValueOut() >= ASSETCHAINS_TIMELOCKGTE) if ((uint64_t)(tx.GetValueOut()) >= ASSETCHAINS_TIMELOCKGTE)
{ {
CScriptID scriptHash; CScriptID scriptHash;
// to be valid, it must be a P2SH transaction and have an op_return in vout[1] that // to be valid, it must be a P2SH transaction and have an op_return in vout[1] that
// holds the full output script, which may include multisig, etc., but starts with // holds the full output script, which may include multisig, etc., but starts with
// the time lock verify of the correct time lock for this block height // the time lock verify of the correct time lock for this block height
if (tx.vout.size() == 2 && if (tx.vout.size() == 2 &&
CScriptExt(tx.vout[0].scriptPubKey).IsPayToScriptHash(&scriptHash) && CScriptExt(tx.vout[0].scriptPubKey).IsPayToScriptHash(&scriptHash) &&
tx.vout[1].scriptPubKey.size() >= 7 && // minimum for any possible future to prevent out of bounds tx.vout[1].scriptPubKey.size() >= 7 && // minimum for any possible future to prevent out of bounds
tx.vout[1].scriptPubKey.data()[0] == OP_RETURN) tx.vout[1].scriptPubKey.data()[0] == OP_RETURN)
@@ -3594,7 +3594,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight+1; int nHeight = pindexPrev->nHeight+1;
// Check proof of work // Check proof of work
if ( (nHeight < 235300 || nHeight > 236000) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) if ( (ASSETCHAINS_SYMBOL[0] != 0 || (nHeight < 235300 || nHeight > 236000)) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
{ {
cout << block.nBits << " block.nBits vs. calc " << GetNextWorkRequired(pindexPrev, &block, consensusParams) << endl; cout << block.nBits << " block.nBits vs. calc " << GetNextWorkRequired(pindexPrev, &block, consensusParams) << endl;
return state.DoS(100, error("%s: incorrect proof of work", __func__), return state.DoS(100, error("%s: incorrect proof of work", __func__),
@@ -3603,8 +3603,10 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
// Check timestamp against prev // Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
{
return state.Invalid(error("%s: block's timestamp is too early", __func__), return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old"); REJECT_INVALID, "time-too-old");
}
if (fCheckpointsEnabled) if (fCheckpointsEnabled)
{ {

View File

@@ -192,8 +192,22 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1; const int nHeight = pindexPrev->nHeight + 1;
uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus()); uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus());
pblock->nTime = GetAdjustedTime();
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
uint32_t proposedTime = GetAdjustedTime();
if (proposedTime == nMedianTimePast)
{
// too fast or stuck, this addresses the too fast issue, while moving
// forward as quickly as possible
for (int i; i < 100; i++)
{
proposedTime = GetAdjustedTime();
if (proposedTime == nMedianTimePast)
MilliSleep(10);
}
}
pblock->nTime = GetAdjustedTime();
CCoinsViewCache view(pcoinsTip); CCoinsViewCache view(pcoinsTip);
uint32_t expired; uint32_t expired;
@@ -402,8 +416,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
txNew.nExpiryHeight = 0; txNew.nExpiryHeight = 0;
// check if coinbase transactions must be time locked at current subsidy and prepend the time lock // check if coinbase transactions must be time locked at current subsidy and prepend the time lock
// to transaction if so // to transaction if so, cast for GTE operator
if (txNew.vout[0].nValue >= ASSETCHAINS_TIMELOCKGTE) if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE)
{ {
int32_t opretlen, p2shlen, scriptlen; int32_t opretlen, p2shlen, scriptlen;
CScriptExt opretScript = CScriptExt(); CScriptExt opretScript = CScriptExt();
@@ -769,6 +783,7 @@ void static BitcoinMiner_noeq()
LogPrintf("KomodoMiner using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); LogPrintf("KomodoMiner using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
printf("FOUND BLOCK! \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str());
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
ProcessBlockFound(pblock, *pwallet, reservekey); ProcessBlockFound(pblock, *pwallet, reservekey);
#else #else

View File

@@ -36,7 +36,7 @@ const CScriptExt &CScriptExt::OpReturnScript(const vector<unsigned char> &data,
if (data.size() < MAX_SCRIPT_ELEMENT_SIZE) if (data.size() < MAX_SCRIPT_ELEMENT_SIZE)
{ {
vector<unsigned char> scratch = vector<unsigned char>(data); vector<unsigned char> scratch = vector<unsigned char>(data);
scratch.insert(data.begin(), opretType); scratch.insert(scratch.begin(), opretType);
*((CScript *)this) << OP_RETURN; *((CScript *)this) << OP_RETURN;
*((CScript *)this) << scratch; *((CScript *)this) << scratch;
} }
@@ -56,11 +56,13 @@ const CScriptExt &CScriptExt::PayToScriptHash(const CScriptID &scriptID) const
// P2SH script, adds to whatever is already in the script (for example CLTV) // P2SH script, adds to whatever is already in the script (for example CLTV)
const CScriptExt &CScriptExt::AddCheckLockTimeVerify(int64_t unlocktime) const const CScriptExt &CScriptExt::AddCheckLockTimeVerify(int64_t unlocktime) const
{ {
unlocktime = unlocktime < 0 ? 0 : unlocktime; if (unlocktime > 0)
*((CScript *)this) << CScriptNum::serialize(unlocktime); {
*((CScript *)this) << OP_CHECKLOCKTIMEVERIFY; *((CScript *)this) << CScriptNum::serialize(unlocktime);
*((CScript *)this) << OP_DROP; *((CScript *)this) << OP_CHECKLOCKTIMEVERIFY;
return *this; *((CScript *)this) << OP_DROP;
return *this;
}
} }
// combined CLTV script and P2PKH // combined CLTV script and P2PKH
@@ -78,11 +80,11 @@ bool CScriptExt::IsCheckLockTimeVerify(int64_t *unlockTime) const
{ {
opcodetype op; opcodetype op;
std::vector<unsigned char> unlockTimeParam = std::vector<unsigned char>(); std::vector<unsigned char> unlockTimeParam = std::vector<unsigned char>();
CScript::const_iterator it = this->begin(); CScript::const_iterator it = this->begin();
if (this->GetOp2(it, op, &unlockTimeParam)) if (this->GetOp2(it, op, &unlockTimeParam))
{ {
if (unlockTimeParam.size() > 1 && unlockTimeParam.size() < 6 && if (unlockTimeParam.size() >= 0 && unlockTimeParam.size() < 6 &&
*(this->data() + unlockTimeParam.size() + 1) == OP_CHECKLOCKTIMEVERIFY) *(this->data() + unlockTimeParam.size() + 1) == OP_CHECKLOCKTIMEVERIFY)
{ {
int i = unlockTimeParam.size() - 1; int i = unlockTimeParam.size() - 1;