-
Notifications
You must be signed in to change notification settings - Fork 8.8k
/
blockutils.go
128 lines (110 loc) · 4 KB
/
blockutils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package utils
import (
"fmt"
"github.com/golang/protobuf/proto"
cb "github.com/hyperledger/fabric/protos/common"
)
// GetChainIDFromBlockBytes returns chain ID given byte array which represents the block
func GetChainIDFromBlockBytes(bytes []byte) (string, error) {
block, err := GetBlockFromBlockBytes(bytes)
if err != nil {
return "", err
}
return GetChainIDFromBlock(block)
}
// GetChainIDFromBlock returns chain ID in the block
func GetChainIDFromBlock(block *cb.Block) (string, error) {
if block == nil || block.Data == nil || block.Data.Data == nil || len(block.Data.Data) == 0 {
return "", fmt.Errorf("failed to retrieve channel id - block is empty")
}
var err error
envelope := &cb.Envelope{}
if err = proto.Unmarshal(block.Data.Data[0], envelope); err != nil {
return "", fmt.Errorf("error reconstructing envelope(%s)", err)
}
payload := &cb.Payload{}
if err = proto.Unmarshal(envelope.Payload, payload); err != nil {
return "", fmt.Errorf("error reconstructing payload(%s)", err)
}
if payload.Header == nil {
return "", fmt.Errorf("failed to retrieve channel id - payload header is empty")
}
chdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader)
if err != nil {
return "", err
}
return chdr.ChannelId, nil
}
// GetMetadataFromBlock retrieves metadata at the specified index.
func GetMetadataFromBlock(block *cb.Block, index cb.BlockMetadataIndex) (*cb.Metadata, error) {
md := &cb.Metadata{}
err := proto.Unmarshal(block.Metadata.Metadata[index], md)
if err != nil {
return nil, err
}
return md, nil
}
// GetMetadataFromBlockOrPanic retrieves metadata at the specified index, or panics on error.
func GetMetadataFromBlockOrPanic(block *cb.Block, index cb.BlockMetadataIndex) *cb.Metadata {
md, err := GetMetadataFromBlock(block, index)
if err != nil {
panic(err)
}
return md
}
// GetLastConfigIndexFromBlock retrieves the index of the last config block as encoded in the block metadata
func GetLastConfigIndexFromBlock(block *cb.Block) (uint64, error) {
md, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_LAST_CONFIG)
if err != nil {
return 0, err
}
lc := &cb.LastConfig{}
err = proto.Unmarshal(md.Value, lc)
if err != nil {
return 0, err
}
return lc.Index, nil
}
// GetLastConfigIndexFromBlockOrPanic retrieves the index of the last config block as encoded in the block metadata, or panics on error.
func GetLastConfigIndexFromBlockOrPanic(block *cb.Block) uint64 {
index, err := GetLastConfigIndexFromBlock(block)
if err != nil {
panic(err)
}
return index
}
// GetBlockFromBlockBytes marshals the bytes into Block
func GetBlockFromBlockBytes(blockBytes []byte) (*cb.Block, error) {
block := &cb.Block{}
err := proto.Unmarshal(blockBytes, block)
return block, err
}
// CopyBlockMetadata copies metadata from one block into another
func CopyBlockMetadata(src *cb.Block, dst *cb.Block) {
dst.Metadata = src.Metadata
// Once copied initialize with rest of the
// required metadata positions.
InitBlockMetadata(dst)
}
// InitBlockMetadata copies metadata from one block into another
func InitBlockMetadata(block *cb.Block) {
if block.Metadata == nil {
block.Metadata = &cb.BlockMetadata{Metadata: [][]byte{{}, {}, {}}}
} else if len(block.Metadata.Metadata) < int(cb.BlockMetadataIndex_TRANSACTIONS_FILTER+1) {
for i := int(len(block.Metadata.Metadata)); i <= int(cb.BlockMetadataIndex_TRANSACTIONS_FILTER); i++ {
block.Metadata.Metadata = append(block.Metadata.Metadata, []byte{})
}
}
}