github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/utils/parserutils.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/martinboehm/btcd/wire"
     8  )
     9  
    10  // minTxPayload is the minimum payload size for a transaction.  Note
    11  // that any realistically usable transaction must have at least one
    12  // input or output, but that is a rule enforced at a higher layer, so
    13  // it is intentionally not included here.
    14  // Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
    15  // number of transaction outputs 1 byte + LockTime 4 bytes + min input
    16  // payload + min output payload.
    17  const minTxPayload = 10
    18  
    19  // maxTxPerBlock is the maximum number of transactions that could
    20  // possibly fit into a block.
    21  const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
    22  
    23  // DecodeTransactions decodes transactions from input stream using wire
    24  func DecodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
    25  	txCount, err := wire.ReadVarInt(r, pver)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	// Prevent more transactions than could possibly fit into a block.
    31  	// It would be possible to cause memory exhaustion and panics without
    32  	// a sane upper bound on this count.
    33  	if txCount > maxTxPerBlock {
    34  		str := fmt.Sprintf("too many transactions to fit into a block "+
    35  			"[count %d, max %d]", txCount, maxTxPerBlock)
    36  		return &wire.MessageError{Func: "utils.decodeTransactions", Description: str}
    37  	}
    38  
    39  	blk.Transactions = make([]*wire.MsgTx, 0, txCount)
    40  	for i := uint64(0); i < txCount; i++ {
    41  		tx := wire.MsgTx{}
    42  		err := tx.BtcDecode(r, pver, enc)
    43  		if err != nil {
    44  			return err
    45  		}
    46  		blk.Transactions = append(blk.Transactions, &tx)
    47  	}
    48  
    49  	return nil
    50  }
    51  
    52  // VersionAuxpow marks that block contains Auxpow
    53  const VersionAuxpow = (1 << 8)
    54  
    55  // SkipAuxpow skips Auxpow data in block
    56  func SkipAuxpow(r io.ReadSeeker) error {
    57  	// skip Auxpow part of the block
    58  	// https://github.com/dogecoin/dogecoin/blob/master/src/auxpow.h#L130
    59  	// CMerkleTx CTransaction
    60  	tx := wire.MsgTx{}
    61  	err := tx.BtcDecode(r, 0, wire.WitnessEncoding)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	// CMerkleTx uint256 hashBlock
    66  	_, err = r.Seek(32, io.SeekCurrent)
    67  	if err != nil {
    68  		return err
    69  	}
    70  	// CMerkleTx std::vector<uint256> vMerkleBranch
    71  	size, err := wire.ReadVarInt(r, 0)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	_, err = r.Seek(int64(size)*32, io.SeekCurrent)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	// CMerkleTx int nIndex
    80  	_, err = r.Seek(4, io.SeekCurrent)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	// CAuxPow std::vector<uint256> vChainMerkleBranch;
    85  	size, err = wire.ReadVarInt(r, 0)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	_, err = r.Seek(int64(size)*32, io.SeekCurrent)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	// CAuxPow int nChainIndex;
    94  	_, err = r.Seek(4, io.SeekCurrent)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	// CAuxPow CPureBlockHeader parentBlock;
    99  	ph := wire.BlockHeader{}
   100  	err = ph.Deserialize(r)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return nil
   105  }