/src/core.h
C Header | 476 lines | 345 code | 84 blank | 47 comment | 36 complexity | e1b49bc587139efb1d464cda64a3257f MD5 | raw file
- // 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.
- #ifndef BITCOIN_CORE_H
- #define BITCOIN_CORE_H
- #include "script.h"
- #include "serialize.h"
- #include "uint256.h"
- #include <stdint.h>
- class CTransaction;
- /** An outpoint - a combination of a transaction hash and an index n into its vout */
- class COutPoint
- {
- public:
- uint256 hash;
- unsigned int n;
- COutPoint() { SetNull(); }
- COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
- IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { hash = 0; n = (unsigned int) -1; }
- bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }
- friend bool operator<(const COutPoint& a, const COutPoint& b)
- {
- return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
- }
- friend bool operator==(const COutPoint& a, const COutPoint& b)
- {
- return (a.hash == b.hash && a.n == b.n);
- }
- friend bool operator!=(const COutPoint& a, const COutPoint& b)
- {
- return !(a == b);
- }
- std::string ToString() const;
- void print() const;
- };
- /** An inpoint - a combination of a transaction and an index n into its vin */
- class CInPoint
- {
- public:
- CTransaction* ptx;
- unsigned int n;
- CInPoint() { SetNull(); }
- CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
- void SetNull() { ptx = NULL; n = (unsigned int) -1; }
- bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
- };
- /** An input of a transaction. It contains the location of the previous
- * transaction's output that it claims and a signature that matches the
- * output's public key.
- */
- class CTxIn
- {
- public:
- COutPoint prevout;
- CScript scriptSig;
- unsigned int nSequence;
- CTxIn()
- {
- nSequence = std::numeric_limits<unsigned int>::max();
- }
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max());
- CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max());
- IMPLEMENT_SERIALIZE
- (
- READWRITE(prevout);
- READWRITE(scriptSig);
- READWRITE(nSequence);
- )
- bool IsFinal() const
- {
- return (nSequence == std::numeric_limits<unsigned int>::max());
- }
- friend bool operator==(const CTxIn& a, const CTxIn& b)
- {
- return (a.prevout == b.prevout &&
- a.scriptSig == b.scriptSig &&
- a.nSequence == b.nSequence);
- }
- friend bool operator!=(const CTxIn& a, const CTxIn& b)
- {
- return !(a == b);
- }
- std::string ToString() const;
- void print() const;
- };
- /** An output of a transaction. It contains the public key that the next input
- * must be able to sign with to claim it.
- */
- class CTxOut
- {
- public:
- int64_t nValue;
- CScript scriptPubKey;
- CTxOut()
- {
- SetNull();
- }
- CTxOut(int64_t nValueIn, CScript scriptPubKeyIn);
- IMPLEMENT_SERIALIZE
- (
- READWRITE(nValue);
- READWRITE(scriptPubKey);
- )
- void SetNull()
- {
- nValue = -1;
- scriptPubKey.clear();
- }
- bool IsNull() const
- {
- return (nValue == -1);
- }
- uint256 GetHash() const;
- bool IsDust(int64_t nMinRelayTxFee) const
- {
- // "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
- // which has units satoshis-per-kilobyte.
- // If you'd pay more than 1/3 in fees
- // to spend something, then we consider it dust.
- // A typical txout is 34 bytes big, and will
- // need a CTxIn of at least 148 bytes to spend,
- // so dust is a txout less than 54 uBTC
- // (5460 satoshis) with default nMinRelayTxFee
- return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee);
- }
- friend bool operator==(const CTxOut& a, const CTxOut& b)
- {
- return (a.nValue == b.nValue &&
- a.scriptPubKey == b.scriptPubKey);
- }
- friend bool operator!=(const CTxOut& a, const CTxOut& b)
- {
- return !(a == b);
- }
- std::string ToString() const;
- void print() const;
- };
- /** The basic transaction that is broadcasted on the network and contained in
- * blocks. A transaction can contain multiple inputs and outputs.
- */
- class CTransaction
- {
- public:
- static int64_t nMinTxFee;
- static int64_t nMinRelayTxFee;
- static const int CURRENT_VERSION=1;
- int nVersion;
- std::vector<CTxIn> vin;
- std::vector<CTxOut> vout;
- unsigned int nLockTime;
- CTransaction()
- {
- SetNull();
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(vin);
- READWRITE(vout);
- READWRITE(nLockTime);
- )
- void SetNull()
- {
- nVersion = CTransaction::CURRENT_VERSION;
- vin.clear();
- vout.clear();
- nLockTime = 0;
- }
- bool IsNull() const
- {
- return (vin.empty() && vout.empty());
- }
- uint256 GetHash() const;
- bool IsNewerThan(const CTransaction& old) const;
- bool IsCoinBase() const
- {
- return (vin.size() == 1 && vin[0].prevout.IsNull());
- }
- friend bool operator==(const CTransaction& a, const CTransaction& b)
- {
- return (a.nVersion == b.nVersion &&
- a.vin == b.vin &&
- a.vout == b.vout &&
- a.nLockTime == b.nLockTime);
- }
- friend bool operator!=(const CTransaction& a, const CTransaction& b)
- {
- return !(a == b);
- }
- std::string ToString() const;
- void print() const;
- };
- /** wrapper for CTxOut that provides a more compact serialization */
- class CTxOutCompressor
- {
- private:
- CTxOut &txout;
- public:
- static uint64_t CompressAmount(uint64_t nAmount);
- static uint64_t DecompressAmount(uint64_t nAmount);
- CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
- IMPLEMENT_SERIALIZE(({
- if (!fRead) {
- uint64_t nVal = CompressAmount(txout.nValue);
- READWRITE(VARINT(nVal));
- } else {
- uint64_t nVal = 0;
- READWRITE(VARINT(nVal));
- txout.nValue = DecompressAmount(nVal);
- }
- CScriptCompressor cscript(REF(txout.scriptPubKey));
- READWRITE(cscript);
- });)
- };
- /** Undo information for a CTxIn
- *
- * Contains the prevout's CTxOut being spent, and if this was the
- * last output of the affected transaction, its metadata as well
- * (coinbase or not, height, transaction version)
- */
- class CTxInUndo
- {
- public:
- CTxOut txout; // the txout data before being spent
- bool fCoinBase; // if the outpoint was the last unspent: whether it belonged to a coinbase
- unsigned int nHeight; // if the outpoint was the last unspent: its height
- int nVersion; // if the outpoint was the last unspent: its version
- CTxInUndo() : txout(), fCoinBase(false), nHeight(0), nVersion(0) {}
- CTxInUndo(const CTxOut &txoutIn, bool fCoinBaseIn = false, unsigned int nHeightIn = 0, int nVersionIn = 0) : txout(txoutIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn), nVersion(nVersionIn) { }
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- return ::GetSerializeSize(VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion) +
- (nHeight > 0 ? ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion) : 0) +
- ::GetSerializeSize(CTxOutCompressor(REF(txout)), nType, nVersion);
- }
- template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
- ::Serialize(s, VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion);
- if (nHeight > 0)
- ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
- ::Serialize(s, CTxOutCompressor(REF(txout)), nType, nVersion);
- }
- template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
- unsigned int nCode = 0;
- ::Unserialize(s, VARINT(nCode), nType, nVersion);
- nHeight = nCode / 2;
- fCoinBase = nCode & 1;
- if (nHeight > 0)
- ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
- ::Unserialize(s, REF(CTxOutCompressor(REF(txout))), nType, nVersion);
- }
- };
- /** Undo information for a CTransaction */
- class CTxUndo
- {
- public:
- // undo information for all txins
- std::vector<CTxInUndo> vprevout;
- IMPLEMENT_SERIALIZE(
- READWRITE(vprevout);
- )
- };
- /** Nodes collect new transactions into a block, hash them into a hash tree,
- * and scan through nonce values to make the block's hash satisfy proof-of-work
- * requirements. When they solve the proof-of-work, they broadcast the block
- * to everyone and the block is added to the block chain. The first transaction
- * in the block is a special one that creates a new coin owned by the creator
- * of the block.
- */
- class CBlockHeader
- {
- public:
- // header
- static const int CURRENT_VERSION=2;
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- CBlockHeader()
- {
- SetNull();
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(hashPrevBlock);
- READWRITE(hashMerkleRoot);
- READWRITE(nTime);
- READWRITE(nBits);
- READWRITE(nNonce);
- )
- void SetNull()
- {
- nVersion = CBlockHeader::CURRENT_VERSION;
- hashPrevBlock = 0;
- hashMerkleRoot = 0;
- nTime = 0;
- nBits = 0;
- nNonce = 0;
- }
- bool IsNull() const
- {
- return (nBits == 0);
- }
- uint256 GetHash() const;
- int64_t GetBlockTime() const
- {
- return (int64_t)nTime;
- }
- };
- class CBlock : public CBlockHeader
- {
- public:
- // network and disk
- std::vector<CTransaction> vtx;
- // memory only
- mutable std::vector<uint256> vMerkleTree;
- CBlock()
- {
- SetNull();
- }
- CBlock(const CBlockHeader &header)
- {
- SetNull();
- *((CBlockHeader*)this) = header;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(*(CBlockHeader*)this);
- READWRITE(vtx);
- )
- void SetNull()
- {
- CBlockHeader::SetNull();
- vtx.clear();
- vMerkleTree.clear();
- }
- CBlockHeader GetBlockHeader() const
- {
- CBlockHeader block;
- block.nVersion = nVersion;
- block.hashPrevBlock = hashPrevBlock;
- block.hashMerkleRoot = hashMerkleRoot;
- block.nTime = nTime;
- block.nBits = nBits;
- block.nNonce = nNonce;
- return block;
- }
- uint256 BuildMerkleTree() const;
- const uint256 &GetTxHash(unsigned int nIndex) const {
- assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
- assert(nIndex < vtx.size());
- return vMerkleTree[nIndex];
- }
- std::vector<uint256> GetMerkleBranch(int nIndex) const;
- static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
- void print() const;
- };
- /** Describes a place in the block chain to another node such that if the
- * other node doesn't have the same branch, it can find a recent common trunk.
- * The further back it is, the further before the fork it may be.
- */
- struct CBlockLocator
- {
- std::vector<uint256> vHave;
- CBlockLocator() {}
- CBlockLocator(const std::vector<uint256>& vHaveIn)
- {
- vHave = vHaveIn;
- }
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vHave);
- )
- void SetNull()
- {
- vHave.clear();
- }
- bool IsNull()
- {
- return vHave.empty();
- }
- };
- #endif