github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/bc/types/block.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/bytom/bytom/encoding/blockchain"
     9  	"github.com/bytom/bytom/encoding/bufpool"
    10  	"github.com/bytom/bytom/errors"
    11  )
    12  
    13  // serflag variables, start with 1
    14  const (
    15  	_ = iota
    16  	SerBlockHeader
    17  	SerBlockTransactions
    18  	SerBlockFull
    19  )
    20  
    21  // Block describes a complete block, including its header and the transactions
    22  // it contains.
    23  type Block struct {
    24  	BlockHeader
    25  	Transactions []*Tx
    26  }
    27  
    28  func (b *Block) marshalText(serflags uint8) ([]byte, error) {
    29  	buf := bufpool.Get()
    30  	defer bufpool.Put(buf)
    31  
    32  	ew := errors.NewWriter(buf)
    33  	if err := b.writeTo(ew, serflags); err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	if err := ew.Err(); err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	enc := make([]byte, hex.EncodedLen(buf.Len()))
    42  	hex.Encode(enc, buf.Bytes())
    43  	return enc, nil
    44  }
    45  
    46  // MarshalText fulfills the json.Marshaler interface. This guarantees that
    47  // blocks will get deserialized correctly when being parsed from HTTP requests.
    48  func (b *Block) MarshalText() ([]byte, error) {
    49  	return b.marshalText(SerBlockFull)
    50  }
    51  
    52  // MarshalTextForBlockHeader fulfills the json.Marshaler interface.
    53  func (b *Block) MarshalTextForBlockHeader() ([]byte, error) {
    54  	return b.marshalText(SerBlockHeader)
    55  }
    56  
    57  // MarshalTextForTransactions fulfills the json.Marshaler interface.
    58  func (b *Block) MarshalTextForTransactions() ([]byte, error) {
    59  	return b.marshalText(SerBlockTransactions)
    60  }
    61  
    62  // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
    63  func (b *Block) UnmarshalText(text []byte) error {
    64  	decoded := make([]byte, hex.DecodedLen(len(text)))
    65  	if _, err := hex.Decode(decoded, text); err != nil {
    66  		return err
    67  	}
    68  
    69  	r := blockchain.NewReader(decoded)
    70  	if err := b.readFrom(r); err != nil {
    71  		return err
    72  	}
    73  
    74  	if trailing := r.Len(); trailing > 0 {
    75  		return fmt.Errorf("trailing garbage (%d bytes)", trailing)
    76  	}
    77  	return nil
    78  }
    79  
    80  func (b *Block) readFrom(r *blockchain.Reader) error {
    81  	serflag, err := b.BlockHeader.readFrom(r)
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	if serflag == SerBlockHeader {
    87  		return nil
    88  	}
    89  
    90  	n, err := blockchain.ReadVarint31(r)
    91  	if err != nil {
    92  		return errors.Wrap(err, "reading number of transactions")
    93  	}
    94  
    95  	for ; n > 0; n-- {
    96  		data := TxData{}
    97  		if err = data.readFrom(r); err != nil {
    98  			return errors.Wrapf(err, "reading transaction %d", len(b.Transactions))
    99  		}
   100  
   101  		b.Transactions = append(b.Transactions, NewTx(data))
   102  	}
   103  	return nil
   104  }
   105  
   106  // WriteTo write block to io.Writer
   107  func (b *Block) WriteTo(w io.Writer) (int64, error) {
   108  	ew := errors.NewWriter(w)
   109  	if err := b.writeTo(ew, SerBlockFull); err != nil {
   110  		return 0, err
   111  	}
   112  	return ew.Written(), ew.Err()
   113  }
   114  
   115  func (b *Block) writeTo(w io.Writer, serflags uint8) error {
   116  	if err := b.BlockHeader.writeTo(w, serflags); err != nil {
   117  		return err
   118  	}
   119  
   120  	if serflags == SerBlockHeader {
   121  		return nil
   122  	}
   123  
   124  	if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil {
   125  		return err
   126  	}
   127  
   128  	for _, tx := range b.Transactions {
   129  		if _, err := tx.WriteTo(w); err != nil {
   130  			return err
   131  		}
   132  	}
   133  	return nil
   134  }