fabric-samples icon indicating copy to clipboard operation
fabric-samples copied to clipboard

failed to submit transaction: rpc error: code = Aborted desc = failed to endorse transaction

Open knight-hjh opened this issue 2 years ago • 0 comments

After execute the sample of asset-transfer-basic. image I try to write my own smart contract, deploy it and invoke it. I wrote my own contract code imitating asset-transfer.

package chaincode

import(
	"encoding/json"
	"fmt"
	
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// SmartContract用于管理TEE相关信息
type SmartContract struct {
	contractapi.Contract
}

type TEEInfo struct {
	ID		String	`json:"ID"`
	PublicKey	String	`json:"PublicKey"`
	TEECert	String	`json:"TEECert"`	
}

// InitInfo adds an example of TEEInfo to the list
func (s *SmartContract) InitInfo (ctx contractapi.TransactionContextInterface) error {
	infos := []Info{
		{ID: "Info1", PublicKey: "PK1", TEECert: "Cert1"},
		{ID: "Info2", PublicKey: "PK2", TEECert: "Cert2"},
	}
	
	for _, info := range infos {
		infoJSON, err := json.Marshal(info)
		if err != nil{
			return err
		}

		err = ctx.GetStub().PutState(info.ID, InfoJSON)
		if err != nil{
			return fmt.Errorf("failed to put to world state. %v", err)
		}
	}

	return nil
	
}

func (s *SmartContract) InsertInfo(ctx contractapi.TransactionContextInterface, id string, publicKey string, teeCert string) error {
	exists, err := s.InfoExists(ctx, id)
	if err != nil {
		return err
	}
	if exists{
		return fmt.Errorf("the info %s already exists", id)
	}

	info := Info{
		ID:		id,
		PublicKey:	publicKey,
		TEECert:	teeCert,
	}	
	infoJSON, err := json.Marshal(info)
	if err != nil {	
		return err
	}
	
	return ctx.GetStub.PutState(id, infoJSON)
}

func (s *SmartContract) InfoExists(ctx contractapi.TransactionContextInterface, id string) (bool, error){
	infoJSON, err := ctx.GetStub().GetState(id)
	if err != nil{
		return false, fmt.Errorf("failed to read from world state: %v", err)
	}	
	
	return infoJSON != nil, nil
}

And I deploy it successfully. image

I try to use gateway to communicate with blockchain. the code is same like asset-transfer.

package main

import (
	//"bytes"
	//"context"
	"crypto/x509"
	//"encoding/json"
	//"errors"
	"fmt"
	"github.com/hyperledger/fabric-gateway/pkg/client"
	"github.com/hyperledger/fabric-gateway/pkg/identity"
	//gwproto "github.com/hyperledger/fabric-protos-go/gateway"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	//"google.golang.org/grpc/status"
	"io/ioutil"
	"log"
	"path"
	"time"
)

const (
	mspID         = "Org1MSP"
	cryptoPath    = "../../test-network/organizations/peerOrganizations/org1.example.com"
	certPath      = cryptoPath + "/users/[email protected]/msp/signcerts/cert.pem"
	keyPath       = cryptoPath + "/users/[email protected]/msp/keystore/"
	tlsCertPath   = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
	peerEndpoint  = "localhost:7051"
	gatewayPeer   = "peer0.org1.example.com"
	channelName   = "mychannel"
	chaincodeName = "teecontract"
)

var now = time.Now()
var Id = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)

func main() {
	log.Println("============ application-golang starts ============")

	// The gRPC client connection should be shared by all Gateway connections to this endpoint
	clientConnection := newGrpcConnection()
	defer clientConnection.Close()

	id := newIdentity()
	sign := newSign()

	// Create a Gateway connection for a specific client identity
	gateway, err := client.Connect(
		id,
		client.WithSign(sign),
		client.WithClientConnection(clientConnection),
		// Default timeouts for different gRPC calls
		client.WithEvaluateTimeout(5*time.Second),
		client.WithEndorseTimeout(15*time.Second),
		client.WithSubmitTimeout(5*time.Second),
		client.WithCommitStatusTimeout(1*time.Minute),
	)
	if err != nil {
		panic(err)
	}
	defer gateway.Close()

	network := gateway.GetNetwork(channelName)
	contract := network.GetContract(chaincodeName)

	fmt.Println("initLedger:")
	initLedger(contract)


	log.Println("============ application-golang ends ============")
}

// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection() *grpc.ClientConn {
	certificate, err := loadCertificate(tlsCertPath)
	if err != nil {
		panic(err)
	}

	certPool := x509.NewCertPool()
	certPool.AddCert(certificate)
	transportCredentials := credentials.NewClientTLSFromCert(certPool, gatewayPeer)

	connection, err := grpc.Dial(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
	if err != nil {
		panic(fmt.Errorf("failed to create gRPC connection: %w", err))
	}

	return connection
}

// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity() *identity.X509Identity {
	certificate, err := loadCertificate(certPath)
	if err != nil {
		panic(err)
	}

	id, err := identity.NewX509Identity(mspID, certificate)
	if err != nil {
		panic(err)
	}

	return id
}

func loadCertificate(filename string) (*x509.Certificate, error) {
	certificatePEM, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("failed to read certificate file: %w", err)
	}
	return identity.CertificateFromPEM(certificatePEM)
}

// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign() identity.Sign {
	files, err := ioutil.ReadDir(keyPath)
	if err != nil {
		panic(fmt.Errorf("failed to read private key directory: %w", err))
	}
	privateKeyPEM, err := ioutil.ReadFile(path.Join(keyPath, files[0].Name()))

	if err != nil {
		panic(fmt.Errorf("failed to read private key file: %w", err))
	}

	privateKey, err := identity.PrivateKeyFromPEM(privateKeyPEM)
	if err != nil {
		panic(err)
	}

	sign, err := identity.NewPrivateKeySign(privateKey)
	if err != nil {
		panic(err)
	}

	return sign
}


func initLedger(contract *client.Contract) {
	fmt.Printf("Submit Transaction: InitLedger, function creates the initial set of assets on the ledger \n")

	_, err := contract.SubmitTransaction("InitInfo")
	if err != nil {
		panic(fmt.Errorf("failed to submit transaction: %w", err))
	}

	fmt.Printf("*** Transaction committed successfully\n")
}

But when I run go run . under the application -gateway-go. it report image Anyone else know why. It seems like the command contract.SubmitTransaction("InitInfo") get wrong. but I don't know why and how I can fix it. :(

knight-hjh avatar Jun 13 '22 02:06 knight-hjh