github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/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 // MarshalText fulfills the json.Marshaler interface. This guarantees that 29 // blocks will get deserialized correctly when being parsed from HTTP requests. 30 func (b *Block) MarshalText() ([]byte, error) { 31 buf := bufpool.Get() 32 defer bufpool.Put(buf) 33 34 if _, err := b.WriteTo(buf); err != nil { 35 return nil, err 36 } 37 38 enc := make([]byte, hex.EncodedLen(buf.Len())) 39 hex.Encode(enc, buf.Bytes()) 40 return enc, nil 41 } 42 43 // UnmarshalText fulfills the encoding.TextUnmarshaler interface. 44 func (b *Block) UnmarshalText(text []byte) error { 45 decoded := make([]byte, hex.DecodedLen(len(text))) 46 if _, err := hex.Decode(decoded, text); err != nil { 47 return err 48 } 49 50 r := blockchain.NewReader(decoded) 51 if err := b.readFrom(r); err != nil { 52 return err 53 } 54 55 if trailing := r.Len(); trailing > 0 { 56 return fmt.Errorf("trailing garbage (%d bytes)", trailing) 57 } 58 return nil 59 } 60 61 func (b *Block) readFrom(r *blockchain.Reader) error { 62 serflags, err := b.BlockHeader.readFrom(r) 63 if err != nil { 64 return err 65 } 66 67 if serflags == SerBlockHeader { 68 return nil 69 } 70 71 n, err := blockchain.ReadVarint31(r) 72 if err != nil { 73 return errors.Wrap(err, "reading number of transactions") 74 } 75 76 for ; n > 0; n-- { 77 data := TxData{} 78 if err = data.readFrom(r); err != nil { 79 return errors.Wrapf(err, "reading transaction %d", len(b.Transactions)) 80 } 81 82 b.Transactions = append(b.Transactions, NewTx(data)) 83 } 84 return nil 85 } 86 87 // WriteTo will write block to input io.Writer 88 func (b *Block) WriteTo(w io.Writer) (int64, error) { 89 ew := errors.NewWriter(w) 90 if err := b.writeTo(ew, SerBlockFull); err != nil { 91 return 0, err 92 } 93 return ew.Written(), ew.Err() 94 } 95 96 func (b *Block) writeTo(w io.Writer, serflags uint8) error { 97 if err := b.BlockHeader.writeTo(w, serflags); err != nil { 98 return err 99 } 100 101 if serflags == SerBlockHeader { 102 return nil 103 } 104 105 if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil { 106 return err 107 } 108 109 for _, tx := range b.Transactions { 110 if _, err := tx.WriteTo(w); err != nil { 111 return err 112 } 113 } 114 return nil 115 }