1 Star 1 Fork 0

Hyperledger Fabric 国密 / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
validator_keylevel.go 10.46 KB
一键复制 编辑 原始数据 按行查看 历史
Jtyoui 提交于 2021-07-22 15:59 . 国密
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package statebased
import (
"fmt"
"sync"
commonerrors "gitee.com/hyperledger-fabric-gm/fabric/common/errors"
"gitee.com/hyperledger-fabric-gm/fabric/core/handlers/validation/api/policies"
"gitee.com/hyperledger-fabric-gm/fabric/core/ledger"
"gitee.com/hyperledger-fabric-gm/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
"gitee.com/hyperledger-fabric-gm/fabric/protos/common"
"gitee.com/hyperledger-fabric-gm/fabric/protos/peer"
"gitee.com/hyperledger-fabric-gm/fabric/protos/utils"
"github.com/pkg/errors"
)
/**********************************************************************************************************/
/**********************************************************************************************************/
type policyChecker struct {
someEPChecked bool
ccEPChecked bool
vpmgr KeyLevelValidationParameterManager
policySupport validation.PolicyEvaluator
ccEP []byte
signatureSet []*common.SignedData
}
func (p *policyChecker) checkCCEPIfCondition(cc string, blockNum, txNum uint64, condition bool) commonerrors.TxValidationError {
if condition {
return nil
}
// validate against cc ep
err := p.policySupport.Evaluate(p.ccEP, p.signatureSet)
if err != nil {
return policyErr(errors.Wrapf(err, "validation of endorsement policy for chaincode %s in tx %d:%d failed", cc, blockNum, txNum))
}
p.ccEPChecked = true
p.someEPChecked = true
return nil
}
func (p *policyChecker) checkCCEPIfNotChecked(cc string, blockNum, txNum uint64) commonerrors.TxValidationError {
return p.checkCCEPIfCondition(cc, blockNum, txNum, p.ccEPChecked)
}
func (p *policyChecker) checkCCEPIfNoEPChecked(cc string, blockNum, txNum uint64) commonerrors.TxValidationError {
return p.checkCCEPIfCondition(cc, blockNum, txNum, p.someEPChecked)
}
func (p *policyChecker) checkSBAndCCEP(cc, coll, key string, blockNum, txNum uint64) commonerrors.TxValidationError {
// see if there is a key-level validation parameter for this key
vp, err := p.vpmgr.GetValidationParameterForKey(cc, coll, key, blockNum, txNum)
if err != nil {
// error handling for GetValidationParameterForKey follows this rationale:
switch err := errors.Cause(err).(type) {
// 1) if there is a conflict because validation params have been updated
// by another transaction in this block, we will get ValidationParameterUpdatedError.
// This should lead to invalidating the transaction by calling policyErr
case *ValidationParameterUpdatedError:
return policyErr(err)
// 2) if the ledger returns "determinstic" errors, that is, errors that
// every peer in the channel will also return (such as errors linked to
// an attempt to retrieve metadata from a non-defined collection) should be
// logged and ignored. The ledger will take the most appropriate action
// when performing its side of the validation.
case *ledger.CollConfigNotDefinedError, *ledger.InvalidCollNameError:
logger.Warningf(errors.WithMessage(err, "skipping key-level validation").Error())
err = nil
// 3) any other type of error should return an execution failure which will
// lead to halting the processing on this channel. Note that any non-categorized
// deterministic error would be caught by the default and would lead to
// a processing halt. This would certainly be a bug, but - in the absence of a
// single, well-defined deterministic error returned by the ledger, it is
// best to err on the side of caution and rather halt processing (because a
// deterministic error is treated like an I/O one) rather than risking a fork
// (in case an I/O error is treated as a deterministic one).
default:
return &commonerrors.VSCCExecutionFailureError{
Err: err,
}
}
}
// if no key-level validation parameter has been specified, the regular cc endorsement policy needs to hold
if len(vp) == 0 {
return p.checkCCEPIfNotChecked(cc, blockNum, txNum)
}
// validate against key-level vp
err = p.policySupport.Evaluate(vp, p.signatureSet)
if err != nil {
return policyErr(errors.Wrapf(err, "validation of key %s (coll'%s':ns'%s') in tx %d:%d failed", key, coll, cc, blockNum, txNum))
}
p.someEPChecked = true
return nil
}
/**********************************************************************************************************/
/**********************************************************************************************************/
type blockDependency struct {
mutex sync.Mutex
blockNum uint64
txDepOnce []sync.Once
}
// KeyLevelValidator implements per-key level ep validation
type KeyLevelValidator struct {
vpmgr KeyLevelValidationParameterManager
policySupport validation.PolicyEvaluator
blockDep blockDependency
}
func NewKeyLevelValidator(policySupport validation.PolicyEvaluator, vpmgr KeyLevelValidationParameterManager) *KeyLevelValidator {
return &KeyLevelValidator{
vpmgr: vpmgr,
policySupport: policySupport,
blockDep: blockDependency{},
}
}
func (klv *KeyLevelValidator) extractDependenciesForTx(blockNum, txNum uint64, envelopeBytes []byte) {
env, err := utils.GetEnvelopeFromBlock(envelopeBytes)
if err != nil {
logger.Warningf("while executing GetEnvelopeFromBlock got error '%s', skipping tx at height (%d,%d)", err, blockNum, txNum)
return
}
payl, err := utils.GetPayload(env)
if err != nil {
logger.Warningf("while executing GetPayload got error '%s', skipping tx at height (%d,%d)", err, blockNum, txNum)
return
}
tx, err := utils.GetTransaction(payl.Data)
if err != nil {
logger.Warningf("while executing GetTransaction got error '%s', skipping tx at height (%d,%d)", err, blockNum, txNum)
return
}
cap, err := utils.GetChaincodeActionPayload(tx.Actions[0].Payload)
if err != nil {
logger.Warningf("while executing GetChaincodeActionPayload got error '%s', skipping tx at height (%d,%d)", err, blockNum, txNum)
return
}
pRespPayload, err := utils.GetProposalResponsePayload(cap.Action.ProposalResponsePayload)
if err != nil {
logger.Warningf("while executing GetProposalResponsePayload got error '%s', skipping tx at height (%d,%d)", err, blockNum, txNum)
return
}
respPayload, err := utils.GetChaincodeAction(pRespPayload.Extension)
if err != nil {
logger.Warningf("while executing GetChaincodeAction got error '%s', skipping tx at height (%d,%d)", err, blockNum, txNum)
return
}
klv.vpmgr.ExtractValidationParameterDependency(blockNum, txNum, respPayload.Results)
}
// PreValidate implements the function of the StateBasedValidator interface
func (klv *KeyLevelValidator) PreValidate(txNum uint64, block *common.Block) {
klv.blockDep.mutex.Lock()
if klv.blockDep.blockNum != block.Header.Number {
klv.blockDep.blockNum = block.Header.Number
klv.blockDep.txDepOnce = make([]sync.Once, len(block.Data.Data))
}
klv.blockDep.mutex.Unlock()
for i := int64(txNum); i >= 0; i-- {
txPosition := uint64(i)
klv.blockDep.txDepOnce[i].Do(
func() {
klv.extractDependenciesForTx(block.Header.Number, txPosition, block.Data.Data[txPosition])
})
}
}
// Validate implements the function of the StateBasedValidator interface
func (klv *KeyLevelValidator) Validate(cc string, blockNum, txNum uint64, rwsetBytes, prp, ccEP []byte, endorsements []*peer.Endorsement) commonerrors.TxValidationError {
// construct signature set
signatureSet := []*common.SignedData{}
for _, endorsement := range endorsements {
data := make([]byte, len(prp)+len(endorsement.Endorser))
copy(data, prp)
copy(data[len(prp):], endorsement.Endorser)
signatureSet = append(signatureSet, &common.SignedData{
// set the data that is signed; concatenation of proposal response bytes and endorser ID
Data: data,
// set the identity that signs the message: it's the endorser
Identity: endorsement.Endorser,
// set the signature
Signature: endorsement.Signature})
}
// construct the policy checker object
policyChecker := policyChecker{
ccEP: ccEP,
policySupport: klv.policySupport,
signatureSet: signatureSet,
vpmgr: klv.vpmgr,
}
// unpack the rwset
rwset := &rwsetutil.TxRwSet{}
if err := rwset.FromProtoBytes(rwsetBytes); err != nil {
return policyErr(errors.WithMessage(err, fmt.Sprintf("txRWSet.FromProtoBytes failed on tx (%d,%d)", blockNum, txNum)))
}
// iterate over all writes in the rwset
for _, nsRWSet := range rwset.NsRwSets {
// skip other namespaces
if nsRWSet.NameSpace != cc {
continue
}
// public writes
// we validate writes against key-level validation parameters
// if any are present or the chaincode-wide endorsement policy
for _, pubWrite := range nsRWSet.KvRwSet.Writes {
err := policyChecker.checkSBAndCCEP(cc, "", pubWrite.Key, blockNum, txNum)
if err != nil {
return err
}
}
// public metadata writes
// we validate writes against key-level validation parameters
// if any are present or the chaincode-wide endorsement policy
for _, pubMdWrite := range nsRWSet.KvRwSet.MetadataWrites {
err := policyChecker.checkSBAndCCEP(cc, "", pubMdWrite.Key, blockNum, txNum)
if err != nil {
return err
}
}
// writes in collections
// we validate writes against key-level validation parameters
// if any are present or the chaincode-wide endorsement policy
for _, collRWSet := range nsRWSet.CollHashedRwSets {
coll := collRWSet.CollectionName
for _, hashedWrite := range collRWSet.HashedRwSet.HashedWrites {
key := string(hashedWrite.KeyHash)
err := policyChecker.checkSBAndCCEP(cc, coll, key, blockNum, txNum)
if err != nil {
return err
}
}
}
// metadata writes in collections
// we validate writes against key-level validation parameters
// if any are present or the chaincode-wide endorsement policy
for _, collRWSet := range nsRWSet.CollHashedRwSets {
coll := collRWSet.CollectionName
for _, hashedMdWrite := range collRWSet.HashedRwSet.MetadataWrites {
key := string(hashedMdWrite.KeyHash)
err := policyChecker.checkSBAndCCEP(cc, coll, key, blockNum, txNum)
if err != nil {
return err
}
}
}
}
// we make sure that we check at least the CCEP to honour FAB-9473
return policyChecker.checkCCEPIfNoEPChecked(cc, blockNum, txNum)
}
// PostValidate implements the function of the StateBasedValidator interface
func (klv *KeyLevelValidator) PostValidate(cc string, blockNum, txNum uint64, err error) {
klv.vpmgr.SetTxValidationResult(cc, blockNum, txNum, err)
}
func policyErr(err error) *commonerrors.VSCCEndorsementPolicyError {
return &commonerrors.VSCCEndorsementPolicyError{
Err: err,
}
}
Go
1
https://gitee.com/hyperledger-fabric-gm/fabric.git
git@gitee.com:hyperledger-fabric-gm/fabric.git
hyperledger-fabric-gm
fabric
fabric
v1.4.9

搜索帮助