mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
Address some PR review feedback points - README reorg
Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>
This commit is contained in:
parent
81748831e7
commit
f7a2eb38f8
6 changed files with 179 additions and 224 deletions
|
|
@ -1,160 +1,12 @@
|
|||
|
||||
## Basic asset transfer
|
||||
## Basic Asset Transfer
|
||||
|
||||
This project demonstrates the use of the Java SDK, running a basic asset transfer contract using the "chaincode as a service"
|
||||
pattern.
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
In this sample we will employ the [Kubernetes Test Network](../../test-network-k8s) to illustrate a scenario of
|
||||
building, running, and debugging chaincode on a development workstation.
|
||||
|
||||
This project is also compatible with the legacy chaincode builder pipeline and the compose based test-network.
|
||||
For additional details, see the [End-to-end with the test-network](../../test-network/CHAINCODE_AS_A_SERVICE_TUTORIAL.md#end-to-end-with-the-the-test-network)
|
||||
documentation.
|
||||
|
||||
## [Quickstart](../../test-network-k8s#quickstart)
|
||||
|
||||
```
|
||||
export PATH=${PWD}/../../test-network-k8s:$PATH
|
||||
|
||||
network kind
|
||||
```
|
||||
```
|
||||
network up
|
||||
network channel create
|
||||
```
|
||||
```
|
||||
network chaincode deploy asset-transfer-basic basic_1.0 ${PWD}
|
||||
```
|
||||
```
|
||||
network chaincode metadata asset-transfer-basic
|
||||
network chaincode invoke asset-transfer-basic '{"Args":["InitLedger"]}'
|
||||
network chaincode query asset-transfer-basic '{"Args":["ReadAsset","asset1"]}' | jq
|
||||
```
|
||||
|
||||
## Detailed Guide
|
||||
|
||||
```shell
|
||||
network down
|
||||
network up
|
||||
network channel create
|
||||
```
|
||||
|
||||
```shell
|
||||
# Build the chaincode docker image
|
||||
docker build -t fabric-samples/asset-transfer-basic/chaincode-java .
|
||||
|
||||
# Load the docker image directly to the KIND control plane.
|
||||
# (Alternately, build/tag/push the image to a remote container registry, e.g. localhost:5000)
|
||||
kind load docker-image fabric-samples/asset-transfer-basic/chaincode-java
|
||||
```
|
||||
|
||||
```shell
|
||||
# Assemble the chaincode package archive
|
||||
network chaincode package basic_1.0 asset-transfer-basic $PWD/build/asset-transfer.tgz
|
||||
|
||||
# Determine the ID for the chaincode package
|
||||
CORE_CHAINCODE_ID_NAME=$(network chaincode id $PWD/build/asset-transfer.tgz)
|
||||
|
||||
# Launch the chaincode in k8s as Deployment + Service
|
||||
network chaincode launch asset-transfer-basic $CORE_CHAINCODE_ID_NAME fabric-samples/asset-transfer-basic/chaincode-java
|
||||
|
||||
# Complete the chaincode lifecycle
|
||||
network chaincode install $PWD/build/asset-transfer.tgz
|
||||
network chaincode approve asset-transfer-basic $CORE_CHAINCODE_ID_NAME
|
||||
network chaincode commit asset-transfer-basic
|
||||
```
|
||||
|
||||
```shell
|
||||
# execute the smart contract by name
|
||||
network chaincode metadata asset-transfer-basic
|
||||
network chaincode invoke asset-transfer-basic '{"Args":["InitLedger"]}'
|
||||
network chaincode query asset-transfer-basic '{"Args":["ReadAsset","asset1"]}'
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl -n test-network logs -f deployment/org1peer1-ccaas-asset-transfer-basic
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Build
|
||||
|
||||
```shell
|
||||
./gradlew shadowJar
|
||||
```
|
||||
or
|
||||
```shell
|
||||
docker build -t fabric-samples/asset-transfer-basic/chaincode-java .
|
||||
```
|
||||
|
||||
|
||||
### Package
|
||||
|
||||
By instructing the peer to connect to chaincode at the Docker host alias `host.docker.internal`, pods running in
|
||||
Kubernetes will access the local process via a special loopback interface established by KIND.
|
||||
|
||||
Set the "address" attribute in the package connection.json descriptor and assemble the chaincode package:
|
||||
```shell
|
||||
export TEST_NETWORK_CHAINCODE_ADDRESS=host.docker.internal:9999
|
||||
|
||||
network cc package basic_1.0 asset-transfer-debug $PWD/build/asset-transfer-debug.tgz
|
||||
```
|
||||
|
||||
### Launch
|
||||
|
||||
When chaincode is launched locally, it must declare the package ID in the environment as if the process had been managed
|
||||
by the peer's chaincode lifecycle manager. Calculate the package ID and start the chaincode, binding to port 9999
|
||||
on the local system:
|
||||
|
||||
```shell
|
||||
export CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999
|
||||
export CORE_CHAINCODE_ID_NAME=$(network chaincode id $PWD/build/asset-transfer-debug.tgz)
|
||||
|
||||
java -jar build/libs/chaincode.jar
|
||||
```
|
||||
|
||||
Or using the editor/debugger/IDE of your choice, create a launch target for `ContractMain.main()`, specifying the
|
||||
environment as above.
|
||||
|
||||
Or launch the chaincode in a Docker container, binding to port 9999 on the host system:
|
||||
|
||||
```shell
|
||||
docker run \
|
||||
--rm \
|
||||
--name basic_1.0 \
|
||||
-p 9999:9999 \
|
||||
-e CHAINCODE_SERVER_ADDRESS \
|
||||
-e CORE_CHAINCODE_ID_NAME \
|
||||
fabric-samples/asset-transfer-basic/chaincode-java
|
||||
```
|
||||
|
||||
### Approve, Invoke, and Query
|
||||
|
||||
After the contract main has launched, install, approve, commit, and invoke the chaincode:
|
||||
|
||||
```shell
|
||||
# Complete the chaincode lifecycle
|
||||
network cc activate asset-transfer-debug $PWD/build/asset-transfer-debug.tgz
|
||||
```
|
||||
|
||||
```shell
|
||||
# execute the smart contract by name
|
||||
network cc metadata asset-transfer-debug
|
||||
network cc invoke asset-transfer-debug '{"Args":["InitLedger"]}'
|
||||
network cc query asset-transfer-debug '{"Args":["ReadAsset","asset1"]}'
|
||||
```
|
||||
|
||||
## Tear Down
|
||||
|
||||
```shell
|
||||
network down
|
||||
```
|
||||
or
|
||||
```shell
|
||||
network unkind
|
||||
```
|
||||
This sample implements the basic asset transfer scenario, illustrating the use of the Java Contract SDKs to provide a
|
||||
smart contract as a service.
|
||||
|
||||
To run this chaincode contract locally on a development network, see:
|
||||
|
||||
- [Debugging chaincode as a service](../../test-network-k8s/docs/CHAINCODE_AS_A_SERVICE.md) (Kube test network)
|
||||
- [End-to-end with the test-network](../../test-network/CHAINCODE_AS_A_SERVICE_TUTORIAL.md#end-to-end-with-the-the-test-network) (Docker compose)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ repositories {
|
|||
}
|
||||
|
||||
application {
|
||||
mainClass = 'org.hyperledger.fabric.contract.ContractRouter'
|
||||
mainClass = 'org.hyperledger.fabric.samples.assettransfer.ContractMain'
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
|
|
|
|||
|
|
@ -200,73 +200,11 @@ docker push $TEST_NETWORK_CHAINCODE_IMAGE
|
|||
|
||||
One of the most compelling features of Fabric's _Chaincode-as-a-Service_ pattern is that when the peer connects to a
|
||||
chaincode URL, it can connect back to a port on the local host. Instead of connecting to a pod running in a
|
||||
container within Kubernetes, we can simply connect to a native binary running in a debugger, an IDE, or docker image
|
||||
running locally!
|
||||
container within Kubernetes, the chaincode process can be launched locally as a native binary in a debugger, an IDE,
|
||||
or a docker image bound to the host network.
|
||||
|
||||
Using a singular framework, we can employ this method to enable _rapid_ **edit/test/debug cycles** when authoring
|
||||
code, **verify** docker images generated by a CI/CD pipeline, and run integration tests on a local Kubernetes.
|
||||
|
||||
For example, we can deploy the basic asset transfer smart contract with a [connection.json](../chaincode/asset-transfer-basic-debug/connection.json)
|
||||
referencing a service bound to the Docker network's IP address for the local host:
|
||||
```json
|
||||
{
|
||||
"address": "host.docker.internal:9999",
|
||||
}
|
||||
```
|
||||
When the test network opens a TCP socket to the chaincode process, the connection will be made from containers
|
||||
running within Kubernetes to the port opened on the local system. Let's employ this to technique by running a
|
||||
chaincode endpoint in a local Docker container, native binary, or IDE debugger:
|
||||
|
||||
|
||||
0. Edit assetTransfer.go and [Build the Chaincode Image](#build-a-chaincode-docker-image)
|
||||
|
||||
|
||||
1. Bring up the test network with:
|
||||
```shell
|
||||
$ ./network up
|
||||
$ ./network channel create
|
||||
```
|
||||
|
||||
2. Install the debug chaincode archive, using a connection to localhost:9999 :
|
||||
```shell
|
||||
$ export TEST_NETWORK_CHAINCODE_NAME=asset-transfer-basic-debug
|
||||
$ export TEST_NETWORK_CHAINCODE_IMAGE=localhost:5000/asset-transfer-basic
|
||||
|
||||
$ ./network chaincode install
|
||||
Installing chaincode "asset-transfer-basic-debug":
|
||||
✅ - Packaging chaincode folder chaincode/asset-transfer-basic-debug ...
|
||||
✅ - Transferring chaincode archive to org1 ...
|
||||
✅ - Installing chaincode for org org1 ...
|
||||
🏁 - Chaincode is installed with CHAINCODE_ID=basic_1.0:159ed2f227586f40c5804e157919903fda2b861488f35eefb365eb9d85a73da3
|
||||
```
|
||||
|
||||
3. Set the `CHAINCODE_ID` and launch the chaincode binding to localhost:9999:
|
||||
```shell
|
||||
$ export CHAINCODE_ID=basic_1.0:159ed2f227586f40c5804e157919903fda2b861488f35eefb365eb9d85a73da3
|
||||
|
||||
$ docker run \
|
||||
--rm \
|
||||
--name asset-transfer-basic-debug \
|
||||
-e CHAINCODE_ID \
|
||||
-e CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999 \
|
||||
-p 9999:9999 \
|
||||
localhost:5000/asset-transfer-basic
|
||||
```
|
||||
|
||||
4. Activate the chaincode (commit and approve on the peer):
|
||||
```shell
|
||||
$ ./network chaincode activate
|
||||
```
|
||||
|
||||
When the peer communicates with chaincode in this fashion, the network will reach out to the grpc server
|
||||
bound to the localhost:9999, rather than connecting to services locked up behind the wall of Kubernetes
|
||||
networking.
|
||||
|
||||
As an exercise, try using this approach to:
|
||||
|
||||
- introduce some `fmt.Printf` logging output to the chaincode, attaching to a process running locally in an IDE / debugger.
|
||||
- build your local modifications into a docker container, publishing locally to localhost:5000/asset-transfer-basic
|
||||
- test your local modifications by running a chaincode referencing the image hosted in the local container registry.
|
||||
For additional details, see the [debugging chaincode](CHAINCODE_AS_A_SERVICE.md) guide for running the basic asset
|
||||
transfer chaincode in an interactive development workflow.
|
||||
|
||||
|
||||
## Next Steps:
|
||||
|
|
|
|||
161
test-network-k8s/docs/CHAINCODE_AS_A_SERVICE.md
Normal file
161
test-network-k8s/docs/CHAINCODE_AS_A_SERVICE.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
# Debugging Chaincode
|
||||
|
||||
In this sample we will employ the [Kubernetes Test Network](../README.md) to illustrate a scenario of
|
||||
building, running, and debugging chaincode on a development workstation.
|
||||
|
||||
While this guide targets the Java [asset-transfer-basic](../../asset-transfer-basic/chaincode-java) sample, the approach
|
||||
may be applied to any sample and chaincode implementation language.
|
||||
|
||||
When debugging chaincode as a service, the chaincode process is launched on the local system, binding to a port
|
||||
on the host's network interface. In this mode the developer has complete flexibility in determining how and where the
|
||||
process runs - it can be launched as a native binary from a CLI, attached to an active debugging session from an IDE,
|
||||
as a Docker container, or even behind a reverse network proxy for diagnosing issues in a remote / cloud-based Fabric
|
||||
network.
|
||||
|
||||
|
||||
## TL/DR
|
||||
|
||||
```
|
||||
export PATH=${PWD}/test-network-k8s:$PATH
|
||||
|
||||
cd asset-transfer-basic/chaincode-java
|
||||
|
||||
network kind
|
||||
```
|
||||
```
|
||||
network up
|
||||
network channel create
|
||||
```
|
||||
```
|
||||
network chaincode deploy asset-transfer-basic basic_1.0 ${PWD}
|
||||
```
|
||||
```
|
||||
network chaincode metadata asset-transfer-basic
|
||||
network chaincode invoke asset-transfer-basic '{"Args":["InitLedger"]}'
|
||||
network chaincode query asset-transfer-basic '{"Args":["ReadAsset","asset1"]}' | jq
|
||||
```
|
||||
|
||||
## Detailed Guide
|
||||
|
||||
```shell
|
||||
network down
|
||||
network up
|
||||
network channel create
|
||||
```
|
||||
|
||||
```shell
|
||||
# Build the chaincode docker image
|
||||
docker build -t fabric-samples/asset-transfer-basic/chaincode-java .
|
||||
|
||||
# Load the docker image directly to the KIND control plane.
|
||||
# (Alternately, build/tag/push the image to a remote container registry, e.g. localhost:5000 or ghcr.io)
|
||||
kind load docker-image fabric-samples/asset-transfer-basic/chaincode-java
|
||||
```
|
||||
|
||||
```shell
|
||||
# Assemble the chaincode package archive
|
||||
network chaincode package basic_1.0 asset-transfer-basic $PWD/build/asset-transfer.tgz
|
||||
|
||||
# Determine the ID for the chaincode package
|
||||
CORE_CHAINCODE_ID_NAME=$(network chaincode id $PWD/build/asset-transfer.tgz)
|
||||
|
||||
# Launch the chaincode in k8s as Deployment + Service
|
||||
network chaincode launch asset-transfer-basic $CORE_CHAINCODE_ID_NAME fabric-samples/asset-transfer-basic/chaincode-java
|
||||
|
||||
# Complete the chaincode lifecycle
|
||||
network chaincode install $PWD/build/asset-transfer.tgz
|
||||
network chaincode approve asset-transfer-basic $CORE_CHAINCODE_ID_NAME
|
||||
network chaincode commit asset-transfer-basic
|
||||
```
|
||||
|
||||
```shell
|
||||
# execute the smart contract by name
|
||||
network chaincode metadata asset-transfer-basic
|
||||
network chaincode invoke asset-transfer-basic '{"Args":["InitLedger"]}'
|
||||
network chaincode query asset-transfer-basic '{"Args":["ReadAsset","asset1"]}'
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl -n test-network logs -f deployment/org1peer1-ccaas-asset-transfer-basic
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Build
|
||||
|
||||
```shell
|
||||
./gradlew shadowJar
|
||||
```
|
||||
or
|
||||
```shell
|
||||
docker build -t fabric-samples/asset-transfer-basic/chaincode-java .
|
||||
```
|
||||
|
||||
|
||||
### Package
|
||||
|
||||
By instructing the peer to connect to chaincode at the Docker host alias `host.docker.internal`, pods running in
|
||||
Kubernetes will access the local process via a special loopback interface established by KIND.
|
||||
|
||||
Set the "address" attribute in the package connection.json descriptor and assemble the chaincode package:
|
||||
```shell
|
||||
export TEST_NETWORK_CHAINCODE_ADDRESS=host.docker.internal:9999
|
||||
|
||||
network cc package basic_1.0 asset-transfer-debug $PWD/build/asset-transfer-debug.tgz
|
||||
```
|
||||
|
||||
### Launch
|
||||
|
||||
When chaincode is launched locally, it must declare the package ID in the environment as if the process had been managed
|
||||
by the peer's chaincode lifecycle manager. Calculate the package ID and start the chaincode, binding to port 9999
|
||||
on the local system:
|
||||
|
||||
```shell
|
||||
export CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999
|
||||
export CORE_CHAINCODE_ID_NAME=$(network chaincode id $PWD/build/asset-transfer-debug.tgz)
|
||||
|
||||
java -jar build/libs/chaincode.jar
|
||||
```
|
||||
|
||||
Or using the editor/debugger/IDE of your choice, create a launch target for `ContractMain.main()`, specifying the
|
||||
environment as above.
|
||||
|
||||
Or launch the chaincode in a Docker container, binding to port 9999 on the host system:
|
||||
|
||||
```shell
|
||||
docker run \
|
||||
--rm \
|
||||
--name basic_1.0 \
|
||||
-p 9999:9999 \
|
||||
-e CHAINCODE_SERVER_ADDRESS \
|
||||
-e CORE_CHAINCODE_ID_NAME \
|
||||
fabric-samples/asset-transfer-basic/chaincode-java
|
||||
```
|
||||
|
||||
### Approve, Invoke, and Query
|
||||
|
||||
After the contract main has launched, install, approve, commit, and invoke the chaincode:
|
||||
|
||||
```shell
|
||||
# Complete the chaincode lifecycle
|
||||
network cc activate asset-transfer-debug $PWD/build/asset-transfer-debug.tgz
|
||||
```
|
||||
|
||||
```shell
|
||||
# execute the smart contract by name
|
||||
network cc metadata asset-transfer-debug
|
||||
network cc invoke asset-transfer-debug '{"Args":["InitLedger"]}'
|
||||
network cc query asset-transfer-debug '{"Args":["ReadAsset","asset1"]}'
|
||||
```
|
||||
|
||||
## Tear Down
|
||||
|
||||
```shell
|
||||
network down
|
||||
```
|
||||
or
|
||||
```shell
|
||||
network unkind
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -41,5 +41,6 @@ _Chaincode-as-a-Service_ running in a shared Kubernetes namespace.
|
|||
- [Deploy Orderers and Peers](TEST_NETWORK.md#starting-peers-and-orderers)
|
||||
- [Working with Channels](CHANNELS.md)
|
||||
- [Working with Chaincode](CHAINCODE.md)
|
||||
- [Debugging Chaincode](CHAINCODE_AS_A_SERVICE.md)
|
||||
- [Working with Applications](APPLICATIONS.md)
|
||||
- [High Availability](HIGH_AVAILABILITY.md)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ function set_chaincode_image() {
|
|||
}
|
||||
|
||||
# Convenience routine to "do everything other than package and launch" a sample CC.
|
||||
# This is useful in local debugging scenarios, where
|
||||
# When debugging a chaincode server, the process must be launched prior to completing
|
||||
# the chaincode lifecycle at the peer. This routine provides a route for packaging
|
||||
# and installing the chaincode out of band, and a single target to complete the peer
|
||||
# chaincode lifecycle.
|
||||
function activate_chaincode() {
|
||||
local cc_name=$1
|
||||
local cc_package=$2
|
||||
|
|
|
|||
Loading…
Reference in a new issue