Skip to content

Commit f47dd7f

Browse files
committed
[FAB-6229] validator accepts RESOURCE_UPDATE txes
This change set introudces support (and tests) to handle incoming txes with the new type HeaderType_PEER_RESOURCE_UPDATE. Change-Id: I12e615a911d9210cf5dbb696d4f9ff03d166d60c Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net>
1 parent ff0b4fa commit f47dd7f

File tree

7 files changed

+137
-23
lines changed

7 files changed

+137
-23
lines changed

core/committer/txvalidator/validator.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,26 @@ package txvalidator
99
import (
1010
"fmt"
1111

12-
"golang.org/x/net/context"
13-
1412
"github.com/golang/protobuf/proto"
13+
"github.com/hyperledger/fabric/common/cauthdsl"
14+
"github.com/hyperledger/fabric/common/channelconfig"
1515
"github.com/hyperledger/fabric/common/configtx"
1616
"github.com/hyperledger/fabric/common/flogging"
17+
"github.com/hyperledger/fabric/common/resourcesconfig"
1718
coreUtil "github.com/hyperledger/fabric/common/util"
1819
"github.com/hyperledger/fabric/core/chaincode/shim"
1920
"github.com/hyperledger/fabric/core/common/ccprovider"
2021
"github.com/hyperledger/fabric/core/common/sysccprovider"
2122
"github.com/hyperledger/fabric/core/common/validation"
2223
"github.com/hyperledger/fabric/core/ledger"
24+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
2325
ledgerUtil "github.com/hyperledger/fabric/core/ledger/util"
2426
"github.com/hyperledger/fabric/msp"
25-
2627
"github.com/hyperledger/fabric/protos/common"
2728
"github.com/hyperledger/fabric/protos/peer"
2829
"github.com/hyperledger/fabric/protos/utils"
2930
"github.com/op/go-logging"
30-
31-
"github.com/hyperledger/fabric/common/cauthdsl"
32-
"github.com/hyperledger/fabric/common/channelconfig"
33-
"github.com/hyperledger/fabric/common/resourcesconfig"
34-
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
31+
"golang.org/x/net/context"
3532
)
3633

3734
// Support provides all of the needed to evaluate the VSCC
@@ -337,7 +334,7 @@ func validateTx(req *blockValidationRequest, results chan<- *blockValidationResu
337334
var txsChaincodeName *sysccprovider.ChaincodeInstance
338335
var txsUpgradedChaincode *sysccprovider.ChaincodeInstance
339336

340-
if payload, txResult = validation.ValidateTransaction(env); txResult != peer.TxValidationCode_VALID {
337+
if payload, txResult = validation.ValidateTransaction(env, v.support.Capabilities()); txResult != peer.TxValidationCode_VALID {
341338
logger.Errorf("Invalid transaction with index %d", tIdx)
342339
results <- &blockValidationResult{
343340
tIdx: tIdx,
@@ -443,6 +440,16 @@ func validateTx(req *blockValidationRequest, results chan<- *blockValidationResu
443440
return
444441
}
445442
logger.Debugf("config transaction received for chain %s", channel)
443+
} else if common.HeaderType(chdr.Type) == common.HeaderType_PEER_RESOURCE_UPDATE {
444+
// FIXME: in the context of FAB-7341, we should introduce validation
445+
// for this kind of transaction here. For now we just ignore this
446+
// type of transaction and delegate its validation to other components
447+
448+
results <- &blockValidationResult{
449+
tIdx: tIdx,
450+
err: nil,
451+
}
452+
return
446453
} else {
447454
logger.Warningf("Unknown transaction type [%s] in block number [%d] transaction index [%d]",
448455
common.HeaderType(chdr.Type), block.Header.Number, tIdx)

core/committer/txvalidator/validator_test.go

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,22 @@ func createRWset(t *testing.T, ccnames ...string) []byte {
8282
return rwsetBytes
8383
}
8484

85-
func getProposal(ccID string) (*peer.Proposal, error) {
85+
func getProposalWithType(ccID string, pType common.HeaderType) (*peer.Proposal, error) {
8686
cis := &peer.ChaincodeInvocationSpec{
8787
ChaincodeSpec: &peer.ChaincodeSpec{
8888
ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion},
8989
Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}},
9090
Type: peer.ChaincodeSpec_GOLANG}}
9191

92-
proposal, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), cis, signerSerialized)
92+
proposal, _, err := utils.CreateProposalFromCIS(pType, util.GetTestChainID(), cis, signerSerialized)
9393
return proposal, err
9494
}
9595

