文章目录

  • 部署
  • 测试

本篇博客基于 Fabric v2.2 部署了一个联盟链,包含一个Org和两个peer,使用了单个节点的raft作为Ordering service。部署过程主要参考了Fabric的官方文档,大部分脚本和配置文件都来自于官方提供的样例。
测试使用了 tape 这个轻量级的工具,个人觉得比 caliper 好用。

部署

curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.2.2 1.4.9
cd fabric-samples/test-network
./network.sh up
./network.sh createChannel   # 使用smallbank进行测试
mkdir -p smallbank/go
cd smallbank/go
touch go.mod smallbank.go # 这两个文件内容在下面,复制进去之后,再运行下一条命令
./network.sh deployCC -ccn smallbank -ccp ./smallbank/go -ccl go -cci InitLedger

go.mod 文件如下:

module github.com/hyperledger/fabric-samples/chaincode/smallbank/gogo 1.13require github.com/hyperledger/fabric-contract-api-go v1.1.0

smallbank.go 文件如下:

package mainimport ("encoding/json""fmt""crypto/sha512""encoding/hex""strings""github.com/hyperledger/fabric-contract-api-go/contractapi"
)var namespace = hexdigest("smallbank")[:6]// SmartContract provides functions for managing a Account
type SmartContract struct {contractapi.Contract
}type Account struct {CustomId   stringCustomName stringSavingsBalance intCheckingBalance int
}func hexdigest(str string) string {hash := sha512.New()hash.Write([]byte(str))hashBytes := hash.Sum(nil)return strings.ToLower(hex.EncodeToString(hashBytes))
}func accountKey(id string) string {return namespace + hexdigest(id)[:64]
}func saveAccount(ctx contractapi.TransactionContextInterface, account *Account) error {accountBytes, err := json.Marshal(account)if err != nil {return err}key := accountKey(account.CustomId)return ctx.GetStub().PutState(key, accountBytes)
}
func loadAccount(ctx contractapi.TransactionContextInterface, id string) (*Account, error) {key := accountKey(id)accountBytes,err := ctx.GetStub().GetState(key)if err != nil {return nil, err}res := Account{}err = json.Unmarshal(accountBytes, &res)if err != nil {return nil, err}return &res, nil
}func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {fmt.Println("init: create two accounts")account1 := &Account{CustomId: "account1",CustomName: "account1",SavingsBalance: 1e9,CheckingBalance: 1e9,}err := saveAccount(ctx, account1)if err != nil {return fmt.Errorf("Put state failed when create account %s", customId)}account2 := &Account{CustomId: "account2",CustomName: "account2",SavingsBalance: 1e9,CheckingBalance: 1e9,}err = saveAccount(ctx, account2)if err != nil {return fmt.Errorf("Put state failed when create account %s", customId)}return nil
}func (s *SmartContract) CreateAccount(ctx contractapi.TransactionContextInterface, customId string, customName string, savingsBalance int, checkingBalance int) error {key := accountKey(customId)data,err := ctx.GetStub().GetState(key)if data != nil {fmt.Println("Can not create duplicated account")}// checking, errcheck := strconv.Atoi(checkingBalance)// if errcheck != nil {//      return fmt.Errorf(" create_account, checking balance should be integer")// }// saving, errsaving := strconv.Atoi(savingsBalance)// if errsaving != nil {//      return fmt.Errorf(" create_account, saving balance should be integer")// }account := &Account{CustomId: customId,CustomName: customName,SavingsBalance: savingsBalance,CheckingBalance: checkingBalance,}err = saveAccount(ctx, account)if err != nil {return fmt.Errorf("Put state failed when create account %s", customId)}return nil}func (t *SmartContract) DepositChecking(ctx contractapi.TransactionContextInterface, customId string, amount int) error {account, err := loadAccount(ctx, customId)if err != nil {return fmt.Errorf("Account %s not found", customId)}account.CheckingBalance += amounterr = saveAccount(ctx, account)if err != nil {return fmt.Errorf("Put state failed in DepositChecking")}return nil
}
func (t *SmartContract) WriteCheck(ctx contractapi.TransactionContextInterface, customId string, amount int) error {account, err := loadAccount(ctx, customId)if err != nil {return fmt.Errorf("Account %s not found", customId)}account.CheckingBalance -= amounterr = saveAccount(ctx, account)if err != nil {return fmt.Errorf("Put state failed in WriteCheck")}return nil
}func (t *SmartContract) TransactSavings(ctx contractapi.TransactionContextInterface, customId string, amount int) error {account, err := loadAccount(ctx, customId)if err != nil {return fmt.Errorf("Account %s not found", customId)}// since the contract is only used for perfomance testing, we ignore this check//if amount < 0 && account.SavingsBalance < (-amount) {//      return errormsg("Insufficient funds in source savings account")//}account.SavingsBalance += amounterr = saveAccount(ctx, account)if err != nil {return fmt.Errorf("Put state failed in TransactionSavings")}return nil
}func (t *SmartContract) SendPayment(ctx contractapi.TransactionContextInterface, src_customId string, dst_customId string, amount int) error {destAccount, err1 := loadAccount(ctx, dst_customId)sourceAccount, err2 := loadAccount(ctx, src_customId)if err1 != nil || err2 != nil {return fmt.Errorf("Account [ %s or %s ] not found", src_customId, dst_customId)}// since the contract is only used for perfomance testing, we ignore this check//if sourceAccount.CheckingBalance < amount {//      return errormsg("Insufficient funds in source checking account")//}sourceAccount.CheckingBalance -= amountdestAccount.CheckingBalance += amounterr1 = saveAccount(ctx, sourceAccount)err2 = saveAccount(ctx, destAccount)if err1 != nil || err2 != nil {return fmt.Errorf("Put state failed in sendPayment")}return nil
}func (t *SmartContract) Amalgamate(ctx contractapi.TransactionContextInterface, dst_customId string, src_customId string) error {destAccount, err1 := loadAccount(ctx, dst_customId)sourceAccount, err2 := loadAccount(ctx, src_customId)if err1 != nil || err2 != nil {return fmt.Errorf("Account [ %s or %s ] not found", src_customId, dst_customId)}err1 = saveAccount(ctx, sourceAccount)err2 = saveAccount(ctx, destAccount)if err1 != nil || err2 != nil {return fmt.Errorf("Put state failed in sendPayment")}return nil
}func (t *SmartContract) Query(ctx contractapi.TransactionContextInterface, customId string) (*Account, error) {key := accountKey(customId)accountBytes,err := ctx.GetStub().GetState(key)if err != nil {return nil, fmt.Errorf("Failed to read from world state.")}if accountBytes == nil {return nil, fmt.Errorf("Account %s does not exist", customId)}account := new(Account)_ = json.Unmarshal(accountBytes, account)// fmt.Printf("%+v\n", account)return account, nil
}func main() {chaincode, err := contractapi.NewChaincode(new(SmartContract))if err != nil {fmt.Printf("Error create fabcar chaincode: %s", err.Error())return}if err := chaincode.Start(); err != nil {fmt.Printf("Error starting fabcar chaincode: %s", err.Error())}
}

