228 lines
6.0 KiB
Go
228 lines
6.0 KiB
Go
package util
|
||
|
||
import (
|
||
"crypto/sha256"
|
||
"encoding/hex"
|
||
|
||
pb "schain/proto"
|
||
|
||
"github.com/pkg/errors"
|
||
"google.golang.org/protobuf/proto"
|
||
)
|
||
|
||
// CreateChaincodeProposal 创建链码请求
|
||
func CreateChaincodeProposal(cis *pb.ChaincodeSpec, creator []byte) (*pb.Proposal, string, error) {
|
||
//创建一个随机的nonce
|
||
nonce, err := getRandomNonce()
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
// 计算txid
|
||
txid := ComputeTxID(nonce, creator)
|
||
|
||
return CreateChaincodeProposalWithTxIDNonce(txid, cis, nonce, creator)
|
||
}
|
||
|
||
// CreateChaincodeProposalWithTxID 创建链码请求(需要交易id)
|
||
func CreateChaincodeProposalWithTxID(cis *pb.ChaincodeSpec, creator []byte, txid string) (*pb.Proposal, string, error) {
|
||
nonce, err := getRandomNonce()
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
// 如果交易id为空,则计算交易id
|
||
if txid == "" {
|
||
txid = ComputeTxID(nonce, creator)
|
||
}
|
||
|
||
return CreateChaincodeProposalWithTxIDNonce(txid, cis, nonce, creator)
|
||
}
|
||
|
||
// CreateChaincodeProposalWithTxIDNonce 创建链码请求(需要交易id和nonce)
|
||
func CreateChaincodeProposalWithTxIDNonce(txid string, cis *pb.ChaincodeSpec, nonce, creator []byte) (*pb.Proposal, string, error) {
|
||
|
||
cisBytes, err := proto.Marshal(cis)
|
||
if err != nil {
|
||
return nil, "", errors.Wrap(err, "error marshaling ChaincodeInvocationSpec")
|
||
}
|
||
|
||
hdr := &pb.SignatureHeader{
|
||
Nonce: nonce,
|
||
Creator: creator,
|
||
}
|
||
|
||
hdrBytes, err := proto.Marshal(hdr)
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
prop := &pb.Proposal{
|
||
Header: hdrBytes,
|
||
Payload: cisBytes,
|
||
}
|
||
return prop, txid, nil
|
||
}
|
||
|
||
func CreateSignatureHeader(signer Signer) (*pb.SignatureHeader, error) {
|
||
nonce, err := getRandomNonce()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
creator, err := signer.Serialize()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
hdr := &pb.SignatureHeader{
|
||
Nonce: nonce,
|
||
Creator: creator,
|
||
}
|
||
return hdr, nil
|
||
}
|
||
|
||
func GetBytesProposalResponsePayload(hash []byte, response *pb.Response, result []byte) ([]byte, error) {
|
||
cAct := &pb.ChaincodeAction{
|
||
Results: result,
|
||
Response: response,
|
||
}
|
||
cActBytes, err := proto.Marshal(cAct)
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "error marshaling ChaincodeAction")
|
||
}
|
||
|
||
prp := &pb.ProposalResponsePayload{
|
||
Extension: cActBytes,
|
||
ProposalHash: hash,
|
||
}
|
||
prpBytes, err := proto.Marshal(prp)
|
||
return prpBytes, errors.Wrap(err, "error marshaling ProposalResponsePayload")
|
||
}
|
||
|
||
// GetBytesChaincodeSpec 获取 ChaincodeSpec 结构的字节数组
|
||
func GetBytesChaincodeSpec(cs *pb.ChaincodeSpec) ([]byte, error) {
|
||
cppBytes, err := proto.Marshal(cs)
|
||
return cppBytes, errors.Wrap(err, "error marshaling ChaincodeSpec")
|
||
}
|
||
|
||
// GetBytesChaincodeActionPayload 获取 ChaincodeActionPayload 结构的字节数组
|
||
func GetBytesChaincodeActionPayload(cap *pb.ChaincodeActionPayload) ([]byte, error) {
|
||
cppBytes, err := proto.Marshal(cap)
|
||
return cppBytes, errors.Wrap(err, "error marshaling ChaincodeActionPayload")
|
||
}
|
||
|
||
// GetBytesResponse 获取 Response 结构的字节数组
|
||
func GetBytesResponse(res *pb.Response) ([]byte, error) {
|
||
resBytes, err := proto.Marshal(res)
|
||
return resBytes, errors.Wrap(err, "error marshaling Response")
|
||
}
|
||
|
||
// GetBytesProposalResponse 获取 ProposalResponse 结构的字节数组
|
||
func GetBytesProposalResponse(pr *pb.ProposalResponse) ([]byte, error) {
|
||
respBytes, err := proto.Marshal(pr)
|
||
return respBytes, errors.Wrap(err, "error marshaling ProposalResponse")
|
||
}
|
||
|
||
// GetBytesSignatureHeader 获取 SignatureHeader 结构的字节数组
|
||
func GetBytesSignatureHeader(shdr *pb.SignatureHeader) ([]byte, error) {
|
||
bytes, err := proto.Marshal(shdr)
|
||
return bytes, errors.Wrap(err, "error marshaling SignatureHeader")
|
||
}
|
||
|
||
// GetBytesTransaction 获取 Transaction 结构的字节数组
|
||
func GetBytesTransaction(tx *pb.Transaction) ([]byte, error) {
|
||
bytes, err := proto.Marshal(tx)
|
||
return bytes, errors.Wrap(err, "error unmarshalling Transaction")
|
||
}
|
||
|
||
// GetBytesPayload 获取 Payload 结构的字节数组
|
||
func GetBytesPayload(payl *pb.Payload) ([]byte, error) {
|
||
bytes, err := proto.Marshal(payl)
|
||
return bytes, errors.Wrap(err, "error marshaling Payload")
|
||
}
|
||
|
||
// GetBytesEnvelope 获取 Envelope 结构的字节数组
|
||
func GetBytesEnvelope(env *pb.Envelope) ([]byte, error) {
|
||
bytes, err := proto.Marshal(env)
|
||
return bytes, errors.Wrap(err, "error marshaling Envelope")
|
||
}
|
||
|
||
func GetActionPayloadFromEnvelope(envBytes []byte) (*pb.ChaincodeActionPayload, error) {
|
||
env, err := UnmarshalEnvelope(envBytes)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return GetActionPayloadFromEnvelopeMsg(env)
|
||
}
|
||
|
||
func GetActionPayloadFromEnvelopeMsg(env *pb.Envelope) (*pb.ChaincodeActionPayload, error) {
|
||
payl, err := UnmarshalPayload(env.Payload)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
tx, err := UnmarshalTransaction(payl.Data)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
if tx.Payload == nil {
|
||
return nil, errors.New("at least one TransactionAction required")
|
||
}
|
||
|
||
respPayload := tx.Payload
|
||
return respPayload, err
|
||
}
|
||
|
||
// CheckTxID 检测交易id是否正确
|
||
func CheckTxID(txid string, nonce, creator []byte) error {
|
||
computedTxID := ComputeTxID(nonce, creator)
|
||
|
||
if txid != computedTxID {
|
||
return errors.Errorf("invalid txid. got [%s], expected [%s]", txid, computedTxID)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// ComputeTxID 计算交易id
|
||
func ComputeTxID(nonce, creator []byte) string {
|
||
hasher := sha256.New()
|
||
hasher.Write(nonce)
|
||
hasher.Write(creator)
|
||
return hex.EncodeToString(hasher.Sum(nil))
|
||
}
|
||
|
||
// CreateChaincodeTxID 创建交易id
|
||
func CreateChaincodeTxID(creator []byte) (string, error) {
|
||
nonce, err := CreateNonce()
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
txid := ComputeTxID(nonce, creator)
|
||
|
||
return txid, nil
|
||
|
||
}
|
||
|
||
func InvokedChaincodeName(proposalBytes []byte) (string, error) {
|
||
proposal := &pb.Proposal{}
|
||
err := proto.Unmarshal(proposalBytes, proposal)
|
||
if err != nil {
|
||
return "", errors.WithMessage(err, "could not unmarshal proposal")
|
||
}
|
||
|
||
cs := &pb.ChaincodeSpec{}
|
||
err = proto.Unmarshal(proposal.Payload, cs)
|
||
if err != nil {
|
||
return "", errors.WithMessage(err, "could not unmarshal chaincode spec")
|
||
}
|
||
|
||
if cs.ChaincodeID == nil {
|
||
return "", errors.Errorf("chaincode id is nil")
|
||
}
|
||
|
||
return cs.ChaincodeID.Name, nil
|
||
}
|