Used asset-transfer-basic chaincode

Signed-off-by: sapthasurendran <saptha.surendran@ibm.com>
This commit is contained in:
sapthasurendran 2022-06-28 13:49:42 +05:30
parent ce8d1ddc5b
commit f3949f316c
8 changed files with 266 additions and 41 deletions

1
hsm-samples-gateway/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
crypto-material

View file

@ -5,10 +5,29 @@ new embedded Gateway in Fabric.
The samples will only run against Fabric v2.4 and higher. The samples will only run against Fabric v2.4 and higher.
This will create a local docker network comprising five peers across three organisations and a single ordering node.
Sample client applications are available to demonstrate the features of the Fabric Gateway and associated SDKs using this network. Sample client applications are available to demonstrate the features of the Fabric Gateway and associated SDKs using this network.
## Running the sample
The Fabric test network is used to deploy and run this sample. Follow these steps in order:
1. Create the test network and a channel (from the `test-network` folder).
```
./network.sh up createChannel -ca
```
1. Deploy one of the smart contract implementations (from the `test-network` folder).
```
# To deploy the TypeScript chaincode implementation
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-typescript/ -ccl typescript
# To deploy the Go chaincode implementation
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go
# To deploy the Java chaincode implementation
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
```
## C Compilers ## C Compilers
In order for the client application to run successfully you must ensure you have C compilers and Python 3 (Note that Python 2 may still work however Python 2 is out of support and could stop working in the future) installed otherwise the node dependency `pkcs11js` will not be built and the application will fail. The failure will have an error such as In order for the client application to run successfully you must ensure you have C compilers and Python 3 (Note that Python 2 may still work however Python 2 is out of support and could stop working in the future) installed otherwise the node dependency `pkcs11js` will not be built and the application will fail. The failure will have an error such as
@ -95,6 +114,8 @@ npm run build
npm start npm start
``` ```
When you are finished running the samples, the local docker network can be brought down with the following command: When you are finished running the samples, the local test-network can be brought down with the following command (from the `test-network` folder):
`docker rm -f $(docker ps -aq) && docker network prune --force` ```
./network.sh down
```

View file

@ -0,0 +1 @@
fabric-ca-client-config.yaml

View file

