From d83fca98af73f65ab38c396ac74947c955f68886 Mon Sep 17 00:00:00 2001 From: Artem Barger Date: Thu, 28 Dec 2023 02:02:40 +0200 Subject: [PATCH] Remove chaincode legacy cli command This commit is to remove peer cli chaincode command to get rid of deprecated chaincode lifecycle. Signed-off-by: Artem Barger --- cmd/peer/main.go | 2 - docs/source/commands/peerchaincode.md | 566 ----------- internal/peer/chaincode/chaincode.go | 157 --- internal/peer/chaincode/common.go | 890 ------------------ internal/peer/chaincode/common_test.go | 841 ----------------- internal/peer/chaincode/flags_test.go | 68 -- internal/peer/chaincode/install.go | 278 ------ internal/peer/chaincode/install_test.go | 152 --- internal/peer/chaincode/instantiate.go | 132 --- internal/peer/chaincode/instantiate_test.go | 90 -- internal/peer/chaincode/invoke.go | 63 -- internal/peer/chaincode/invoke_test.go | 411 -------- internal/peer/chaincode/list.go | 170 ---- internal/peer/chaincode/list_test.go | 176 ---- internal/peer/chaincode/mock/deliver.go | 587 ------------ .../peer/chaincode/mock/deliver_client.go | 277 ------ .../peer/chaincode/mock/signer_serializer.go | 185 ---- internal/peer/chaincode/package.go | 225 ----- internal/peer/chaincode/package_test.go | 213 ----- internal/peer/chaincode/query.go | 64 -- internal/peer/chaincode/query_test.go | 103 -- internal/peer/chaincode/signpackage.go | 70 -- internal/peer/chaincode/signpackage_test.go | 131 --- .../testdata/connectionprofile-uneven.yaml | 184 ---- .../chaincode/testdata/connectionprofile.yaml | 184 ---- .../testdata/src/chaincodes/noop/chaincode.go | 32 - internal/peer/chaincode/upgrade.go | 135 --- internal/peer/chaincode/upgrade_test.go | 171 ---- .../lifecycle/chaincode/approveformyorg.go | 5 +- internal/peer/lifecycle/chaincode/commit.go | 5 +- internal/peer/lifecycle/chaincode/common.go | 375 +++++++- scripts/help_docs.sh | 7 - 32 files changed, 377 insertions(+), 6572 deletions(-) delete mode 100644 docs/source/commands/peerchaincode.md delete mode 100644 internal/peer/chaincode/chaincode.go delete mode 100644 internal/peer/chaincode/common.go delete mode 100644 internal/peer/chaincode/common_test.go delete mode 100644 internal/peer/chaincode/flags_test.go delete mode 100644 internal/peer/chaincode/install.go delete mode 100644 internal/peer/chaincode/install_test.go delete mode 100644 internal/peer/chaincode/instantiate.go delete mode 100644 internal/peer/chaincode/instantiate_test.go delete mode 100644 internal/peer/chaincode/invoke.go delete mode 100644 internal/peer/chaincode/invoke_test.go delete mode 100644 internal/peer/chaincode/list.go delete mode 100644 internal/peer/chaincode/list_test.go delete mode 100644 internal/peer/chaincode/mock/deliver.go delete mode 100644 internal/peer/chaincode/mock/deliver_client.go delete mode 100644 internal/peer/chaincode/mock/signer_serializer.go delete mode 100644 internal/peer/chaincode/package.go delete mode 100644 internal/peer/chaincode/package_test.go delete mode 100644 internal/peer/chaincode/query.go delete mode 100644 internal/peer/chaincode/query_test.go delete mode 100644 internal/peer/chaincode/signpackage.go delete mode 100644 internal/peer/chaincode/signpackage_test.go delete mode 100644 internal/peer/chaincode/testdata/connectionprofile-uneven.yaml delete mode 100644 internal/peer/chaincode/testdata/connectionprofile.yaml delete mode 100644 internal/peer/chaincode/testdata/src/chaincodes/noop/chaincode.go delete mode 100644 internal/peer/chaincode/upgrade.go delete mode 100644 internal/peer/chaincode/upgrade_test.go diff --git a/cmd/peer/main.go b/cmd/peer/main.go index e2cc3228287..7ad9010763f 100644 --- a/cmd/peer/main.go +++ b/cmd/peer/main.go @@ -12,7 +12,6 @@ import ( "strings" "github.com/hyperledger/fabric/bccsp/factory" - "github.com/hyperledger/fabric/internal/peer/chaincode" "github.com/hyperledger/fabric/internal/peer/channel" "github.com/hyperledger/fabric/internal/peer/common" "github.com/hyperledger/fabric/internal/peer/lifecycle" @@ -42,7 +41,6 @@ func main() { mainCmd.AddCommand(version.Cmd()) mainCmd.AddCommand(node.Cmd()) - mainCmd.AddCommand(chaincode.Cmd(nil, cryptoProvider)) mainCmd.AddCommand(channel.Cmd(nil)) mainCmd.AddCommand(lifecycle.Cmd(cryptoProvider)) mainCmd.AddCommand(snapshot.Cmd(cryptoProvider)) diff --git a/docs/source/commands/peerchaincode.md b/docs/source/commands/peerchaincode.md deleted file mode 100644 index 3108b2883cd..00000000000 --- a/docs/source/commands/peerchaincode.md +++ /dev/null @@ -1,566 +0,0 @@ - - -# peer chaincode - -The `peer chaincode` command allows administrators to perform chaincode -related operations on a peer, such as installing, instantiating, invoking, -packaging, querying, and upgrading chaincode. - -## Syntax - -The `peer chaincode` command has the following subcommands: - - * install - * instantiate - * invoke - * list - * package - * query - * signpackage - * upgrade - -The different subcommand options (install, instantiate...) relate to the -different chaincode operations that are relevant to a peer. For example, use the -`peer chaincode install` subcommand option to install a chaincode on a peer, or -the `peer chaincode query` subcommand option to query a chaincode for the -current value on a peer's ledger. - -Some subcommands take flag `--ctor`, of which the value must be a JSON string -that has either key 'Args' or 'Function' and 'Args'. These keys are -case-insensitive. - -If the JSON string only has the Args key, the key value is an array, where the -first array element is the target function to call, and the subsequent elements -are arguments of the function. If the JSON string has both 'Function' and -'Args', the value of Function is the target function to call, and the value of -Args is an array of arguments of the function. For instance, -`{"Args":["GetAllAssets"]}` is equivalent to -`{"Function":"GetAllAssets", "Args":[]}`. - -Each peer chaincode subcommand is described together with its options in its own -section in this topic. - -## Flags - -Each `peer chaincode` subcommand has both a set of flags specific to an -individual subcommand, as well as a set of global flags that relate to all -`peer chaincode` subcommands. Not all subcommands would use these flags. -For instance, the `query` subcommand does not need the `--orderer` flag. - -The individual flags are described with the relevant subcommand. The global -flags are - -* `--cafile ` - - Path to file containing PEM-encoded trusted certificate(s) for the ordering - endpoint - -* `--certfile ` - - Path to file containing PEM-encoded X509 public key to use for mutual TLS - communication with the orderer endpoint - -* `--keyfile ` - - Path to file containing PEM-encoded private key to use for mutual TLS - communication with the orderer endpoint - -* `-o` or `--orderer ` - - Ordering service endpoint specified as `:` - -* `--ordererTLSHostnameOverride ` - - The hostname override to use when validating the TLS connection to the orderer - -* `--tls` - - Use TLS when communicating with the orderer endpoint - -* `--transient ` - - Transient map of arguments in JSON encoding - -Flags of type stringArray are to be repeated rather than concatenating their -values. For example, you will use `--peerAddresses localhost:9051 ---peerAddresses localhost:7051` rather than `--peerAddresses "localhost:9051 -localhost:7051"`. - -## peer chaincode install -``` -Install a chaincode on a peer. This installs a chaincode deployment spec package (if provided) or packages the specified chaincode before subsequently installing it. - -Usage: - peer chaincode install [flags] - -Flags: - --connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information - -c, --ctor string Constructor message for the chaincode in JSON format (default "{}") - -h, --help help for install - -l, --lang string Language the chaincode is written in (default "golang") - -n, --name string Name of the chaincode - -p, --path string Path to chaincode - --peerAddresses stringArray The addresses of the peers to connect to - --tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag - -v, --version string Version of the chaincode specified in install/instantiate/upgrade commands - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode instantiate -``` -Deploy the specified chaincode to the network. - -Usage: - peer chaincode instantiate [flags] - -Flags: - -C, --channelID string The channel on which this command should be executed - --collections-config string The fully qualified path to the collection JSON file including the file name - --connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information - -c, --ctor string Constructor message for the chaincode in JSON format (default "{}") - -E, --escc string The name of the endorsement system chaincode to be used for this chaincode - -h, --help help for instantiate - -l, --lang string Language the chaincode is written in (default "golang") - -n, --name string Name of the chaincode - --peerAddresses stringArray The addresses of the peers to connect to - -P, --policy string The endorsement policy associated to this chaincode - --tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag - -v, --version string Version of the chaincode specified in install/instantiate/upgrade commands - -V, --vscc string The name of the verification system chaincode to be used for this chaincode - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode invoke -``` -Invoke the specified chaincode. It will try to commit the endorsed transaction to the network. - -Usage: - peer chaincode invoke [flags] - -Flags: - -C, --channelID string The channel on which this command should be executed - --connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information - -c, --ctor string Constructor message for the chaincode in JSON format (default "{}") - -h, --help help for invoke - -I, --isInit Is this invocation for init (useful for supporting legacy chaincodes in the new lifecycle) - -n, --name string Name of the chaincode - --peerAddresses stringArray The addresses of the peers to connect to - --tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag - --waitForEvent Whether to wait for the event from each peer's deliver filtered service signifying that the 'invoke' transaction has been committed successfully - --waitForEventTimeout duration Time to wait for the event from each peer's deliver filtered service signifying that the 'invoke' transaction has been committed successfully (default 30s) - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode list -``` -Get the instantiated chaincodes in the channel if specify channel, or get installed chaincodes on the peer - -Usage: - peer chaincode list [flags] - -Flags: - -C, --channelID string The channel on which this command should be executed - --connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information - -h, --help help for list - --installed Get the installed chaincodes on a peer - --instantiated Get the instantiated chaincodes on a channel - --peerAddresses stringArray The addresses of the peers to connect to - --tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode package -``` -Package a chaincode and write the package to a file. - -Usage: - peer chaincode package [outputfile] [flags] - -Flags: - -s, --cc-package create CC deployment spec for owner endorsements instead of raw CC deployment spec - -c, --ctor string Constructor message for the chaincode in JSON format (default "{}") - -h, --help help for package - -i, --instantiate-policy string instantiation policy for the chaincode - -l, --lang string Language the chaincode is written in (default "golang") - -n, --name string Name of the chaincode - -p, --path string Path to chaincode - -S, --sign if creating CC deployment spec package for owner endorsements, also sign it with local MSP - -v, --version string Version of the chaincode specified in install/instantiate/upgrade commands - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode query -``` -Get endorsed result of chaincode function call and print it. It won't generate transaction. - -Usage: - peer chaincode query [flags] - -Flags: - -C, --channelID string The channel on which this command should be executed - --connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information - -c, --ctor string Constructor message for the chaincode in JSON format (default "{}") - -h, --help help for query - -x, --hex If true, output the query value byte array in hexadecimal. Incompatible with --raw - -n, --name string Name of the chaincode - --peerAddresses stringArray The addresses of the peers to connect to - -r, --raw If true, output the query value as raw bytes, otherwise format as a printable string - --tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode signpackage -``` -Sign the specified chaincode package - -Usage: - peer chaincode signpackage [flags] - -Flags: - -h, --help help for signpackage - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - - -## peer chaincode upgrade -``` -Upgrade an existing chaincode with the specified one. The new chaincode will immediately replace the existing chaincode upon the transaction committed. - -Usage: - peer chaincode upgrade [flags] - -Flags: - -C, --channelID string The channel on which this command should be executed - --collections-config string The fully qualified path to the collection JSON file including the file name - --connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information - -c, --ctor string Constructor message for the chaincode in JSON format (default "{}") - -E, --escc string The name of the endorsement system chaincode to be used for this chaincode - -h, --help help for upgrade - -l, --lang string Language the chaincode is written in (default "golang") - -n, --name string Name of the chaincode - -p, --path string Path to chaincode - --peerAddresses stringArray The addresses of the peers to connect to - -P, --policy string The endorsement policy associated to this chaincode - --tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag - -v, --version string Version of the chaincode specified in install/instantiate/upgrade commands - -V, --vscc string The name of the verification system chaincode to be used for this chaincode - -Global Flags: - --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint - --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint - --clientauth Use mutual TLS when communicating with the orderer endpoint - --connTimeout duration Timeout for client to connect (default 3s) - --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint - -o, --orderer string Ordering service endpoint - --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer - --tls Use TLS when communicating with the orderer endpoint - --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint - --transient string Transient map of arguments in JSON encoding -``` - -## Example Usage - -### peer chaincode instantiate examples - -Here are some examples of the `peer chaincode instantiate` command, which -instantiates the chaincode named `mycc` at version `1.0` on channel -`mychannel`: - - * Using the `--tls` and `--cafile` global flags to instantiate the chaincode - in a network with TLS enabled: - - ``` - export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem - peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" - - 2018-02-22 16:33:53.324 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc - 2018-02-22 16:33:53.324 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc - 2018-02-22 16:34:08.698 UTC [main] main -> INFO 003 Exiting..... - - ``` - - * Using only the command-specific options to instantiate the chaincode in a - network with TLS disabled: - - ``` - peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" - - - 2018-02-22 16:34:09.324 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc - 2018-02-22 16:34:09.324 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc - 2018-02-22 16:34:24.698 UTC [main] main -> INFO 003 Exiting..... - ``` - -### peer chaincode invoke example - -Here is an example of the `peer chaincode invoke` command: - - * Invoke the chaincode named `mycc` at version `1.0` on channel `mychannel` - on `peer0.org1.example.com:7051` and `peer0.org2.example.com:9051` (the - peers defined by `--peerAddresses`), requesting to move 10 units from - variable `a` to variable `b`: - - ``` - peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --peerAddresses peer0.org2.example.com:9051 -c '{"Args":["invoke","a","b","10"]}' - - 2018-02-22 16:34:27.069 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc - 2018-02-22 16:34:27.069 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc - . - . - . - 2018-02-22 16:34:27.106 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> DEBU 00a ESCC invoke result: version:1 response: payload:"\n \237mM\376? [\214\002 \332\204\035\275q\227\2132A\n\204&\2106\037W|\346#\3413\274\022Y\nE\022\024\n\004lscc\022\014\n\n\n\004mycc\022\002\010\003\022-\n\004mycc\022%\n\007\n\001a\022\002\010\003\n\007\n\001b\022\002\010\003\032\007\n\001a\032\00290\032\010\n\001b\032\003210\032\003\010\310\001\"\013\022\004mycc\032\0031.0" endorsement: - 2018-02-22 16:34:27.107 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00b Chaincode invoke successful. result: status:200 - 2018-02-22 16:34:27.107 UTC [main] main -> INFO 00c Exiting..... - - ``` - - Here you can see that the invoke was submitted successfully based on the log - message: - - ``` - 2018-02-22 16:34:27.107 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00b Chaincode invoke successful. result: status:200 - - ``` - - A successful response indicates that the transaction was submitted for ordering - successfully. The transaction will then be added to a block and, finally, validated - or invalidated by each peer on the channel. - -Here is an example of how to format the `peer chaincode invoke` command when the chaincode package includes multiple smart contracts. - - * If you are using the [contract-api](https://www.npmjs.com/package/fabric-contract-api), the name you pass to `super("MyContract")` can be used as a prefix. - - ``` - peer chaincode invoke -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{ "Args": ["MyContract:methodName", "{}"] }' - - peer chaincode invoke -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{ "Args": ["MyOtherContract:methodName", "{}"] }' - - ``` - - -### peer chaincode list example - -Here are some examples of the `peer chaincode list ` command: - - * Using the `--installed` flag to list the chaincodes installed on a peer. - - ``` - peer chaincode list --installed - - Get installed chaincodes on peer: - Name: mycc, Version: 1.0, Path: github.com/hyperledger/fabric-samples/chaincode/abstore/go, Id: 8cc2730fdafd0b28ef734eac12b29df5fc98ad98bdb1b7e0ef96265c3d893d61 - 2018-02-22 17:07:13.476 UTC [main] main -> INFO 001 Exiting..... - ``` - - You can see that the peer has installed a chaincode called `mycc` which is at - version `1.0`. - - * Using the `--instantiated` in combination with the `-C` (channel ID) flag to - list the chaincodes instantiated on a channel. - - ``` - peer chaincode list --instantiated -C mychannel - - Get instantiated chaincodes on channel mychannel: - Name: mycc, Version: 1.0, Path: github.com/hyperledger/fabric-samples/chaincode/abstore/go, Escc: escc, Vscc: vscc - 2018-02-22 17:07:42.969 UTC [main] main -> INFO 001 Exiting..... - - ``` - - You can see that chaincode `mycc` at version `1.0` is instantiated on - channel `mychannel`. - -### peer chaincode package example - -Here is an example of the `peer chaincode package` command, which -packages the chaincode named `mycc` at version `1.1`, creates the chaincode -deployment spec, signs the package using the local MSP, and outputs it as -`ccpack.out`: - - ``` - peer chaincode package ccpack.out -n mycc -p github.com/hyperledger/fabric-samples/chaincode/abstore/go -v 1.1 -s -S - . - . - . - 2018-02-22 17:27:01.404 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc - 2018-02-22 17:27:01.405 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc - . - . - . - 2018-02-22 17:27:01.879 UTC [chaincodeCmd] chaincodePackage -> DEBU 011 Packaged chaincode into deployment spec of size <3426>, with args = [ccpack.out] - 2018-02-22 17:27:01.879 UTC [main] main -> INFO 012 Exiting..... - - ``` - -### peer chaincode query example - -Here is an example of the `peer chaincode query` command, which queries the -peer ledger for the chaincode named `mycc` at version `1.0` for the value of -variable `a`: - - * You can see from the output that variable `a` had a value of 90 at the time of - the query. - - ``` - peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' - - 2018-02-22 16:34:30.816 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc - 2018-02-22 16:34:30.816 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc - Query Result: 90 - - ``` - -### peer chaincode signpackage example - -Here is an example of the `peer chaincode signpackage` command, which accepts an -existing signed package and creates a new one with signature of the local MSP -appended to it. - - ``` - peer chaincode signpackage ccwith1sig.pak ccwith2sig.pak - Wrote signed package to ccwith2sig.pak successfully - 2018-02-24 19:32:47.189 EST [main] main -> INFO 002 Exiting..... - ``` - -### peer chaincode upgrade example - -Here is an example of the `peer chaincode upgrade` command, which -upgrades the chaincode named `mycc` at version `1.1` on channel -`mychannel` to version `1.2`, which contains a new variable `c`: - - * Using the `--tls` and `--cafile` global flags to upgrade the chaincode - in a network with TLS enabled: - - ``` - export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem - peer chaincode upgrade -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C mychannel -n mycc -v 1.2 -c '{"Args":["init","a","100","b","200","c","300"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" - . - . - . - 2018-02-22 18:26:31.433 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc - 2018-02-22 18:26:31.434 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc - 2018-02-22 18:26:31.435 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled - 2018-02-22 18:26:31.435 UTC [chaincodeCmd] upgrade -> DEBU 006 Get upgrade proposal for chaincode - . - . - . - 2018-02-22 18:26:46.687 UTC [chaincodeCmd] upgrade -> DEBU 009 endorse upgrade proposal, get response - . - . - . - 2018-02-22 18:26:46.693 UTC [chaincodeCmd] upgrade -> DEBU 00c Get Signed envelope - 2018-02-22 18:26:46.693 UTC [chaincodeCmd] chaincodeUpgrade -> DEBU 00d Send signed envelope to orderer - 2018-02-22 18:26:46.908 UTC [main] main -> INFO 00e Exiting..... - ``` - - * Using only the command-specific options to upgrade the chaincode in a - network with TLS disabled: - - ``` - peer chaincode upgrade -o orderer.example.com:7050 -C mychannel -n mycc -v 1.2 -c '{"Args":["init","a","100","b","200","c","300"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" - . - . - . - 2018-02-22 18:28:31.433 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc - 2018-02-22 18:28:31.434 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc - 2018-02-22 18:28:31.435 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled - 2018-02-22 18:28:31.435 UTC [chaincodeCmd] upgrade -> DEBU 006 Get upgrade proposal for chaincode - . - . - . - 2018-02-22 18:28:46.687 UTC [chaincodeCmd] upgrade -> DEBU 009 endorse upgrade proposal, get response - . - . - . - 2018-02-22 18:28:46.693 UTC [chaincodeCmd] upgrade -> DEBU 00c Get Signed envelope - 2018-02-22 18:28:46.693 UTC [chaincodeCmd] chaincodeUpgrade -> DEBU 00d Send signed envelope to orderer - 2018-02-22 18:28:46.908 UTC [main] main -> INFO 00e Exiting..... - ``` - -Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. diff --git a/internal/peer/chaincode/chaincode.go b/internal/peer/chaincode/chaincode.go deleted file mode 100644 index c06491acb40..00000000000 --- a/internal/peer/chaincode/chaincode.go +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - "time" - - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/common/flogging" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/hyperledger/fabric/internal/peer/packaging" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -const ( - chainFuncName = "chaincode" - chainCmdDes = "Operate a chaincode: install|instantiate|invoke|package|query|signpackage|upgrade|list." -) - -var logger = flogging.MustGetLogger("chaincodeCmd") - -// XXX This is a terrible singleton hack, however -// it simply making a latent dependency explicit. -// It should be removed along with the other package -// scoped variables -var platformRegistry = packaging.NewRegistry(packaging.SupportedPlatforms...) - -func addFlags(cmd *cobra.Command) { - common.AddOrdererFlags(cmd) - flags := cmd.PersistentFlags() - flags.StringVarP(&transient, "transient", "", "", "Transient map of arguments in JSON encoding") -} - -// Cmd returns the cobra command for Chaincode -func Cmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - addFlags(chaincodeCmd) - - chaincodeCmd.AddCommand(installCmd(cf, nil, cryptoProvider)) - chaincodeCmd.AddCommand(instantiateCmd(cf, cryptoProvider)) - chaincodeCmd.AddCommand(invokeCmd(cf, cryptoProvider)) - chaincodeCmd.AddCommand(packageCmd(cf, nil, nil, cryptoProvider)) - chaincodeCmd.AddCommand(queryCmd(cf, cryptoProvider)) - chaincodeCmd.AddCommand(signpackageCmd(cf, cryptoProvider)) - chaincodeCmd.AddCommand(upgradeCmd(cf, cryptoProvider)) - chaincodeCmd.AddCommand(listCmd(cf, cryptoProvider)) - - return chaincodeCmd -} - -// Chaincode-related variables. -var ( - chaincodeLang string - chaincodeCtorJSON string - chaincodePath string - chaincodeName string - chaincodeUsr string // Not used - chaincodeQueryRaw bool - chaincodeQueryHex bool - channelID string - chaincodeVersion string - policy string - escc string - vscc string - policyMarshalled []byte - transient string - isInit bool - collectionsConfigFile string - collectionConfigBytes []byte - peerAddresses []string - tlsRootCertFiles []string - connectionProfile string - waitForEvent bool - waitForEventTimeout time.Duration -) - -var chaincodeCmd = &cobra.Command{ - Use: chainFuncName, - Short: fmt.Sprint(chainCmdDes), - Long: fmt.Sprint(chainCmdDes), - PersistentPreRun: func(cmd *cobra.Command, args []string) { - common.InitCmd(cmd, args) - common.SetOrdererEnv(cmd, args) - }, -} - -var flags *pflag.FlagSet - -func init() { - resetFlags() -} - -// Explicitly define a method to facilitate tests -func resetFlags() { - flags = &pflag.FlagSet{} - - flags.StringVarP(&chaincodeLang, "lang", "l", "golang", - fmt.Sprintf("Language the %s is written in", chainFuncName)) - flags.StringVarP(&chaincodeCtorJSON, "ctor", "c", "{}", - fmt.Sprintf("Constructor message for the %s in JSON format", chainFuncName)) - flags.StringVarP(&chaincodePath, "path", "p", common.UndefinedParamValue, - fmt.Sprintf("Path to %s", chainFuncName)) - flags.StringVarP(&chaincodeName, "name", "n", common.UndefinedParamValue, - "Name of the chaincode") - flags.StringVarP(&chaincodeVersion, "version", "v", common.UndefinedParamValue, - "Version of the chaincode specified in install/instantiate/upgrade commands") - flags.StringVarP(&chaincodeUsr, "username", "u", common.UndefinedParamValue, - "Username for chaincode operations when security is enabled") - flags.StringVarP(&channelID, "channelID", "C", "", - "The channel on which this command should be executed") - flags.StringVarP(&policy, "policy", "P", common.UndefinedParamValue, - "The endorsement policy associated to this chaincode") - flags.StringVarP(&escc, "escc", "E", common.UndefinedParamValue, - "The name of the endorsement system chaincode to be used for this chaincode") - flags.StringVarP(&vscc, "vscc", "V", common.UndefinedParamValue, - "The name of the verification system chaincode to be used for this chaincode") - flags.BoolVarP(&isInit, "isInit", "I", false, - "Is this invocation for init (useful for supporting legacy chaincodes in the new lifecycle)") - flags.BoolVarP(&getInstalledChaincodes, "installed", "", false, - "Get the installed chaincodes on a peer") - flags.BoolVarP(&getInstantiatedChaincodes, "instantiated", "", false, - "Get the instantiated chaincodes on a channel") - flags.StringVar(&collectionsConfigFile, "collections-config", common.UndefinedParamValue, - "The fully qualified path to the collection JSON file including the file name") - flags.StringArrayVarP(&peerAddresses, "peerAddresses", "", []string{common.UndefinedParamValue}, - "The addresses of the peers to connect to") - flags.StringArrayVarP(&tlsRootCertFiles, "tlsRootCertFiles", "", []string{common.UndefinedParamValue}, - "If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag") - flags.StringVarP(&connectionProfile, "connectionProfile", "", common.UndefinedParamValue, - "Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information") - flags.BoolVar(&waitForEvent, "waitForEvent", false, - "Whether to wait for the event from each peer's deliver filtered service signifying that the 'invoke' transaction has been committed successfully") - flags.DurationVar(&waitForEventTimeout, "waitForEventTimeout", 30*time.Second, - "Time to wait for the event from each peer's deliver filtered service signifying that the 'invoke' transaction has been committed successfully") - flags.BoolVarP(&createSignedCCDepSpec, "cc-package", "s", false, - "create CC deployment spec for owner endorsements instead of raw CC deployment spec") - flags.BoolVarP(&signCCDepSpec, "sign", "S", false, - "if creating CC deployment spec package for owner endorsements, also sign it with local MSP") - flags.StringVarP(&instantiationPolicy, "instantiate-policy", "i", "", - "instantiation policy for the chaincode") -} - -func attachFlags(cmd *cobra.Command, names []string) { - cmdFlags := cmd.Flags() - for _, name := range names { - if flag := flags.Lookup(name); flag != nil { - cmdFlags.AddFlag(flag) - } else { - logger.Fatalf("Could not find flag '%s' to attach to command '%s'", name, cmd.Name()) - } - } -} diff --git a/internal/peer/chaincode/common.go b/internal/peer/chaincode/common.go deleted file mode 100644 index 169f975c9e3..00000000000 --- a/internal/peer/chaincode/common.go +++ /dev/null @@ -1,890 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "context" - "crypto/tls" - "encoding/json" - "fmt" - "math" - "os" - "strings" - "sync" - - "github.com/golang/protobuf/proto" - "github.com/hyperledger/fabric-chaincode-go/shim" - pcommon "github.com/hyperledger/fabric-protos-go/common" - ab "github.com/hyperledger/fabric-protos-go/orderer" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/common/policydsl" - "github.com/hyperledger/fabric/common/util" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/hyperledger/fabric/internal/pkg/identity" - "github.com/hyperledger/fabric/protoutil" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -// checkSpec to see if chaincode resides within current package capture for language. -func checkSpec(spec *pb.ChaincodeSpec) error { - // Don't allow nil value - if spec == nil { - return errors.New("expected chaincode specification, nil received") - } - if spec.ChaincodeId == nil { - return errors.New("expected chaincode ID, nil received") - } - - return platformRegistry.ValidateSpec(spec.Type.String(), spec.ChaincodeId.Path) -} - -// getChaincodeDeploymentSpec get chaincode deployment spec given the chaincode spec -func getChaincodeDeploymentSpec(spec *pb.ChaincodeSpec, crtPkg bool) (*pb.ChaincodeDeploymentSpec, error) { - var codePackageBytes []byte - if crtPkg { - var err error - if err = checkSpec(spec); err != nil { - return nil, err - } - - codePackageBytes, err = platformRegistry.GetDeploymentPayload(spec.Type.String(), spec.ChaincodeId.Path) - if err != nil { - return nil, errors.WithMessage(err, "error getting chaincode package bytes") - } - chaincodePath, err := platformRegistry.NormalizePath(spec.Type.String(), spec.ChaincodeId.Path) - if err != nil { - return nil, errors.WithMessage(err, "failed to normalize chaincode path") - } - spec.ChaincodeId.Path = chaincodePath - } - - return &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes}, nil -} - -// getChaincodeSpec get chaincode spec from the cli cmd parameters -func getChaincodeSpec(cmd *cobra.Command) (*pb.ChaincodeSpec, error) { - spec := &pb.ChaincodeSpec{} - if err := checkChaincodeCmdParams(cmd); err != nil { - // unset usage silence because it's a command line usage error - cmd.SilenceUsage = false - return spec, err - } - - // Build the spec - input := chaincodeInput{} - if err := json.Unmarshal([]byte(chaincodeCtorJSON), &input); err != nil { - return spec, errors.Wrap(err, "chaincode argument error") - } - input.IsInit = isInit - - chaincodeLang = strings.ToUpper(chaincodeLang) - spec = &pb.ChaincodeSpec{ - Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value[chaincodeLang]), - ChaincodeId: &pb.ChaincodeID{Path: chaincodePath, Name: chaincodeName, Version: chaincodeVersion}, - Input: &input.ChaincodeInput, - } - return spec, nil -} - -// chaincodeInput is wrapper around the proto defined ChaincodeInput message that -// is decorated with a custom JSON unmarshaller. -type chaincodeInput struct { - pb.ChaincodeInput -} - -// UnmarshalJSON converts the string-based REST/JSON input to -// the []byte-based current ChaincodeInput structure. -func (c *chaincodeInput) UnmarshalJSON(b []byte) error { - sa := struct { - Function string - Args []string - }{} - err := json.Unmarshal(b, &sa) - if err != nil { - return err - } - allArgs := sa.Args - if sa.Function != "" { - allArgs = append([]string{sa.Function}, sa.Args...) - } - c.Args = util.ToChaincodeArgs(allArgs...) - return nil -} - -func chaincodeInvokeOrQuery(cmd *cobra.Command, invoke bool, cf *ChaincodeCmdFactory) (err error) { - spec, err := getChaincodeSpec(cmd) - if err != nil { - return err - } - - // call with empty txid to ensure production code generates a txid. - // otherwise, tests can explicitly set their own txid - txID := "" - - proposalResp, err := ChaincodeInvokeOrQuery( - spec, - channelID, - txID, - invoke, - cf.Signer, - cf.Certificate, - cf.EndorserClients, - cf.DeliverClients, - cf.BroadcastClient, - ) - if err != nil { - return errors.Errorf("%s - proposal response: %v", err, proposalResp) - } - - if invoke { - logger.Debugf("ESCC invoke result: %v", proposalResp) - pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(proposalResp.Payload) - if err != nil { - return errors.WithMessage(err, "error while unmarshalling proposal response payload") - } - ca, err := protoutil.UnmarshalChaincodeAction(pRespPayload.Extension) - if err != nil { - return errors.WithMessage(err, "error while unmarshalling chaincode action") - } - if proposalResp.Endorsement == nil { - return errors.Errorf("endorsement failure during invoke. response: %v", proposalResp.Response) - } - logger.Infof("Chaincode invoke successful. result: %v", ca.Response) - } else { - if proposalResp == nil { - return errors.New("error during query: received nil proposal response") - } - if proposalResp.Endorsement == nil { - return errors.Errorf("endorsement failure during query. response: %v", proposalResp.Response) - } - - if chaincodeQueryRaw && chaincodeQueryHex { - return fmt.Errorf("options --raw (-r) and --hex (-x) are not compatible") - } - if chaincodeQueryRaw { - fmt.Println(proposalResp.Response.Payload) - return nil - } - if chaincodeQueryHex { - fmt.Printf("%x\n", proposalResp.Response.Payload) - return nil - } - fmt.Println(string(proposalResp.Response.Payload)) - } - return nil -} - -type endorsementPolicy struct { - ChannelConfigPolicy string `json:"channelConfigPolicy,omitempty"` - SignaturePolicy string `json:"signaturePolicy,omitempty"` -} - -type collectionConfigJson struct { - Name string `json:"name"` - Policy string `json:"policy"` - RequiredPeerCount *int32 `json:"requiredPeerCount"` - MaxPeerCount *int32 `json:"maxPeerCount"` - BlockToLive uint64 `json:"blockToLive"` - MemberOnlyRead bool `json:"memberOnlyRead"` - MemberOnlyWrite bool `json:"memberOnlyWrite"` - EndorsementPolicy *endorsementPolicy `json:"endorsementPolicy,omitempty"` -} - -// GetCollectionConfigFromFile retrieves the collection configuration -// from the supplied file; the supplied file must contain a -// json-formatted array of collectionConfigJson elements -func GetCollectionConfigFromFile(ccFile string) (*pb.CollectionConfigPackage, []byte, error) { - fileBytes, err := os.ReadFile(ccFile) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not read file '%s'", ccFile) - } - - return getCollectionConfigFromBytes(fileBytes) -} - -// getCollectionConfig retrieves the collection configuration -// from the supplied byte array; the byte array must contain a -// json-formatted array of collectionConfigJson elements -func getCollectionConfigFromBytes(cconfBytes []byte) (*pb.CollectionConfigPackage, []byte, error) { - cconf := &[]collectionConfigJson{} - err := json.Unmarshal(cconfBytes, cconf) - if err != nil { - return nil, nil, errors.Wrap(err, "could not parse the collection configuration") - } - - ccarray := make([]*pb.CollectionConfig, 0, len(*cconf)) - for _, cconfitem := range *cconf { - p, err := policydsl.FromString(cconfitem.Policy) - if err != nil { - return nil, nil, errors.WithMessagef(err, "invalid policy %s", cconfitem.Policy) - } - - cpc := &pb.CollectionPolicyConfig{ - Payload: &pb.CollectionPolicyConfig_SignaturePolicy{ - SignaturePolicy: p, - }, - } - - var ep *pb.ApplicationPolicy - if cconfitem.EndorsementPolicy != nil { - signaturePolicy := cconfitem.EndorsementPolicy.SignaturePolicy - channelConfigPolicy := cconfitem.EndorsementPolicy.ChannelConfigPolicy - ep, err = getApplicationPolicy(signaturePolicy, channelConfigPolicy) - if err != nil { - return nil, nil, errors.WithMessagef(err, "invalid endorsement policy [%#v]", cconfitem.EndorsementPolicy) - } - } - - // Set default requiredPeerCount and MaxPeerCount if not specified in json - requiredPeerCount := int32(0) - maxPeerCount := int32(1) - if cconfitem.RequiredPeerCount != nil { - requiredPeerCount = *cconfitem.RequiredPeerCount - } - if cconfitem.MaxPeerCount != nil { - maxPeerCount = *cconfitem.MaxPeerCount - } - - cc := &pb.CollectionConfig{ - Payload: &pb.CollectionConfig_StaticCollectionConfig{ - StaticCollectionConfig: &pb.StaticCollectionConfig{ - Name: cconfitem.Name, - MemberOrgsPolicy: cpc, - RequiredPeerCount: requiredPeerCount, - MaximumPeerCount: maxPeerCount, - BlockToLive: cconfitem.BlockToLive, - MemberOnlyRead: cconfitem.MemberOnlyRead, - MemberOnlyWrite: cconfitem.MemberOnlyWrite, - EndorsementPolicy: ep, - }, - }, - } - - ccarray = append(ccarray, cc) - } - - ccp := &pb.CollectionConfigPackage{Config: ccarray} - ccpBytes, err := proto.Marshal(ccp) - return ccp, ccpBytes, err -} - -func getApplicationPolicy(signaturePolicy, channelConfigPolicy string) (*pb.ApplicationPolicy, error) { - if signaturePolicy == "" && channelConfigPolicy == "" { - // no policy, no problem - return nil, nil - } - - if signaturePolicy != "" && channelConfigPolicy != "" { - // mo policies, mo problems - return nil, errors.New(`cannot specify both "--signature-policy" and "--channel-config-policy"`) - } - - var applicationPolicy *pb.ApplicationPolicy - if signaturePolicy != "" { - signaturePolicyEnvelope, err := policydsl.FromString(signaturePolicy) - if err != nil { - return nil, errors.Errorf("invalid signature policy: %s", signaturePolicy) - } - - applicationPolicy = &pb.ApplicationPolicy{ - Type: &pb.ApplicationPolicy_SignaturePolicy{ - SignaturePolicy: signaturePolicyEnvelope, - }, - } - } - - if channelConfigPolicy != "" { - applicationPolicy = &pb.ApplicationPolicy{ - Type: &pb.ApplicationPolicy_ChannelConfigPolicyReference{ - ChannelConfigPolicyReference: channelConfigPolicy, - }, - } - } - - return applicationPolicy, nil -} - -func checkChaincodeCmdParams(cmd *cobra.Command) error { - // we need chaincode name for everything, including deploy - if chaincodeName == common.UndefinedParamValue { - return errors.Errorf("must supply value for %s name parameter", chainFuncName) - } - - if cmd.Name() == instantiateCmdName || cmd.Name() == installCmdName || - cmd.Name() == upgradeCmdName || cmd.Name() == packageCmdName { - if chaincodeVersion == common.UndefinedParamValue { - return errors.Errorf("chaincode version is not provided for %s", cmd.Name()) - } - - if escc != common.UndefinedParamValue { - logger.Infof("Using escc %s", escc) - } else { - logger.Info("Using default escc") - escc = "escc" - } - - if vscc != common.UndefinedParamValue { - logger.Infof("Using vscc %s", vscc) - } else { - logger.Info("Using default vscc") - vscc = "vscc" - } - - if policy != common.UndefinedParamValue { - p, err := policydsl.FromString(policy) - if err != nil { - return errors.Errorf("invalid policy %s", policy) - } - policyMarshalled = protoutil.MarshalOrPanic(p) - } - - if collectionsConfigFile != common.UndefinedParamValue { - var err error - _, collectionConfigBytes, err = GetCollectionConfigFromFile(collectionsConfigFile) - if err != nil { - return errors.WithMessagef(err, "invalid collection configuration in file %s", collectionsConfigFile) - } - } - } - - // Check that non-empty chaincode parameters contain only Args as a key. - // Type checking is done later when the JSON is actually unmarshaled - // into a pb.ChaincodeInput. To better understand what's going - // on here with JSON parsing see http://blog.golang.org/json-and-go - - // Generic JSON with interface{} - if chaincodeCtorJSON != "{}" { - var f interface{} - err := json.Unmarshal([]byte(chaincodeCtorJSON), &f) - if err != nil { - return errors.Wrap(err, "chaincode argument error") - } - m := f.(map[string]interface{}) - sm := make(map[string]interface{}) - for k := range m { - sm[strings.ToLower(k)] = m[k] - } - _, argsPresent := sm["args"] - _, funcPresent := sm["function"] - if !argsPresent || (len(m) == 2 && !funcPresent) || len(m) > 2 { - return errors.New("non-empty JSON chaincode parameters must contain the following keys: 'Args' or 'Function' and 'Args'") - } - } else { - if cmd == nil || (cmd != chaincodeInstallCmd && cmd != chaincodePackageCmd) { - return errors.New("empty JSON chaincode parameters must contain the following keys: 'Args' or 'Function' and 'Args'") - } - } - - return nil -} - -func validatePeerConnectionParameters(cmdName string) error { - if connectionProfile != common.UndefinedParamValue { - networkConfig, err := common.GetConfig(connectionProfile) - if err != nil { - return err - } - if len(networkConfig.Channels[channelID].Peers) != 0 { - peerAddresses = []string{} - tlsRootCertFiles = []string{} - for peer, peerChannelConfig := range networkConfig.Channels[channelID].Peers { - if peerChannelConfig.EndorsingPeer { - peerConfig, ok := networkConfig.Peers[peer] - if !ok { - return errors.Errorf("peer '%s' is defined in the channel config but doesn't have associated peer config", peer) - } - peerAddresses = append(peerAddresses, peerConfig.URL) - tlsRootCertFiles = append(tlsRootCertFiles, peerConfig.TLSCACerts.Path) - } - } - } - } - - // currently only support multiple peer addresses for invoke - multiplePeersAllowed := map[string]bool{ - "invoke": true, - } - _, ok := multiplePeersAllowed[cmdName] - if !ok && len(peerAddresses) > 1 { - return errors.Errorf("'%s' command can only be executed against one peer. received %d", cmdName, len(peerAddresses)) - } - - if len(tlsRootCertFiles) > len(peerAddresses) { - logger.Warningf("received more TLS root cert files (%d) than peer addresses (%d)", len(tlsRootCertFiles), len(peerAddresses)) - } - - if viper.GetBool("peer.tls.enabled") { - if len(tlsRootCertFiles) != len(peerAddresses) { - return errors.Errorf("number of peer addresses (%d) does not match the number of TLS root cert files (%d)", len(peerAddresses), len(tlsRootCertFiles)) - } - } else { - tlsRootCertFiles = nil - } - - return nil -} - -// ChaincodeCmdFactory holds the clients used by ChaincodeCmd -type ChaincodeCmdFactory struct { - EndorserClients []pb.EndorserClient - DeliverClients []pb.DeliverClient - Certificate tls.Certificate - Signer identity.SignerSerializer - BroadcastClient common.BroadcastClient -} - -// InitCmdFactory init the ChaincodeCmdFactory with default clients -func InitCmdFactory(cmdName string, isEndorserRequired, isOrdererRequired bool, cryptoProvider bccsp.BCCSP) (*ChaincodeCmdFactory, error) { - var err error - var endorserClients []pb.EndorserClient - var deliverClients []pb.DeliverClient - if isEndorserRequired { - if err = validatePeerConnectionParameters(cmdName); err != nil { - return nil, errors.WithMessage(err, "error validating peer connection parameters") - } - for i, address := range peerAddresses { - var tlsRootCertFile string - if tlsRootCertFiles != nil { - tlsRootCertFile = tlsRootCertFiles[i] - } - endorserClient, err := common.GetEndorserClientFnc(address, tlsRootCertFile) - if err != nil { - return nil, errors.WithMessagef(err, "error getting endorser client for %s", cmdName) - } - endorserClients = append(endorserClients, endorserClient) - deliverClient, err := common.GetPeerDeliverClientFnc(address, tlsRootCertFile) - if err != nil { - return nil, errors.WithMessagef(err, "error getting deliver client for %s", cmdName) - } - deliverClients = append(deliverClients, deliverClient) - } - if len(endorserClients) == 0 { - return nil, errors.New("no endorser clients retrieved - this might indicate a bug") - } - } - certificate, err := common.GetClientCertificateFnc() - if err != nil { - return nil, errors.WithMessage(err, "error getting client certificate") - } - - signer, err := common.GetDefaultSignerFnc() - if err != nil { - return nil, errors.WithMessage(err, "error getting default signer") - } - - var broadcastClient common.BroadcastClient - if isOrdererRequired { - if len(common.OrderingEndpoint) == 0 { - if len(endorserClients) == 0 { - return nil, errors.New("orderer is required, but no ordering endpoint or endorser client supplied") - } - endorserClient := endorserClients[0] - - orderingEndpoints, err := common.GetOrdererEndpointOfChainFnc(channelID, signer, endorserClient, cryptoProvider) - if err != nil { - return nil, errors.WithMessagef(err, "error getting channel (%s) orderer endpoint", channelID) - } - if len(orderingEndpoints) == 0 { - return nil, errors.Errorf("no orderer endpoints retrieved for channel %s, pass orderer endpoint with -o flag instead", channelID) - } - logger.Infof("Retrieved channel (%s) orderer endpoint: %s", channelID, orderingEndpoints[0]) - // override viper env - viper.Set("orderer.address", orderingEndpoints[0]) - } - - broadcastClient, err = common.GetBroadcastClientFnc() - if err != nil { - return nil, errors.WithMessage(err, "error getting broadcast client") - } - } - return &ChaincodeCmdFactory{ - EndorserClients: endorserClients, - DeliverClients: deliverClients, - Signer: signer, - BroadcastClient: broadcastClient, - Certificate: certificate, - }, nil -} - -// processProposals sends a signed proposal to a set of peers, and gathers all the responses. -func processProposals(endorserClients []pb.EndorserClient, signedProposal *pb.SignedProposal) ([]*pb.ProposalResponse, error) { - responsesCh := make(chan *pb.ProposalResponse, len(endorserClients)) - errorCh := make(chan error, len(endorserClients)) - wg := sync.WaitGroup{} - for _, endorser := range endorserClients { - wg.Add(1) - go func(endorser pb.EndorserClient) { - defer wg.Done() - proposalResp, err := endorser.ProcessProposal(context.Background(), signedProposal) - if err != nil { - errorCh <- err - return - } - responsesCh <- proposalResp - }(endorser) - } - wg.Wait() - close(responsesCh) - close(errorCh) - for err := range errorCh { - return nil, err - } - var responses []*pb.ProposalResponse - for response := range responsesCh { - responses = append(responses, response) - } - return responses, nil -} - -// ChaincodeInvokeOrQuery invokes or queries the chaincode. If successful, the -// INVOKE form prints the ProposalResponse to STDOUT, and the QUERY form prints -// the query result on STDOUT. A command-line flag (-r, --raw) determines -// whether the query result is output as raw bytes, or as a printable string. -// The printable form is optionally (-x, --hex) a hexadecimal representation -// of the query response. If the query response is NIL, nothing is output. -// -// NOTE - Query will likely go away as all interactions with the endorser are -// Proposal and ProposalResponses -func ChaincodeInvokeOrQuery( - spec *pb.ChaincodeSpec, - cID string, - txID string, - invoke bool, - signer identity.SignerSerializer, - certificate tls.Certificate, - endorserClients []pb.EndorserClient, - deliverClients []pb.DeliverClient, - bc common.BroadcastClient, -) (*pb.ProposalResponse, error) { - // Build the ChaincodeInvocationSpec message - invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} - - creator, err := signer.Serialize() - if err != nil { - return nil, errors.WithMessage(err, "error serializing identity") - } - - funcName := "invoke" - if !invoke { - funcName = "query" - } - - // extract the transient field if it exists - var tMap map[string][]byte - if transient != "" { - if err := json.Unmarshal([]byte(transient), &tMap); err != nil { - return nil, errors.Wrap(err, "error parsing transient string") - } - } - - prop, txid, err := protoutil.CreateChaincodeProposalWithTxIDAndTransient(pcommon.HeaderType_ENDORSER_TRANSACTION, cID, invocation, creator, txID, tMap) - if err != nil { - return nil, errors.WithMessagef(err, "error creating proposal for %s", funcName) - } - - signedProp, err := protoutil.GetSignedProposal(prop, signer) - if err != nil { - return nil, errors.WithMessagef(err, "error creating signed proposal for %s", funcName) - } - - responses, err := processProposals(endorserClients, signedProp) - if err != nil { - return nil, errors.WithMessagef(err, "error endorsing %s", funcName) - } - - if len(responses) == 0 { - // this should only happen if some new code has introduced a bug - return nil, errors.New("no proposal responses received - this might indicate a bug") - } - // all responses will be checked when the signed transaction is created. - // for now, just set this so we check the first response's status - proposalResp := responses[0] - - if invoke { - if proposalResp != nil { - if proposalResp.Response.Status >= shim.ERRORTHRESHOLD { - return proposalResp, nil - } - // assemble a signed transaction (it's an Envelope message) - env, err := protoutil.CreateSignedTx(prop, signer, responses...) - if err != nil { - return proposalResp, errors.WithMessage(err, "could not assemble transaction") - } - var dg *DeliverGroup - var ctx context.Context - if waitForEvent { - var cancelFunc context.CancelFunc - ctx, cancelFunc = context.WithTimeout(context.Background(), waitForEventTimeout) - defer cancelFunc() - - dg = NewDeliverGroup( - deliverClients, - peerAddresses, - signer, - certificate, - channelID, - txid, - ) - // connect to deliver service on all peers - err := dg.Connect(ctx) - if err != nil { - return nil, err - } - } - - // send the envelope for ordering - if err = bc.Send(env); err != nil { - return proposalResp, errors.WithMessagef(err, "error sending transaction for %s", funcName) - } - - if dg != nil && ctx != nil { - // wait for event that contains the txid from all peers - err = dg.Wait(ctx) - if err != nil { - return nil, err - } - } - } - } - - return proposalResp, nil -} - -// DeliverGroup holds all of the information needed to connect -// to a set of peers to wait for the interested txid to be -// committed to the ledgers of all peers. This functionality -// is currently implemented via the peer's DeliverFiltered service. -// An error from any of the peers/deliver clients will result in -// the invoke command returning an error. Only the first error that -// occurs will be set -type DeliverGroup struct { - Clients []*DeliverClient - Certificate tls.Certificate - ChannelID string - TxID string - Signer identity.SignerSerializer - mutex sync.Mutex - Error error - wg sync.WaitGroup -} - -// DeliverClient holds the client/connection related to a specific -// peer. The address is included for logging purposes -type DeliverClient struct { - Client pb.DeliverClient - Connection pb.Deliver_DeliverClient - Address string -} - -func NewDeliverGroup( - deliverClients []pb.DeliverClient, - peerAddresses []string, - signer identity.SignerSerializer, - certificate tls.Certificate, - channelID string, - txid string, -) *DeliverGroup { - clients := make([]*DeliverClient, len(deliverClients)) - for i, client := range deliverClients { - address := peerAddresses[i] - if address == "" { - address = viper.GetString("peer.address") - } - dc := &DeliverClient{ - Client: client, - Address: address, - } - clients[i] = dc - } - - dg := &DeliverGroup{ - Clients: clients, - Certificate: certificate, - ChannelID: channelID, - TxID: txid, - Signer: signer, - } - - return dg -} - -// Connect waits for all deliver clients in the group to connect to -// the peer's deliver service, receive an error, or for the context -// to timeout. An error will be returned whenever even a single -// deliver client fails to connect to its peer -func (dg *DeliverGroup) Connect(ctx context.Context) error { - dg.wg.Add(len(dg.Clients)) - for _, client := range dg.Clients { - go dg.ClientConnect(ctx, client) - } - readyCh := make(chan struct{}) - go dg.WaitForWG(readyCh) - - select { - case <-readyCh: - if dg.Error != nil { - err := errors.WithMessage(dg.Error, "failed to connect to deliver on all peers") - return err - } - case <-ctx.Done(): - err := errors.New("timed out waiting for connection to deliver on all peers") - return err - } - - return nil -} - -// ClientConnect sends a deliver seek info envelope using the -// provided deliver client, setting the deliverGroup's Error -// field upon any error -func (dg *DeliverGroup) ClientConnect(ctx context.Context, dc *DeliverClient) { - defer dg.wg.Done() - df, err := dc.Client.DeliverFiltered(ctx) - if err != nil { - err = errors.WithMessagef(err, "error connecting to deliver filtered at %s", dc.Address) - dg.setError(err) - return - } - defer df.CloseSend() - dc.Connection = df - - envelope := createDeliverEnvelope(dg.ChannelID, dg.Certificate, dg.Signer) - err = df.Send(envelope) - if err != nil { - err = errors.WithMessagef(err, "error sending deliver seek info envelope to %s", dc.Address) - dg.setError(err) - return - } -} - -// Wait waits for all deliver client connections in the group to -// either receive a block with the txid, an error, or for the -// context to timeout -func (dg *DeliverGroup) Wait(ctx context.Context) error { - if len(dg.Clients) == 0 { - return nil - } - - dg.wg.Add(len(dg.Clients)) - for _, client := range dg.Clients { - go dg.ClientWait(client) - } - readyCh := make(chan struct{}) - go dg.WaitForWG(readyCh) - - select { - case <-readyCh: - if dg.Error != nil { - return dg.Error - } - case <-ctx.Done(): - err := errors.New("timed out waiting for txid on all peers") - return err - } - - return nil -} - -// ClientWait waits for the specified deliver client to receive -// a block event with the requested txid -func (dg *DeliverGroup) ClientWait(dc *DeliverClient) { - defer dg.wg.Done() - for { - resp, err := dc.Connection.Recv() - if err != nil { - err = errors.WithMessagef(err, "error receiving from deliver filtered at %s", dc.Address) - dg.setError(err) - return - } - switch r := resp.Type.(type) { - case *pb.DeliverResponse_FilteredBlock: - filteredTransactions := r.FilteredBlock.FilteredTransactions - for _, tx := range filteredTransactions { - if tx.Txid == dg.TxID { - logger.Infof("txid [%s] committed with status (%s) at %s", dg.TxID, tx.TxValidationCode, dc.Address) - if tx.TxValidationCode != pb.TxValidationCode_VALID { - err = errors.Errorf("transaction invalidated with status (%s)", tx.TxValidationCode) - dg.setError(err) - } - return - } - } - case *pb.DeliverResponse_Status: - err = errors.Errorf("deliver completed with status (%s) before txid received", r.Status) - dg.setError(err) - return - default: - err = errors.Errorf("received unexpected response type (%T) from %s", r, dc.Address) - dg.setError(err) - return - } - } -} - -// WaitForWG waits for the deliverGroup's wait group and closes -// the channel when ready -func (dg *DeliverGroup) WaitForWG(readyCh chan struct{}) { - dg.wg.Wait() - close(readyCh) -} - -// setError serializes an error for the deliverGroup -func (dg *DeliverGroup) setError(err error) { - dg.mutex.Lock() - dg.Error = err - dg.mutex.Unlock() -} - -func createDeliverEnvelope( - channelID string, - certificate tls.Certificate, - signer identity.SignerSerializer, -) *pcommon.Envelope { - var tlsCertHash []byte - // check for client certificate and create hash if present - if len(certificate.Certificate) > 0 { - tlsCertHash = util.ComputeSHA256(certificate.Certificate[0]) - } - - start := &ab.SeekPosition{ - Type: &ab.SeekPosition_Newest{ - Newest: &ab.SeekNewest{}, - }, - } - - stop := &ab.SeekPosition{ - Type: &ab.SeekPosition_Specified{ - Specified: &ab.SeekSpecified{ - Number: math.MaxUint64, - }, - }, - } - - seekInfo := &ab.SeekInfo{ - Start: start, - Stop: stop, - Behavior: ab.SeekInfo_BLOCK_UNTIL_READY, - } - - env, err := protoutil.CreateSignedEnvelopeWithTLSBinding( - pcommon.HeaderType_DELIVER_SEEK_INFO, - channelID, - signer, - seekInfo, - int32(0), - uint64(0), - tlsCertHash, - ) - if err != nil { - logger.Errorf("Error signing envelope: %s", err) - return nil - } - - return env -} diff --git a/internal/peer/chaincode/common_test.go b/internal/peer/chaincode/common_test.go deleted file mode 100644 index 885779a6337..00000000000 --- a/internal/peer/chaincode/common_test.go +++ /dev/null @@ -1,841 +0,0 @@ -/* -Copyright Digital Asset Holdings, LLC. All Rights Reserved. -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "context" - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "sort" - "testing" - "time" - - "github.com/golang/protobuf/proto" - cb "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/common/policydsl" - "github.com/hyperledger/fabric/core/config/configtest" - "github.com/hyperledger/fabric/internal/peer/chaincode/mock" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/hyperledger/fabric/internal/pkg/identity" - . "github.com/onsi/gomega" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" -) - -//go:generate counterfeiter -o mock/signer_serializer.go --fake-name SignerSerializer . signerSerializer - -type signerSerializer interface { - identity.SignerSerializer -} - -//go:generate counterfeiter -o mock/deliver.go --fake-name Deliver . deliver - -type deliver interface { - pb.Deliver_DeliverClient -} - -//go:generate counterfeiter -o mock/deliver_client.go --fake-name PeerDeliverClient . peerDeliverClient - -type peerDeliverClient interface { - pb.DeliverClient -} - -func TestCheckChaincodeCmdParamsWithNewCallingSchema(t *testing.T) { - chaincodeCtorJSON = `{ "Args":["func", "param"] }` - chaincodePath = "some/path" - chaincodeName = "somename" - require := require.New(t) - result := checkChaincodeCmdParams(&cobra.Command{}) - - require.Nil(result) -} - -func TestCheckChaincodeCmdParamsWithOldCallingSchema(t *testing.T) { - chaincodeCtorJSON = `{ "Function":"func", "Args":["param"] }` - chaincodePath = "some/path" - chaincodeName = "somename" - require := require.New(t) - result := checkChaincodeCmdParams(&cobra.Command{}) - - require.Nil(result) -} - -func TestCheckChaincodeCmdParamsWithoutName(t *testing.T) { - chaincodeCtorJSON = `{ "Function":"func", "Args":["param"] }` - chaincodePath = "some/path" - chaincodeName = "" - require := require.New(t) - result := checkChaincodeCmdParams(&cobra.Command{}) - - require.Error(result) -} - -func TestCheckChaincodeCmdParamsWithFunctionOnly(t *testing.T) { - chaincodeCtorJSON = `{ "Function":"func" }` - chaincodePath = "some/path" - chaincodeName = "somename" - require := require.New(t) - result := checkChaincodeCmdParams(&cobra.Command{}) - - require.Error(result) -} - -func TestCheckChaincodeCmdParamsEmptyCtor(t *testing.T) { - chaincodeCtorJSON = `{}` - chaincodePath = "some/path" - chaincodeName = "somename" - require := require.New(t) - result := checkChaincodeCmdParams(&cobra.Command{}) - - require.Error(result) -} - -func TestCheckValidJSON(t *testing.T) { - validJSON := `{"Args":["a","b","c"]}` - input := &chaincodeInput{} - if err := json.Unmarshal([]byte(validJSON), &input); err != nil { - t.Fail() - t.Logf("Chaincode argument error: %s", err) - return - } - - validJSON = `{"Function":"f", "Args":["a","b","c"]}` - if err := json.Unmarshal([]byte(validJSON), &input); err != nil { - t.Fail() - t.Logf("Chaincode argument error: %s", err) - return - } - - validJSON = `{"Function":"f", "Args":[]}` - if err := json.Unmarshal([]byte(validJSON), &input); err != nil { - t.Fail() - t.Logf("Chaincode argument error: %s", err) - return - } - - validJSON = `{"Function":"f"}` - if err := json.Unmarshal([]byte(validJSON), &input); err != nil { - t.Fail() - t.Logf("Chaincode argument error: %s", err) - return - } -} - -func TestCheckInvalidJSON(t *testing.T) { - invalidJSON := `{["a","b","c"]}` - input := &chaincodeInput{} - if err := json.Unmarshal([]byte(invalidJSON), &input); err == nil { - t.Fail() - t.Logf("Bar argument error should have been caught: %s", invalidJSON) - return - } - - invalidJSON = `{"Function":}` - if err := json.Unmarshal([]byte(invalidJSON), &input); err == nil { - t.Fail() - t.Logf("Chaincode argument error: %s", err) - t.Logf("Bar argument error should have been caught: %s", invalidJSON) - return - } -} - -const sampleCollectionConfigGood = `[ - { - "name": "foo", - "policy": "OR('A.member', 'B.member')", - "requiredPeerCount": 3, - "maxPeerCount": 483279847, - "blockToLive":10, - "memberOnlyRead": true, - "memberOnlyWrite": true - } -]` - -const sampleCollectionConfigGoodNoMaxPeerCountOrRequiredPeerCount = `[ - { - "name": "foo", - "policy": "OR('A.member', 'B.member')", - "blockToLive":10, - "memberOnlyRead": true, - "memberOnlyWrite": true - } -]` - -const sampleCollectionConfigGoodWithSignaturePolicy = `[ - { - "name": "foo", - "policy": "OR('A.member', 'B.member')", - "requiredPeerCount": 3, - "maxPeerCount": 483279847, - "blockToLive":10, - "memberOnlyRead": true, - "memberOnlyWrite": true, - "endorsementPolicy": { - "signaturePolicy": "OR('A.member', 'B.member')" - } - } -]` - -const sampleCollectionConfigGoodWithChannelConfigPolicy = `[ - { - "name": "foo", - "policy": "OR('A.member', 'B.member')", - "requiredPeerCount": 3, - "maxPeerCount": 483279847, - "blockToLive":10, - "memberOnlyRead": true, - "memberOnlyWrite": true, - "endorsementPolicy": { - "channelConfigPolicy": "/Channel/Application/Endorsement" - } - } -]` - -const sampleCollectionConfigBad = `[ - { - "name": "foo", - "policy": "barf", - "requiredPeerCount": 3, - "maxPeerCount": 483279847 - } -]` - -const sampleCollectionConfigBadInvalidSignaturePolicy = `[ - { - "name": "foo", - "policy": "OR('A.member', 'B.member')", - "requiredPeerCount": 3, - "maxPeerCount": 483279847, - "blockToLive":10, - "memberOnlyRead": true, - "memberOnlyWrite": true, - "endorsementPolicy": { - "signaturePolicy": "invalid" - } - } -]` - -const sampleCollectionConfigBadSignaturePolicyAndChannelConfigPolicy = `[ - { - "name": "foo", - "policy": "OR('A.member', 'B.member')", - "requiredPeerCount": 3, - "maxPeerCount": 483279847, - "blockToLive":10, - "memberOnlyRead": true, - "memberOnlyWrite": true, - "endorsementPolicy": { - "signaturePolicy": "OR('A.member', 'B.member')", - "channelConfigPolicy": "/Channel/Application/Endorsement" - } - } -]` - -func TestCollectionParsing(t *testing.T) { - ccp, ccpBytes, err := getCollectionConfigFromBytes([]byte(sampleCollectionConfigGood)) - require.NoError(t, err) - require.NotNil(t, ccp) - require.NotNil(t, ccpBytes) - conf := ccp.Config[0].GetStaticCollectionConfig() - pol, _ := policydsl.FromString("OR('A.member', 'B.member')") - require.Equal(t, 3, int(conf.RequiredPeerCount)) - require.Equal(t, 483279847, int(conf.MaximumPeerCount)) - require.Equal(t, "foo", conf.Name) - require.True(t, proto.Equal(pol, conf.MemberOrgsPolicy.GetSignaturePolicy())) - require.Equal(t, 10, int(conf.BlockToLive)) - require.Equal(t, true, conf.MemberOnlyRead) - require.Nil(t, conf.EndorsementPolicy) - t.Logf("conf=%s", conf) - - // Test default values for RequiredPeerCount and MaxPeerCount - ccp, ccpBytes, err = getCollectionConfigFromBytes([]byte(sampleCollectionConfigGoodNoMaxPeerCountOrRequiredPeerCount)) - require.NoError(t, err) - require.NotNil(t, ccp) - require.NotNil(t, ccpBytes) - conf = ccp.Config[0].GetStaticCollectionConfig() - pol, _ = policydsl.FromString("OR('A.member', 'B.member')") - require.Equal(t, 0, int(conf.RequiredPeerCount)) - require.Equal(t, 1, int(conf.MaximumPeerCount)) - require.Equal(t, "foo", conf.Name) - require.True(t, proto.Equal(pol, conf.MemberOrgsPolicy.GetSignaturePolicy())) - require.Equal(t, 10, int(conf.BlockToLive)) - require.Equal(t, true, conf.MemberOnlyRead) - require.Nil(t, conf.EndorsementPolicy) - t.Logf("conf=%s", conf) - - ccp, ccpBytes, err = getCollectionConfigFromBytes([]byte(sampleCollectionConfigGoodWithSignaturePolicy)) - require.NoError(t, err) - require.NotNil(t, ccp) - require.NotNil(t, ccpBytes) - conf = ccp.Config[0].GetStaticCollectionConfig() - pol, _ = policydsl.FromString("OR('A.member', 'B.member')") - require.Equal(t, 3, int(conf.RequiredPeerCount)) - require.Equal(t, 483279847, int(conf.MaximumPeerCount)) - require.Equal(t, "foo", conf.Name) - require.True(t, proto.Equal(pol, conf.MemberOrgsPolicy.GetSignaturePolicy())) - require.Equal(t, 10, int(conf.BlockToLive)) - require.Equal(t, true, conf.MemberOnlyRead) - require.True(t, proto.Equal(pol, conf.EndorsementPolicy.GetSignaturePolicy())) - t.Logf("conf=%s", conf) - - ccp, ccpBytes, err = getCollectionConfigFromBytes([]byte(sampleCollectionConfigGoodWithChannelConfigPolicy)) - require.NoError(t, err) - require.NotNil(t, ccp) - require.NotNil(t, ccpBytes) - conf = ccp.Config[0].GetStaticCollectionConfig() - pol, _ = policydsl.FromString("OR('A.member', 'B.member')") - require.Equal(t, 3, int(conf.RequiredPeerCount)) - require.Equal(t, 483279847, int(conf.MaximumPeerCount)) - require.Equal(t, "foo", conf.Name) - require.True(t, proto.Equal(pol, conf.MemberOrgsPolicy.GetSignaturePolicy())) - require.Equal(t, 10, int(conf.BlockToLive)) - require.Equal(t, true, conf.MemberOnlyRead) - require.Equal(t, "/Channel/Application/Endorsement", conf.EndorsementPolicy.GetChannelConfigPolicyReference()) - t.Logf("conf=%s", conf) - - failureTests := []struct { - name string - collectionConfig string - expectedErr string - }{ - { - name: "Invalid member orgs policy", - collectionConfig: sampleCollectionConfigBad, - expectedErr: "invalid policy barf: unrecognized token 'barf' in policy string", - }, - { - name: "Invalid collection config", - collectionConfig: "barf", - expectedErr: "could not parse the collection configuration: invalid character 'b' looking for beginning of value", - }, - { - name: "Invalid signature policy", - collectionConfig: sampleCollectionConfigBadInvalidSignaturePolicy, - expectedErr: `invalid endorsement policy [&chaincode.endorsementPolicy{ChannelConfigPolicy:"", SignaturePolicy:"invalid"}]: invalid signature policy: invalid`, - }, - { - name: "Signature policy and channel config policy both specified", - collectionConfig: sampleCollectionConfigBadSignaturePolicyAndChannelConfigPolicy, - expectedErr: `invalid endorsement policy [&chaincode.endorsementPolicy{ChannelConfigPolicy:"/Channel/Application/Endorsement", SignaturePolicy:"OR('A.member', 'B.member')"}]: cannot specify both "--signature-policy" and "--channel-config-policy"`, - }, - } - - for _, test := range failureTests { - t.Run(test.name, func(t *testing.T) { - ccp, ccpBytes, err = getCollectionConfigFromBytes([]byte(test.collectionConfig)) - require.EqualError(t, err, test.expectedErr) - require.Nil(t, ccp) - require.Nil(t, ccpBytes) - }) - } -} - -func TestValidatePeerConnectionParams(t *testing.T) { - defer resetFlags() - defer viper.Reset() - require := require.New(t) - configtest.SetDevFabricConfigPath(t) - - // TLS disabled - viper.Set("peer.tls.enabled", false) - - // failure - more than one peer and TLS root cert - not invoke - resetFlags() - peerAddresses = []string{"peer0", "peer1"} - tlsRootCertFiles = []string{"cert0", "cert1"} - err := validatePeerConnectionParameters("query") - require.Error(err) - require.Contains(err.Error(), "command can only be executed against one peer") - - // success - peer provided and no TLS root certs - // TLS disabled - resetFlags() - peerAddresses = []string{"peer0"} - err = validatePeerConnectionParameters("query") - require.NoError(err) - require.Nil(tlsRootCertFiles) - - // success - more TLS root certs than peers - // TLS disabled - resetFlags() - peerAddresses = []string{"peer0"} - tlsRootCertFiles = []string{"cert0", "cert1"} - err = validatePeerConnectionParameters("invoke") - require.NoError(err) - require.Nil(tlsRootCertFiles) - - // success - multiple peers and no TLS root certs - invoke - // TLS disabled - resetFlags() - peerAddresses = []string{"peer0", "peer1"} - err = validatePeerConnectionParameters("invoke") - require.NoError(err) - require.Nil(tlsRootCertFiles) - - // TLS enabled - viper.Set("peer.tls.enabled", true) - - // failure - uneven number of peers and TLS root certs - invoke - // TLS enabled - resetFlags() - peerAddresses = []string{"peer0", "peer1"} - tlsRootCertFiles = []string{"cert0"} - err = validatePeerConnectionParameters("invoke") - require.Error(err) - require.Contains(err.Error(), fmt.Sprintf("number of peer addresses (%d) does not match the number of TLS root cert files (%d)", len(peerAddresses), len(tlsRootCertFiles))) - - // success - more than one peer and TLS root certs - invoke - // TLS enabled - resetFlags() - peerAddresses = []string{"peer0", "peer1"} - tlsRootCertFiles = []string{"cert0", "cert1"} - err = validatePeerConnectionParameters("invoke") - require.NoError(err) - - // failure - connection profile doesn't exist - resetFlags() - connectionProfile = "blah" - err = validatePeerConnectionParameters("invoke") - require.Error(err) - require.Contains(err.Error(), "error reading connection profile") - - // failure - connection profile has peer defined in channel config but - // not in peer config - resetFlags() - channelID = "mychannel" - connectionProfile = "testdata/connectionprofile-uneven.yaml" - err = validatePeerConnectionParameters("invoke") - require.Error(err) - require.Contains(err.Error(), "defined in the channel config but doesn't have associated peer config") - - // success - connection profile exists - resetFlags() - channelID = "mychannel" - connectionProfile = "testdata/connectionprofile.yaml" - err = validatePeerConnectionParameters("invoke") - require.NoError(err) -} - -func TestInitCmdFactoryFailures(t *testing.T) { - defer resetFlags() - require := require.New(t) - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.Nil(err) - - // failure validating peer connection parameters - resetFlags() - peerAddresses = []string{"peer0", "peer1"} - tlsRootCertFiles = []string{"cert0", "cert1"} - cf, err := InitCmdFactory("query", true, false, cryptoProvider) - require.Error(err) - require.Contains(err.Error(), "error validating peer connection parameters: 'query' command can only be executed against one peer") - require.Nil(cf) - - // failure - no peers supplied and endorser client is needed - resetFlags() - peerAddresses = []string{} - cf, err = InitCmdFactory("query", true, false, cryptoProvider) - require.Error(err) - require.Contains(err.Error(), "no endorser clients retrieved") - require.Nil(cf) - - // failure - orderer client is needed, ordering endpoint is empty and no - // endorser client supplied - resetFlags() - peerAddresses = nil - cf, err = InitCmdFactory("invoke", false, true, cryptoProvider) - require.Error(err) - require.Contains(err.Error(), "no ordering endpoint or endorser client supplied") - require.Nil(cf) -} - -func TestDeliverGroupConnect(t *testing.T) { - defer resetFlags() - g := NewGomegaWithT(t) - - // success - mockDeliverClients := []*DeliverClient{ - { - Client: getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_VALID, "txid0"), - Address: "peer0", - }, - { - Client: getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_VALID, "txid0"), - Address: "peer1", - }, - } - dg := DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err := dg.Connect(context.Background()) - g.Expect(err).To(BeNil()) - - // failure - DeliverFiltered returns error - mockDC := &mock.PeerDeliverClient{} - mockDC.DeliverFilteredReturns(nil, errors.New("icecream")) - mockDeliverClients = []*DeliverClient{ - { - Client: mockDC, - Address: "peer0", - }, - } - dg = DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err = dg.Connect(context.Background()) - g.Expect(err.Error()).To(ContainSubstring("error connecting to deliver filtered")) - g.Expect(err.Error()).To(ContainSubstring("icecream")) - - // failure - Send returns error - mockD := &mock.Deliver{} - mockD.SendReturns(errors.New("blah")) - mockDC.DeliverFilteredReturns(mockD, nil) - mockDeliverClients = []*DeliverClient{ - { - Client: mockDC, - Address: "peer0", - }, - } - dg = DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err = dg.Connect(context.Background()) - g.Expect(err.Error()).To(ContainSubstring("error sending deliver seek info")) - g.Expect(err.Error()).To(ContainSubstring("blah")) - - // failure - deliver registration timeout - delayChan := make(chan struct{}) - mockDCDelay := getMockDeliverClientRegisterAfterDelay(delayChan) - mockDeliverClients = []*DeliverClient{ - { - Client: mockDCDelay, - Address: "peer0", - }, - } - ctx, cancelFunc := context.WithTimeout(context.Background(), 10*time.Millisecond) - defer cancelFunc() - dg = DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err = dg.Connect(ctx) - g.Expect(err.Error()).To(ContainSubstring("timed out waiting for connection to deliver on all peers")) - close(delayChan) -} - -func TestDeliverGroupWait(t *testing.T) { - defer resetFlags() - g := NewGomegaWithT(t) - - // success - mockConn := &mock.Deliver{} - filteredResp := &pb.DeliverResponse{ - Type: &pb.DeliverResponse_FilteredBlock{FilteredBlock: createFilteredBlock(pb.TxValidationCode_VALID, "txid0")}, - } - mockConn.RecvReturns(filteredResp, nil) - mockDeliverClients := []*DeliverClient{ - { - Connection: mockConn, - Address: "peer0", - }, - } - dg := DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err := dg.Wait(context.Background()) - g.Expect(err).To(BeNil()) - - // failure - Recv returns error - mockConn = &mock.Deliver{} - mockConn.RecvReturns(nil, errors.New("avocado")) - mockDeliverClients = []*DeliverClient{ - { - Connection: mockConn, - Address: "peer0", - }, - } - dg = DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err = dg.Wait(context.Background()) - g.Expect(err.Error()).To(ContainSubstring("error receiving from deliver filtered")) - g.Expect(err.Error()).To(ContainSubstring("avocado")) - - // failure - Recv returns unexpected type - mockConn = &mock.Deliver{} - resp := &pb.DeliverResponse{ - Type: &pb.DeliverResponse_Block{}, - } - mockConn.RecvReturns(resp, nil) - mockDeliverClients = []*DeliverClient{ - { - Connection: mockConn, - Address: "peer0", - }, - } - dg = DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err = dg.Wait(context.Background()) - g.Expect(err.Error()).To(ContainSubstring("unexpected response type")) - - // failure - both connections return error - mockConn = &mock.Deliver{} - mockConn.RecvReturns(nil, errors.New("barbeque")) - mockConn2 := &mock.Deliver{} - mockConn2.RecvReturns(nil, errors.New("tofu")) - mockDeliverClients = []*DeliverClient{ - { - Connection: mockConn, - Address: "peerBBQ", - }, - { - Connection: mockConn2, - Address: "peerTOFU", - }, - } - dg = DeliverGroup{ - Clients: mockDeliverClients, - ChannelID: "testchannel", - Signer: &mock.SignerSerializer{}, - Certificate: tls.Certificate{ - Certificate: [][]byte{[]byte("test")}, - }, - TxID: "txid0", - } - err = dg.Wait(context.Background()) - g.Expect(err.Error()).To(SatisfyAny( - ContainSubstring("barbeque"), - ContainSubstring("tofu"))) -} - -func TestChaincodeInvokeOrQuery_waitForEvent(t *testing.T) { - defer resetFlags() - - waitForEvent = true - mockCF, err := getMockChaincodeCmdFactory() - require.NoError(t, err) - peerAddresses = []string{"peer0", "peer1"} - channelID := "testchannel" - txID := "txid0" - - t.Run("success - deliver clients returns event with expected txid", func(t *testing.T) { - _, err = ChaincodeInvokeOrQuery( - &pb.ChaincodeSpec{}, - channelID, - txID, - true, - mockCF.Signer, - mockCF.Certificate, - mockCF.EndorserClients, - mockCF.DeliverClients, - mockCF.BroadcastClient, - ) - require.NoError(t, err) - }) - - t.Run("success - one deliver client first receives block without txid and then one with txid", func(t *testing.T) { - filteredBlocks := []*pb.FilteredBlock{ - createFilteredBlock(pb.TxValidationCode_VALID, "theseare", "notthetxidsyouarelookingfor"), - createFilteredBlock(pb.TxValidationCode_VALID, "txid0"), - } - mockDCTwoBlocks := getMockDeliverClientRespondsWithFilteredBlocks(filteredBlocks) - mockDC := getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_VALID, "txid0") - mockDeliverClients := []pb.DeliverClient{mockDCTwoBlocks, mockDC} - - _, err = ChaincodeInvokeOrQuery( - &pb.ChaincodeSpec{}, - channelID, - txID, - true, - mockCF.Signer, - mockCF.Certificate, - mockCF.EndorserClients, - mockDeliverClients, - mockCF.BroadcastClient, - ) - require.NoError(t, err) - }) - - t.Run("failure - one of the deliver clients returns error", func(t *testing.T) { - mockDCErr := getMockDeliverClientWithErr("moist") - mockDC := getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_VALID, "txid0") - mockDeliverClients := []pb.DeliverClient{mockDCErr, mockDC} - - _, err = ChaincodeInvokeOrQuery( - &pb.ChaincodeSpec{}, - channelID, - txID, - true, - mockCF.Signer, - mockCF.Certificate, - mockCF.EndorserClients, - mockDeliverClients, - mockCF.BroadcastClient, - ) - require.Error(t, err) - require.Contains(t, err.Error(), "moist") - }) - - t.Run("failure - transaction committed with non-success validation code", func(t *testing.T) { - mockDC := getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_VALID, "txid0") - mockDCFail := getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_ENDORSEMENT_POLICY_FAILURE, "txid0") - mockDeliverClients := []pb.DeliverClient{mockDCFail, mockDC} - - _, err = ChaincodeInvokeOrQuery( - &pb.ChaincodeSpec{}, - channelID, - txID, - true, - mockCF.Signer, - mockCF.Certificate, - mockCF.EndorserClients, - mockDeliverClients, - mockCF.BroadcastClient, - ) - require.Error(t, err) - require.Equal(t, err.Error(), "transaction invalidated with status (ENDORSEMENT_POLICY_FAILURE)") - }) - - t.Run("failure - deliver returns response status instead of block", func(t *testing.T) { - mockDC := &mock.PeerDeliverClient{} - mockDF := &mock.Deliver{} - resp := &pb.DeliverResponse{ - Type: &pb.DeliverResponse_Status{ - Status: cb.Status_FORBIDDEN, - }, - } - mockDF.RecvReturns(resp, nil) - mockDC.DeliverFilteredReturns(mockDF, nil) - mockDeliverClients := []pb.DeliverClient{mockDC} - _, err = ChaincodeInvokeOrQuery( - &pb.ChaincodeSpec{}, - channelID, - txID, - true, - mockCF.Signer, - mockCF.Certificate, - mockCF.EndorserClients, - mockDeliverClients, - mockCF.BroadcastClient, - ) - require.Error(t, err) - require.Equal(t, err.Error(), "deliver completed with status (FORBIDDEN) before txid received") - }) - - t.Run(" failure - timeout occurs - both deliver clients don't return an event with the expected txid before timeout", func(t *testing.T) { - delayChan := make(chan struct{}) - mockDCDelay := getMockDeliverClientRespondAfterDelay(delayChan, pb.TxValidationCode_VALID, "txid0") - mockDeliverClients := []pb.DeliverClient{mockDCDelay, mockDCDelay} - waitForEventTimeout = 10 * time.Millisecond - - _, err = ChaincodeInvokeOrQuery( - &pb.ChaincodeSpec{}, - channelID, - txID, - true, - mockCF.Signer, - mockCF.Certificate, - mockCF.EndorserClients, - mockDeliverClients, - mockCF.BroadcastClient, - ) - require.Error(t, err) - require.Contains(t, err.Error(), "timed out") - close(delayChan) - }) -} - -func TestProcessProposals(t *testing.T) { - // Build clients that return a range of status codes (for verifying each client is called). - mockClients := []pb.EndorserClient{} - for i := 2; i <= 5; i++ { - response := &pb.ProposalResponse{ - Response: &pb.Response{Status: int32(i * 100)}, - Endorsement: &pb.Endorsement{}, - } - mockClients = append(mockClients, common.GetMockEndorserClient(response, nil)) - } - mockErrorClient := common.GetMockEndorserClient(nil, errors.New("failed to call endorser")) - signedProposal := &pb.SignedProposal{} - t.Run("should process a proposal for a single peer", func(t *testing.T) { - responses, err := processProposals([]pb.EndorserClient{mockClients[0]}, signedProposal) - require.NoError(t, err) - require.Len(t, responses, 1) - require.Equal(t, responses[0].Response.Status, int32(200)) - }) - t.Run("should process a proposal for multiple peers", func(t *testing.T) { - responses, err := processProposals(mockClients, signedProposal) - require.NoError(t, err) - require.Len(t, responses, 4) - // Sort the statuses (as they may turn up in different order) before comparing. - statuses := []int32{} - for _, response := range responses { - statuses = append(statuses, response.Response.Status) - } - sort.Slice(statuses, func(i, j int) bool { return statuses[i] < statuses[j] }) - require.EqualValues(t, []int32{200, 300, 400, 500}, statuses) - }) - t.Run("should return an error from processing a proposal for a single peer", func(t *testing.T) { - responses, err := processProposals([]pb.EndorserClient{mockErrorClient}, signedProposal) - require.EqualError(t, err, "failed to call endorser") - require.Nil(t, responses) - }) - t.Run("should return an error from processing a proposal for a single peer within multiple peers", func(t *testing.T) { - responses, err := processProposals([]pb.EndorserClient{mockClients[0], mockErrorClient, mockClients[1]}, signedProposal) - require.EqualError(t, err, "failed to call endorser") - require.Nil(t, responses) - }) -} diff --git a/internal/peer/chaincode/flags_test.go b/internal/peer/chaincode/flags_test.go deleted file mode 100644 index 8d0d2b820cd..00000000000 --- a/internal/peer/chaincode/flags_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright IBM Corp. 2016-2017 All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "testing" - - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" -) - -func TestOrdererFlags(t *testing.T) { - var ( - ca = "root.crt" - key = "client.key" - cert = "client.crt" - endpoint = "orderer.example.com:7050" - sn = "override.example.com" - ) - - testCmd := &cobra.Command{ - Use: "test", - Run: func(cmd *cobra.Command, args []string) { - t.Logf("rootcert: %s", viper.GetString("orderer.tls.rootcert.file")) - require.Equal(t, ca, viper.GetString("orderer.tls.rootcert.file")) - require.Equal(t, key, viper.GetString("orderer.tls.clientKey.file")) - require.Equal(t, cert, viper.GetString("orderer.tls.clientCert.file")) - require.Equal(t, endpoint, viper.GetString("orderer.address")) - require.Equal(t, sn, viper.GetString("orderer.tls.serverhostoverride")) - require.Equal(t, true, viper.GetBool("orderer.tls.enabled")) - require.Equal(t, true, viper.GetBool("orderer.tls.clientAuthRequired")) - }, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - common.SetOrdererEnv(cmd, args) - }, - } - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - runCmd := Cmd(nil, cryptoProvider) - - runCmd.AddCommand(testCmd) - - runCmd.SetArgs([]string{ - "test", "--cafile", ca, "--keyfile", key, - "--certfile", cert, "--orderer", endpoint, "--tls", "--clientauth", - "--ordererTLSHostnameOverride", sn, - }) - err = runCmd.Execute() - require.NoError(t, err) - - // check env one more time - t.Logf("address: %s", viper.GetString("orderer.address")) - require.Equal(t, ca, viper.GetString("orderer.tls.rootcert.file")) - require.Equal(t, key, viper.GetString("orderer.tls.clientKey.file")) - require.Equal(t, cert, viper.GetString("orderer.tls.clientCert.file")) - require.Equal(t, endpoint, viper.GetString("orderer.address")) - require.Equal(t, sn, viper.GetString("orderer.tls.serverhostoverride")) - require.Equal(t, true, viper.GetBool("orderer.tls.enabled")) - require.Equal(t, true, viper.GetBool("orderer.tls.clientAuthRequired")) -} diff --git a/internal/peer/chaincode/install.go b/internal/peer/chaincode/install.go deleted file mode 100644 index 2d92a6d12cd..00000000000 --- a/internal/peer/chaincode/install.go +++ /dev/null @@ -1,278 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "context" - "os" - - "github.com/golang/protobuf/proto" - cb "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/core/common/ccpackage" - "github.com/hyperledger/fabric/core/common/ccprovider" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/hyperledger/fabric/internal/pkg/identity" - "github.com/hyperledger/fabric/protoutil" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var chaincodeInstallCmd *cobra.Command - -const ( - installCmdName = "install" -) - -// Installer holds the dependencies needed to install -// a chaincode -type Installer struct { - Command *cobra.Command - EndorserClients []pb.EndorserClient - Input *InstallInput - Signer identity.SignerSerializer - CryptoProvider bccsp.BCCSP -} - -// InstallInput holds the input parameters for installing -// a chaincode -type InstallInput struct { - Name string - Version string - Language string - PackageFile string - Path string -} - -// installCmd returns the cobra command for chaincode install -func installCmd(cf *ChaincodeCmdFactory, i *Installer, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodeInstallCmd = &cobra.Command{ - Use: "install", - Short: "Install a chaincode.", - Long: "Install a chaincode on a peer. This installs a chaincode deployment spec package (if provided) or packages the specified chaincode before subsequently installing it.", - ValidArgs: []string{"1"}, - RunE: func(cmd *cobra.Command, args []string) error { - if i == nil { - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), true, false, cryptoProvider) - if err != nil { - return err - } - } - i = &Installer{ - Command: cmd, - EndorserClients: cf.EndorserClients, - Signer: cf.Signer, - CryptoProvider: cryptoProvider, - } - } - return i.installChaincode(args) - }, - } - flagList := []string{ - "lang", - "ctor", - "path", - "name", - "version", - "peerAddresses", - "tlsRootCertFiles", - "connectionProfile", - } - attachFlags(chaincodeInstallCmd, flagList) - - return chaincodeInstallCmd -} - -// installChaincode installs the chaincode -func (i *Installer) installChaincode(args []string) error { - if i.Command != nil { - // Parsing of the command line is done so silence cmd usage - i.Command.SilenceUsage = true - } - - i.setInput(args) - - // LSCC install - return i.install() -} - -func (i *Installer) setInput(args []string) { - i.Input = &InstallInput{ - Name: chaincodeName, - Version: chaincodeVersion, - Path: chaincodePath, - } - - if len(args) > 0 { - i.Input.PackageFile = args[0] - } -} - -// install installs a chaincode deployment spec to "peer.address" -// for use with lscc -func (i *Installer) install() error { - ccPkgMsg, err := i.getChaincodePackageMessage() - if err != nil { - return err - } - - proposal, err := i.createInstallProposal(ccPkgMsg) - if err != nil { - return err - } - - signedProposal, err := protoutil.GetSignedProposal(proposal, i.Signer) - if err != nil { - return errors.WithMessagef(err, "error creating signed proposal for %s", chainFuncName) - } - - return i.submitInstallProposal(signedProposal) -} - -func (i *Installer) submitInstallProposal(signedProposal *pb.SignedProposal) error { - // install is currently only supported for one peer - proposalResponse, err := i.EndorserClients[0].ProcessProposal(context.Background(), signedProposal) - if err != nil { - return errors.WithMessage(err, "error endorsing chaincode install") - } - - if proposalResponse == nil { - return errors.New("error during install: received nil proposal response") - } - - if proposalResponse.Response == nil { - return errors.New("error during install: received proposal response with nil response") - } - - if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) { - return errors.Errorf("install failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message) - } - logger.Infof("Installed remotely: %v", proposalResponse) - - return nil -} - -func (i *Installer) getChaincodePackageMessage() (proto.Message, error) { - // if no package provided, create one - if i.Input.PackageFile == "" { - if i.Input.Path == common.UndefinedParamValue || i.Input.Version == common.UndefinedParamValue || i.Input.Name == common.UndefinedParamValue { - return nil, errors.Errorf("must supply value for %s name, path and version parameters", chainFuncName) - } - // generate a raw ChaincodeDeploymentSpec - ccPkgMsg, err := genChaincodeDeploymentSpec(i.Command, i.Input.Name, i.Input.Version) - if err != nil { - return nil, err - } - return ccPkgMsg, nil - } - - // read in a package generated by the "package" sub-command (and perhaps signed - // by multiple owners with the "signpackage" sub-command) - // var cds *pb.ChaincodeDeploymentSpec - ccPkgMsg, cds, err := getPackageFromFile(i.Input.PackageFile, i.CryptoProvider) - if err != nil { - return nil, err - } - - // get the chaincode details from cds - cName := cds.ChaincodeSpec.ChaincodeId.Name - cVersion := cds.ChaincodeSpec.ChaincodeId.Version - - // if user provided chaincodeName, use it for validation - if i.Input.Name != "" && i.Input.Name != cName { - return nil, errors.Errorf("chaincode name %s does not match name %s in package", i.Input.Name, cName) - } - - // if user provided chaincodeVersion, use it for validation - if i.Input.Version != "" && i.Input.Version != cVersion { - return nil, errors.Errorf("chaincode version %s does not match version %s in packages", i.Input.Version, cVersion) - } - - return ccPkgMsg, nil -} - -func (i *Installer) createInstallProposal(msg proto.Message) (*pb.Proposal, error) { - creator, err := i.Signer.Serialize() - if err != nil { - return nil, errors.WithMessage(err, "error serializing identity") - } - - prop, _, err := protoutil.CreateInstallProposalFromCDS(msg, creator) - if err != nil { - return nil, errors.WithMessagef(err, "error creating proposal for %s", chainFuncName) - } - - return prop, nil -} - -// genChaincodeDeploymentSpec creates ChaincodeDeploymentSpec as the package to install -func genChaincodeDeploymentSpec(cmd *cobra.Command, chaincodeName, chaincodeVersion string) (*pb.ChaincodeDeploymentSpec, error) { - if existed, _ := ccprovider.ChaincodePackageExists(chaincodeName, chaincodeVersion); existed { - return nil, errors.Errorf("chaincode %s:%s already exists", chaincodeName, chaincodeVersion) - } - - spec, err := getChaincodeSpec(cmd) - if err != nil { - return nil, err - } - - cds, err := getChaincodeDeploymentSpec(spec, true) - if err != nil { - return nil, errors.WithMessagef(err, "error getting chaincode deployment spec for %s", chaincodeName) - } - - return cds, nil -} - -// getPackageFromFile get the chaincode package from file and the extracted ChaincodeDeploymentSpec -func getPackageFromFile(ccPkgFile string, cryptoProvider bccsp.BCCSP) (proto.Message, *pb.ChaincodeDeploymentSpec, error) { - ccPkgBytes, err := os.ReadFile(ccPkgFile) - if err != nil { - return nil, nil, err - } - - // the bytes should be a valid package (CDS or SignedCDS) - ccpack, err := ccprovider.GetCCPackage(ccPkgBytes, cryptoProvider) - if err != nil { - return nil, nil, err - } - - // either CDS or Envelope - o := ccpack.GetPackageObject() - - // try CDS first - cds, ok := o.(*pb.ChaincodeDeploymentSpec) - if !ok || cds == nil { - // try Envelope next - env, ok := o.(*cb.Envelope) - if !ok || env == nil { - return nil, nil, errors.New("error extracting valid chaincode package") - } - - // this will check for a valid package Envelope - _, sCDS, err := ccpackage.ExtractSignedCCDepSpec(env) - if err != nil { - return nil, nil, errors.WithMessage(err, "error extracting valid signed chaincode package") - } - - // ...and get the CDS at last - cds, err = protoutil.UnmarshalChaincodeDeploymentSpec(sCDS.ChaincodeDeploymentSpec) - if err != nil { - return nil, nil, errors.WithMessage(err, "error extracting chaincode deployment spec") - } - - err = platformRegistry.ValidateDeploymentSpec(cds.ChaincodeSpec.Type.String(), cds.CodePackage) - if err != nil { - return nil, nil, errors.WithMessage(err, "chaincode deployment spec validation failed") - } - } - - return o, cds, nil -} diff --git a/internal/peer/chaincode/install_test.go b/internal/peer/chaincode/install_test.go deleted file mode 100644 index 68781669af6..00000000000 --- a/internal/peer/chaincode/install_test.go +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - "os" - "testing" - - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" -) - -func initInstallTest(t *testing.T, fsPath string, ec pb.EndorserClient, mockResponse *pb.ProposalResponse) (*cobra.Command, *ChaincodeCmdFactory) { - viper.Set("peer.fileSystemPath", fsPath) - - signer, err := common.GetDefaultSigner() - if err != nil { - t.Fatalf("Get default signer error: %v", err) - } - - if mockResponse == nil { - mockResponse = &pb.ProposalResponse{ - Response: &pb.Response{Status: 200}, - Endorsement: &pb.Endorsement{}, - } - } - if ec == nil { - ec = common.GetMockEndorserClient(mockResponse, nil) - } - - mockCF := &ChaincodeCmdFactory{ - Signer: signer, - EndorserClients: []pb.EndorserClient{ec}, - } - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - cmd := installCmd(mockCF, nil, cryptoProvider) - addFlags(cmd) - - return cmd, mockCF -} - -func TestInstallBadVersion(t *testing.T) { - fsPath := t.TempDir() - - cmd, _ := initInstallTest(t, fsPath, nil, nil) - - args := []string{"-n", "mychaincode", "-p", "github.com/hyperledger/fabric/internal/peer/chaincode/testdata/src/chaincodes/noop"} - cmd.SetArgs(args) - - if err := cmd.Execute(); err == nil { - t.Fatal("Expected error executing install command for version not specified") - } -} - -func TestInstallNonExistentCC(t *testing.T) { - fsPath := t.TempDir() - - cmd, _ := initInstallTest(t, fsPath, nil, nil) - - args := []string{"-n", "badmychaincode", "-p", "github.com/hyperledger/fabric/internal/peer/chaincode/testdata/src/chaincodes/bad_mychaincode", "-v", "testversion"} - cmd.SetArgs(args) - - if err := cmd.Execute(); err == nil { - t.Fatal("Expected error executing install command for bad chaincode") - } - - if _, err := os.Stat(fsPath + "/chaincodes/badmychaincode.testversion"); err == nil { - t.Fatal("chaincode mychaincode.testversion should not exist") - } -} - -func TestInstallFromPackage(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - err := createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", ccpackfile}, false) - if err != nil { - t.Fatalf("could not create package :%v", err) - } - - fsPath := t.TempDir() - - cmd, mockCF := initInstallTest(t, fsPath, nil, nil) - - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 200}, - Endorsement: &pb.Endorsement{}, - } - mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil) - mockCF.EndorserClients = []pb.EndorserClient{mockEndorserClient} - - args := []string{ccpackfile} - cmd.SetArgs(args) - - if err := cmd.Execute(); err != nil { - t.Fatal("error executing install command from package") - } -} - -func TestInstallFromBadPackage(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - err := os.WriteFile(ccpackfile, []byte("really bad CC package"), 0o700) - if err != nil { - t.Fatalf("could not create package :%v", err) - } - - fsPath := t.TempDir() - - cmd, _ := initInstallTest(t, fsPath, nil, nil) - - args := []string{ccpackfile} - cmd.SetArgs(args) - - if err := cmd.Execute(); err == nil { - t.Fatal("expected error installing bad package") - } -} - -func installCC(t *testing.T) error { - defer viper.Reset() - - fsPath := t.TempDir() - cmd, _ := initInstallTest(t, fsPath, nil, nil) - - args := []string{"-n", "mychaincode", "-p", "github.com/hyperledger/fabric/internal/peer/chaincode/testdata/src/chaincodes/noop", "-v", "anotherversion"} - cmd.SetArgs(args) - - if err := cmd.Execute(); err != nil { - return fmt.Errorf("Run chaincode upgrade cmd error:%v", err) - } - - return nil -} - -func TestInstall(t *testing.T) { - if err := installCC(t); err != nil { - t.Fatalf("Install failed with error: %v", err) - } -} diff --git a/internal/peer/chaincode/instantiate.go b/internal/peer/chaincode/instantiate.go deleted file mode 100644 index fe73afaca38..00000000000 --- a/internal/peer/chaincode/instantiate.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "context" - "errors" - "fmt" - - protcommon "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/protoutil" - "github.com/spf13/cobra" -) - -var chaincodeInstantiateCmd *cobra.Command - -const instantiateCmdName = "instantiate" - -const instantiateDesc = "Deploy the specified chaincode to the network." - -// instantiateCmd returns the cobra command for Chaincode Deploy -func instantiateCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodeInstantiateCmd = &cobra.Command{ - Use: instantiateCmdName, - Short: fmt.Sprint(instantiateDesc), - Long: fmt.Sprint(instantiateDesc), - ValidArgs: []string{"1"}, - RunE: func(cmd *cobra.Command, args []string) error { - return chaincodeDeploy(cmd, args, cf, cryptoProvider) - }, - } - flagList := []string{ - "lang", - "ctor", - "name", - "channelID", - "version", - "policy", - "escc", - "vscc", - "collections-config", - "peerAddresses", - "tlsRootCertFiles", - "connectionProfile", - } - attachFlags(chaincodeInstantiateCmd, flagList) - - return chaincodeInstantiateCmd -} - -// instantiate the command via Endorser -func instantiate(cmd *cobra.Command, cf *ChaincodeCmdFactory) (*protcommon.Envelope, error) { - spec, err := getChaincodeSpec(cmd) - if err != nil { - return nil, err - } - - cds, err := getChaincodeDeploymentSpec(spec, false) - if err != nil { - return nil, fmt.Errorf("error getting chaincode code %s: %s", chaincodeName, err) - } - - creator, err := cf.Signer.Serialize() - if err != nil { - return nil, fmt.Errorf("error serializing identity: %s", err) - } - - prop, _, err := protoutil.CreateDeployProposalFromCDS(channelID, cds, creator, policyMarshalled, []byte(escc), []byte(vscc), collectionConfigBytes) - if err != nil { - return nil, fmt.Errorf("error creating proposal %s: %s", chainFuncName, err) - } - - var signedProp *pb.SignedProposal - signedProp, err = protoutil.GetSignedProposal(prop, cf.Signer) - if err != nil { - return nil, fmt.Errorf("error creating signed proposal %s: %s", chainFuncName, err) - } - - // instantiate is currently only supported for one peer - proposalResponse, err := cf.EndorserClients[0].ProcessProposal(context.Background(), signedProp) - if err != nil { - return nil, fmt.Errorf("error endorsing %s: %s", chainFuncName, err) - } - - if proposalResponse != nil { - // assemble a signed transaction (it's an Envelope message) - env, err := protoutil.CreateSignedTx(prop, cf.Signer, proposalResponse) - if err != nil { - return nil, fmt.Errorf("could not assemble transaction, err %s", err) - } - - return env, nil - } - - return nil, nil -} - -// chaincodeDeploy instantiates the chaincode. On success, the chaincode name -// (hash) is printed to STDOUT for use by subsequent chaincode-related CLI -// commands. -func chaincodeDeploy(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { - if channelID == "" { - return errors.New("The required parameter 'channelID' is empty. Rerun the command with -C flag") - } - // Parsing of the command line is done so silence cmd usage - cmd.SilenceUsage = true - - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), true, true, cryptoProvider) - if err != nil { - return err - } - } - defer cf.BroadcastClient.Close() - env, err := instantiate(cmd, cf) - if err != nil { - return err - } - - if env != nil { - err = cf.BroadcastClient.Send(env) - } - - return err -} diff --git a/internal/peer/chaincode/instantiate_test.go b/internal/peer/chaincode/instantiate_test.go deleted file mode 100644 index 816e4977290..00000000000 --- a/internal/peer/chaincode/instantiate_test.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "testing" - - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/stretchr/testify/require" -) - -func TestInstantiateCmd(t *testing.T) { - mockCF, err := getMockChaincodeCmdFactory() - require.NoError(t, err, "Error getting mock chaincode command factory") - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - // basic function tests - tests := []struct { - name string - args []string - errorExpected bool - errMsg string - }{ - { - name: "successful", - args: []string{"-n", "example02", "-v", "anotherversion", "-C", "mychannel", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"}, - errorExpected: false, - errMsg: "Run chaincode instantiate cmd error", - }, - { - name: "no option", - args: []string{}, - errorExpected: true, - errMsg: "Expected error executing instantiate command without required options", - }, - { - name: "missing version", - args: []string{"-n", "example02", "-C", "mychannel", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"}, - errorExpected: true, - errMsg: "Expected error executing instantiate command without the -v option", - }, - { - name: "missing name", - args: []string{"-v", "anotherversion", "-C", "mychannel", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"}, - errorExpected: true, - errMsg: "Expected error executing instantiate command without the -n option", - }, - { - name: "missing channelID", - args: []string{"-n", "example02", "-v", "anotherversion", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"}, - errorExpected: true, - errMsg: "Expected error executing instantiate command without the -C option", - }, - { - name: "missing ctor", - args: []string{"-n", "example02", "-C", "mychannel", "-v", "anotherversion"}, - errorExpected: true, - errMsg: "Expected error executing instantiate command without the -c option", - }, - { - name: "successful with policy", - args: []string{"-P", "OR('MSP.member', 'MSP.WITH.DOTS.member', 'MSP-WITH-DASHES.member')", "-n", "example02", "-v", "anotherversion", "-C", "mychannel", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"}, - errorExpected: false, - errMsg: "Run chaincode instantiate cmd error", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - resetFlags() - cmd := instantiateCmd(mockCF, cryptoProvider) - addFlags(cmd) - cmd.SetArgs(test.args) - err = cmd.Execute() - checkError(t, err, test.errorExpected, test.errMsg) - }) - } -} - -func checkError(t *testing.T, err error, expectedError bool, msg string) { - if expectedError { - require.Error(t, err, msg) - } else { - require.NoError(t, err, msg) - } -} diff --git a/internal/peer/chaincode/invoke.go b/internal/peer/chaincode/invoke.go deleted file mode 100644 index a428d0eae74..00000000000 --- a/internal/peer/chaincode/invoke.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - - "github.com/hyperledger/fabric/bccsp" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var chaincodeInvokeCmd *cobra.Command - -// invokeCmd returns the cobra command for Chaincode Invoke -func invokeCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodeInvokeCmd = &cobra.Command{ - Use: "invoke", - Short: fmt.Sprintf("Invoke the specified %s.", chainFuncName), - Long: fmt.Sprintf("Invoke the specified %s. It will try to commit the endorsed transaction to the network.", chainFuncName), - ValidArgs: []string{"1"}, - RunE: func(cmd *cobra.Command, args []string) error { - return chaincodeInvoke(cmd, cf, cryptoProvider) - }, - } - flagList := []string{ - "name", - "ctor", - "isInit", - "channelID", - "peerAddresses", - "tlsRootCertFiles", - "connectionProfile", - "waitForEvent", - "waitForEventTimeout", - } - attachFlags(chaincodeInvokeCmd, flagList) - - return chaincodeInvokeCmd -} - -func chaincodeInvoke(cmd *cobra.Command, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { - if channelID == "" { - return errors.New("The required parameter 'channelID' is empty. Rerun the command with -C flag") - } - // Parsing of the command line is done so silence cmd usage - cmd.SilenceUsage = true - - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), true, true, cryptoProvider) - if err != nil { - return err - } - } - defer cf.BroadcastClient.Close() - - return chaincodeInvokeOrQuery(cmd, true, cf) -} diff --git a/internal/peer/chaincode/invoke_test.go b/internal/peer/chaincode/invoke_test.go deleted file mode 100644 index 6bcc5560819..00000000000 --- a/internal/peer/chaincode/invoke_test.go +++ /dev/null @@ -1,411 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "context" - "errors" - "fmt" - "testing" - "time" - - cb "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/common/flogging/floggingtest" - "github.com/hyperledger/fabric/internal/peer/chaincode/mock" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/hyperledger/fabric/msp" - "github.com/hyperledger/fabric/protoutil" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" -) - -func TestInvokeCmd(t *testing.T) { - defer viper.Reset() - defer resetFlags() - - resetFlags() - mockCF, err := getMockChaincodeCmdFactory() - require.NoError(t, err, "Error getting mock chaincode command factory") - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - // Error case 0: no channelID specified - cmd := invokeCmd(mockCF, cryptoProvider) - addFlags(cmd) - args := []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}"} - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "'peer chaincode invoke' command should have returned error when called without -C flag") - - // Success case - cmd = invokeCmd(mockCF, cryptoProvider) - addFlags(cmd) - args = []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}", "-C", "mychannel"} - cmd.SetArgs(args) - err = cmd.Execute() - require.NoError(t, err, "Run chaincode invoke cmd error") - - // set timeout for error cases - viper.Set("peer.client.connTimeout", 10*time.Millisecond) - - // Error case 1: no orderer endpoints - t.Logf("Start error case 1: no orderer endpoints") - getEndorserClient := common.GetEndorserClientFnc - getOrdererEndpointOfChain := common.GetOrdererEndpointOfChainFnc - getBroadcastClient := common.GetBroadcastClientFnc - getDefaultSigner := common.GetDefaultSignerFnc - getDeliverClient := common.GetDeliverClientFnc - getPeerDeliverClient := common.GetPeerDeliverClientFnc - defer func() { - common.GetEndorserClientFnc = getEndorserClient - common.GetOrdererEndpointOfChainFnc = getOrdererEndpointOfChain - common.GetBroadcastClientFnc = getBroadcastClient - common.GetDefaultSignerFnc = getDefaultSigner - common.GetDeliverClientFnc = getDeliverClient - common.GetPeerDeliverClientFnc = getPeerDeliverClient - }() - common.GetEndorserClientFnc = func(string, string) (pb.EndorserClient, error) { - return mockCF.EndorserClients[0], nil - } - common.GetOrdererEndpointOfChainFnc = func(chainID string, signer common.Signer, endorserClient pb.EndorserClient, cryptoProvider bccsp.BCCSP) ([]string, error) { - return []string{}, nil - } - cmd = invokeCmd(nil, cryptoProvider) - addFlags(cmd) - args = []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}", "-C", "mychannel"} - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err) - - // Error case 2: getEndorserClient returns error - t.Logf("Start error case 2: getEndorserClient returns error") - common.GetEndorserClientFnc = func(string, string) (pb.EndorserClient, error) { - return nil, errors.New("error") - } - err = cmd.Execute() - require.Error(t, err) - - // Error case 3: getDeliverClient returns error - t.Logf("Start error case 3: getDeliverClient returns error") - common.GetDeliverClientFnc = func(string, string) (pb.Deliver_DeliverClient, error) { - return nil, errors.New("error") - } - err = cmd.Execute() - require.Error(t, err) - - // Error case 4 : getPeerDeliverClient returns error - t.Logf("Start error case 4: getPeerDeliverClient returns error") - common.GetPeerDeliverClientFnc = func(string, string) (pb.DeliverClient, error) { - return nil, errors.New("error") - } - err = cmd.Execute() - require.Error(t, err) - - // Error case 5: getDefaultSignerFnc returns error - t.Logf("Start error case 5: getDefaultSignerFnc returns error") - common.GetEndorserClientFnc = func(string, string) (pb.EndorserClient, error) { - return mockCF.EndorserClients[0], nil - } - common.GetPeerDeliverClientFnc = func(string, string) (pb.DeliverClient, error) { - return mockCF.DeliverClients[0], nil - } - common.GetDefaultSignerFnc = func() (msp.SigningIdentity, error) { - return nil, errors.New("error") - } - err = cmd.Execute() - require.Error(t, err) - common.GetDefaultSignerFnc = common.GetDefaultSigner - - // Error case 6: getOrdererEndpointOfChainFnc returns error - t.Logf("Start error case 6: getOrdererEndpointOfChainFnc returns error") - common.GetEndorserClientFnc = func(string, string) (pb.EndorserClient, error) { - return mockCF.EndorserClients[0], nil - } - common.GetOrdererEndpointOfChainFnc = func(chainID string, signer common.Signer, endorserClient pb.EndorserClient, cryptoProvider bccsp.BCCSP) ([]string, error) { - return nil, errors.New("error") - } - err = cmd.Execute() - require.Error(t, err) - - // Error case 7: getBroadcastClient returns error - t.Logf("Start error case 7: getBroadcastClient returns error") - common.GetOrdererEndpointOfChainFnc = func(chainID string, signer common.Signer, endorserClient pb.EndorserClient, cryptoProvider bccsp.BCCSP) ([]string, error) { - return []string{"localhost:9999"}, nil - } - common.GetBroadcastClientFnc = func() (common.BroadcastClient, error) { - return nil, errors.New("error") - } - err = cmd.Execute() - require.Error(t, err) - - // Success case - t.Logf("Start success case") - common.GetBroadcastClientFnc = func() (common.BroadcastClient, error) { - return mockCF.BroadcastClient, nil - } - err = cmd.Execute() - require.NoError(t, err) -} - -func TestInvokeCmdSimulateESCCPluginResponse(t *testing.T) { - defer resetFlags() - mockCF, err := getMockChaincodeCmdFactory() - require.NoError(t, err, "Error getting mock chaincode command factory") - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - // success case - simulate an ESCC plugin that endorses a chaincode response - // with status greater than shim.ERRORTHRESHOLD or even shim.ERROR - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 504}, - Endorsement: &pb.Endorsement{}, - } - mockCF.EndorserClients = []pb.EndorserClient{ - common.GetMockEndorserClient(mockResponse, nil), - common.GetMockEndorserClient(mockResponse, nil), - } - - // set logger to logger with a backend that writes to a byte buffer - oldLogger := logger - defer func() { logger = oldLogger }() - l, recorder := floggingtest.NewTestLogger(t) - logger = l - - cmd := invokeCmd(mockCF, cryptoProvider) - addFlags(cmd) - args := []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}", "-C", "mychannel"} - cmd.SetArgs(args) - - err = cmd.Execute() - require.NoError(t, err, "Run chaincode invoke cmd error") - - require.NotEmpty(t, recorder.MessagesContaining("Chaincode invoke successful"), "missing invoke success log record") - require.NotEmpty(t, recorder.MessagesContaining("result: "), "missing result log record") -} - -func TestInvokeCmdEndorsementError(t *testing.T) { - defer resetFlags() - mockCF, err := getMockChaincodeCmdFactoryWithErr() - require.NoError(t, err, "Error getting mock chaincode command factory") - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - cmd := invokeCmd(mockCF, cryptoProvider) - addFlags(cmd) - args := []string{"-n", "example02", "-C", "mychannel", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}"} - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "Expected error executing invoke command") -} - -func TestInvokeCmdEndorsementFailure(t *testing.T) { - defer resetFlags() - ccRespStatus := [2]int32{502, 400} - ccRespPayload := [][]byte{[]byte("Invalid function name"), []byte("Incorrect parameters")} - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - for i := 0; i < 2; i++ { - mockCF, err := getMockChaincodeCmdFactoryEndorsementFailure(ccRespStatus[i], ccRespPayload[i]) - require.NoError(t, err, "Error getting mock chaincode command factory") - - cmd := invokeCmd(mockCF, cryptoProvider) - addFlags(cmd) - args := []string{"-C", "mychannel", "-n", "example02", "-c", "{\"Args\": [\"invokeinvalid\",\"a\",\"b\",\"10\"]}"} - cmd.SetArgs(args) - - err = cmd.Execute() - require.Error(t, err) - require.Contains(t, err.Error(), "endorsement failure during invoke") - require.Contains(t, err.Error(), fmt.Sprintf("response: status:%d payload:\"%s\"", ccRespStatus[i], ccRespPayload[i])) - } -} - -// Returns mock chaincode command factory with multiple endorser and deliver clients -func getMockChaincodeCmdFactory() (*ChaincodeCmdFactory, error) { - signer, err := common.GetDefaultSigner() - if err != nil { - return nil, err - } - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 200}, - Endorsement: &pb.Endorsement{}, - } - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil), common.GetMockEndorserClient(mockResponse, nil)} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockDC := getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_VALID, "txid0") - mockDeliverClients := []pb.DeliverClient{mockDC, mockDC} - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - DeliverClients: mockDeliverClients, - } - return mockCF, nil -} - -// Returns mock chaincode command factory that is constructed with an endorser -// client that returns an error for proposal request and a deliver client -func getMockChaincodeCmdFactoryWithErr() (*ChaincodeCmdFactory, error) { - signer, err := common.GetDefaultSigner() - if err != nil { - return nil, err - } - - errMsg := "invoke error" - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(nil, errors.New(errMsg))} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockDeliverClients := []pb.DeliverClient{getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode_INVALID_OTHER_REASON, "txid0")} - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - DeliverClients: mockDeliverClients, - } - return mockCF, nil -} - -// Returns mock chaincode command factory with an endorser client (that fails) and -// a deliver client -func getMockChaincodeCmdFactoryEndorsementFailure(ccRespStatus int32, ccRespPayload []byte) (*ChaincodeCmdFactory, error) { - signer, err := common.GetDefaultSigner() - if err != nil { - return nil, err - } - - // create a proposal from a ChaincodeInvocationSpec - prop, _, err := protoutil.CreateChaincodeProposal(cb.HeaderType_ENDORSER_TRANSACTION, "testchannelid", createCIS(), nil) - if err != nil { - return nil, fmt.Errorf("Could not create chaincode proposal, err %s\n", err) - } - - response := &pb.Response{Status: ccRespStatus, Payload: ccRespPayload} - result := []byte("res") - - mockRespFailure, err := protoutil.CreateProposalResponseFailure(prop.Header, prop.Payload, response, result, nil, "foo") - if err != nil { - return nil, fmt.Errorf("Could not create proposal response failure, err %s\n", err) - } - - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockRespFailure, nil)} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockDeliverClients := []pb.DeliverClient{getMockDeliverClientResponseWithTxStatusAndID(pb.TxValidationCode(mockRespFailure.Response.Status), "txid0")} - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - DeliverClients: mockDeliverClients, - } - return mockCF, nil -} - -func createCIS() *pb.ChaincodeInvocationSpec { - return &pb.ChaincodeInvocationSpec{ - ChaincodeSpec: &pb.ChaincodeSpec{ - Type: pb.ChaincodeSpec_GOLANG, - ChaincodeId: &pb.ChaincodeID{Name: "chaincode_name"}, - Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("arg1"), []byte("arg2")}}, - }, - } -} - -func getMockDeliverClientResponseWithTxStatusAndID(txStatus pb.TxValidationCode, txID string) *mock.PeerDeliverClient { - mockDC := &mock.PeerDeliverClient{} - mockDC.DeliverFilteredStub = func(ctx context.Context, opts ...grpc.CallOption) (pb.Deliver_DeliverFilteredClient, error) { - return getMockDeliverConnectionResponseWithTxStatusAndID(txStatus, txID), nil - } - return mockDC -} - -func getMockDeliverConnectionResponseWithTxStatusAndID(txStatus pb.TxValidationCode, txID string) *mock.Deliver { - mockDF := &mock.Deliver{} - resp := &pb.DeliverResponse{ - Type: &pb.DeliverResponse_FilteredBlock{ - FilteredBlock: createFilteredBlock(txStatus, txID), - }, - } - mockDF.RecvReturns(resp, nil) - return mockDF -} - -func getMockDeliverClientRespondsWithFilteredBlocks(fb []*pb.FilteredBlock) *mock.PeerDeliverClient { - mockDC := &mock.PeerDeliverClient{} - mockDC.DeliverFilteredStub = func(ctx context.Context, opts ...grpc.CallOption) (pb.Deliver_DeliverFilteredClient, error) { - mockDF := &mock.Deliver{} - for i, f := range fb { - resp := &pb.DeliverResponse{ - Type: &pb.DeliverResponse_FilteredBlock{ - FilteredBlock: f, - }, - } - mockDF.RecvReturnsOnCall(i, resp, nil) - } - return mockDF, nil - } - return mockDC -} - -func getMockDeliverClientRegisterAfterDelay(delayChan chan struct{}) *mock.PeerDeliverClient { - mockDC := &mock.PeerDeliverClient{} - mockDC.DeliverFilteredStub = func(ctx context.Context, opts ...grpc.CallOption) (pb.Deliver_DeliverFilteredClient, error) { - mockDF := &mock.Deliver{} - mockDF.SendStub = func(*cb.Envelope) error { - <-delayChan - return nil - } - return mockDF, nil - } - return mockDC -} - -func getMockDeliverClientRespondAfterDelay(delayChan chan struct{}, txStatus pb.TxValidationCode, txID string) *mock.PeerDeliverClient { - mockDC := &mock.PeerDeliverClient{} - mockDC.DeliverFilteredStub = func(ctx context.Context, opts ...grpc.CallOption) (pb.Deliver_DeliverFilteredClient, error) { - mockDF := &mock.Deliver{} - mockDF.RecvStub = func() (*pb.DeliverResponse, error) { - <-delayChan - resp := &pb.DeliverResponse{ - Type: &pb.DeliverResponse_FilteredBlock{ - FilteredBlock: createFilteredBlock(txStatus, txID), - }, - } - return resp, nil - } - return mockDF, nil - } - return mockDC -} - -func getMockDeliverClientWithErr(errMsg string) *mock.PeerDeliverClient { - mockDC := &mock.PeerDeliverClient{} - mockDC.DeliverFilteredStub = func(ctx context.Context, opts ...grpc.CallOption) (pb.Deliver_DeliverFilteredClient, error) { - return nil, fmt.Errorf(errMsg) - } - return mockDC -} - -func createFilteredBlock(txStatus pb.TxValidationCode, txIDs ...string) *pb.FilteredBlock { - var filteredTransactions []*pb.FilteredTransaction - for _, txID := range txIDs { - ft := &pb.FilteredTransaction{ - Txid: txID, - TxValidationCode: txStatus, - } - filteredTransactions = append(filteredTransactions, ft) - } - fb := &pb.FilteredBlock{ - Number: 0, - ChannelId: "testchannel", - FilteredTransactions: filteredTransactions, - } - return fb -} diff --git a/internal/peer/chaincode/list.go b/internal/peer/chaincode/list.go deleted file mode 100644 index 39287f607e4..00000000000 --- a/internal/peer/chaincode/list.go +++ /dev/null @@ -1,170 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "bytes" - "context" - "encoding/hex" - "fmt" - "reflect" - "strings" - - "github.com/golang/protobuf/proto" - cb "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/protoutil" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - chaincodeListCmd *cobra.Command - getInstalledChaincodes bool - getInstantiatedChaincodes bool -) - -// listCmd returns the cobra command for listing -// the installed or instantiated chaincodes -func listCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodeListCmd = &cobra.Command{ - Use: "list", - Short: "Get the instantiated chaincodes on a channel or installed chaincodes on a peer.", - Long: "Get the instantiated chaincodes in the channel if specify channel, or get installed chaincodes on the peer", - RunE: func(cmd *cobra.Command, args []string) error { - return getChaincodes(cmd, cf, cryptoProvider) - }, - } - - flagList := []string{ - "channelID", - "installed", - "instantiated", - "peerAddresses", - "tlsRootCertFiles", - "connectionProfile", - } - attachFlags(chaincodeListCmd, flagList) - - return chaincodeListCmd -} - -func getChaincodes(cmd *cobra.Command, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { - if getInstantiatedChaincodes && channelID == "" { - return errors.New("The required parameter 'channelID' is empty. Rerun the command with -C flag") - } - // Parsing of the command line is done so silence cmd usage - cmd.SilenceUsage = true - - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), true, false, cryptoProvider) - if err != nil { - return err - } - } - - creator, err := cf.Signer.Serialize() - if err != nil { - return fmt.Errorf("error serializing identity: %s", err) - } - - var proposal *pb.Proposal - - if getInstalledChaincodes == getInstantiatedChaincodes { - return errors.New("must explicitly specify \"--installed\" or \"--instantiated\"") - } - - if getInstalledChaincodes { - proposal, _, err = protoutil.CreateGetInstalledChaincodesProposal(creator) - } - - if getInstantiatedChaincodes { - proposal, _, err = protoutil.CreateGetChaincodesProposal(channelID, creator) - } - - if err != nil { - return errors.WithMessage(err, "error creating proposal") - } - - var signedProposal *pb.SignedProposal - signedProposal, err = protoutil.GetSignedProposal(proposal, cf.Signer) - if err != nil { - return errors.WithMessage(err, "error creating signed proposal") - } - - // list is currently only supported for one peer - proposalResponse, err := cf.EndorserClients[0].ProcessProposal(context.Background(), signedProposal) - if err != nil { - return errors.WithMessage(err, "error endorsing proposal") - } - - if proposalResponse.Response == nil { - return errors.Errorf("proposal response had nil response") - } - - if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) { - return errors.Errorf("bad response: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message) - } - - return printResponse(getInstalledChaincodes, getInstantiatedChaincodes, proposalResponse) -} - -// printResponse prints the information included in the response -// from the server. If getInstalledChaincodes is set to false, the -// proposal response will be interpreted as containing instantiated -// chaincode information. -func printResponse(getInstalledChaincodes, getInstantiatedChaincodes bool, proposalResponse *pb.ProposalResponse) error { - cqr := &pb.ChaincodeQueryResponse{} - err := proto.Unmarshal(proposalResponse.Response.Payload, cqr) - if err != nil { - return err - } - - if getInstalledChaincodes { - fmt.Println("Get installed chaincodes on peer:") - } else { - fmt.Printf("Get instantiated chaincodes on channel %s:\n", channelID) - } - - for _, chaincode := range cqr.Chaincodes { - fmt.Printf("%v\n", ccInfo{chaincode}.String()) - } - - return nil -} - -type ccInfo struct { - *pb.ChaincodeInfo -} - -func (cci ccInfo) String() string { - b := bytes.Buffer{} - md := reflect.ValueOf(*cci.ChaincodeInfo) - md2 := reflect.Indirect(reflect.ValueOf(*cci.ChaincodeInfo)).Type() - for i := 0; i < md.NumField(); i++ { - f := md.Field(i) - val := f.String() - if isBytes(f) { - val = hex.EncodeToString(f.Bytes()) - } - if len(val) == 0 { - continue - } - // Skip the proto-internal generated fields - if strings.HasPrefix(md2.Field(i).Name, "XXX") { - continue - } - b.WriteString(fmt.Sprintf("%s: %s, ", md2.Field(i).Name, val)) - } - return b.String()[:len(b.String())-2] -} - -func isBytes(v reflect.Value) bool { - return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 -} diff --git a/internal/peer/chaincode/list_test.go b/internal/peer/chaincode/list_test.go deleted file mode 100644 index 56c5645ab22..00000000000 --- a/internal/peer/chaincode/list_test.go +++ /dev/null @@ -1,176 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "encoding/hex" - "fmt" - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/stretchr/testify/require" -) - -func TestChaincodeListCmd(t *testing.T) { - signer, err := common.GetDefaultSigner() - if err != nil { - t.Fatalf("Get default signer error: %s", err) - } - - installedCqr := &pb.ChaincodeQueryResponse{ - Chaincodes: []*pb.ChaincodeInfo{ - {Name: "mycc1", Version: "1.0", Path: "codePath1", Input: "input", Escc: "escc", Vscc: "vscc", Id: []byte{1, 2, 3}}, - {Name: "mycc2", Version: "1.0", Path: "codePath2", Input: "input", Escc: "escc", Vscc: "vscc"}, - }, - } - installedCqrBytes, err := proto.Marshal(installedCqr) - if err != nil { - t.Fatalf("Marshal error: %s", err) - } - - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 200, Payload: installedCqrBytes}, - Endorsement: &pb.Endorsement{}, - } - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil)} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - } - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - cmd := listCmd(mockCF, cryptoProvider) - - t.Run("get installed chaincodes - lscc", func(t *testing.T) { - resetFlags() - - args := []string{"--installed"} - cmd.SetArgs(args) - if err := cmd.Execute(); err != nil { - t.Errorf("Run chaincode list cmd to get installed chaincodes error:%v", err) - } - }) - - t.Run("get instantiated chaincodes - no channel", func(t *testing.T) { - resetFlags() - - args := []string{"--instantiated"} - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "Run chaincode list cmd to get instantiated chaincodes should fail if invoked without -C flag") - }) - - t.Run("get instantiated chaincodes - no channel", func(t *testing.T) { - resetFlags() - - args := []string{"--instantiated"} - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "Run chaincode list cmd to get instantiated chaincodes should fail if invoked without -C flag") - }) - - t.Run("get instantiated chaincodes - success", func(t *testing.T) { - resetFlags() - instantiatedChaincodesCmd := listCmd(mockCF, cryptoProvider) - args := []string{"--instantiated", "-C", "mychannel"} - instantiatedChaincodesCmd.SetArgs(args) - if err := instantiatedChaincodesCmd.Execute(); err != nil { - t.Errorf("Run chaincode list cmd to get instantiated chaincodes error:%v", err) - } - }) - - t.Run("both --installed and --instantiated set - no channel", func(t *testing.T) { - resetFlags() - - // Wrong case: Set both "--installed" and "--instantiated" - cmd = listCmd(mockCF, cryptoProvider) - args := []string{"--installed", "--instantiated"} - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "Run chaincode list cmd to get instantiated/installed chaincodes should fail if invoked without -C flag") - }) - - t.Run("both --installed and --instantiated set - no channel", func(t *testing.T) { - resetFlags() - args := []string{"--installed", "--instantiated", "-C", "mychannel"} - cmd.SetArgs(args) - expectErr := fmt.Errorf("must explicitly specify \"--installed\" or \"--instantiated\"") - err = cmd.Execute() - require.Error(t, err) - require.Equal(t, expectErr.Error(), err.Error()) - }) - - t.Run("neither --installed nor --instantiated set", func(t *testing.T) { - resetFlags() - args := []string{"-C", "mychannel"} - cmd.SetArgs(args) - - expectErr := fmt.Errorf("must explicitly specify \"--installed\" or \"--instantiated\"") - err = cmd.Execute() - require.Error(t, err) - require.Equal(t, expectErr.Error(), err.Error()) - }) -} - -func TestChaincodeListFailure(t *testing.T) { - signer, err := common.GetDefaultSigner() - if err != nil { - t.Fatalf("Get default signer error: %s", err) - } - - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 500, Message: "error message"}, - Endorsement: &pb.Endorsement{}, - } - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil)} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - } - - // reset channelID, it might have been set by previous test - channelID = "" - - resetFlags() - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - // Get instantiated chaincodes - instantiatedChaincodesCmd := listCmd(mockCF, cryptoProvider) - args := []string{"--instantiated", "-C", "mychannel"} - instantiatedChaincodesCmd.SetArgs(args) - err = instantiatedChaincodesCmd.Execute() - require.Error(t, err) - require.Regexp(t, "bad response: 500 - error message", err.Error()) -} - -func TestString(t *testing.T) { - id := []byte{1, 2, 3, 4, 5} - idBytes := hex.EncodeToString(id) - b, _ := hex.DecodeString(idBytes) - ccInf := &ccInfo{ - ChaincodeInfo: &pb.ChaincodeInfo{ - Name: "ccName", - Id: b, - Version: "1.0", - Escc: "escc", - Input: "input", - Vscc: "vscc", - }, - } - require.Equal(t, "Name: ccName, Version: 1.0, Input: input, Escc: escc, Vscc: vscc, Id: 0102030405", ccInf.String()) -} diff --git a/internal/peer/chaincode/mock/deliver.go b/internal/peer/chaincode/mock/deliver.go deleted file mode 100644 index 5d1a5e3c37e..00000000000 --- a/internal/peer/chaincode/mock/deliver.go +++ /dev/null @@ -1,587 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package mock - -import ( - "context" - "sync" - - "github.com/hyperledger/fabric-protos-go/common" - "github.com/hyperledger/fabric-protos-go/peer" - "google.golang.org/grpc/metadata" -) - -type Deliver struct { - CloseSendStub func() error - closeSendMutex sync.RWMutex - closeSendArgsForCall []struct { - } - closeSendReturns struct { - result1 error - } - closeSendReturnsOnCall map[int]struct { - result1 error - } - ContextStub func() context.Context - contextMutex sync.RWMutex - contextArgsForCall []struct { - } - contextReturns struct { - result1 context.Context - } - contextReturnsOnCall map[int]struct { - result1 context.Context - } - HeaderStub func() (metadata.MD, error) - headerMutex sync.RWMutex - headerArgsForCall []struct { - } - headerReturns struct { - result1 metadata.MD - result2 error - } - headerReturnsOnCall map[int]struct { - result1 metadata.MD - result2 error - } - RecvStub func() (*peer.DeliverResponse, error) - recvMutex sync.RWMutex - recvArgsForCall []struct { - } - recvReturns struct { - result1 *peer.DeliverResponse - result2 error - } - recvReturnsOnCall map[int]struct { - result1 *peer.DeliverResponse - result2 error - } - RecvMsgStub func(interface{}) error - recvMsgMutex sync.RWMutex - recvMsgArgsForCall []struct { - arg1 interface{} - } - recvMsgReturns struct { - result1 error - } - recvMsgReturnsOnCall map[int]struct { - result1 error - } - SendStub func(*common.Envelope) error - sendMutex sync.RWMutex - sendArgsForCall []struct { - arg1 *common.Envelope - } - sendReturns struct { - result1 error - } - sendReturnsOnCall map[int]struct { - result1 error - } - SendMsgStub func(interface{}) error - sendMsgMutex sync.RWMutex - sendMsgArgsForCall []struct { - arg1 interface{} - } - sendMsgReturns struct { - result1 error - } - sendMsgReturnsOnCall map[int]struct { - result1 error - } - TrailerStub func() metadata.MD - trailerMutex sync.RWMutex - trailerArgsForCall []struct { - } - trailerReturns struct { - result1 metadata.MD - } - trailerReturnsOnCall map[int]struct { - result1 metadata.MD - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *Deliver) CloseSend() error { - fake.closeSendMutex.Lock() - ret, specificReturn := fake.closeSendReturnsOnCall[len(fake.closeSendArgsForCall)] - fake.closeSendArgsForCall = append(fake.closeSendArgsForCall, struct { - }{}) - fake.recordInvocation("CloseSend", []interface{}{}) - fake.closeSendMutex.Unlock() - if fake.CloseSendStub != nil { - return fake.CloseSendStub() - } - if specificReturn { - return ret.result1 - } - fakeReturns := fake.closeSendReturns - return fakeReturns.result1 -} - -func (fake *Deliver) CloseSendCallCount() int { - fake.closeSendMutex.RLock() - defer fake.closeSendMutex.RUnlock() - return len(fake.closeSendArgsForCall) -} - -func (fake *Deliver) CloseSendCalls(stub func() error) { - fake.closeSendMutex.Lock() - defer fake.closeSendMutex.Unlock() - fake.CloseSendStub = stub -} - -func (fake *Deliver) CloseSendReturns(result1 error) { - fake.closeSendMutex.Lock() - defer fake.closeSendMutex.Unlock() - fake.CloseSendStub = nil - fake.closeSendReturns = struct { - result1 error - }{result1} -} - -func (fake *Deliver) CloseSendReturnsOnCall(i int, result1 error) { - fake.closeSendMutex.Lock() - defer fake.closeSendMutex.Unlock() - fake.CloseSendStub = nil - if fake.closeSendReturnsOnCall == nil { - fake.closeSendReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.closeSendReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *Deliver) Context() context.Context { - fake.contextMutex.Lock() - ret, specificReturn := fake.contextReturnsOnCall[len(fake.contextArgsForCall)] - fake.contextArgsForCall = append(fake.contextArgsForCall, struct { - }{}) - fake.recordInvocation("Context", []interface{}{}) - fake.contextMutex.Unlock() - if fake.ContextStub != nil { - return fake.ContextStub() - } - if specificReturn { - return ret.result1 - } - fakeReturns := fake.contextReturns - return fakeReturns.result1 -} - -func (fake *Deliver) ContextCallCount() int { - fake.contextMutex.RLock() - defer fake.contextMutex.RUnlock() - return len(fake.contextArgsForCall) -} - -func (fake *Deliver) ContextCalls(stub func() context.Context) { - fake.contextMutex.Lock() - defer fake.contextMutex.Unlock() - fake.ContextStub = stub -} - -func (fake *Deliver) ContextReturns(result1 context.Context) { - fake.contextMutex.Lock() - defer fake.contextMutex.Unlock() - fake.ContextStub = nil - fake.contextReturns = struct { - result1 context.Context - }{result1} -} - -func (fake *Deliver) ContextReturnsOnCall(i int, result1 context.Context) { - fake.contextMutex.Lock() - defer fake.contextMutex.Unlock() - fake.ContextStub = nil - if fake.contextReturnsOnCall == nil { - fake.contextReturnsOnCall = make(map[int]struct { - result1 context.Context - }) - } - fake.contextReturnsOnCall[i] = struct { - result1 context.Context - }{result1} -} - -func (fake *Deliver) Header() (metadata.MD, error) { - fake.headerMutex.Lock() - ret, specificReturn := fake.headerReturnsOnCall[len(fake.headerArgsForCall)] - fake.headerArgsForCall = append(fake.headerArgsForCall, struct { - }{}) - fake.recordInvocation("Header", []interface{}{}) - fake.headerMutex.Unlock() - if fake.HeaderStub != nil { - return fake.HeaderStub() - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.headerReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *Deliver) HeaderCallCount() int { - fake.headerMutex.RLock() - defer fake.headerMutex.RUnlock() - return len(fake.headerArgsForCall) -} - -func (fake *Deliver) HeaderCalls(stub func() (metadata.MD, error)) { - fake.headerMutex.Lock() - defer fake.headerMutex.Unlock() - fake.HeaderStub = stub -} - -func (fake *Deliver) HeaderReturns(result1 metadata.MD, result2 error) { - fake.headerMutex.Lock() - defer fake.headerMutex.Unlock() - fake.HeaderStub = nil - fake.headerReturns = struct { - result1 metadata.MD - result2 error - }{result1, result2} -} - -func (fake *Deliver) HeaderReturnsOnCall(i int, result1 metadata.MD, result2 error) { - fake.headerMutex.Lock() - defer fake.headerMutex.Unlock() - fake.HeaderStub = nil - if fake.headerReturnsOnCall == nil { - fake.headerReturnsOnCall = make(map[int]struct { - result1 metadata.MD - result2 error - }) - } - fake.headerReturnsOnCall[i] = struct { - result1 metadata.MD - result2 error - }{result1, result2} -} - -func (fake *Deliver) Recv() (*peer.DeliverResponse, error) { - fake.recvMutex.Lock() - ret, specificReturn := fake.recvReturnsOnCall[len(fake.recvArgsForCall)] - fake.recvArgsForCall = append(fake.recvArgsForCall, struct { - }{}) - fake.recordInvocation("Recv", []interface{}{}) - fake.recvMutex.Unlock() - if fake.RecvStub != nil { - return fake.RecvStub() - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.recvReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *Deliver) RecvCallCount() int { - fake.recvMutex.RLock() - defer fake.recvMutex.RUnlock() - return len(fake.recvArgsForCall) -} - -func (fake *Deliver) RecvCalls(stub func() (*peer.DeliverResponse, error)) { - fake.recvMutex.Lock() - defer fake.recvMutex.Unlock() - fake.RecvStub = stub -} - -func (fake *Deliver) RecvReturns(result1 *peer.DeliverResponse, result2 error) { - fake.recvMutex.Lock() - defer fake.recvMutex.Unlock() - fake.RecvStub = nil - fake.recvReturns = struct { - result1 *peer.DeliverResponse - result2 error - }{result1, result2} -} - -func (fake *Deliver) RecvReturnsOnCall(i int, result1 *peer.DeliverResponse, result2 error) { - fake.recvMutex.Lock() - defer fake.recvMutex.Unlock() - fake.RecvStub = nil - if fake.recvReturnsOnCall == nil { - fake.recvReturnsOnCall = make(map[int]struct { - result1 *peer.DeliverResponse - result2 error - }) - } - fake.recvReturnsOnCall[i] = struct { - result1 *peer.DeliverResponse - result2 error - }{result1, result2} -} - -func (fake *Deliver) RecvMsg(arg1 interface{}) error { - fake.recvMsgMutex.Lock() - ret, specificReturn := fake.recvMsgReturnsOnCall[len(fake.recvMsgArgsForCall)] - fake.recvMsgArgsForCall = append(fake.recvMsgArgsForCall, struct { - arg1 interface{} - }{arg1}) - fake.recordInvocation("RecvMsg", []interface{}{arg1}) - fake.recvMsgMutex.Unlock() - if fake.RecvMsgStub != nil { - return fake.RecvMsgStub(arg1) - } - if specificReturn { - return ret.result1 - } - fakeReturns := fake.recvMsgReturns - return fakeReturns.result1 -} - -func (fake *Deliver) RecvMsgCallCount() int { - fake.recvMsgMutex.RLock() - defer fake.recvMsgMutex.RUnlock() - return len(fake.recvMsgArgsForCall) -} - -func (fake *Deliver) RecvMsgCalls(stub func(interface{}) error) { - fake.recvMsgMutex.Lock() - defer fake.recvMsgMutex.Unlock() - fake.RecvMsgStub = stub -} - -func (fake *Deliver) RecvMsgArgsForCall(i int) interface{} { - fake.recvMsgMutex.RLock() - defer fake.recvMsgMutex.RUnlock() - argsForCall := fake.recvMsgArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *Deliver) RecvMsgReturns(result1 error) { - fake.recvMsgMutex.Lock() - defer fake.recvMsgMutex.Unlock() - fake.RecvMsgStub = nil - fake.recvMsgReturns = struct { - result1 error - }{result1} -} - -func (fake *Deliver) RecvMsgReturnsOnCall(i int, result1 error) { - fake.recvMsgMutex.Lock() - defer fake.recvMsgMutex.Unlock() - fake.RecvMsgStub = nil - if fake.recvMsgReturnsOnCall == nil { - fake.recvMsgReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.recvMsgReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *Deliver) Send(arg1 *common.Envelope) error { - fake.sendMutex.Lock() - ret, specificReturn := fake.sendReturnsOnCall[len(fake.sendArgsForCall)] - fake.sendArgsForCall = append(fake.sendArgsForCall, struct { - arg1 *common.Envelope - }{arg1}) - fake.recordInvocation("Send", []interface{}{arg1}) - fake.sendMutex.Unlock() - if fake.SendStub != nil { - return fake.SendStub(arg1) - } - if specificReturn { - return ret.result1 - } - fakeReturns := fake.sendReturns - return fakeReturns.result1 -} - -func (fake *Deliver) SendCallCount() int { - fake.sendMutex.RLock() - defer fake.sendMutex.RUnlock() - return len(fake.sendArgsForCall) -} - -func (fake *Deliver) SendCalls(stub func(*common.Envelope) error) { - fake.sendMutex.Lock() - defer fake.sendMutex.Unlock() - fake.SendStub = stub -} - -func (fake *Deliver) SendArgsForCall(i int) *common.Envelope { - fake.sendMutex.RLock() - defer fake.sendMutex.RUnlock() - argsForCall := fake.sendArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *Deliver) SendReturns(result1 error) { - fake.sendMutex.Lock() - defer fake.sendMutex.Unlock() - fake.SendStub = nil - fake.sendReturns = struct { - result1 error - }{result1} -} - -func (fake *Deliver) SendReturnsOnCall(i int, result1 error) { - fake.sendMutex.Lock() - defer fake.sendMutex.Unlock() - fake.SendStub = nil - if fake.sendReturnsOnCall == nil { - fake.sendReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.sendReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *Deliver) SendMsg(arg1 interface{}) error { - fake.sendMsgMutex.Lock() - ret, specificReturn := fake.sendMsgReturnsOnCall[len(fake.sendMsgArgsForCall)] - fake.sendMsgArgsForCall = append(fake.sendMsgArgsForCall, struct { - arg1 interface{} - }{arg1}) - fake.recordInvocation("SendMsg", []interface{}{arg1}) - fake.sendMsgMutex.Unlock() - if fake.SendMsgStub != nil { - return fake.SendMsgStub(arg1) - } - if specificReturn { - return ret.result1 - } - fakeReturns := fake.sendMsgReturns - return fakeReturns.result1 -} - -func (fake *Deliver) SendMsgCallCount() int { - fake.sendMsgMutex.RLock() - defer fake.sendMsgMutex.RUnlock() - return len(fake.sendMsgArgsForCall) -} - -func (fake *Deliver) SendMsgCalls(stub func(interface{}) error) { - fake.sendMsgMutex.Lock() - defer fake.sendMsgMutex.Unlock() - fake.SendMsgStub = stub -} - -func (fake *Deliver) SendMsgArgsForCall(i int) interface{} { - fake.sendMsgMutex.RLock() - defer fake.sendMsgMutex.RUnlock() - argsForCall := fake.sendMsgArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *Deliver) SendMsgReturns(result1 error) { - fake.sendMsgMutex.Lock() - defer fake.sendMsgMutex.Unlock() - fake.SendMsgStub = nil - fake.sendMsgReturns = struct { - result1 error - }{result1} -} - -func (fake *Deliver) SendMsgReturnsOnCall(i int, result1 error) { - fake.sendMsgMutex.Lock() - defer fake.sendMsgMutex.Unlock() - fake.SendMsgStub = nil - if fake.sendMsgReturnsOnCall == nil { - fake.sendMsgReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.sendMsgReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *Deliver) Trailer() metadata.MD { - fake.trailerMutex.Lock() - ret, specificReturn := fake.trailerReturnsOnCall[len(fake.trailerArgsForCall)] - fake.trailerArgsForCall = append(fake.trailerArgsForCall, struct { - }{}) - fake.recordInvocation("Trailer", []interface{}{}) - fake.trailerMutex.Unlock() - if fake.TrailerStub != nil { - return fake.TrailerStub() - } - if specificReturn { - return ret.result1 - } - fakeReturns := fake.trailerReturns - return fakeReturns.result1 -} - -func (fake *Deliver) TrailerCallCount() int { - fake.trailerMutex.RLock() - defer fake.trailerMutex.RUnlock() - return len(fake.trailerArgsForCall) -} - -func (fake *Deliver) TrailerCalls(stub func() metadata.MD) { - fake.trailerMutex.Lock() - defer fake.trailerMutex.Unlock() - fake.TrailerStub = stub -} - -func (fake *Deliver) TrailerReturns(result1 metadata.MD) { - fake.trailerMutex.Lock() - defer fake.trailerMutex.Unlock() - fake.TrailerStub = nil - fake.trailerReturns = struct { - result1 metadata.MD - }{result1} -} - -func (fake *Deliver) TrailerReturnsOnCall(i int, result1 metadata.MD) { - fake.trailerMutex.Lock() - defer fake.trailerMutex.Unlock() - fake.TrailerStub = nil - if fake.trailerReturnsOnCall == nil { - fake.trailerReturnsOnCall = make(map[int]struct { - result1 metadata.MD - }) - } - fake.trailerReturnsOnCall[i] = struct { - result1 metadata.MD - }{result1} -} - -func (fake *Deliver) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.closeSendMutex.RLock() - defer fake.closeSendMutex.RUnlock() - fake.contextMutex.RLock() - defer fake.contextMutex.RUnlock() - fake.headerMutex.RLock() - defer fake.headerMutex.RUnlock() - fake.recvMutex.RLock() - defer fake.recvMutex.RUnlock() - fake.recvMsgMutex.RLock() - defer fake.recvMsgMutex.RUnlock() - fake.sendMutex.RLock() - defer fake.sendMutex.RUnlock() - fake.sendMsgMutex.RLock() - defer fake.sendMsgMutex.RUnlock() - fake.trailerMutex.RLock() - defer fake.trailerMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *Deliver) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} diff --git a/internal/peer/chaincode/mock/deliver_client.go b/internal/peer/chaincode/mock/deliver_client.go deleted file mode 100644 index 7f6dc4d391a..00000000000 --- a/internal/peer/chaincode/mock/deliver_client.go +++ /dev/null @@ -1,277 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package mock - -import ( - "context" - "sync" - - "github.com/hyperledger/fabric-protos-go/peer" - "google.golang.org/grpc" -) - -type PeerDeliverClient struct { - DeliverStub func(context.Context, ...grpc.CallOption) (peer.Deliver_DeliverClient, error) - deliverMutex sync.RWMutex - deliverArgsForCall []struct { - arg1 context.Context - arg2 []grpc.CallOption - } - deliverReturns struct { - result1 peer.Deliver_DeliverClient - result2 error - } - deliverReturnsOnCall map[int]struct { - result1 peer.Deliver_DeliverClient - result2 error - } - DeliverFilteredStub func(context.Context, ...grpc.CallOption) (peer.Deliver_DeliverFilteredClient, error) - deliverFilteredMutex sync.RWMutex - deliverFilteredArgsForCall []struct { - arg1 context.Context - arg2 []grpc.CallOption - } - deliverFilteredReturns struct { - result1 peer.Deliver_DeliverFilteredClient - result2 error - } - deliverFilteredReturnsOnCall map[int]struct { - result1 peer.Deliver_DeliverFilteredClient - result2 error - } - DeliverWithPrivateDataStub func(context.Context, ...grpc.CallOption) (peer.Deliver_DeliverWithPrivateDataClient, error) - deliverWithPrivateDataMutex sync.RWMutex - deliverWithPrivateDataArgsForCall []struct { - arg1 context.Context - arg2 []grpc.CallOption - } - deliverWithPrivateDataReturns struct { - result1 peer.Deliver_DeliverWithPrivateDataClient - result2 error - } - deliverWithPrivateDataReturnsOnCall map[int]struct { - result1 peer.Deliver_DeliverWithPrivateDataClient - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *PeerDeliverClient) Deliver(arg1 context.Context, arg2 ...grpc.CallOption) (peer.Deliver_DeliverClient, error) { - fake.deliverMutex.Lock() - ret, specificReturn := fake.deliverReturnsOnCall[len(fake.deliverArgsForCall)] - fake.deliverArgsForCall = append(fake.deliverArgsForCall, struct { - arg1 context.Context - arg2 []grpc.CallOption - }{arg1, arg2}) - fake.recordInvocation("Deliver", []interface{}{arg1, arg2}) - fake.deliverMutex.Unlock() - if fake.DeliverStub != nil { - return fake.DeliverStub(arg1, arg2...) - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.deliverReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PeerDeliverClient) DeliverCallCount() int { - fake.deliverMutex.RLock() - defer fake.deliverMutex.RUnlock() - return len(fake.deliverArgsForCall) -} - -func (fake *PeerDeliverClient) DeliverCalls(stub func(context.Context, ...grpc.CallOption) (peer.Deliver_DeliverClient, error)) { - fake.deliverMutex.Lock() - defer fake.deliverMutex.Unlock() - fake.DeliverStub = stub -} - -func (fake *PeerDeliverClient) DeliverArgsForCall(i int) (context.Context, []grpc.CallOption) { - fake.deliverMutex.RLock() - defer fake.deliverMutex.RUnlock() - argsForCall := fake.deliverArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *PeerDeliverClient) DeliverReturns(result1 peer.Deliver_DeliverClient, result2 error) { - fake.deliverMutex.Lock() - defer fake.deliverMutex.Unlock() - fake.DeliverStub = nil - fake.deliverReturns = struct { - result1 peer.Deliver_DeliverClient - result2 error - }{result1, result2} -} - -func (fake *PeerDeliverClient) DeliverReturnsOnCall(i int, result1 peer.Deliver_DeliverClient, result2 error) { - fake.deliverMutex.Lock() - defer fake.deliverMutex.Unlock() - fake.DeliverStub = nil - if fake.deliverReturnsOnCall == nil { - fake.deliverReturnsOnCall = make(map[int]struct { - result1 peer.Deliver_DeliverClient - result2 error - }) - } - fake.deliverReturnsOnCall[i] = struct { - result1 peer.Deliver_DeliverClient - result2 error - }{result1, result2} -} - -func (fake *PeerDeliverClient) DeliverFiltered(arg1 context.Context, arg2 ...grpc.CallOption) (peer.Deliver_DeliverFilteredClient, error) { - fake.deliverFilteredMutex.Lock() - ret, specificReturn := fake.deliverFilteredReturnsOnCall[len(fake.deliverFilteredArgsForCall)] - fake.deliverFilteredArgsForCall = append(fake.deliverFilteredArgsForCall, struct { - arg1 context.Context - arg2 []grpc.CallOption - }{arg1, arg2}) - fake.recordInvocation("DeliverFiltered", []interface{}{arg1, arg2}) - fake.deliverFilteredMutex.Unlock() - if fake.DeliverFilteredStub != nil { - return fake.DeliverFilteredStub(arg1, arg2...) - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.deliverFilteredReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PeerDeliverClient) DeliverFilteredCallCount() int { - fake.deliverFilteredMutex.RLock() - defer fake.deliverFilteredMutex.RUnlock() - return len(fake.deliverFilteredArgsForCall) -} - -func (fake *PeerDeliverClient) DeliverFilteredCalls(stub func(context.Context, ...grpc.CallOption) (peer.Deliver_DeliverFilteredClient, error)) { - fake.deliverFilteredMutex.Lock() - defer fake.deliverFilteredMutex.Unlock() - fake.DeliverFilteredStub = stub -} - -func (fake *PeerDeliverClient) DeliverFilteredArgsForCall(i int) (context.Context, []grpc.CallOption) { - fake.deliverFilteredMutex.RLock() - defer fake.deliverFilteredMutex.RUnlock() - argsForCall := fake.deliverFilteredArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *PeerDeliverClient) DeliverFilteredReturns(result1 peer.Deliver_DeliverFilteredClient, result2 error) { - fake.deliverFilteredMutex.Lock() - defer fake.deliverFilteredMutex.Unlock() - fake.DeliverFilteredStub = nil - fake.deliverFilteredReturns = struct { - result1 peer.Deliver_DeliverFilteredClient - result2 error - }{result1, result2} -} - -func (fake *PeerDeliverClient) DeliverFilteredReturnsOnCall(i int, result1 peer.Deliver_DeliverFilteredClient, result2 error) { - fake.deliverFilteredMutex.Lock() - defer fake.deliverFilteredMutex.Unlock() - fake.DeliverFilteredStub = nil - if fake.deliverFilteredReturnsOnCall == nil { - fake.deliverFilteredReturnsOnCall = make(map[int]struct { - result1 peer.Deliver_DeliverFilteredClient - result2 error - }) - } - fake.deliverFilteredReturnsOnCall[i] = struct { - result1 peer.Deliver_DeliverFilteredClient - result2 error - }{result1, result2} -} - -func (fake *PeerDeliverClient) DeliverWithPrivateData(arg1 context.Context, arg2 ...grpc.CallOption) (peer.Deliver_DeliverWithPrivateDataClient, error) { - fake.deliverWithPrivateDataMutex.Lock() - ret, specificReturn := fake.deliverWithPrivateDataReturnsOnCall[len(fake.deliverWithPrivateDataArgsForCall)] - fake.deliverWithPrivateDataArgsForCall = append(fake.deliverWithPrivateDataArgsForCall, struct { - arg1 context.Context - arg2 []grpc.CallOption - }{arg1, arg2}) - fake.recordInvocation("DeliverWithPrivateData", []interface{}{arg1, arg2}) - fake.deliverWithPrivateDataMutex.Unlock() - if fake.DeliverWithPrivateDataStub != nil { - return fake.DeliverWithPrivateDataStub(arg1, arg2...) - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.deliverWithPrivateDataReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PeerDeliverClient) DeliverWithPrivateDataCallCount() int { - fake.deliverWithPrivateDataMutex.RLock() - defer fake.deliverWithPrivateDataMutex.RUnlock() - return len(fake.deliverWithPrivateDataArgsForCall) -} - -func (fake *PeerDeliverClient) DeliverWithPrivateDataCalls(stub func(context.Context, ...grpc.CallOption) (peer.Deliver_DeliverWithPrivateDataClient, error)) { - fake.deliverWithPrivateDataMutex.Lock() - defer fake.deliverWithPrivateDataMutex.Unlock() - fake.DeliverWithPrivateDataStub = stub -} - -func (fake *PeerDeliverClient) DeliverWithPrivateDataArgsForCall(i int) (context.Context, []grpc.CallOption) { - fake.deliverWithPrivateDataMutex.RLock() - defer fake.deliverWithPrivateDataMutex.RUnlock() - argsForCall := fake.deliverWithPrivateDataArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *PeerDeliverClient) DeliverWithPrivateDataReturns(result1 peer.Deliver_DeliverWithPrivateDataClient, result2 error) { - fake.deliverWithPrivateDataMutex.Lock() - defer fake.deliverWithPrivateDataMutex.Unlock() - fake.DeliverWithPrivateDataStub = nil - fake.deliverWithPrivateDataReturns = struct { - result1 peer.Deliver_DeliverWithPrivateDataClient - result2 error - }{result1, result2} -} - -func (fake *PeerDeliverClient) DeliverWithPrivateDataReturnsOnCall(i int, result1 peer.Deliver_DeliverWithPrivateDataClient, result2 error) { - fake.deliverWithPrivateDataMutex.Lock() - defer fake.deliverWithPrivateDataMutex.Unlock() - fake.DeliverWithPrivateDataStub = nil - if fake.deliverWithPrivateDataReturnsOnCall == nil { - fake.deliverWithPrivateDataReturnsOnCall = make(map[int]struct { - result1 peer.Deliver_DeliverWithPrivateDataClient - result2 error - }) - } - fake.deliverWithPrivateDataReturnsOnCall[i] = struct { - result1 peer.Deliver_DeliverWithPrivateDataClient - result2 error - }{result1, result2} -} - -func (fake *PeerDeliverClient) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.deliverMutex.RLock() - defer fake.deliverMutex.RUnlock() - fake.deliverFilteredMutex.RLock() - defer fake.deliverFilteredMutex.RUnlock() - fake.deliverWithPrivateDataMutex.RLock() - defer fake.deliverWithPrivateDataMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *PeerDeliverClient) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} diff --git a/internal/peer/chaincode/mock/signer_serializer.go b/internal/peer/chaincode/mock/signer_serializer.go deleted file mode 100644 index 577c415348b..00000000000 --- a/internal/peer/chaincode/mock/signer_serializer.go +++ /dev/null @@ -1,185 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package mock - -import ( - "sync" -) - -type SignerSerializer struct { - SerializeStub func() ([]byte, error) - serializeMutex sync.RWMutex - serializeArgsForCall []struct { - } - serializeReturns struct { - result1 []byte - result2 error - } - serializeReturnsOnCall map[int]struct { - result1 []byte - result2 error - } - SignStub func([]byte) ([]byte, error) - signMutex sync.RWMutex - signArgsForCall []struct { - arg1 []byte - } - signReturns struct { - result1 []byte - result2 error - } - signReturnsOnCall map[int]struct { - result1 []byte - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *SignerSerializer) Serialize() ([]byte, error) { - fake.serializeMutex.Lock() - ret, specificReturn := fake.serializeReturnsOnCall[len(fake.serializeArgsForCall)] - fake.serializeArgsForCall = append(fake.serializeArgsForCall, struct { - }{}) - fake.recordInvocation("Serialize", []interface{}{}) - fake.serializeMutex.Unlock() - if fake.SerializeStub != nil { - return fake.SerializeStub() - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.serializeReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *SignerSerializer) SerializeCallCount() int { - fake.serializeMutex.RLock() - defer fake.serializeMutex.RUnlock() - return len(fake.serializeArgsForCall) -} - -func (fake *SignerSerializer) SerializeCalls(stub func() ([]byte, error)) { - fake.serializeMutex.Lock() - defer fake.serializeMutex.Unlock() - fake.SerializeStub = stub -} - -func (fake *SignerSerializer) SerializeReturns(result1 []byte, result2 error) { - fake.serializeMutex.Lock() - defer fake.serializeMutex.Unlock() - fake.SerializeStub = nil - fake.serializeReturns = struct { - result1 []byte - result2 error - }{result1, result2} -} - -func (fake *SignerSerializer) SerializeReturnsOnCall(i int, result1 []byte, result2 error) { - fake.serializeMutex.Lock() - defer fake.serializeMutex.Unlock() - fake.SerializeStub = nil - if fake.serializeReturnsOnCall == nil { - fake.serializeReturnsOnCall = make(map[int]struct { - result1 []byte - result2 error - }) - } - fake.serializeReturnsOnCall[i] = struct { - result1 []byte - result2 error - }{result1, result2} -} - -func (fake *SignerSerializer) Sign(arg1 []byte) ([]byte, error) { - var arg1Copy []byte - if arg1 != nil { - arg1Copy = make([]byte, len(arg1)) - copy(arg1Copy, arg1) - } - fake.signMutex.Lock() - ret, specificReturn := fake.signReturnsOnCall[len(fake.signArgsForCall)] - fake.signArgsForCall = append(fake.signArgsForCall, struct { - arg1 []byte - }{arg1Copy}) - fake.recordInvocation("Sign", []interface{}{arg1Copy}) - fake.signMutex.Unlock() - if fake.SignStub != nil { - return fake.SignStub(arg1) - } - if specificReturn { - return ret.result1, ret.result2 - } - fakeReturns := fake.signReturns - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *SignerSerializer) SignCallCount() int { - fake.signMutex.RLock() - defer fake.signMutex.RUnlock() - return len(fake.signArgsForCall) -} - -func (fake *SignerSerializer) SignCalls(stub func([]byte) ([]byte, error)) { - fake.signMutex.Lock() - defer fake.signMutex.Unlock() - fake.SignStub = stub -} - -func (fake *SignerSerializer) SignArgsForCall(i int) []byte { - fake.signMutex.RLock() - defer fake.signMutex.RUnlock() - argsForCall := fake.signArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *SignerSerializer) SignReturns(result1 []byte, result2 error) { - fake.signMutex.Lock() - defer fake.signMutex.Unlock() - fake.SignStub = nil - fake.signReturns = struct { - result1 []byte - result2 error - }{result1, result2} -} - -func (fake *SignerSerializer) SignReturnsOnCall(i int, result1 []byte, result2 error) { - fake.signMutex.Lock() - defer fake.signMutex.Unlock() - fake.SignStub = nil - if fake.signReturnsOnCall == nil { - fake.signReturnsOnCall = make(map[int]struct { - result1 []byte - result2 error - }) - } - fake.signReturnsOnCall[i] = struct { - result1 []byte - result2 error - }{result1, result2} -} - -func (fake *SignerSerializer) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.serializeMutex.RLock() - defer fake.serializeMutex.RUnlock() - fake.signMutex.RLock() - defer fake.signMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *SignerSerializer) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} diff --git a/internal/peer/chaincode/package.go b/internal/peer/chaincode/package.go deleted file mode 100644 index b6a23eed59e..00000000000 --- a/internal/peer/chaincode/package.go +++ /dev/null @@ -1,225 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "os" - - "github.com/golang/protobuf/proto" - pcommon "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/bccsp/factory" - "github.com/hyperledger/fabric/common/policydsl" - "github.com/hyperledger/fabric/core/common/ccpackage" - "github.com/hyperledger/fabric/internal/pkg/identity" - mspmgmt "github.com/hyperledger/fabric/msp/mgmt" - "github.com/hyperledger/fabric/protoutil" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - chaincodePackageCmd *cobra.Command - createSignedCCDepSpec bool - signCCDepSpec bool - instantiationPolicy string -) - -const packageCmdName = "package" - -type ccDepSpecFactory func(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) - -func defaultCDSFactory(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) { - return getChaincodeDeploymentSpec(spec, true) -} - -// Packager holds the dependencies needed to package -// a chaincode and write it -type Packager struct { - CDSFactory ccDepSpecFactory - ChaincodeCmdFactory *ChaincodeCmdFactory - Command *cobra.Command - Input *PackageInput - CryptoProvider bccsp.BCCSP -} - -// PackageInput holds the input parameters for packaging a -// ChaincodeInstallPackage -type PackageInput struct { - Name string - Version string - InstantiationPolicy string - CreateSignedCCDepSpec bool - SignCCDepSpec bool - OutputFile string - Path string - Type string -} - -// packageCmd returns the cobra command for packaging chaincode -func packageCmd(cf *ChaincodeCmdFactory, cdsFact ccDepSpecFactory, p *Packager, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodePackageCmd = &cobra.Command{ - Use: "package [outputfile]", - Short: "Package a chaincode", - Long: "Package a chaincode and write the package to a file.", - ValidArgs: []string{"1"}, - RunE: func(cmd *cobra.Command, args []string) error { - if p == nil { - // UT will supply its own mock factory - if cdsFact == nil { - cdsFact = defaultCDSFactory - } - p = &Packager{ - CDSFactory: cdsFact, - ChaincodeCmdFactory: cf, - CryptoProvider: cryptoProvider, - } - } - p.Command = cmd - - return p.packageChaincode(args) - }, - } - flagList := []string{ - "lang", - "path", - "ctor", - "name", - "version", - "cc-package", - "sign", - "instantiate-policy", - } - attachFlags(chaincodePackageCmd, flagList) - - return chaincodePackageCmd -} - -// packageChaincode packages the chaincode. -func (p *Packager) packageChaincode(args []string) error { - if p.Command != nil { - // Parsing of the command line is done so silence cmd usage - p.Command.SilenceUsage = true - } - - if len(args) != 1 { - return errors.New("output file not specified or invalid number of args (filename should be the only arg)") - } - p.setInput(args[0]) - - // LSCC package - return p.packageCC() -} - -func (p *Packager) setInput(outputFile string) { - p.Input = &PackageInput{ - Name: chaincodeName, - Version: chaincodeVersion, - InstantiationPolicy: instantiationPolicy, - CreateSignedCCDepSpec: createSignedCCDepSpec, - SignCCDepSpec: signCCDepSpec, - OutputFile: outputFile, - Path: chaincodePath, - Type: chaincodeLang, - } -} - -// packageCC creates the LSCC chaincode packages -// (ChaincodeDeploymentSpec and SignedChaincodeDeploymentSpec) -func (p *Packager) packageCC() error { - if p.CDSFactory == nil { - return errors.New("chaincode deployment spec factory not specified") - } - - var err error - if p.ChaincodeCmdFactory == nil { - p.ChaincodeCmdFactory, err = InitCmdFactory(p.Command.Name(), false, false, p.CryptoProvider) - if err != nil { - return err - } - } - spec, err := getChaincodeSpec(p.Command) - if err != nil { - return err - } - - cds, err := p.CDSFactory(spec) - if err != nil { - return errors.WithMessagef(err, "error getting chaincode code %s", p.Input.Name) - } - - var bytesToWrite []byte - if createSignedCCDepSpec { - bytesToWrite, err = getChaincodeInstallPackage(cds, p.ChaincodeCmdFactory) - if err != nil { - return err - } - } else { - bytesToWrite = protoutil.MarshalOrPanic(cds) - } - - logger.Debugf("Packaged chaincode into deployment spec of size %d, output file %s", len(bytesToWrite), p.Input.OutputFile) - err = os.WriteFile(p.Input.OutputFile, bytesToWrite, 0o700) - if err != nil { - logger.Errorf("failed writing deployment spec to file [%s]: [%s]", p.Input.OutputFile, err) - return err - } - - return err -} - -func getInstantiationPolicy(policy string) (*pcommon.SignaturePolicyEnvelope, error) { - p, err := policydsl.FromString(policy) - if err != nil { - return nil, errors.WithMessagef(err, "invalid policy %s", policy) - } - return p, nil -} - -// getChaincodeInstallPackage returns either a raw ChaincodeDeploymentSpec or -// a Envelope with ChaincodeDeploymentSpec and (optional) signature -func getChaincodeInstallPackage(cds *pb.ChaincodeDeploymentSpec, cf *ChaincodeCmdFactory) ([]byte, error) { - var owner identity.SignerSerializer - // check if we need to sign and set the owner - if createSignedCCDepSpec && signCCDepSpec { - if cf.Signer == nil { - return nil, errors.New("signing identity not found") - } - owner = cf.Signer - } - - ip := instantiationPolicy - if ip == "" { - // if an instantiation policy is not given, default - // to "admin must sign chaincode instantiation proposals" - mspid, err := mspmgmt.GetLocalMSP(factory.GetDefault()).GetIdentifier() - if err != nil { - return nil, err - } - ip = "AND('" + mspid + ".admin')" - } - - sp, err := getInstantiationPolicy(ip) - if err != nil { - return nil, err - } - - // we get the Envelope of type CHAINCODE_PACKAGE - objToWrite, err := ccpackage.OwnerCreateSignedCCDepSpec(cds, sp, owner) - if err != nil { - return nil, err - } - - // convert the proto object to bytes - bytesToWrite, err := proto.Marshal(objToWrite) - if err != nil { - return nil, errors.Wrap(err, "error marshalling chaincode package") - } - - return bytesToWrite, nil -} diff --git a/internal/peer/chaincode/package_test.go b/internal/peer/chaincode/package_test.go deleted file mode 100644 index 75da11a8bee..00000000000 --- a/internal/peer/chaincode/package_test.go +++ /dev/null @@ -1,213 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - "os" - "testing" - - "github.com/golang/protobuf/proto" - pcommon "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/hyperledger/fabric/msp" - msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" - "github.com/stretchr/testify/require" -) - -func TestMain(m *testing.M) { - err := msptesttools.LoadMSPSetupForTesting() - if err != nil { - panic(fmt.Sprintf("Fatal error when reading MSP config: %s", err)) - } - - os.Exit(m.Run()) -} - -func mockCDSFactory(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) { - return &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: []byte("somecode")}, nil -} - -func extractSignedCCDepSpec(env *pcommon.Envelope) (*pcommon.ChannelHeader, *pb.SignedChaincodeDeploymentSpec, error) { - p := &pcommon.Payload{} - err := proto.Unmarshal(env.Payload, p) - if err != nil { - return nil, nil, err - } - ch := &pcommon.ChannelHeader{} - err = proto.Unmarshal(p.Header.ChannelHeader, ch) - if err != nil { - return nil, nil, err - } - - sp := &pb.SignedChaincodeDeploymentSpec{} - err = proto.Unmarshal(p.Data, sp) - if err != nil { - return nil, nil, err - } - - return ch, sp, nil -} - -// TestCDSPackage tests generation of the old ChaincodeDeploymentSpec install -// which we will presumably continue to support at least for a bit -func TestCDSPackage(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - err := createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", ccpackfile}, false) - if err != nil { - t.Fatalf("Run chaincode package cmd error:%v", err) - } - - b, err := os.ReadFile(ccpackfile) - if err != nil { - t.Fatalf("package file %s not created", ccpackfile) - } - cds := &pb.ChaincodeDeploymentSpec{} - err = proto.Unmarshal(b, cds) - if err != nil { - t.Fatalf("could not unmarshall package into CDS") - } -} - -// helper to create a SignedChaincodeDeploymentSpec -func createSignedCDSPackage(t *testing.T, args []string, sign bool) error { - p := newPackagerForTest(t, sign) - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - cmd := packageCmd(nil, mockCDSFactory, p, cryptoProvider) - addFlags(cmd) - - cmd.SetArgs(args) - - if err := cmd.Execute(); err != nil { - return err - } - - return nil -} - -func mockChaincodeCmdFactoryForTest(sign bool) (*ChaincodeCmdFactory, error) { - var signer msp.SigningIdentity - var err error - if sign { - signer, err = common.GetDefaultSigner() - if err != nil { - return nil, fmt.Errorf("Get default signer error: %v", err) - } - } - - cf := &ChaincodeCmdFactory{Signer: signer} - return cf, nil -} - -// TestSignedCDSPackage generates the new envelope encapsulating -// CDS, policy -func TestSignedCDSPackage(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - err := createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", "-s", ccpackfile}, false) - if err != nil { - t.Fatalf("could not create signed cds package %s", err) - } - - b, err := os.ReadFile(ccpackfile) - if err != nil { - t.Fatalf("package file %s not created", ccpackfile) - } - - e := &pcommon.Envelope{} - err = proto.Unmarshal(b, e) - if err != nil { - t.Fatalf("could not unmarshall envelope") - } - - _, p, err := extractSignedCCDepSpec(e) - if err != nil { - t.Fatalf("could not extract signed dep spec") - } - - if p.OwnerEndorsements != nil { - t.Fatalf("expected no signatures but found endorsements") - } -} - -// TestSignedCDSPackageWithSignature generates the new envelope encapsulating -// CDS, policy and signs the package with local MSP -func TestSignedCDSPackageWithSignature(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - err := createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", "-s", "-S", ccpackfile}, true) - if err != nil { - t.Fatalf("could not create signed cds package %s", err) - } - - b, err := os.ReadFile(ccpackfile) - if err != nil { - t.Fatalf("package file %s not created", ccpackfile) - } - e := &pcommon.Envelope{} - err = proto.Unmarshal(b, e) - if err != nil { - t.Fatalf("could not unmarshall envelope") - } - - _, p, err := extractSignedCCDepSpec(e) - if err != nil { - t.Fatalf("could not extract signed dep spec") - } - - if p.OwnerEndorsements == nil { - t.Fatalf("expected signatures and found nil") - } -} - -func TestNoOwnerToSign(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - // note "-S" requires signer but we are passing fase - err := createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", "-s", "-S", ccpackfile}, false) - - if err == nil { - t.Fatalf("Expected error with nil signer but succeeded") - } -} - -func TestInvalidPolicy(t *testing.T) { - pdir := t.TempDir() - - ccpackfile := pdir + "/ccpack.file" - err := createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", "-s", "-i", "AND('a bad policy')", ccpackfile}, false) - - if err == nil { - t.Fatalf("Expected error with nil signer but succeeded") - } -} - -func newPackagerForTest(t *testing.T /*pr PlatformRegistry, w Writer,*/, sign bool) *Packager { - mockCF, err := mockChaincodeCmdFactoryForTest(sign) - if err != nil { - t.Fatal("error creating mock ChaincodeCmdFactory", err) - } - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - p := &Packager{ - ChaincodeCmdFactory: mockCF, - CDSFactory: mockCDSFactory, - CryptoProvider: cryptoProvider, - } - - return p -} diff --git a/internal/peer/chaincode/query.go b/internal/peer/chaincode/query.go deleted file mode 100644 index 83f9c65cd27..00000000000 --- a/internal/peer/chaincode/query.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "errors" - "fmt" - - "github.com/hyperledger/fabric/bccsp" - "github.com/spf13/cobra" -) - -var chaincodeQueryCmd *cobra.Command - -// queryCmd returns the cobra command for Chaincode Query -func queryCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodeQueryCmd = &cobra.Command{ - Use: "query", - Short: fmt.Sprintf("Query using the specified %s.", chainFuncName), - Long: fmt.Sprintf("Get endorsed result of %s function call and print it. It won't generate transaction.", chainFuncName), - ValidArgs: []string{"1"}, - RunE: func(cmd *cobra.Command, args []string) error { - return chaincodeQuery(cmd, cf, cryptoProvider) - }, - } - flagList := []string{ - "ctor", - "name", - "channelID", - "peerAddresses", - "tlsRootCertFiles", - "connectionProfile", - } - attachFlags(chaincodeQueryCmd, flagList) - - chaincodeQueryCmd.Flags().BoolVarP(&chaincodeQueryRaw, "raw", "r", false, - "If true, output the query value as raw bytes, otherwise format as a printable string") - chaincodeQueryCmd.Flags().BoolVarP(&chaincodeQueryHex, "hex", "x", false, - "If true, output the query value byte array in hexadecimal. Incompatible with --raw") - - return chaincodeQueryCmd -} - -func chaincodeQuery(cmd *cobra.Command, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { - if channelID == "" { - return errors.New("The required parameter 'channelID' is empty. Rerun the command with -C flag") - } - // Parsing of the command line is done so silence cmd usage - cmd.SilenceUsage = true - - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), true, false, cryptoProvider) - if err != nil { - return err - } - } - - return chaincodeInvokeOrQuery(cmd, false, cf) -} diff --git a/internal/peer/chaincode/query_test.go b/internal/peer/chaincode/query_test.go deleted file mode 100644 index 9d15de866d3..00000000000 --- a/internal/peer/chaincode/query_test.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - "testing" - - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/spf13/cobra" - "github.com/stretchr/testify/require" -) - -func TestQueryCmd(t *testing.T) { - mockCF, err := getMockChaincodeCmdFactory() - require.NoError(t, err, "Error getting mock chaincode command factory") - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - // reset channelID, it might have been set by previous test - channelID = "" - - // Failure case: run query command without -C option - args := []string{"-n", "example02", "-c", "{\"Args\": [\"query\",\"a\"]}"} - cmd := newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.Error(t, err, "'peer chaincode query' command should have failed without -C flag") - - // Success case: run query command without -r or -x option - args = []string{"-C", "mychannel", "-n", "example02", "-c", "{\"Args\": [\"query\",\"a\"]}"} - cmd = newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.NoError(t, err, "Run chaincode query cmd error") - - // Success case: run query command with -r option - args = []string{"-r", "-C", "mychannel", "-n", "example02", "-c", "{\"Args\": [\"query\",\"a\"]}"} - cmd = newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.NoError(t, err, "Run chaincode query cmd error") - chaincodeQueryRaw = false - - // Success case: run query command with -x option - args = []string{"-x", "-C", "mychannel", "-n", "example02", "-c", "{\"Args\": [\"query\",\"a\"]}"} - cmd = newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.NoError(t, err, "Run chaincode query cmd error") - - // Failure case: run query command with both -x and -r options - args = []string{"-r", "-x", "-C", "mychannel", "-n", "example02", "-c", "{\"Args\": [\"query\",\"a\"]}"} - cmd = newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.Error(t, err, "Expected error executing query command with both -r and -x options") - - // Failure case: run query command with mock chaincode cmd factory built to return error - mockCF, err = getMockChaincodeCmdFactoryWithErr() - require.NoError(t, err, "Error getting mock chaincode command factory") - args = []string{"-r", "-n", "example02", "-c", "{\"Args\": [\"query\",\"a\"]}"} - cmd = newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.Error(t, err, "Expected error executing query command") -} - -func TestQueryCmdEndorsementFailure(t *testing.T) { - args := []string{"-C", "mychannel", "-n", "example02", "-c", "{\"Args\": [\"queryinvalid\",\"a\"]}"} - ccRespStatus := [2]int32{502, 400} - ccRespPayload := [][]byte{[]byte("Invalid function name"), []byte("Incorrect parameters")} - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - for i := 0; i < 2; i++ { - mockCF, err := getMockChaincodeCmdFactoryEndorsementFailure(ccRespStatus[i], ccRespPayload[i]) - require.NoError(t, err, "Error getting mock chaincode command factory") - - cmd := newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.Error(t, err) - require.Regexp(t, "endorsement failure during query", err.Error()) - require.Regexp(t, fmt.Sprintf("response: status:%d payload:\"%s\"", ccRespStatus[i], ccRespPayload[i]), err.Error()) - } - - // failure - nil proposal response - mockCF, err := getMockChaincodeCmdFactory() - require.NoError(t, err, "Error getting mock chaincode command factory") - mockCF.EndorserClients[0] = common.GetMockEndorserClient(nil, nil) - mockCF.EndorserClients[1] = common.GetMockEndorserClient(nil, nil) - - cmd := newQueryCmdForTest(mockCF, args, cryptoProvider) - err = cmd.Execute() - require.Error(t, err) - require.Regexp(t, "error during query: received nil proposal response", err.Error()) -} - -func newQueryCmdForTest(cf *ChaincodeCmdFactory, args []string, cryptoProvider bccsp.BCCSP) *cobra.Command { - cmd := queryCmd(cf, cryptoProvider) - addFlags(cmd) - cmd.SetArgs(args) - return cmd -} diff --git a/internal/peer/chaincode/signpackage.go b/internal/peer/chaincode/signpackage.go deleted file mode 100644 index d99d2cff482..00000000000 --- a/internal/peer/chaincode/signpackage.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright IBM Corp. 2016 All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - "os" - - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/core/common/ccpackage" - "github.com/hyperledger/fabric/protoutil" - "github.com/spf13/cobra" -) - -// signpackageCmd returns the cobra command for signing a package -func signpackageCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - spCmd := &cobra.Command{ - Use: "signpackage", - Short: "Sign the specified chaincode package", - Long: "Sign the specified chaincode package", - ValidArgs: []string{"2"}, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) < 2 { - return fmt.Errorf("peer chaincode signpackage ") - } - return signpackage(cmd, args[0], args[1], cf, cryptoProvider) - }, - } - - return spCmd -} - -func signpackage(cmd *cobra.Command, ipackageFile string, opackageFile string, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { - // Parsing of the command line is done so silence cmd usage - cmd.SilenceUsage = true - - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), false, false, cryptoProvider) - if err != nil { - return err - } - } - - b, err := os.ReadFile(ipackageFile) - if err != nil { - return err - } - - env := protoutil.UnmarshalEnvelopeOrPanic(b) - - env, err = ccpackage.SignExistingPackage(env, cf.Signer) - if err != nil { - return err - } - - b = protoutil.MarshalOrPanic(env) - err = os.WriteFile(opackageFile, b, 0o700) - if err != nil { - return err - } - - fmt.Printf("Wrote signed package to %s successfully\n", opackageFile) - - return nil -} diff --git a/internal/peer/chaincode/signpackage_test.go b/internal/peer/chaincode/signpackage_test.go deleted file mode 100644 index dd2de3370df..00000000000 --- a/internal/peer/chaincode/signpackage_test.go +++ /dev/null @@ -1,131 +0,0 @@ -/* -Copyright Digital Asset Holdings, LLC. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "fmt" - "os" - "testing" - - "github.com/golang/protobuf/proto" - pcommon "github.com/hyperledger/fabric-protos-go/common" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/stretchr/testify/require" -) - -// helper to sign an existing package -func signExistingPackage(env *pcommon.Envelope, infile, outfile string, cryptoProvider bccsp.BCCSP) error { - signer, err := common.GetDefaultSigner() - if err != nil { - return fmt.Errorf("Get default signer error: %v", err) - } - - mockCF := &ChaincodeCmdFactory{Signer: signer} - - cmd := signpackageCmd(mockCF, cryptoProvider) - addFlags(cmd) - - cmd.SetArgs([]string{infile, outfile}) - - if err := cmd.Execute(); err != nil { - return err - } - - return nil -} - -// TestSignExistingPackage signs an existing package -func TestSignExistingPackage(t *testing.T) { - resetFlags() - defer resetFlags() - pdir := t.TempDir() - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - ccpackfile := pdir + "/ccpack.file" - err = createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", "-s", "-S", ccpackfile}, true) - if err != nil { - t.Fatalf("error creating signed :%v", err) - } - - b, err := os.ReadFile(ccpackfile) - if err != nil { - t.Fatalf("package file %s not created", ccpackfile) - } - - e := &pcommon.Envelope{} - err = proto.Unmarshal(b, e) - if err != nil { - t.Fatalf("could not unmarshall envelope") - } - - signedfile := pdir + "/signed.file" - err = signExistingPackage(e, ccpackfile, signedfile, cryptoProvider) - if err != nil { - t.Fatalf("could not sign envelope") - } - - b, err = os.ReadFile(signedfile) - if err != nil { - t.Fatalf("signed package file %s not created", signedfile) - } - - e = &pcommon.Envelope{} - err = proto.Unmarshal(b, e) - if err != nil { - t.Fatalf("could not unmarshall signed envelope") - } - - _, p, err := extractSignedCCDepSpec(e) - if err != nil { - t.Fatalf("could not extract signed dep spec") - } - - if p.OwnerEndorsements == nil { - t.Fatalf("expected endorsements") - } - - if len(p.OwnerEndorsements) != 2 { - t.Fatalf("expected 2 endorserments but found %d", len(p.OwnerEndorsements)) - } -} - -// TestFailSignUnsignedPackage tries to signs a package that was not originally signed -func TestFailSignUnsignedPackage(t *testing.T) { - resetFlags() - defer resetFlags() - pdir := t.TempDir() - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - - ccpackfile := pdir + "/ccpack.file" - // don't sign it ... no "-S" - err = createSignedCDSPackage(t, []string{"-n", "somecc", "-p", "some/go/package", "-v", "0", "-s", ccpackfile}, true) - if err != nil { - t.Fatalf("error creating signed :%v", err) - } - - b, err := os.ReadFile(ccpackfile) - if err != nil { - t.Fatalf("package file %s not created", ccpackfile) - } - - e := &pcommon.Envelope{} - err = proto.Unmarshal(b, e) - if err != nil { - t.Fatalf("could not unmarshall envelope") - } - - signedfile := pdir + "/signed.file" - err = signExistingPackage(e, ccpackfile, signedfile, cryptoProvider) - if err == nil { - t.Fatalf("expected signing a package that's not originally signed to fail") - } -} diff --git a/internal/peer/chaincode/testdata/connectionprofile-uneven.yaml b/internal/peer/chaincode/testdata/connectionprofile-uneven.yaml deleted file mode 100644 index e95e23d7926..00000000000 --- a/internal/peer/chaincode/testdata/connectionprofile-uneven.yaml +++ /dev/null @@ -1,184 +0,0 @@ -name: connection-profile-uneven-peers - -# -# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming -# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave -# them for the applications to process. This is a mechanism for different components of an application -# to exchange information that are not part of the standard schema described below. In particular, -# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to -# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with. -# -x-type: "hlfv1" -x-loggingLevel: info - -# -# Describe what the target network is/does. -# -description: "The network to be in if you want to stay in the global trade business" - -# -# Schema version of the content. Used by the SDK to apply the corresponding parsing rules. -# -version: 1.2.0 - -# -# [Optional]. But most apps would have this section so that channel objects can be constructed -# based on the content below. If an app is creating channels, then it likely will not need this -# section. -# -channels: - # name of the channel - mychannel: - # Required. list of orderers designated by the application to use for transactions on this - # channel. This list can be a result of access control ("org1" can only access "ordererA"), or - # operational decisions to share loads from applications among the orderers. The values must - # be "names" of orgs defined under "organizations/peers" - orderers: - - orderer.example.com - - # Required. list of peers from participating orgs - peers: - peer0.org1.example.com: - # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must - # have the chaincode installed. The app can also use this property to decide which peers - # to send the chaincode install request. Default: true - endorsingPeer: true - - # [Optional]. will this peer be sent query proposals? The peer must have the chaincode - # installed. The app can also use this property to decide which peers to send the - # chaincode install request. Default: true - chaincodeQuery: true - - # [Optional]. will this peer be sent query proposals that do not require chaincodes, like - # queryBlock(), queryTransaction(), etc. Default: true - ledgerQuery: true - - # [Optional]. will this peer be the target of the SDK's listener registration? All peers can - # produce events but the app typically only needs to connect to one to listen to events. - # Default: true - eventSource: true - - peer0.org2.example.com: - # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must - # have the chaincode installed. The app can also use this property to decide which peers - # to send the chaincode install request. Default: true - endorsingPeer: true - - # [Optional]. will this peer be sent query proposals? The peer must have the chaincode - # installed. The app can also use this property to decide which peers to send the - # chaincode install request. Default: true - chaincodeQuery: true - - # [Optional]. will this peer be sent query proposals that do not require chaincodes, like - # queryBlock(), queryTransaction(), etc. Default: true - ledgerQuery: true - - # [Optional]. will this peer be the target of the SDK's listener registration? All peers can - # produce events but the app typically only needs to connect to one to listen to events. - # Default: true - eventSource: true - -# -# list of participating organizations in this network -# -organizations: - org1: - mspid: Org1MSP - - # This org's MSP store (absolute path or relative to client.cryptoconfig) - cryptoPath: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp - - peers: - - peer0.org1.example.com - - # the profile will contain public information about organizations other than the one it belongs to. - # These are necessary information to make transaction lifecycles work, including MSP IDs and - # peers with a public URL to send transaction proposals. The file will not contain private - # information reserved for members of the organization, such as admin key and certificate, - # fabric-ca registrar enroll ID and secret, etc. - org2: - mspid: Org2MSP - - # This org's MSP store (absolute path or relative to client.cryptoconfig) - cryptoPath: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp - - peers: - - peer0.org2.example.com - - # Orderer Org name - ordererorg: - # Membership Service Provider ID for this organization - mspID: "OrdererOrg" - - # Needed to load users crypto keys and certs for this org (absolute path or relative to global crypto path, DEV mode) - cryptoPath: ordererOrganizations/example.com/users/Admin@example.com/msp - - -# -# List of orderers to send transaction and channel create/update requests to. For the time -# being only one orderer is needed. If more than one is defined, which one get used by the -# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. -# -orderers: - local.orderer.example.com: - url: orderer.example.com:7050 - - # these are standard properties defined by the gRPC library - # they will be passed in as-is to gRPC client constructor - grpcOptions: - ssl-target-name-override: orderer.example.com - # These parameters should be set in coordination with the keepalive policy on the server, - # as incompatible settings can result in closing of connection. - # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled - keep-alive-time: 0s - keep-alive-timeout: 20s - keep-alive-permit: false - fail-fast: false - # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs - allow-insecure: false - - tlsCACerts: - # Certificate location absolute path - path: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem - -# -# List of peers to send various requests to, including endorsement, query -# and event listener registration. -# -peers: - peer0.org1.example.com: - # this URL is used to send endorsement and query requests - url: peer0.org1.example.com:7051 - - grpcOptions: - ssl-target-name-override: peer0.org1.example.com - # These parameters should be set in coordination with the keepalive policy on the server, - # as incompatible settings can result in closing of connection. - # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled - keep-alive-time: 0s - keep-alive-timeout: 20s - keep-alive-permit: false - fail-fast: false - # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs - allow-insecure: false - - tlsCACerts: - # Certificate location absolute path - path: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem - - # peer0.org2.example.com: - # url: peer0.org2.example.com:7051 - # grpcOptions: - # ssl-target-name-override: peer0.org2.example.com - # # These parameters should be set in coordination with the keepalive policy on the server, - # # as incompatible settings can result in closing of connection. - # # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled - # keep-alive-time: 0s - # keep-alive-timeout: 20s - # keep-alive-permit: false - # fail-fast: false - # # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs - # allow-insecure: false - - # tlsCACerts: - # path: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem diff --git a/internal/peer/chaincode/testdata/connectionprofile.yaml b/internal/peer/chaincode/testdata/connectionprofile.yaml deleted file mode 100644 index 5ae74e952f8..00000000000 --- a/internal/peer/chaincode/testdata/connectionprofile.yaml +++ /dev/null @@ -1,184 +0,0 @@ -name: connection-profile - -# -# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming -# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave -# them for the applications to process. This is a mechanism for different components of an application -# to exchange information that are not part of the standard schema described below. In particular, -# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to -# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with. -# -x-type: "hlfv1" -x-loggingLevel: info - -# -# Describe what the target network is/does. -# -description: "The network to be in if you want to stay in the global trade business" - -# -# Schema version of the content. Used by the SDK to apply the corresponding parsing rules. -# -version: 1.2.0 - -# -# [Optional]. But most apps would have this section so that channel objects can be constructed -# based on the content below. If an app is creating channels, then it likely will not need this -# section. -# -channels: - # name of the channel - mychannel: - # Required. list of orderers designated by the application to use for transactions on this - # channel. This list can be a result of access control ("org1" can only access "ordererA"), or - # operational decisions to share loads from applications among the orderers. The values must - # be "names" of orgs defined under "organizations/peers" - orderers: - - orderer.example.com - - # Required. list of peers from participating orgs - peers: - peer0.org1.example.com: - # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must - # have the chaincode installed. The app can also use this property to decide which peers - # to send the chaincode install request. Default: true - endorsingPeer: true - - # [Optional]. will this peer be sent query proposals? The peer must have the chaincode - # installed. The app can also use this property to decide which peers to send the - # chaincode install request. Default: true - chaincodeQuery: true - - # [Optional]. will this peer be sent query proposals that do not require chaincodes, like - # queryBlock(), queryTransaction(), etc. Default: true - ledgerQuery: true - - # [Optional]. will this peer be the target of the SDK's listener registration? All peers can - # produce events but the app typically only needs to connect to one to listen to events. - # Default: true - eventSource: true - - peer0.org2.example.com: - # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must - # have the chaincode installed. The app can also use this property to decide which peers - # to send the chaincode install request. Default: true - endorsingPeer: true - - # [Optional]. will this peer be sent query proposals? The peer must have the chaincode - # installed. The app can also use this property to decide which peers to send the - # chaincode install request. Default: true - chaincodeQuery: true - - # [Optional]. will this peer be sent query proposals that do not require chaincodes, like - # queryBlock(), queryTransaction(), etc. Default: true - ledgerQuery: true - - # [Optional]. will this peer be the target of the SDK's listener registration? All peers can - # produce events but the app typically only needs to connect to one to listen to events. - # Default: true - eventSource: true - -# -# list of participating organizations in this network -# -organizations: - org1: - mspid: Org1MSP - - # This org's MSP store (absolute path or relative to client.cryptoconfig) - cryptoPath: peerOrganizations/org1.example.com/users/{username}@org1.example.com/msp - - peers: - - peer0.org1.example.com - - # the profile will contain public information about organizations other than the one it belongs to. - # These are necessary information to make transaction lifecycles work, including MSP IDs and - # peers with a public URL to send transaction proposals. The file will not contain private - # information reserved for members of the organization, such as admin key and certificate, - # fabric-ca registrar enroll ID and secret, etc. - org2: - mspid: Org2MSP - - # This org's MSP store (absolute path or relative to client.cryptoconfig) - cryptoPath: peerOrganizations/org2.example.com/users/{username}@org2.example.com/msp - - peers: - - peer0.org2.example.com - - # Orderer Org name - ordererorg: - # Membership Service Provider ID for this organization - mspID: "OrdererOrg" - - # Needed to load users crypto keys and certs for this org (absolute path or relative to global crypto path, DEV mode) - cryptoPath: ordererOrganizations/example.com/users/{username}@example.com/msp - - -# -# List of orderers to send transaction and channel create/update requests to. For the time -# being only one orderer is needed. If more than one is defined, which one get used by the -# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. -# -orderers: - local.orderer.example.com: - url: orderer.example.com:7050 - - # these are standard properties defined by the gRPC library - # they will be passed in as-is to gRPC client constructor - grpcOptions: - ssl-target-name-override: orderer.example.com - # These parameters should be set in coordination with the keepalive policy on the server, - # as incompatible settings can result in closing of connection. - # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled - keep-alive-time: 0s - keep-alive-timeout: 20s - keep-alive-permit: false - fail-fast: false - # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs - allow-insecure: false - - tlsCACerts: - # Certificate location absolute path - path: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem - -# -# List of peers to send various requests to, including endorsement, query -# and event listener registration. -# -peers: - peer0.org1.example.com: - # this URL is used to send endorsement and query requests - url: peer0.org1.example.com:7051 - - grpcOptions: - ssl-target-name-override: peer0.org1.example.com - # These parameters should be set in coordination with the keepalive policy on the server, - # as incompatible settings can result in closing of connection. - # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled - keep-alive-time: 0s - keep-alive-timeout: 20s - keep-alive-permit: false - fail-fast: false - # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs - allow-insecure: false - - tlsCACerts: - # Certificate location absolute path - path: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem - - peer0.org2.example.com: - url: peer0.org2.example.com:7051 - grpcOptions: - ssl-target-name-override: peer0.org2.example.com - # These parameters should be set in coordination with the keepalive policy on the server, - # as incompatible settings can result in closing of connection. - # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled - keep-alive-time: 0s - keep-alive-timeout: 20s - keep-alive-permit: false - fail-fast: false - # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs - allow-insecure: false - - tlsCACerts: - path: /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem diff --git a/internal/peer/chaincode/testdata/src/chaincodes/noop/chaincode.go b/internal/peer/chaincode/testdata/src/chaincodes/noop/chaincode.go deleted file mode 100644 index 71058bd41fa..00000000000 --- a/internal/peer/chaincode/testdata/src/chaincodes/noop/chaincode.go +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package main - -import ( - "fmt" - - "github.com/hyperledger/fabric-chaincode-go/shim" - pb "github.com/hyperledger/fabric-protos-go/peer" -) - -// No-op test chaincode -type TestChaincode struct{} - -func (t *TestChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { - return shim.Success(nil) -} - -func (t *TestChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { - return shim.Success(nil) -} - -func main() { - err := shim.Start(new(TestChaincode)) - if err != nil { - fmt.Printf("Error starting Simple chaincode: %s", err) - } -} diff --git a/internal/peer/chaincode/upgrade.go b/internal/peer/chaincode/upgrade.go deleted file mode 100644 index 04f99951f83..00000000000 --- a/internal/peer/chaincode/upgrade.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "context" - "errors" - "fmt" - - protcommon "github.com/hyperledger/fabric-protos-go/common" - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/protoutil" - "github.com/spf13/cobra" -) - -var chaincodeUpgradeCmd *cobra.Command - -const upgradeCmdName = "upgrade" - -// upgradeCmd returns the cobra command for Chaincode Upgrade -func upgradeCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { - chaincodeUpgradeCmd = &cobra.Command{ - Use: upgradeCmdName, - Short: "Upgrade chaincode.", - Long: "Upgrade an existing chaincode with the specified one. The new chaincode will immediately replace the existing chaincode upon the transaction committed.", - ValidArgs: []string{"1"}, - RunE: func(cmd *cobra.Command, args []string) error { - return chaincodeUpgrade(cmd, args, cf, cryptoProvider) - }, - } - flagList := []string{ - "lang", - "ctor", - "path", - "name", - "channelID", - "version", - "policy", - "escc", - "vscc", - "peerAddresses", - "tlsRootCertFiles", - "connectionProfile", - "collections-config", - } - attachFlags(chaincodeUpgradeCmd, flagList) - - return chaincodeUpgradeCmd -} - -// upgrade the command via Endorser -func upgrade(cmd *cobra.Command, cf *ChaincodeCmdFactory) (*protcommon.Envelope, error) { - spec, err := getChaincodeSpec(cmd) - if err != nil { - return nil, err - } - - cds, err := getChaincodeDeploymentSpec(spec, false) - if err != nil { - return nil, fmt.Errorf("error getting chaincode code %s: %s", chaincodeName, err) - } - - creator, err := cf.Signer.Serialize() - if err != nil { - return nil, fmt.Errorf("error serializing identity: %s", err) - } - - prop, _, err := protoutil.CreateUpgradeProposalFromCDS(channelID, cds, creator, policyMarshalled, []byte(escc), []byte(vscc), collectionConfigBytes) - if err != nil { - return nil, fmt.Errorf("error creating proposal %s: %s", chainFuncName, err) - } - logger.Debugf("Get upgrade proposal for chaincode <%v>", spec.ChaincodeId) - - var signedProp *pb.SignedProposal - signedProp, err = protoutil.GetSignedProposal(prop, cf.Signer) - if err != nil { - return nil, fmt.Errorf("error creating signed proposal %s: %s", chainFuncName, err) - } - - // upgrade is currently only supported for one peer - proposalResponse, err := cf.EndorserClients[0].ProcessProposal(context.Background(), signedProp) - if err != nil { - return nil, fmt.Errorf("error endorsing %s: %s", chainFuncName, err) - } - - if proposalResponse != nil { - logger.Debugf("endorse upgrade proposal, get response <%v>", proposalResponse.Response) - // assemble a signed transaction (it's an Envelope message) - env, err := protoutil.CreateSignedTx(prop, cf.Signer, proposalResponse) - if err != nil { - return nil, fmt.Errorf("could not assemble transaction, err %s", err) - } - logger.Debug("Get Signed envelope") - return env, nil - } - - return nil, nil -} - -// chaincodeUpgrade upgrades the chaincode. On success, the new chaincode -// version is printed to STDOUT -func chaincodeUpgrade(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { - if channelID == "" { - return errors.New("The required parameter 'channelID' is empty. Rerun the command with -C flag") - } - // Parsing of the command line is done so silence cmd usage - cmd.SilenceUsage = true - - var err error - if cf == nil { - cf, err = InitCmdFactory(cmd.Name(), true, true, cryptoProvider) - if err != nil { - return err - } - } - defer cf.BroadcastClient.Close() - - env, err := upgrade(cmd, cf) - if err != nil { - return err - } - - if env != nil { - logger.Debug("Send signed envelope to orderer") - err = cf.BroadcastClient.Send(env) - return err - } - - return nil -} diff --git a/internal/peer/chaincode/upgrade_test.go b/internal/peer/chaincode/upgrade_test.go deleted file mode 100644 index bedc0855a9a..00000000000 --- a/internal/peer/chaincode/upgrade_test.go +++ /dev/null @@ -1,171 +0,0 @@ -/* -Copyright Digital Asset Holdings, LLC. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package chaincode - -import ( - "errors" - "fmt" - "testing" - "time" - - pb "github.com/hyperledger/fabric-protos-go/peer" - "github.com/hyperledger/fabric/bccsp/sw" - "github.com/hyperledger/fabric/internal/peer/common" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" -) - -func TestUpgradeCmd(t *testing.T) { - signer, err := common.GetDefaultSigner() - if err != nil { - t.Fatalf("Get default signer error: %v", err) - } - - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 200}, - Endorsement: &pb.Endorsement{}, - } - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil)} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - } - - // reset channelID, it might have been set by previous test - channelID = "" - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - cmd := upgradeCmd(mockCF, cryptoProvider) - addFlags(cmd) - - args := []string{ - "-n", "mychaincode", "-p", "mychaincodepath", - "-v", "anotherversion", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}", - } - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "'peer chaincode upgrade' command should have failed without -C flag") - - args = []string{ - "-C", "mychannel", "-n", "mychaincode", "-p", "mychaincodepath", - "-v", "anotherversion", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}", - } - cmd.SetArgs(args) - err = cmd.Execute() - require.NoError(t, err, "'peer chaincode upgrade' command failed") -} - -func TestUpgradeCmdEndorseFail(t *testing.T) { - signer, err := common.GetDefaultSigner() - if err != nil { - t.Fatalf("Get default signer error: %v", err) - } - - errCode := int32(500) - errMsg := "upgrade error" - mockResponse := &pb.ProposalResponse{Response: &pb.Response{Status: errCode, Message: errMsg}} - - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil)} - mockBroadcastClient := common.GetMockBroadcastClient(nil) - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - } - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - cmd := upgradeCmd(mockCF, cryptoProvider) - addFlags(cmd) - - args := []string{ - "-C", "mychannel", "-n", "mychaincode", "-p", "mychaincodepath", - "-v", "anotherversion", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}", - } - cmd.SetArgs(args) - - expectErrMsg := fmt.Sprintf("could not assemble transaction, err proposal response was not successful, error code %d, msg %s", errCode, errMsg) - if err := cmd.Execute(); err == nil { - t.Errorf("Run chaincode upgrade cmd error:%v", err) - } else { - if err.Error() != expectErrMsg { - t.Errorf("Run chaincode upgrade cmd get unexpected error: %s", err.Error()) - } - } -} - -func TestUpgradeCmdSendTXFail(t *testing.T) { - signer, err := common.GetDefaultSigner() - if err != nil { - t.Fatalf("Get default signer error: %v", err) - } - - mockResponse := &pb.ProposalResponse{ - Response: &pb.Response{Status: 200}, - Endorsement: &pb.Endorsement{}, - } - mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil)} - sendErr := errors.New("send tx failed") - mockBroadcastClient := common.GetMockBroadcastClient(sendErr) - mockCF := &ChaincodeCmdFactory{ - EndorserClients: mockEndorserClients, - Signer: signer, - BroadcastClient: mockBroadcastClient, - } - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - cmd := upgradeCmd(mockCF, cryptoProvider) - addFlags(cmd) - - args := []string{"-C", "mychannel", "-n", "mychaincode", "-p", "mychaincodepath", "-v", "anotherversion", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}"} - cmd.SetArgs(args) - - expectErrMsg := sendErr.Error() - if err := cmd.Execute(); err == nil { - t.Errorf("Run chaincode upgrade cmd error:%v", err) - } else { - if err.Error() != expectErrMsg { - t.Errorf("Run chaincode upgrade cmd get unexpected error: %s", err.Error()) - } - } -} - -func TestUpgradeCmdWithNilCF(t *testing.T) { - defer viper.Reset() - defer resetFlags() - - // set timeout for failure cases - viper.Set("peer.client.connTimeout", 10*time.Millisecond) - - // trap possible SIGSEV panic - defer func() { - var err error - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - } - require.NoError(t, err, "'peer chaincode upgrade' command should have failed without a panic") - }() - - channelID = "" - - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) - cmd := upgradeCmd(nil, cryptoProvider) - addFlags(cmd) - - args := []string{ - "-C", "mychannel", "-n", "mychaincode", "-p", "mychaincodepath", - "-v", "anotherversion", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}", - } - cmd.SetArgs(args) - err = cmd.Execute() - require.Error(t, err, "'peer chaincode upgrade' command should have failed without a panic") -} diff --git a/internal/peer/lifecycle/chaincode/approveformyorg.go b/internal/peer/lifecycle/chaincode/approveformyorg.go index db312019e7f..290511dee36 100644 --- a/internal/peer/lifecycle/chaincode/approveformyorg.go +++ b/internal/peer/lifecycle/chaincode/approveformyorg.go @@ -16,7 +16,6 @@ import ( pb "github.com/hyperledger/fabric-protos-go/peer" lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle" "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/internal/peer/chaincode" "github.com/hyperledger/fabric/internal/peer/common" "github.com/hyperledger/fabric/protoutil" "github.com/pkg/errors" @@ -206,14 +205,14 @@ func (a *ApproverForMyOrg) Approve() error { if err != nil { return errors.WithMessage(err, "failed to create signed transaction") } - var dg *chaincode.DeliverGroup + var dg *DeliverGroup var ctx context.Context if a.Input.WaitForEvent { var cancelFunc context.CancelFunc ctx, cancelFunc = context.WithTimeout(context.Background(), a.Input.WaitForEventTimeout) defer cancelFunc() - dg = chaincode.NewDeliverGroup( + dg = NewDeliverGroup( a.DeliverClients, a.Input.PeerAddresses, a.Signer, diff --git a/internal/peer/lifecycle/chaincode/commit.go b/internal/peer/lifecycle/chaincode/commit.go index bc0be67a8af..61f381a4e75 100644 --- a/internal/peer/lifecycle/chaincode/commit.go +++ b/internal/peer/lifecycle/chaincode/commit.go @@ -16,7 +16,6 @@ import ( pb "github.com/hyperledger/fabric-protos-go/peer" lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle" "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/internal/peer/chaincode" "github.com/hyperledger/fabric/internal/peer/common" "github.com/hyperledger/fabric/protoutil" "github.com/pkg/errors" @@ -205,14 +204,14 @@ func (c *Committer) Commit() error { return errors.WithMessage(err, "failed to create signed transaction") } - var dg *chaincode.DeliverGroup + var dg *DeliverGroup var ctx context.Context if c.Input.WaitForEvent { var cancelFunc context.CancelFunc ctx, cancelFunc = context.WithTimeout(context.Background(), c.Input.WaitForEventTimeout) defer cancelFunc() - dg = chaincode.NewDeliverGroup( + dg = NewDeliverGroup( c.DeliverClients, c.Input.PeerAddresses, c.Signer, diff --git a/internal/peer/lifecycle/chaincode/common.go b/internal/peer/lifecycle/chaincode/common.go index 1773e5bf104..369da56017a 100644 --- a/internal/peer/lifecycle/chaincode/common.go +++ b/internal/peer/lifecycle/chaincode/common.go @@ -8,19 +8,260 @@ package chaincode import ( "context" + "crypto/tls" "encoding/json" "fmt" "io" + "math" + "os" + "sync" "github.com/golang/protobuf/proto" + pcommon "github.com/hyperledger/fabric-protos-go/common" + ab "github.com/hyperledger/fabric-protos-go/orderer" pb "github.com/hyperledger/fabric-protos-go/peer" "github.com/hyperledger/fabric/common/policydsl" - "github.com/hyperledger/fabric/internal/peer/chaincode" + "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/internal/pkg/identity" "github.com/hyperledger/fabric/protoutil" "github.com/pkg/errors" + "github.com/spf13/viper" "google.golang.org/grpc" ) +// DeliverGroup holds all of the information needed to connect +// to a set of peers to wait for the interested txid to be +// committed to the ledgers of all peers. This functionality +// is currently implemented via the peer's DeliverFiltered service. +// An error from any of the peers/deliver clients will result in +// the invoke command returning an error. Only the first error that +// occurs will be set +type DeliverGroup struct { + Clients []*DeliverClient + Certificate tls.Certificate + ChannelID string + TxID string + Signer identity.SignerSerializer + mutex sync.Mutex + Error error + wg sync.WaitGroup +} + +// DeliverClient holds the client/connection related to a specific +// peer. The address is included for logging purposes +type DeliverClient struct { + Client pb.DeliverClient + Connection pb.Deliver_DeliverClient + Address string +} + +func NewDeliverGroup( + deliverClients []pb.DeliverClient, + peerAddresses []string, + signer identity.SignerSerializer, + certificate tls.Certificate, + channelID string, + txid string, +) *DeliverGroup { + clients := make([]*DeliverClient, len(deliverClients)) + for i, client := range deliverClients { + address := peerAddresses[i] + if address == "" { + address = viper.GetString("peer.address") + } + dc := &DeliverClient{ + Client: client, + Address: address, + } + clients[i] = dc + } + + dg := &DeliverGroup{ + Clients: clients, + Certificate: certificate, + ChannelID: channelID, + TxID: txid, + Signer: signer, + } + + return dg +} + +// Connect waits for all deliver clients in the group to connect to +// the peer's deliver service, receive an error, or for the context +// to timeout. An error will be returned whenever even a single +// deliver client fails to connect to its peer +func (dg *DeliverGroup) Connect(ctx context.Context) error { + dg.wg.Add(len(dg.Clients)) + for _, client := range dg.Clients { + go dg.ClientConnect(ctx, client) + } + readyCh := make(chan struct{}) + go dg.WaitForWG(readyCh) + + select { + case <-readyCh: + if dg.Error != nil { + err := errors.WithMessage(dg.Error, "failed to connect to deliver on all peers") + return err + } + case <-ctx.Done(): + err := errors.New("timed out waiting for connection to deliver on all peers") + return err + } + + return nil +} + +// ClientConnect sends a deliver seek info envelope using the +// provided deliver client, setting the deliverGroup's Error +// field upon any error +func (dg *DeliverGroup) ClientConnect(ctx context.Context, dc *DeliverClient) { + defer dg.wg.Done() + df, err := dc.Client.DeliverFiltered(ctx) + if err != nil { + err = errors.WithMessagef(err, "error connecting to deliver filtered at %s", dc.Address) + dg.setError(err) + return + } + defer df.CloseSend() + dc.Connection = df + + envelope := createDeliverEnvelope(dg.ChannelID, dg.Certificate, dg.Signer) + err = df.Send(envelope) + if err != nil { + err = errors.WithMessagef(err, "error sending deliver seek info envelope to %s", dc.Address) + dg.setError(err) + return + } +} + +// Wait waits for all deliver client connections in the group to +// either receive a block with the txid, an error, or for the +// context to timeout +func (dg *DeliverGroup) Wait(ctx context.Context) error { + if len(dg.Clients) == 0 { + return nil + } + + dg.wg.Add(len(dg.Clients)) + for _, client := range dg.Clients { + go dg.ClientWait(client) + } + readyCh := make(chan struct{}) + go dg.WaitForWG(readyCh) + + select { + case <-readyCh: + if dg.Error != nil { + return dg.Error + } + case <-ctx.Done(): + err := errors.New("timed out waiting for txid on all peers") + return err + } + + return nil +} + +// ClientWait waits for the specified deliver client to receive +// a block event with the requested txid +func (dg *DeliverGroup) ClientWait(dc *DeliverClient) { + defer dg.wg.Done() + for { + resp, err := dc.Connection.Recv() + if err != nil { + err = errors.WithMessagef(err, "error receiving from deliver filtered at %s", dc.Address) + dg.setError(err) + return + } + switch r := resp.Type.(type) { + case *pb.DeliverResponse_FilteredBlock: + filteredTransactions := r.FilteredBlock.FilteredTransactions + for _, tx := range filteredTransactions { + if tx.Txid == dg.TxID { + logger.Infof("txid [%s] committed with status (%s) at %s", dg.TxID, tx.TxValidationCode, dc.Address) + if tx.TxValidationCode != pb.TxValidationCode_VALID { + err = errors.Errorf("transaction invalidated with status (%s)", tx.TxValidationCode) + dg.setError(err) + } + return + } + } + case *pb.DeliverResponse_Status: + err = errors.Errorf("deliver completed with status (%s) before txid received", r.Status) + dg.setError(err) + return + default: + err = errors.Errorf("received unexpected response type (%T) from %s", r, dc.Address) + dg.setError(err) + return + } + } +} + +// WaitForWG waits for the deliverGroup's wait group and closes +// the channel when ready +func (dg *DeliverGroup) WaitForWG(readyCh chan struct{}) { + dg.wg.Wait() + close(readyCh) +} + +// setError serializes an error for the deliverGroup +func (dg *DeliverGroup) setError(err error) { + dg.mutex.Lock() + dg.Error = err + dg.mutex.Unlock() +} + +func createDeliverEnvelope( + channelID string, + certificate tls.Certificate, + signer identity.SignerSerializer, +) *pcommon.Envelope { + var tlsCertHash []byte + // check for client certificate and create hash if present + if len(certificate.Certificate) > 0 { + tlsCertHash = util.ComputeSHA256(certificate.Certificate[0]) + } + + start := &ab.SeekPosition{ + Type: &ab.SeekPosition_Newest{ + Newest: &ab.SeekNewest{}, + }, + } + + stop := &ab.SeekPosition{ + Type: &ab.SeekPosition_Specified{ + Specified: &ab.SeekSpecified{ + Number: math.MaxUint64, + }, + }, + } + + seekInfo := &ab.SeekInfo{ + Start: start, + Stop: stop, + Behavior: ab.SeekInfo_BLOCK_UNTIL_READY, + } + + env, err := protoutil.CreateSignedEnvelopeWithTLSBinding( + pcommon.HeaderType_DELIVER_SEEK_INFO, + channelID, + signer, + seekInfo, + int32(0), + uint64(0), + tlsCertHash, + ) + if err != nil { + logger.Errorf("Error signing envelope: %s", err) + return nil + } + + return env +} + // EndorserClient defines the interface for sending a proposal // to an endorser type EndorserClient interface { @@ -111,7 +352,7 @@ func createCollectionConfigPackage(collectionsConfigFile string) (*pb.Collection var ccp *pb.CollectionConfigPackage if collectionsConfigFile != "" { var err error - ccp, _, err = chaincode.GetCollectionConfigFromFile(collectionsConfigFile) + ccp, _, err = GetCollectionConfigFromFile(collectionsConfigFile) if err != nil { return nil, errors.WithMessagef(err, "invalid collection configuration in file %s", collectionsConfigFile) } @@ -119,6 +360,136 @@ func createCollectionConfigPackage(collectionsConfigFile string) (*pb.Collection return ccp, nil } +type endorsementPolicy struct { + ChannelConfigPolicy string `json:"channelConfigPolicy,omitempty"` + SignaturePolicy string `json:"signaturePolicy,omitempty"` +} + +type collectionConfigJson struct { + Name string `json:"name"` + Policy string `json:"policy"` + RequiredPeerCount *int32 `json:"requiredPeerCount"` + MaxPeerCount *int32 `json:"maxPeerCount"` + BlockToLive uint64 `json:"blockToLive"` + MemberOnlyRead bool `json:"memberOnlyRead"` + MemberOnlyWrite bool `json:"memberOnlyWrite"` + EndorsementPolicy *endorsementPolicy `json:"endorsementPolicy,omitempty"` +} + +// GetCollectionConfigFromFile retrieves the collection configuration +// from the supplied file; the supplied file must contain a +// json-formatted array of collectionConfigJson elements +func GetCollectionConfigFromFile(ccFile string) (*pb.CollectionConfigPackage, []byte, error) { + fileBytes, err := os.ReadFile(ccFile) + if err != nil { + return nil, nil, errors.Wrapf(err, "could not read file '%s'", ccFile) + } + + return getCollectionConfigFromBytes(fileBytes) +} + +// getCollectionConfig retrieves the collection configuration +// from the supplied byte array; the byte array must contain a +// json-formatted array of collectionConfigJson elements +func getCollectionConfigFromBytes(cconfBytes []byte) (*pb.CollectionConfigPackage, []byte, error) { + cconf := &[]collectionConfigJson{} + err := json.Unmarshal(cconfBytes, cconf) + if err != nil { + return nil, nil, errors.Wrap(err, "could not parse the collection configuration") + } + + ccarray := make([]*pb.CollectionConfig, 0, len(*cconf)) + for _, cconfitem := range *cconf { + p, err := policydsl.FromString(cconfitem.Policy) + if err != nil { + return nil, nil, errors.WithMessagef(err, "invalid policy %s", cconfitem.Policy) + } + + cpc := &pb.CollectionPolicyConfig{ + Payload: &pb.CollectionPolicyConfig_SignaturePolicy{ + SignaturePolicy: p, + }, + } + + var ep *pb.ApplicationPolicy + if cconfitem.EndorsementPolicy != nil { + signaturePolicy := cconfitem.EndorsementPolicy.SignaturePolicy + channelConfigPolicy := cconfitem.EndorsementPolicy.ChannelConfigPolicy + ep, err = getApplicationPolicy(signaturePolicy, channelConfigPolicy) + if err != nil { + return nil, nil, errors.WithMessagef(err, "invalid endorsement policy [%#v]", cconfitem.EndorsementPolicy) + } + } + + // Set default requiredPeerCount and MaxPeerCount if not specified in json + requiredPeerCount := int32(0) + maxPeerCount := int32(1) + if cconfitem.RequiredPeerCount != nil { + requiredPeerCount = *cconfitem.RequiredPeerCount + } + if cconfitem.MaxPeerCount != nil { + maxPeerCount = *cconfitem.MaxPeerCount + } + + cc := &pb.CollectionConfig{ + Payload: &pb.CollectionConfig_StaticCollectionConfig{ + StaticCollectionConfig: &pb.StaticCollectionConfig{ + Name: cconfitem.Name, + MemberOrgsPolicy: cpc, + RequiredPeerCount: requiredPeerCount, + MaximumPeerCount: maxPeerCount, + BlockToLive: cconfitem.BlockToLive, + MemberOnlyRead: cconfitem.MemberOnlyRead, + MemberOnlyWrite: cconfitem.MemberOnlyWrite, + EndorsementPolicy: ep, + }, + }, + } + + ccarray = append(ccarray, cc) + } + + ccp := &pb.CollectionConfigPackage{Config: ccarray} + ccpBytes, err := proto.Marshal(ccp) + return ccp, ccpBytes, err +} + +func getApplicationPolicy(signaturePolicy, channelConfigPolicy string) (*pb.ApplicationPolicy, error) { + if signaturePolicy == "" && channelConfigPolicy == "" { + // no policy, no problem + return nil, nil + } + + if signaturePolicy != "" && channelConfigPolicy != "" { + // mo policies, mo problems + return nil, errors.New(`cannot specify both "--signature-policy" and "--channel-config-policy"`) + } + + var applicationPolicy *pb.ApplicationPolicy + if signaturePolicy != "" { + signaturePolicyEnvelope, err := policydsl.FromString(signaturePolicy) + if err != nil { + return nil, errors.Errorf("invalid signature policy: %s", signaturePolicy) + } + + applicationPolicy = &pb.ApplicationPolicy{ + Type: &pb.ApplicationPolicy_SignaturePolicy{ + SignaturePolicy: signaturePolicyEnvelope, + }, + } + } + + if channelConfigPolicy != "" { + applicationPolicy = &pb.ApplicationPolicy{ + Type: &pb.ApplicationPolicy_ChannelConfigPolicyReference{ + ChannelConfigPolicyReference: channelConfigPolicy, + }, + } + } + + return applicationPolicy, nil +} + func printResponseAsJSON(proposalResponse *pb.ProposalResponse, msg proto.Message, out io.Writer) error { err := proto.Unmarshal(proposalResponse.Response.Payload, msg) if err != nil { diff --git a/scripts/help_docs.sh b/scripts/help_docs.sh index 169c3be495b..587dfa9ff4d 100755 --- a/scripts/help_docs.sh +++ b/scripts/help_docs.sh @@ -78,13 +78,6 @@ generateOrCheck \ docs/wrappers/license_postscript.md \ "${commands[@]}" -commands=("peer chaincode install" "peer chaincode instantiate" "peer chaincode invoke" "peer chaincode list" "peer chaincode package" "peer chaincode query" "peer chaincode signpackage" "peer chaincode upgrade") -generateOrCheck \ - docs/source/commands/peerchaincode.md \ - docs/wrappers/peer_chaincode_preamble.md \ - docs/wrappers/peer_chaincode_postscript.md \ - "${commands[@]}" - commands=("peer lifecycle" "peer lifecycle chaincode" "peer lifecycle chaincode package" "peer lifecycle chaincode install" "peer lifecycle chaincode queryinstalled" "peer lifecycle chaincode getinstalledpackage" "peer lifecycle chaincode calculatepackageid" "peer lifecycle chaincode approveformyorg" "peer lifecycle chaincode queryapproved" "peer lifecycle chaincode checkcommitreadiness" "peer lifecycle chaincode commit" "peer lifecycle chaincode querycommitted") generateOrCheck \ docs/source/commands/peerlifecycle.md \