Skip to content

Commit 82e72f4

Browse files
committed
Restructure static bootstrapper's genesis block
The data section of the genesis block currently output by the static bootstrap helper consists of a single marshaled ConfigurationEnvelope. This is not right. It should instead be a single marshaled Envelope. This changeset also addresses the following issues: - The previous hash of the genesis block was erroneously set to a non-nil value. - The signature of the makeSignedConfigurationItem() has been modified so that the order of the input arguments makes sense. Change-Id: I29cd095d5510dc16dccb808dc9dc8bce931cf391 Signed-off-by: Kostas Christidis <[email protected]>
1 parent 7e7e23c commit 82e72f4

File tree

3 files changed

+91
-44
lines changed

3 files changed

+91
-44
lines changed

orderer/common/bootstrap/static/static.go

+70-30
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,34 @@ limitations under the License.
1717
package static
1818

1919
import (
20-
"math/rand"
20+
"fmt"
21+
"time"
2122

23+
"github.com/hyperledger/fabric/core/crypto/primitives"
2224
"github.com/hyperledger/fabric/orderer/common/bootstrap"
2325
"github.com/hyperledger/fabric/orderer/common/cauthdsl"
2426
"github.com/hyperledger/fabric/orderer/common/configtx"
2527
cb "github.com/hyperledger/fabric/protos/common"
2628

2729
"github.com/golang/protobuf/proto"
30+
"github.com/golang/protobuf/ptypes/timestamp"
2831
)
2932

3033
type bootstrapper struct {
3134
chainID []byte
3235
}
3336

