陆羽协议5-使用docker配置fabric同构跨链

1,两台centos虚拟机

ip分别为172.16.162.133、172.16.162.134,下文标注101表示在133机器上执行,标注102表示在134机器上执行

2,启动fabric网络,配置fabric-ly证书
2.1 两台机器都启动fabric网络
./byfn.sh up -i 1.4.4
2.2 使用cryptogen工具生成跨链所需用户证书

本例中取用户名为luyutest:

cryptogen extendly 
--input=/Users/ch/Downloads/testfle/crypto-config-1 
--input=/Users/ch/Downloads/testfle/crypto-config-2 
--config=/Users/ch/Downloads/testfle/crypto-config-1.yaml 
--config=/Users/ch/Downloads/testfle/crypto-config-2.yaml
# extendly子命令是为了跨链场景中给同一个私钥所属用户在不同的机构下颁发证书的工具
# extendly子命令可以接受多个input和多个config参数,需要几个跨链组织就可以配几个。
# 每个input和每个config参数要一一对应,表示使用crypto-config-1.yaml配置继承的证书及生成证书的路径是crypto-config-1

生成证书的路径:

$GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/signcerts/luyutest@org1.example.com-cert.pem
3,router镜像

任一机器执行,打包后导出导入

cd /root/java/
git clone https://gitee.com/luyu-community/router.git
cd /root/java/router
vi Dockerfile
FROM centos
RUN mkdir /usr/local/java
ADD jdk-11.0.13_linux-x64_bin.tar.gz /usr/local/java
#ADD ./dist /root/java/router/dist
WORKDIR /root/java/router/dist
ENV JAVA_HOME /usr/local/java/jdk-11.0.13
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 8250
EXPOSE 25500
CMD sh /root/java/router/dist/routers/start_all.sh  && tail -f /root/java/router/dist/routers/127.0.0.1-8250-25500/logs/info.log
docker build . -t router:0.0.1
4,account-manager镜像
cd /root/java/
git clone https://gitee.com/luyu-community/account-manager.git
cd /root/java/account-manager
vi Dockerfile
FROM centos
RUN mkdir /usr/local/java
ADD jdk-11.0.13_linux-x64_bin.tar.gz /usr/local/java
#ADD ./dist /root/java/account-manager/dist
WORKDIR /root/java/account-manager/dist
ENV JAVA_HOME /usr/local/java/jdk-11.0.13
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 8340
CMD sh /root/java/account-manager/dist/start.sh && tail -f /root/java/account-manager/dist/start.out
docker build . -t account-manager:0.0.1

导出导入:

docker save -o router:0.0.1.tar router:0.0.1
docker save -o account-manager:0.0.1.tar account-manager:0.0.1
docker load -i account-manager\:0.0.1.tar
docker load -i router\:0.0.1.tar
5,编译fabric插件(101&102)
cd /root/java/
git clone https://gitee.com/luyu-community/fabric-plugin.git
cd fabric-plugin
gradle assemble

/root/java/fabric-plugin/dist/apps目录下生成fabric1-stub-2.0.0-rc2.jar

6,配置router
6.1 编译router(101&102)
cd /root/java/router/
gradle assemble
6.2 生成router本地证书(101)
cd /root/java/router/dist
sh build_router.sh -n payment1 -l 127.0.0.1:8250:25500

生成的router目录默认位于routers目录下

tree -L 1 routers/
routers/
├── 127.0.0.1-8250-25500 # 路由8250
├── cert # 证书目录
├── start_all.sh
└── stop_all.sh

account-managersdk所需的证书位于cert目录下(后面会用到)

tree -L 1 routers/cert/
routers/cert/
├── account-manager # account-manager 所需证书
├── ca.crt # 根证书
├── ca.key # 根证书私钥
├── ca.srl
├── cert.cnf
├── create_cert.sh # 生成证书的脚本,可用此脚本基于本目录的ca继续生成更多的证书
├── node0 # 路由8250 证书(已自动配置)
└── sdk # sdk 所需证书,按需拷贝
6.3 生成102router所需证书

