Skip to content

Commit

Permalink
[WIP] Update to use fabric-gateway
Browse files Browse the repository at this point in the history
Signed-off-by: James Taylor <jamest@uk.ibm.com>
  • Loading branch information
jt-nti committed Nov 3, 2023
1 parent 16c4aaf commit b7bc1cf
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 261 deletions.
139 changes: 102 additions & 37 deletions cmd/ccmetadata/main.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
package main

import (
"bytes"
"crypto/x509"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"

"github.com/hyperledger/fabric-sdk-go/pkg/common/logging"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/gateway"
"github.com/hyperledger/fabric-gateway/pkg/client"
"github.com/hyperledger/fabric-gateway/pkg/identity"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

func usage() {
fmt.Fprintf(os.Stderr, "Usage: ccmetadata --cert=<path> --key=<path> --mspid=<name> --connection=<path> --channel=<name> [--aslocalhost] [--verbose] <chaincode>\n\n")
fmt.Fprintf(os.Stderr, "Usage: ccmetadata --cert=<path> --key=<path> --mspid=<name> TODOTODOTODO --channel=<name> [--aslocalhost] [--verbose] <chaincode>\n\n")

fmt.Fprintf(os.Stderr, "Get metadata for the specified chaincode name\n\n")

fmt.Fprintf(os.Stderr, " -t, --tlscert string\n tls certificate file\n")
fmt.Fprintf(os.Stderr, " -c, --cert string\n certificate file\n")
fmt.Fprintf(os.Stderr, " -k, --key string\n private key file\n")
fmt.Fprintf(os.Stderr, " -m, --mspid string\n membership service provider name, e.g. Org1MSP\n")
fmt.Fprintf(os.Stderr, " -p, --connection string\n connection profile file\n")
fmt.Fprintf(os.Stderr, " -p, --peer string\n gateway peer name(TODO?)\n")
fmt.Fprintf(os.Stderr, " -a, --address string\n gateway(TODO?) peer address\n")
fmt.Fprintf(os.Stderr, " -n, --channel string\n channel name, e.g. mychannel\n")
fmt.Fprintf(os.Stderr, " -l, --aslocalhost\n use discovery service as localhost\n")
fmt.Fprintf(os.Stderr, " -v, --verbose\n enable verbose logging\n")
}

func main() {
// TODO add...
// tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
// gatewayPeer = "peer0.org1.example.com"
// peerEndpoint = "localhost:7051"
var tlsCertPath string
var certPath string
var gatewayPeer string
var peerEndpoint string
var keyPath string
var mspid string
var ccpPath string
var channelName string
var aslocalhost bool
var verbose bool
Expand All @@ -44,8 +55,6 @@ func main() {
flag.StringVar(&keyPath, "k", "", "private key file")
flag.StringVar(&mspid, "mspid", "", "membership service provider name, e.g. Org1MSP")
flag.StringVar(&mspid, "m", "", "membership service provider name, e.g. Org1MSP")
flag.StringVar(&ccpPath, "connection", "", "connection profile file")
flag.StringVar(&ccpPath, "p", "", "connection profile file")
flag.StringVar(&channelName, "channel", "", "channel name, e.g. mychannel")
flag.StringVar(&channelName, "n", "", "channel name, e.g. mychannel")
flag.BoolVar(&aslocalhost, "aslocalhost", false, "use discovery service as localhost")
Expand Down Expand Up @@ -80,62 +89,118 @@ func main() {
fmt.Printf("Channel name: %s\n", channelName)
fmt.Printf("As localhost option: %t\n", aslocalhost)
fmt.Printf("Chaincode name: %s\n", chaincodeName)
} else {
logging.SetLevel("", logging.ERROR)
}

if aslocalhost {
err := os.Setenv("DISCOVERY_AS_LOCALHOST", "true")
if err != nil {
log.Fatalf("Failed to set DISCOVERY_AS_LOCALHOST environment variable: %v", err)
panic(fmt.Errorf("failed to set DISCOVERY_AS_LOCALHOST environment variable: %w", err))
}
}

wallet, err := createWallet(certPath, keyPath, mspid)
clientConnection := newGrpcConnection(tlsCertPath, gatewayPeer, peerEndpoint)
defer clientConnection.Close()

id := newIdentity(certPath, mspid)
sign := newSign(keyPath)

gw, 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 {
log.Fatalf("Failed to get credentials: %v", err)
panic(err)
}
defer gw.Close()

connectionConfig := config.FromFile(filepath.Clean(ccpPath))
network := gw.GetNetwork(channelName)
contract := network.GetContract(chaincodeName)

gateway, err := gateway.Connect(
gateway.WithConfig(connectionConfig),
gateway.WithIdentity(wallet, "identity"),
)
evaluateResult, err := contract.EvaluateTransaction("org.hyperledger.fabric:GetMetadata")
if err != nil {
log.Fatalf("Failed to connect to gateway: %v", err)
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
}
defer gateway.Close()
result := formatJSON(evaluateResult)
fmt.Printf(result)
}

// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection(tlsCertPath, gatewayPeer, peerEndpoint string) *grpc.ClientConn {
// TODO make TLS optional?
// clientConnection, err := grpc.Dial("gateway.example.org:1337", grpc.WithTransportCredentials(insecure.NewCredentials()))

network, err := gateway.GetNetwork(channelName)
certificate, err := loadCertificate(tlsCertPath)
if err != nil {
log.Fatalf("Failed to get network: %v", err)
panic(err)
}

contract := network.GetContract(chaincodeName)
certPool := x509.NewCertPool()
certPool.AddCert(certificate)
// TODO servernameOverride optional?
transportCredentials := credentials.NewClientTLSFromCert(certPool, gatewayPeer)

result, err := contract.EvaluateTransaction("org.hyperledger.fabric:GetMetadata")
connection, err := grpc.Dial(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
if err != nil {
log.Fatalf("Failed to evaluate transaction: %v", err)
panic(fmt.Errorf("failed to create gRPC connection: %w", err))
}
fmt.Println(string(result))

return connection
}

func createWallet(certPath, keyPath, mspid string) (*gateway.Wallet, error) {
wallet := gateway.NewInMemoryWallet()
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity(certPath, mspID string) *identity.X509Identity {
certificate, err := loadCertificate(certPath)
if err != nil {
panic(err)
}

cert, err := ioutil.ReadFile(filepath.Clean(certPath))
id, err := identity.NewX509Identity(mspID, certificate)
if err != nil {
return wallet, err
panic(err)
}

key, err := ioutil.ReadFile(filepath.Clean(keyPath))
return id
}

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

identity := gateway.NewX509Identity(mspid, string(cert), string(key))
wallet.Put("identity", identity)
// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign(keyPath string) identity.Sign {
privateKeyPEM, err := os.ReadFile(filepath.Clean(keyPath))
if err != nil {
panic(fmt.Errorf("failed to read private key file: %w", err))
}

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

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

return sign
}

// Format JSON data
func formatJSON(data []byte) string {
var prettyJSON bytes.Buffer
if err := json.Indent(&prettyJSON, data, "", " "); err != nil {
panic(fmt.Errorf("failed to parse JSON: %w", err))
}
return prettyJSON.String()
}
19 changes: 17 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
module github.com/hyperledgendary/ccmetadata

go 1.14
go 1.18

require github.com/hyperledger/fabric-sdk-go v1.0.0
require (
github.com/hyperledger/fabric-gateway v1.4.0
google.golang.org/grpc v1.59.0
)

require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/hyperledger/fabric-protos-go-apiv2 v0.2.1 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
Loading

0 comments on commit b7bc1cf

Please sign in to comment.