@ -389,7 +389,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
@@ -389,7 +389,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
CTxIndex txindex ;
if ( ! CTxDB ( " r " ) . ReadTxIndex ( GetHash ( ) , txindex ) )
return 0 ;
if ( ! blockTmp . ReadFromDisk ( txindex . pos . nFile , txindex . pos . nB lockPos) )
if ( ! blockTmp . ReadFromDisk ( txindex . pos . b lockPos) )
return 0 ;
pblock = & blockTmp ;
}
@ -646,7 +646,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs,
@@ -646,7 +646,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 ( mapInputs , mapUnused , CDiskTxPos ( 1 , 1 , 1 ) , pindexBest , false , false ) )
if ( ! tx . ConnectInputs ( mapInputs , mapUnused , CDiskTxPos ( true ) , pindexBest , false , false ) )
{
return error ( " CTxMemPool::accept() : ConnectInputs failed % s " , hash.ToString().substr(0,10).c_str()) ;
}
@ -817,7 +817,7 @@ int CTxIndex::GetDepthInMainChain() const
@@ -817,7 +817,7 @@ int CTxIndex::GetDepthInMainChain() const
{
// Read block header
CBlock block ;
if ( ! block . ReadFromDisk ( pos . nFile , pos . nB lockPos, false ) )
if ( ! block . ReadFromDisk ( pos . b lockPos, false ) )
return 0 ;
// Find the block in the index
map < uint256 , CBlockIndex * > : : iterator mi = mapBlockIndex . find ( block . GetHash ( ) ) ;
@ -847,7 +847,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
@@ -847,7 +847,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
if ( tx . ReadFromDisk ( txdb , COutPoint ( hash , 0 ) , txindex ) )
{
CBlock block ;
if ( block . ReadFromDisk ( txindex . pos . nFile , txindex . pos . nB lockPos, false ) )
if ( block . ReadFromDisk ( txindex . pos . b lockPos, false ) )
hashBlock = block . GetHash ( ) ;
return true ;
}
@ -892,7 +892,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
@@ -892,7 +892,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
* this = pindex - > GetBlockHeader ( ) ;
return true ;
}
if ( ! ReadFromDisk ( pindex - > nFile , pindex - > nBlockPos , fReadTransactions ) )
if ( ! ReadFromDisk ( pindex - > GetBlockPos ( ) , fReadTransactions ) )
return false ;
if ( GetHash ( ) ! = pindex - > GetBlockHash ( ) )
return error ( " CBlock::ReadFromDisk() : GetHash ( ) doesn ' t match index " ) ;
@ -1156,7 +1156,7 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
@@ -1156,7 +1156,7 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
// Read txPrev
CTransaction & txPrev = inputsRet [ prevout . hash ] . second ;
if ( ! fFound | | txindex . pos = = CDiskTxPos ( 1 , 1 , 1 ) )
if ( ! fFound | | txindex . pos . IsMemPool ( ) )
{
// Get prev tx from single transactions in memory
{
@ -1262,7 +1262,7 @@ bool CTransaction::ConnectInputs(MapPrevTx inputs,
@@ -1262,7 +1262,7 @@ bool CTransaction::ConnectInputs(MapPrevTx inputs,
// If prev is coinbase, check that it's matured
if ( txPrev . IsCoinBase ( ) )
for ( const CBlockIndex * pindex = pindexBlock ; pindex & & pindexBlock - > nHeight - pindex - > nHeight < COINBASE_MATURITY ; pindex = pindex - > pprev )
if ( pindex - > nBlockPos = = txindex . pos . nBlockPos & & pindex - > nFile = = txindex . pos . nFile )
if ( pindex - > GetBlockPos ( ) = = txindex . pos . blockPos )
return error ( " ConnectInputs() : tried to spend coinbase at depth % d " , pindexBlock->nHeight - pindex->nHeight) ;
// Check for negative or overflow input values
@ -1427,11 +1427,10 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
@@ -1427,11 +1427,10 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
//// issue here: it doesn't know the version
unsigned int nTxPos ;
if ( fJustCheck )
// FetchInputs treats CDiskTxPos(1,1,1) as a special "refer to memorypool" indicator
// Since we're just checking the block and not actually connecting it, it might not (and probably shouldn't) be on the disk to get the transaction from
nTxPos = 1 ;
else
nTxPos = pindex - > nBlockPos + : : GetSerializeSize ( CBlock ( ) , SER_DISK , CLIENT_VERSION ) - 1 + GetSizeOfCompactSize ( vtx . size ( ) ) ;
nTxPos = : : GetSerializeSize ( CBlock ( ) , SER_DISK , CLIENT_VERSION ) - 1 + GetSizeOfCompactSize ( vtx . size ( ) ) ;
map < uint256 , CTxIndex > mapQueuedChanges ;
int64 nFees = 0 ;
@ -1453,9 +1452,11 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
@@ -1453,9 +1452,11 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
if ( nSigOps > MAX_BLOCK_SIGOPS )
return DoS ( 100 , error ( " ConnectBlock() : too many sigops " )) ;
CDiskTxPos posThisTx ( pindex - > nFile , pindex - > nBlockPos , nTxPos ) ;
CDiskTxPos posThisTx ( pindex - > GetBlockPos ( ) , nTxPos ) ;
if ( ! fJustCheck )
nTxPos + = : : GetSerializeSize ( tx , SER_DISK , CLIENT_VERSION ) ;
else
posThisTx = CDiskTxPos ( true ) ;
MapPrevTx mapInputs ;
if ( ! tx . IsCoinBase ( ) )
@ -1750,7 +1751,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
@@ -1750,7 +1751,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
}
bool CBlock : : AddToBlockIndex ( unsigned int nFile , unsigned int nBlockP os)
bool CBlock : : AddToBlockIndex ( const CDiskBlockPos & p os)
{
// Check for duplicate
uint256 hash = GetHash ( ) ;
@ -1758,7 +1759,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
@@ -1758,7 +1759,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
return error ( " AddToBlockIndex() : % s already exists " , hash.ToString().substr(0,20).c_str()) ;
// Construct new block index object
CBlockIndex * pindexNew = new CBlockIndex ( nFile , nBlockPos , * this ) ;
CBlockIndex * pindexNew = new CBlockIndex ( * this ) ;
if ( ! pindexNew )
return error ( " AddToBlockIndex() : new CBlockIndex failed " ) ;
map < uint256 , CBlockIndex * > : : iterator mi = mapBlockIndex . insert ( make_pair ( hash , pindexNew ) ) . first ;
@ -1770,6 +1771,8 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
@@ -1770,6 +1771,8 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
pindexNew - > nHeight = pindexNew - > pprev - > nHeight + 1 ;
}
pindexNew - > bnChainWork = ( pindexNew - > pprev ? pindexNew - > pprev - > bnChainWork : 0 ) + pindexNew - > GetBlockWork ( ) ;
assert ( pos . nHeight = = pindexNew - > nHeight ) ;
pindexNew - > nAlternative = pos . nAlternative ;
CTxDB txdb ;
if ( ! txdb . TxnBegin ( ) )
@ -1908,13 +1911,12 @@ bool CBlock::AcceptBlock()
@@ -1908,13 +1911,12 @@ bool CBlock::AcceptBlock()
}
// Write block to history file
CDiskBlockPos blockPos = CDiskBlockPos ( nHeight ) ;
if ( ! CheckDiskSpace ( : : GetSerializeSize ( * this , SER_DISK , CLIENT_VERSION ) ) )
return error ( " AcceptBlock() : out of disk space " ) ;
unsigned int nFile = - 1 ;
unsigned int nBlockPos = 0 ;
if ( ! WriteToDisk ( nFile , nBlockPos ) )
if ( ! WriteToDisk ( blockPos ) )
return error ( " AcceptBlock() : WriteToDisk failed " ) ;
if ( ! AddToBlockIndex ( nFile , nB lockPos) )
if ( ! AddToBlockIndex ( blockPos ) )
return error ( " AcceptBlock() : AddToBlockIndex failed " ) ;
// Relay inventory, but don't relay old inventory during initial block download
@ -2048,53 +2050,18 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
@@ -2048,53 +2050,18 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
return true ;
}
static filesystem : : path BlockFilePath ( unsigned int nFil e)
FILE * OpenBlockFile ( const CDiskBlockPos & pos , const char * pszMod e)
{
string strBlockFn = strprintf ( " blk%04u.dat " , nFile ) ;
return GetDataDir ( ) / strBlockFn ;
}
FILE * OpenBlockFile ( unsigned int nFile , unsigned int nBlockPos , const char * pszMode )
{
if ( ( nFile < 1 ) | | ( nFile = = ( unsigned int ) - 1 ) )
boost : : filesystem : : path path = pos . GetFileName ( GetDataDir ( ) ) ;
boost : : filesystem : : create_directories ( path . parent_path ( ) ) ;
if ( pos . IsNull ( ) | | pos . IsMemPool ( ) )
return NULL ;
FILE * file = fopen ( BlockFilePath ( nFile ) . string ( ) . c_str ( ) , pszMode ) ;
FILE * file = fopen ( path . string ( ) . c_str ( ) , pszMode ) ;
if ( ! file )
return NULL ;
if ( nBlockPos ! = 0 & & ! strchr ( pszMode , ' a ' ) & & ! strchr ( pszMode , ' w ' ) )
{
if ( fseek ( file , nBlockPos , SEEK_SET ) ! = 0 )
{
fclose ( file ) ;
return NULL ;
}
}
return file ;
}
static unsigned int nCurrentBlockFile = 1 ;
FILE * AppendBlockFile ( unsigned int & nFileRet )
{
nFileRet = 0 ;
loop
{
FILE * file = OpenBlockFile ( nCurrentBlockFile , 0 , " ab " ) ;
if ( ! file )
return NULL ;
if ( fseek ( file , 0 , SEEK_END ) ! = 0 )
return NULL ;
// FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB
if ( ftell ( file ) < ( long ) ( 0x7F000000 - MAX_SIZE ) )
{
nFileRet = nCurrentBlockFile ;
return file ;
}
fclose ( file ) ;
nCurrentBlockFile + + ;
}
}
bool LoadBlockIndex ( bool fAllowNew )
{
if ( fTestNet )
@ -2153,19 +2120,19 @@ bool LoadBlockIndex(bool fAllowNew)
@@ -2153,19 +2120,19 @@ bool LoadBlockIndex(bool fAllowNew)
}
//// debug print
printf ( " %s \n " , block . GetHash ( ) . ToString ( ) . c_str ( ) ) ;
uint256 hash = block . GetHash ( ) ;
printf ( " %s \n " , hash . ToString ( ) . c_str ( ) ) ;
printf ( " %s \n " , hashGenesisBlock . ToString ( ) . c_str ( ) ) ;
printf ( " %s \n " , block . hashMerkleRoot . ToString ( ) . c_str ( ) ) ;
assert ( block . hashMerkleRoot = = uint256 ( " 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b " ) ) ;
block . print ( ) ;
assert ( block . GetHash ( ) = = hashGenesisBlock ) ;
assert ( hash = = hashGenesisBlock ) ;
// Start new block file
unsigned int nFile ;
unsigned int nBlockPos ;
if ( ! block . WriteToDisk ( nFile , nBlockPos ) )
CDiskBlockPos blockPos ( 0 ) ;
if ( ! block . WriteToDisk ( blockPos ) )
return error ( " LoadBlockIndex() : writing genesis block to disk failed " ) ;
if ( ! block . AddToBlockIndex ( nFile , nB lockPos) )
if ( ! block . AddToBlockIndex ( b lockPos) )
return error ( " LoadBlockIndex() : genesis block not accepted " ) ;
}
@ -2219,11 +2186,9 @@ void PrintBlockTree()
@@ -2219,11 +2186,9 @@ void PrintBlockTree()
// print item
CBlock block ;
block . ReadFromDisk ( pindex ) ;
printf ( " %d (%u,%u) % s %s tx % " PRIszu " " ,
printf ( " %d (%s) %s tx % " PRIszu " " ,
pindex - > nHeight ,
pindex - > nFile ,
pindex - > nBlockPos ,
block . GetHash ( ) . ToString ( ) . substr ( 0 , 20 ) . c_str ( ) ,
pindex - > GetBlockPos ( ) . GetFileName ( " " ) . string ( ) . c_str ( ) ,
DateTimeStrFormat ( " %x %H:%M:%S " , block . GetBlockTime ( ) ) . c_str ( ) ,
block . vtx . size ( ) ) ;
@ -3693,9 +3658,9 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
@@ -3693,9 +3658,9 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
if ( nBlockSigOps + nTxSigOps > = MAX_BLOCK_SIGOPS )
continue ;
if ( ! tx . ConnectInputs ( mapInputs , mapTestPoolTmp , CDiskTxPos ( 1 , 1 , 1 ) , pindexPrev , false , true ) )
if ( ! tx . ConnectInputs ( mapInputs , mapTestPoolTmp , CDiskTxPos ( true ) , pindexPrev , false , true ) )
continue ;
mapTestPoolTmp [ tx . GetHash ( ) ] = CTxIndex ( CDiskTxPos ( 1 , 1 , 1 ) , tx . vout . size ( ) ) ;
mapTestPoolTmp [ tx . GetHash ( ) ] = CTxIndex ( CDiskTxPos ( true ) , tx . vout . size ( ) ) ;
swap ( mapTestPool , mapTestPoolTmp ) ;
// Added
@ -3743,7 +3708,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
@@ -3743,7 +3708,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
pblock - > nNonce = 0 ;
pblock - > vtx [ 0 ] . vin [ 0 ] . scriptSig = scriptDummy ;
CBlockIndex indexDummy ( 1 , 1 , * pblock ) ;
CBlockIndex indexDummy ( * pblock ) ;
indexDummy . pprev = pindexPrev ;
indexDummy . nHeight = pindexPrev - > nHeight + 1 ;
if ( ! pblock - > ConnectBlock ( txdb , & indexDummy , true ) )