使用同一个根证书生成证书,并发送至102

cd /root/java/router/dist
sh  build_router.sh -n payment2 -l 127.0.0.1:8250:25500 -o config-102 -c routers/cert/
scp -r config-102 root@172.16.164.134:/root/java/router/dist/routers
6.4 fabric插件(101&102)

把编译fabric插件放置于router的plugins目录下

cp /root/java/fabric-plugin/dist/apps/fabric1-stub-2.0.0-rc2.jar /root/java/router/dist/routers/127.0.0.1-8250-25500/plugin/
6.5 编辑配置本地fabric接入参数

101

mkdir -p /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101

cd /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101
vi plugin.toml
[common]
    name = 'fabric101'
    type = 'Fabric1.4'
vi connection.toml
[fabricServices]
    channelName = 'mychannel'
    orgUserName = 'fabric_admin'
    ordererTlsCaFile = 'orderer-tlsca.crt'
    ordererAddress = 'grpcs://orderer.example.com:7050'

[orgs]
    [orgs.Org1]
        tlsCaFile = 'org1-tlsca.crt'
        adminName = 'fabric_admin_org1' # 配置方式与fabric_admin相同
        endorsers = ['grpcs://peer0.org1.example.com:7051']

    [orgs.Org2]
        tlsCaFile = 'org2-tlsca.crt'
        adminName = 'fabric_admin_org2' # 配置方式与fabric_admin相同,但account.toml 中的mspid为Org2MSP
        endorsers = ['grpcs://peer0.org2.example.com:9051']

102

mkdir -p /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102

cd /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102
vi plugin.toml
[common]
    name = 'fabric102'
    type = 'Fabric1.4'
vi connection.toml
[fabricServices]
    channelName = 'mychannel'
    orgUserName = 'fabric_admin'
    ordererTlsCaFile = 'orderer-tlsca.crt'
    ordererAddress = 'grpcs://orderer.example.com:7050'

[orgs]
    [orgs.Org1]
        tlsCaFile = 'org1-tlsca.crt'
        adminName = 'fabric_admin_org1' # 配置方式与fabric_admin相同
        endorsers = ['grpcs://peer0.org1.example.com:7051']

    [orgs.Org2]
        tlsCaFile = 'org2-tlsca.crt'
        adminName = 'fabric_admin_org2' # 配置方式与fabric_admin相同,但account.toml 中的mspid为Org2MSP
        endorsers = ['grpcs://peer0.org2.example.com:9051']
6.6 指定fabric账户证书路径(101&102)

为了适应不同的背书策略,要每个组织都配置账户

cd /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/
mkdir fabric_admin fabric_admin_org1 fabric_admin_org2
vi fabric_admin/account.toml
[account]
    type = 'Fabric1.4'
    mspid = 'Org1MSP' 
    keystore = 'account.key'
    signcert = 'account.crt'
vi fabric_admin_org1/account.toml
[account]
    type = 'Fabric1.4'
    mspid = 'Org1MSP' 
    keystore = 'account.key'
    signcert = 'account.crt'
vi fabric_admin_org2/account.toml
[account]
    type = 'Fabric1.4'
    mspid = 'Org2MSP'  # 此处不同
    keystore = 'account.key'
    signcert = 'account.crt'
6.7 拷贝证书到配置路径下

101:

连接排序节点的根证书

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101/orderer-tlsca.crt

连接org1的背书节点的根证书

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101/org1-tlsca.crt

连接org2的背书节点的根证书

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101/org2-tlsca.crt 

org1账户证书

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/signcerts/luyutest@org1.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin/account.crt

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/signcerts/luyutest@org1.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org1/account.crt

