mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-25 11:05:10 +00:00
Name changes
Signed-off-by: sapthasurendran <saptha.surendran@ibm.com>
This commit is contained in:
parent
a37f4523e0
commit
90cf860e50
13 changed files with 14 additions and 904 deletions
|
|
@ -1,10 +1,12 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
# script directory
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
# define the CA setup
|
# define the CA setup
|
||||||
CA_HOST=localhost
|
CA_HOST=localhost
|
||||||
CA_URL=${CA_HOST}:7054
|
CA_URL=${CA_HOST}:7054
|
||||||
TLS_CERT='../../test-network/organizations/fabric-ca/org1/tls-cert.pem'
|
|
||||||
|
TLS_CERT="${SCRIPT_DIR}/../../test-network/organizations/fabric-ca/org1/tls-cert.pem"
|
||||||
|
|
||||||
LocateHsmLib() {
|
LocateHsmLib() {
|
||||||
if [[ -n "${PKCS11_LIB}" && -f "${PKCS11_LIB}" ]]; then
|
if [[ -n "${PKCS11_LIB}" && -f "${PKCS11_LIB}" ]]; then
|
||||||
|
|
@ -27,35 +29,34 @@ LocateHsmLib() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HSM2_LIB=$(LocateHsmLib)
|
HSM2_LIB=$(LocateHsmLib)
|
||||||
[ -z $HSM2_LIB ] && echo No SoftHSM PKCS11 Library found, ensure you have installed softhsm2 && exit 1
|
[ -z "$HSM2_LIB" ] && echo No SoftHSM PKCS11 Library found, ensure you have installed softhsm2 && exit 1
|
||||||
|
|
||||||
# create a softhsm2.conf file if one doesn't exist
|
# create a softhsm2.conf file if one doesn't exist
|
||||||
HSM2_CONF=$HOME/softhsm2.conf
|
HSM2_CONF=$HOME/softhsm2.conf
|
||||||
[ ! -f $HSM2_CONF ] && echo directories.tokendir = /tmp > $HSM2_CONF
|
[ ! -f "$HSM2_CONF" ] && echo directories.tokendir = /tmp > "$HSM2_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
|
||||||
echo 'directory' $PWD
|
|
||||||
|
|
||||||
CLIENT_CONFIG_TEMPLATE=../ca-client-config/fabric-ca-client-config-template.yaml
|
CLIENT_CONFIG_TEMPLATE=../ca-client-config/fabric-ca-client-config-template.yaml
|
||||||
CLIENT_CONFIG=../ca-client-config/fabric-ca-client-config.yaml
|
CLIENT_CONFIG=../ca-client-config/fabric-ca-client-config.yaml
|
||||||
cp $CLIENT_CONFIG_TEMPLATE $CLIENT_CONFIG
|
cp $CLIENT_CONFIG_TEMPLATE $CLIENT_CONFIG
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
sed -i '' s+REPLACE_ME_HSMLIB+${HSM2_LIB}+g $CLIENT_CONFIG
|
sed -i '' s+REPLACE_ME_HSMLIB+"${HSM2_LIB}"+g $CLIENT_CONFIG
|
||||||
else
|
else
|
||||||
sed -i s+REPLACE_ME_HSMLIB+${HSM2_LIB}+g $CLIENT_CONFIG
|
sed -i s+REPLACE_ME_HSMLIB+"${HSM2_LIB}"+g $CLIENT_CONFIG
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 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 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 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 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 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}
|
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}"
|
||||||
1
hsm-gateway-applications/.gitignore
vendored
1
hsm-gateway-applications/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
||||||
crypto-material
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
# Fabric Gateway HSM Samples
|
|
||||||
|
|
||||||
The samples show how to create client applications that invoke transactions with HSM Identities using the
|
|
||||||
new embedded Gateway in Fabric.
|
|
||||||
|
|
||||||
The samples will only run against Fabric v2.4 and higher.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
```
|
|
||||||
Error: Cannot find module 'pkcs11js'
|
|
||||||
```
|
|
||||||
|
|
||||||
how to install the required C Compilers and Python will depend on your operating system and version.
|
|
||||||
|
|
||||||
## Install SoftHSM
|
|
||||||
|
|
||||||
In order to run the application in the absence of a real HSM, a software
|
|
||||||
emulator of the PKCS#11 interface is required.
|
|
||||||
For more information please refer to [SoftHSM](https://www.opendnssec.org/softhsm/).
|
|
||||||
|
|
||||||
SoftHSM can either be installed using the package manager for your host system:
|
|
||||||
|
|
||||||
* Ubuntu: `sudo apt install softhsm2`
|
|
||||||
* macOS: `brew install softhsm`
|
|
||||||
* Windows: **unsupported**
|
|
||||||
|
|
||||||
Or compiled and installed from source:
|
|
||||||
|
|
||||||
1. install openssl 1.0.0+ or botan 1.10.0+
|
|
||||||
2. download the source code from <https://dist.opendnssec.org/source/softhsm-2.5.0.tar.gz>
|
|
||||||
3. `tar -xvf softhsm-2.5.0.tar.gz`
|
|
||||||
4. `cd softhsm-2.5.0`
|
|
||||||
5. `./configure --disable-gost` (would require additional libraries, turn it off unless you need 'gost' algorithm support for the Russian market)
|
|
||||||
6. `make`
|
|
||||||
7. `sudo make install`
|
|
||||||
|
|
||||||
## Initialize a token to store keys in SoftHSM
|
|
||||||
|
|
||||||
If you have not initialized a token previously (or it has been deleted) then you will need to perform this one time operation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo directories.tokendir = /tmp > $HOME/softhsm2.conf
|
|
||||||
export SOFTHSM2_CONF=$HOME/softhsm2.conf
|
|
||||||
softhsm2-util --init-token --slot 0 --label "ForFabric" --pin 98765432 --so-pin 1234
|
|
||||||
```
|
|
||||||
|
|
||||||
This will create a SoftHSM configuration file called `softhsm2.conf` and will be stored in the home directory. This is
|
|
||||||
where the sample expects to find a SoftHSM configuration file
|
|
||||||
|
|
||||||
The Security Officer PIN, specified with the `--so-pin` flag, can be used to re-initialize the token,
|
|
||||||
and the user PIN (see below), specified with the `--pin` flag, is used by applications to access the token for
|
|
||||||
generating and retrieving keys.
|
|
||||||
|
|
||||||
## Install PKCS#11 enabled fabric-ca-client binary
|
|
||||||
To be able to register and enroll identities using an HSM you need a PKCS#11 enabled version of `fabric-ca-client`
|
|
||||||
To install this use the following command
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install -tags 'pkcs11' github.com/hyperledger/fabric-ca/cmd/fabric-ca-client@latest
|
|
||||||
```
|
|
||||||
## Enroll the HSM User
|
|
||||||
|
|
||||||
A user, `HSMUser`, who is HSM managed needs to be registered then enrolled for the sample.
|
|
||||||
|
|
||||||
If the "standard" PKCS11 library locations checked for by the script don't include the library(libsofthsm2.so) location for your environment set the `PKCS11_LIB` environment variable to define the library location.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd scripts
|
|
||||||
PKCS11_LIB='<path to PKCS11 library location>' ./generate-hsm-user.sh HSMUser
|
|
||||||
```
|
|
||||||
|
|
||||||
This will register a user `HSMUser` with the CA in Org1 (if not already registered) and then enroll that user which will
|
|
||||||
generate a certificate on the file system for use by the sample. The private key is stored in SoftHSM
|
|
||||||
|
|
||||||
### Go SDK
|
|
||||||
|
|
||||||
For HSM support you need to ensure you include the `pkcs11` build tag.
|
|
||||||
|
|
||||||
```
|
|
||||||
cd hsm-gateway-applications/go
|
|
||||||
go run -tags pkcs11 hsm-sample.go
|
|
||||||
```
|
|
||||||
|
|
||||||
### Node SDK
|
|
||||||
|
|
||||||
```
|
|
||||||
cd hsm-gateway-applications/node
|
|
||||||
npm install
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
When you are finished running the samples, the local test-network can be brought down with the following command (from the `test-network` folder):
|
|
||||||
|
|
||||||
```
|
|
||||||
./network.sh down
|
|
||||||
```
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
fabric-ca-client-config.yaml
|
|
||||||
|
|
@ -1,168 +0,0 @@
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# 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
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
module github.com/hyperledger/fabric-samples/asset-transfer-basic/application-gateway-hsm/go
|
|
||||||
|
|
||||||
go 1.18
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/hyperledger/fabric-gateway v1.1.0
|
|
||||||
google.golang.org/grpc v1.47.0
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
|
||||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.0.0-20220615102044-467be1c7b2e7 // indirect
|
|
||||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
|
||||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
|
||||||
golang.org/x/text v0.3.7 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 // indirect
|
|
||||||
google.golang.org/protobuf v1.28.0 // indirect
|
|
||||||
)
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
|
||||||
github.com/hyperledger/fabric-gateway v1.1.0 h1:zQ6BjUCBCUUbPQNI/B/rzBD6QRvaqWxEIYAI6gtUZ14=
|
|
||||||
github.com/hyperledger/fabric-gateway v1.1.0/go.mod h1:A+MuROWOKhmUsYVO2PREggHLPgPAXaudwCoZRpuSeqs=
|
|
||||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.0.0-20220615102044-467be1c7b2e7 h1:loYDK6Vrf7z3fff6YBVKFkFeCGCoKr8O2ed02CESBUQ=
|
|
||||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.0.0-20220615102044-467be1c7b2e7/go.mod h1:smwq1q6eKByqQAp0SYdVvE1MvDoneF373j11XwWajgA=
|
|
||||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
|
|
||||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 h1:a221mAAEAzq4Lz6ZWRkcS8ptb2mxoxYSt4N68aRyQHM=
|
|
||||||
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
|
||||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
|
||||||
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
|
|
||||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
|
|
@ -1,200 +0,0 @@
|
||||||
//go:build pkcs11
|
|
||||||
// +build pkcs11
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright IBM Corp. All Rights Reserved.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/pem"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hyperledger/fabric-gateway/pkg/client"
|
|
||||||
"github.com/hyperledger/fabric-gateway/pkg/identity"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
mspID = "Org1MSP"
|
|
||||||
certPath = "../crypto-material/hsm/HSMUser/signcerts/cert.pem"
|
|
||||||
tlsCertPath = "../../test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
|
|
||||||
peerEndpoint = "localhost:7051"
|
|
||||||
)
|
|
||||||
|
|
||||||
var now = time.Now()
|
|
||||||
var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println("Running the GO HSM Sample")
|
|
||||||
|
|
||||||
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
|
||||||
clientConnection := newGrpcConnection()
|
|
||||||
defer clientConnection.Close()
|
|
||||||
|
|
||||||
hsmSignerFactory, err := identity.NewHSMSignerFactory(findSoftHSMLibrary())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer hsmSignerFactory.Dispose()
|
|
||||||
|
|
||||||
certificatePEM, err := ioutil.ReadFile(certPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
id := newIdentity(certificatePEM)
|
|
||||||
ski := getSKI(certificatePEM)
|
|
||||||
hsmSign, hsmSignClose := newHSMSign(hsmSignerFactory, ski)
|
|
||||||
defer hsmSignClose()
|
|
||||||
|
|
||||||
// Create a Gateway connection for a specific client identity
|
|
||||||
gateway, err := client.Connect(id, client.WithSign(hsmSign), client.WithClientConnection(clientConnection))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer gateway.Close()
|
|
||||||
|
|
||||||
exampleTransaction(gateway)
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("Go HSM Sample completed successfully")
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
func exampleTransaction(gateway *client.Gateway) {
|
|
||||||
network := gateway.GetNetwork("mychannel")
|
|
||||||
contract := network.GetContract("basic")
|
|
||||||
|
|
||||||
fmt.Printf("Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments \n")
|
|
||||||
|
|
||||||
_, err := contract.SubmitTransaction("CreateAsset", assetId, "yellow", "5", "Tom", "1300")
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to submit transaction: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("*** Transaction committed successfully\n")
|
|
||||||
|
|
||||||
fmt.Printf("Evaluate Transaction: ReadAsset, function returns asset attributes\n")
|
|
||||||
|
|
||||||
evaluateResult, err := contract.EvaluateTransaction("ReadAsset", assetId)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
|
|
||||||
}
|
|
||||||
result := formatJSON(evaluateResult)
|
|
||||||
|
|
||||||
fmt.Printf("*** Result:%s\n", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// newGrpcConnection creates a gRPC connection to the Gateway server.
|
|
||||||
func newGrpcConnection() *grpc.ClientConn {
|
|
||||||
certificate, err := loadCertificate(tlsCertPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to obtain commit status: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
certPool := x509.NewCertPool()
|
|
||||||
certPool.AddCert(certificate)
|
|
||||||
transportCredentials := credentials.NewClientTLSFromCert(certPool, "peer0.org1.example.com")
|
|
||||||
|
|
||||||
connection, err := grpc.Dial(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection
|
|
||||||
}
|
|
||||||
|
|
||||||
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
|
|
||||||
func newIdentity(certificatePEM []byte) *identity.X509Identity {
|
|
||||||
cert, err := identity.CertificateFromPEM(certificatePEM)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
id, err := identity.NewX509Identity(mspID, cert)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
// newHSMSign creates a function that generates a digital signature from a message digest using a private key.
|
|
||||||
func newHSMSign(h *identity.HSMSignerFactory, certPEM []byte) (identity.Sign, identity.HSMSignClose) {
|
|
||||||
opt := identity.HSMSignerOptions{
|
|
||||||
Label: "ForFabric",
|
|
||||||
Pin: "98765432",
|
|
||||||
Identifier: string(certPEM),
|
|
||||||
}
|
|
||||||
|
|
||||||
sign, close, err := h.NewHSMSigner(opt)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign, close
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadCertificate(filename string) (*x509.Certificate, error) {
|
|
||||||
certificatePEM, err := ioutil.ReadFile(filename) //#nosec G304
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return identity.CertificateFromPEM(certificatePEM)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSKI(certPEM []byte) []byte {
|
|
||||||
block, _ := pem.Decode(certPEM)
|
|
||||||
|
|
||||||
x590cert, _ := x509.ParseCertificate(block.Bytes)
|
|
||||||
pk := x590cert.PublicKey
|
|
||||||
|
|
||||||
return skiForKey(pk.(*ecdsa.PublicKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
func skiForKey(pk *ecdsa.PublicKey) []byte {
|
|
||||||
ski := sha256.Sum256(elliptic.Marshal(pk.Curve, pk.X, pk.Y))
|
|
||||||
return ski[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func findSoftHSMLibrary() string {
|
|
||||||
|
|
||||||
libraryLocations := []string{
|
|
||||||
"/usr/lib/softhsm/libsofthsm2.so",
|
|
||||||
"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so",
|
|
||||||
"/usr/local/lib/softhsm/libsofthsm2.so",
|
|
||||||
"/usr/lib/libacsp-pkcs11.so",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, libraryLocation := range libraryLocations {
|
|
||||||
if _, err := os.Stat(libraryLocation); !errors.Is(err, os.ErrNotExist) {
|
|
||||||
return libraryLocation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
env:
|
|
||||||
node: true
|
|
||||||
es2020: true
|
|
||||||
root: true
|
|
||||||
ignorePatterns:
|
|
||||||
- dist/
|
|
||||||
extends:
|
|
||||||
- eslint:recommended
|
|
||||||
rules:
|
|
||||||
indent:
|
|
||||||
- error
|
|
||||||
- 4
|
|
||||||
quotes:
|
|
||||||
- error
|
|
||||||
- single
|
|
||||||
overrides:
|
|
||||||
- files:
|
|
||||||
- "**/*.ts"
|
|
||||||
parser: "@typescript-eslint/parser"
|
|
||||||
parserOptions:
|
|
||||||
sourceType: module
|
|
||||||
ecmaFeatures:
|
|
||||||
impliedStrict: true
|
|
||||||
plugins:
|
|
||||||
- "@typescript-eslint"
|
|
||||||
extends:
|
|
||||||
- eslint:recommended
|
|
||||||
- plugin:@typescript-eslint/eslint-recommended
|
|
||||||
- plugin:@typescript-eslint/recommended
|
|
||||||
3
hsm-gateway-applications/node/.gitignore
vendored
3
hsm-gateway-applications/node/.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
dist/
|
|
||||||
node_modules/
|
|
||||||
package-lock.json
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"name": "gateway-hsm-sample",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"description": "",
|
|
||||||
"main": "dist/hsm-sample.js",
|
|
||||||
"engines": {
|
|
||||||
"node": "^14.15.0 || ^16.13.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"prepare": "npm run build",
|
|
||||||
"build": "npm-run-all clean compile lint",
|
|
||||||
"clean": "rimraf dist",
|
|
||||||
"compile": "tsc",
|
|
||||||
"lint": "eslint . --ext .ts",
|
|
||||||
"start": "SOFTHSM2_CONF=${HOME}/softhsm2.conf node dist/hsm-sample.js",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@grpc/grpc-js": "~1.6.7",
|
|
||||||
"@hyperledger/fabric-gateway": "^1.1.0",
|
|
||||||
"jsrsasign": "^10.3.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tsconfig/node14": "^1.0.1",
|
|
||||||
"@types/jsrsasign": "^9.0.3",
|
|
||||||
"@types/node": "^14.17.32",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
|
||||||
"@typescript-eslint/parser": "^5.3.0",
|
|
||||||
"eslint": "^8.1.0",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"typescript": "~4.5.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright IBM Corp. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as grpc from '@grpc/grpc-js';
|
|
||||||
import * as crypto from 'crypto';
|
|
||||||
import { connect, Gateway, HSMSigner, HSMSignerFactory, HSMSignerOptions, signers } from '@hyperledger/fabric-gateway';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as jsrsa from 'jsrsasign';
|
|
||||||
import * as path from 'path';
|
|
||||||
import { TextDecoder } from 'util';
|
|
||||||
|
|
||||||
const mspId = 'Org1MSP';
|
|
||||||
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
|
|
||||||
// and has been stored in a directory of the name given to the identity.
|
|
||||||
|
|
||||||
const certPath = path.resolve(__dirname, '..', '..', 'crypto-material', 'hsm', user, 'signcerts', 'cert.pem');
|
|
||||||
|
|
||||||
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() {
|
|
||||||
console.log('\nRunning the Node HSM sample');
|
|
||||||
|
|
||||||
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
|
||||||
const client = await newGrpcConnection();
|
|
||||||
|
|
||||||
// get an HSMSigner Factory. You only need to do this once for the application
|
|
||||||
const hsmSignerFactory = signers.newHSMSignerFactory(findSoftHSMPKCS11Lib());
|
|
||||||
const credentials = await fs.promises.readFile(certPath);
|
|
||||||
|
|
||||||
// Get the signer function and a close function. The close function closes the signer
|
|
||||||
// once there is no further need for it.
|
|
||||||
const {signer, close} = await newHSMSigner(hsmSignerFactory, credentials.toString());
|
|
||||||
|
|
||||||
const gateway = connect({
|
|
||||||
client,
|
|
||||||
identity: {mspId, credentials},
|
|
||||||
signer,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await exampleTransaction(gateway);
|
|
||||||
console.log();
|
|
||||||
console.log('Node HSM sample completed successfully');
|
|
||||||
} finally {
|
|
||||||
gateway.close();
|
|
||||||
client.close();
|
|
||||||
|
|
||||||
// close the HSM Signer
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function exampleTransaction(gateway: Gateway):Promise<void> {
|
|
||||||
const network = gateway.getNetwork('mychannel');
|
|
||||||
const contract = network.getContract('basic');
|
|
||||||
|
|
||||||
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments');
|
|
||||||
|
|
||||||
await contract.submitTransaction(
|
|
||||||
'CreateAsset',
|
|
||||||
assetId,
|
|
||||||
'yellow',
|
|
||||||
'5',
|
|
||||||
'Tom',
|
|
||||||
'1300',
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('*** Transaction committed successfully');
|
|
||||||
|
|
||||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns asset attributes');
|
|
||||||
|
|
||||||
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> {
|
|
||||||
const tlsRootCert = await fs.promises.readFile(tlsCertPath);
|
|
||||||
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert);
|
|
||||||
|
|
||||||
return new grpc.Client(peerEndpoint, tlsCredentials, {
|
|
||||||
'grpc.ssl_target_name_override': 'peer0.org1.example.com'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new HSM Signer
|
|
||||||
async function newHSMSigner(hsmSignerFactory: HSMSignerFactory, certificatePEM: string): Promise<HSMSigner> {
|
|
||||||
const ski = getSKIFromCertificate(certificatePEM);
|
|
||||||
|
|
||||||
// Options for the signer based on using SoftHSM with Token initialized as follows
|
|
||||||
// softhsm2-util --init-token --slot 0 --label "ForFabric" --pin 98765432 --so-pin 1234
|
|
||||||
const hsmSignerOptions: HSMSignerOptions = {
|
|
||||||
label: 'ForFabric',
|
|
||||||
pin: '98765432',
|
|
||||||
identifier: ski
|
|
||||||
}
|
|
||||||
return hsmSignerFactory.newSigner(hsmSignerOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility to find the SoftHSM PKCS11 library as it's location can vary based on
|
|
||||||
// operating system and version
|
|
||||||
function findSoftHSMPKCS11Lib(): string {
|
|
||||||
const commonSoftHSMPathNames = [
|
|
||||||
'/usr/lib/softhsm/libsofthsm2.so',
|
|
||||||
'/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so',
|
|
||||||
'/usr/local/lib/softhsm/libsofthsm2.so',
|
|
||||||
'/usr/lib/libacsp-pkcs11.so',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const pathnameToTry of commonSoftHSMPathNames) {
|
|
||||||
if (fs.existsSync(pathnameToTry)) {
|
|
||||||
return pathnameToTry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Unable to find PKCS11 library')
|
|
||||||
}
|
|
||||||
|
|
||||||
// fabric-ca-client set's the CKA_ID of the public/private keys in the HSM to a generated SKI
|
|
||||||
// value. This function replicates that calculation from a certificate PEM so that the HSM
|
|
||||||
// object associated with the certificate can be found
|
|
||||||
function getSKIFromCertificate(certificatePEM: string): Buffer {
|
|
||||||
const key = jsrsa.KEYUTIL.getKey(certificatePEM);
|
|
||||||
const uncompressedPoint = getUncompressedPointOnCurve(key as jsrsa.KJUR.crypto.ECDSA);
|
|
||||||
const hashBuffer = crypto.createHash('sha256');
|
|
||||||
hashBuffer.update(uncompressedPoint);
|
|
||||||
|
|
||||||
const digest = hashBuffer.digest('hex');
|
|
||||||
return Buffer.from(digest, 'hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUncompressedPointOnCurve(key: jsrsa.KJUR.crypto.ECDSA): Buffer {
|
|
||||||
const xyhex = key.getPublicKeyXYHex();
|
|
||||||
const xBuffer = Buffer.from(xyhex.x, 'hex');
|
|
||||||
const yBuffer = Buffer.from(xyhex.y, 'hex');
|
|
||||||
const uncompressedPrefix = Buffer.from('04', 'hex');
|
|
||||||
const uncompressedPoint = Buffer.concat([uncompressedPrefix, xBuffer, yBuffer]);
|
|
||||||
return uncompressedPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error);
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "@tsconfig/node14/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "dist",
|
|
||||||
"rootDir": "src",
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"forceConsistentCasingInFileNames": true
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue