-
Notifications
You must be signed in to change notification settings - Fork 1
/
configtx_processor.go
154 lines (131 loc) · 5.24 KB
/
configtx_processor.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package peer
import (
"fmt"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/resourcesconfig"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/customtx"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/utils"
)
const (
resourcesConfigKey = "resourcesconfigtx.RESOURCES_CONFIG_KEY"
channelConfigKey = "resourcesconfigtx.CHANNEL_CONFIG_KEY"
peerNamespace = ""
)
// txProcessor implements the interface 'github.com/hyperledger/fabric/core/ledger/customtx/Processor'
type configtxProcessor struct {
}
// newTxProcessor constructs a new instance of txProcessor
func newConfigTxProcessor() customtx.Processor {
return &configtxProcessor{}
}
// GenerateSimulationResults implements function in the interface 'github.com/hyperledger/fabric/core/ledger/customtx/Processor'
// This implemantation processes following two types of transactions.
// CONFIG - simply stores the config in the statedb. Additionally, stores the resource config seed if the transaction is from the genesis block.
// PEER_RESOURCE_UPDATE - In a normal course, this validates the transaction against the current resource bundle,
// computes the full configuration, and stores the full configuration if the transaction is found valid.
// However, if 'initializingLedger' is true (i.e., either the ledger is being created from the genesis block
// or the ledger is synching the state with the blockchain, during start up), the full config is computed using
// the most recent configs from statedb
func (tp *configtxProcessor) GenerateSimulationResults(txEnv *common.Envelope, simulator ledger.TxSimulator, initializingLedger bool) error {
payload := utils.UnmarshalPayloadOrPanic(txEnv.Payload)
channelHdr := utils.UnmarshalChannelHeaderOrPanic(payload.Header.ChannelHeader)
chainid := channelHdr.ChannelId
txType := common.HeaderType(channelHdr.GetType())
switch txType {
case common.HeaderType_CONFIG:
peerLogger.Debugf("Processing CONFIG")
return processChannelConfigTx(chainid, txEnv, simulator)
case common.HeaderType_PEER_RESOURCE_UPDATE:
peerLogger.Debugf("Processing PEER_RESOURCE_UPDATE")
if initializingLedger {
return processResourceConfigTxDuringInitialization(chainid, txEnv, simulator)
}
return processResourceConfigTx(chainid, txEnv, simulator)
default:
return fmt.Errorf("tx type [%s] is not expected", txType)
}
}
func processChannelConfigTx(chainid string, txEnv *common.Envelope, simulator ledger.TxSimulator) error {
configEnvelope := &common.ConfigEnvelope{}
if _, err := utils.UnmarshalEnvelopeOfType(txEnv, common.HeaderType_CONFIG, configEnvelope); err != nil {
return err
}
channelConfig := configEnvelope.Config
if err := persistConf(simulator, channelConfigKey, channelConfig); err != nil {
return err
}
peerLogger.Debugf("channelConfig=%s", channelConfig)
if channelConfig == nil {
return fmt.Errorf("Channel config found nil")
}
resConfCapabilityOn, err := isResConfigCapabilityOn(chainid, channelConfig)
if err != nil {
return err
}
resourceConfigSeed, err := extractFullConfigFromSeedTx(configEnvelope)
if err != nil {
return err
}
if channelConfig.Sequence == 1 && resConfCapabilityOn {
if resourceConfigSeed == nil {
return fmt.Errorf("Resource config cannot be nil in the genesis ('CONFIG') transaction")
}
return persistConf(simulator, resourcesConfigKey, resourceConfigSeed)
}
return nil
}
func processResourceConfigTx(chainid string, txEnv *common.Envelope, simulator ledger.TxSimulator) error {
fullResConf, err := validateAndApplyResourceConfig(chainid, txEnv)
if err != nil {
return err
}
return persistConf(simulator, resourcesConfigKey, fullResConf)
}
func processResourceConfigTxDuringInitialization(chainid string, txEnv *common.Envelope, simulator ledger.TxSimulator) error {
var existingResConf, existingChanConf, updatedResConf *common.Config
var err error
if existingResConf, err = retrievePersistedConf(simulator, resourcesConfigKey); err != nil {
return err
}
if existingChanConf, err = retrievePersistedConf(simulator, channelConfigKey); err != nil {
return err
}
if existingResConf == nil || existingChanConf == nil {
return fmt.Errorf("Channel config or resource config should not be nil")
}
chanConfigBundle, err := channelconfig.NewBundle(chainid, existingChanConf)
if err != nil {
return err
}
resConfigBundle, err := resourcesconfig.NewBundle(chainid, existingResConf, chanConfigBundle)
if err != nil {
return err
}
if updatedResConf, err = computeFullConfig(resConfigBundle, txEnv); err != nil {
return err
}
return persistConf(simulator, resourcesConfigKey, updatedResConf)
}
func persistConf(simulator ledger.TxSimulator, key string, config *common.Config) error {
serializedConfig, err := serialize(config)
if err != nil {
return err
}
return simulator.SetState(peerNamespace, key, serializedConfig)
}
func retrievePersistedConf(queryExecuter ledger.QueryExecutor, key string) (*common.Config, error) {
serializedConfig, err := queryExecuter.GetState(peerNamespace, key)
if err != nil {
return nil, err
}
if serializedConfig == nil {
return nil, nil
}
return deserialize(serializedConfig)
}