2020-04-16 13:14:08 -04:00
// Copyright (c) 2016-2020 The Bitcoin Core developers
2016-04-15 16:23:57 -03:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2018-03-22 11:19:44 -03:00
# ifndef BITCOIN_BLOCKENCODINGS_H
# define BITCOIN_BLOCKENCODINGS_H
2016-04-15 16:23:57 -03:00
2017-11-09 21:57:53 -03:00
# include <primitives/block.h>
2016-04-15 16:23:57 -03:00
class CTxMemPool ;
2020-02-04 00:41:42 -03:00
// Transaction compression schemes for compact block relay can be introduced by writing
// an actual formatter here.
using TransactionCompression = DefaultFormatter ;
2016-04-15 16:23:57 -03:00
2020-02-16 00:05:11 -03:00
class DifferenceFormatter
{
uint64_t m_shift = 0 ;
public :
template < typename Stream , typename I >
void Ser ( Stream & s , I v )
{
if ( v < m_shift | | v > = std : : numeric_limits < uint64_t > : : max ( ) ) throw std : : ios_base : : failure ( " differential value overflow " ) ;
WriteCompactSize ( s , v - m_shift ) ;
m_shift = uint64_t ( v ) + 1 ;
}
template < typename Stream , typename I >
void Unser ( Stream & s , I & v )
{
uint64_t n = ReadCompactSize ( s ) ;
m_shift + = n ;
if ( m_shift < n | | m_shift > = std : : numeric_limits < uint64_t > : : max ( ) | | m_shift < std : : numeric_limits < I > : : min ( ) | | m_shift > std : : numeric_limits < I > : : max ( ) ) throw std : : ios_base : : failure ( " differential value overflow " ) ;
v = I ( m_shift + + ) ;
}
} ;
2016-04-15 16:23:57 -03:00
class BlockTransactionsRequest {
public :
// A BlockTransactionsRequest message
uint256 blockhash ;
std : : vector < uint16_t > indexes ;
2020-02-04 00:41:42 -03:00
SERIALIZE_METHODS ( BlockTransactionsRequest , obj )
{
READWRITE ( obj . blockhash , Using < VectorFormatter < DifferenceFormatter > > ( obj . indexes ) ) ;
2016-04-15 16:23:57 -03:00
}
} ;
class BlockTransactions {
public :
// A BlockTransactions message
uint256 blockhash ;
2016-11-10 22:34:17 -03:00
std : : vector < CTransactionRef > txn ;
2016-04-15 16:23:57 -03:00
BlockTransactions ( ) { }
2017-08-01 06:22:41 -04:00
explicit BlockTransactions ( const BlockTransactionsRequest & req ) :
2016-04-15 16:23:57 -03:00
blockhash ( req . blockhash ) , txn ( req . indexes . size ( ) ) { }
2020-02-04 00:41:42 -03:00
SERIALIZE_METHODS ( BlockTransactions , obj )
{
READWRITE ( obj . blockhash , Using < VectorFormatter < TransactionCompression > > ( obj . txn ) ) ;
2016-04-15 16:23:57 -03:00
}
} ;
2017-01-18 12:15:37 -03:00
// Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock
2016-04-15 16:23:57 -03:00
struct PrefilledTransaction {
// Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs,
// as a proper transaction-in-block-index in PartiallyDownloadedBlock
uint16_t index ;
2016-11-10 22:34:17 -03:00
CTransactionRef tx ;
2016-04-15 16:23:57 -03:00
2020-02-04 00:41:42 -03:00
SERIALIZE_METHODS ( PrefilledTransaction , obj ) { READWRITE ( COMPACTSIZE ( obj . index ) , Using < TransactionCompression > ( obj . tx ) ) ; }
2016-04-15 16:23:57 -03:00
} ;
typedef enum ReadStatus_t
{
READ_STATUS_OK ,
READ_STATUS_INVALID , // Invalid object, peer is sending bogus crap
READ_STATUS_FAILED , // Failed to process object
2016-10-31 11:03:49 -03:00
READ_STATUS_CHECKBLOCK_FAILED , // Used only by FillBlock to indicate a
// failure in CheckBlock.
2016-04-15 16:23:57 -03:00
} ReadStatus ;
class CBlockHeaderAndShortTxIDs {
private :
mutable uint64_t shorttxidk0 , shorttxidk1 ;
uint64_t nonce ;
void FillShortTxIDSelector ( ) const ;
friend class PartiallyDownloadedBlock ;
protected :
std : : vector < uint64_t > shorttxids ;
std : : vector < PrefilledTransaction > prefilledtxn ;
public :
2020-03-11 13:35:39 -03:00
static constexpr int SHORTTXIDS_LENGTH = 6 ;
2016-04-15 16:23:57 -03:00
CBlockHeader header ;
// Dummy for deserialization
CBlockHeaderAndShortTxIDs ( ) { }
2016-06-25 13:17:45 -04:00
CBlockHeaderAndShortTxIDs ( const CBlock & block , bool fUseWTXID ) ;
2016-04-15 16:23:57 -03:00
uint64_t GetShortID ( const uint256 & txhash ) const ;
size_t BlockTxCount ( ) const { return shorttxids . size ( ) + prefilledtxn . size ( ) ; }
2020-02-04 00:41:42 -03:00
SERIALIZE_METHODS ( CBlockHeaderAndShortTxIDs , obj )
{
READWRITE ( obj . header , obj . nonce , Using < VectorFormatter < CustomUintFormatter < SHORTTXIDS_LENGTH > > > ( obj . shorttxids ) , obj . prefilledtxn ) ;
2016-04-15 16:23:57 -03:00
if ( ser_action . ForRead ( ) ) {
2020-02-04 00:41:42 -03:00
if ( obj . BlockTxCount ( ) > std : : numeric_limits < uint16_t > : : max ( ) ) {
throw std : : ios_base : : failure ( " indexes overflowed 16 bits " ) ;
2016-04-15 16:23:57 -03:00
}
2020-02-04 00:41:42 -03:00
obj . FillShortTxIDSelector ( ) ;
2016-04-15 16:23:57 -03:00
}
}
} ;
class PartiallyDownloadedBlock {
protected :
2016-11-10 22:34:17 -03:00
std : : vector < CTransactionRef > txn_available ;
2017-01-12 17:19:14 -03:00
size_t prefilled_count = 0 , mempool_count = 0 , extra_count = 0 ;
2020-05-28 02:55:39 -04:00
const CTxMemPool * pool ;
2016-04-15 16:23:57 -03:00
public :
CBlockHeader header ;
2017-08-01 06:22:41 -04:00
explicit PartiallyDownloadedBlock ( CTxMemPool * poolIn ) : pool ( poolIn ) { }
2016-04-15 16:23:57 -03:00
2016-12-05 01:44:37 -03:00
// extra_txn is a list of extra transactions to look at, in <witness hash, reference> form
2017-01-12 17:20:11 -03:00
ReadStatus InitData ( const CBlockHeaderAndShortTxIDs & cmpctblock , const std : : vector < std : : pair < uint256 , CTransactionRef > > & extra_txn ) ;
2016-04-15 16:23:57 -03:00
bool IsTxAvailable ( size_t index ) const ;
2016-11-11 18:01:27 -03:00
ReadStatus FillBlock ( CBlock & block , const std : : vector < CTransactionRef > & vtx_missing ) ;
2016-04-15 16:23:57 -03:00
} ;
2018-03-22 11:19:44 -03:00
# endif // BITCOIN_BLOCKENCODINGS_H