// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 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 "util.h" std::string COutPoint::ToString() const { return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n); } void COutPoint::print() const { LogPrintf("%s\n", ToString().c_str()); } CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, unsigned int nSequenceIn) { prevout = prevoutIn; scriptSig = scriptSigIn; nSequence = nSequenceIn; } CTxIn::CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn, unsigned int 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).c_str()); else str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str()); if (nSequence != std::numeric_limits::max()) str += strprintf(", nSequence=%u", nSequence); str += ")"; return str; } void CTxIn::print() const { LogPrintf("%s\n", ToString().c_str()); } CTxOut::CTxOut(int64_t nValueIn, CScript scriptPubKeyIn) { nValue = nValueIn; scriptPubKey = scriptPubKeyIn; } uint256 CTxOut::GetHash() const { return SerializeHash(*this); } std::string CTxOut::ToString() const { return strprintf("CTxOut(nValue=%"PRId64".%08"PRId64", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str()); } void CTxOut::print() const { LogPrintf("%s\n", ToString().c_str()); } uint256 CTransaction::GetHash() const { return SerializeHash(*this); } bool CTransaction::IsNewerThan(const CTransaction& old) const { if (vin.size() != old.vin.size()) return false; for (unsigned int i = 0; i < vin.size(); i++) if (vin[i].prevout != old.vin[i].prevout) return false; bool fNewer = false; unsigned int nLowest = std::numeric_limits::max(); for (unsigned int i = 0; i < vin.size(); i++) { if (vin[i].nSequence != old.vin[i].nSequence) { if (vin[i].nSequence <= nLowest) { fNewer = false; nLowest = vin[i].nSequence; } if (old.vin[i].nSequence < nLowest) { fNewer = true; nLowest = old.vin[i].nSequence; } } } return fNewer; } std::string CTransaction::ToString() const { std::string str; str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n", GetHash().ToString().substr(0,10).c_str(), 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; } void CTransaction::print() const { LogPrintf("%s", ToString().c_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() const { vMerkleTree.clear(); BOOST_FOREACH(const CTransaction& tx, vtx) vMerkleTree.push_back(tx.GetHash()); int j = 0; 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); vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); } j += nSize; } return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); } std::vector CBlock::GetMerkleBranch(int nIndex) const { if (vMerkleTree.empty()) BuildMerkleTree(); std::vector 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& vMerkleBranch, int nIndex) { if (nIndex == -1) return 0; BOOST_FOREACH(const uint256& otherside, vMerkleBranch) { if (nIndex & 1) hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); else hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside)); nIndex >>= 1; } return hash; } void CBlock::print() const { LogPrintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n", GetHash().ToString().c_str(), nVersion, hashPrevBlock.ToString().c_str(), hashMerkleRoot.ToString().c_str(), nTime, nBits, nNonce, vtx.size()); for (unsigned int i = 0; i < vtx.size(); i++) { LogPrintf(" "); vtx[i].print(); } LogPrintf(" vMerkleTree: "); for (unsigned int i = 0; i < vMerkleTree.size(); i++) LogPrintf("%s ", vMerkleTree[i].ToString().c_str()); LogPrintf("\n"); }