Browse Source

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

metaverse
miketout 6 years ago
parent
commit
a0dd01bc50
  1. 4
      src/crypto/verus_hash.cpp
  2. 3
      src/crypto/verus_hash.h
  3. 2
      src/hash.h
  4. 2
      src/komodo_globals.h
  5. 41
      src/komodo_utils.h
  6. 8
      src/main.cpp
  7. 21
      src/miner.cpp
  8. 18
      src/script/script_ext.cpp

4
src/crypto/verus_hash.cpp

@ -49,7 +49,7 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len)
unsigned char *tmp;
// 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;
@ -66,7 +66,7 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len)
else
{
memcpy(curBuf + 32 + curPos, data + pos, len - pos);
curPos = 32 - (len - pos);
curPos += len - pos;
pos = len;
}
}

3
src/crypto/verus_hash.h

@ -46,7 +46,8 @@ class CVerusHash
}
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;
size_t curPos = 0;
};

2
src/hash.h

@ -203,7 +203,7 @@ public:
int nType;
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) {
state.Write((const unsigned char*)pch, size);

2
src/komodo_globals.h

@ -56,7 +56,7 @@ uint32_t ASSETCHAIN_INIT;
uint32_t ASSETCHAINS_MAGIC = 2387029918;
uint64_t ASSETCHAINS_SUPPLY = 10;
uint64_t ASSETCHAINS_COMMISSION;
int64_t ASSETCHAINS_GENESISPREMINE = 5000000000;
int64_t ASSETCHAINS_GENESISTXVAL = 5000000000;
// 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

41
src/komodo_utils.h

@ -1042,8 +1042,7 @@ uint64_t blockPRG(uint32_t nHeight)
{
int i;
uint8_t hashSrc[8];
uint32_t result = 0;
uint64_t hashSrc64 = ASSETCHAINS_MAGIC << 32 + nHeight;
uint64_t result, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight;
bits256 hashResult;
for ( i = 0; i < sizeof(hashSrc); i++ )
@ -1051,11 +1050,11 @@ uint64_t blockPRG(uint32_t nHeight)
hashSrc[i] = hashSrc64 & 0xff;
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);
}
@ -1552,8 +1551,13 @@ int64_t komodo_max_money()
max_money = komodo_maxallowed(baseid);
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
max_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISPREMINE;
// 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_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++ )
{
@ -1604,9 +1608,9 @@ int64_t komodo_max_money()
uint64_t komodo_ac_block_subsidy(int nHeight)
{
// 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;
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;
// 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;
subsidy = (int64_t)ASSETCHAINS_REWARD[curEra];
if ( subsidy )
if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 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
subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1];
if (subsidyDifference < 0)
{
sign = -1;
subsidyDifference *= sign;
}
}
numerator = (ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight);
subsidy = subsidy - (subsidyDifference * numerator) / (ASSETCHAINS_ENDSUBSIDY[curEra] - nStart);
denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart;
numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra]));
subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator);
}
else
{
@ -1732,6 +1742,13 @@ void komodo_args(char *argv0)
ASSETCHAINS_TIMELOCKGTE = GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF);
ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 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_reward",""), ASSETCHAINS_REWARD, 0);

8
src/main.cpp

@ -901,14 +901,14 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
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 (tx.GetValueOut() >= ASSETCHAINS_TIMELOCKGTE)
if ((uint64_t)(tx.GetValueOut()) >= ASSETCHAINS_TIMELOCKGTE)
{
CScriptID scriptHash;
// 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
// 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) &&
tx.vout[1].scriptPubKey.size() >= 7 && // minimum for any possible future to prevent out of bounds
tx.vout[1].scriptPubKey.data()[0] == OP_RETURN)
@ -3594,7 +3594,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight+1;
// 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;
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
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
{
return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old");
}
if (fCheckpointsEnabled)
{

21
src/miner.cpp

@ -192,8 +192,22 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus());
pblock->nTime = GetAdjustedTime();
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);
uint32_t expired;
@ -402,8 +416,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
txNew.nExpiryHeight = 0;
// check if coinbase transactions must be time locked at current subsidy and prepend the time lock
// to transaction if so
if (txNew.vout[0].nValue >= ASSETCHAINS_TIMELOCKGTE)
// to transaction if so, cast for GTE operator
if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE)
{
int32_t opretlen, p2shlen, scriptlen;
CScriptExt opretScript = CScriptExt();
@ -769,6 +783,7 @@ void static BitcoinMiner_noeq()
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());
printf("FOUND BLOCK! \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str());
#ifdef ENABLE_WALLET
ProcessBlockFound(pblock, *pwallet, reservekey);
#else

18
src/script/script_ext.cpp

@ -36,7 +36,7 @@ const CScriptExt &CScriptExt::OpReturnScript(const vector<unsigned char> &data,
if (data.size() < MAX_SCRIPT_ELEMENT_SIZE)
{
vector<unsigned char> scratch = vector<unsigned char>(data);
scratch.insert(data.begin(), opretType);
scratch.insert(scratch.begin(), opretType);
*((CScript *)this) << OP_RETURN;
*((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)
const CScriptExt &CScriptExt::AddCheckLockTimeVerify(int64_t unlocktime) const
{
unlocktime = unlocktime < 0 ? 0 : unlocktime;
*((CScript *)this) << CScriptNum::serialize(unlocktime);
*((CScript *)this) << OP_CHECKLOCKTIMEVERIFY;
*((CScript *)this) << OP_DROP;
return *this;
if (unlocktime > 0)
{
*((CScript *)this) << CScriptNum::serialize(unlocktime);
*((CScript *)this) << OP_CHECKLOCKTIMEVERIFY;
*((CScript *)this) << OP_DROP;
return *this;
}
}
// combined CLTV script and P2PKH
@ -78,11 +80,11 @@ bool CScriptExt::IsCheckLockTimeVerify(int64_t *unlockTime) const
{
opcodetype op;
std::vector<unsigned char> unlockTimeParam = std::vector<unsigned char>();
CScript::const_iterator it = this->begin();
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)
{
int i = unlockTimeParam.size() - 1;

Loading…
Cancel
Save