@ -0,0 +1,174 @@
#############################################################################
# This is a configuration file for the fabric-ca-client command.
#
# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES
# ------------------------------------------------
# Each configuration element can be overridden via command line
# arguments or environment variables. The precedence for determining
# the value of each element is as follows:
# 1) command line argument
# Examples:
# a) --url https://localhost:7054
# To set the fabric-ca server url
# b) --tls.client.certfile certfile.pem
# To set the client certificate for TLS
# 2) environment variable
# Examples:
# a) FABRIC_CA_CLIENT_URL=https://localhost:7054
# To set the fabric-ca server url
# b) FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE=certfile.pem
# To set the client certificate for TLS
# 3) configuration file
# 4) default value (if there is one)
# All default values are shown beside each element below.
#
# FILE NAME ELEMENTS
# ------------------
# The value of all fields whose name ends with "file" or "files" are
# name or names of other files.
# For example, see "tls.certfiles" and "tls.client.certfile".
# The value of each of these fields can be a simple filename, a
# relative path, or an absolute path. If the value is not an
# absolute path, it is interpreted as being relative to the location
# of this configuration file.
#
#############################################################################
#############################################################################
# Client Configuration
#############################################################################
# URL of the Fabric-ca-server (default: http://localhost:7054)
url: http://localhost:7054
# Membership Service Provider (MSP) directory
# This is useful when the client is used to enroll a peer or orderer, so
# that the enrollment artifacts are stored in the format expected by MSP.
mspdir: caadmin
#############################################################################
# TLS section for secure socket connection
#
# certfiles - PEM-encoded list of trusted root certificate files
# client:
# certfile - PEM-encoded certificate file for when client authentication
# is enabled on server
# keyfile - PEM-encoded key file for when client authentication
# is enabled on server
#############################################################################
tls:
# TLS section for secure socket connection
certfiles:
client:
certfile:
keyfile:
#############################################################################
# Certificate Signing Request section for generating the CSR for an
# enrollment certificate (ECert)
#
# cn - Used by CAs to determine which domain the certificate is to be generated for
#
# keyrequest - Properties to use when generating a private key.
# algo - key generation algorithm to use
# size - size of key to generate
# reusekey - reuse existing key during reenrollment
#
# serialnumber - The serialnumber field, if specified, becomes part of the issued
# certificate's DN (Distinguished Name). For example, one use case for this is
# a company with its own CA (Certificate Authority) which issues certificates
# to its employees and wants to include the employee's serial number in the DN
# of its issued certificates.
# WARNING: The serialnumber field should not be confused with the certificate's
# serial number which is set by the CA but is not a component of the
# certificate's DN.
#
# names - A list of name objects. Each name object should contain at least one
# "C", "L", "O", or "ST" value (or any combination of these) where these
# are abbreviations for the following:
# "C": country
# "L": locality or municipality (such as city or town name)
# "O": organization
# "OU": organizational unit, such as the department responsible for owning the key;
# it can also be used for a "Doing Business As" (DBS) name
# "ST": the state or province
#
# Note that the "OU" or organizational units of an ECert are always set according
# to the values of the identities type and affiliation. OUs are calculated for an enroll
# as OU=<type>, OU=<affiliationRoot>, ..., OU=<affiliationLeaf>. For example, an identity
# of type "client" with an affiliation of "org1.dept2.team3" would have the following
# organizational units: OU=client, OU=org1, OU=dept2, OU=team3
#
# hosts - A list of host names for which the certificate should be valid
#
#############################################################################
csr:
cn: admin
keyrequest:
algo: ecdsa
size: 256
reusekey: false
serialnumber:
names:
- C: US
ST: North Carolina
L:
O: Hyperledger
OU: Fabric
hosts:
- tryfabric
#############################################################################
# Registration section used to register a new identity with fabric-ca server
#
# name - Unique name of the identity
# type - Type of identity being registered (e.g. 'peer, app, user')
# affiliation - The identity's affiliation
# maxenrollments - The maximum number of times the secret can be reused to enroll.
# Specially, -1 means unlimited; 0 means to use CA's max enrollment
# value.
# attributes - List of name/value pairs of attribute for identity
#############################################################################
id:
name:
type:
affiliation:
maxenrollments: 0
attributes:
# - name:
# value:
#############################################################################
# Enrollment section used to enroll an identity with fabric-ca server
#
# profile - Name of the signing profile to use in issuing the certificate
# label - Label to use in HSM operations
#############################################################################
enrollment:
profile:
label:
#############################################################################
# Name of the CA to connect to within the fabric-ca server
#############################################################################
caname:
#############################################################################
# BCCSP (BlockChain Crypto Service Provider) section allows to select which
# crypto implementation library to use
#############################################################################
bccsp:
default: PKCS11
PKCS11:
Library: REPLACE_ME_HSMLIB
Pin: 98765432
Label: ForFabric
hash: SHA2
security: 256
# sw:
# hash: SHA2
# security: 256
# filekeystore:
# # The directory used for the software file-based keystore
# keystore: msp/keystore

View file

@ -10,9 +10,11 @@ SPDX-License-Identifier: Apache-2.0
package main package main
import ( import (
"bytes"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/sha256" "crypto/sha256"
"encoding/json"
"encoding/pem" "encoding/pem"
"errors" "errors"
"os" "os"
@ -30,12 +32,14 @@ import (
const ( const (
mspID = "Org1MSP" mspID = "Org1MSP"
cryptoPath = "../../scenario/fixtures/crypto-material/" certPath = "../crypto-material/hsm/HSMUser/signcerts/cert.pem"
certPath = cryptoPath + "hsm/HSMUser/signcerts/cert.pem" tlsCertPath = "../../test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
tlsCertPath = cryptoPath + "crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
peerEndpoint = "localhost:7051" peerEndpoint = "localhost:7051"
) )
var now = time.Now()
var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)
func main() { func main() {
fmt.Println("Running the GO HSM Sample") fmt.Println("Running the GO HSM Sample")
@ -66,34 +70,34 @@ func main() {
} }
defer gateway.Close() defer gateway.Close()
exampleSubmit(gateway) exampleTransaction(gateway)
fmt.Println() fmt.Println()
fmt.Println("Go HSM Sample Completed Successfully") fmt.Println("Go HSM Sample completed successfully")
fmt.Println() fmt.Println()
} }
func exampleSubmit(gateway *client.Gateway) { func exampleTransaction(gateway *client.Gateway) {
network := gateway.GetNetwork("mychannel") network := gateway.GetNetwork("mychannel")
contract := network.GetContract("basic") contract := network.GetContract("basic")
timestamp := time.Now().String() fmt.Printf("Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments \n")
fmt.Printf("Submitting \"put\" transaction with arguments: time, %s\n", timestamp)
// Submit transaction, blocking until the transaction has been committed on the ledger _, err := contract.SubmitTransaction("CreateAsset", assetId, "yellow", "5", "Tom", "1300")
submitResult, err := contract.SubmitTransaction("put", "time", timestamp)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to submit transaction: %w", err)) panic(fmt.Errorf("failed to submit transaction: %w", err))
} }
fmt.Printf("Submit result: %s\n", string(submitResult)) fmt.Printf("*** Transaction committed successfully\n")
fmt.Println("Evaluating \"get\" query with arguments: time")
evaluateResult, err := contract.EvaluateTransaction("get", "time") fmt.Printf("Evaluate Transaction: ReadAsset, function returns asset attributes\n")
evaluateResult, err := contract.EvaluateTransaction("ReadAsset", assetId)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to evaluate transaction: %w", err)) panic(fmt.Errorf("failed to evaluate transaction: %w", err))
} }
result := formatJSON(evaluateResult)
fmt.Printf("Query result = %s\n", string(evaluateResult)) fmt.Printf("*** Result:%s\n", result)
} }
// newGrpcConnection creates a gRPC connection to the Gateway server. // newGrpcConnection creates a gRPC connection to the Gateway server.
@ -185,3 +189,12 @@ func findSoftHSMLibrary() string {
panic("No SoftHSM library can be found. The Sample requires SoftHSM to be installed") panic("No SoftHSM library can be found. The Sample requires SoftHSM to be installed")
} }
// 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()
}

