Skip to content

Commit

Permalink
Add off-chain-data go client application
Browse files Browse the repository at this point in the history
Created project structure, fixed typos, added connect.go and started
working on getAllAssets.go.

Signed-off-by: Stanislav Jakuschevskij <stas@two-giants.com>
  • Loading branch information
twoGiants committed Nov 11, 2024
1 parent 9b199d4 commit 465255a
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 5 deletions.
6 changes: 3 additions & 3 deletions asset-transfer-private-data/application-gateway-go/connect.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2022 IBM All Rights Reserved.
Copyright 2024 IBM All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -77,8 +77,8 @@ func newIdentity(certDirectoryPath, mspId string) *identity.X509Identity {
}

// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign(keyDirectoryPash string) identity.Sign {
privateKeyPEM, err := readFirstFile(keyDirectoryPash)
func newSign(keyDirectoryPath string) identity.Sign {
privateKeyPEM, err := readFirstFile(keyDirectoryPath)
if err != nil {
panic(fmt.Errorf("failed to read private key file: %w", err))
}
Expand Down
4 changes: 2 additions & 2 deletions off_chain_data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The client application provides several "commands" that can be invoked using the

To keep the sample code concise, the **listen** command writes ledger updates to an output file named `store.log` in the current working directory (which for the Java sample is the `application-java/app` directory). A real implementation could write ledger updates directly to an off-chain data store of choice. You can inspect the information captured in this file as you run the sample.

Note that the **listen** command is is restartable and will resume event listening after the last successfully processed block / transaction. This is achieved using a checkpointer to persist the current listening position. Checkpoint state is persisted to a file named `checkpoint.json` in the current working directory. If no checkpoint state is present, event listening begins from the start of the ledger (block number zero).
Note that the **listen** command is restartable and will resume event listening after the last successfully processed block / transaction. This is achieved using a checkpointer to persist the current listening position. Checkpoint state is persisted to a file named `checkpoint.json` in the current working directory. If no checkpoint state is present, event listening begins from the start of the ledger (block number zero).

### Smart Contract

Expand Down Expand Up @@ -112,4 +112,4 @@ When you are finished, you can bring down the test network (from the `test-netwo

```
./network.sh down
```
```
7 changes: 7 additions & 0 deletions off_chain_data/application-go/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "fmt"

func main() {
fmt.Println("Hello World!")
}
142 changes: 142 additions & 0 deletions off_chain_data/application-go/connect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
Copyright 2024 IBM All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package main

import (
"crypto/x509"
"fmt"
"os"
"path"
"time"

"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"
)

const peerName = "peer0.org1.example.com"

var (
channelName = envOrDefault("CHANNEL_NAME", "mychannel")
chaincodeName = envOrDefault("CHAINCODE_NAME", "basic")
mspID = envOrDefault("MSP_ID", "Org1MSP")

// Path to crypto materials.
cryptoPath = envOrDefault("CRYPTO_PATH", "../../test-network/organizations/peerOrganizations/org1.example.com")

// Path to user private key directory.
keyDirectoryPath = envOrDefault("KEY_DIRECTORY_PATH", cryptoPath+"/users/User1@org1.example.com/msp/keystore")

// Path to user certificate.
certPath = envOrDefault("CERT_PATH", cryptoPath+"/users/User1@org1.example.com/msp/signcerts/cert.pem")

// Path to peer tls certificate.
tlsCertPath = envOrDefault("TLS_CERT_PATH", cryptoPath+"/peers/peer0.org1.example.com/tls/ca.crt")

// Gateway peer endpoint.
peerEndpoint = envOrDefault("PEER_ENDPOINT", "dns:///localhost:7051")

// Gateway peer SSL host name override.
peerHostAlias = envOrDefault("PEER_HOST_ALIAS", peerName)
)

func envOrDefault(key, defaultValue string) string {
result := os.Getenv(key)
if result == "" {
return defaultValue
}
return result
}

func newGrpcConnection() *grpc.ClientConn {
certificatePEM, err := os.ReadFile(tlsCertPath)
if err != nil {
panic(fmt.Errorf("failed to read TLS certificate file: %w", err))
}

certificate, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}

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

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

return connection
}

func newConnectOptions(clientConnection *grpc.ClientConn) (identity.Identity, []client.ConnectOption) {
return newIdentity(), []client.ConnectOption{
client.WithSign(newSign()),
client.WithHash(hash.SHA256),
client.WithClientConnection(clientConnection),
client.WithEvaluateTimeout(5 * time.Second),
client.WithEndorseTimeout(15 * time.Second),
client.WithSubmitTimeout(5 * time.Second),
client.WithCommitStatusTimeout(1 * time.Minute),
}
}

func newIdentity() *identity.X509Identity {
certificatePEM, err := os.ReadFile(certPath)
if err != nil {
panic(fmt.Errorf("failed to read certificate file: %w", err))
}

certificate, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}

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

return id
}

func newSign() identity.Sign {
privateKeyPEM, err := readFirstFile(keyDirectoryPath)
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 readFirstFile(dirPath string) ([]byte, error) {
dir, err := os.Open(dirPath)
if err != nil {
return nil, err
}

fileNames, err := dir.Readdirnames(1)
if err != nil {
return nil, err
}

return os.ReadFile(path.Join(dirPath, fileNames[0]))
}
15 changes: 15 additions & 0 deletions off_chain_data/application-go/getAllAssets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"github.com/hyperledger/fabric-gateway/pkg/client"
"google.golang.org/grpc"
)

func getAllAssets(clientConnection *grpc.ClientConn) {
id, options := newConnectOptions(clientConnection)
gateway, err := client.Connect(id, options...)
if err != nil {
panic((err))
}
defer gateway.Close()
}
19 changes: 19 additions & 0 deletions off_chain_data/application-go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module offChainData

go 1.22.0

require (
github.com/hyperledger/fabric-gateway v1.7.0
google.golang.org/grpc v1.67.1
)

require (
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/protobuf v1.35.1 // indirect
)
32 changes: 32 additions & 0 deletions off_chain_data/application-go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hyperledger/fabric-gateway v1.7.0 h1:bd1quU8qYPYqYO69m1tPIDSjB+D+u/rBJfE1eWFcpjY=
github.com/hyperledger/fabric-gateway v1.7.0/go.mod h1:TItDGnq71eJcgz5TW+m5Sq3kWGp0AEI1HPCNxj0Eu7k=
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4 h1:YJrd+gMaeY0/vsN0aS0QkEKTivGoUnSRIXxGJ7KI+Pc=
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4/go.mod h1:bau/6AJhvEcu9GKKYHlDXAxXKzYNfhP6xu2GXuxEcFk=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 comments on commit 465255a

Please sign in to comment.