9696
const ccVersion = "1.0"
9797

98-
func getEnv(ccID string, res []byte, t *testing.T) *common.Envelope {
98+
func getEnvWithType(ccID string, res []byte, pType common.HeaderType, t *testing.T) *common.Envelope {
9999
// get a toy proposal
100-
prop, err := getProposal(ccID)
100+
prop, err := getProposalWithType(ccID, pType)
101101
assert.NoError(t, err)
102102

103103
response := &peer.Response{Status: 200}
@@ -113,6 +113,10 @@ func getEnv(ccID string, res []byte, t *testing.T) *common.Envelope {
113113
return tx
114114
}
115115

116+
func getEnv(ccID string, res []byte, t *testing.T) *common.Envelope {
117+
return getEnvWithType(ccID, res, common.HeaderType_ENDORSER_TRANSACTION, t)
118+
}
119+
116120
func putCCInfoWithVSCCAndVer(theLedger ledger.PeerLedger, ccname, vscc, ver string, policy []byte, t *testing.T) {
117121
cd := &ccp.ChaincodeData{
118122
Name: ccname,
@@ -615,6 +619,52 @@ func TestValidationInvalidEndorsing(t *testing.T) {
615619
assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
616620
}
617621

622+
func TestValidationResourceUpdate(t *testing.T) {
623+
theLedger := new(mockLedger)
624+
sup := &mocktxvalidator.Support{LedgerVal: theLedger, ACVal: &mockconfig.MockApplicationCapabilities{}}
625+
vcs := struct {
626+
*mocktxvalidator.Support
627+
*semaphore.Weighted
628+
}{sup, semaphore.NewWeighted(10)}
629+
validator := NewTxValidator(vcs)
630+
631+
ccID := "mycc"
632+
tx := getEnvWithType(ccID, createRWset(t, ccID), common.HeaderType_PEER_RESOURCE_UPDATE, t)
633+
634+
theLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, errors.New("Cannot find the transaction"))
635+
636+
cd := &ccp.ChaincodeData{
637+
Name: ccID,
638+
Version: ccVersion,
639+
Vscc: "vscc",
640+
Policy: signedByAnyMember([]string{"DEFAULT"}),
641+
}
642+
643+
cdbytes := utils.MarshalOrPanic(cd)
644+
645+
queryExecutor := new(mockQueryExecutor)
646+
queryExecutor.On("GetState", "lscc", ccID).Return(cdbytes, nil)
647+
theLedger.On("NewQueryExecutor", mock.Anything).Return(queryExecutor, nil)
648+
649+
b1 := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}}
650+
b2 := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}}
651+
652+
// Keep default callback
653+
c := executeChaincodeProvider.getCallback()
654+
executeChaincodeProvider.setCallback(func() (*peer.Response, *peer.ChaincodeEvent, error) {
655+
return &peer.Response{Status: shim.ERROR}, nil, nil
656+
})
657+
err := validator.Validate(b1)
658+
assert.NoError(t, err)
659+
sup.ACVal = &mockconfig.MockApplicationCapabilities{LifecycleViaConfigRv: true}
660+
err = validator.Validate(b2)
661+
assert.NoError(t, err)
662+
// Restore default callback
663+
executeChaincodeProvider.setCallback(c)
664+
assertInvalid(b1, t, peer.TxValidationCode_UNSUPPORTED_TX_PAYLOAD)
665+
assertValid(b2, t)
666+
}
667+
618668
type ccResultCallback func() (*peer.Response, *peer.ChaincodeEvent, error)
619669

