Skip to content

Commit

Permalink
[FAB-3269] properly honor endorsement policies
Browse files Browse the repository at this point in the history
This change set introduces proper validation of transactions: the write set
of every transaction is validated according to the endorsement policy that
was defined for the corresponding chaincode.

Change-Id: Ie1cd22e1ad348d4fc1a2f8895f759955a461f416
Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net>
  • Loading branch information
ale-linux committed Apr 30, 2017
1 parent 8f7bfc3 commit 22e2fc9
Show file tree
Hide file tree
Showing 18 changed files with 800 additions and 351 deletions.
51 changes: 51 additions & 0 deletions common/mocks/scc/sccprovider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scc

import (
lm "github.com/hyperledger/fabric/common/mocks/ledger"
"github.com/hyperledger/fabric/core/common/sysccprovider"
"github.com/hyperledger/fabric/core/ledger"
)

type MocksccProviderFactory struct {
Qe *lm.MockQueryExecutor
}

func (c *MocksccProviderFactory) NewSystemChaincodeProvider() sysccprovider.SystemChaincodeProvider {
return &mocksccProviderImpl{Qe: c.Qe}
}

type mocksccProviderImpl struct {
Qe *lm.MockQueryExecutor
}

func (c *mocksccProviderImpl) IsSysCC(name string) bool {
return (name == "lscc") || (name == "escc") || (name == "vscc") || (name == "notext")
}

func (c *mocksccProviderImpl) IsSysCCAndNotInvokableCC2CC(name string) bool {
return (name == "escc") || (name == "vscc")
}

func (c *mocksccProviderImpl) IsSysCCAndNotInvokableExternal(name string) bool {
return (name == "escc") || (name == "vscc") || (name == "notext")
}

