github.com/okex/exchain@v1.8.0/libs/tendermint/types/block_meta.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/tendermint/go-amino" 7 8 "github.com/pkg/errors" 9 ) 10 11 // BlockMeta contains meta information. 12 type BlockMeta struct { 13 BlockID BlockID `json:"block_id"` 14 BlockSize int `json:"block_size"` 15 Header Header `json:"header"` 16 NumTxs int `json:"num_txs"` 17 } 18 19 // NewBlockMeta returns a new BlockMeta. 20 func NewBlockMeta(block *Block, blockParts *PartSet) *BlockMeta { 21 return &BlockMeta{ 22 BlockID: BlockID{block.Hash(), blockParts.Header()}, 23 BlockSize: block.Size(), 24 Header: block.Header, 25 NumTxs: len(block.Data.Txs), 26 } 27 } 28 29 func (bm *BlockMeta) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 30 const fieldCount = 4 31 var currentField int 32 var currentType amino.Typ3 33 var err error 34 35 for cur := 1; cur <= fieldCount; cur++ { 36 if len(data) != 0 && (currentField == 0 || currentField < cur) { 37 var nextField int 38 if nextField, currentType, err = amino.ParseProtoPosAndTypeMustOneByte(data[0]); err != nil { 39 return err 40 } 41 if nextField < currentField { 42 return errors.Errorf("next field should greater than %d, got %d", currentField, nextField) 43 } else { 44 currentField = nextField 45 } 46 } 47 48 if len(data) == 0 || currentField != cur { 49 switch cur { 50 case 1: 51 bm.BlockID = BlockID{} 52 case 2: 53 bm.BlockSize = 0 54 case 3: 55 bm.Header = Header{} 56 case 4: 57 bm.NumTxs = 0 58 default: 59 return fmt.Errorf("unexpect feild num %d", cur) 60 } 61 } else { 62 pbk := data[0] 63 data = data[1:] 64 var subData []byte 65 if currentType == amino.Typ3_ByteLength { 66 if subData, err = amino.DecodeByteSliceWithoutCopy(&data); err != nil { 67 return err 68 } 69 } 70 switch pbk { 71 case 1<<3 | byte(amino.Typ3_ByteLength): 72 if err = bm.BlockID.UnmarshalFromAmino(cdc, subData); err != nil { 73 return err 74 } 75 case 2<<3 | byte(amino.Typ3_Varint): 76 if bm.BlockSize, err = amino.DecodeIntUpdateBytes(&data); err != nil { 77 return err 78 } 79 case 3<<3 | byte(amino.Typ3_ByteLength): 80 if err = bm.Header.UnmarshalFromAmino(cdc, subData); err != nil { 81 return err 82 } 83 case 4<<3 | byte(amino.Typ3_Varint): 84 if bm.NumTxs, err = amino.DecodeIntUpdateBytes(&data); err != nil { 85 return err 86 } 87 default: 88 return fmt.Errorf("unexpect pb key %d", pbk) 89 } 90 } 91 } 92 93 if len(data) != 0 { 94 return errors.Errorf("unexpect data remain %X", data) 95 } 96 97 return nil 98 } 99 100 //----------------------------------------------------------- 101 // These methods are for Protobuf Compatibility 102 103 // Size returns the size of the amino encoding, in bytes. 104 func (bm *BlockMeta) Size() int { 105 bs, _ := bm.Marshal() 106 return len(bs) 107 } 108 109 // Marshal returns the amino encoding. 110 func (bm *BlockMeta) Marshal() ([]byte, error) { 111 return cdc.MarshalBinaryBare(bm) 112 } 113 114 // MarshalTo calls Marshal and copies to the given buffer. 115 func (bm *BlockMeta) MarshalTo(data []byte) (int, error) { 116 bs, err := bm.Marshal() 117 if err != nil { 118 return -1, err 119 } 120 return copy(data, bs), nil 121 } 122 123 // Unmarshal deserializes from amino encoded form. 124 func (bm *BlockMeta) Unmarshal(bs []byte) error { 125 return cdc.UnmarshalBinaryBare(bs, bm) 126 } 127 128 // ValidateBasic performs basic validation. 129 func (bm *BlockMeta) ValidateBasic() error { 130 if err := bm.BlockID.ValidateBasic(); err != nil { 131 return err 132 } 133 if !bytes.Equal(bm.BlockID.Hash, bm.Header.Hash()) { 134 return errors.Errorf("expected BlockID#Hash and Header#Hash to be the same, got %X != %X", 135 bm.BlockID.Hash, bm.Header.Hash()) 136 } 137 return nil 138 }