在shell脚本中调用chaincode函数



我已经建立了一个超级账本网络,网络设置得很好。链码也已部署。现在,我想调用链码中的一个函数。如果我必须通过终端操作,那么它会像这样:

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"StorePacketData","Args":["a0", "b0", "c0", "d0", "e0"]}'

这工作得很好。但是,我想从shell脚本调用这个函数,其中函数的参数将是变量。该shell脚本文件可由另一个shell脚本调用。因此,我的shell脚本文件看起来像这样:

#!/bin/bash
invokeCC() {
arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}'
}
invokeCC $1 $2 $3 $4 $5

很明显:

'{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}'

作为一个完整的字符串,不能传递变量。因此,我尝试了一个变体:

#!/bin/bash
invokeCC() {
arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
QUOTE="'"
args="{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c $QUOTE$args$QUOTE
}
invokeCC $1 $2 $3 $4 $5

这也给出了错误,也就是

Error: chaincode argument error: invalid character ''' looking for beginning of value

我知道我在第二种方法中出错了,但我不知道还能做什么。

请建议我在这里应该做什么来调用链码。如果还需要我提供其他信息,请告诉我。

提前感谢!

要使用任意命令行参数列表生成格式良好、语法有效的JSON,请使用jqversion 1.6和$ARGS.positional:

#!/usr/bin/env bash
invokeCC() {
args=$(jq -n '{"function":"StorePacketData", "Args": $ARGS.positional}' --args "$@")
peer chaincode invoke ... --args "$args"
}
invokeCC "$@"

使用--arg$ARGS.named也可以达到同样的目的:

invokeCC() {
local -a jq_args=( )
local arg idx=0 idx_str
for arg in "$@"; do
printf -v idx_str '%04d' "$idx"
jq_args+=( --arg "arg$idx_str" "$arg" )
(( ++idx ))
done
jq -nc "${jq_args[@]}" '{"function": "StorePacketData", "Args": [$ARGS.named | to_entries | sort_by(.key)[] | .value]}'
}
invokeCC "$@"

正如@Charles Duffy建议的那样,我使用jq来传递参数。因此,我将shell脚本更改为:

#!/bin/bash
invokeCC() {
arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
echo hello
args=$(jq 
-n --arg val1 "$arg1" 
-n --arg val2 "$arg2" 
-n --arg val3 "$arg3" 
-n --arg val4 "$arg4" 
-n --arg val5 "$arg5" 
'{"function":"StorePacketData", "Args": [$val1, $val2, $val3, $val4, $val5]}'
)
echo "$args"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c "$args"
}
invokeCC "$1" "$2" "$3" "$4" "$5"

这工作得很好。然而,@Charles Duffy提出的解决方案要好得多。