X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=aaa8c52dca62c15c1c612d20b6d82ff17597bea4;hb=36d2ec199438bb189921d8adf12ad77fee1d969e;hp=70bdce48870bdcc87b33ce0856bd543db486d057;hpb=42c55f2e8a14a2f1c504cfe62e3d1717e8ac5454;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index 70bdce4..aaa8c52 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -139,7 +139,7 @@ void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate, { if (!fConnect) { - // ppcoin: wallets need to refund inputs when disconnecting coinstake + // wallets need to refund inputs when disconnecting coinstake if (tx.IsCoinStake()) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) @@ -430,9 +430,14 @@ unsigned int CTransaction::GetLegacySigOpCount() const { unsigned int nSigOps = 0; - BOOST_FOREACH(const CTxIn& txin, vin) + if (!IsCoinBase() || nTime < COINBASE_SIGOPS_SWITCH_TIME) { - nSigOps += txin.scriptSig.GetSigOpCount(false); + // Coinbase scriptsigs are never executed, so there is + // no sense in calculation of sigops. + BOOST_FOREACH(const CTxIn& txin, vin) + { + nSigOps += txin.scriptSig.GetSigOpCount(false); + } } BOOST_FOREACH(const CTxOut& txout, vout) { @@ -557,7 +562,7 @@ int64_t CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, enum G if(IsCoinStake()) { - // Enforce 0.01 as minimum fee for old approach or coinstake + // Enforce 0.01 as minimum fee for coinstake nMinTxFee = CENT; nMinRelayTxFee = CENT; } @@ -732,7 +737,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false, true, SIG_SWITCH_TIME < tx.nTime ? STRICT_FLAGS : SOFT_FLAGS)) + if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false, true, STRICT_FLAGS)) { return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); } @@ -1061,85 +1066,61 @@ int64_t GetProofOfStakeReward(int64_t nCoinAge, unsigned int nBits, int64_t nTim { int64_t nRewardCoinYear, nSubsidy, nSubsidyLimit = 10 * COIN; - if(fTestNet || nTime > STAKE_SWITCH_TIME) - { - // Stage 2 of emission process is PoS-based. It will be active on mainNet since 20 Jun 2013. + // Stage 2 of emission process is mostly PoS-based. - CBigNum bnRewardCoinYearLimit = MAX_MINT_PROOF_OF_STAKE; // Base stake mint rate, 100% year interest - CBigNum bnTarget; - bnTarget.SetCompact(nBits); - CBigNum bnTargetLimit = GetProofOfStakeLimit(0, nTime); - bnTargetLimit.SetCompact(bnTargetLimit.GetCompact()); + CBigNum bnRewardCoinYearLimit = MAX_MINT_PROOF_OF_STAKE; // Base stake mint rate, 100% year interest + CBigNum bnTarget; + bnTarget.SetCompact(nBits); + CBigNum bnTargetLimit = GetProofOfStakeLimit(0, nTime); + bnTargetLimit.SetCompact(bnTargetLimit.GetCompact()); - // NovaCoin: A reasonably continuous curve is used to avoid shock to market + // A reasonably continuous curve is used to avoid shock to market - CBigNum bnLowerBound = 1 * CENT, // Lower interest bound is 1% per year - bnUpperBound = bnRewardCoinYearLimit, // Upper interest bound is 100% per year - bnMidPart, bnRewardPart; + CBigNum bnLowerBound = 1 * CENT, // Lower interest bound is 1% per year + bnUpperBound = bnRewardCoinYearLimit, // Upper interest bound is 100% per year + bnMidPart, bnRewardPart; - while (bnLowerBound + CENT <= bnUpperBound) - { - CBigNum bnMidValue = (bnLowerBound + bnUpperBound) / 2; - if(!fTestNet && nTime < STAKECURVE_SWITCH_TIME) - { - // - // Until 20 Oct 2013: reward for coin-year is cut in half every 64x multiply of PoS difficulty - // - // (nRewardCoinYearLimit / nRewardCoinYear) ** 6 == bnProofOfStakeLimit / bnTarget - // - // Human readable form: nRewardCoinYear = 1 / (posdiff ^ 1/6) - // - - bnMidPart = bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnMidValue; - bnRewardPart = bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit; - } - else - { - // - // Since 20 Oct 2013: reward for coin-year is cut in half every 8x multiply of PoS difficulty - // - // (nRewardCoinYearLimit / nRewardCoinYear) ** 3 == bnProofOfStakeLimit / bnTarget - // - // Human readable form: nRewardCoinYear = 1 / (posdiff ^ 1/3) - // - - bnMidPart = bnMidValue * bnMidValue * bnMidValue; - bnRewardPart = bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit; - } + while (bnLowerBound + CENT <= bnUpperBound) + { + CBigNum bnMidValue = (bnLowerBound + bnUpperBound) / 2; - if (bnMidPart * bnTargetLimit > bnRewardPart * bnTarget) - bnUpperBound = bnMidValue; - else - bnLowerBound = bnMidValue; - } + // + // Reward for coin-year is cut in half every 8x multiply of PoS difficulty + // + // (nRewardCoinYearLimit / nRewardCoinYear) ** 3 == bnProofOfStakeLimit / bnTarget + // + // Human readable form: nRewardCoinYear = 1 / (posdiff ^ 1/3) + // - nRewardCoinYear = bnUpperBound.getuint64(); - nRewardCoinYear = min((nRewardCoinYear / CENT) * CENT, MAX_MINT_PROOF_OF_STAKE); - } - else - { - // Old creation amount per coin-year, 5% fixed stake mint rate - nRewardCoinYear = 5 * CENT; + bnMidPart = bnMidValue * bnMidValue * bnMidValue; + bnRewardPart = bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit; + + if (bnMidPart * bnTargetLimit > bnRewardPart * bnTarget) + bnUpperBound = bnMidValue; + else + bnLowerBound = bnMidValue; } + nRewardCoinYear = bnUpperBound.getuint64(); + nRewardCoinYear = min((nRewardCoinYear / CENT) * CENT, MAX_MINT_PROOF_OF_STAKE); + if(bCoinYearOnly) return nRewardCoinYear; nSubsidy = nCoinAge * nRewardCoinYear * 33 / (365 * 33 + 8); - // Set reasonable reward limit for large inputs since 20 Oct 2013 + // Set reasonable reward limit for large inputs // // This will stimulate large holders to use smaller inputs, that's good for the network protection - if(fTestNet || STAKECURVE_SWITCH_TIME < nTime) - { - if (fDebug && GetBoolArg("-printcreation") && nSubsidyLimit < nSubsidy) - printf("GetProofOfStakeReward(): %s is greater than %s, coinstake reward will be truncated\n", FormatMoney(nSubsidy).c_str(), FormatMoney(nSubsidyLimit).c_str()); - nSubsidy = min(nSubsidy, nSubsidyLimit); - } + if (fDebug && GetBoolArg("-printcreation") && nSubsidyLimit < nSubsidy) + printf("GetProofOfStakeReward(): %s is greater than %s, coinstake reward will be truncated\n", FormatMoney(nSubsidy).c_str(), FormatMoney(nSubsidyLimit).c_str()); + + nSubsidy = min(nSubsidy, nSubsidyLimit); if (fDebug && GetBoolArg("-printcreation")) printf("GetProofOfStakeReward(): create=%s nCoinAge=%" PRId64 " nBits=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge, nBits); + return nSubsidy; } @@ -1571,18 +1552,21 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs, map Checkpoints::GetLastCheckpointTime()) + { + unsigned int nTxSize = GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION); - unsigned int nTxSize = (nTime > VALIDATION_SWITCH_TIME || fTestNet) ? GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) : 0; + // coin stake tx earns reward instead of paying fee + uint64_t nCoinAge; + if (!GetCoinAge(txdb, nCoinAge)) + return error("ConnectInputs() : %s unable to get coin age for coinstake", GetHash().ToString().substr(0,10).c_str()); - int64_t nReward = GetValueOut() - nValueIn; - int64_t nCalculatedReward = GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime) - GetMinFee(1, false, GMF_BLOCK, nTxSize) + CENT; + int64_t nReward = GetValueOut() - nValueIn; + int64_t nCalculatedReward = GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime) - GetMinFee(1, false, GMF_BLOCK, nTxSize) + CENT; - if (nReward > nCalculatedReward) - return DoS(100, error("ConnectInputs() : coinstake pays too much(actual=%" PRId64 " vs calculated=%" PRId64 ")", nReward, nCalculatedReward)); + if (nReward > nCalculatedReward) + return DoS(100, error("ConnectInputs() : coinstake pays too much(actual=%" PRId64 " vs calculated=%" PRId64 ")", nReward, nCalculatedReward)); + } } else { @@ -2413,21 +2397,9 @@ uint256 CBlockIndex::GetBlockTrust() const if (bnTarget <= 0) return 0; - /* Old protocol */ - if (!fTestNet && GetBlockTime() < CHAINCHECKS_SWITCH_TIME) - return (IsProofOfStake()? ((CBigNum(1)<<256) / (bnTarget+1)).getuint256() : 1); - - /* New protocol */ - - // Calculate work amount for block - uint256 nPoWTrust = (CBigNum(nPoWBase) / (bnTarget+1)).getuint256(); - - // Set nPowTrust to 1 if we are checking PoS block or PoW difficulty is too low - nPoWTrust = (IsProofOfStake() || nPoWTrust < 1) ? 1 : nPoWTrust; - - // Return nPoWTrust for the first 12 blocks + // Return 1 for the first 12 blocks if (pprev == NULL || pprev->nHeight < 12) - return nPoWTrust; + return 1; const CBlockIndex* currentIndex = pprev; @@ -2457,11 +2429,18 @@ uint256 CBlockIndex::GetBlockTrust() const } else { + // Calculate work amount for block + CBigNum bnPoWTrust = CBigNum(nPoWBase) / (bnTarget+1); + + // Set nPowTrust to 1 if PoW difficulty is too low + if (bnPoWTrust < 1) + bnPoWTrust = 1; + CBigNum bnLastBlockTrust = CBigNum(pprev->nChainTrust - pprev->pprev->nChainTrust); // Return nPoWTrust + 2/3 of previous block score if two parent blocks are not PoS blocks if (!(pprev->IsProofOfStake() && pprev->pprev->IsProofOfStake())) - return nPoWTrust + (2 * bnLastBlockTrust / 3).getuint256(); + return (bnPoWTrust + 2 * bnLastBlockTrust / 3).getuint256(); int nPoSCount = 0; @@ -2475,7 +2454,7 @@ uint256 CBlockIndex::GetBlockTrust() const // Return nPoWTrust + 2/3 of previous block score if less than 7 PoS blocks found if (nPoSCount < 7) - return nPoWTrust + (2 * bnLastBlockTrust / 3).getuint256(); + return (bnPoWTrust + 2 * bnLastBlockTrust / 3).getuint256(); bnTarget.SetCompact(pprev->nBits); @@ -2485,7 +2464,7 @@ uint256 CBlockIndex::GetBlockTrust() const CBigNum bnNewTrust = (CBigNum(1)<<256) / (bnTarget+1); // Return nPoWTrust + full trust score for previous block nBits - return nPoWTrust + bnNewTrust.getuint256(); + return (bnPoWTrust + bnNewTrust).getuint256(); } } @@ -2650,26 +2629,23 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) // ppcoin: check block signature bool CBlock::CheckBlockSignature() const { - if (IsProofOfWork()) - return true; + if (vchBlockSig.empty()) + return false; - vector vSolutions; txnouttype whichType; - - const CTxOut& txout = vtx[1].vout[1]; - - if (!Solver(txout.scriptPubKey, whichType, vSolutions)) + vector vSolutions; + if (!Solver(vtx[1].vout[1].scriptPubKey, whichType, vSolutions)) return false; + if (whichType == TX_PUBKEY) { valtype& vchPubKey = vSolutions[0]; CKey key; if (!key.SetPubKey(vchPubKey)) return false; - if (vchBlockSig.empty()) - return false; return key.Verify(GetHash(), vchBlockSig); } + return false; } @@ -3007,7 +2983,7 @@ bool LoadExternalBlockFile(FILE* fileIn) } } } - catch (std::exception &e) { + catch (const std::exception&) { printf("%s() : Deserialize or I/O error caught during load\n", BOOST_CURRENT_FUNCTION); }