网上很多安装教程,现普遍使用2.2
cd /home/xx/go/src/github.com/hyperledger/fabric/scripts/fabric-samples
cd test-network
./network.sh up
与Fabric网络交互的每个节点和用户都需要属于作为网络成员的组织即联盟。测试网络有两个联盟成员,Org1和Org2。网络还包括维护网络的排序服务的排序节点组织。
节点是任何Fabric网络的基本组成部分。节点存储区块链账本,并在提交到账本之前验证交易。节点运行智能合约,其中包含用于管理区块链账本上资产的业务逻辑。
排序服务允许节点集中精力验证交易并将其提交到账本。在排序节点从客户端接收到背书的交易后,它们就交易的顺序达成共识,然后将它们添加到块中。然后,区块被分发到普通节点,普通节点将区块添加到区块链账本中。排序节点还操作定义Fabric网络功能的系统通道,例如如何生成块以及节点可以使用的Fabric版本。系统通道定义了哪些组织是联盟的成员。
docker ps -a
通道是特定网络成员之间的专用通信层。通道只能由受邀加入通道的组织使用,并对网络的其他成员不可见。每个通道都有一个单独的区块链账本。创建默认名称为mychannel的通道
./network.sh createChannel
也可以使用通道标志创建具有自定义名称的通道。例如,以下命令将创建名为channel1的通道。
./network.sh createChannel -c channel1
如果要启动网络并在一个步骤中创建通道,可以同时使用up和createChannel模式:
./network.sh up createChannel
创建通道后,可以使用智能合约与通道账本进行交互。智能合约包含管理区块链账本上资产的业务逻辑。网络成员运行的应用程序可以调用智能合约在账本上创建资产,以及更改和转移这些资产。应用程序还可以查询智能合约以读取账本上的数据。
为确保交易有效,使用智能合约创建的交易通常需要由多个组织签署才能提交到通道账本。多重签名是Fabric信任模型不可或缺的一部分。要求对一个交易进行多重背书可以防止通道上的一个组织篡改其节点的账本或使用未经同意的业务逻辑。要签署一个交易,每个组织都需要在其节点上调用和执行智能合约,然后由节点对交易的输出进行签名。如果输出是一致的,并且已经有足够的组织签名,则可以将交易提交到账本。指定通道上需要执行智能合约的已设置组织的策略称为背书策略,它是作为链码定义的一部分为每个链码设置的。
在Fabric中,智能合约在网络上部署在称为链码的包中。链码安装在组织的节点上,然后部署到一个通道,在那里它可以被用来背书交易和与区块链账本交互。在将链码部署到通道之前,通道成员需要就建立链码治理的链码定义达成一致。当所需数量的组织达成一致时,可以将链码定义提交给通道,并且可以使用链码。
需把链码放在/home/blockchain/go/src/github.com/hyperledger/fabric/scripts/fabric-samples目录下
链码在import shim和peer时注意fabric2.x版本
"github.com/hyperledger/fabric-chaincode-go/shim"
sc "github.com/hyperledger/fabric-protos-go/peer"
./network.sh deployCC -ccn car_demo -ccp ../car_demo/chaincode-go -ccl go
./network.sh deployCC -ccn cbc -ccp ../cbc/chaincode-go -ccl go
在启动测试网络后,可以使用peer cli客户端与网络进行交互,通过peer cli客户端可以调用已部署的智能合约,更新通道,或者安装和部署新的智能合约。
首先确保操作目录为test-netwok目录
pwd
执行一下命令将cli客户端添加到环境变量中
export PATH=${PWD}/../bin:$PATH
还需要将fabric-samples代码库中的FABRIC_CFG_PATH设置为指向其中的core.yaml文件:
export FABRIC_CFG_PATH=$PWD/../config/
设置允许org1操作peer cli的环境变量:
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
CORE_PEER_TLS_ROOTCERT_FILE 和 CORE_PEER_MSPCONFIGPATH 环境变量指向Org1的 organizations 文件夹中的的加密材料。
执行以下命令用一些资产来初始化账本: 注意-n 后面参数改为链码名称
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 car_demo --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 car_demo -c '{"Args":["queryAllCars"]}'
peer chaincode query -C mychannel -n cbc -c '{"Args":["RegisterUser","Alice"]}'
peer chaincode query -C mychannel -n abe_lightweight -c '{"Args":["RegisterUser","Alice"]}'
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/gateway"
"github.com/robfig/cron"
)
func main() {
err := os.RemoveAll("./keystore")
err = os.RemoveAll("./wallet")
if err != nil {
log.Fatal(err)
}
log.Println("============ application-golang starts ============")
err = os.Setenv("DISCOVERY_AS_LOCALHOST", "true")
if err != nil {
log.Fatalf("Error setting DISCOVERY_AS_LOCALHOST environemnt variable: %v", err)
}
wallet, err := gateway.NewFileSystemWallet("wallet")
if err != nil {
log.Fatalf("Failed to create wallet: %v", err)
}
if !wallet.Exists("appUser") {
err = populateWallet(wallet)
if err != nil {
log.Fatalf("Failed to populate wallet contents: %v", err)
}
}
ccpPath := filepath.Join(
"..",
"..",
"test-network",
"organizations",
"peerOrganizations",
"org1.example.com",
"connection-org1.yaml",
)
gw, err := gateway.Connect(
gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
gateway.WithIdentity(wallet, "appUser"),
)
if err != nil {
log.Fatalf("Failed to connect to gateway: %v", err)
}
defer gw.Close()
network, err := gw.GetNetwork("mychannel")//链接到channel
if err != nil {
log.Fatalf("Failed to get network: %v", err)
}
contract := network.GetContract("test") //获得智能合约
log.Println("--> Submit Transaction: RegisterUser, function creates the initial set of assets on the ledger")
result, err := contract.SubmitTransaction("RegisterUser","Alice") //提交交易
print(result)
if err != nil {
log.Fatalf("Failed to Submit transaction: %v", err)
}
log.Println(string(result))
}
func populateWallet(wallet *gateway.Wallet) error {
log.Println("============ Populating wallet ============")
credPath := filepath.Join(
"..",
"..",
"test-network",
"organizations",
"peerOrganizations",
"org1.example.com",
"users",
"User1@org1.example.com",
"msp",
)
certPath := filepath.Join(credPath, "signcerts", "User1@org1.example.com-cert.pem")
// read the certificate pem
cert, err := ioutil.ReadFile(filepath.Clean(certPath))
if err != nil {
return err
}
keyDir := filepath.Join(credPath, "keystore")
// there's a single file in this dir containing the private key
files, err := ioutil.ReadDir(keyDir)
if err != nil {
return err
}
if len(files) != 1 {
return fmt.Errorf("keystore folder should have contain one file")
}
keyPath := filepath.Join(keyDir, files[0].Name())
key, err := ioutil.ReadFile(filepath.Clean(keyPath))
if err != nil {
return err
}
identity := gateway.NewX509Identity("Org1MSP", string(cert), string(key))
return wallet.Put("appUser", identity)
}
./network.sh down
注意依赖包的版本可能会导致出现错误
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://
之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
有没有一种简单的方法可以判断ruby脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免