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 }