620670
type ccExecuteChaincode struct {

core/common/validation/config_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package validation
1919
import (
2020
"testing"
2121

22+
"github.com/hyperledger/fabric/common/mocks/config"
2223
"github.com/hyperledger/fabric/common/tools/configtxgen/encoder"
2324
genesisconfig "github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
2425
"github.com/hyperledger/fabric/common/util"
@@ -52,7 +53,7 @@ func TestValidateConfigTx(t *testing.T) {
5253
}),
5354
}
5455
updateResult.Signature, _ = signer.Sign(updateResult.Payload)
55-
_, txResult := ValidateTransaction(updateResult)
56+
_, txResult := ValidateTransaction(updateResult, &config.MockApplicationCapabilities{})
5657
if txResult != peer.TxValidationCode_VALID {
5758
t.Fatalf("ValidateTransaction failed, err %s", err)
5859
return

core/common/validation/fullflow_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"testing"
2424
"time"
2525

26+
"github.com/hyperledger/fabric/common/mocks/config"
2627
mmsp "github.com/hyperledger/fabric/common/mocks/msp"
2728
"github.com/hyperledger/fabric/common/util"
2829
"github.com/hyperledger/fabric/msp"
@@ -157,7 +158,7 @@ func TestGoodPath(t *testing.T) {
157158
}
158159

159160
// validate the transaction
160-
payl, txResult := ValidateTransaction(tx)
161+
payl, txResult := ValidateTransaction(tx, &config.MockApplicationCapabilities{})
161162
if txResult != peer.TxValidationCode_VALID {
162163
t.Fatalf("ValidateTransaction failed, err %s", err)
163164
return
@@ -217,7 +218,7 @@ func TestTXWithTwoActionsRejected(t *testing.T) {
217218
}
218219

219220
// validate the transaction
220-
_, txResult := ValidateTransaction(tx)
221+
_, txResult := ValidateTransaction(tx, &config.MockApplicationCapabilities{})
221222
if txResult == peer.TxValidationCode_VALID {
222223
t.Fatalf("ValidateTransaction should have failed")
223224
return
@@ -333,7 +334,7 @@ func TestBadTx(t *testing.T) {
333334
copy(paylCopy, paylOrig)
334335
paylCopy[i] = byte(int(paylCopy[i]+1) % 255)
335336
// validate the transaction it should fail
336-
_, txResult := ValidateTransaction(&common.Envelope{Signature: tx.Signature, Payload: paylCopy})
337+
_, txResult := ValidateTransaction(&common.Envelope{Signature: tx.Signature, Payload: paylCopy}, &config.MockApplicationCapabilities{})
337338
if txResult == peer.TxValidationCode_VALID {
338339
t.Fatal("ValidateTransaction should have failed")
339340
return
@@ -351,7 +352,7 @@ func TestBadTx(t *testing.T) {
351352
corrupt(tx.Signature)
352353

353354
// validate the transaction it should fail
354-
_, txResult := ValidateTransaction(tx)
355+
_, txResult := ValidateTransaction(tx, &config.MockApplicationCapabilities{})
355356
if txResult == peer.TxValidationCode_VALID {
356357
t.Fatal("ValidateTransaction should have failed")
357358
return
@@ -394,7 +395,7 @@ func Test2EndorsersAgree(t *testing.T) {
394395
}
395396

396397
// validate the transaction
397-
_, txResult := ValidateTransaction(tx)
398+
_, txResult := ValidateTransaction(tx, &config.MockApplicationCapabilities{})
398399
if txResult != peer.TxValidationCode_VALID {
399400
t.Fatalf("ValidateTransaction failed, err %s", err)
400401
return
@@ -438,7 +439,7 @@ func Test2EndorsersDisagree(t *testing.T) {
438439
}
439440

440441
func TestInvocationsBadArgs(t *testing.T) {
441-
_, code := ValidateTransaction(nil)
442+
_, code := ValidateTransaction(nil, &config.MockApplicationCapabilities{})
442443
assert.Equal(t, code, peer.TxValidationCode_NIL_ENVELOPE)
443444
err := validateEndorserTransaction(nil, nil)
444445
assert.Error(t, err)

core/common/validation/msgvalidation.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323

24+
"github.com/hyperledger/fabric/common/channelconfig"
2425
"github.com/hyperledger/fabric/common/flogging"
2526
mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
2627
"github.com/hyperledger/fabric/protos/common"
@@ -115,6 +116,9 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm
115116

116117
// continue the validation in a way that depends on the type specified in the header
117118
switch common.HeaderType(chdr.Type) {
119+
case common.HeaderType_PEER_RESOURCE_UPDATE:
120+
// no additional validation required for transactions of this type
121+
return prop, hdr, nil, err
118122
case common.HeaderType_CONFIG:
119123
//which the types are different the validation is the same
120124
//viz, validate a proposal to a chaincode. If we need other
@@ -208,7 +212,8 @@ func validateChannelHeader(cHdr *common.ChannelHeader) error {
208212
// validate the header type
209213
if common.HeaderType(cHdr.Type) != common.HeaderType_ENDORSER_TRANSACTION &&
210214
common.HeaderType(cHdr.Type) != common.HeaderType_CONFIG_UPDATE &&
211-
common.HeaderType(cHdr.Type) != common.HeaderType_CONFIG {
215+
common.HeaderType(cHdr.Type) != common.HeaderType_CONFIG &&
216+
common.HeaderType(cHdr.Type) != common.HeaderType_PEER_RESOURCE_UPDATE {
212217
return fmt.Errorf("invalid header type %s", common.HeaderType(cHdr.Type))
213218
}
214219

@@ -358,7 +363,7 @@ func validateEndorserTransaction(data []byte, hdr *common.Header) error {
358363
}
359364

360365
// ValidateTransaction checks that the transaction envelope is properly formed
361-
func ValidateTransaction(e *common.Envelope) (*common.Payload, pb.TxValidationCode) {
366+
func ValidateTransaction(e *common.Envelope, c channelconfig.ApplicationCapabilities) (*common.Payload, pb.TxValidationCode) {
362367
putilsLogger.Debugf("ValidateTransactionEnvelope starts for envelope %p", e)
363368

364369
// check for nil argument
@@ -417,6 +422,13 @@ func ValidateTransaction(e *common.Envelope) (*common.Payload, pb.TxValidationCo
417422
} else {
418423
return payload, pb.TxValidationCode_VALID
419424
}
425+
case common.HeaderType_PEER_RESOURCE_UPDATE:
426+
if !c.LifecycleViaConfig() {
427+
return nil, pb.TxValidationCode_UNSUPPORTED_TX_PAYLOAD
428+
}
429+
430+
// perform similar validation to common.HeaderType_CONFIG
431+
fallthrough
420432
case common.HeaderType_CONFIG:
421433
// Config transactions have signatures inside which will be validated, especially at genesis there may be no creator or
422434
// signature on the outermost envelope
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package validation
8+
9+
import (
10+
"testing"
11+
12+
"github.com/docker/docker/pkg/testutil/assert"
13+
"github.com/hyperledger/fabric/common/mocks/config"
14+
"github.com/hyperledger/fabric/common/util"
15+
cb "github.com/hyperledger/fabric/protos/common"
16+
"github.com/hyperledger/fabric/protos/peer"
17+
"github.com/hyperledger/fabric/protos/utils"
18+
)
19+
20+
func TestValidateResourceUpdateTx(t *testing.T) {
21+
chainID := util.GetTestChainID()
22+
23+
updateResult := &cb.Envelope{
24+
Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{
25+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
26+
Type: int32(cb.HeaderType_PEER_RESOURCE_UPDATE),
27+
ChannelId: chainID,
28+
}),
29+
SignatureHeader: utils.MarshalOrPanic(&cb.SignatureHeader{
30+
Creator: signerSerialized,
31+
Nonce: utils.CreateNonceOrPanic(),
32+
}),
33+
},
34+
Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{LastUpdate: &cb.Envelope{}}),
35+
}),
36+
}
37+
updateResult.Signature, _ = signer.Sign(updateResult.Payload)
38+
_, txResult := ValidateTransaction(updateResult, &config.MockApplicationCapabilities{})
39+
assert.Equal(t, txResult, peer.TxValidationCode_UNSUPPORTED_TX_PAYLOAD)
40+
_, txResult = ValidateTransaction(updateResult, &config.MockApplicationCapabilities{LifecycleViaConfigRv: true})
41+
assert.Equal(t, txResult, peer.TxValidationCode_VALID)
42+
}

core/scc/escc/endorser_onevalidsignature_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"testing"
2424

2525
"github.com/golang/protobuf/proto"
26+
"github.com/hyperledger/fabric/common/mocks/config"
2627
"github.com/hyperledger/fabric/common/util"
2728
"github.com/hyperledger/fabric/core/chaincode/shim"
2829
"github.com/hyperledger/fabric/core/common/validation"
@@ -370,7 +371,7 @@ func validateProposalResponse(prBytes []byte, proposal *pb.Proposal, ccid *pb.Ch
370371
}
371372

372373
// validate the transaction
373-
_, txResult := validation.ValidateTransaction(tx)
374+
_, txResult := validation.ValidateTransaction(tx, &config.MockApplicationCapabilities{})
374375
if txResult != pb.TxValidationCode_VALID {
375376
return err
376377
}

0 commit comments

Comments
 (0)