测试

Caliper 个人感觉有些复杂,不如 tape 好用,因此这里使用 tape 进行测试。
以下命令都在 fabric-samples/test-network 目录下进行。

git clone https://github.com/Hyperledger-TWGC/tape.git
cd tape
go build ./cmd/tape
ln -s ../organizations organizations

修改 config.yaml 如下:

# Definition of nodes
peer1: &peer1addr: localhost:7051tls_ca_cert: ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/tlscacerts/tlsca.org1.example.com-cert.pempeer2: &peer2addr: localhost:9051tls_ca_cert: ./organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp/tlscacerts/tlsca.org2.example.com-cert.pemorderer1: &orderer1addr: localhost:7050tls_ca_cert: ./organizations/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem# Nodes to interact with
endorsers:- *peer1
# we might support multi-committer in the future for more complex test scenario,
# i.e. consider tx committed only if it's done on >50% of nodes. But for now,
# it seems sufficient to support single committer.
committers:- *peer2
commitThreshold: 1
orderer: *orderer1# Invocation configs
channel: mychannel
chaincode: smallbank
args:- SendPayment- account1- account2- 1
mspid: Org1MSP
private_key: ./organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk
sign_cert: ./organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem
num_of_conn: 10
client_per_conn: 10

测试:

./tape -c config.yaml -n 100 # account1 向 account2 转账100次

