diff options
Diffstat (limited to 'src/core.cpp')
-rw-r--r-- | src/core.cpp | 339 |
1 files changed, 0 insertions, 339 deletions
diff --git a/src/core.cpp b/src/core.cpp deleted file mode 100644 index 73e6de88e1..0000000000 --- a/src/core.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "core.h" - -#include "hash.h" -#include "tinyformat.h" -#include "utilstrencodings.h" - -std::string COutPoint::ToString() const -{ - return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n); -} - -CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn) -{ - prevout = prevoutIn; - scriptSig = scriptSigIn; - nSequence = nSequenceIn; -} - -CTxIn::CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn) -{ - prevout = COutPoint(hashPrevTx, nOut); - scriptSig = scriptSigIn; - nSequence = nSequenceIn; -} - -std::string CTxIn::ToString() const -{ - std::string str; - str += "CTxIn("; - str += prevout.ToString(); - if (prevout.IsNull()) - str += strprintf(", coinbase %s", HexStr(scriptSig)); - else - str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24)); - if (nSequence != std::numeric_limits<unsigned int>::max()) - str += strprintf(", nSequence=%u", nSequence); - str += ")"; - return str; -} - -CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn) -{ - nValue = nValueIn; - scriptPubKey = scriptPubKeyIn; -} - -uint256 CTxOut::GetHash() const -{ - return SerializeHash(*this); -} - -std::string CTxOut::ToString() const -{ - return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30)); -} - -CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) -{ - if (nSize > 0) - nSatoshisPerK = nFeePaid*1000/nSize; - else - nSatoshisPerK = 0; -} - -CAmount CFeeRate::GetFee(size_t nSize) const -{ - CAmount nFee = nSatoshisPerK*nSize / 1000; - - if (nFee == 0 && nSatoshisPerK > 0) - nFee = nSatoshisPerK; - - return nFee; -} - -std::string CFeeRate::ToString() const -{ - return strprintf("%d.%08d BTC/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN); -} - -CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {} -CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {} - -uint256 CMutableTransaction::GetHash() const -{ - return SerializeHash(*this); -} - -void CTransaction::UpdateHash() const -{ - *const_cast<uint256*>(&hash) = SerializeHash(*this); -} - -CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } - -CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { - UpdateHash(); -} - -CTransaction& CTransaction::operator=(const CTransaction &tx) { - *const_cast<int*>(&nVersion) = tx.nVersion; - *const_cast<std::vector<CTxIn>*>(&vin) = tx.vin; - *const_cast<std::vector<CTxOut>*>(&vout) = tx.vout; - *const_cast<unsigned int*>(&nLockTime) = tx.nLockTime; - *const_cast<uint256*>(&hash) = tx.hash; - return *this; -} - -CAmount CTransaction::GetValueOut() const -{ - CAmount nValueOut = 0; - for (std::vector<CTxOut>::const_iterator it(vout.begin()); it != vout.end(); ++it) - { - nValueOut += it->nValue; - if (!MoneyRange(it->nValue) || !MoneyRange(nValueOut)) - throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); - } - return nValueOut; -} - -double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSize) const -{ - nTxSize = CalculateModifiedSize(nTxSize); - if (nTxSize == 0) return 0.0; - - return dPriorityInputs / nTxSize; -} - -unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const -{ - // In order to avoid disincentivizing cleaning up the UTXO set we don't count - // the constant overhead for each txin and up to 110 bytes of scriptSig (which - // is enough to cover a compressed pubkey p2sh redemption) for priority. - // Providing any more cleanup incentive than making additional inputs free would - // risk encouraging people to create junk outputs to redeem later. - if (nTxSize == 0) - nTxSize = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); - for (std::vector<CTxIn>::const_iterator it(vin.begin()); it != vin.end(); ++it) - { - unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size()); - if (nTxSize > offset) - nTxSize -= offset; - } - return nTxSize; -} - -std::string CTransaction::ToString() const -{ - std::string str; - str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n", - GetHash().ToString().substr(0,10), - nVersion, - vin.size(), - vout.size(), - nLockTime); - for (unsigned int i = 0; i < vin.size(); i++) - str += " " + vin[i].ToString() + "\n"; - for (unsigned int i = 0; i < vout.size(); i++) - str += " " + vout[i].ToString() + "\n"; - return str; -} - -// Amount compression: -// * If the amount is 0, output 0 -// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9) -// * if e<9, the last digit of the resulting number cannot be 0; store it as d, and drop it (divide by 10) -// * call the result n -// * output 1 + 10*(9*n + d - 1) + e -// * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9 -// (this is decodable, as d is in [1-9] and e is in [0-9]) - -uint64_t CTxOutCompressor::CompressAmount(uint64_t n) -{ - if (n == 0) - return 0; - int e = 0; - while (((n % 10) == 0) && e < 9) { - n /= 10; - e++; - } - if (e < 9) { - int d = (n % 10); - assert(d >= 1 && d <= 9); - n /= 10; - return 1 + (n*9 + d - 1)*10 + e; - } else { - return 1 + (n - 1)*10 + 9; - } -} - -uint64_t CTxOutCompressor::DecompressAmount(uint64_t x) -{ - // x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9 - if (x == 0) - return 0; - x--; - // x = 10*(9*n + d - 1) + e - int e = x % 10; - x /= 10; - uint64_t n = 0; - if (e < 9) { - // x = 9*n + d - 1 - int d = (x % 9) + 1; - x /= 9; - // x = n - n = x*10 + d; - } else { - n = x+1; - } - while (e) { - n *= 10; - e--; - } - return n; -} - -uint256 CBlockHeader::GetHash() const -{ - return Hash(BEGIN(nVersion), END(nNonce)); -} - -uint256 CBlock::BuildMerkleTree(bool* fMutated) const -{ - /* WARNING! If you're reading this because you're learning about crypto - and/or designing a new system that will use merkle trees, keep in mind - that the following merkle tree algorithm has a serious flaw related to - duplicate txids, resulting in a vulnerability (CVE-2012-2459). - - The reason is that if the number of hashes in the list at a given time - is odd, the last one is duplicated before computing the next level (which - is unusual in Merkle trees). This results in certain sequences of - transactions leading to the same merkle root. For example, these two - trees: - - A A - / \ / \ - B C B C - / \ | / \ / \ - D E F D E F F - / \ / \ / \ / \ / \ / \ / \ - 1 2 3 4 5 6 1 2 3 4 5 6 5 6 - - for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and - 6 are repeated) result in the same root hash A (because the hash of both - of (F) and (F,F) is C). - - The vulnerability results from being able to send a block with such a - transaction list, with the same merkle root, and the same block hash as - the original without duplication, resulting in failed validation. If the - receiving node proceeds to mark that block as permanently invalid - however, it will fail to accept further unmodified (and thus potentially - valid) versions of the same block. We defend against this by detecting - the case where we would hash two identical hashes at the end of the list - together, and treating that identically to the block having an invalid - merkle root. Assuming no double-SHA256 collisions, this will detect all - known ways of changing the transactions without affecting the merkle - root. - */ - vMerkleTree.clear(); - vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. - for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it) - vMerkleTree.push_back(it->GetHash()); - int j = 0; - bool mutated = false; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) - { - for (int i = 0; i < nSize; i += 2) - { - int i2 = std::min(i+1, nSize-1); - if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) { - // Two identical hashes at the end of the list at a particular level. - mutated = true; - } - vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), - BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); - } - j += nSize; - } - if (fMutated) { - *fMutated = mutated; - } - return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); -} - -std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const -{ - if (vMerkleTree.empty()) - BuildMerkleTree(); - std::vector<uint256> vMerkleBranch; - int j = 0; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) - { - int i = std::min(nIndex^1, nSize-1); - vMerkleBranch.push_back(vMerkleTree[j+i]); - nIndex >>= 1; - j += nSize; - } - return vMerkleBranch; -} - -uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex) -{ - if (nIndex == -1) - return 0; - for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it) - { - if (nIndex & 1) - hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); - else - hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); - nIndex >>= 1; - } - return hash; -} - -std::string CBlock::ToString() const -{ - std::stringstream s; - s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", - GetHash().ToString(), - nVersion, - hashPrevBlock.ToString(), - hashMerkleRoot.ToString(), - nTime, nBits, nNonce, - vtx.size()); - for (unsigned int i = 0; i < vtx.size(); i++) - { - s << " " << vtx[i].ToString() << "\n"; - } - s << " vMerkleTree: "; - for (unsigned int i = 0; i < vMerkleTree.size(); i++) - s << " " << vMerkleTree[i].ToString(); - s << "\n"; - return s.str(); -} |