Skip to content

Commit f30fc74

Browse files
jiangyaoguoSrinivasan Muralidharan
authored and
Srinivasan Muralidharan
committed
[FAB-3330] validate chaincode version
1. Add VsccOutputData struct to keep output of vscc. Vscc will return proposalResponsePayload(has verison info) bytes contained in ChaincodeAction. 2. When committer validates transaction, check that the chaincode version in ProposalResponse matches the verision in lscc. 3. Add new ValidateCode to distinguash two kinds of invalid reason because of chaincode upgrade. 4. vsccValidatorImpl will return latest chaincodeInstance from lscc and vsccOutputData from vscc. So we can mock system chaincode in UT. 5. Move ChaincodeInstance to sysccprovider to avoid cycle import. Change-Id: I45387f119054d64b57d28173cabda0194a9e3464 Signed-off-by: jiangyaoguo <[email protected]>
1 parent ca3a1a2 commit f30fc74

File tree

11 files changed

+356
-135
lines changed

11 files changed

+356
-135
lines changed

common/ledger/testutil/test_helper.go

+9
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,15 @@ func ConstructTestBlocks(t *testing.T, numBlocks int) []*common.Block {
125125
return append(blocks, bg.NextTestBlocks(numBlocks-1)...)
126126
}
127127

128+
// ConstructBytesProposalResponsePayload constructs a ProposalResponse byte with given chaincode version and simulationResults for testing
129+
func ConstructBytesProposalResponsePayload(version string, simulationResults []byte) ([]byte, error) {
130+
ccid := &pb.ChaincodeID{
131+
Name: "foo",
132+
Version: version,
133+
}
134+
return ptestutils.ConstractBytesProposalResponsePayload(util.GetTestChainID(), ccid, nil, simulationResults)
135+
}
136+
128137
func newBlock(env []*common.Envelope, blockNum uint64, previousHash []byte) *common.Block {
129138
block := common.NewBlock(blockNum, previousHash)
130139
for i := 0; i < len(env); i++ {

core/committer/txvalidator/txvalidator_test.go

+66-27
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/hyperledger/fabric/common/configtx/test"
2424
"github.com/hyperledger/fabric/common/ledger/testutil"
2525
util2 "github.com/hyperledger/fabric/common/util"
26+
"github.com/hyperledger/fabric/core/common/sysccprovider"
2627
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
2728
"github.com/hyperledger/fabric/core/ledger/util"
2829
ledgerUtil "github.com/hyperledger/fabric/core/ledger/util"
@@ -38,7 +39,7 @@ import (
3839
"github.com/stretchr/testify/assert"
3940
)
4041

41-
func TestFirstBlockValidation(t *testing.T) {
42+
func TestBlockValidation(t *testing.T) {
4243
viper.Set("peer.fileSystemPath", "/tmp/fabric/txvalidatortest")
4344
ledgermgmt.InitializeTestEnv()
4445
defer ledgermgmt.CleanupTestEnv()
@@ -48,11 +49,11 @@ func TestFirstBlockValidation(t *testing.T) {
4849
ledger, _ := ledgermgmt.CreateLedger(gb)
4950
defer ledger.Close()
5051

51-
tValidator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, &validator.MockVsccValidator{}}
52-
53-
bcInfo, _ := ledger.GetBlockchainInfo()
54-
testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{
55-
Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil})
52+
chaincodeIns := &sysccprovider.ChaincodeInstance{
53+
ChaincodeName: "foo",
54+
ChaincodeVersion: "v1",
55+
ChainID: util2.GetTestChainID(),
56+
}
5657

5758
simulator, _ := ledger.NewTxSimulator()
5859
simulator.SetState("ns1", "key1", []byte("value1"))
@@ -61,12 +62,50 @@ func TestFirstBlockValidation(t *testing.T) {
6162
simulator.Done()
6263

6364
simRes, _ := simulator.GetTxSimulationResults()
65+
66+
prespPaylBytes, err := testutil.ConstructBytesProposalResponsePayload("v1", simRes)
67+
if err != nil {
68+
t.Fatalf("Could not construct ProposalResponsePayload bytes, err: %s", err)
69+
}
70+
71+
mockVsccValidator := &validator.MockVsccValidator{
72+
CIns: chaincodeIns,
73+
RespPayl: prespPaylBytes,
74+
}
75+
tValidator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, mockVsccValidator}
76+
77+
bcInfo, _ := ledger.GetBlockchainInfo()
78+
testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{
79+
Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil})
80+
6481
block := testutil.ConstructBlock(t, 1, gbHash, [][]byte{simRes}, true)
6582

6683
tValidator.Validate(block)
6784

6885
txsfltr := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
6986
assert.True(t, txsfltr.IsSetTo(0, peer.TxValidationCode_VALID))
87+
88+
// upgrade chaincode version
89+
upgradeChaincodeIns := &sysccprovider.ChaincodeInstance{
90+
ChaincodeName: "foo",
91+
ChaincodeVersion: "v2", // new version
92+
ChainID: util2.GetTestChainID(),
93+
}
94+
95+
newMockVsccValidator := &validator.MockVsccValidator{
96+
CIns: upgradeChaincodeIns,
97+
RespPayl: prespPaylBytes,
98+
}
99+
newTxValidator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, newMockVsccValidator}
100+
101+
// generate new block
102+
newBlock := testutil.ConstructBlock(t, 2, block.Header.Hash(), [][]byte{simRes}, true) // contains one tx with chaincode version v1
103+
104+
newTxValidator.Validate(newBlock)
105+
106+
// tx should be invalided because of chaincode upgrade
107+
txsfltr = util.TxValidationFlags(newBlock.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
108+
assert.True(t, txsfltr.IsSetTo(0, peer.TxValidationCode_EXPIRED_CHAINCODE))
70109
}
71110

72111
func TestNewTxValidator_DuplicateTransactions(t *testing.T) {
@@ -186,12 +225,12 @@ func TestGetTxCCInstance(t *testing.T) {
186225
payload, err := utils.GetPayload(env)
187226
assert.NoError(t, err)
188227

189-
expectInvokeCCIns := &ChaincodeInstance{
228+
expectInvokeCCIns := &sysccprovider.ChaincodeInstance{
190229
ChainID: chainID,
191230
ChaincodeName: "lscc",
192231
ChaincodeVersion: "",
193232
}
194-
expectUpgradeCCIns := &ChaincodeInstance{
233+
expectUpgradeCCIns := &sysccprovider.ChaincodeInstance{
195234
ChainID: chainID,
196235
ChaincodeName: upgradeCCName,
197236
ChaincodeVersion: upgradeCCVersion,
@@ -207,20 +246,20 @@ func TestGetTxCCInstance(t *testing.T) {
207246
}
208247

209248
func TestInvalidTXsForUpgradeCC(t *testing.T) {
210-
txsChaincodeNames := map[int]*ChaincodeInstance{
211-
0: &ChaincodeInstance{"chain0", "cc0", "v0"}, // invoke cc0/chain0:v0, should not be affected by upgrade tx in other chain
212-
1: &ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
213-
2: &ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v1, should be invalided by latter cc0/chain1 upgtade tx
214-
3: &ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
215-
4: &ChaincodeInstance{"chain1", "cc0", "v1"}, // invoke cc0/chain1:v1, should be invalided by cc1/chain1 upgrade tx
216-
5: &ChaincodeInstance{"chain1", "cc1", "v0"}, // invoke cc1/chain1:v0, should not be affected by other chaincode upgrade tx
217-
6: &ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v2, should be invalided by latter cc0/chain1 upgtade tx
218-
7: &ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v3
219-
}
220-
upgradedChaincodes := map[int]*ChaincodeInstance{
221-
2: &ChaincodeInstance{"chain1", "cc0", "v1"},
222-
6: &ChaincodeInstance{"chain1", "cc0", "v2"},
223-
7: &ChaincodeInstance{"chain1", "cc0", "v3"},
249+
txsChaincodeNames := map[int]*sysccprovider.ChaincodeInstance{
250+
0: &sysccprovider.ChaincodeInstance{"chain0", "cc0", "v0"}, // invoke cc0/chain0:v0, should not be affected by upgrade tx in other chain
251+
1: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
252+
2: &sysccprovider.ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v1, should be invalided by latter cc0/chain1 upgtade tx
253+
3: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
254+
4: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v1"}, // invoke cc0/chain1:v1, should be invalided by cc1/chain1 upgrade tx
255+
5: &sysccprovider.ChaincodeInstance{"chain1", "cc1", "v0"}, // invoke cc1/chain1:v0, should not be affected by other chaincode upgrade tx
256+
6: &sysccprovider.ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v2, should be invalided by latter cc0/chain1 upgtade tx
257+
7: &sysccprovider.ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v3
258+
}
259+
upgradedChaincodes := map[int]*sysccprovider.ChaincodeInstance{
260+
2: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v1"},
261+
6: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v2"},
262+
7: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v3"},
224263
}
225264

226265
txsfltr := ledgerUtil.NewTxValidationFlags(8)
@@ -235,12 +274,12 @@ func TestInvalidTXsForUpgradeCC(t *testing.T) {
235274

236275
expectTxsFltr := ledgerUtil.NewTxValidationFlags(8)
237276
expectTxsFltr.SetFlag(0, peer.TxValidationCode_VALID)
238-
expectTxsFltr.SetFlag(1, peer.TxValidationCode_EXPIRED_CHAINCODE)
239-
expectTxsFltr.SetFlag(2, peer.TxValidationCode_EXPIRED_CHAINCODE)
240-
expectTxsFltr.SetFlag(3, peer.TxValidationCode_EXPIRED_CHAINCODE)
241-
expectTxsFltr.SetFlag(4, peer.TxValidationCode_EXPIRED_CHAINCODE)
277+
expectTxsFltr.SetFlag(1, peer.TxValidationCode_CHAINCODE_VERSION_CONFLICT)
278+
expectTxsFltr.SetFlag(2, peer.TxValidationCode_CHAINCODE_VERSION_CONFLICT)
279+
expectTxsFltr.SetFlag(3, peer.TxValidationCode_CHAINCODE_VERSION_CONFLICT)
280+
expectTxsFltr.SetFlag(4, peer.TxValidationCode_CHAINCODE_VERSION_CONFLICT)
242281
expectTxsFltr.SetFlag(5, peer.TxValidationCode_VALID)
243-
expectTxsFltr.SetFlag(6, peer.TxValidationCode_EXPIRED_CHAINCODE)
282+
expectTxsFltr.SetFlag(6, peer.TxValidationCode_CHAINCODE_VERSION_CONFLICT)
244283
expectTxsFltr.SetFlag(7, peer.TxValidationCode_VALID)
245284

246285
tValidator := &txValidator{}

0 commit comments

Comments
 (0)