Skip to content

Commit f97b321

Browse files
committed
FAB-1020 Configuration system chaincode
This commit supports FAB-1020 work later. It provides some utilities on block manipulation and a test configuration block to be used in testing new chains. Change-Id: I4ac4949e95256b06b066abb7889f68862a401a45 Signed-off-by: Binh Q. Nguyen <[email protected]>
1 parent 81eda7b commit f97b321

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed

protos/utils/blockutils.go

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package utils
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/golang/protobuf/proto"
23+
24+
"github.com/hyperledger/fabric/orderer/common/cauthdsl"
25+
"github.com/hyperledger/fabric/orderer/common/configtx"
26+
cb "github.com/hyperledger/fabric/protos/common"
27+
ab "github.com/hyperledger/fabric/protos/orderer"
28+
)
29+
30+
// GetChainIDFromBlock returns chain ID in the block
31+
func GetChainIDFromBlock(block *cb.Block) (string, error) {
32+
if block.Data == nil || block.Data.Data == nil || len(block.Data.Data) == 0 {
33+
return "", fmt.Errorf("Failed to find chain ID because the block is empty.")
34+
}
35+
var err error
36+
envelope := &cb.Envelope{}
37+
if err = proto.Unmarshal(block.Data.Data[0], envelope); err != nil {
38+
return "", fmt.Errorf("Error reconstructing envelope(%s)", err)
39+
}
40+
payload := &cb.Payload{}
41+
if err = proto.Unmarshal(envelope.Payload, payload); err != nil {
42+
return "", fmt.Errorf("Error reconstructing payload(%s)", err)
43+
}
44+
45+
return payload.Header.ChainHeader.ChainID, nil
46+
}
47+
48+
// GetBlockFromBlockBytes marshals the bytes into Block
49+
func GetBlockFromBlockBytes(blockBytes []byte) (*cb.Block, error) {
50+
block := &cb.Block{}
51+
err := proto.Unmarshal(blockBytes, block)
52+
return block, err
53+
}
54+
55+
// MakeConfigurationBlock creates a mock configuration block for testing in
56+
// various modules. This is a convenient function rather than every test
57+
// implements its own
58+
func MakeConfigurationBlock(testChainID string) (*cb.Block, error) {
59+
configItemChainHeader := MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM,
60+
messageVersion, testChainID, epoch)
61+
62+
configEnvelope := MakeConfigurationEnvelope(
63+
encodeConsensusType(testChainID),
64+
encodeBatchSize(testChainID),
65+
lockDefaultModificationPolicy(testChainID),
66+
)
67+
payloadChainHeader := MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION,
68+
configItemChainHeader.Version, testChainID, epoch)
69+
payloadSignatureHeader := MakeSignatureHeader(nil, CreateNonceOrPanic())
70+
payloadHeader := MakePayloadHeader(payloadChainHeader, payloadSignatureHeader)
71+
payload := &cb.Payload{Header: payloadHeader, Data: MarshalOrPanic(configEnvelope)}
72+
envelope := &cb.Envelope{Payload: MarshalOrPanic(payload), Signature: nil}
73+
74+
blockData := &cb.BlockData{Data: [][]byte{MarshalOrPanic(envelope)}}
75+
76+
return &cb.Block{
77+
Header: &cb.BlockHeader{
78+
Number: 0,
79+
PreviousHash: nil,
80+
DataHash: blockData.Hash(),
81+
},
82+
Data: blockData,
83+
Metadata: nil,
84+
}, nil
85+
}
86+
87+
const (
88+
batchSize = 10
89+
consensusType = "solo"
90+
epoch = uint64(0)
91+
messageVersion = int32(1)
92+
lastModified = uint64(0)
93+
consensusTypeKey = "ConsensusType"
94+
batchSizeKey = "BatchSize"
95+
)
96+
97+
func createSignedConfigItem(chainID string,
98+
configItemKey string,
99+
configItemValue []byte,
100+
modPolicy string) *cb.SignedConfigurationItem {
101+
102+
ciChainHeader := MakeChainHeader(cb.HeaderType_CONFIGURATION_ITEM,
103+
messageVersion, chainID, epoch)
104+
configItem := MakeConfigurationItem(ciChainHeader,
105+
cb.ConfigurationItem_Orderer, lastModified, modPolicy,
106+
configItemKey, configItemValue)
107+
108+
return &cb.SignedConfigurationItem{
109+
ConfigurationItem: MarshalOrPanic(configItem),
110+
Signatures: nil}
111+
}
112+
113+
func encodeConsensusType(testChainID string) *cb.SignedConfigurationItem {
114+
return createSignedConfigItem(testChainID,
115+
consensusTypeKey,
116+
MarshalOrPanic(&ab.ConsensusType{Type: consensusType}),
117+
configtx.DefaultModificationPolicyID)
118+
}
119+
120+
func encodeBatchSize(testChainID string) *cb.SignedConfigurationItem {
121+
return createSignedConfigItem(testChainID,
122+
batchSizeKey,
123+
MarshalOrPanic(&ab.BatchSize{Messages: batchSize}),
124+
configtx.DefaultModificationPolicyID)
125+
}
126+
127+
func lockDefaultModificationPolicy(testChainID string) *cb.SignedConfigurationItem {
128+
return createSignedConfigItem(testChainID,
129+
configtx.DefaultModificationPolicyID,
130+
MarshalOrPanic(MakePolicyOrPanic(cauthdsl.RejectAllPolicy)),
131+
configtx.DefaultModificationPolicyID)
132+
}

protos/utils/blockutils_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// This package provides unit tests for blocks
18+
package utils
19+
20+
import (
21+
"testing"
22+
23+
"github.com/hyperledger/fabric/protos/common"
24+
)
25+
26+
func TestGetChainIDFromBlock(t *testing.T) {
27+
var err error
28+
var gb *common.Block
29+
var cid string
30+
31+
testChainID := "myuniquetestchainid"
32+
33+
gb, err = MakeConfigurationBlock(testChainID)
34+
if err != nil {
35+
t.Fatalf("failed to create test configuration block: %s", err)
36+
}
37+
cid, err = GetChainIDFromBlock(gb)
38+
if err != nil {
39+
t.Fatalf("failed to get chain ID from block: %s", err)
40+
}
41+
if testChainID != cid {
42+
t.Fatalf("failed with wrong chain ID: Actual=%s; Got=%s", testChainID, cid)
43+
}
44+
45+
badBlock := gb
46+
badBlock.Data = nil
47+
_, err = GetChainIDFromBlock(badBlock)
48+
// We should get error
49+
if err == nil {
50+
t.Fatalf("error is expected -- the block must not be marshallable")
51+
}
52+
}
53+
54+
func TestGetBlockFromBlockBytes(t *testing.T) {
55+
testChainID := "myuniquetestchainid"
56+
gb, err := MakeConfigurationBlock(testChainID)
57+
if err != nil {
58+
t.Fatalf("failed to create test configuration block: %s", err)
59+
}
60+
blockBytes, err := Marshal(gb)
61+
if err != nil {
62+
t.Fatalf("failed to marshal block: %s", err)
63+
}
64+
_, err = GetBlockFromBlockBytes(blockBytes)
65+
if err != nil {
66+
t.Fatalf("failed to get block from block bytes: %s", err)
67+
}
68+
}

0 commit comments

Comments
 (0)