Fabric v2.2 单机部署 使用tape测试相关推荐

  1. Hyperledger Fabric 2.x 单机部署多节点网络

    本博客主要记录搭建一个3个排序节点.4个组织的每个组织各2个节点的fabric区块链网络 单机部署多节点网络 1.相关环境的安装与配置 2.生成相关的证书文件 3.生成相关的通道配置文件 4.生成do ...

  2. centos6.5环境下zookeeper-3.4.6集群环境部署及单机部署详解

    centos6.5环境下Zookeeper-3.4.6集群环境部署 [系统]Centos 6.5 集群部署 [软件]准备好jdk环境,此次我们的环境是open_jdk1.8.0_101 zookeep ...

  3. Fabric v2.3 手动模拟(一) - 测试网络./network.sh up命令创建自己的网络

    目录 0. 引言 1. 创建自己的网络目录 (1)进入fabric-samples目录 (2)创建文件夹test-network-myself(自己的网络目录) (3)进入test-network-m ...

  4. Fabric v2.3 测试网络 - 脚本分析(二)- 创建通道createChannel.sh解析

    本文针对创建通道脚本createChannel.sh进行分析,此脚本被创建测试网络network.sh脚本在执行命令./network.sh createChannel时调用 调用脚本及参数默认值命令 ...

  5. Ubuntu 20.04 下Fabric V2.2.0 和 V1.1.0 运行及配置说明(均可运行)

    ubuntu 20.04 下Fabric V2.2.0 和 V1.1.0 运行及配置说明 ubuntu 20.04 下Fabric运行及配置说明 注:本文是对 <hyperledger/fabr ...

  6. 002_FastDFS单机部署

    1. 环境准备 1.1. 使用的系统软件 1.2. 编译环境 1.2.1. 编译命令(实际安装了git.gcc.gcc-c++.pcre.pcre-devel.zlib.zlib-devel.open ...

  7. Geomesa-Hbase单机部署及ingest、export shp文件数据

    本文记录一下Geomesa-Hbase单机部署,步骤如下: 1.在VMware下创建虚拟机 2.安装Linux系统(我选的是centos6.8) https://www.cnblogs.com/hel ...

  8. kylin版本_kylin多维数据分析(一)单机部署

    点击上方蓝字关注 [写在前面]:前段时间因为项目需要,使用了一段时间的kylin进行多维数据分析.从kylin单机/分布式部署.事实表维度表设计.再到cube优化和调度等全都亲手实操了一遍.过程中的所 ...

  9. sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署、故障转移群集与日志传送

    sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署.故障转移群集与日志传送 数据库的选型和部署 sqlserver的安装和升级 选择高可用性和灾难恢复技术 故障转移群集 日志传 ...

  10. nacos安装配置和单机部署教程

    首先说明:次教程是针对的nacos版本:1.3.2,不同的版本,可能略有不同. Springcloudalibaba的版本与Springboot的版本与nacos版本需要对应 Nacos支持三种部署模 ...

最新文章

  1. vb 怎样指定 dll 引用路径_C#/VB.NET 比较两个Word文档差异
  2. 在JAVA中使用MongoDB
  3. SQL Union 和 Union All 的区别以及二者的性能问题 - 使用Sqlite演示
  4. linux 线程_Linux 多线程编程(不限Linux)
  5. 【故障分析】基于matlab轴承故障分析(时频图+功率谱)【含Matlab源码 922期】
  6. 【步步到位】mysql安装教程 8.0.26
  7. 关于起点中文网的一个我自认为是BUG的BUG(花了我一毛三分钱才实验出来的)...
  8. Linux服务器搭建24小时直播平台
  9. fastadmin使用ECharts制作统计图
  10. Final发布中间产物
  11. Node.js 中 __dirname 和 ./ 的区别
  12. Retinex、log对数变换、直方图均衡化区别,边缘增强Retinex算法与拉普拉斯算法联系、均衡化与亮度调节算法、大津阈值计算
  13. 线程池七个参数的含义
  14. ndk开发(二)JNI、java互调
  15. int不是默认为0吗?为什么会提示要初始化?
  16. 使用Scratch制作打弹球游戏(五)-排名
  17. matlab求条件概率密度_Matlab对量子力学中的一维无限深势阱的模拟计算
  18. 墨迹天气携手友盟+U-APM,共同打造良好应用性能体验
  19. oracle 大会旧金山,甲骨文全球大会2013旧金山- In-Memory Option即将发布
  20. 03前端入门课--数组的属性 操作方法

热门文章

  1. python操作word文档,合并
  2. 电子基础元器件——电阻器
  3. C++ 调用Asprise OCR识别图片中的文字
  4. 使用plist文件进行ipa的安装
  5. 用 Mac 输入罗马数字
  6. NOIP模拟 9.09
  7. 计算机关机后风扇还转,电脑关机后cpu风扇还在转怎么办?解决电脑关机后cpu散热器还在转...
  8. html5做出toast效果,toast提示效果
  9. 解读加多宝的营销案例分析
  10. 人工智能终究会抢了我们程序员的饭碗