Fabric v2.2 单机部署 使用tape测试
文章目录
- 部署
- 测试
本篇博客基于 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测试相关推荐
- Hyperledger Fabric 2.x 单机部署多节点网络
本博客主要记录搭建一个3个排序节点.4个组织的每个组织各2个节点的fabric区块链网络 单机部署多节点网络 1.相关环境的安装与配置 2.生成相关的证书文件 3.生成相关的通道配置文件 4.生成do ...
- centos6.5环境下zookeeper-3.4.6集群环境部署及单机部署详解
centos6.5环境下Zookeeper-3.4.6集群环境部署 [系统]Centos 6.5 集群部署 [软件]准备好jdk环境,此次我们的环境是open_jdk1.8.0_101 zookeep ...
- Fabric v2.3 手动模拟(一) - 测试网络./network.sh up命令创建自己的网络
目录 0. 引言 1. 创建自己的网络目录 (1)进入fabric-samples目录 (2)创建文件夹test-network-myself(自己的网络目录) (3)进入test-network-m ...
- Fabric v2.3 测试网络 - 脚本分析(二)- 创建通道createChannel.sh解析
本文针对创建通道脚本createChannel.sh进行分析,此脚本被创建测试网络network.sh脚本在执行命令./network.sh createChannel时调用 调用脚本及参数默认值命令 ...
- 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 ...
- 002_FastDFS单机部署
1. 环境准备 1.1. 使用的系统软件 1.2. 编译环境 1.2.1. 编译命令(实际安装了git.gcc.gcc-c++.pcre.pcre-devel.zlib.zlib-devel.open ...
- Geomesa-Hbase单机部署及ingest、export shp文件数据
本文记录一下Geomesa-Hbase单机部署,步骤如下: 1.在VMware下创建虚拟机 2.安装Linux系统(我选的是centos6.8) https://www.cnblogs.com/hel ...
- kylin版本_kylin多维数据分析(一)单机部署
点击上方蓝字关注 [写在前面]:前段时间因为项目需要,使用了一段时间的kylin进行多维数据分析.从kylin单机/分布式部署.事实表维度表设计.再到cube优化和调度等全都亲手实操了一遍.过程中的所 ...
- sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署、故障转移群集与日志传送
sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署.故障转移群集与日志传送 数据库的选型和部署 sqlserver的安装和升级 选择高可用性和灾难恢复技术 故障转移群集 日志传 ...
- nacos安装配置和单机部署教程
首先说明:次教程是针对的nacos版本:1.3.2,不同的版本,可能略有不同. Springcloudalibaba的版本与Springboot的版本与nacos版本需要对应 Nacos支持三种部署模 ...
最新文章
- vb 怎样指定 dll 引用路径_C#/VB.NET 比较两个Word文档差异
- 在JAVA中使用MongoDB
- SQL Union 和 Union All 的区别以及二者的性能问题 - 使用Sqlite演示
- linux 线程_Linux 多线程编程(不限Linux)
- 【故障分析】基于matlab轴承故障分析(时频图+功率谱)【含Matlab源码 922期】
- 【步步到位】mysql安装教程 8.0.26
- 关于起点中文网的一个我自认为是BUG的BUG(花了我一毛三分钱才实验出来的)...
- Linux服务器搭建24小时直播平台
- fastadmin使用ECharts制作统计图
- Final发布中间产物
- Node.js 中 __dirname 和 ./ 的区别
- Retinex、log对数变换、直方图均衡化区别,边缘增强Retinex算法与拉普拉斯算法联系、均衡化与亮度调节算法、大津阈值计算
- 线程池七个参数的含义
- ndk开发(二)JNI、java互调
- int不是默认为0吗?为什么会提示要初始化?
- 使用Scratch制作打弹球游戏(五)-排名
- matlab求条件概率密度_Matlab对量子力学中的一维无限深势阱的模拟计算
- 墨迹天气携手友盟+U-APM,共同打造良好应用性能体验
- oracle 大会旧金山,甲骨文全球大会2013旧金山- In-Memory Option即将发布
- 03前端入门课--数组的属性 操作方法