View file

@ -18,7 +18,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.3.0", "@grpc/grpc-js": "^1.3.0",
"@hyperledger/fabric-gateway": "file:../../node/fabric-gateway-dev.tgz", "@hyperledger/fabric-gateway": "^1.0.0",
"jsrsasign": "^10.3.0" "jsrsasign": "^10.3.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -10,17 +10,20 @@ import { connect, Gateway, HSMSigner, HSMSignerFactory, HSMSignerOptions, signer
import * as fs from 'fs'; import * as fs from 'fs';
import * as jsrsa from 'jsrsasign'; import * as jsrsa from 'jsrsasign';
import * as path from 'path'; import * as path from 'path';
import { TextDecoder } from 'util';
const mspId = 'Org1MSP'; const mspId = 'Org1MSP';
const user = 'HSMUser'; const user = 'HSMUser';
const assetId = `asset${Date.now()}`;
const utf8Decoder = new TextDecoder();
// Sample uses fabric-ca-client generated HSM identities, certificate is located in the signcerts directory // Sample uses fabric-ca-client generated HSM identities, certificate is located in the signcerts directory
// and has been stored in a directory of the name given to the identity. // and has been stored in a directory of the name given to the identity.
const cryptoPath = path.resolve(__dirname, '..', '..', '..', 'scenario', 'fixtures', 'crypto-material');
const certPath = path.resolve(cryptoPath, 'hsm', user, 'signcerts', 'cert.pem');
const tlsCertPath = path.resolve(cryptoPath, 'crypto-config', 'peerOrganizations', 'org1.example.com', 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt'); const certPath = path.resolve(__dirname, '..', '..', 'crypto-material', 'hsm', user, 'signcerts', 'cert.pem');
const peerEndpoint = 'localhost:7051'
const tlsCertPath = path.resolve('..', '..','test-network','organizations','peerOrganizations', 'org1.example.com', 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt');
const peerEndpoint = 'localhost:7051';
async function main() { async function main() {
console.log('\nRunning the Node HSM sample'); console.log('\nRunning the Node HSM sample');
@ -43,7 +46,7 @@ async function main() {
}); });
try { try {
await exampleSubmit(gateway); await exampleTransaction(gateway);
console.log(); console.log();
console.log('Node HSM sample completed successfully'); console.log('Node HSM sample completed successfully');
} finally { } finally {
@ -55,22 +58,30 @@ async function main() {
} }
} }
async function exampleSubmit(gateway: Gateway) { async function exampleTransaction(gateway: Gateway):Promise<void> {
const network = gateway.getNetwork('mychannel'); const network = gateway.getNetwork('mychannel');
const contract = network.getContract('basic'); const contract = network.getContract('basic');
const timestamp = new Date().toISOString(); console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments');
console.log('Submitting "put" transaction with arguments: time,', timestamp);
// Submit a transaction, blocking until the transaction has been committed on the ledger await contract.submitTransaction(
const submitResult = await contract.submitTransaction('put', 'time', timestamp); 'CreateAsset',
assetId,
'yellow',
'5',
'Tom',
'1300',
);
console.log('Submit result:', submitResult.toString()); console.log('*** Transaction committed successfully');
console.log('Evaluating "get" query with arguments: time');
const evaluateResult = await contract.evaluateTransaction('get', 'time'); console.log('\n--> Evaluate Transaction: ReadAsset, function returns asset attributes');
console.log('Query result:', evaluateResult.toString()); const resultBytes = await contract.evaluateTransaction('ReadAsset', assetId);
const resultJson = utf8Decoder.decode(resultBytes);
const result = JSON.parse(resultJson);
console.log('*** Result:', result);
} }
async function newGrpcConnection(): Promise<grpc.Client> { async function newGrpcConnection(): Promise<grpc.Client> {

View file

@ -2,8 +2,9 @@
set -eo pipefail set -eo pipefail
# define the CA setup # define the CA setup
CA_HOST=127.0.0.1 CA_HOST=localhost
CA_URL=${CA_HOST}:7054 CA_URL=${CA_HOST}:7054
TLS_CERT='../../test-network/organizations/fabric-ca/org1/tls-cert.pem'
# try to locate the Soft HSM library # try to locate the Soft HSM library
POSSIBLE_LIB_LOC=('/usr/lib/softhsm/libsofthsm2.so' \ POSSIBLE_LIB_LOC=('/usr/lib/softhsm/libsofthsm2.so' \
@ -26,19 +27,22 @@ HSM2_CONF=$HOME/softhsm2.conf
# Update the client config file to point to the softhsm pkcs11 library # Update the client config file to point to the softhsm pkcs11 library
# which must be in $HOME/softhsm directory # which must be in $HOME/softhsm directory
CLIENT_CONFIG_TEMPLATE=./ca-client-config/fabric-ca-client-config-template.yaml echo 'directory' $PWD
CLIENT_CONFIG=./ca-client-config/fabric-ca-client-config.yaml
CLIENT_CONFIG_TEMPLATE=../ca-client-config/fabric-ca-client-config-template.yaml
CLIENT_CONFIG=../ca-client-config/fabric-ca-client-config.yaml
cp $CLIENT_CONFIG_TEMPLATE $CLIENT_CONFIG cp $CLIENT_CONFIG_TEMPLATE $CLIENT_CONFIG
sed -i s+REPLACE_ME_HSMLIB+${HSM2_LIB}+g $CLIENT_CONFIG sed -i '' -e s+REPLACE_ME_HSMLIB+${HSM2_LIB}+g $CLIENT_CONFIG
# create the users, remove any existing users # create the users, remove any existing users
CRYPTO_PATH=$PWD/crypto-material/hsm CRYPTO_PATH=$PWD/../crypto-material/hsm
[ -d $CRYPTO_PATH ] && rm -fr $CRYPTO_PATH [ -d $CRYPTO_PATH ] && rm -fr $CRYPTO_PATH
# user passed in as parameter # user passed in as parameter
CAADMIN=admin CAADMIN=admin
CAADMIN_PW=adminpw CAADMIN_PW=adminpw
HSMUSER=$1 HSMUSER=$1
SOFTHSM2_CONF=$HSM2_CONF fabric-ca-client enroll -c $CLIENT_CONFIG -u http://$CAADMIN:$CAADMIN_PW@$CA_URL --mspdir $CRYPTO_PATH/$CAADMIN --csr.hosts example.com
! SOFTHSM2_CONF=$HSM2_CONF fabric-ca-client register -c $CLIENT_CONFIG --mspdir $CRYPTO_PATH/$CAADMIN --id.name $HSMUSER --id.secret $HSMUSER --id.type client --caname ca-org1 --id.maxenrollments 0 -m example.com -u http://$CA_URL && echo user probably already registered, continuing SOFTHSM2_CONF=$HSM2_CONF fabric-ca-client enroll -c $CLIENT_CONFIG -u https://$CAADMIN:$CAADMIN_PW@$CA_URL --mspdir $CRYPTO_PATH/$CAADMIN --csr.hosts example.com --tls.certfiles ${TLS_CERT}
SOFTHSM2_CONF=$HSM2_CONF fabric-ca-client enroll -c $CLIENT_CONFIG -u http://$HSMUSER:$HSMUSER@$CA_URL --mspdir $CRYPTO_PATH/$HSMUSER --csr.hosts example.com ! SOFTHSM2_CONF=$HSM2_CONF fabric-ca-client register -c $CLIENT_CONFIG --mspdir $CRYPTO_PATH/$CAADMIN --id.name $HSMUSER --id.secret $HSMUSER --id.type client --caname ca-org1 --id.maxenrollments 0 -m example.com -u https://$CA_URL --tls.certfiles ${TLS_CERT} && echo user probably already registered, continuing
SOFTHSM2_CONF=$HSM2_CONF fabric-ca-client enroll -c $CLIENT_CONFIG -u https://$HSMUSER:$HSMUSER@$CA_URL --mspdir $CRYPTO_PATH/$HSMUSER --csr.hosts example.com --tls.certfiles ${TLS_CERT}