github.com/lzy4123/fabric@v2.1.1+incompatible/protoutil/blockutils.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package protoutil 8 9 import ( 10 "bytes" 11 "crypto/sha256" 12 "encoding/asn1" 13 "math/big" 14 15 "github.com/golang/protobuf/proto" 16 cb "github.com/hyperledger/fabric-protos-go/common" 17 "github.com/pkg/errors" 18 ) 19 20 // NewBlock constructs a block with no data and no metadata. 21 func NewBlock(seqNum uint64, previousHash []byte) *cb.Block { 22 block := &cb.Block{} 23 block.Header = &cb.BlockHeader{} 24 block.Header.Number = seqNum 25 block.Header.PreviousHash = previousHash 26 block.Header.DataHash = []byte{} 27 block.Data = &cb.BlockData{} 28 29 var metadataContents [][]byte 30 for i := 0; i < len(cb.BlockMetadataIndex_name); i++ { 31 metadataContents = append(metadataContents, []byte{}) 32 } 33 block.Metadata = &cb.BlockMetadata{Metadata: metadataContents} 34 35 return block 36 } 37 38 type asn1Header struct { 39 Number *big.Int 40 PreviousHash []byte 41 DataHash []byte 42 } 43 44 func BlockHeaderBytes(b *cb.BlockHeader) []byte { 45 asn1Header := asn1Header{ 46 PreviousHash: b.PreviousHash, 47 DataHash: b.DataHash, 48 Number: new(big.Int).SetUint64(b.Number), 49 } 50 result, err := asn1.Marshal(asn1Header) 51 if err != nil { 52 // Errors should only arise for types which cannot be encoded, since the 53 // BlockHeader type is known a-priori to contain only encodable types, an 54 // error here is fatal and should not be propogated 55 panic(err) 56 } 57 return result 58 } 59 60 func BlockHeaderHash(b *cb.BlockHeader) []byte { 61 sum := sha256.Sum256(BlockHeaderBytes(b)) 62 return sum[:] 63 } 64 65 func BlockDataHash(b *cb.BlockData) []byte { 66 sum := sha256.Sum256(bytes.Join(b.Data, nil)) 67 return sum[:] 68 } 69 70 // GetChainIDFromBlockBytes returns chain ID given byte array which represents 71 // the block 72 func GetChainIDFromBlockBytes(bytes []byte) (string, error) { 73 block, err := UnmarshalBlock(bytes) 74 if err != nil { 75 return "", err 76 } 77 78 return GetChainIDFromBlock(block) 79 } 80 81 // GetChainIDFromBlock returns chain ID in the block 82 func GetChainIDFromBlock(block *cb.Block) (string, error) { 83 if block == nil || block.Data == nil || block.Data.Data == nil || len(block.Data.Data) == 0 { 84 return "", errors.New("failed to retrieve channel id - block is empty") 85 } 86 var err error 87 envelope, err := GetEnvelopeFromBlock(block.Data.Data[0]) 88 if err != nil { 89 return "", err 90 } 91 payload, err := UnmarshalPayload(envelope.Payload) 92 if err != nil { 93 return "", err 94 } 95 96 if payload.Header == nil { 97 return "", errors.New("failed to retrieve channel id - payload header is empty") 98 } 99 chdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader) 100 if err != nil { 101 return "", err 102 } 103 104 return chdr.ChannelId, nil 105 } 106 107 // GetMetadataFromBlock retrieves metadata at the specified index. 108 func GetMetadataFromBlock(block *cb.Block, index cb.BlockMetadataIndex) (*cb.Metadata, error) { 109 if block.Metadata == nil { 110 return nil, errors.New("no metadata in block") 111 } 112 113 if len(block.Metadata.Metadata) <= int(index) { 114 return nil, errors.Errorf("no metadata at index [%s]", index) 115 } 116 117 md := &cb.Metadata{} 118 err := proto.Unmarshal(block.Metadata.Metadata[index], md) 119 if err != nil { 120 return nil, errors.Wrapf(err, "error unmarshaling metadata at index [%s]", index) 121 } 122 return md, nil 123 } 124 125 // GetMetadataFromBlockOrPanic retrieves metadata at the specified index, or 126 // panics on error 127 func GetMetadataFromBlockOrPanic(block *cb.Block, index cb.BlockMetadataIndex) *cb.Metadata { 128 md, err := GetMetadataFromBlock(block, index) 129 if err != nil { 130 panic(err) 131 } 132 return md 133 } 134 135 // GetConsenterMetadataFromBlock attempts to retrieve consenter metadata from the value 136 // stored in block metadata at index SIGNATURES (first field). If no consenter metadata 137 // is found there, it falls back to index ORDERER (third field). 138 func GetConsenterMetadataFromBlock(block *cb.Block) (*cb.Metadata, error) { 139 m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES) 140 if err != nil { 141 return nil, errors.WithMessage(err, "failed to retrieve metadata") 142 } 143 144 // TODO FAB-15864 Remove this fallback when we can stop supporting upgrade from pre-1.4.1 orderer 145 if len(m.Value) == 0 { 146 return GetMetadataFromBlock(block, cb.BlockMetadataIndex_ORDERER) 147 } 148 149 obm := &cb.OrdererBlockMetadata{} 150 err = proto.Unmarshal(m.Value, obm) 151 if err != nil { 152 return nil, errors.Wrap(err, "failed to unmarshal orderer block metadata") 153 } 154 155 res := &cb.Metadata{} 156 err = proto.Unmarshal(obm.ConsenterMetadata, res) 157 if err != nil { 158 return nil, errors.Wrap(err, "failed to unmarshal consenter metadata") 159 } 160 161 return res, nil 162 } 163 164 // GetLastConfigIndexFromBlock retrieves the index of the last config block as 165 // encoded in the block metadata 166 func GetLastConfigIndexFromBlock(block *cb.Block) (uint64, error) { 167 m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES) 168 if err != nil { 169 return 0, errors.WithMessage(err, "failed to retrieve metadata") 170 } 171 // TODO FAB-15864 Remove this fallback when we can stop supporting upgrade from pre-1.4.1 orderer 172 if len(m.Value) == 0 { 173 m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_LAST_CONFIG) 174 if err != nil { 175 return 0, errors.WithMessage(err, "failed to retrieve metadata") 176 } 177 lc := &cb.LastConfig{} 178 err = proto.Unmarshal(m.Value, lc) 179 if err != nil { 180 return 0, errors.Wrap(err, "error unmarshaling LastConfig") 181 } 182 return lc.Index, nil 183 } 184 185 obm := &cb.OrdererBlockMetadata{} 186 err = proto.Unmarshal(m.Value, obm) 187 if err != nil { 188 return 0, errors.Wrap(err, "failed to unmarshal orderer block metadata") 189 } 190 return obm.LastConfig.Index, nil 191 } 192 193 // GetLastConfigIndexFromBlockOrPanic retrieves the index of the last config 194 // block as encoded in the block metadata, or panics on error 195 func GetLastConfigIndexFromBlockOrPanic(block *cb.Block) uint64 { 196 index, err := GetLastConfigIndexFromBlock(block) 197 if err != nil { 198 panic(err) 199 } 200 return index 201 } 202 203 // CopyBlockMetadata copies metadata from one block into another 204 func CopyBlockMetadata(src *cb.Block, dst *cb.Block) { 205 dst.Metadata = src.Metadata 206 // Once copied initialize with rest of the 207 // required metadata positions. 208 InitBlockMetadata(dst) 209 } 210 211 // InitBlockMetadata initializes metadata structure 212 func InitBlockMetadata(block *cb.Block) { 213 if block.Metadata == nil { 214 block.Metadata = &cb.BlockMetadata{Metadata: [][]byte{{}, {}, {}, {}, {}}} 215 } else if len(block.Metadata.Metadata) < int(cb.BlockMetadataIndex_COMMIT_HASH+1) { 216 for i := int(len(block.Metadata.Metadata)); i <= int(cb.BlockMetadataIndex_COMMIT_HASH); i++ { 217 block.Metadata.Metadata = append(block.Metadata.Metadata, []byte{}) 218 } 219 } 220 }