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

     1  package types
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"io"
     7  	"time"
     8  
     9  	"github.com/bytom/bytom/encoding/blockchain"
    10  	"github.com/bytom/bytom/encoding/bufpool"
    11  	"github.com/bytom/bytom/errors"
    12  	"github.com/bytom/bytom/protocol/bc"
    13  )
    14  
    15  // BlockHeader defines information about a block and is used in the Bytom
    16  type BlockHeader struct {
    17  	Version           uint64  // The version of the block.
    18  	Height            uint64  // The height of the block.
    19  	PreviousBlockHash bc.Hash // The hash of the previous block.
    20  	Timestamp         uint64  // The time of the block in seconds.
    21  	BlockWitness
    22  	SupLinks
    23  	BlockCommitment
    24  }
    25  
    26  // Hash returns complete hash of the block header.
    27  func (bh *BlockHeader) Hash() bc.Hash {
    28  	h, _ := mapBlockHeader(bh)
    29  	return h
    30  }
    31  
    32  // Time returns the time represented by the Timestamp in block header.
    33  func (bh *BlockHeader) Time() time.Time {
    34  	return time.Unix(int64(bh.Timestamp/1000), 0).UTC()
    35  }
    36  
    37  // MarshalText fulfills the json.Marshaler interface. This guarantees that
    38  // block headers will get deserialized correctly when being parsed from HTTP
    39  // requests.
    40  func (bh *BlockHeader) MarshalText() ([]byte, error) {
    41  	buf := bufpool.Get()
    42  	defer bufpool.Put(buf)
    43  
    44  	if _, err := bh.WriteTo(buf); err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	enc := make([]byte, hex.EncodedLen(buf.Len()))
    49  	hex.Encode(enc, buf.Bytes())
    50  	return enc, nil
    51  }
    52  
    53  // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
    54  func (bh *BlockHeader) UnmarshalText(text []byte) error {
    55  	decoded := make([]byte, hex.DecodedLen(len(text)))
    56  	if _, err := hex.Decode(decoded, text); err != nil {
    57  		return err
    58  	}
    59  
    60  	serflag, err := bh.readFrom(blockchain.NewReader(decoded))
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	if serflag == SerBlockTransactions {
    66  		return fmt.Errorf("unsupported serialization flags 0x%02x", serflag)
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  // WriteTo writes the block header to the input io.Writer
    73  func (bh *BlockHeader) WriteTo(w io.Writer) (int64, error) {
    74  	ew := errors.NewWriter(w)
    75  	if err := bh.writeTo(ew, SerBlockHeader); err != nil {
    76  		return 0, err
    77  	}
    78  	return ew.Written(), ew.Err()
    79  }
    80  
    81  func (bh *BlockHeader) readFrom(r *blockchain.Reader) (serflag uint8, err error) {
    82  	var serflags [1]byte
    83  	if _, err := io.ReadFull(r, serflags[:]); err != nil {
    84  		return 0, err
    85  	}
    86  
    87  	serflag = serflags[0]
    88  	switch serflag {
    89  	case SerBlockHeader, SerBlockFull:
    90  	case SerBlockTransactions:
    91  		return
    92  	default:
    93  		return 0, fmt.Errorf("unsupported serialization flags 0x%x", serflags)
    94  	}
    95  
    96  	if bh.Version, err = blockchain.ReadVarint63(r); err != nil {
    97  		return 0, err
    98  	}
    99  
   100  	if bh.Height, err = blockchain.ReadVarint63(r); err != nil {
   101  		return 0, err
   102  	}
   103  
   104  	if _, err = bh.PreviousBlockHash.ReadFrom(r); err != nil {
   105  		return 0, err
   106  	}
   107  
   108  	if bh.Timestamp, err = blockchain.ReadVarint63(r); err != nil {
   109  		return 0, err
   110  	}
   111  
   112  	if _, err = blockchain.ReadExtensibleString(r, bh.BlockCommitment.readFrom); err != nil {
   113  		return 0, err
   114  	}
   115  
   116  	if _, err = blockchain.ReadExtensibleString(r, bh.BlockWitness.readFrom); err != nil {
   117  		return 0, err
   118  	}
   119  
   120  	if _, err = blockchain.ReadExtensibleString(r, bh.SupLinks.readFrom); err != nil {
   121  		return 0, err
   122  	}
   123  
   124  	return
   125  }
   126  
   127  func (bh *BlockHeader) writeTo(w io.Writer, serflags uint8) (err error) {
   128  	w.Write([]byte{serflags})
   129  	if serflags == SerBlockTransactions {
   130  		return nil
   131  	}
   132  
   133  	if _, err = blockchain.WriteVarint63(w, bh.Version); err != nil {
   134  		return err
   135  	}
   136  
   137  	if _, err = blockchain.WriteVarint63(w, bh.Height); err != nil {
   138  		return err
   139  	}
   140  
   141  	if _, err = bh.PreviousBlockHash.WriteTo(w); err != nil {
   142  		return err
   143  	}
   144  
   145  	if _, err = blockchain.WriteVarint63(w, bh.Timestamp); err != nil {
   146  		return err
   147  	}
   148  
   149  	if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockCommitment.writeTo); err != nil {
   150  		return err
   151  	}
   152  
   153  	if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockWitness.writeTo); err != nil {
   154  		return err
   155  	}
   156  
   157  	if _, err = blockchain.WriteExtensibleString(w, nil, bh.SupLinks.writeTo); err != nil {
   158  		return err
   159  	}
   160  
   161  	return
   162  }