org1账户私钥

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/keystore/*_sk  /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin/account.key
    
cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/keystore/*_sk  /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org1/account.key

org2账户证书

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org2/account.crt

org2账户私钥

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/*_sk /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org2/account.key

102:

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102/orderer-tlsca.crt

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102/org1-tlsca.crt

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102/org2-tlsca.crt 

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/signcerts/luyutest@org1.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin/account.crt

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/signcerts/luyutest@org1.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org1/account.crt

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/keystore/*_sk  /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin/account.key

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/luyutest@org1.example.com/msp/keystore/*_sk  /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org1/account.key

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/users/luyutest@org2.example.com/msp/signcerts/luyutest@org2.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org2/account.crt

cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/*_sk /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/fabric_admin_org2/account.key

完成后的目录结构:

tree -L 2 /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/accounts/
/root/java/router/dist/routers/127.0.0.1-8251-25501/conf/accounts/
├── fabric_admin
│   ├── account.crt
│   ├── account.key
│   └── account.toml
├── fabric_admin_org1
│   ├── account.crt
│   ├── account.key
│   └── account.toml
└── fabric_admin_org2
    ├── account.crt
    ├── account.key
    └── account.toml
tree /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102 -L 2
/root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102
├── connection.toml
├── orderer-tlsca.crt
├── org1-tlsca.crt
├── org2-tlsca.crt
└── plugin.toml
6.8 配置101连接102(101)
cd /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains 
mkdir fabric102 && cd fabric102
vi plugin.toml
[common]
    name = 'fabric102'
    type = 'Fabric1.4'
vi driver.toml
[verifier]
     [verifier.endorserCA] # 机构的CA列表
            Org1MSP = 'verifier/org1CA/ca.org1.example.com-cert.pem' # 相对路径:验证证书所在位置的
            Org2MSP = 'verifier/org2CA/ca.org2.example.com-cert.pem'
     [verifier.ordererCA] # 排序节点的CA证书
            OrdererMSP = 'verifier/ordererCA/ca.example.com-cert.pem'
mkdir verifier && cd verifier
mkdir ordererCA org1CA org2CA
scp root@172.16.164.134:/root/go/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/ca/ca.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102/verifier/ordererCA/

scp root@172.16.164.134:/root/go/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102/verifier/org1CA/

scp root@172.16.164.134:/root/go/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric102/verifier/org2CA/

修改router配置文件

vi /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/application.toml
      ...
      8 [rpc] # rpc ip & port
      9     address = '127.0.0.1' #允许访问本机8250的ip,改为0.0.0.0表示允许所有
     10     port = 8250
      ...
     18 [p2p]
      ...
     23     sslKey = 'classpath:ssl.key'
     24     peers = ['172.16.164.134:25500'] #连接router的ip端口
     25
     26 [account-manager]
     27     server =  'account-manager:8340' #改成镜像的名字
     28     sslKey = 'classpath:ssl.key'
     29     sslCert = 'classpath:ssl.crt'
     30     caCert = 'classpath:ca.crt'
     31     enableSignVerify = false #改为false表示不验签 
6.9 配置102连接101(102)
cd /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains
mkdir fabric101 && cd fabric101
vi plugin.toml
[common]
    name = 'fabric101'
    type = 'Fabric1.4'

vi driver.toml
[verifier]
     [verifier.endorserCA] # 机构的CA列表
            Org1MSP = 'verifier/org1CA/ca.org1.example.com-cert.pem' # 相对路径:验证证书所在位置的
            Org2MSP = 'verifier/org2CA/ca.org2.example.com-cert.pem'
     [verifier.ordererCA] # 排序节点的CA证书
            OrdererMSP = 'verifier/ordererCA/ca.example.com-cert.pem'
mkdir verifier && cd verifier
mkdir ordererCA org1CA org2CA
scp root@172.16.164.133:/root/go/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/ca/ca.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101/verifier/ordererCA/

scp root@172.16.164.133:/root/go/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101/verifier/org1CA/

scp root@172.16.164.133:/root/go/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/chains/fabric101/verifier/org2CA/
vi /root/java/router/dist/routers/127.0.0.1-8250-25500/conf/application.toml
  ...
  8 [rpc] # rpc ip & port
  9     address = '127.0.0.1' #允许访问本机8250的ip,改为0.0.0.0表示允许所有
 10     port = 8250
  ...
 18 [p2p]
  ...
 23     sslKey = 'classpath:ssl.key'
 24     peers = ['172.16.164.133:25500'] #连接router的ip端口
 25
 26 [account-manager]
 27     server =  'account-manager:8340' #改成镜像的名字
 28     sslKey = 'classpath:ssl.key'
 29     sslCert = 'classpath:ssl.crt'
 30     caCert = 'classpath:ca.crt'
 31     enableSignVerify = false #改为false表示不验签 
6.10 启动router容器

101&102:

docker run -d --network net_byfn -v /root/java/router/dist:/root/java/router/dist --name router -p 8250:8250 -p 25500:25500 router:0.0.1 

--network参数是指定加入的网络,该网络是fabric示例网络创建的

8250端口和25500端口均要映射出来

查看启动日志:

docker logs -f router

看到日志里两个fabric网络都纳入了router的管理

Current active chains: [chain=payment1.fabric101,blockNumber=4], [chain=payment2.fabric102,blockNumber=4]
7,配置account-manager
7.1 编译account-manager(101&102)
cd /root/java/account-manager/
gradle assemble
7.2 拷贝证书(101&102)

把router生成的证书拷贝到dist/conf目录下

cp /root/java/router/dist/routers/cert/account-manager/* /root/java/account-manager/dist/conf/
7.3 修改配置文件(101&102)

拷贝并修改配置文件

cd /root/java/account-manager/dist/
cp conf/application-sample.toml conf/application.toml

vim /root/java/account-manager/dist/conf/application.toml 
sslOn改为false

如果开启了ssl,则需要使用https的方式访问,先使用false,添加二级账户之后再设置成true

7.4 启动account-manager(101&102)
docker run -d --network net_byfn -v /root/java/account-manager/dist:/root/java/account-manager/dist --name account-manager -p 8340:8340 account-manager:0.0.1 
7.5 生成一级账户(101&102)

下载java-sdk,执行脚本生成一级账户私钥

cd /root/java/
git clone https://gitee.com/luyu-community/luyu-java-sdk.git
cd luyu-java-sdk/
gradle assemble
cd dist

生成一个一级账户地址

sh gen_account.sh 
[SUCCESS] Account secret key generated: 0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64.key 

向router发交易的时候,使用该私钥签名即可

101账户地址:0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64

102账户地址:0x274c618751cde87831a9c07e30f4d1a1fc7d0788

7.6 互相签名

问题已解决,详见2.2

7.7 生成加载二级账户报文

在配置了本插件的路由下执行命令(6.4步骤已配)

cd /root/java/router/dist/routers/127.0.0.1-8250-25500

101:

java -cp conf/:lib/*:plugin/* link.luyu.protocol.link.fabric1.tools.AddAlgAccountRequestPacketBuilder 0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64 payment1.fabric101 fabric_admin

102

java -cp conf/:lib/*:plugin/* link.luyu.protocol.link.fabric1.tools.AddAlgAccountRequestPacketBuilder 0x274c618751cde87831a9c07e30f4d1a1fc7d0788 payment2.fabric102 fabric_admin

参数1:sender,指定一级账户地址,即:用sdk的gen_account.sh生成的账户地址(0x开头的一串16进制字符串)
参数2:chain path,指定fabric链的链path,如:payment1.fabric101
参数3:account name,指定conf/account下的二级账户所在目录名,如:fabric_admin

得到组装好的json:

101

{
  "data" : {
    "luyuSign" : "",
    "type" : "ECDSA_SECP256R1_WITH_SHA256",
    "nonce" : 1641800592292,
    "identity" : "0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64",
    "pubKey" : "BCHZbJUbc9bPrIFaVdvr9tFKRNCvkvZDdXyZ7K4cugUHUkPA+wSSR9h85rTTK+qnthP2xTechBkR8/s2INXUwcA=",
    "secKey" : "AO81ostmGjavy4JAEObrpOVPfgCYRDoZBI3Xfff+++E7",
    "properties" : {
      "Fabric1.4:payment1.fabric101:cert" : "-----BEGIN CERTIFICATE-----\nMIICKTCCAc+gAwIBAgIQFbDE7H0O6F4KGOiO+wcUejAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0yMjAxMTAwMTUwMDBaFw0zMjAxMDgwMTUwMDBa\nMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ4wDAYDVQQLEwVhZG1pbjEfMB0GA1UEAwwWQWRtaW5Ab3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCHZbJUbc9bP\nrIFaVdvr9tFKRNCvkvZDdXyZ7K4cugUHUkPA+wSSR9h85rTTK+qnthP2xTechBkR\n8/s2INXUwcCjTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIMWWr0Q1IL/qseILf/Wo3dnFHPy3Q9Z2hDvBPfIbn3CUMAoGCCqGSM49\nBAMCA0gAMEUCIQD6JpcbGe9jpXAycGWHMZSUOGgNemEL7vWrBds2RpV+2AIgbtYk\nJ4w7pDJcmehXxIaW4oiFra0fp6a6b9mY8b6FMEw=\n-----END CERTIFICATE-----\n",
      "Fabric1.4:payment1.fabric101:name" : "fabric_admin",
      "Fabric1.4:payment1.fabric101:mspid" : "Org1MSP"
    },
    "isDefault" : true
  }
}

102:

{
  "data" : {
    "luyuSign" : "",
    "type" : "ECDSA_SECP256R1_WITH_SHA256",
    "nonce" : 1641800606644,
    "identity" : "0x274c618751cde87831a9c07e30f4d1a1fc7d0788",
    "pubKey" : "BNhgfr0BL6ahoVgpPsN6vtMi/EqfNv59DdDYp56LsuxaxAU9jiCYIg0jxtgD3qqcmB0MYipTxZgFKlsptci9LK8=",
    "secKey" : "AMns5PUl6divm3tKUZHB8uHDWKXSt17cBfjDYLTo1QU6",
    "properties" : {
      "Fabric1.4:payment2.fabric102:name" : "fabric_admin",
      "Fabric1.4:payment2.fabric102:mspid" : "Org1MSP",
      "Fabric1.4:payment2.fabric102:cert" : "-----BEGIN CERTIFICATE-----\nMIICKDCCAc+gAwIBAgIQUuw6tI7pT0UiVpcjve6H5DAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0yMjAxMTAwMTUwMDBaFw0zMjAxMDgwMTUwMDBa\nMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ4wDAYDVQQLEwVhZG1pbjEfMB0GA1UEAwwWQWRtaW5Ab3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNhgfr0BL6ah\noVgpPsN6vtMi/EqfNv59DdDYp56LsuxaxAU9jiCYIg0jxtgD3qqcmB0MYipTxZgF\nKlsptci9LK+jTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIAGsbgVlAMrLMRvi5+a9qx8EqLvfetMfmQjWK2rHxIdTMAoGCCqGSM49\nBAMCA0cAMEQCID3PSb0/im0Ev1AeuBUYGfEiHa243k5e2B6TSz0yV49nAiA217bD\nYLSNUgPvzQQAeBo554tJpcdEizI+02Ui6spttA==\n-----END CERTIFICATE-----\n"
    },
    "isDefault" : true
  }
}
7.8 报文拼接

把102的properties拼接到101:

{
  "data" : {
    "luyuSign" : "",
    "type" : "ECDSA_SECP256R1_WITH_SHA256",
    "nonce" : 1641800592292,
    "identity" : "0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64",
    "pubKey" : "BCHZbJUbc9bPrIFaVdvr9tFKRNCvkvZDdXyZ7K4cugUHUkPA+wSSR9h85rTTK+qnthP2xTechBkR8/s2INXUwcA=",
    "secKey" : "AO81ostmGjavy4JAEObrpOVPfgCYRDoZBI3Xfff+++E7",
    "properties" : {
      "Fabric1.4:payment1.fabric101:cert" : "-----BEGIN CERTIFICATE-----\nMIICKTCCAc+gAwIBAgIQFbDE7H0O6F4KGOiO+wcUejAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0yMjAxMTAwMTUwMDBaFw0zMjAxMDgwMTUwMDBa\nMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ4wDAYDVQQLEwVhZG1pbjEfMB0GA1UEAwwWQWRtaW5Ab3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCHZbJUbc9bP\nrIFaVdvr9tFKRNCvkvZDdXyZ7K4cugUHUkPA+wSSR9h85rTTK+qnthP2xTechBkR\n8/s2INXUwcCjTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIMWWr0Q1IL/qseILf/Wo3dnFHPy3Q9Z2hDvBPfIbn3CUMAoGCCqGSM49\nBAMCA0gAMEUCIQD6JpcbGe9jpXAycGWHMZSUOGgNemEL7vWrBds2RpV+2AIgbtYk\nJ4w7pDJcmehXxIaW4oiFra0fp6a6b9mY8b6FMEw=\n-----END CERTIFICATE-----\n",
      "Fabric1.4:payment1.fabric101:name" : "fabric_admin",
      "Fabric1.4:payment1.fabric101:mspid" : "Org1MSP",
      
      "Fabric1.4:payment2.fabric102:name" : "fabric_admin",
      "Fabric1.4:payment2.fabric102:mspid" : "Org1MSP",
      "Fabric1.4:payment2.fabric102:cert" : "-----BEGIN CERTIFICATE-----\nMIICKDCCAc+gAwIBAgIQUuw6tI7pT0UiVpcjve6H5DAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0yMjAxMTAwMTUwMDBaFw0zMjAxMDgwMTUwMDBa\nMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ4wDAYDVQQLEwVhZG1pbjEfMB0GA1UEAwwWQWRtaW5Ab3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNhgfr0BL6ah\noVgpPsN6vtMi/EqfNv59DdDYp56LsuxaxAU9jiCYIg0jxtgD3qqcmB0MYipTxZgF\nKlsptci9LK+jTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIAGsbgVlAMrLMRvi5+a9qx8EqLvfetMfmQjWK2rHxIdTMAoGCCqGSM49\nBAMCA0cAMEQCID3PSb0/im0Ev1AeuBUYGfEiHa243k5e2B6TSz0yV49nAiA217bD\nYLSNUgPvzQQAeBo554tJpcdEizI+02Ui6spttA==\n-----END CERTIFICATE-----\n"
    },
    "isDefault" : true
  }
}

把101的properties拼接到102:

{
  "data" : {
    "luyuSign" : "",
    "type" : "ECDSA_SECP256R1_WITH_SHA256",
    "nonce" : 1641800606644,
    "identity" : "0x274c618751cde87831a9c07e30f4d1a1fc7d0788",
    "pubKey" : "BNhgfr0BL6ahoVgpPsN6vtMi/EqfNv59DdDYp56LsuxaxAU9jiCYIg0jxtgD3qqcmB0MYipTxZgFKlsptci9LK8=",
    "secKey" : "AMns5PUl6divm3tKUZHB8uHDWKXSt17cBfjDYLTo1QU6",
    "properties" : {
      "Fabric1.4:payment2.fabric102:name" : "fabric_admin",
      "Fabric1.4:payment2.fabric102:mspid" : "Org1MSP",
      "Fabric1.4:payment2.fabric102:cert" : "-----BEGIN CERTIFICATE-----\nMIICKDCCAc+gAwIBAgIQUuw6tI7pT0UiVpcjve6H5DAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0yMjAxMTAwMTUwMDBaFw0zMjAxMDgwMTUwMDBa\nMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ4wDAYDVQQLEwVhZG1pbjEfMB0GA1UEAwwWQWRtaW5Ab3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNhgfr0BL6ah\noVgpPsN6vtMi/EqfNv59DdDYp56LsuxaxAU9jiCYIg0jxtgD3qqcmB0MYipTxZgF\nKlsptci9LK+jTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIAGsbgVlAMrLMRvi5+a9qx8EqLvfetMfmQjWK2rHxIdTMAoGCCqGSM49\nBAMCA0cAMEQCID3PSb0/im0Ev1AeuBUYGfEiHa243k5e2B6TSz0yV49nAiA217bD\nYLSNUgPvzQQAeBo554tJpcdEizI+02Ui6spttA==\n-----END CERTIFICATE-----\n",
      
      "Fabric1.4:payment1.fabric101:cert" : "-----BEGIN CERTIFICATE-----\nMIICKTCCAc+gAwIBAgIQFbDE7H0O6F4KGOiO+wcUejAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0yMjAxMTAwMTUwMDBaFw0zMjAxMDgwMTUwMDBa\nMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ4wDAYDVQQLEwVhZG1pbjEfMB0GA1UEAwwWQWRtaW5Ab3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCHZbJUbc9bP\nrIFaVdvr9tFKRNCvkvZDdXyZ7K4cugUHUkPA+wSSR9h85rTTK+qnthP2xTechBkR\n8/s2INXUwcCjTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIMWWr0Q1IL/qseILf/Wo3dnFHPy3Q9Z2hDvBPfIbn3CUMAoGCCqGSM49\nBAMCA0gAMEUCIQD6JpcbGe9jpXAycGWHMZSUOGgNemEL7vWrBds2RpV+2AIgbtYk\nJ4w7pDJcmehXxIaW4oiFra0fp6a6b9mY8b6FMEw=\n-----END CERTIFICATE-----\n",
      "Fabric1.4:payment1.fabric101:name" : "fabric_admin",
      "Fabric1.4:payment1.fabric101:mspid" : "Org1MSP"
    },
    "isDefault" : true
  }
}

把两个报文拼起来,就可以将两个fabric链的二级账户同时纳入101和102的两个一级账户管理。

这样做是因为目前陆羽协议对fabric的二级账户机制支持的不是很好,无法动态的添加fabric的二级账户,只能一次性添加。

7.9 添加二级账户

将上面两个报文分别发送至101和102

http://172.16.164.133:8340/auth/addAlgAccount
http://172.16.164.134:8340/auth/addAlgAccount
{
    "version": "1.0",
    "errorCode": 0,
    "message": "success",
    "data": {
        "errorCode": 0,
        "message": "success"
    }
}
7.10 查询二级账户

使用对应ip的地址查询是否添加成功

接口:

http://172.16.164.133:8340/auth/listAccount

报文( sender不同):

{
    "data":{
        "luyuSign": [],
        "signData":{
            "sender": "0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64"
        }
    }
}

陆羽协议到此就配置完毕,下面是调用

调用router时,需要调用account-manager验证账户,因此需要把7.3sslOn配置改成true,之后重启容器

docker restart account-manager
8,调用cc

查询接口:http://172.16.164.133:8250/resource/call

调用接口:http://172.16.164.133:8250/resource/sendTransaction

在path参数中定义调用的资源路径,纳入router管理的资源都可以调用

{
    "version":"1",
    "data":{
        "path": "payment1.fabric101.mycc", #资源路径
        "method": "invoke",#调用合约的方法名
        "args": ["a","b","1"],#参数
        "nonce":1,
        "luyuSign":"",#签名,配置application.toml中是否需要签名
        "sender": "0xc0a485c9a36539bb0ecc4deb9f38f2f2a0192b64"#调用者一级账户
    }
}
9,合约跨链

配置完毕后跨链功能的实现主要是合约的编写,示例:

package main

import (
    "fmt"
    "github.com/hyperledger/fabric/core/chaincode/shim"
    pb "github.com/hyperledger/fabric/protos/peer"
    "strconv"
)

type Chcc struct {
}

func main() {
    err := shim.Start(new(Chcc))
    if err != nil {
        fmt.Printf("Error starting Simple chaincode: %s", err)
    }
}

const (
    ccbt  = "callCallBackTimes"            //用来计数,回调了call方法多少次
    stcbt = "sendTransactionCallBackTimes" //用来计数,回调了sendTransaction方法多少次
    aval  = "fabric102AValue"
)

func (c *Chcc) Init(stub shim.ChaincodeStubInterface) pb.Response {
    z := strconv.Itoa(0)
    //两个次数都设成0
    stub.PutState(ccbt, []byte(z))
    stub.PutState(stcbt, []byte(z))
    return shim.Success(nil)
}

func (c *Chcc) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    function, args := stub.GetFunctionAndParameters()
    if function == "callFabric102" { //调用查询方法,直接返回值
        return c.callFabric102(stub, args)
    } else if function == "sendTxToFabric102" { //调用sengTransaction方法
        return c.sendTxToFabric102(stub, args)
    } else if function == "getLuYuInvokeTimes" { //查询调用次数
        return c.getLuYuInvokeTimes(stub, args)
    } else if function == "getCallback" { //callFabric102回调函数
        var nonce uint64
        nonce, callbackArgs, err := ParseCallbackArgs(args)
        if err != nil {
            return shim.Error(err.Error())
        }
        return c.getCallback(stub, nonce, callbackArgs)
    } else if function == "setCallback" { //sendTxToFabric102回调函数
        var nonce uint64
        var callbackArgs []string
        nonce, callbackArgs, err := ParseCallbackArgs(args)
        if err != nil {
            return shim.Error(err.Error())
        }
        return c.setCallback(stub, nonce, callbackArgs)
    }
    return shim.Error("Invalid invoke function name.")
}

func (c *Chcc) callFabric102(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    //调用CrossCall方法会生成_event_call的event,plugin捕捉到这个event之后就会向对应的路径资源发送
    nonce, err := CrossCall(stub, "payment2.fabric102.mycc", //资源路径
        "query",       //调用方法名
        []string{"a"}, //参数
        "0x1f80e895ba2387a29ba9723b6fb3d6eded5e73c3", //一级账户地址
        "getCallback") //跨链成功后回调函数方法名
    if err != nil {
        return shim.Error("call error:" + err.Error())
    }
    return shim.Success([]byte(fmt.Sprintf("nonce: %d", nonce)))
}

func (c *Chcc) sendTxToFabric102(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    //
    nonce, err := CrossSendTransaction(stub, "payment2.fabric102.mycc", //资源路径
        "invoke",                //调用方法名
        []string{"b", "a", "1"}, //参数
        "0x1f80e895ba2387a29ba9723b6fb3d6eded5e73c3", //一级账户地址
        "setCallback") //跨链成功后回调函数方法名
    if err != nil {
        return shim.Error("call error:" + err.Error())
    }
    return shim.Success([]byte(fmt.Sprintf("nonce: %d", nonce)))
}

//回调函数调用成功标志:aval取到最新值,ccbt次数+1
func (c *Chcc) getCallback(stub shim.ChaincodeStubInterface, nonce uint64, value []string) pb.Response {
    res, err := stub.GetState(ccbt)
    if err != nil {
        return shim.Error(err.Error())
    }
    i, _ := strconv.Atoi(string(res))
    i++
    if err := stub.PutState(ccbt, []byte(strconv.Itoa(i))); err != nil {
        return shim.Error(err.Error())
    }
    a := value[0]
    stub.PutState(aval, []byte(a))
    return shim.Success(nil)
}

//回调函数调用成功标志:stcbt次数+1
func (c *Chcc) setCallback(stub shim.ChaincodeStubInterface, nonce uint64, args []string) pb.Response {
    res, err := stub.GetState(stcbt)
    if err != nil {
        return shim.Error(err.Error())
    }
    i, _ := strconv.Atoi(string(res))
    i++
    stub.PutState(stcbt, []byte(strconv.Itoa(i)))
    return shim.Success(nil)
}

//查询ccbt,stcbt,aval
func (c *Chcc) getLuYuInvokeTimes(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    res1, err := stub.GetState(ccbt)
    if err != nil {
        return shim.Error(err.Error())
    }
    res2, err := stub.GetState(stcbt)
    if err != nil {
        return shim.Error(err.Error())
    }
    r1, _ := strconv.Atoi(string(res1))
    r2, _ := strconv.Atoi(string(res2))
    a, _ := stub.GetState(aval)
    res := []byte(fmt.Sprintf("callCallBackTimes = %v,sendTransactionCallBackTimes = %v, 102A-Value = %v \n",
        r1, r2, string(a)))
    return shim.Success(res)
}

转载请注明来源

×

喜欢就点赞,疼爱就打赏