-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor: remove fabric import "github.com/hyperledger/fabric/protout…
…il". Signed-off-by: yiwenlong <wlong.yi@gmail.com>
- Loading branch information
Showing
5 changed files
with
725 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package protoutil | ||
|
||
import ( | ||
"crypto/rand" | ||
"time" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/golang/protobuf/ptypes/timestamp" | ||
cb "github.com/hyperledger/fabric-protos-go/common" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// MarshalOrPanic serializes a protobuf message and panics if this | ||
// operation fails | ||
func MarshalOrPanic(pb proto.Message) []byte { | ||
data, err := proto.Marshal(pb) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return data | ||
} | ||
|
||
// Marshal serializes a protobuf message. | ||
func Marshal(pb proto.Message) ([]byte, error) { | ||
return proto.Marshal(pb) | ||
} | ||
|
||
// CreateNonce generates a nonce using the common/crypto package. | ||
func CreateNonce() ([]byte, error) { | ||
nonce, err := getRandomNonce() | ||
return nonce, errors.WithMessage(err, "error generating random nonce") | ||
} | ||
|
||
// ExtractEnvelope retrieves the requested envelope from a given block and | ||
// unmarshals it | ||
func ExtractEnvelope(block *cb.Block, index int) (*cb.Envelope, error) { | ||
if block.Data == nil { | ||
return nil, errors.New("block data is nil") | ||
} | ||
|
||
envelopeCount := len(block.Data.Data) | ||
if index < 0 || index >= envelopeCount { | ||
return nil, errors.New("envelope index out of bounds") | ||
} | ||
marshaledEnvelope := block.Data.Data[index] | ||
envelope, err := GetEnvelopeFromBlock(marshaledEnvelope) | ||
err = errors.WithMessagef(err, "block data does not carry an envelope at index %d", index) | ||
return envelope, err | ||
} | ||
|
||
// MakeChannelHeader creates a ChannelHeader. | ||
func MakeChannelHeader(headerType cb.HeaderType, version int32, chainID string, epoch uint64) *cb.ChannelHeader { | ||
return &cb.ChannelHeader{ | ||
Type: int32(headerType), | ||
Version: version, | ||
Timestamp: ×tamp.Timestamp{ | ||
Seconds: time.Now().Unix(), | ||
Nanos: 0, | ||
}, | ||
ChannelId: chainID, | ||
Epoch: epoch, | ||
} | ||
} | ||
|
||
// MakePayloadHeader creates a Payload Header. | ||
func MakePayloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader) *cb.Header { | ||
return &cb.Header{ | ||
ChannelHeader: MarshalOrPanic(ch), | ||
SignatureHeader: MarshalOrPanic(sh), | ||
} | ||
} | ||
|
||
// NewSignatureHeader returns a SignatureHeader with a valid nonce. | ||
func NewSignatureHeader(id Signer) (*cb.SignatureHeader, error) { | ||
creator, err := id.Serialize() | ||
if err != nil { | ||
return nil, err | ||
} | ||
nonce, err := CreateNonce() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &cb.SignatureHeader{ | ||
Creator: creator, | ||
Nonce: nonce, | ||
}, nil | ||
} | ||
|
||
// ChannelHeader returns the *cb.ChannelHeader for a given *cb.Envelope. | ||
func ChannelHeader(env *cb.Envelope) (*cb.ChannelHeader, error) { | ||
envPayload, err := UnmarshalPayload(env.Payload) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if envPayload.Header == nil { | ||
return nil, errors.New("header not set") | ||
} | ||
|
||
if envPayload.Header.ChannelHeader == nil { | ||
return nil, errors.New("channel header not set") | ||
} | ||
|
||
chdr, err := UnmarshalChannelHeader(envPayload.Header.ChannelHeader) | ||
if err != nil { | ||
return nil, errors.WithMessage(err, "error unmarshaling channel header") | ||
} | ||
|
||
return chdr, nil | ||
} | ||
|
||
// ChannelID returns the Channel ID for a given *cb.Envelope. | ||
func ChannelID(env *cb.Envelope) (string, error) { | ||
chdr, err := ChannelHeader(env) | ||
if err != nil { | ||
return "", errors.WithMessage(err, "error retrieving channel header") | ||
} | ||
|
||
return chdr.ChannelId, nil | ||
} | ||
|
||
func getRandomNonce() ([]byte, error) { | ||
key := make([]byte, 24) | ||
|
||
_, err := rand.Read(key) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "error getting random bytes") | ||
} | ||
return key, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package protoutil | ||
|
||
import ( | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"time" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/golang/protobuf/ptypes" | ||
"github.com/hyperledger/fabric-protos-go/common" | ||
"github.com/hyperledger/fabric-protos-go/peer" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// CreateChaincodeProposal creates a proposal from given input. | ||
// It returns the proposal and the transaction id associated to the proposal | ||
func CreateChaincodeProposal(typ common.HeaderType, channelID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) { | ||
return CreateChaincodeProposalWithTransient(typ, channelID, cis, creator, nil) | ||
} | ||
|
||
// CreateChaincodeProposalWithTransient creates a proposal from given input | ||
// It returns the proposal and the transaction id associated to the proposal | ||
func CreateChaincodeProposalWithTransient(typ common.HeaderType, channelID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) { | ||
// generate a random nonce | ||
nonce, err := getRandomNonce() | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
// compute txid | ||
txid := ComputeTxID(nonce, creator) | ||
|
||
return CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, channelID, cis, nonce, creator, transientMap) | ||
} | ||
|
||
// CreateChaincodeProposalWithTxIDNonceAndTransient creates a proposal from | ||
// given input | ||
func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, channelID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) { | ||
ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId} | ||
ccHdrExtBytes, err := proto.Marshal(ccHdrExt) | ||
if err != nil { | ||
return nil, "", errors.Wrap(err, "error marshaling ChaincodeHeaderExtension") | ||
} | ||
|
||
cisBytes, err := proto.Marshal(cis) | ||
if err != nil { | ||
return nil, "", errors.Wrap(err, "error marshaling ChaincodeInvocationSpec") | ||
} | ||
|
||
ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap} | ||
ccPropPayloadBytes, err := proto.Marshal(ccPropPayload) | ||
if err != nil { | ||
return nil, "", errors.Wrap(err, "error marshaling ChaincodeProposalPayload") | ||
} | ||
|
||
// TODO: epoch is now set to zero. This must be changed once we | ||
// get a more appropriate mechanism to handle it in. | ||
var epoch uint64 | ||
|
||
timestamp, err := ptypes.TimestampProto(time.Now().UTC()) | ||
if err != nil { | ||
return nil, "", errors.Wrap(err, "error validating Timestamp") | ||
} | ||
|
||
hdr := &common.Header{ | ||
ChannelHeader: MarshalOrPanic( | ||
&common.ChannelHeader{ | ||
Type: int32(typ), | ||
TxId: txid, | ||
Timestamp: timestamp, | ||
ChannelId: channelID, | ||
Extension: ccHdrExtBytes, | ||
Epoch: epoch, | ||
}, | ||
), | ||
SignatureHeader: MarshalOrPanic( | ||
&common.SignatureHeader{ | ||
Nonce: nonce, | ||
Creator: creator, | ||
}, | ||
), | ||
} | ||
|
||
hdrBytes, err := proto.Marshal(hdr) | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
prop := &peer.Proposal{ | ||
Header: hdrBytes, | ||
Payload: ccPropPayloadBytes, | ||
} | ||
return prop, txid, nil | ||
} | ||
|
||
// GetBytesProposalResponsePayload gets proposal response payload | ||
func GetBytesProposalResponsePayload(hash []byte, response *peer.Response, result []byte, event []byte, ccid *peer.ChaincodeID) ([]byte, error) { | ||
cAct := &peer.ChaincodeAction{ | ||
Events: event, Results: result, | ||
Response: response, | ||
ChaincodeId: ccid, | ||
} | ||
cActBytes, err := proto.Marshal(cAct) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "error marshaling ChaincodeAction") | ||
} | ||
|
||
prp := &peer.ProposalResponsePayload{ | ||
Extension: cActBytes, | ||
ProposalHash: hash, | ||
} | ||
prpBytes, err := proto.Marshal(prp) | ||
return prpBytes, errors.Wrap(err, "error marshaling ProposalResponsePayload") | ||
} | ||
|
||
// GetBytesChaincodeProposalPayload gets the chaincode proposal payload | ||
func GetBytesChaincodeProposalPayload(cpp *peer.ChaincodeProposalPayload) ([]byte, error) { | ||
cppBytes, err := proto.Marshal(cpp) | ||
return cppBytes, errors.Wrap(err, "error marshaling ChaincodeProposalPayload") | ||
} | ||
|
||
// GetBytesChaincodeActionPayload get the bytes of ChaincodeActionPayload from | ||
// the message | ||
func GetBytesChaincodeActionPayload(cap *peer.ChaincodeActionPayload) ([]byte, error) { | ||
capBytes, err := proto.Marshal(cap) | ||
return capBytes, errors.Wrap(err, "error marshaling ChaincodeActionPayload") | ||
} | ||
|
||
// GetBytesTransaction get the bytes of Transaction from the message | ||
func GetBytesTransaction(tx *peer.Transaction) ([]byte, error) { | ||
bytes, err := proto.Marshal(tx) | ||
return bytes, errors.Wrap(err, "error unmarshaling Transaction") | ||
} | ||
|
||
// GetBytesPayload get the bytes of Payload from the message | ||
func GetBytesPayload(payl *common.Payload) ([]byte, error) { | ||
bytes, err := proto.Marshal(payl) | ||
return bytes, errors.Wrap(err, "error marshaling Payload") | ||
} | ||
|
||
// CreateProposalFromCIS returns a proposal given a serialized identity and a | ||
// ChaincodeInvocationSpec | ||
func CreateProposalFromCIS(typ common.HeaderType, channelID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) { | ||
return CreateChaincodeProposal(typ, channelID, cis, creator) | ||
} | ||
|
||
// ComputeTxID computes TxID as the Hash computed | ||
// over the concatenation of nonce and creator. | ||
func ComputeTxID(nonce, creator []byte) string { | ||
// TODO: Get the Hash function to be used from | ||
// channel configuration | ||
hasher := sha256.New() | ||
hasher.Write(nonce) | ||
hasher.Write(creator) | ||
return hex.EncodeToString(hasher.Sum(nil)) | ||
} |
Oops, something went wrong.