forked from HyperledgerHandsOn/trade-network
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrade.sh
executable file
·1588 lines (1443 loc) · 55 KB
/
trade.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#
# SPDX-License-Identifier: Apache-2.0
#
# This script will orchestrate a sample end-to-end execution of the Hyperledger
# Fabric network.
#
# The end-to-end verification provisions a sample Fabric network consisting of
# two organizations, each maintaining two peers, and a “solo” ordering service.
#
# This verification makes use of two fundamental tools, which are necessary to
# create a functioning transactional network with digital signature validation
# and access control:
#
# * cryptogen - generates the x509 certificates used to identify and
# authenticate the various components in the network.
# * configtxgen - generates the requisite configuration artifacts for orderer
# bootstrap and channel creation.
#
# Each tool consumes a configuration yaml file, within which we specify the topology
# of our network (cryptogen) and the location of our certificates for various
# configuration operations (configtxgen). Once the tools have been successfully run,
# we are able to launch our network. More detail on the tools and the structure of
# the network will be provided later in this document. For now, let's get going...
# prepending $PWD/../bin to PATH to ensure we are picking up the correct binaries
# this may be commented out to resolve installed version of tools if desired
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=${PWD}
# By default we standup a full network.
DEV_MODE=false
# Print the usage message
function printHelp () {
echo "Usage: "
echo " trade.sh up|down|restart|generate|reset|clean|cleanall|createchannel|joinchannel|fetchconfig|updateanchorpeers|updatechannel|installcontract|initcontract|upgradecontract|invokecontract|querycontract|upgrade|createnewpeer|startnewpeer|stopnewpeer|joinnewpeer|createneworg|startneworg|stopneworg|joinneworg|updateneworganchorpeer|startrest|stoprest [-c <channel name>] [-p <contract name] [-f <docker-compose-file>] [-l <logfile>] [-b <block-file>] [-o <number-of-orgs>] [-d <true|false>] [-t <contract init-func>] [-a <contract init-args>] [-m <mode>] [-g <org-name>] [-s <db-type>] [-r]"
echo " trade.sh -h|--help (print this message)"
echo " <command> - select one from the list below'"
echo " - 'up' - bring up the network with docker-compose up"
echo " - 'down' - clear the network with docker-compose down"
echo " - 'restart' - restart the network"
echo " - 'generate' - generate required certificates and genesis block"
echo " - 'reset' - delete chaincode containers while keeping network artifacts"
echo " - 'clean' - delete network and channel artifacts"
echo " - 'cleanall' - delete network, channel, and crypto artifacts"
echo " - 'createchannel' - create a channel through the ordering service"
echo " - 'joinchannel' - join orgs' peers to this channel"
echo " - 'fetchconfig' - fetch latest channel configuration block"
echo " - 'updateanchorpeers' - update (set) anchor peers for all orgs"
echo " - 'updatechannel' - update a channel configuration through the ordering service"
echo " - 'installcontract' - package and install contract on peers, and commit definition"
echo " - 'initcontract' - initialize contract state"
echo " - 'upgradecontract' - upgrade contract code after addition of new org"
echo " - 'invokecontract' - invoke contract transaction"
echo " - 'querycontract' - query contract function"
echo " - 'upgrade' - upgrade the network from one version to another (new Fabric and Fabric-CA versions specified in .env)"
echo " - 'createnewpeer' - create cryptographic artifacts for a new peer for an org"
echo " - 'startnewpeer' - start new peer in a separate container"
echo " - 'stopnewpeer' - stop new peer"
echo " - 'joinnewpeer' - join new peer to existing channels"
echo " - 'createneworg' - create channel and crypto artifacts for new org"
echo " - 'startneworg' - start peers and CAs for new org in containers"
echo " - 'stopneworg' - stop peers and CAs of new org"
echo " - 'joinneworg' - join peer of new org to existing channels"
echo " - 'startrest' - start all rest servers (importer, exporter, regulator)"
echo " - 'stoprest' - stop all rest servers (importer, exporter, regulator)"
echo " -c <channel name> - channel name to use"
echo " -l <logfile> - log file path"
echo " -o <number-of-orgs> - number of organizations in a channel's configuration (either 3 or 4 in this application)"
echo " -p <contract name> - contract name to use"
echo " -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-e2e.yaml)"
echo " -d <true|false> - Apply command to the network in dev mode if value is 'true'"
echo " -b <block-file> - defaults to '<channel name>.block'"
echo " -t <contract init-func> - contract initialization function (defaults to \'init\')"
echo " -a <contract init-args> - contract initialization arguments: comma separated strings within single quotes, each string within double quotes (defaults to blank string). Example: '\"abcd\",\"xyz 123\", \"234\"'"
echo " -m <mode> - development mode: either 'test' (solo orderer) or 'prod' (Raft ordering service). Defaults to 'test'"
echo " -g <org-name> - organization name: e.g., 'exporterorg', 'importerorg'"
echo " -s <db-type> - either 'leveldb' or 'couchdb' (defaults to 'couchdb')"
echo " -r - indicates that volumes ought to be retained when containers are brought down"
echo
echo "Typically, one would first generate the required certificates and "
echo "genesis block, then bring up the network. e.g.:"
echo
echo " ./trade.sh generate -c tradechannel -o 3"
echo " ./trade.sh up -l logs/network.log"
echo " ./trade.sh down"
echo " ./trade.sh reset"
echo " ./trade.sh clean"
echo " ./trade.sh cleanall"
echo
echo "Taking all defaults:"
echo " trade.sh generate"
echo " trade.sh up"
echo " trade.sh down"
}
function verifyChannelName () {
if [ "$CHANNEL_NAME" == "" ]
then
echo "Channel name must be specified for this action"
exit 1
fi
}
function verifyNumOrgsInChannel () {
if [ "$NUM_ORGS_IN_CHANNEL" == "" ]
then
echo "Number of orgs in channel must be specified for this action"
exit 1
fi
}
function verifyContractName () {
if [ "$CONTRACT_NAME" == "" ]
then
echo "Contract name must be specified for this action"
exit 1
fi
}
function verifyContractFunc () {
if [ "$CONTRACT_FUNC" == "" ]
then
echo "Contract function must be specified for this action"
exit 1
fi
}
function verifyOrganization () {
if [ "$ORGANIZATION" == "" ]
then
echo "Organization name must be specified for this action"
exit 1
fi
}
# Keeps pushd silent
pushd () {
command pushd "$@" > /dev/null
}
# Keeps popd silent
popd () {
command popd "$@" > /dev/null
}
# Ask user for confirmation to proceed
function askProceed () {
read -p "Continue? [Y/n] " ans
case "$ans" in
y|Y|"" )
echo "proceeding ..."
;;
n|N )
echo "exiting..."
exit 1
;;
* )
echo "invalid response"
askProceed
;;
esac
}
# Delete any images that were generated as a part of this setup
# specifically the following images are often left behind:
# TODO list generated image naming patterns
function removeUnwantedImages() {
DOCKER_IMAGE_IDS=$(docker images | grep "dev\|none\|test-vp\|peer[0-9]-" | awk '{print $3}')
if [ -z "$DOCKER_IMAGE_IDS" -o "$DOCKER_IMAGE_IDS" == " " ]; then
echo "---- No images available for deletion ----"
else
docker rmi -f $DOCKER_IMAGE_IDS
fi
}
# Do some basic sanity checking to make sure that the appropriate versions of fabric
# binaries/images are available. In the future, additional checking for the presence
# of go or other items could be added.
function checkPrereqs() {
# Note, we check configtxlator externally because it does not require a config file, and peer in the
# docker image because of FAB-8551 that makes configtxlator return 'development version' in docker
LOCAL_VERSION=$(configtxlator version | sed -ne 's/ Version: //p')
DOCKER_IMAGE_VERSION=$(docker run --platform $PLATFORM --rm hyperledger/fabric-tools:$IMAGE_TAG peer version | sed -ne 's/ Version: //p'|head -1)
echo "LOCAL_VERSION=$LOCAL_VERSION"
echo "DOCKER_IMAGE_VERSION=$DOCKER_IMAGE_VERSION"
IMAGE_MAJOR_VERSION=${DOCKER_IMAGE_VERSION:0:3}
if [ "$IMAGE_MAJOR_VERSION" != "$FABRIC_VERSION" ]
then
echo "=========================== VERSION ERROR ==========================="
echo " Expected peer image version ${FABRIC_VERSION}.x"
echo " Found peer image version ${DOCKER_IMAGE_VERSION}"
echo " Build or download Fabric images ${FABRIC_VERSION}.x"
echo " Use the 'release-${FABRIC_VERSION}' branch of Fabric for building from source"
echo "====================================================================="
exit 1
fi
if [ "$LOCAL_VERSION" != "$DOCKER_IMAGE_VERSION" ] ; then
echo "=================== WARNING ==================="
echo " Local fabric binaries and docker images are "
echo " out of sync. This may cause problems. "
echo "==============================================="
fi
}
# Generate all the network configuration files for bootstrap and operation
function generateConfig () {
PUSHED=false
# Check if we are already in the 'devmode' folder
if [ "$DEV_MODE" = true -a -d "devmode" ] ; then
pushd ./devmode
export FABRIC_CFG_PATH=${PWD}
PUSHED=true
fi
# Create credentials for network nodes only if they don't currently exist
generateCerts
# Create credentials for multiple Raft ordering nodes only if they don't currently exist
if [ "$ORDERER_MODE" = "prod" ]
then
generateCertsForRaftOrderingNodes
fi
# We will overwrite channel artifacts if they already exist
generateChannelArtifacts
if [ "$PUSHED" = true ] ; then
popd
export FABRIC_CFG_PATH=${PWD}
fi
}
# Generate the needed certificates, the genesis block and start the network.
function networkUp () {
checkPrereqs
# If we are in dev mode, we move to the devmode directory
if [ "$DEV_MODE" = true ] ; then
pushd ./devmode
export FABRIC_CFG_PATH=${PWD}
fi
# generate artifacts if they don't exist
if [ ! -d "crypto-config" -o ! -f "channel-artifacts/genesis.block" -o ! -f "docker-compose-e2e.yaml" ]; then
echo "Network artifacts or configuration missing. Run './trade.sh generate -c <channel_name>' to recreate them."
exit 1
fi
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
COMPOSE_FILE_DB=
NUM_CONTAINERS=0
if [ "$DB_TYPE" = "couchdb" -a "$DEV_MODE" != true ]
then
COMPOSE_FILE_DB="-f "$COMPOSE_FILE_COUCHDB
NUM_CONTAINERS=3
fi
if [ "$ORDERER_MODE" = "prod" ]
then
docker-compose -f $COMPOSE_FILE_RAFT $COMPOSE_FILE_DB up >$LOG_FILE 2>&1 &
NUM_CONTAINERS=$(($NUM_CONTAINERS + 13))
else
docker-compose -f $COMPOSE_FILE $COMPOSE_FILE_DB up >$LOG_FILE 2>&1 &
NUM_CONTAINERS=$(($NUM_CONTAINERS + 9))
fi
if [ "$DEV_MODE" = true ] ; then
popd
export FABRIC_CFG_PATH=${PWD}
fi
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start network"
exit 1
fi
sleep 2
if [ "$DEV_MODE" = true ] ; then
NUM_CONTAINERS=6
fi
# Below check assumes there are no container running other than in our network
NETWORK_CONTAINERS=$(docker ps -a | grep "hyperledger/\|couchdb" | wc -l)
while [ $NETWORK_CONTAINERS -ne $NUM_CONTAINERS ]
do
sleep 2
NETWORK_CONTAINERS=$(docker ps -a | grep "hyperledger/\|couchdb" | wc -l)
done
echo "Network containers started"
}
# Start the container for the new peer.
function newPeerUp () {
checkPrereqs
# generate artifacts if they don't exist
if [ ! -d "crypto-config/peerOrganizations/importerorg.trade.com/peers/peer1.importerorg.trade.com" ]; then
echo "Peer artifacts or configuration missing. Run './trade.sh createnewpeer' to recreate them."
exit 1
fi
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_NEW_PEER)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
docker-compose -f $COMPOSE_FILE_NEW_PEER up >$LOG_FILE_NEW_PEER 2>&1 &
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start peer"
exit 1
fi
}
# Start the network components for the new org.
function newOrgNetworkUp () {
checkPrereqs
# generate artifacts if they don't exist
if [ ! -d "crypto-config/peerOrganizations/exportingentityorg.trade.com" ]; then
echo "New org crypto artifacts missing. Run './trade.sh createneworg -c <channel_name>' to create them."
exit 1
fi
for dir in ./channel-artifacts/*
do
if [ -d $dir ]
then
if [ ! -f $dir/exportingEntityOrg.json ]
then
echo "New org channel configuration missing in "$dir". Run './trade.sh createneworg -c "$(basename $dir)"' to create it."
exit 1
fi
fi
done
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_NEW_ORG)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
docker-compose -f $COMPOSE_FILE_NEW_ORG up >$LOG_FILE_NEW_ORG 2>&1 &
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start org network"
exit 1
fi
}
# Check if CLI container is running, and start it if it isn't
function checkAndStartCliContainer() {
CLI_CONTAINERS=$(docker ps | grep $CONTAINER_CLI)
if [ -z "$CLI_CONTAINERS" ] ; then
echo "No CLI container running"
# Start the container
docker-compose -f $COMPOSE_FILE_CLI up >$LOG_FILE_CLI 2>&1 &
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start cli"
exit 1
fi
sleep 2
CLI_CONTAINERS=$(docker ps | grep $CONTAINER_CLI | wc -l)
while [ $CLI_CONTAINERS -ne 1 ]
do
sleep 2
CLI_CONTAINERS=$(docker ps | grep $CONTAINER_CLI | wc -l)
done
echo "CLI container started"
fi
echo "CLI container running"
}
# Create a channel using the generated genesis block.
function createChannel () {
checkPrereqs
# check presence of channel transaction file
if [ ! -f "channel-artifacts/"${CHANNEL_NAME}"/channel.tx" ]; then
echo "ERROR !!!! No 'channel.tx' found in folder 'channel-artifacts/"${CHANNEL_NAME}"'"
echo "ERROR !!!! Run './trade.sh generate -c "$CHANNEL_NAME"' to create this transaction file"
exit 1
fi
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Create the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME $CONTAINER_CLI scripts/channel.sh create >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to create channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Channel "$CHANNEL_NAME" created"
}
# Join peers to the channel with the given name.
function joinPeersToChannel () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Join peers to the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e NUM_ORGS_IN_CHANNEL=$NUM_ORGS_IN_CHANNEL $CONTAINER_CLI scripts/channel.sh join >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to join channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Joined peers to channel "$CHANNEL_NAME
}
# Join new peer to the channel with the given name.
function joinNewPeerToChannel () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Restart the cli container to sync new peer's artifacts
docker kill $CONTAINER_CLI
docker rm $CONTAINER_CLI
checkAndStartCliContainer
# Join new peer to the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e PEER=peer1 -e ORG=importerorg $CONTAINER_CLI scripts/channel.sh joinnewpeer >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to join new peer to channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Joined peer to channel "$CHANNEL_NAME
}
# Join peer of new org to the channel with the given name.
function joinNewOrgPeerToChannel () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Restart the cli container to sync new peer's artifacts
docker kill $CONTAINER_CLI
docker rm $CONTAINER_CLI
checkAndStartCliContainer
# Join peer of new org to the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e PEER=peer0 -e ORG=exportingentityorg $CONTAINER_CLI scripts/channel.sh joinnewpeer >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to join peer of new org to channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Joined peer of new org to channel "$CHANNEL_NAME
}
# Fetch latest channel configuration block
function fetchChannelConfig () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Fetch channel config block
docker exec -e CHANNEL_NAME=$CHANNEL_NAME $CONTAINER_CLI scripts/channel.sh fetch >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to join channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
CLI_WORKING_DIR=$(docker exec $CONTAINER_CLI pwd)
docker cp $CONTAINER_CLI:$CLI_WORKING_DIR/$CHANNEL_NAME.block $BLOCK_FILE
echo "Fetched latest configuration block of channel "$CHANNEL_NAME
}
# Update anchor peers for all orgs.
function updateAnchorPeers () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Set anchor peers on the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e NUM_ORGS_IN_CHANNEL=$NUM_ORGS_IN_CHANNEL $CONTAINER_CLI scripts/channel.sh anchor >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to set anchor peers in channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Updated anchor peers in channel "$CHANNEL_NAME
}
# Update anchor peers for all orgs.
function updateNewOrgAnchorPeer () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Set anchor peer for the new org on the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME $CONTAINER_CLI scripts/channel.sh anchorneworg >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to set anchor peer for new org in channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Updated anchor peer for new org in channel "$CHANNEL_NAME
}
# Update a channel using the new organization's configuration JSON.
function updateChannel () {
checkPrereqs
# check presence of new organization's configuration JSON file
if [ ! -f "channel-artifacts/"${CHANNEL_NAME}"/exportingEntityOrg.json" ]; then
echo "ERROR !!!! No 'exportingEntityOrg.json' found in folder 'channel-artifacts/"${CHANNEL_NAME}"'"
echo "ERROR !!!! Run './trade.sh createneworg -c "$CHANNEL_NAME"' to create this transaction file"
exit 1
fi
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Restart the cli container to sync new peer's artifacts
docker kill $CONTAINER_CLI
docker rm $CONTAINER_CLI
checkAndStartCliContainer
# Update the channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e NUM_ORGS_IN_CHANNEL=$NUM_ORGS_IN_CHANNEL $CONTAINER_CLI scripts/channel.sh update >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to update channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Channel "$CHANNEL_NAME" updated"
}
# Install contract on channel.
function installContract () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Package contract
if [ "$CONTRACT_NAME" == "trade" ]
then
CC_LANGUAGE=node
PEERORGLIST="exporterorg importerorg regulatororg"
elif [ "$CONTRACT_NAME" == "letterOfCredit" ]
then
CC_LANGUAGE=java
PEERORGLIST="exporterorg importerorg"
elif [ "$CONTRACT_NAME" == "exportLicense" ]
then
CC_LANGUAGE=java
PEERORGLIST="exporterorg regulatororg"
elif [ "$CONTRACT_NAME" == "shipment" ]
then
CC_LANGUAGE=node
PEERORGLIST="exporterorg importerorg carrierorg"
else
echo "ERROR !!!! Unknown contract: "$CONTRACT_NAME
exit 1
fi
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e CC_LANGUAGE=$CC_LANGUAGE -e CC_LABEL=$CONTRACT_NAME -e CC_VERSION=v1 trade_cli scripts/chaincode.sh package >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to package contract"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Packaged contract "$CONTRACT_NAME" in channel "$CHANNEL_NAME
# Install contract on peers
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e PEERORGLIST="$PEERORGLIST" -e CC_LABEL=$CONTRACT_NAME -e CC_VERSION=v1 trade_cli scripts/chaincode.sh install >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to install contract on peers"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Installed contract "$CONTRACT_NAME" in channel "$CHANNEL_NAME
# Approve contract definition from each peer on channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e NUM_ORGS_IN_CHANNEL=$NUM_ORGS_IN_CHANNEL -e PEERORGLIST="$PEERORGLIST" -e CC_LABEL=$CONTRACT_NAME -e CC_VERSION=v1 trade_cli scripts/chaincode.sh approve >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to approve contract definitions on channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Approved contract "$CONTRACT_NAME" definitions in channel "$CHANNEL_NAME
# Commit chaincode definition on channel
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e NUM_ORGS_IN_CHANNEL=$NUM_ORGS_IN_CHANNEL -e PEERORGLIST="$PEERORGLIST" -e CC_LABEL=$CONTRACT_NAME -e CC_VERSION=v1 trade_cli scripts/chaincode.sh commit >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to commit contract definition on channel"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Committed contract "$CONTRACT_NAME" definition in channel "$CHANNEL_NAME
}
# Initialize contract on channel.
function initContract () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Initialize contract state on ledger
if [ "$CONTRACT_NAME" == "trade" ]
then
PEERORGLIST="exporterorg importerorg regulatororg"
elif [ "$CONTRACT_NAME" == "letterOfCredit" ]
then
PEERORGLIST="exporterorg importerorg"
elif [ "$CONTRACT_NAME" == "exportLicense" ]
then
PEERORGLIST="exporterorg regulatororg"
elif [ "$CONTRACT_NAME" == "shipment" ]
then
PEERORGLIST="exporterorg importerorg carrierorg"
else
echo "ERROR !!!! Unknown contract: "$CONTRACT_NAME
exit 1
fi
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e PEERORGLIST="$PEERORGLIST" -e CC_LABEL=$CONTRACT_NAME -e CC_FUNC=$CONTRACT_FUNC -e CC_ARGS="$CONTRACT_ARGS" trade_cli scripts/chaincode.sh init >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to initialize contract"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Initialized contract "$CONTRACT_NAME" state on ledger in channel "$CHANNEL_NAME
}
# Upgrade contract on channel.
function upgradeContract () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
docker kill $CONTAINER_CLI
docker rm $CONTAINER_CLI
checkAndStartCliContainer
# Upgrade contract state on ledger
if [ "$CONTRACT_NAME" == "trade" ]
then
CC_LANGUAGE=node
PEERORGLIST="exporterorg importerorg regulatororg"
elif [ "$CONTRACT_NAME" == "letterOfCredit" ]
then
CC_LANGUAGE=java
PEERORGLIST="exporterorg importerorg"
elif [ "$CONTRACT_NAME" == "exportLicense" ]
then
CC_LANGUAGE=java
PEERORGLIST="exporterorg regulatororg"
elif [ "$CONTRACT_NAME" == "shipment" ]
then
CC_LANGUAGE=node
PEERORGLIST="exporterorg importerorg carrierorg"
else
echo "ERROR !!!! Unknown contract: "$CONTRACT_NAME
exit 1
fi
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e NUM_ORGS_IN_CHANNEL=$NUM_ORGS_IN_CHANNEL -e PEERORGLIST="$PEERORGLIST" -e CC_LANGUAGE=$CC_LANGUAGE -e CC_LABEL=$CONTRACT_NAME -e CC_VERSION=v2 -e OLD_CC_VERSION=v1 -e CC_FUNC=$CONTRACT_FUNC -e CC_ARGS="$CONTRACT_ARGS" trade_cli scripts/chaincode.sh upgrade >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to upgrade contract"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Upgraded contract "$CONTRACT_NAME" state on ledger in channel "$CHANNEL_NAME
}
# Invoke contract transaction on channel.
function invokeContract () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Invoke contract transaction
if [ "$CONTRACT_NAME" == "trade" ]
then
PEERORGLIST="exporterorg importerorg regulatororg"
elif [ "$CONTRACT_NAME" == "letterOfCredit" ]
then
PEERORGLIST="exporterorg importerorg"
elif [ "$CONTRACT_NAME" == "exportLicense" ]
then
PEERORGLIST="exporterorg regulatororg"
elif [ "$CONTRACT_NAME" == "shipment" ]
then
PEERORGLIST="exporterorg importerorg carrierorg"
else
echo "ERROR !!!! Unknown contract: "$CONTRACT_NAME
exit 1
fi
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e PEERORGLIST="$PEERORGLIST" -e CC_LABEL=$CONTRACT_NAME -e CC_FUNC=$CONTRACT_FUNC -e CC_ARGS="$CONTRACT_ARGS" -e ORGANIZATION=$ORGANIZATION trade_cli scripts/chaincode.sh invoke >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to invoke contract"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Invoked contract "$CONTRACT_NAME" transaction in channel "$CHANNEL_NAME" using org "$ORGANIZATION
}
# Query contract function on channel.
function queryContract () {
checkPrereqs
# Create folder for docker network logs
LOG_DIR=$(dirname $LOG_FILE_CLI)
if [ ! -d $LOG_DIR ]
then
mkdir -p $LOG_DIR
fi
# Check if the cli container is already running
checkAndStartCliContainer
# Query contract function
docker exec -e CHANNEL_NAME=$CHANNEL_NAME -e CC_LABEL=$CONTRACT_NAME -e CC_FUNC=$CONTRACT_FUNC -e CC_ARGS="$CONTRACT_ARGS" -e ORGANIZATION=$ORGANIZATION trade_cli scripts/chaincode.sh query >>$LOG_FILE_CLI 2>&1
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to query contract"
echo "ERROR !!!! See "$LOG_FILE_CLI" for details"
exit 1
fi
echo "Queried contract "$CONTRACT_NAME" function in channel "$CHANNEL_NAME" using org "$ORGANIZATION
}
# Upgrade the network from one version to another
# The new image tag is looked up from the .env file
# Stop the orderer and peers, backup the ledger from orderer and peers, cleanup chaincode containers and images
# and relaunch the orderer and peers with latest tag
function upgradeNetwork () {
docker inspect -f '{{.Config.Volumes}}' orderer.trade.com |grep -q '/var/hyperledger/production/orderer'
if [ $? -ne 0 ]; then
echo "ERROR !!!! This network does not appear to be using volumes for its ledgers, did you start from fabric-samples >= v1.0.6?"
exit 1
fi
LEDGERS_BACKUP=./ledgers-backup
# create ledger-backup directory
mkdir -p $LEDGERS_BACKUP
if [ "$ORDERER_MODE" = "prod" ]
then
COMPOSE_FILES="-f $COMPOSE_FILE_RAFT"
ORDERERS="orderer.trade.com orderer2.trade.com orderer3.trade.com orderer4.trade.com orderer5.trade.com"
else
COMPOSE_FILES="-f $COMPOSE_FILE"
ORDERERS="orderer.trade.com"
fi
for ORDERER in $ORDERERS; do
echo "Upgrading orderer $ORDERER"
docker-compose $COMPOSE_FILES stop $ORDERER
mkdir -p $LEDGERS_BACKUP/$ORDERER
docker cp -a $ORDERER:/var/hyperledger/production/orderer $LEDGERS_BACKUP/$ORDERER/
docker-compose $COMPOSE_FILES up --no-deps $ORDERER >$LOG_FILE 2>&1 &
done
for PEER in peer0.exporterorg.trade.com peer0.importerorg.trade.com peer0.carrierorg.trade.com peer0.regulatororg.trade.com; do
echo "Upgrading peer $PEER"
# Stop the peer and backup its ledger
docker-compose $COMPOSE_FILES stop $PEER
mkdir -p $LEDGERS_BACKUP/$PEER
docker cp -a $PEER:/var/hyperledger/production $LEDGERS_BACKUP/$PEER/
# Remove any old containers and images for this peer
CC_CONTAINERS=$(docker ps | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_CONTAINERS" ] ; then
docker rm -f $CC_CONTAINERS
fi
CC_IMAGES=$(docker images | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_IMAGES" ] ; then
docker rmi -f $CC_IMAGES
fi
# Start the peer again
docker-compose $COMPOSE_FILES up --no-deps $PEER >$LOG_FILE 2>&1 &
done
for CA in exporter importer carrier regulator; do
echo "Upgrading CA ${CA}-ca"
# Stop the CA and backup its database
docker-compose $COMPOSE_FILES stop ${CA}-ca
mkdir -p $LEDGERS_BACKUP/${CA}-ca
docker cp -a ca.${CA}org.trade.com:/etc/hyperledger/fabric-ca-server $LEDGERS_BACKUP/${CA}-ca/
# Start the CA again
docker-compose $COMPOSE_FILES up --no-deps ${CA}-ca >$LOG_FILE 2>&1 &
done
}
# Bring down running network
function networkDown () {
if [ "$ORDERER_MODE" = "prod" ]
then
COMPOSE_FILES="-f "$COMPOSE_FILE_RAFT
else
COMPOSE_FILES="-f "$COMPOSE_FILE
fi
# If we are in dev mode, we move to the devmode directory
if [ "$DEV_MODE" = true ] ; then
pushd ./devmode
else
COMPOSE_FILES=$COMPOSE_FILES" -f "$COMPOSE_FILE_CLI" -f "$COMPOSE_FILE_NEW_PEER" -f "$COMPOSE_FILE_NEW_ORG" -f "$COMPOSE_FILE_REST" -f "$COMPOSE_FILE_COUCHDB
fi
# Stop network containers, and also the CLI container if it is running
if [ "$RETAIN_VOLUMES" == "true" ]
then
docker-compose $COMPOSE_FILES down
else
docker-compose $COMPOSE_FILES down --volumes
fi
echo "Network containers stopped"
for PEER in peer0.exporterorg.trade.com peer0.importerorg.trade.com peer0.carrierorg.trade.com peer0.regulatororg.trade.com peer1.importerorg.trade.com peer0.exportingentityorg.trade.com; do
# Remove any old containers and images for this peer
CC_CONTAINERS=$(docker ps -a | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_CONTAINERS" ] ; then
docker rm -f $CC_CONTAINERS
fi
done
echo "Chaincode containers stopped"
if [ "$DEV_MODE" = true ] ; then
popd
fi
if [ "$RETAIN_VOLUMES" == "false" ]
then
echo "Pruning remaining local volumes"
# Prune any remaining local volumes
docker volume prune -f
fi
}
# Bring down new peer
function newPeerDown () {
docker-compose -f $COMPOSE_FILE_NEW_PEER down --volumes
echo "Ignore any error messages of the form 'error while removing network' you see above!!!"
docker volume rm ${COMPOSE_PROJECT_NAME}_peer1.importerorg.trade.com
}
# Bring down running network components of the new org
function newOrgNetworkDown () {
docker-compose -f $COMPOSE_FILE_NEW_ORG down --volumes
echo "Ignore any error messages of the form 'error while removing network' you see above!!!"
for PEER in peer0.exportingentityorg.trade.com; do
# Remove any old containers and images for this peer
CC_CONTAINERS=$(docker ps -a | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_CONTAINERS" ] ; then
docker rm -f $CC_CONTAINERS
fi
done
docker volume rm ${COMPOSE_PROJECT_NAME}_peer0.exportingentityorg.trade.com
}
# Delete dynamically created credentials, like wallet identities
function cleanDynamicIdentities () {
# remove wallet identities
rm -rf ../wallets/exporterorg/*
rm -rf ../wallets/importerorg/*
rm -rf ../wallets/carrierorg/*
rm -rf ../wallets/regulatororg/*
# remove client certs (this is a holdover from the legacy first-edition code)
rm -rf client-certs
}
# Stop network, and delete dynamically created credentials and channel artifacts
function networkClean () {
#Cleanup the chaincode containers and volumes
NETWORK_CONTAINERS=$(docker ps -a | grep -v CONT | wc -l)
if [ $NETWORK_CONTAINERS -gt 0 ]
then
networkDown
fi
# If we are in dev mode, we move to the devmode directory
if [ "$DEV_MODE" = true ] ; then
pushd ./devmode
else
# remove dynamic identities
cleanDynamicIdentities
# remove images created for contracts
removeUnwantedImages
fi
# remove orderer block and other channel configuration transactions and certs
rm -rf channel-artifacts
if [ "$DEV_MODE" = true ] ; then
popd
fi
}
# Stop network, and delete dynamically created credentials, channel artifacts, and all crypto material
function networkCleanAll () {
networkClean
# If we are in dev mode, we move to the devmode directory
if [ "$DEV_MODE" = true ] ; then
pushd ./devmode
fi
rm -rf crypto-config
if [ "$DEV_MODE" = true ] ; then
popd
fi
}
# We will use the cryptogen tool to generate the cryptographic material (x509 certs)
# for our various network entities. The certificates are based on a standard PKI
# implementation where validation is achieved by reaching a common trust anchor.
#
# Cryptogen consumes a file - ``crypto-config.yaml`` - that contains the network
# topology and allows us to generate a library of certificates for both the
# Organizations and the components that belong to those Organizations. Each
# Organization is provisioned a unique root certificate (``ca-cert``), that binds