├── .gitignore ├── scripts └── cidataiso.sh ├── README.md ├── devenv-cloud-config.yaml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *.iso 2 | -------------------------------------------------------------------------------- /scripts/cidataiso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -l 2 | 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | usage() { 8 | echo "Usage: cidataiso.sh -u " 9 | echo 10 | echo " Creates a cloud init ISO" 11 | echo 12 | echo " Flags:" 13 | echo " -u - the cloud-config user-data file to include in the ISO" 14 | echo " -h - Print this message" 15 | } 16 | 17 | error_exit() { 18 | echo "${1:-"Unknown Error"}" 1>&2 19 | exit 1 20 | } 21 | 22 | while getopts "hu:" opt; do 23 | case "$opt" in 24 | h) 25 | usage 26 | exit 0 27 | ;; 28 | u) 29 | config=${OPTARG} 30 | ;; 31 | *) 32 | usage 33 | exit 1 34 | ;; 35 | esac 36 | done 37 | shift $((OPTIND-1)) 38 | 39 | if [ ! -f "$config" ]; then 40 | usage 41 | exit 1 42 | fi 43 | 44 | isoname=config.iso 45 | 46 | prefix=$(basename "$0") 47 | tempdir=$(mktemp -d -t "$prefix.XXXXXXXX") || error_exit "Error creating temporary directory" 48 | 49 | if [ -n "$DEBUG" ]; then 50 | echo "config = $config" 51 | echo "isoname = $isoname" 52 | echo "tempdir = $tempdir" 53 | fi 54 | 55 | mkdir -p "$tempdir/cidata" 56 | cp "$config" "$tempdir/cidata/user-data" 57 | touch "$tempdir/cidata/meta-data" 58 | 59 | if command -v hdiutil > /dev/null; then 60 | hdiutil makehybrid -o "$isoname" -hfs -joliet -iso -default-volume-name cidata "$tempdir/cidata" 61 | elif command -v genisoimage > /dev/null; then 62 | genisoimage -output "$isoname" -volid cidata -joliet -rock "$tempdir/cidata/user-data" "$tempdir/cidata/meta-data" 63 | else 64 | error_exit "Cannot find hdiutil or genisoimage" 65 | fi 66 | 67 | rm -Rf "$tempdir" 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fabric-cloud-init 2 | 3 | Experimental cloud config to set up a Fabric development environment which is intended to work on both amd64 and arm64 architectures. 4 | 5 | **Important:** Due to the lack of arm64 based Fabric docker images, the only option for running smart contracts on arm64 is to use the nano test network and the chaincode as a service (CCaaS) builder. 6 | 7 | ## Usage 8 | 9 | ```shell 10 | multipass launch \ 11 | --name fabric-dev \ 12 | --disk 80G \ 13 | --cpus 8 \ 14 | --mem 8G \ 15 | --cloud-init devenv-cloud-config.yaml 16 | ``` 17 | 18 | And then... 19 | 20 | ```shell 21 | multipass shell fabric-dev 22 | ``` 23 | 24 | And then... 25 | 26 | ```shell 27 | setup-fabric 28 | ``` 29 | 30 | No and then... 31 | 32 | Everything should be ready to start developing and testing Fabric chaincode! 33 | 34 | ## Running chaincode as a service 35 | 36 | First, change to the nano test network directory. 37 | 38 | ```shell 39 | cd ~/fabric-samples/test-network-nano-bash/ 40 | ``` 41 | 42 | Next, start the Fabric network. 43 | 44 | ```shell 45 | ./network.sh start 46 | ``` 47 | 48 | Open another terminal, and shell in to the `fabric-dev` VM again. 49 | 50 | ```shell 51 | multipass shell fabric-dev 52 | ``` 53 | 54 | Make sure you're in the nano test network directory. 55 | 56 | ```shell 57 | cd ~/fabric-samples/test-network-nano-bash/ 58 | ``` 59 | 60 | Set up the environment to run `peer` commands against `peer1`. 61 | 62 | ```shell 63 | . ./peer1admin.sh 64 | ``` 65 | 66 | Create a CCaaS package. 67 | 68 | ```shell 69 | pkgccaas -l devcc -a 127.0.0.1:9999 70 | ``` 71 | 72 | Install the CCaaS package. 73 | 74 | ```shell 75 | peer lifecycle chaincode install devcc.tgz 76 | ``` 77 | 78 | Export a PACKAGE_ID environment variable for use in the following commands. 79 | 80 | ```shell 81 | export PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid devcc.tgz) && echo $PACKAGE_ID 82 | ``` 83 | 84 | Note: the PACKAGE_ID must match the chaincode code package identifier shown by the peer lifecycle chaincode install command. 85 | 86 | Approve the chaincode. 87 | 88 | ```shell 89 | peer lifecycle chaincode approveformyorg -o 127.0.0.1:6050 --channelID mychannel --name dev-contract --version 1 --package-id $PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt 90 | ``` 91 | 92 | Commit the chaincode. 93 | 94 | ```shell 95 | peer lifecycle chaincode commit -o 127.0.0.1:6050 --channelID mychannel --name dev-contract --version 1 --sequence 1 --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt 96 | ``` 97 | 98 | Everything is configured but now you actually need to run some chaincode for Fabric to connect to! 99 | Open another new terminal, and shell in to the `fabric-dev` VM again. 100 | 101 | ```shell 102 | multipass shell fabric-dev 103 | ``` 104 | 105 | Change to the a suitable chaincode source directory, e.g. 106 | 107 | ```shell 108 | cd ~/fabric-samples/asset-transfer-basic/chaincode-go/ 109 | ``` 110 | 111 | Export a `CORE_CHAINCODE_ID_NAME` environment variable, which is required to run chaincode as a service. 112 | This is the same as the `PACKAGE_ID` in previous steps. 113 | [TODO: don't include the value here?] 114 | 115 | ```shell 116 | export CORE_CHAINCODE_ID_NAME=devcc:f357d81429a6a2fe63708d257e18e9c35dfe06c6b073c85b4baa65b0b4f159cb 117 | ``` 118 | 119 | Export a `CHAINCODE_SERVER_ADDRESS` environment variable, which is the address the chaincode will run at. 120 | 121 | ```shell 122 | export CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999 123 | ``` 124 | 125 | Update the chaincode to the latest version of `fabric-contract-api-go`. 126 | [TODO: fix this!] 127 | 128 | ```shell 129 | go get -u github.com/hyperledger/fabric-contract-api-go 130 | go mod tidy 131 | ``` 132 | 133 | Start the chaincode! 134 | 135 | ```shell 136 | go run assetTransfer.go 137 | ``` 138 | 139 | To run transactions, switch back to the terminal you used to run the `peer` commands. 140 | 141 | For example, query the chaincode metadata. 142 | 143 | ```shell 144 | peer chaincode query -C mychannel -n dev-contract -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}' 145 | ``` 146 | 147 | ## Work in progress 148 | 149 | Nothing to see here! 150 | 151 | Would a specific fabric user with ssh access be useful? (TBC) 152 | 153 | ```yaml 154 | users: 155 | - name: fabdev 156 | lock_passwd: false 157 | sudo: ['ALL=(ALL) NOPASSWD:ALL'] 158 | groups: sudo 159 | shell: /bin/bash 160 | 161 | chpasswd: 162 | expire: true 163 | users: 164 | - name: fabdev 165 | type: RANDOM 166 | 167 | runcmd: 168 | - sed -i -e '/^Port/s/^.*$/Port 4444/' /etc/ssh/sshd_config 169 | - sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config 170 | - sed -i -e '$aAllowUsers demo' /etc/ssh/sshd_config 171 | - restart ssh 172 | ``` 173 | 174 | Git clone or download source tarball? 175 | 176 | ```shell 177 | wget -O fabric.tar.gz https://github.com/hyperledger/fabric/archive/refs/tags/v2.4.6.tar.gz 178 | 179 | git clone --depth 1 --branch release-2.4 https://github.com/hyperledger/fabric.git 180 | ``` 181 | 182 | Cannot use `make release` because Fabric Makefile doesn't include arm in release platforms... 183 | 184 | ``` 185 | RELEASE_PLATFORMS = darwin-amd64 linux-amd64 windows-amd64 linux-arm64 186 | ``` 187 | 188 | What's up with Go? It keeps complaining that `warning: GOPATH set to GOROOT (/usr/local/go) has no effect` which doesn't appear to be true! At least I've not found another way to get the binaries installed in the right place yet! 189 | 190 | ``` 191 | GOMODCACHE=/usr/local/go/pkg/mod GOCACHE=/root/.cache/go-build 192 | ``` 193 | 194 | 195 | 196 | 197 | 198 | K8s.. 199 | 200 | kind create cluster 201 | 202 | kubectl cluster-info --context kind-kind 203 | 204 | export KUBECONFIG_PATH=$HOME/.kube/config 205 | 206 | ip addr show docker0 <- didn't work! 207 | 208 | docker exec kind-control-plane sh -c 'ip addr show eth0' 209 | 210 | docker network inspect kinds 211 | 212 | jq to extract Gateway? 213 | 214 | Find/replace CCADDR with the default gateway in the four peerX.sh scripts, e.g. 172.18.0.1 215 | 216 | ./network.sh start 217 | 218 | New terminal in nano test network dir... 219 | 220 | cd ~/fabric-samples/test-network-nano-bash/ 221 | 222 | . ./peer1admin.sh 223 | 224 | ``` 225 | curl -fsSL \ 226 | https://github.com/hyperledgendary/conga-nft-contract/releases/download/v0.1.3/conga-nft-contract-v0.1.3.tgz \ 227 | -o conga-nft.tgz 228 | ``` 229 | 230 | peer lifecycle chaincode install conga-nft.tgz 231 | 232 | export PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid conga-nft.tgz) && echo $PACKAGE_ID 233 | 234 | peer lifecycle chaincode approveformyorg -o 127.0.0.1:6050 --channelID mychannel --name sample-contract --version 1 --package-id $PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt 235 | 236 | peer lifecycle chaincode commit -o 127.0.0.1:6050 --channelID mychannel --name sample-contract --version 1 --sequence 1 --tls --cafile "${PWD}"/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt 237 | 238 | peer chaincode query -C mychannel -n sample-contract -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}' 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | https://docs.docker.com/network/network-tutorial-standalone/ 248 | 249 | https://gist.github.com/developer-guy/173347e71f92a61abbc017deb518b6cb 250 | 251 | 252 | kubectl run bash-shell --rm -i --tty --image ubuntu -- bash 253 | 254 | kubectl apply -f https://k8s.io/examples/application/shell-demo.yaml 255 | -------------------------------------------------------------------------------- /devenv-cloud-config.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | groups: 4 | - docker 5 | 6 | system_info: 7 | default_user: 8 | groups: [docker] 9 | 10 | apt: 11 | sources: 12 | docker.list: 13 | source: deb https://download.docker.com/linux/ubuntu $RELEASE stable 14 | keyid: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 15 | kubernetes.list: 16 | source: deb https://apt.kubernetes.io/ kubernetes-xenial main 17 | keyid: 7F92E05B31093BEF5A3C2D38FEEA9169307EA071 18 | 19 | # prebuilt-mpr should have "just" but doesn't seem to include arm :( 20 | # prebuilt.list: 21 | # source: deb https://proget.makedeb.org prebuilt-mpr $RELEASE 22 | # key: | 23 | # -----BEGIN PGP PUBLIC KEY BLOCK----- 24 | # Version: BCPG C# v1.8.1.0 25 | 26 | # mQINBGJslcEBEACWT0Kphz3bmIO7s3BRW8Rw2m36YI0lDQmdkZy9F6Aa8+Ov9b6+ 27 | # 44hAvPYfm0fjOiGxq264v9Av5/26vcrDYsPKupaQs6EjT0NjcZ2A47KLpeJGzbzt 28 | # 74KP+YyKm/oqW8Md8jb8GBRq0dnFoLOOA6bvHzP7TzANAKFIEZQ0m4GO/AI6Y9ap 29 | # 09Q+gZramLl9OCoKRhnmC7QiJO9PSLLvBJOWk3pORpMU5GK5df2RYgpC6d0laFe4 30 | # KmmqcmuU7PgGAJ9C0Fy9i4WEEPdIrJ1Sg0PNnCloLGxFYg1he3gkF2GnTHAU05Ih 31 | # yc1anMv4MDh5m3+Em3laEnR16lMPPi/veLvdyGJ61f1I8cih391afvHloN2J3Z+j 32 | # 0sZN7BZthIWkoqhd6DnZ+XGwJoM3lAsPaH3uHsNtquWIqEOO0UBndIOmrcVd5QyY 33 | # 1tAJBQHl9XDRirIfsbFxESevANTkc6DCe7VPLADK/nTqwVrrruOZAIXrEwnoWTFj 34 | # xxl7lW+zswiVJWcpYIMQClCAgdq0g7bLs3UvPn4cUYYLTXRp+3LDps7hwmmoEYCD 35 | # bsp4exVPS9Whzu2/6ojR4pwJcXdvXsnPsqcQGwwd/pNaJrjC/BmWbQBZaBspfj2X 36 | # AtnhObFJkB49UWr+cFBIcoJAUEL16WyAf/o/1K8n1299Cc1QeUgBg1F41wARAQAB 37 | # tBNjb250YWN0QG1ha2VkZWIub3JniQIlBBMBAgAPApsDBYJibJXBBYkAAAAAAAoJ 38 | # EE/p8sQ9lCig3esQAIXM6ib4PJqKbAd5enhPBkAquZzLIsdaNg3f5dqan5BptIGM 39 | # 8EOS82Urlw7PACLlqf8lkM+0riU1SXGuEig+TFHHeYE9xYL9JguLnT+Iumfe/0YM 40 | # y/26VNadQJv581eJUnRfOBdhUFsCwksLE28qq8SKDq9a8n719TgPngTZNaD0zCNB 41 | # Tk90cwa7oRfUQza9IMn/7AvjvkpuwpsyZeSMj4RNL+1PaqgSgF1W94YWbXGO0e+g 42 | # fyp+r8WH0rYEUbl51FxGw5vXV9hGKe2Xbo40TAIv//l//8LeluA3P4nzPnr1pGaq 43 | # iqsIsVTfluC8OC0uEFTnsMCiyEUnP7LlCJc5dZeA+JfSuiwUI117cZ5TQr8uRY9L 44 | # zHiwKJkkrg2XNxwjQ20BZASd4HOHW8NcD/MULUL3d+pQ+lzbqcHLqT69YJdfVnPa 45 | # PEAsjHEauDbwgHyhy2pa2l43GcvecxlZTIXgKH+gGO+G2vC3vMFVcPLN0JWbHEkD 46 | # Tyiht2rMcIaEGXqzigc/S9czkOzsUuFdlWlBslBxJ6/yJYj5kvpSyGRJIe0dKZMp 47 | # yYDQQmO0+OuA75BUveDK9v9msA25NX8Ynus7tNh1LdlSnaJv6JYEIEhWDVBEkPmQ 48 | # TKGNsT2a5xrLry8pS3XJYThitIc8G7/ngzVOejsZ94G4OmYuCQxK97Hf/aHu 49 | # =Vi1D 50 | # -----END PGP PUBLIC KEY BLOCK----- 51 | 52 | package_update: true 53 | package_upgrade: true 54 | 55 | packages: 56 | - jq 57 | - curl 58 | - software-properties-common 59 | - apt-transport-https 60 | - ca-certificates 61 | - gnupg-agent 62 | - software-properties-common 63 | - docker-ce 64 | - docker-ce-cli 65 | - containerd.io 66 | - make 67 | - gcc 68 | - tzdata 69 | - kubectl 70 | 71 | write_files: 72 | - path: /etc/profile 73 | content: | 74 | export PATH=$PATH:$HOME/go/bin:/usr/local/go/bin 75 | append: true 76 | - path: /etc/nsswitch.conf 77 | content: | 78 | hosts: files dns 79 | - path: /usr/local/bin/pkgccaas 80 | permissions: '0755' 81 | content: | 82 | #!/usr/bin/env sh 83 | 84 | # TODO: 85 | # - download pkgccaas script from git instead of embedding it in yaml? 86 | # - same for pkgk8s, or combine the two? 87 | 88 | usage() { 89 | echo "Usage: pkgccaas -l