From 0e7d3d9187e8432e507979ab960197d0e45e6471 Mon Sep 17 00:00:00 2001 From: "Mark S. Lewis" Date: Sun, 6 Oct 2024 17:35:55 +0100 Subject: [PATCH] Include hash in example client connection code When using non-ECDSA private keys, such as ed25519, it can be necessary to specify an alternative hash algorithm. Highlight that a hash can (and probably should) be explicitly specified when creating a Gateway connection by including this in the client code examples. Signed-off-by: Mark S. Lewis --- java/README.md | 4 +-- java/src/main/javadoc/overview.html | 48 +++++++++++++++++++++++------ node/src/README.md | 11 +++++-- pkg/client/example_test.go | 4 ++- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/java/README.md b/java/README.md index acd925162..38031314b 100644 --- a/java/README.md +++ b/java/README.md @@ -38,7 +38,7 @@ A suitable gRPC channel service provider must also be specified (as described in io.grpc grpc-netty-shaded - 1.68.0 + 1.67.1 runtime ``` @@ -54,7 +54,7 @@ implementation 'org.hyperledger.fabric:fabric-gateway:1.6.0' A suitable gRPC channel service provider must also be specified (as described in the [gRPC security documentation](https://github.com/grpc/grpc-java/blob/master/SECURITY.md#transport-security-tls)), such as: ```groovy -runtimeOnly 'io.grpc:grpc-netty-shaded:1.68.0' +runtimeOnly 'io.grpc:grpc-netty-shaded:1.67.1' ``` ## Compatibility diff --git a/java/src/main/javadoc/overview.html b/java/src/main/javadoc/overview.html index a9ff42965..1a48036cf 100644 --- a/java/src/main/javadoc/overview.html +++ b/java/src/main/javadoc/overview.html @@ -34,45 +34,73 @@


-    import io.grpc.Grpc;
-    import io.grpc.ManagedChannel;
-    import io.grpc.TlsChannelCredentials;
-    import org.hyperledger.fabric.client.*;
-    import org.hyperledger.fabric.client.identity.*;
+import io.grpc.ChannelCredentials;
+import io.grpc.Grpc;
+import io.grpc.ManagedChannel;
+import io.grpc.TlsChannelCredentials;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.InvalidKeyException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.time.LocalDateTime;
+import java.util.concurrent.TimeUnit;
+import org.hyperledger.fabric.client.identity.Identities;
+import org.hyperledger.fabric.client.identity.Identity;
+import org.hyperledger.fabric.client.identity.Signer;
+import org.hyperledger.fabric.client.identity.Signers;
+import org.hyperledger.fabric.client.identity.X509Identity;
 
-    public static void main(final String[] args) throws CommitException, GatewayException, InterruptedException {
-        Reader certReader = Files.newBufferedReader(certificatePath);
+public final class Example {
+    public static void main(final String[] args)
+            throws IOException, CertificateException, InvalidKeyException, GatewayException, CommitException,
+                    InterruptedException {
+        // Create client identity based on X.509 certificate.
+        Reader certReader = Files.newBufferedReader(Paths.get("path/to/certificate.pem"));
         X509Certificate certificate = Identities.readX509Certificate(certReader);
         Identity identity = new X509Identity("mspId", certificate);
 
-        Reader keyReader = Files.newBufferedReader(privateKeyPath);
+        // Create signing implementation based on private key.
+        Reader keyReader = Files.newBufferedReader(Paths.get("path/to/private-key.pem"));
         PrivateKey privateKey = Identities.readPrivateKey(keyReader);
         Signer signer = Signers.newPrivateKeySigner(privateKey);
 
+        // Create gRPC client connection, which should be shared by all gateway connections to this endpoint.
         ChannelCredentials tlsCredentials = TlsChannelCredentials.newBuilder()
-                .trustManager(Paths.get(tlsRootCertPath).toFile())
+                .trustManager(Paths.get("path/to/tls-CA-certificate.pem").toFile())
                 .build();
         ManagedChannel grpcChannel = Grpc.newChannelBuilder("gateway.example.org:1337", tlsCredentials)
                 .build();
 
+        // Create a Gateway connection for a specific client identity.
         Gateway.Builder builder = Gateway.newInstance()
                 .identity(identity)
                 .signer(signer)
+                .hash(Hash.SHA256)
                 .connection(grpcChannel);
 
         try (Gateway gateway = builder.connect()) {
+            // Obtain smart contract deployed on the network.
             Network network = gateway.getNetwork("channelName");
             Contract contract = network.getContract("chaincodeName");
 
-            byte[] putResult = contract.submitTransaction("put", "time", LocalDateTime.now().toString());
+            // Submit transactions that store state to the ledger.
+            byte[] putResult = contract.submitTransaction(
+                    "put", "time", LocalDateTime.now().toString());
             System.out.println(new String(putResult, StandardCharsets.UTF_8));
 
+            // Evaluate transactions that query state from the ledger.
             byte[] getResult = contract.evaluateTransaction("get", "time");
             System.out.println(new String(getResult, StandardCharsets.UTF_8));
         } finally {
             grpcChannel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
         }
     }
+}
     
diff --git a/node/src/README.md b/node/src/README.md index 5f4324771..f17e6dd23 100644 --- a/node/src/README.md +++ b/node/src/README.md @@ -16,8 +16,8 @@ The following complete example shows how to connect to a Fabric network, submit ```TypeScript import * as grpc from '@grpc/grpc-js'; +import { connect, hash, signers } from '@hyperledger/fabric-gateway'; import * as crypto from 'node:crypto'; -import { connect, Identity, signers } from '@hyperledger/fabric-gateway'; import { promises as fs } from 'node:fs'; import { TextDecoder } from 'node:util'; @@ -25,7 +25,6 @@ const utf8Decoder = new TextDecoder(); async function main(): Promise { const credentials = await fs.readFile('path/to/certificate.pem'); - const identity: Identity = { mspId: 'myorg', credentials }; const privateKeyPem = await fs.readFile('path/to/privateKey.pem'); const privateKey = crypto.createPrivateKey(privateKeyPem); @@ -34,7 +33,13 @@ async function main(): Promise { const tlsRootCert = await fs.readFile('path/to/tlsRootCertificate.pem'); const client = new grpc.Client('gateway.example.org:1337', grpc.credentials.createSsl(tlsRootCert)); - const gateway = connect({ identity, signer, client }); + const gateway = connect({ + identity: { mspId: 'myorg', credentials }, + signer, + hash: hash.sha256, + client, + }); + try { const network = gateway.getNetwork('channelName'); const contract = network.getContract('chaincodeName'); diff --git a/pkg/client/example_test.go b/pkg/client/example_test.go index 4f7a63ba7..086cfc499 100644 --- a/pkg/client/example_test.go +++ b/pkg/client/example_test.go @@ -9,6 +9,7 @@ import ( "os" "github.com/hyperledger/fabric-gateway/pkg/client" + "github.com/hyperledger/fabric-gateway/pkg/hash" "github.com/hyperledger/fabric-gateway/pkg/identity" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -25,7 +26,8 @@ func Example() { sign := NewSign() // Create a Gateway connection for a specific client identity. - gateway, err := client.Connect(id, client.WithSign(sign), client.WithClientConnection(clientConnection)) + gateway, err := client.Connect(id, client.WithSign(sign), client.WithHash(hash.SHA256), + client.WithClientConnection(clientConnection)) panicOnError(err) defer gateway.Close()