34-
// New returns a new static bootstrap helper
37+
// New returns a new static bootstrap helper.
3538
func New() bootstrap.Helper {
36-
b := make([]byte, 16)
37-
rand.Read(b)
38-
39-
return &bootstrapper{
40-
chainID: b,
39+
chainID, err := primitives.GetRandomBytes(16)
40+
if err != nil {
41+
panic(fmt.Errorf("Cannot generate random chain ID: %s", err))
4142
}
43+
return &bootstrapper{chainID}
4244
}
4345

44-
// errorlessMarshal prevents poluting this code with many panics, if the genesis block cannot be created, the system cannot start so panic is correct
46+
// errorlessMarshal prevents poluting this code with panics
47+
// If the genesis block cannot be created, the system cannot start so panic is correct
4548
func errorlessMarshal(thing proto.Message) []byte {
4649
data, err := proto.Marshal(thing)
4750
if err != nil {
@@ -50,19 +53,63 @@ func errorlessMarshal(thing proto.Message) []byte {
5053
return data
5154
}
5255

53-
func (b *bootstrapper) makeSignedConfigurationItem(id string, ctype cb.ConfigurationItem_ConfigurationType, data []byte, modificationPolicyID string) *cb.SignedConfigurationItem {
54-
configurationBytes := errorlessMarshal(&cb.ConfigurationItem{
55-
Header: &cb.ChainHeader{
56-
ChainID: b.chainID,
56+
func makeChainHeader(headerType cb.HeaderType, version int32, chainID []byte) *cb.ChainHeader {
57+
return &cb.ChainHeader{
58+
Type: int32(headerType),
59+
Version: version,
60+
Timestamp: &timestamp.Timestamp{
61+
Seconds: time.Now().Unix(),
62+
Nanos: 0,
5763
},
64+
ChainID: chainID,
65+
}
66+
}
67+
68+
func makeSignatureHeader(serializedCreatorCertChain []byte, nonce []byte, epoch uint64) *cb.SignatureHeader {
69+
return &cb.SignatureHeader{
70+
Creator: serializedCreatorCertChain,
71+
Nonce: nonce,
72+
Epoch: epoch,
73+
}
74+
}
75+
76+
func (b *bootstrapper) makeSignedConfigurationItem(configurationItemType cb.ConfigurationItem_ConfigurationType, modificationPolicyID string, key string, value []byte) *cb.SignedConfigurationItem {
77+
marshaledConfigurationItem := errorlessMarshal(&cb.ConfigurationItem{
78+
Header: makeChainHeader(cb.HeaderType_CONFIGURATION_ITEM, 1, b.chainID),
79+
Type: configurationItemType,
5880
LastModified: 0,
59-
Type: ctype,
6081
ModificationPolicy: modificationPolicyID,
61-
Key: id,
62-
Value: data,
82+
Key: key,
83+
Value: value,
6384
})
85+
6486
return &cb.SignedConfigurationItem{
65-
ConfigurationItem: configurationBytes,
87+
ConfigurationItem: marshaledConfigurationItem,
88+
Signatures: nil,
89+
}
90+
}
91+
92+
func (b *bootstrapper) makeConfigurationEnvelope(items ...*cb.SignedConfigurationItem) *cb.ConfigurationEnvelope {
93+
return &cb.ConfigurationEnvelope{
94+
Items: items,
95+
}
96+
}
97+
98+
func (b *bootstrapper) makeEnvelope(configurationEnvelope *cb.ConfigurationEnvelope) *cb.Envelope {
99+
nonce, err := primitives.GetRandomNonce()
100+
if err != nil {
101+
panic(fmt.Errorf("Cannot generate random nonce: %s", err))
102+
}
103+
marshaledPayload := errorlessMarshal(&cb.Payload{
104+
Header: &cb.Header{
105+
ChainHeader: makeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, 1, b.chainID),
106+
SignatureHeader: makeSignatureHeader(nil, nonce, 0),
107+
},
108+
Data: errorlessMarshal(configurationEnvelope),
109+
})
110+
return &cb.Envelope{
111+
Payload: marshaledPayload,
112+
Signature: nil,
66113
}
67114
}
68115

@@ -77,27 +124,20 @@ func sigPolicyToPolicy(sigPolicy *cb.SignaturePolicyEnvelope) []byte {
77124

78125
// GenesisBlock returns the genesis block to be used for bootstrapping
79126
func (b *bootstrapper) GenesisBlock() (*cb.Block, error) {
80-
81127
// Lock down the default modification policy to prevent any further policy modifications
82-
lockdownDefaultModificationPolicy := b.makeSignedConfigurationItem(configtx.DefaultModificationPolicyID, cb.ConfigurationItem_Policy, sigPolicyToPolicy(cauthdsl.RejectAllPolicy), configtx.DefaultModificationPolicyID)
83-
84-
initialConfigTX := errorlessMarshal(&cb.ConfigurationEnvelope{
85-
Items: []*cb.SignedConfigurationItem{
86-
lockdownDefaultModificationPolicy,
87-
},
88-
})
128+
lockdownDefaultModificationPolicy := b.makeSignedConfigurationItem(cb.ConfigurationItem_Policy, configtx.DefaultModificationPolicyID, configtx.DefaultModificationPolicyID, sigPolicyToPolicy(cauthdsl.RejectAllPolicy))
89129

90-
data := &cb.BlockData{
91-
Data: [][]byte{initialConfigTX},
130+
blockData := &cb.BlockData{
131+
Data: [][]byte{errorlessMarshal(b.makeEnvelope(b.makeConfigurationEnvelope(lockdownDefaultModificationPolicy)))},
92132
}
93133

94134
return &cb.Block{
95135
Header: &cb.BlockHeader{
96136
Number: 0,
97-
PreviousHash: []byte("GENESIS"),
98-
DataHash: data.Hash(),
137+
PreviousHash: nil,
138+
DataHash: blockData.Hash(),
99139
},
100-
Data: data,
140+
Data: blockData,
141+
Metadata: nil,
101142
}, nil
102-
103143
}

orderer/main.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,34 @@ func init() {
8787
func retrieveConfiguration(rl rawledger.Reader) *cb.ConfigurationEnvelope {
8888
var lastConfigTx *cb.ConfigurationEnvelope
8989

90+
envelope := new(cb.Envelope)
91+
payload := new(cb.Payload)
92+
configurationEnvelope := new(cb.ConfigurationEnvelope)
93+
9094
it, _ := rl.Iterator(ab.SeekInfo_OLDEST, 0)
9195
// Iterate over the blockchain, looking for config transactions, track the most recent one encountered
92-
// this will be the transaction which is returned
96+
// This will be the transaction which is returned
9397
for {
9498
select {
9599
case <-it.ReadyChan():
96100
block, status := it.Next()
97101
if status != cb.Status_SUCCESS {
98102
panic(fmt.Errorf("Error parsing blockchain at startup: %v", status))
99103
}
100-
// ConfigTxs should always be by themselves
101104
if len(block.Data.Data) != 1 {
102105
continue
103106
}
104-
105-
maybeConfigTx := &cb.ConfigurationEnvelope{}
106-
107-
err := proto.Unmarshal(block.Data.Data[0], maybeConfigTx)
108-
109-
if err == nil {
110-
lastConfigTx = maybeConfigTx
107+
if err := proto.Unmarshal(block.Data.Data[0], envelope); err != nil {
108+
panic(fmt.Errorf("Block doesn't carry a message envelope: %s", err))
109+
}
110+
if err := proto.Unmarshal(envelope.Payload, payload); err != nil {
111+
panic(fmt.Errorf("Message envelope doesn't carry a payload: %s", err))
112+
}
113+
if payload.Header.ChainHeader.Type != int32(cb.HeaderType_CONFIGURATION_TRANSACTION) {
114+
continue
115+
}
116+
if err := proto.Unmarshal(payload.Data, configurationEnvelope); err == nil {
117+
lastConfigTx = configurationEnvelope
111118
}
112119
default:
113120
return lastConfigTx

protos/common/configuration.proto

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,22 @@ package common;
3535
// b) The ConfigurationSignature signature is over the concatenation of signatureHeader and the ConfigurationItem bytes (which includes a ChainHeader)
3636
// 5. Submit new Configuration for ordering in Envelope signed by submitter
3737
// a) The Envelope Payload has data set to the marshaled ConfigurationEnvelope
38-
// b) The Envelope Payload has a header of type Header.Type.CONFIGURATION_TRANSACTION
39-
//
38+
// b) The Envelope Payload has a header of type Header.Type.CONFIGURATION_TRANSACTION
39+
//
4040
// The configuration manager will verify:
4141
// 1. All configuration items and the envelope refer to the correct chain
4242
// 2. Some configuration item has been added or modified
4343
// 3. No existing configuration item has been ommitted
4444
// 4. All configuration changes have a LastModification of one more than the last configuration's highest LastModification number
45-
// 5. All configuration changes satisfy the corresponding modification policy
45+
// 5. All configuration changes satisfy the corresponding modification policy
4646
message ConfigurationEnvelope {
4747
repeated SignedConfigurationItem Items = 1;
4848
}
4949

5050
// This message may change slightly depending on the finalization of signature schemes for transactions
5151
message SignedConfigurationItem {
5252
bytes ConfigurationItem = 1;
53-
repeated ConfigurationSignature Signatures = 2; // Signatures over the hash of Configuration
53+
repeated ConfigurationSignature Signatures = 2; // Signatures over the hash of ConfigurationItem
5454
}
5555

5656
message ConfigurationItem {
@@ -100,7 +100,7 @@ message SignaturePolicy {
100100
repeated SignaturePolicy Policies = 2;
101101
}
102102
oneof Type {
103-
int32 SignedBy = 1;
103+
int32 SignedBy = 1;
104104
NOutOf From = 2;
105105
}
106106
}

0 commit comments

Comments
 (0)