Skip to content

Commit 9dbaeca

Browse files
author
Jason Yellick
committed
[FAB-1812] Pass configtx.Manager.Apply to validate
https://jira.hyperledger.org/browse/FAB-1812 The peer needs to apply configuration transactions as they are committed. This changeset hooks the configtx.Manager.Apply method into core/committer/txvalidator/validator.go so that configuration is updated as configuration blocks are committed. Because it was in the same path, it also passes the MSPManager to the validator to remove one of the dependencies on the throwaway MSP multichain manager. Change-Id: I4d606d850dddb684468d7a5dd7257e8dd967ad28 Signed-off-by: Jason Yellick <[email protected]>
1 parent 2be1717 commit 9dbaeca

File tree

6 files changed

+141
-32
lines changed

6 files changed

+141
-32
lines changed

core/committer/committer_impl.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,13 @@ func NewLedgerCommitter(ledger ledger.PeerLedger, validator txvalidator.Validato
4949
}
5050

5151
// Commit commits block to into the ledger
52+
// Note, it is important that this always be called serially
5253
func (lc *LedgerCommitter) Commit(block *common.Block) error {
5354
// Validate and mark invalid transactions
5455
logger.Debug("Validating block")
55-
lc.validator.Validate(block)
56+
if err := lc.validator.Validate(block); err != nil {
57+
return err
58+
}
5659

5760
if err := lc.ledger.Commit(block); err != nil {
5861
return err

core/committer/txvalidator/txvalidator_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
2525
"github.com/hyperledger/fabric/core/ledger/testutil"
2626
"github.com/hyperledger/fabric/core/ledger/util"
27+
mocktxvalidator "github.com/hyperledger/fabric/core/mocks/txvalidator"
2728
"github.com/hyperledger/fabric/core/mocks/validator"
2829
"github.com/hyperledger/fabric/protos/common"
2930
pb "github.com/hyperledger/fabric/protos/peer"
@@ -39,7 +40,7 @@ func TestKVLedgerBlockStorage(t *testing.T) {
3940
ledger, _ := ledgermgmt.CreateLedger("TestLedger")
4041
defer ledger.Close()
4142

42-
validator := &txValidator{ledger, &validator.MockVsccValidator{}}
43+
validator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, &validator.MockVsccValidator{}}
4344

4445
bcInfo, _ := ledger.GetBlockchainInfo()
4546
testutil.AssertEquals(t, bcInfo, &pb.BlockchainInfo{
@@ -70,7 +71,7 @@ func TestNewTxValidator_DuplicateTransactions(t *testing.T) {
7071
ledger, _ := ledgermgmt.CreateLedger("TestLedger")
7172
defer ledger.Close()
7273

73-
validator := &txValidator{ledger, &validator.MockVsccValidator{}}
74+
validator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, &validator.MockVsccValidator{}}
7475

7576
// Create simeple endorsement transaction
7677
payload := &common.Payload{

core/committer/txvalidator/validator.go

+39-21
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,30 @@ import (
2626
"github.com/hyperledger/fabric/core/common/validation"
2727
"github.com/hyperledger/fabric/core/ledger"
2828
ledgerUtil "github.com/hyperledger/fabric/core/ledger/util"
29-
"github.com/hyperledger/fabric/core/peer/msp"
3029
"github.com/hyperledger/fabric/msp"
3130
"github.com/hyperledger/fabric/protos/common"
3231
"github.com/hyperledger/fabric/protos/utils"
3332
"github.com/op/go-logging"
3433
"github.com/syndtr/goleveldb/leveldb/errors"
3534
)
3635

36+
// Support provides all of the needed to evaluate the VSCC
37+
type Support interface {
38+
// Ledger returns the ledger associated with this validator
39+
Ledger() ledger.PeerLedger
40+
41+
// MSPManager returns the MSP manager for this chain
42+
MSPManager() msp.MSPManager
43+
44+
// Apply attempts to apply a configtx to become the new configuration
45+
Apply(configtx *common.ConfigurationEnvelope) error
46+
}
47+
3748
//Validator interface which defines API to validate block transactions
3849
// and return the bit array mask indicating invalid transactions which
3950
// didn't pass validation.
4051
type Validator interface {
41-
Validate(block *common.Block)
52+
Validate(block *common.Block) error
4253
}
4354

4455
// private interface to decouple tx validator
@@ -51,16 +62,16 @@ type vsccValidator interface {
5162
// vsccValidator implementation which used to call
5263
// vscc chaincode and validate block transactions
5364
type vsccValidatorImpl struct {
54-
ledger ledger.PeerLedger
65+
support Support
5566
ccprovider ccprovider.ChaincodeProvider
5667
}
5768

5869
// implementation of Validator interface, keeps
5970
// reference to the ledger to enable tx simulation
6071
// and execution of vscc
6172
type txValidator struct {
62-
ledger ledger.PeerLedger
63-
vscc vsccValidator
73+
support Support
74+
vscc vsccValidator
6475
}
6576

6677
var logger *logging.Logger // package-level logger
@@ -71,17 +82,17 @@ func init() {
7182
}
7283

7384
// NewTxValidator creates new transactions validator
74-
func NewTxValidator(ledger ledger.PeerLedger) Validator {
85+
func NewTxValidator(support Support) Validator {
7586
// Encapsulates interface implementation
76-
return &txValidator{ledger, &vsccValidatorImpl{ledger: ledger, ccprovider: ccprovider.GetChaincodeProvider()}}
87+
return &txValidator{support, &vsccValidatorImpl{support: support, ccprovider: ccprovider.GetChaincodeProvider()}}
7788
}
7889

7990
func (v *txValidator) chainExists(chain string) bool {
8091
// TODO: implement this function!
8192
return true
8293
}
8394

84-
func (v *txValidator) Validate(block *common.Block) {
95+
func (v *txValidator) Validate(block *common.Block) error {
8596
logger.Debug("START Block Validation")
8697
defer logger.Debug("END Block Validation")
8798
txsfltr := ledgerUtil.NewFilterBitArray(uint(len(block.Data.Data)))
@@ -117,7 +128,7 @@ func (v *txValidator) Validate(block *common.Block) {
117128
if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
118129
// Check duplicate transactions
119130
txID := payload.Header.ChainHeader.TxID
120-
if _, err := v.ledger.GetTransactionByID(txID); err == nil {
131+
if _, err := v.support.Ledger().GetTransactionByID(txID); err == nil {
121132
logger.Warning("Duplicate transaction found, ", txID, ", skipping")
122133
continue
123134
}
@@ -130,13 +141,19 @@ func (v *txValidator) Validate(block *common.Block) {
130141
continue
131142
}
132143
} else if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_CONFIGURATION_TRANSACTION {
133-
// TODO: here we should call CSCC and pass it the config tx
134-
// note that there is quite a bit more validation necessary
135-
// on this tx, namely, validation that each config item has
136-
// signature matching the policy required for the item from
137-
// the existing configuration; this is taken care of nicely
138-
// by configtx.Manager (see fabric/common/configtx).
139-
logger.Debug("config transaction received for chain %s", chain)
144+
configEnvelope, err := utils.UnmarshalConfigurationEnvelope(payload.Data)
145+
if err != nil {
146+
err := fmt.Errorf("Error unmarshaling configuration which passed initial validity checks: %s", err)
147+
logger.Critical(err)
148+
return err
149+
}
150+
151+
if err := v.support.Apply(configEnvelope); err != nil {
152+
err := fmt.Errorf("Error validating configuration which passed initial validity checks: %s", err)
153+
logger.Critical(err)
154+
return err
155+
}
156+
logger.Debugf("config transaction received for chain %s", chain)
140157
}
141158

142159
if _, err := proto.Marshal(env); err != nil {
@@ -155,16 +172,17 @@ func (v *txValidator) Validate(block *common.Block) {
155172
utils.InitBlockMetadata(block)
156173
// Serialize invalid transaction bit array into block metadata field
157174
block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsfltr.ToBytes()
175+
176+
return nil
158177
}
159178

160-
// getHardcodedPolicy returns a policy that requests
179+
// getSemiHardcodedPolicy returns a policy that requests
161180
// one valid signature from the first MSP in this
162181
// chain's MSP manager
163182
// FIXME: this needs to be removed as soon as we extract the policy from LCCC
164-
func getHardcodedPolicy(chainID string) ([]byte, error) {
183+
func getSemiHardcodedPolicy(chainID string, mspMgr msp.MSPManager) ([]byte, error) {
165184
// 1) determine the MSP identifier for the first MSP in this chain
166185
var msp msp.MSP
167-
mspMgr := mspmgmt.GetManagerForChain(chainID)
168186
msps, err := mspMgr.GetMSPs()
169187
if err != nil {
170188
return nil, fmt.Errorf("Could not retrieve the MSPs for the chain manager, err %s", err)
@@ -215,7 +233,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
215233
// by the deployer and can be retrieved via LCCC: we create
216234
// a policy that requests 1 valid signature from this chain's
217235
// MSP
218-
policy, err := getHardcodedPolicy(chainID)
236+
policy, err := getSemiHardcodedPolicy(chainID, v.support.MSPManager())
219237
if err != nil {
220238
return err
221239
}
@@ -226,7 +244,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
226244
// args[2] - serialized policy
227245
args := [][]byte{[]byte(""), envBytes, policy}
228246

229-
ctxt, err := v.ccprovider.GetContext(v.ledger)
247+
ctxt, err := v.ccprovider.GetContext(v.support.Ledger())
230248
if err != nil {
231249
logger.Errorf("Cannot obtain context for txid=%s, err %s", txid, err)
232250
return err

core/mocks/txvalidator/support.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright IBM Corp. 2017 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 support
18+
19+
import (
20+
"github.com/hyperledger/fabric/core/ledger"
21+
"github.com/hyperledger/fabric/msp"
22+
"github.com/hyperledger/fabric/protos/common"
23+
)
24+
25+
type Support struct {
26+
LedgerVal ledger.PeerLedger
27+
MSPManagerVal msp.MSPManager
28+
ApplyVal error
29+
}
30+
31+
// Ledger returns LedgerVal
32+
func (ms *Support) Ledger() ledger.PeerLedger {
33+
return ms.LedgerVal
34+
}
35+
36+
// MSPManager returns MSPManagerVal
37+
func (ms *Support) MSPManager() msp.MSPManager {
38+
return ms.MSPManagerVal
39+
}
40+
41+
// Apply returns ApplyVal
42+
func (ms *Support) Apply(configtx *common.ConfigurationEnvelope) error {
43+
return ms.ApplyVal
44+
}

core/mocks/validator/validator.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import "github.com/hyperledger/fabric/protos/common"
2222
type MockValidator struct {
2323
}
2424

25-
// Validate does nothing
26-
func (m *MockValidator) Validate(block *common.Block) {
25+
// Validate does nothing, returning no error
26+
func (m *MockValidator) Validate(block *common.Block) error {
27+
return nil
2728
}
2829

2930
// MockVsccValidator is a mock implementation of the VSCC validation interface

core/peer/peer.go

+48-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/op/go-logging"
2828
"github.com/spf13/viper"
2929

30+
"github.com/hyperledger/fabric/common/configtx"
3031
"github.com/hyperledger/fabric/core/comm"
3132
"github.com/hyperledger/fabric/core/committer"
3233
"github.com/hyperledger/fabric/core/committer/txvalidator"
@@ -41,12 +42,25 @@ import (
4142

4243
var peerLogger = logging.MustGetLogger("peer")
4344

45+
type chainSupport struct {
46+
configtx.Manager
47+
ledger ledger.PeerLedger
48+
mspmgr msp.MSPManager
49+
}
50+
51+
func (cs *chainSupport) Ledger() ledger.PeerLedger {
52+
return cs.ledger
53+
}
54+
55+
func (cs *chainSupport) MSPManager() msp.MSPManager {
56+
return cs.mspmgr
57+
}
58+
4459
// chain is a local struct to manage objects in a chain
4560
type chain struct {
61+
cs *chainSupport
4662
cb *common.Block
47-
ledger ledger.PeerLedger
4863
committer committer.Committer
49-
mspmgr msp.MSPManager
5064
}
5165

5266
// chains is a local map of chainID->chainObject
@@ -146,13 +160,33 @@ func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, erro
146160

147161
// createChain creates a new chain object and insert it into the chains
148162
func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {
149-
c := committer.NewLedgerCommitter(ledger, txvalidator.NewTxValidator(ledger))
150163

164+
configEnvelope, _, err := utils.BreakOutBlockToConfigurationEnvelope(cb)
165+
if err != nil {
166+
return err
167+
}
168+
169+
configtxInitializer := configtx.NewInitializer()
170+
// TODO Hook peer shared config manager in here once it exists
171+
configtxManager, err := configtx.NewManagerImpl(configEnvelope, configtxInitializer)
172+
if err != nil {
173+
return err
174+
}
175+
176+
// TODO Move to the configtx.Handler interface (which MSP already implements)
151177
mgr, err := mspmgmt.GetMSPManagerFromBlock(cid, cb)
152178
if err != nil {
153179
return err
154180
}
155181

182+
cs := &chainSupport{
183+
Manager: configtxManager,
184+
ledger: ledger,
185+
mspmgr: mgr,
186+
}
187+
188+
c := committer.NewLedgerCommitter(ledger, txvalidator.NewTxValidator(cs))
189+
156190
// TODO This should be called from a configtx.Manager but it's not
157191
// implemented yet. When it will be, this needs to move there,
158192
// and the inner fields (AnchorPeers) only should be passed to this.
@@ -162,7 +196,15 @@ func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {
162196

163197
chains.Lock()
164198
defer chains.Unlock()
165-
chains.list[cid] = &chain{cb: cb, ledger: ledger, mspmgr: mgr, committer: c}
199+
chains.list[cid] = &chain{
200+
cs: &chainSupport{
201+
Manager: configtxManager,
202+
ledger: ledger,
203+
mspmgr: mgr,
204+
},
205+
cb: cb,
206+
committer: c,
207+
}
166208
return nil
167209
}
168210

@@ -191,7 +233,7 @@ func MockCreateChain(cid string) error {
191233

192234
chains.Lock()
193235
defer chains.Unlock()
194-
chains.list[cid] = &chain{ledger: ledger}
236+
chains.list[cid] = &chain{cs: &chainSupport{ledger: ledger}}
195237

196238
return nil
197239
}
@@ -202,7 +244,7 @@ func GetLedger(cid string) ledger.PeerLedger {
202244
chains.RLock()
203245
defer chains.RUnlock()
204246
if c, ok := chains.list[cid]; ok {
205-
return c.ledger
247+
return c.cs.ledger
206248
}
207249
return nil
208250
}

0 commit comments

Comments
 (0)