Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615082
main.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
36 KB
Subscribers
None
main.h
View Options
// 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.
#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
#if defined(HAVE_CONFIG_H)
#include
"bitcoin-config.h"
#endif
#include
"bignum.h"
#include
"chainparams.h"
#include
"coins.h"
#include
"core.h"
#include
"net.h"
#include
"script.h"
#include
"sync.h"
#include
"txmempool.h"
#include
"uint256.h"
#include
<algorithm>
#include
<exception>
#include
<map>
#include
<set>
#include
<stdint.h>
#include
<string>
#include
<utility>
#include
<vector>
class
CBlockIndex
;
class
CBloomFilter
;
class
CInv
;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static
const
unsigned
int
MAX_BLOCK_SIZE
=
1000000
;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static
const
unsigned
int
DEFAULT_BLOCK_MAX_SIZE
=
750000
;
static
const
unsigned
int
DEFAULT_BLOCK_MIN_SIZE
=
0
;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static
const
unsigned
int
DEFAULT_BLOCK_PRIORITY_SIZE
=
50000
;
/** The maximum size for transactions we're willing to relay/mine */
static
const
unsigned
int
MAX_STANDARD_TX_SIZE
=
100000
;
/** The maximum allowed number of signature check operations in a block (network rule) */
static
const
unsigned
int
MAX_BLOCK_SIGOPS
=
MAX_BLOCK_SIZE
/
50
;
/** The maximum number of orphan transactions kept in memory */
static
const
unsigned
int
MAX_ORPHAN_TRANSACTIONS
=
MAX_BLOCK_SIZE
/
100
;
/** The maximum number of orphan blocks kept in memory */
static
const
unsigned
int
MAX_ORPHAN_BLOCKS
=
750
;
/** The maximum size of a blk?????.dat file (since 0.8) */
static
const
unsigned
int
MAX_BLOCKFILE_SIZE
=
0x8000000
;
// 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
static
const
unsigned
int
BLOCKFILE_CHUNK_SIZE
=
0x1000000
;
// 16 MiB
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
static
const
unsigned
int
UNDOFILE_CHUNK_SIZE
=
0x100000
;
// 1 MiB
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static
const
int
COINBASE_MATURITY
=
100
;
/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */
static
const
unsigned
int
LOCKTIME_THRESHOLD
=
500000000
;
// Tue Nov 5 00:53:20 1985 UTC
/** Maximum number of script-checking threads allowed */
static
const
int
MAX_SCRIPTCHECK_THREADS
=
16
;
/** -par default (number of script-checking threads, 0 = auto) */
static
const
int
DEFAULT_SCRIPTCHECK_THREADS
=
0
;
/** Number of blocks that can be requested at any given time from a single peer. */
static
const
int
MAX_BLOCKS_IN_TRANSIT_PER_PEER
=
128
;
/** Timeout in seconds before considering a block download peer unresponsive. */
static
const
unsigned
int
BLOCK_DOWNLOAD_TIMEOUT
=
60
;
#ifdef USE_UPNP
static
const
int
fHaveUPnP
=
true
;
#else
static
const
int
fHaveUPnP
=
false
;
#endif
/** "reject" message codes **/
static
const
unsigned
char
REJECT_MALFORMED
=
0x01
;
static
const
unsigned
char
REJECT_INVALID
=
0x10
;
static
const
unsigned
char
REJECT_OBSOLETE
=
0x11
;
static
const
unsigned
char
REJECT_DUPLICATE
=
0x12
;
static
const
unsigned
char
REJECT_NONSTANDARD
=
0x40
;
static
const
unsigned
char
REJECT_DUST
=
0x41
;
static
const
unsigned
char
REJECT_INSUFFICIENTFEE
=
0x42
;
static
const
unsigned
char
REJECT_CHECKPOINT
=
0x43
;
extern
CScript
COINBASE_FLAGS
;
extern
CCriticalSection
cs_main
;
extern
CTxMemPool
mempool
;
extern
std
::
map
<
uint256
,
CBlockIndex
*>
mapBlockIndex
;
extern
uint64_t
nLastBlockTx
;
extern
uint64_t
nLastBlockSize
;
extern
const
std
::
string
strMessageMagic
;
extern
int64_t
nTimeBestReceived
;
extern
bool
fImporting
;
extern
bool
fReindex
;
extern
bool
fBenchmark
;
extern
int
nScriptCheckThreads
;
extern
bool
fTxIndex
;
extern
unsigned
int
nCoinCacheSize
;
// Minimum disk space required - used in CheckDiskSpace()
static
const
uint64_t
nMinDiskSpace
=
52428800
;
class
CCoinsDB
;
class
CBlockTreeDB
;
struct
CDiskBlockPos
;
class
CTxUndo
;
class
CScriptCheck
;
class
CValidationState
;
class
CWalletInterface
;
struct
CNodeStateStats
;
struct
CBlockTemplate
;
/** Register a wallet to receive updates from core */
void
RegisterWallet
(
CWalletInterface
*
pwalletIn
);
/** Unregister a wallet from core */
void
UnregisterWallet
(
CWalletInterface
*
pwalletIn
);
/** Unregister all wallets from core */
void
UnregisterAllWallets
();
/** Push an updated transaction to all registered wallets */
void
SyncWithWallets
(
const
uint256
&
hash
,
const
CTransaction
&
tx
,
const
CBlock
*
pblock
=
NULL
);
/** Register with a network node to receive its signals */
void
RegisterNodeSignals
(
CNodeSignals
&
nodeSignals
);
/** Unregister a network node */
void
UnregisterNodeSignals
(
CNodeSignals
&
nodeSignals
);
void
PushGetBlocks
(
CNode
*
pnode
,
CBlockIndex
*
pindexBegin
,
uint256
hashEnd
);
/** Process an incoming block */
bool
ProcessBlock
(
CValidationState
&
state
,
CNode
*
pfrom
,
CBlock
*
pblock
,
CDiskBlockPos
*
dbp
=
NULL
);
/** Check whether enough disk space is available for an incoming block */
bool
CheckDiskSpace
(
uint64_t
nAdditionalBytes
=
0
);
/** Open a block file (blk?????.dat) */
FILE
*
OpenBlockFile
(
const
CDiskBlockPos
&
pos
,
bool
fReadOnly
=
false
);
/** Open an undo file (rev?????.dat) */
FILE
*
OpenUndoFile
(
const
CDiskBlockPos
&
pos
,
bool
fReadOnly
=
false
);
/** Import blocks from an external file */
bool
LoadExternalBlockFile
(
FILE
*
fileIn
,
CDiskBlockPos
*
dbp
=
NULL
);
/** Initialize a new block tree database + block data on disk */
bool
InitBlockIndex
();
/** Load the block tree and coins database from disk */
bool
LoadBlockIndex
();
/** Unload database information */
void
UnloadBlockIndex
();
/** Verify consistency of the block and coin databases */
bool
VerifyDB
(
int
nCheckLevel
,
int
nCheckDepth
);
/** Print the loaded block tree */
void
PrintBlockTree
();
/** Process protocol messages received from a given node */
bool
ProcessMessages
(
CNode
*
pfrom
);
/** Send queued protocol messages to be sent to a give node */
bool
SendMessages
(
CNode
*
pto
,
bool
fSendTrickle
);
/** Run an instance of the script checking thread */
void
ThreadScriptCheck
();
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool
CheckProofOfWork
(
uint256
hash
,
unsigned
int
nBits
);
/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */
unsigned
int
ComputeMinWork
(
unsigned
int
nBase
,
int64_t
nTime
);
/** Get the number of active peers */
int
GetNumBlocksOfPeers
();
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool
IsInitialBlockDownload
();
/** Format a string that describes several potential problems detected by the core */
std
::
string
GetWarnings
(
std
::
string
strFor
);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool
GetTransaction
(
const
uint256
&
hash
,
CTransaction
&
tx
,
uint256
&
hashBlock
,
bool
fAllowSlow
=
false
);
/** Find the best known block, and make it the tip of the block chain */
bool
ActivateBestChain
(
CValidationState
&
state
);
int64_t
GetBlockValue
(
int
nHeight
,
int64_t
nFees
);
unsigned
int
GetNextWorkRequired
(
const
CBlockIndex
*
pindexLast
,
const
CBlockHeader
*
pblock
);
void
UpdateTime
(
CBlockHeader
&
block
,
const
CBlockIndex
*
pindexPrev
);
/** Create a new block index entry for a given block hash */
CBlockIndex
*
InsertBlockIndex
(
uint256
hash
);
/** Verify a signature */
bool
VerifySignature
(
const
CCoins
&
txFrom
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
unsigned
int
flags
,
int
nHashType
);
/** Abort with a message */
bool
AbortNode
(
const
std
::
string
&
msg
);
/** Get statistics from node state */
bool
GetNodeStateStats
(
NodeId
nodeid
,
CNodeStateStats
&
stats
);
/** Increase a node's misbehavior score. */
void
Misbehaving
(
NodeId
nodeid
,
int
howmuch
);
/** (try to) add transaction to memory pool **/
bool
AcceptToMemoryPool
(
CTxMemPool
&
pool
,
CValidationState
&
state
,
const
CTransaction
&
tx
,
bool
fLimitFree
,
bool
*
pfMissingInputs
,
bool
fRejectInsaneFee
=
false
);
struct
CNodeStateStats
{
int
nMisbehavior
;
};
struct
CDiskBlockPos
{
int
nFile
;
unsigned
int
nPos
;
IMPLEMENT_SERIALIZE
(
READWRITE
(
VARINT
(
nFile
));
READWRITE
(
VARINT
(
nPos
));
)
CDiskBlockPos
()
{
SetNull
();
}
CDiskBlockPos
(
int
nFileIn
,
unsigned
int
nPosIn
)
{
nFile
=
nFileIn
;
nPos
=
nPosIn
;
}
friend
bool
operator
==
(
const
CDiskBlockPos
&
a
,
const
CDiskBlockPos
&
b
)
{
return
(
a
.
nFile
==
b
.
nFile
&&
a
.
nPos
==
b
.
nPos
);
}
friend
bool
operator
!=
(
const
CDiskBlockPos
&
a
,
const
CDiskBlockPos
&
b
)
{
return
!
(
a
==
b
);
}
void
SetNull
()
{
nFile
=
-1
;
nPos
=
0
;
}
bool
IsNull
()
const
{
return
(
nFile
==
-1
);
}
};
struct
CDiskTxPos
:
public
CDiskBlockPos
{
unsigned
int
nTxOffset
;
// after header
IMPLEMENT_SERIALIZE
(
READWRITE
(
*
(
CDiskBlockPos
*
)
this
);
READWRITE
(
VARINT
(
nTxOffset
));
)
CDiskTxPos
(
const
CDiskBlockPos
&
blockIn
,
unsigned
int
nTxOffsetIn
)
:
CDiskBlockPos
(
blockIn
.
nFile
,
blockIn
.
nPos
),
nTxOffset
(
nTxOffsetIn
)
{
}
CDiskTxPos
()
{
SetNull
();
}
void
SetNull
()
{
CDiskBlockPos
::
SetNull
();
nTxOffset
=
0
;
}
};
enum
GetMinFee_mode
{
GMF_RELAY
,
GMF_SEND
,
};
int64_t
GetMinFee
(
const
CTransaction
&
tx
,
unsigned
int
nBytes
,
bool
fAllowFree
,
enum
GetMinFee_mode
mode
);
//
// Check transaction inputs, and make sure any
// pay-to-script-hash transactions are evaluating IsStandard scripts
//
// Why bother? To avoid denial-of-service attacks; an attacker
// can submit a standard HASH... OP_EQUAL transaction,
// which will get accepted into blocks. The redemption
// script can be anything; an attacker could use a very
// expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
//
/** Check for standard transaction types
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@return True if all inputs (scriptSigs) use only standard transaction forms
*/
bool
AreInputsStandard
(
const
CTransaction
&
tx
,
CCoinsViewCache
&
mapInputs
);
/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
@return number of sigops this transaction's outputs will produce when spent
@see CTransaction::FetchInputs
*/
unsigned
int
GetLegacySigOpCount
(
const
CTransaction
&
tx
);
/** Count ECDSA signature operations in pay-to-script-hash inputs.
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@return maximum number of sigops required to validate this transaction's inputs
@see CTransaction::FetchInputs
*/
unsigned
int
GetP2SHSigOpCount
(
const
CTransaction
&
tx
,
CCoinsViewCache
&
mapInputs
);
inline
bool
AllowFree
(
double
dPriority
)
{
// Large (in bytes) low-priority (new, small-coin) transactions
// need a fee.
return
dPriority
>
COIN
*
144
/
250
;
}
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
// instead of being performed inline.
bool
CheckInputs
(
const
CTransaction
&
tx
,
CValidationState
&
state
,
CCoinsViewCache
&
view
,
bool
fScriptChecks
=
true
,
unsigned
int
flags
=
SCRIPT_VERIFY_P2SH
|
SCRIPT_VERIFY_STRICTENC
,
std
::
vector
<
CScriptCheck
>
*
pvChecks
=
NULL
);
// Apply the effects of this transaction on the UTXO set represented by view
void
UpdateCoins
(
const
CTransaction
&
tx
,
CValidationState
&
state
,
CCoinsViewCache
&
inputs
,
CTxUndo
&
txundo
,
int
nHeight
,
const
uint256
&
txhash
);
// Context-independent validity checks
bool
CheckTransaction
(
const
CTransaction
&
tx
,
CValidationState
&
state
);
/** Check for standard transaction types
@return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
bool
IsStandardTx
(
const
CTransaction
&
tx
,
std
::
string
&
reason
);
bool
IsFinalTx
(
const
CTransaction
&
tx
,
int
nBlockHeight
=
0
,
int64_t
nBlockTime
=
0
);
/** Undo information for a CBlock */
class
CBlockUndo
{
public
:
std
::
vector
<
CTxUndo
>
vtxundo
;
// for all but the coinbase
IMPLEMENT_SERIALIZE
(
READWRITE
(
vtxundo
);
)
bool
WriteToDisk
(
CDiskBlockPos
&
pos
,
const
uint256
&
hashBlock
)
{
// Open history file to append
CAutoFile
fileout
=
CAutoFile
(
OpenUndoFile
(
pos
),
SER_DISK
,
CLIENT_VERSION
);
if
(
!
fileout
)
return
error
(
"CBlockUndo::WriteToDisk : OpenUndoFile failed"
);
// Write index header
unsigned
int
nSize
=
fileout
.
GetSerializeSize
(
*
this
);
fileout
<<
FLATDATA
(
Params
().
MessageStart
())
<<
nSize
;
// Write undo data
long
fileOutPos
=
ftell
(
fileout
);
if
(
fileOutPos
<
0
)
return
error
(
"CBlockUndo::WriteToDisk : ftell failed"
);
pos
.
nPos
=
(
unsigned
int
)
fileOutPos
;
fileout
<<
*
this
;
// calculate & write checksum
CHashWriter
hasher
(
SER_GETHASH
,
PROTOCOL_VERSION
);
hasher
<<
hashBlock
;
hasher
<<
*
this
;
fileout
<<
hasher
.
GetHash
();
// Flush stdio buffers and commit to disk before returning
fflush
(
fileout
);
if
(
!
IsInitialBlockDownload
())
FileCommit
(
fileout
);
return
true
;
}
bool
ReadFromDisk
(
const
CDiskBlockPos
&
pos
,
const
uint256
&
hashBlock
)
{
// Open history file to read
CAutoFile
filein
=
CAutoFile
(
OpenUndoFile
(
pos
,
true
),
SER_DISK
,
CLIENT_VERSION
);
if
(
!
filein
)
return
error
(
"CBlockUndo::ReadFromDisk : OpenBlockFile failed"
);
// Read block
uint256
hashChecksum
;
try
{
filein
>>
*
this
;
filein
>>
hashChecksum
;
}
catch
(
std
::
exception
&
e
)
{
return
error
(
"%s : Deserialize or I/O error - %s"
,
__PRETTY_FUNCTION__
,
e
.
what
());
}
// Verify checksum
CHashWriter
hasher
(
SER_GETHASH
,
PROTOCOL_VERSION
);
hasher
<<
hashBlock
;
hasher
<<
*
this
;
if
(
hashChecksum
!=
hasher
.
GetHash
())
return
error
(
"CBlockUndo::ReadFromDisk : Checksum mismatch"
);
return
true
;
}
};
/** Closure representing one script verification
* Note that this stores references to the spending transaction */
class
CScriptCheck
{
private
:
CScript
scriptPubKey
;
const
CTransaction
*
ptxTo
;
unsigned
int
nIn
;
unsigned
int
nFlags
;
int
nHashType
;
public
:
CScriptCheck
()
{}
CScriptCheck
(
const
CCoins
&
txFromIn
,
const
CTransaction
&
txToIn
,
unsigned
int
nInIn
,
unsigned
int
nFlagsIn
,
int
nHashTypeIn
)
:
scriptPubKey
(
txFromIn
.
vout
[
txToIn
.
vin
[
nInIn
].
prevout
.
n
].
scriptPubKey
),
ptxTo
(
&
txToIn
),
nIn
(
nInIn
),
nFlags
(
nFlagsIn
),
nHashType
(
nHashTypeIn
)
{
}
bool
operator
()()
const
;
void
swap
(
CScriptCheck
&
check
)
{
scriptPubKey
.
swap
(
check
.
scriptPubKey
);
std
::
swap
(
ptxTo
,
check
.
ptxTo
);
std
::
swap
(
nIn
,
check
.
nIn
);
std
::
swap
(
nFlags
,
check
.
nFlags
);
std
::
swap
(
nHashType
,
check
.
nHashType
);
}
};
/** A transaction with a merkle branch linking it to the block chain. */
class
CMerkleTx
:
public
CTransaction
{
private
:
int
GetDepthInMainChainINTERNAL
(
CBlockIndex
*
&
pindexRet
)
const
;
public
:
uint256
hashBlock
;
std
::
vector
<
uint256
>
vMerkleBranch
;
int
nIndex
;
// memory only
mutable
bool
fMerkleVerified
;
CMerkleTx
()
{
Init
();
}
CMerkleTx
(
const
CTransaction
&
txIn
)
:
CTransaction
(
txIn
)
{
Init
();
}
void
Init
()
{
hashBlock
=
0
;
nIndex
=
-1
;
fMerkleVerified
=
false
;
}
IMPLEMENT_SERIALIZE
(
nSerSize
+=
SerReadWrite
(
s
,
*
(
CTransaction
*
)
this
,
nType
,
nVersion
,
ser_action
);
nVersion
=
this
->
nVersion
;
READWRITE
(
hashBlock
);
READWRITE
(
vMerkleBranch
);
READWRITE
(
nIndex
);
)
int
SetMerkleBranch
(
const
CBlock
*
pblock
=
NULL
);
// Return depth of transaction in blockchain:
// -1 : not in blockchain, and not in memory pool (conflicted transaction)
// 0 : in memory pool, waiting to be included in a block
// >=1 : this many blocks deep in the main chain
int
GetDepthInMainChain
(
CBlockIndex
*
&
pindexRet
)
const
;
int
GetDepthInMainChain
()
const
{
CBlockIndex
*
pindexRet
;
return
GetDepthInMainChain
(
pindexRet
);
}
bool
IsInMainChain
()
const
{
CBlockIndex
*
pindexRet
;
return
GetDepthInMainChainINTERNAL
(
pindexRet
)
>
0
;
}
int
GetBlocksToMaturity
()
const
;
bool
AcceptToMemoryPool
(
bool
fLimitFree
=
true
);
};
/** Data structure that represents a partial merkle tree.
*
* It respresents a subset of the txid's of a known block, in a way that
* allows recovery of the list of txid's and the merkle root, in an
* authenticated way.
*
* The encoding works as follows: we traverse the tree in depth-first order,
* storing a bit for each traversed node, signifying whether the node is the
* parent of at least one matched leaf txid (or a matched txid itself). In
* case we are at the leaf level, or this bit is 0, its merkle node hash is
* stored, and its children are not explorer further. Otherwise, no hash is
* stored, but we recurse into both (or the only) child branch. During
* decoding, the same depth-first traversal is performed, consuming bits and
* hashes as they written during encoding.
*
* The serialization is fixed and provides a hard guarantee about the
* encoded size:
*
* SIZE <= 10 + ceil(32.25*N)
*
* Where N represents the number of leaf nodes of the partial tree. N itself
* is bounded by:
*
* N <= total_transactions
* N <= 1 + matched_transactions*tree_height
*
* The serialization format:
* - uint32 total_transactions (4 bytes)
* - varint number of hashes (1-3 bytes)
* - uint256[] hashes in depth-first order (<= 32*N bytes)
* - varint number of bytes of flag bits (1-3 bytes)
* - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
* The size constraints follow from this.
*/
class
CPartialMerkleTree
{
protected
:
// the total number of transactions in the block
unsigned
int
nTransactions
;
// node-is-parent-of-matched-txid bits
std
::
vector
<
bool
>
vBits
;
// txids and internal hashes
std
::
vector
<
uint256
>
vHash
;
// flag set when encountering invalid data
bool
fBad
;
// helper function to efficiently calculate the number of nodes at given height in the merkle tree
unsigned
int
CalcTreeWidth
(
int
height
)
{
return
(
nTransactions
+
(
1
<<
height
)
-1
)
>>
height
;
}
// calculate the hash of a node in the merkle tree (at leaf level: the txid's themself)
uint256
CalcHash
(
int
height
,
unsigned
int
pos
,
const
std
::
vector
<
uint256
>
&
vTxid
);
// recursive function that traverses tree nodes, storing the data as bits and hashes
void
TraverseAndBuild
(
int
height
,
unsigned
int
pos
,
const
std
::
vector
<
uint256
>
&
vTxid
,
const
std
::
vector
<
bool
>
&
vMatch
);
// recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
// it returns the hash of the respective node.
uint256
TraverseAndExtract
(
int
height
,
unsigned
int
pos
,
unsigned
int
&
nBitsUsed
,
unsigned
int
&
nHashUsed
,
std
::
vector
<
uint256
>
&
vMatch
);
public
:
// serialization implementation
IMPLEMENT_SERIALIZE
(
READWRITE
(
nTransactions
);
READWRITE
(
vHash
);
std
::
vector
<
unsigned
char
>
vBytes
;
if
(
fRead
)
{
READWRITE
(
vBytes
);
CPartialMerkleTree
&
us
=
*
(
const_cast
<
CPartialMerkleTree
*>
(
this
));
us
.
vBits
.
resize
(
vBytes
.
size
()
*
8
);
for
(
unsigned
int
p
=
0
;
p
<
us
.
vBits
.
size
();
p
++
)
us
.
vBits
[
p
]
=
(
vBytes
[
p
/
8
]
&
(
1
<<
(
p
%
8
)))
!=
0
;
us
.
fBad
=
false
;
}
else
{
vBytes
.
resize
((
vBits
.
size
()
+
7
)
/
8
);
for
(
unsigned
int
p
=
0
;
p
<
vBits
.
size
();
p
++
)
vBytes
[
p
/
8
]
|=
vBits
[
p
]
<<
(
p
%
8
);
READWRITE
(
vBytes
);
}
)
// Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them
CPartialMerkleTree
(
const
std
::
vector
<
uint256
>
&
vTxid
,
const
std
::
vector
<
bool
>
&
vMatch
);
CPartialMerkleTree
();
// extract the matching txid's represented by this partial merkle tree.
// returns the merkle root, or 0 in case of failure
uint256
ExtractMatches
(
std
::
vector
<
uint256
>
&
vMatch
);
};
/** Functions for disk access for blocks */
bool
WriteBlockToDisk
(
CBlock
&
block
,
CDiskBlockPos
&
pos
);
bool
ReadBlockFromDisk
(
CBlock
&
block
,
const
CDiskBlockPos
&
pos
);
bool
ReadBlockFromDisk
(
CBlock
&
block
,
const
CBlockIndex
*
pindex
);
/** Functions for validating blocks and updating the block tree */
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
* In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
* will be true if no problems were found. Otherwise, the return value will be false in case
* of problems. Note that in any case, coins may be modified. */
bool
DisconnectBlock
(
CBlock
&
block
,
CValidationState
&
state
,
CBlockIndex
*
pindex
,
CCoinsViewCache
&
coins
,
bool
*
pfClean
=
NULL
);
// Apply the effects of this block (with given index) on the UTXO set represented by coins
bool
ConnectBlock
(
CBlock
&
block
,
CValidationState
&
state
,
CBlockIndex
*
pindex
,
CCoinsViewCache
&
coins
,
bool
fJustCheck
=
false
);
// Add this block to the block index, and if necessary, switch the active block chain to this
bool
AddToBlockIndex
(
CBlock
&
block
,
CValidationState
&
state
,
const
CDiskBlockPos
&
pos
);
// Context-independent validity checks
bool
CheckBlock
(
const
CBlock
&
block
,
CValidationState
&
state
,
bool
fCheckPOW
=
true
,
bool
fCheckMerkleRoot
=
true
);
// Store block on disk
// if dbp is provided, the file is known to already reside on disk
bool
AcceptBlock
(
CBlock
&
block
,
CValidationState
&
state
,
CDiskBlockPos
*
dbp
=
NULL
);
class
CBlockFileInfo
{
public
:
unsigned
int
nBlocks
;
// number of blocks stored in file
unsigned
int
nSize
;
// number of used bytes of block file
unsigned
int
nUndoSize
;
// number of used bytes in the undo file
unsigned
int
nHeightFirst
;
// lowest height of block in file
unsigned
int
nHeightLast
;
// highest height of block in file
uint64_t
nTimeFirst
;
// earliest time of block in file
uint64_t
nTimeLast
;
// latest time of block in file
IMPLEMENT_SERIALIZE
(
READWRITE
(
VARINT
(
nBlocks
));
READWRITE
(
VARINT
(
nSize
));
READWRITE
(
VARINT
(
nUndoSize
));
READWRITE
(
VARINT
(
nHeightFirst
));
READWRITE
(
VARINT
(
nHeightLast
));
READWRITE
(
VARINT
(
nTimeFirst
));
READWRITE
(
VARINT
(
nTimeLast
));
)
void
SetNull
()
{
nBlocks
=
0
;
nSize
=
0
;
nUndoSize
=
0
;
nHeightFirst
=
0
;
nHeightLast
=
0
;
nTimeFirst
=
0
;
nTimeLast
=
0
;
}
CBlockFileInfo
()
{
SetNull
();
}
std
::
string
ToString
()
const
{
return
strprintf
(
"CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("
%
Y
-%
m
-%
d
", nTimeFirst).c_str(), DateTimeStrFormat("
%
Y
-%
m
-%
d
", nTimeLast).c_str())
;
}
// update statistics (does not update nSize)
void
AddBlock
(
unsigned
int
nHeightIn
,
uint64_t
nTimeIn
)
{
if
(
nBlocks
==
0
||
nHeightFirst
>
nHeightIn
)
nHeightFirst
=
nHeightIn
;
if
(
nBlocks
==
0
||
nTimeFirst
>
nTimeIn
)
nTimeFirst
=
nTimeIn
;
nBlocks
++
;
if
(
nHeightIn
>
nHeightLast
)
nHeightLast
=
nHeightIn
;
if
(
nTimeIn
>
nTimeLast
)
nTimeLast
=
nTimeIn
;
}
};
enum
BlockStatus
{
BLOCK_VALID_UNKNOWN
=
0
,
BLOCK_VALID_HEADER
=
1
,
// parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
BLOCK_VALID_TREE
=
2
,
// parent found, difficulty matches, timestamp >= median previous, checkpoint
BLOCK_VALID_TRANSACTIONS
=
3
,
// only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids, sigops, size, merkle root
BLOCK_VALID_CHAIN
=
4
,
// outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30
BLOCK_VALID_SCRIPTS
=
5
,
// scripts/signatures ok
BLOCK_VALID_MASK
=
7
,
BLOCK_HAVE_DATA
=
8
,
// full block available in blk*.dat
BLOCK_HAVE_UNDO
=
16
,
// undo data available in rev*.dat
BLOCK_HAVE_MASK
=
24
,
BLOCK_FAILED_VALID
=
32
,
// stage after last reached validness failed
BLOCK_FAILED_CHILD
=
64
,
// descends from failed block
BLOCK_FAILED_MASK
=
96
};
/** The block chain is a tree shaped structure starting with the
* genesis block at the root, with each block potentially having multiple
* candidates to be the next block. A blockindex may have multiple pprev pointing
* to it, but at most one of them can be part of the currently active branch.
*/
class
CBlockIndex
{
public
:
// pointer to the hash of the block, if any. memory is owned by this CBlockIndex
const
uint256
*
phashBlock
;
// pointer to the index of the predecessor of this block
CBlockIndex
*
pprev
;
// height of the entry in the chain. The genesis block has height 0
int
nHeight
;
// Which # file this block is stored in (blk?????.dat)
int
nFile
;
// Byte offset within blk?????.dat where this block's data is stored
unsigned
int
nDataPos
;
// Byte offset within rev?????.dat where this block's undo data is stored
unsigned
int
nUndoPos
;
// (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
uint256
nChainWork
;
// Number of transactions in this block.
// Note: in a potential headers-first mode, this number cannot be relied upon
unsigned
int
nTx
;
// (memory only) Number of transactions in the chain up to and including this block
unsigned
int
nChainTx
;
// change to 64-bit type when necessary; won't happen before 2030
// Verification status of this block. See enum BlockStatus
unsigned
int
nStatus
;
// block header
int
nVersion
;
uint256
hashMerkleRoot
;
unsigned
int
nTime
;
unsigned
int
nBits
;
unsigned
int
nNonce
;
// (memory only) Sequencial id assigned to distinguish order in which blocks are received.
uint32_t
nSequenceId
;
CBlockIndex
()
{
phashBlock
=
NULL
;
pprev
=
NULL
;
nHeight
=
0
;
nFile
=
0
;
nDataPos
=
0
;
nUndoPos
=
0
;
nChainWork
=
0
;
nTx
=
0
;
nChainTx
=
0
;
nStatus
=
0
;
nSequenceId
=
0
;
nVersion
=
0
;
hashMerkleRoot
=
0
;
nTime
=
0
;
nBits
=
0
;
nNonce
=
0
;
}
CBlockIndex
(
CBlockHeader
&
block
)
{
phashBlock
=
NULL
;
pprev
=
NULL
;
nHeight
=
0
;
nFile
=
0
;
nDataPos
=
0
;
nUndoPos
=
0
;
nChainWork
=
0
;
nTx
=
0
;
nChainTx
=
0
;
nStatus
=
0
;
nSequenceId
=
0
;
nVersion
=
block
.
nVersion
;
hashMerkleRoot
=
block
.
hashMerkleRoot
;
nTime
=
block
.
nTime
;
nBits
=
block
.
nBits
;
nNonce
=
block
.
nNonce
;
}
CDiskBlockPos
GetBlockPos
()
const
{
CDiskBlockPos
ret
;
if
(
nStatus
&
BLOCK_HAVE_DATA
)
{
ret
.
nFile
=
nFile
;
ret
.
nPos
=
nDataPos
;
}
return
ret
;
}
CDiskBlockPos
GetUndoPos
()
const
{
CDiskBlockPos
ret
;
if
(
nStatus
&
BLOCK_HAVE_UNDO
)
{
ret
.
nFile
=
nFile
;
ret
.
nPos
=
nUndoPos
;
}
return
ret
;
}
CBlockHeader
GetBlockHeader
()
const
{
CBlockHeader
block
;
block
.
nVersion
=
nVersion
;
if
(
pprev
)
block
.
hashPrevBlock
=
pprev
->
GetBlockHash
();
block
.
hashMerkleRoot
=
hashMerkleRoot
;
block
.
nTime
=
nTime
;
block
.
nBits
=
nBits
;
block
.
nNonce
=
nNonce
;
return
block
;
}
uint256
GetBlockHash
()
const
{
return
*
phashBlock
;
}
int64_t
GetBlockTime
()
const
{
return
(
int64_t
)
nTime
;
}
CBigNum
GetBlockWork
()
const
{
CBigNum
bnTarget
;
bnTarget
.
SetCompact
(
nBits
);
if
(
bnTarget
<=
0
)
return
0
;
return
(
CBigNum
(
1
)
<<
256
)
/
(
bnTarget
+
1
);
}
bool
CheckIndex
()
const
{
return
CheckProofOfWork
(
GetBlockHash
(),
nBits
);
}
enum
{
nMedianTimeSpan
=
11
};
int64_t
GetMedianTimePast
()
const
{
int64_t
pmedian
[
nMedianTimeSpan
];
int64_t
*
pbegin
=
&
pmedian
[
nMedianTimeSpan
];
int64_t
*
pend
=
&
pmedian
[
nMedianTimeSpan
];
const
CBlockIndex
*
pindex
=
this
;
for
(
int
i
=
0
;
i
<
nMedianTimeSpan
&&
pindex
;
i
++
,
pindex
=
pindex
->
pprev
)
*
(
--
pbegin
)
=
pindex
->
GetBlockTime
();
std
::
sort
(
pbegin
,
pend
);
return
pbegin
[(
pend
-
pbegin
)
/
2
];
}
int64_t
GetMedianTime
()
const
;
/**
* Returns true if there are nRequired or more blocks of minVersion or above
* in the last nToCheck blocks, starting at pstart and going backwards.
*/
static
bool
IsSuperMajority
(
int
minVersion
,
const
CBlockIndex
*
pstart
,
unsigned
int
nRequired
,
unsigned
int
nToCheck
);
std
::
string
ToString
()
const
{
return
strprintf
(
"CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
pprev
,
nHeight
,
hashMerkleRoot
.
ToString
().
c_str
(),
GetBlockHash
().
ToString
().
c_str
());
}
void
print
()
const
{
LogPrintf
(
"%s
\n
"
,
ToString
().
c_str
());
}
};
/** Used to marshal pointers into hashes for db storage. */
class
CDiskBlockIndex
:
public
CBlockIndex
{
public
:
uint256
hashPrev
;
CDiskBlockIndex
()
{
hashPrev
=
0
;
}
explicit
CDiskBlockIndex
(
CBlockIndex
*
pindex
)
:
CBlockIndex
(
*
pindex
)
{
hashPrev
=
(
pprev
?
pprev
->
GetBlockHash
()
:
0
);
}
IMPLEMENT_SERIALIZE
(
if
(
!
(
nType
&
SER_GETHASH
))
READWRITE
(
VARINT
(
nVersion
));
READWRITE
(
VARINT
(
nHeight
));
READWRITE
(
VARINT
(
nStatus
));
READWRITE
(
VARINT
(
nTx
));
if
(
nStatus
&
(
BLOCK_HAVE_DATA
|
BLOCK_HAVE_UNDO
))
READWRITE
(
VARINT
(
nFile
));
if
(
nStatus
&
BLOCK_HAVE_DATA
)
READWRITE
(
VARINT
(
nDataPos
));
if
(
nStatus
&
BLOCK_HAVE_UNDO
)
READWRITE
(
VARINT
(
nUndoPos
));
// block header
READWRITE
(
this
->
nVersion
);
READWRITE
(
hashPrev
);
READWRITE
(
hashMerkleRoot
);
READWRITE
(
nTime
);
READWRITE
(
nBits
);
READWRITE
(
nNonce
);
)
uint256
GetBlockHash
()
const
{
CBlockHeader
block
;
block
.
nVersion
=
nVersion
;
block
.
hashPrevBlock
=
hashPrev
;
block
.
hashMerkleRoot
=
hashMerkleRoot
;
block
.
nTime
=
nTime
;
block
.
nBits
=
nBits
;
block
.
nNonce
=
nNonce
;
return
block
.
GetHash
();
}
std
::
string
ToString
()
const
{
std
::
string
str
=
"CDiskBlockIndex("
;
str
+=
CBlockIndex
::
ToString
();
str
+=
strprintf
(
"
\n
hashBlock=%s, hashPrev=%s)"
,
GetBlockHash
().
ToString
().
c_str
(),
hashPrev
.
ToString
().
c_str
());
return
str
;
}
void
print
()
const
{
LogPrintf
(
"%s
\n
"
,
ToString
().
c_str
());
}
};
/** Capture information about block/transaction validation */
class
CValidationState
{
private
:
enum
mode_state
{
MODE_VALID
,
// everything ok
MODE_INVALID
,
// network rule violation (DoS value may be set)
MODE_ERROR
,
// run-time error
}
mode
;
int
nDoS
;
std
::
string
strRejectReason
;
unsigned
char
chRejectCode
;
bool
corruptionPossible
;
public
:
CValidationState
()
:
mode
(
MODE_VALID
),
nDoS
(
0
),
corruptionPossible
(
false
)
{}
bool
DoS
(
int
level
,
bool
ret
=
false
,
unsigned
char
chRejectCodeIn
=
0
,
std
::
string
strRejectReasonIn
=
""
,
bool
corruptionIn
=
false
)
{
chRejectCode
=
chRejectCodeIn
;
strRejectReason
=
strRejectReasonIn
;
corruptionPossible
=
corruptionIn
;
if
(
mode
==
MODE_ERROR
)
return
ret
;
nDoS
+=
level
;
mode
=
MODE_INVALID
;
return
ret
;
}
bool
Invalid
(
bool
ret
=
false
,
unsigned
char
_chRejectCode
=
0
,
std
::
string
_strRejectReason
=
""
)
{
return
DoS
(
0
,
ret
,
_chRejectCode
,
_strRejectReason
);
}
bool
Error
(
std
::
string
strRejectReasonIn
=
""
)
{
if
(
mode
==
MODE_VALID
)
strRejectReason
=
strRejectReasonIn
;
mode
=
MODE_ERROR
;
return
false
;
}
bool
Abort
(
const
std
::
string
&
msg
)
{
AbortNode
(
msg
);
return
Error
(
msg
);
}
bool
IsValid
()
const
{
return
mode
==
MODE_VALID
;
}
bool
IsInvalid
()
const
{
return
mode
==
MODE_INVALID
;
}
bool
IsError
()
const
{
return
mode
==
MODE_ERROR
;
}
bool
IsInvalid
(
int
&
nDoSOut
)
const
{
if
(
IsInvalid
())
{
nDoSOut
=
nDoS
;
return
true
;
}
return
false
;
}
bool
CorruptionPossible
()
const
{
return
corruptionPossible
;
}
unsigned
char
GetRejectCode
()
const
{
return
chRejectCode
;
}
std
::
string
GetRejectReason
()
const
{
return
strRejectReason
;
}
};
/** An in-memory indexed chain of blocks. */
class
CChain
{
private
:
std
::
vector
<
CBlockIndex
*>
vChain
;
public
:
/** Returns the index entry for the genesis block of this chain, or NULL if none. */
CBlockIndex
*
Genesis
()
const
{
return
vChain
.
size
()
>
0
?
vChain
[
0
]
:
NULL
;
}
/** Returns the index entry for the tip of this chain, or NULL if none. */
CBlockIndex
*
Tip
()
const
{
return
vChain
.
size
()
>
0
?
vChain
[
vChain
.
size
()
-
1
]
:
NULL
;
}
/** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
CBlockIndex
*
operator
[](
int
nHeight
)
const
{
if
(
nHeight
<
0
||
nHeight
>=
(
int
)
vChain
.
size
())
return
NULL
;
return
vChain
[
nHeight
];
}
/** Compare two chains efficiently. */
friend
bool
operator
==
(
const
CChain
&
a
,
const
CChain
&
b
)
{
return
a
.
vChain
.
size
()
==
b
.
vChain
.
size
()
&&
a
.
vChain
[
a
.
vChain
.
size
()
-
1
]
==
b
.
vChain
[
b
.
vChain
.
size
()
-
1
];
}
/** Efficiently check whether a block is present in this chain. */
bool
Contains
(
const
CBlockIndex
*
pindex
)
const
{
return
(
*
this
)[
pindex
->
nHeight
]
==
pindex
;
}
/** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
CBlockIndex
*
Next
(
const
CBlockIndex
*
pindex
)
const
{
if
(
Contains
(
pindex
))
return
(
*
this
)[
pindex
->
nHeight
+
1
];
else
return
NULL
;
}
/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
int
Height
()
const
{
return
vChain
.
size
()
-
1
;
}
/** Set/initialize a chain with a given tip. Returns the forking point. */
CBlockIndex
*
SetTip
(
CBlockIndex
*
pindex
);
/** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
CBlockLocator
GetLocator
(
const
CBlockIndex
*
pindex
=
NULL
)
const
;
/** Find the last common block between this chain and a locator. */
CBlockIndex
*
FindFork
(
const
CBlockLocator
&
locator
)
const
;
};
/** The currently-connected chain of blocks. */
extern
CChain
chainActive
;
/** The currently best known chain of headers (some of which may be invalid). */
extern
CChain
chainMostWork
;
/** Global variable that points to the active CCoinsView (protected by cs_main) */
extern
CCoinsViewCache
*
pcoinsTip
;
/** Global variable that points to the active block tree (protected by cs_main) */
extern
CBlockTreeDB
*
pblocktree
;
struct
CBlockTemplate
{
CBlock
block
;
std
::
vector
<
int64_t
>
vTxFees
;
std
::
vector
<
int64_t
>
vTxSigOps
;
};
/** Used to relay blocks as header + vector<merkle branch>
* to filtered nodes.
*/
class
CMerkleBlock
{
public
:
// Public only for unit testing
CBlockHeader
header
;
CPartialMerkleTree
txn
;
public
:
// Public only for unit testing and relay testing
// (not relayed)
std
::
vector
<
std
::
pair
<
unsigned
int
,
uint256
>
>
vMatchedTxn
;
// Create from a CBlock, filtering transactions according to filter
// Note that this will call IsRelevantAndUpdate on the filter for each transaction,
// thus the filter will likely be modified.
CMerkleBlock
(
const
CBlock
&
block
,
CBloomFilter
&
filter
);
IMPLEMENT_SERIALIZE
(
READWRITE
(
header
);
READWRITE
(
txn
);
)
};
class
CWalletInterface
{
protected
:
virtual
void
SyncTransaction
(
const
uint256
&
hash
,
const
CTransaction
&
tx
,
const
CBlock
*
pblock
)
=
0
;
virtual
void
EraseFromWallet
(
const
uint256
&
hash
)
=
0
;
virtual
void
SetBestChain
(
const
CBlockLocator
&
locator
)
=
0
;
virtual
void
UpdatedTransaction
(
const
uint256
&
hash
)
=
0
;
virtual
void
Inventory
(
const
uint256
&
hash
)
=
0
;
virtual
void
ResendWalletTransactions
()
=
0
;
friend
void
::
RegisterWallet
(
CWalletInterface
*
);
friend
void
::
UnregisterWallet
(
CWalletInterface
*
);
friend
void
::
UnregisterAllWallets
();
};
#endif
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Nov 23, 09:56 (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4550775
Default Alt Text
main.h (36 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment