链码开发学习
一、编写链码
直接抄袭https://hyperledger-fabric.readthedocs.io/en/release-2.2/chaincode4ade.html
二、链码部署
1、启动测试网络,这个简单
testnet
./network.sh down
./network.sh up createChannel
2、打包链码
设置环境变量
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
添加链码名字的环境变量
export CHAINCODE_NAME=firstcc
打包链码
#注意替换链码文件路径
#注意替换<chaincode-name>内容
peer lifecycle chaincode package $CHAINCODE_NAME.tar.gz --path /root/hyperledger/sacc/ --lang golang --label firstcc_1.0
3、安装链码
以org1身份运行
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
在org1安装链码
peer lifecycle chaincode install $CHAINCODE_NAME.tar.gz
以org2身份运行
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer lifecycle chaincode install $CHAINCODE_NAME.tar.gz
查询链码包ID
peer lifecycle chaincode queryinstalled
添加链码包ID的环境变量
export CC_PACKAGE_ID=firstcc_1.0:e2b1790a571761895b9324b3ff95171215b88f1ab31d370a95a39f48bae426ab #注意替换这里的链码包ID
4、批准链码定义
org2同意该链码定义
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name $CHAINCODE_NAME \
--version 1.0 \
--package-id $CC_PACKAGE_ID \
--sequence 1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
org1同意该定义
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name $CHAINCODE_NAME \
--version 1.0 \
--package-id $CC_PACKAGE_ID \
--sequence 1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
检查同意情况
peer lifecycle chaincode checkcommitreadiness \
--channelID mychannel \
--name $CHAINCODE_NAME \
--version 1.0 \
--sequence 1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
--output json
5、提交链码
peer lifecycle chaincode commit \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name $CHAINCODE_NAME \
--version 1.0 \
--sequence 1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
--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
注意,这里是以org1身份提交的链码,亦可以用org2进行提交,只需一方提交一次即可。
确认是否提交
peer lifecycle chaincode querycommitted \
--channelID mychannel \
--name $CHAINCODE_NAME \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
6、调用链码
初始化资产
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 $CHAINCODE_NAME \
--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":"initLedger","Args":[]}'
查询所有资产
peer chaincode query \
-C mychannel \
-n $CHAINCODE_NAME \
-c '{"Args":["getAllAssets"]}'
可以在测试完成后关闭网络
./network.sh down
nodejs开发
智能合约处理文档:https://hyperledger-fabric.readthedocs.io/en/latest/developapps/smartcontract.html
fabric-contract-api官方文档:https://hyperledger.github.io/fabric-chaincode-node/master/api/#toc1__anchor
在开发模式下运行chaincode
一、搭建开发环境
https://hyperledger-fabric.readthedocs.io/en/latest/peer-chaincode-devmode.html#
1、所有命令均在fabric/文件夹中执行
2、运行以下命令来构建orderer,peer和configtxgen的二进制文件:
make orderer peer configtxgen
会在build/bin目录下生成二进制的执行文件
3、设置PATH环境变量以包括orderer和peer二进制文件:
export PATH=$(pwd)/build/bin:$PATH
4、将FABRIC_CFG_PATH环境变量设置为指向sampleconfig文件夹:
export FABRIC_CFG_PATH=$(pwd)/sampleconfig
5、生成订单服务的创世块。
运行以下命令以生成创世块并将其存储在其中,$(pwd)/sampleconfig/genesisblock以便订购者可以在启动订购者时在下一步中使用它。
configtxgen -profile SampleDevModeSolo -channelID syschannel -outputBlock genesisblock -configPath $FABRIC_CFG_PATH -outputBlock "$(pwd)/sampleconfig/genesisblock"
二、启动orderer
运行以下命令以使用SampleDevModeSolo概要文件启动订购者并启动订购服务:
export PATH=$(pwd)/build/bin:$PATH
export FABRIC_CFG_PATH=$(pwd)/sampleconfig
ORDERER_GENERAL_GENESISPROFILE=SampleDevModeSolo orderer >> log_orderer.log 2>&1 &
三、在DevMode中启动对等
打开另一个终端窗口(不开也没事),并设置所需的环境变量以覆盖对等配置并启动对等节点。以该--peer-chaincodedev=true标志启动对等方会使对等方进入DevMode。(遇上了端口冲突,不知道什么毛病,修改了一下端口)
export PATH=$(pwd)/build/bin:$PATH
export FABRIC_CFG_PATH=$(pwd)/sampleconfig
FABRIC_LOGGING_SPEC=chaincode=debug CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 peer node start --peer-chaincodedev=true >> log_peer.log 2>&1 &
**提醒:**在中运行时DevMode,无法启用TLS。
四、创建频道并加入peer
打开另一个终端窗口,然后运行以下命令以使用该configtxgen工具生成通道创建事务。此命令ch1使用SampleSingleMSPChannel配置文件创建频道:
export PATH=$(pwd)/build/bin:$PATH
export FABRIC_CFG_PATH=$(pwd)/sampleconfig
configtxgen -channelID ch1 -outputCreateChannelTx ch1.tx -profile SampleSingleMSPChannel -configPath $FABRIC_CFG_PATH
peer channel create -o 127.0.0.1:7050 -c ch1 -f ch1.tx
成功后,您应该会看到类似以下结果:
2020-09-14 17:42:56.931 EDT [cli.common] readBlock -> INFO 002 Received block: 0
现在,通过运行以下命令将对等方加入通道:
peer channel join -b ch1.block
成功后,您应该看到类似于以下内容的结果:
2020-09-14 17:43:34.976 EDT [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
同行现在已加入频道ch1。
五、建立链码
我们使用目录中的简单链码fabric/integration/chaincode来演示如何在DevMode中运行链码包。在与上一步相同的终端窗口中,运行以下命令来构建链码:
go build -o simpleChaincode ./integration/chaincode/simple/cmd
六、启动链码
当DevMode对端已启用,CORE_CHAINCODE_ID_NAME环境变量必须设置为<CHAINCODE_NAME>:<CHAINCODE_VERSION>否则,对方是无法找到chaincode。在此示例中,我们将其设置为mycc:1.0。运行以下命令以启动链码并将其连接到对等方:(不知道为啥一直在运行,窗口没有关闭,所以我又开了另一个窗口)
CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_TLS_ENABLED=false CORE_CHAINCODE_ID_NAME=mycc:1.0 ./simpleChaincode -peer.address 127.0.0.1:7052
因为我们是在启动对等节点时在其上设置调试日志的,所以您可以确认链码注册成功。在对等日志中,您应该看到类似于以下内容的结果:(在第二个窗口其实能看到)
2020-09-14 17:53:43.413 EDT [chaincode] sendReady -> DEBU 045 Changed to state ready for chaincode mycc:1.0
七、批准并提交链码定义
现在,您需要运行以下Fabric链码生命周期命令来批准并将链码定义提交给通道:(另开了一个窗口)
export PATH=$(pwd)/build/bin:$PATH
export FABRIC_CFG_PATH=$(pwd)/sampleconfig
#批准链码
peer lifecycle chaincode approveformyorg -o 127.0.0.1:7050 --channelID ch1 --name mycc --version 1.0 --sequence 1 --init-required --signature-policy "OR ('SampleOrg.member')" --package-id mycc:1.0
#确认批准
peer lifecycle chaincode checkcommitreadiness -o 127.0.0.1:7050 --channelID ch1 --name mycc --version 1.0 --sequence 1 --init-required --signature-policy "OR ('SampleOrg.member')"
#提交链码
peer lifecycle chaincode commit -o 127.0.0.1:7050 --channelID ch1 --name mycc --version 1.0 --sequence 1 --init-required --signature-policy "OR ('SampleOrg.member')" --peerAddresses 127.0.0.1:7051
您应该看到类似于以下内容的结果:
2020-09-14 17:56:30.820 EDT [chaincodeCmd] ClientWait -> INFO 001 txid [f22b3c25dfea7fe0b28af9ee818056db81e29a9421c83fe00eb22fa41d1d1e21] committed with status (VALID) at
Chaincode definition for chaincode 'mycc', version '1.0', sequence '1' on channel 'ch1' approval status by org:
SampleOrg: true
2020-09-14 17:57:43.295 EDT [chaincodeCmd] ClientWait -> INFO 001 txid [fb803e8b0b4eae6b3a9ed35668f223753e1a34ffd2a7042f9e5bb516a383eb32] committed with status (VALID) at 127.0.0.1:7051
八、下一步
您可以根据需要发出CLI命令来调用和查询链码,以验证您的智能合约逻辑。对于此示例,我们发出三个命令。第一个初始化智能合约,第二个命令10从资产移动a到资产b。最后一条命令查询值,a以验证它已成功从更改100为90。
CORE_PEER_ADDRESS=127.0.0.1:7051 peer chaincode invoke -o 127.0.0.1:7050 -C ch1 -n mycc -c '{"Args":["init","a","100","b","200"]}' --isInit
CORE_PEER_ADDRESS=127.0.0.1:7051 peer chaincode invoke -o 127.0.0.1:7050 -C ch1 -n mycc -c '{"Args":["invoke","a","b","10"]}'
CORE_PEER_ADDRESS=127.0.0.1:7051 peer chaincode invoke -o 127.0.0.1:7050 -C ch1 -n mycc -c '{"Args":["query","a"]}'
您应该看到类似于以下内容的结果:
2020-09-14 18:15:00.034 EDT [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
2020-09-14 18:16:29.704 EDT [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
2020-09-14 18:17:42.101 EDT [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"90"
在DevMode中运行对等方的好处是,您现在可以迭代地对智能合约进行更新,保存更改,构建链码,然后使用上述步骤重新启动它。您无需每次更改都运行对等生命周期命令来更新链码。
java开发链码试验性质
二、搭建开发环境
1、启动网络
导航到存储库test-network本地克隆中的子目录 fabric-samples。
cd fabric-samples/test-network
如果您已经在运行测试网络,请将其关闭以确保环境干净。
./network.sh down
使用network.shshell脚本启动Fabric测试网络。
./network.sh up createChannel -c mychannel -ca
2、部署链码
./network.sh deployCC -ccn fabcar -ccp ../chaincode/fabcar/java/ -ccl java
3、环境变量配置
#fabric
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
# Environment variavles for Org1
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=$PWD/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_ROOTCERT_FILE=/root/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
4、调用链码
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 fabcar --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":"initLedger","Args":[]}'
peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
java开发第一个
一、链码编写
抄袭fabcar的编写,写了个ticket,其实就是把属性值换了一下
从idea拷贝过去,然后要给权限
chmod +x gradlew
二、搭建开发环境
1、启动网络
导航到存储库test-network本地克隆中的子目录 fabric-samples。
cd fabric-samples/test-network
如果您已经在运行测试网络,请将其关闭以确保环境干净。
./network.sh down
使用network.shshell脚本启动Fabric测试网络。
./network.sh up createChannel -c mychannel -ca
2、部署链码
export CHAINCODE_NAME=ticket
./network.sh deployCC -ccn $CHAINCODE_NAME -ccp /root/hyperledger/contract/java/ticket -ccl java
3、环境变量配置
#fabric
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
# Environment variavles for Org1
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=$PWD/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_ROOTCERT_FILE=/root/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
4、调用链码
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 $CHAINCODE_NAME --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":"initLedger","Args":[]}'
peer chaincode query -C mychannel -n $CHAINCODE_NAME -c '{"Args":["queryAllTickets"]}'
ERC-20 token 学习
1、启动网络
导航到存储库test-network本地克隆中的子目录 fabric-samples。
cd fabric-samples/test-network
如果您已经在运行测试网络,请将其关闭以确保环境干净。
./network.sh down
使用network.shshell脚本启动Fabric测试网络。
./network.sh up createChannel -ca
2、部署链码
export CHAINCODE_NAME=token_erc20
./network.sh deployCC -ccn $CHAINCODE_NAME -ccp ../token-erc-20/chaincode-javascript/ -ccl javascript
./network.sh deployCC -ccn token -ccp ../commercial-paper/chaincode-token/ -ccl javascript
./network.sh deployCC -ccn ticket -ccp ../commercial-paper/chaincode-ticket/ -ccl javascript
./network.sh deployCC -ccn $CHAINCODE_NAME -ccp ../token-erc-20/chaincode-go/ -ccl go
3、注册身份
智能合约支持来自渠道成员组织的各个客户身份拥有的帐户。在我们的方案中,代币的铸造者将是Org1的成员,而接收者将属于Org2。为了突出显示GetClientIdentity().GetID()API和用户证书中信息之间的联系,我们将使用Org1和Org2证书颁发机构(CA)注册两个新的身份,然后使用CA生成每个身份的证书和私钥。
3.1 Org1
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
我们一直在使用的终端将代表Org1。我们将使用Org1 CA创建铸造者身份。将Fabric CA客户端设置为Org1 CA管理员的MSP(此身份由测试网络脚本生成):
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/peerOrganizations/org1.example.com/
您可以使用以下fabric-ca-client工具注册新的Minter客户身份:
fabric-ca-client register --caname ca-org1 --id.name minter --id.secret minterpw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem"
现在,您可以通过将铸币者的注册名称和密码提供给enroll命令来生成身份证书和MSP文件夹:
fabric-ca-client enroll -u https://minter:minterpw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/users/minter@org1.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem"
运行以下命令以将节点OU配置文件复制到minter身份MSP文件夹中。
cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org1.example.com/users/minter@org1.example.com/msp/config.yaml"
3.2 Org2
打开一个代表Org2的新终端,然后导航到fabric-samples / test-network。我们将使用Org2 CA创建Org2收件人身份。将Fabric CA客户端设置为Org2 CA管理员的MSP:
cd fabric-samples/test-network
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/peerOrganizations/org2.example.com/
您可以使用以下fabric-ca-client工具注册收件人客户端身份:
fabric-ca-client register --caname ca-org2 --id.name recipient --id.secret recipientpw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org2/tls-cert.pem"
现在,我们可以注册以生成收件人的身份证书和MSP文件夹:
fabric-ca-client enroll -u https://recipient:recipientpw@localhost:8054 --caname ca-org2 -M "${PWD}/organizations/peerOrganizations/org2.example.com/users/recipient@org2.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org2/tls-cert.pem"
运行以下命令,将节点OU配置文件复制到收件人身份MSP文件夹中。
cp "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org2.example.com/users/recipient@org2.example.com/msp/config.yaml"
4、铸造一些代币
现在我们已经创建了铸造者的身份,我们可以调用智能合约铸造一些代币。返回Org1终端,我们将设置以下环境变量以将peerCLI作为Org1中的标记身份进行操作。
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/minter@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
export TARGET_TLS_OPTIONS=(-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" --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")
上面的最后一个环境变量将在CLI调用命令中使用,以设置要认可的目标对等方以及目标订购服务端点和TLS选项。
然后,我们可以调用智能合约以铸造5000个代币:
(这个@也可以改成*,表示这个数组内的所有元素)
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"Mint","Args":["5000"]}'
造币厂功能验证客户是造币厂组织的成员,然后将5000个代币记入造币厂客户的帐户。我们可以通过调用该ClientAccountBalance功能来检查铸造者客户的帐户余额。
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"ClientAccountBalance","Args":[]}'
该函数查询与铸币者客户端ID关联的帐户余额,并返回:
5000
5、转移代币
在Org2的终端下操作
铸造者打算将100个代币转移给Org2接收者,但首先Org2接收者需要提供自己的帐户ID作为付款地址。客户可以从其自己的公共证书中获取其帐户ID,但为确保该帐户ID正确,合同具有ClientAccountID实用程序功能,可以简单地查看呼叫者证书并返回主叫客户的ID,该ID将用作帐户ID。让我们通过为Org2接收者用户设置环境变量来准备Org2终端。
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/recipient@org2.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:9051
使用Org2终端,Org2收件人用户可以检索自己的帐户ID:
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"ClientAccountID","Args":[]}'
对于Go合约:
该函数返回收件人的帐户ID:
eDUwOTo6Q049cmVjaXBpZW50LE9VPWNsaWVudCxPPUh5cGVybGVkZ2VyLFNUPU5vcnRoIENhcm9saW5hLEM9VVM6OkNOPWNhLm9yZzIuZXhhbXBsZS5jb20sTz1vcmcyLmV4YW1wbGUuY29tLEw9SHVyc2xleSxTVD1IYW1wc2hpcmUsQz1VSw==
让base64解码帐户ID以确保它代表Org2收件人用户:
echo eDUwOTo6Q049cmVjaXBpZW50LE9VPWNsaWVudCxPPUh5cGVybGVkZ2VyLFNUPU5vcnRoIENhcm9saW5hLEM9VVM6OkNOPWNhLm9yZzIuZXhhbXBsZS5jb20sTz1vcmcyLmV4YW1wbGUuY29tLEw9SHVyc2xleSxTVD1IYW1wc2hpcmUsQz1VSw== | base64 --decode
结果表明,主题和颁发者确实是Org2的收件人用户:
x509::CN=recipient,OU=client,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org2.example.com,O=org2.example.com,L=Hursley,ST=Hampshire,C=UK
对于JavaScript合同:
该函数返回收件人的客户ID。结果表明,主题和颁发者确实是Org2的收件人用户:
x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=recipient::/C=UK/ST=Hampshire/L=Hursley/O=org2.example.com/CN=ca.org2.example.com
在Org2收件人向铸造者提供其帐户ID之后,铸造者可以启动从其帐户到接收者帐户的转移。
返回到Org1终端,请求将100个代币转移到接收者帐户:
对于Go合约:
export RECIPIENT="eDUwOTo6Q049cmVjaXBpZW50LE9VPWNsaWVudCxPPUh5cGVybGVkZ2VyLFNUPU5vcnRoIENhcm9saW5hLEM9VVM6OkNOPWNhLm9yZzIuZXhhbXBsZS5jb20sTz1vcmcyLmV4YW1wbGUuY29tLEw9SHVyc2xleSxTVD1IYW1wc2hpcmUsQz1VSw=="
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"Transfer","Args":[ "'"$RECIPIENT"'","100"]}'
对于JavaScript合同:
export RECIPIENT="x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=recipient::/C=UK/ST=Hampshire/L=Hursley/O=org2.example.com/CN=ca.org2.example.com"
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"Transfer","Args":[ "'"$RECIPIENT"'","100"]}'
该Transfer功能验证与主叫客户ID相关联的帐户是否有足够的资金用于转账。然后,它将从呼叫者的帐户中扣款,并在接收者的帐户中贷记。请注意,示例合同将为收款人自动创建一个余额为零的帐户(如果尚不存在)。
仍在Org1终端中时,让我们再次请求铸造者的帐户余额:
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"ClientAccountBalance","Args":[]}'
该函数查询与铸币者客户端ID关联的帐户余额,并返回:
4900
然后使用Org2终端,要求接收者的余额:
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"ClientAccountBalance","Args":[]}'
该函数查询与收件人客户端ID关联的帐户余额,并返回:
100
恭喜,您已转移了100个代币!现在,Org2收件人可以以相同方式将代币转移给其他注册用户。
6、第三方转帐(TransferFrom)
该示例还有另一种称为的ERC-20转移方法TransferFrom,该方法允许批准的第三方支出者代表帐户所有者转移可替代的代币。此业务情景演示了如何批准支出者和转移可替代代币。
在这种情况下,您将批准支出者并按以下方式转移代币:
- 铸币商已经根据上述情况创建了代币。
- 相同的铸造者客户端使用该
Approve功能来设置花费者客户端可以代表铸造者转移的代币配额。假定花费者已经将他们的客户ID提供给了Approve呼叫者带外。 - 然后,消费者客户端将使用该
TransferFrom功能代表铸币者将请求数量的代币转移到接收者的帐户中。假定接收者已经将他们的客户ID提供给了TransferFrom呼叫者带外。
1、注册第三方消费者的身份
您已经建立了网络,并将智能合约部署到了渠道。我们将使用相同的网络和智能合约。
我们将使用Org1 CA创建支出者身份。回到Org1终端,您可以使用以下fabric-ca-client工具注册新的客户帐户身份:
fabric-ca-client register --caname ca-org1 --id.name spender --id.secret spenderpw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem"
现在,您可以通过将花费者的注册名称和秘密提供给enroll命令来生成身份证书和MSP文件夹:
fabric-ca-client enroll -u https://spender:spenderpw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/users/spender@org1.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem"
运行以下命令以将节点OU配置文件复制到支出者身份MSP文件夹中。
cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org1.example.com/users/spender@org1.example.com/msp/config.yaml"
2、批准支出者
造币商打算批准要由支出者转让的500个代币,但是首先,支出者需要提供自己的客户ID作为付款地址。
打开第三个终端
以代表Org1中的支出者,然后导航到fabric-samples / test-network。为Org1支出者用户设置环境变量。
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/spender@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
export TARGET_TLS_OPTIONS=(-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" --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")
现在,Org1支出者可以检索自己的客户ID:
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"ClientAccountID","Args":[]}'
对于Go合约:
该函数返回支出者的帐户ID:
eDUwOTo6Q049c3BlbmRlcixPVT1jbGllbnQsTz1IeXBlcmxlZGdlcixTVD1Ob3J0aCBDYXJvbGluYSxDPVVTOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT
对于JavaScript合同:
该函数返回支出者的客户ID。结果表明,主题和颁发者确实是Org2的收件人用户:
x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=spender::/C=US/ST=North Carolina/L=Durham/O=org1.example.com/CN=ca.org1.example.com
在Org1支出者将其客户ID提供给铸币商之后,铸币者可以批准支出者。
回到Org1造币厂终端,请求批准500个代币,以由支出者撤回。
对于Go合约:
export SPENDER="eDUwOTo6Q049c3BlbmRlcixPVT1jbGllbnQsTz1IeXBlcmxlZGdlcixTVD1Ob3J0aCBDYXJvbGluYSxDPVVTOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT"
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"Approve","Args":[ "'"$SPENDER"'","500"]}'
对于JavaScript合同:
export SPENDER="x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=spender::/C=US/ST=North Carolina/L=Durham/O=org1.example.com/CN=ca.org1.example.com"
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"Approve","Args":["'"$SPENDER"'", "500"]}'
批准功能指定支出者客户端可以代表铸造者转移500个代币。我们可以通过调用该allowance功能从铸币厂检查支出者客户的补贴。
让我们从Org1造币厂终端请求支出者的补贴。
对于Go合约:
export MINTER="eDUwOTo6Q049bWludGVyLE9VPWNsaWVudCxPPUh5cGVybGVkZ2VyLFNUPU5vcnRoIENhcm9saW5hLEM9VVM6OkNOPWNhLm9yZzEuZXhhbXBsZS5jb20sTz1vcmcxLmV4YW1wbGUuY29tLEw9RHVyaGFtLFNUPU5vcnRoIENhcm9saW5hLEM9VVM="
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"Allowance","Args":["'"$MINTER"'", "'"$SPENDER"'"]}'
对于JavaScript合同:
export MINTER="x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=minter::/C=US/ST=North Carolina/L=Durham/O=org1.example.com/CN=ca.org1.example.com"
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"Allowance","Args":["'"$MINTER"'", "'"$SPENDER"'"]}'
该函数查询与支出者客户ID相关联的配额,并返回:
500
3、TransferFrom代币
支出者打算代表铸币者将100个代币转移给Org2接收者。支出者已经获得了铸造者客户ID和接收者客户ID。
返回第三个终端,请求将100个代币转移到接收者帐户。
对于Go合约:
export MINTER="eDUwOTo6Q049bWludGVyLE9VPWNsaWVudCxPPUh5cGVybGVkZ2VyLFNUPU5vcnRoIENhcm9saW5hLEM9VVM6OkNOPWNhLm9yZzEuZXhhbXBsZS5jb20sTz1vcmcxLmV4YW1wbGUuY29tLEw9RHVyaGFtLFNUPU5vcnRoIENhcm9saW5hLEM9VVM="
export RECIPIENT="eDUwOTo6Q049cmVjaXBpZW50LE9VPWNsaWVudCxPPUh5cGVybGVkZ2VyLFNUPU5vcnRoIENhcm9saW5hLEM9VVM6OkNOPWNhLm9yZzIuZXhhbXBsZS5jb20sTz1vcmcyLmV4YW1wbGUuY29tLEw9SHVyc2xleSxTVD1IYW1wc2hpcmUsQz1VSw=="
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"TransferFrom","Args":[ "'"$MINTER"'", "'"$RECIPIENT"'", "100"]}'
对于JavaScript合同:
export MINTER="x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=minter::/C=US/ST=North Carolina/L=Durham/O=org1.example.com/CN=ca.org1.example.com"
export RECIPIENT="x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=recipient::/C=UK/ST=Hampshire/L=Hursley/O=org2.example.com/CN=ca.org2.example.com"
peer chaincode invoke "${TARGET_TLS_OPTIONS[@]}" -C mychannel -n token_erc20 -c '{"function":"TransferFrom","Args":[ "'"$MINTER"'", "'"$RECIPIENT"'", "100"]}'
该TransferFrom函数具有三个参数:发件人,收件人,金额。该功能验证与发件人关联的帐户是否有足够的资金来进行转帐。该功能还验证与主叫客户ID相关的配额是否超过要转账的资金。然后,它将从发件人的帐户中扣除并在收款人的帐户中贷记。这也将减少铸币商批准的支出者补贴。请注意,示例合同将为收款人自动创建一个余额为零的帐户(如果尚不存在)。
在仍处于支出者的第三个终端时,让我们再次请求铸造者的帐户余额:
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"BalanceOf","Args":["'"$MINTER"'"]}'
该函数查询与铸币者客户端ID关联的帐户余额,并返回:
4800
在仍处于支出者的第三个终端时,让我们再次向铸造者请求支出者的津贴。
对于Go合约:
export SPENDER="eDUwOTo6Q049c3BlbmRlcixPVT1jbGllbnQsTz1IeXBlcmxlZGdlcixTVD1Ob3J0aCBDYXJvbGluYSxDPVVTOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT"
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"Allowance","Args":["'"$MINTER"'", "'"$SPENDER"'"]}'
对于JavaScript合同:
export SPENDER="x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=spender::/C=US/ST=North Carolina/L=Durham/O=org1.example.com/CN=ca.org1.example.com"
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"Allowance","Args":["'"$MINTER"'", "'"$SPENDER"'"]}'
该函数查询与支出者客户ID相关联的配额,并返回:
400
然后使用Org2终端,要求接收者的余额:
peer chaincode query -C mychannel -n token_erc20 -c '{"function":"ClientAccountBalance","Args":[]}'
该函数查询与收件人客户端ID关联的帐户余额,并返回:
200
恭喜,您已转移了100个代币!现在,Org2收件人可以以相同方式将代币转移给其他注册用户。
7、清理
完成后,您可以关闭测试网络。该命令将删除测试网络的所有节点,并删除您创建的所有分类帐数据:
./network.sh down
合同延期的想法
您可以扩展基本的基于ERC-20帐户的代币示例,以满足其他要求。例如:
- 您可以将认可策略设置为代表合同执行的信任锚的组织子集,而不是使用默认的“多数”认可策略。
- 您还可能要求帐户在使用之前进行设置,并对每个已创建的帐户密钥应用基于状态的背书。例如,在Org1帐户上,将基于州的背书策略设置为Org1和中央银行(或其他一些信任锚)。并在Org2帐户上,将基于州的背书策略设置为Org2和中央银行(或其他一些信任锚)。然后,要将代币从Org1帐户转移到Org2帐户,您需要获得Org1,Org2和中央银行(或某些其他信任锚)的认可。
- 您可以为基于私钥-公钥对的帐户使用匿名地址,而不是由客户端ID键入密钥的帐户。为了花费代币,客户将必须在转移输入上签名以证明他们拥有地址私钥,然后合同将对其进行验证,类似于无许可区块链空间中的以太坊模型。但是,在诸如Fabric之类的许可区块链中,只有注册的客户才有权参与。此外,如果您不想泄漏与每个帐户关联的已注册客户端身份,则可以使用Identity Mixer MSP来注册客户端,以便在每个代币交易中客户端本身也是匿名的。





