代码拉取完成,页面将自动刷新
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package endorsertx
import (
"regexp"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/pkg/tx"
"github.com/hyperledger/fabric/protoutil"
"github.com/pkg/errors"
)
var (
// ChannelAllowedChars tracks the permitted characters for a channel name
ChannelAllowedChars = "[a-z][a-z0-9.-]*"
// MaxLength tracks the maximum length of a channel name
MaxLength = 249
)
// EndorserTx represents a parsed common.Envelope protobuf
type EndorserTx struct {
ComputedTxID string
ChannelID string
ChaincodeID *peer.ChaincodeID
Creator []byte
Response *peer.Response
Events []byte
Results []byte
Endorsements []*peer.Endorsement
Type int32
Version int32
Epoch uint64
Nonce []byte
}
func unmarshalEndorserTx(txenv *tx.Envelope) (*EndorserTx, error) {
if len(txenv.ChannelHeader.Extension) == 0 {
return nil, errors.New("empty header extension")
}
hdrExt, err := protoutil.UnmarshalChaincodeHeaderExtension(
txenv.ChannelHeader.Extension,
)
if err != nil {
return nil, err
}
if len(txenv.Data) == 0 {
return nil, errors.New("nil payload data")
}
tx, err := protoutil.UnmarshalTransaction(txenv.Data)
if err != nil {
return nil, err
}
if len(tx.GetActions()) != 1 {
return nil, errors.Errorf("only one transaction action is supported, %d were present", len(tx.GetActions()))
}
txAction := tx.GetActions()[0]
if txAction == nil {
return nil, errors.New("nil action")
}
if len(txAction.Payload) == 0 {
return nil, errors.New("empty ChaincodeActionPayload")
}
ccActionPayload, err := protoutil.UnmarshalChaincodeActionPayload(txAction.Payload)
if err != nil {
return nil, err
}
if ccActionPayload.Action == nil {
return nil, errors.New("nil ChaincodeEndorsedAction")
}
if len(ccActionPayload.Action.ProposalResponsePayload) == 0 {
return nil, errors.New("empty ProposalResponsePayload")
}
proposalResponsePayload, err := protoutil.UnmarshalProposalResponsePayload(
ccActionPayload.Action.ProposalResponsePayload,
)
if err != nil {
return nil, err
}
if len(proposalResponsePayload.Extension) == 0 {
return nil, errors.New("nil Extension")
}
ccAction, err := protoutil.UnmarshalChaincodeAction(proposalResponsePayload.Extension)
if err != nil {
return nil, err
}
computedTxID := protoutil.ComputeTxID(
txenv.SignatureHeader.Nonce,
txenv.SignatureHeader.Creator,
)
return &EndorserTx{
ComputedTxID: computedTxID,
ChannelID: txenv.ChannelHeader.ChannelId,
Creator: txenv.SignatureHeader.Creator,
Response: ccAction.Response,
Events: ccAction.Events,
Results: ccAction.Results,
Endorsements: ccActionPayload.Action.Endorsements,
ChaincodeID: hdrExt.ChaincodeId,
Type: txenv.ChannelHeader.Type,
Version: txenv.ChannelHeader.Version,
Epoch: txenv.ChannelHeader.Epoch,
Nonce: txenv.SignatureHeader.Nonce,
}, nil
}
func (e *EndorserTx) validate() error {
if e.Epoch != 0 {
return errors.Errorf("invalid epoch in ChannelHeader. Expected 0, got [%d]", e.Epoch)
}
if e.Version != 0 {
return errors.Errorf("invalid version in ChannelHeader. Expected 0, got [%d]", e.Version)
}
if err := ValidateChannelID(e.ChannelID); err != nil {
return err
}
if len(e.Nonce) == 0 {
return errors.New("empty nonce")
}
if len(e.Creator) == 0 {
return errors.New("empty creator")
}
if e.ChaincodeID == nil {
return errors.New("nil ChaincodeId")
}
if e.ChaincodeID.Name == "" {
return errors.New("empty chaincode name in chaincode id")
}
// TODO FAB-16170: check proposal hash
// TODO FAB-16170: verify that txid matches the one in the header
// TODO FAB-16170: check that header in the tx action and channel header match bitwise
return nil
}
// UnmarshalEndorserTxAndValidate receives a tx.Envelope containing
// a partially unmarshalled endorser transaction and returns an EndorserTx
// instance (or an error)
func UnmarshalEndorserTxAndValidate(txenv *tx.Envelope) (*EndorserTx, error) {
etx, err := unmarshalEndorserTx(txenv)
if err != nil {
return nil, err
}
err = etx.validate()
if err != nil {
return nil, err
}
return etx, nil
}
// ValidateChannelID makes sure that proposed channel IDs comply with the
// following restrictions:
// 1. Contain only lower case ASCII alphanumerics, dots '.', and dashes '-'
// 2. Are shorter than 250 characters.
// 3. Start with a letter
//
// This is the intersection of the Kafka restrictions and CouchDB restrictions
// with the following exception: '.' is converted to '_' in the CouchDB naming
// This is to accommodate existing channel names with '.', especially in the
// behave tests which rely on the dot notation for their sluggification.
//
// note: this function is a copy of the same in common/configtx/validator.go
//
func ValidateChannelID(channelID string) error {
re, _ := regexp.Compile(ChannelAllowedChars)
// Length
if len(channelID) <= 0 {
return errors.Errorf("channel ID illegal, cannot be empty")
}
if len(channelID) > MaxLength {
return errors.Errorf("channel ID illegal, cannot be longer than %d", MaxLength)
}
// Illegal characters
matched := re.FindString(channelID)
if len(matched) != len(channelID) {
return errors.Errorf("'%s' contains illegal characters", channelID)
}
return nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。