func (c *mocksccProviderImpl) GetQueryExecutorForLedger(cid string) (ledger.QueryExecutor, error) {
return c.Qe, nil
}
77 changes: 33 additions & 44 deletions core/committer/txvalidator/txvalidator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/hyperledger/fabric/common/configtx/test"
"github.com/hyperledger/fabric/common/ledger/testutil"
util2 "github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/common/sysccprovider"
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
"github.com/hyperledger/fabric/core/ledger/util"
ledgerUtil "github.com/hyperledger/fabric/core/ledger/util"
Expand All @@ -49,12 +48,6 @@ func TestBlockValidation(t *testing.T) {
ledger, _ := ledgermgmt.CreateLedger(gb)
defer ledger.Close()

chaincodeIns := &sysccprovider.ChaincodeInstance{
ChaincodeName: "foo",
ChaincodeVersion: "v1",
ChainID: util2.GetTestChainID(),
}

simulator, _ := ledger.NewTxSimulator()
simulator.SetState("ns1", "key1", []byte("value1"))
simulator.SetState("ns1", "key2", []byte("value2"))
Expand All @@ -63,15 +56,12 @@ func TestBlockValidation(t *testing.T) {

simRes, _ := simulator.GetTxSimulationResults()

prespPaylBytes, err := testutil.ConstructBytesProposalResponsePayload("v1", simRes)
_, err := testutil.ConstructBytesProposalResponsePayload("v1", simRes)
if err != nil {
t.Fatalf("Could not construct ProposalResponsePayload bytes, err: %s", err)
}

mockVsccValidator := &validator.MockVsccValidator{
CIns: chaincodeIns,
RespPayl: prespPaylBytes,
}
mockVsccValidator := &validator.MockVsccValidator{}
tValidator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, mockVsccValidator}

bcInfo, _ := ledger.GetBlockchainInfo()
Expand All @@ -85,27 +75,26 @@ func TestBlockValidation(t *testing.T) {
txsfltr := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
assert.True(t, txsfltr.IsSetTo(0, peer.TxValidationCode_VALID))

// upgrade chaincode version
upgradeChaincodeIns := &sysccprovider.ChaincodeInstance{
ChaincodeName: "foo",
ChaincodeVersion: "v2", // new version
ChainID: util2.GetTestChainID(),
}
/*
newMockVsccValidator := &validator.MockVsccValidator{
CIns: upgradeChaincodeIns,
RespPayl: prespPaylBytes,
}
newTxValidator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, newMockVsccValidator}
a better way of testing this without all of the mocking was
implemented in validator_test.go
newMockVsccValidator := &validator.MockVsccValidator{
CIns: upgradeChaincodeIns,
RespPayl: prespPaylBytes,
}
newTxValidator := &txValidator{&mocktxvalidator.Support{LedgerVal: ledger}, newMockVsccValidator}
// generate new block
newBlock := testutil.ConstructBlock(t, 2, block.Header.Hash(), [][]byte{simRes}, true) // contains one tx with chaincode version v1
// generate new block
newBlock := testutil.ConstructBlock(t, 2, block.Header.Hash(), [][]byte{simRes}, true) // contains one tx with chaincode version v1
newTxValidator.Validate(newBlock)
newTxValidator.Validate(newBlock)
// tx should be invalided because of chaincode upgrade
txsfltr = util.TxValidationFlags(newBlock.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
assert.True(t, txsfltr.IsSetTo(0, peer.TxValidationCode_EXPIRED_CHAINCODE))
// tx should be invalided because of chaincode upgrade
txsfltr = util.TxValidationFlags(newBlock.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
assert.True(t, txsfltr.IsSetTo(0, peer.TxValidationCode_EXPIRED_CHAINCODE))
*/
}

func TestNewTxValidator_DuplicateTransactions(t *testing.T) {
Expand Down Expand Up @@ -225,12 +214,12 @@ func TestGetTxCCInstance(t *testing.T) {
payload, err := utils.GetPayload(env)
assert.NoError(t, err)

expectInvokeCCIns := &sysccprovider.ChaincodeInstance{
expectInvokeCCIns := &ChaincodeInstance{
ChainID: chainID,
ChaincodeName: "lscc",
ChaincodeVersion: "",
}
expectUpgradeCCIns := &sysccprovider.ChaincodeInstance{
expectUpgradeCCIns := &ChaincodeInstance{
ChainID: chainID,
ChaincodeName: upgradeCCName,
ChaincodeVersion: upgradeCCVersion,
Expand All @@ -246,20 +235,20 @@ func TestGetTxCCInstance(t *testing.T) {
}

func TestInvalidTXsForUpgradeCC(t *testing.T) {
txsChaincodeNames := map[int]*sysccprovider.ChaincodeInstance{
0: &sysccprovider.ChaincodeInstance{"chain0", "cc0", "v0"}, // invoke cc0/chain0:v0, should not be affected by upgrade tx in other chain
1: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
2: &sysccprovider.ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v1, should be invalided by latter cc0/chain1 upgtade tx
3: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
4: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v1"}, // invoke cc0/chain1:v1, should be invalided by cc1/chain1 upgrade tx
5: &sysccprovider.ChaincodeInstance{"chain1", "cc1", "v0"}, // invoke cc1/chain1:v0, should not be affected by other chaincode upgrade tx
6: &sysccprovider.ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v2, should be invalided by latter cc0/chain1 upgtade tx
7: &sysccprovider.ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v3
txsChaincodeNames := map[int]*ChaincodeInstance{
0: &ChaincodeInstance{"chain0", "cc0", "v0"}, // invoke cc0/chain0:v0, should not be affected by upgrade tx in other chain
1: &ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
2: &ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v1, should be invalided by latter cc0/chain1 upgtade tx
3: &ChaincodeInstance{"chain1", "cc0", "v0"}, // invoke cc0/chain1:v0, should be invalided by cc1/chain1 upgrade tx
4: &ChaincodeInstance{"chain1", "cc0", "v1"}, // invoke cc0/chain1:v1, should be invalided by cc1/chain1 upgrade tx
5: &ChaincodeInstance{"chain1", "cc1", "v0"}, // invoke cc1/chain1:v0, should not be affected by other chaincode upgrade tx
6: &ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v2, should be invalided by latter cc0/chain1 upgtade tx
7: &ChaincodeInstance{"chain1", "lscc", ""}, // upgrade cc0/chain1 to v3
}
upgradedChaincodes := map[int]*sysccprovider.ChaincodeInstance{
2: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v1"},
6: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v2"},
7: &sysccprovider.ChaincodeInstance{"chain1", "cc0", "v3"},
upgradedChaincodes := map[int]*ChaincodeInstance{
2: &ChaincodeInstance{"chain1", "cc0", "v1"},
6: &ChaincodeInstance{"chain1", "cc0", "v2"},
7: &ChaincodeInstance{"chain1", "cc0", "v3"},
}

txsfltr := ledgerUtil.NewTxValidationFlags(8)
Expand Down
Loading

0 comments on commit 22e2fc9

Please sign in to comment.