Fabric笔记

#1 简单描述Fabric数据上链过程

##1.1、模拟

client发起交易请求,请求被发送至endorsers,模拟进行这些交易,会产生一个read set和一个write set记录这个交易的影响,模拟完成后,endorser对read set和write set进行签名并将其一起返回给client

如果client收到的read set和write set是一致的(可能存在恶意endorser或者智能合约存在不确定的算法导致出现不一致),那么client就会生成一个真正的交易请求,包含read set、write set和对应的签名,并将这个请求发送给ordering service。

##1.2、排序

ordering service对来自client的交易进行排序,需要注意的是这里并不检查交易的内容,默认按照交易到达的顺序进行排序,ordering service将交易排序后打包成block,发送给网络中的peers,这里不保证所有的peer同时收到这个block,但保证收到的block的顺序是一致的(使用gossip协议)。

##1.3、验证
当peer收到block后,就开始验证阶段。

验证阶段主要包括两个检查:

####Endorsement Policy检查

检查交易是否满足endorsement policy以及是否包含有效的签名,否则说明交易可能被client或者恶意peer篡改过,直接丢弃。

####交易冲突检查

检查交易之间是否存在冲突,也就是是否读脏数据的问题(某个交易在读取ledger之前,ledger被前一个交易改变了),如果存在就丢弃该交易。
两次检查都通过的话就可以进入commit阶段了。

##1.4、上链
peer将block添加到链上,注意这里是所有的交易(有效的和无效的)都加进来了。然后根据有效的交易改变当前的ledger状态

1
https://hyperledger-fabric-zh-cn.readthedocs.io/zh/latest/docs/Ledger.html#transaction-flow

#2 Fabric如何动态增加组织、节点

调用k8s创建同一个namespace下containter–pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
func (service *channelService) updateChannelConfig(request module.PutChannelOrganizationRequest) error {
namespace := request.OrderNamespace
clientset, err := kubernetes.NewKubernetesClient()
if err != nil {
return err
}
dep, err := clientset.AppsV1beta1().Deployments(namespace).Get(CliDepName, v1.GetOptions{})
if err != nil {
return err
}

podLabels := dep.Spec.Selector.MatchLabels
podSelector := pkglabels.FormatLabels(podLabels)
podOpts := v1.ListOptions{
LabelSelector: podSelector,
}
podList, err := clientset.CoreV1().Pods(namespace).List(podOpts)
if err != nil {
return err
}

if len(podList.Items) == 0 {
return errors.New("can't find cli pod")
}

podName := podList.Items[0].Name
containerName := podList.Items[0].Spec.Containers[0].Name
peerOrgs := strings.Join(request.PeerOrgs, ",")
command := fmt.Sprintf("/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/addorg.sh %s %s %s %s", request.ChannelName, request.OrderNamespace, request.OrgName, peerOrgs)
glog.Infof("ContainerExec namespace :%s", namespace)
glog.Infof("ContainerExec podName :%s", podName)
glog.Infof("ContainerExec containerName :%s", containerName)
glog.Infof("ContainerExec command :%s", command)
stdout, stderr, err := kubernetes.ContainerExec(namespace, podName, containerName, command)
if err != nil {
glog.Errorf("Invoke ContainerExec occur a error. It is %s", err)
return err
}
glog.Info("stdout ==>", stdout)
glog.Info("stderr ==>", stderr)
return nil
}

将节点加入通道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

fabric网络中创建通道
mspId, _ := db.GetMspIdByPeerId(peer)
fabricClient, err := context.GetServer().GetClient(joinChl.NetId, "Admin", mspId)
if err != nil {
log.Logger.Errorf("GetClient error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{
"err": err.Error(),
})
}
// Resmgmt client
clientProvider := fabricClient.GetClientProvider()
resmgmtClient, err := resmgmt.New(clientProvider)
ctx, err := clientProvider()
log.Logger.Debugf("join channel resmgmtClient.ctx = %+v, %v", ctx, err)
err = resmgmtClient.JoinChannel(channelName, resmgmt.WithTargetURLs(peerURL), resmgmt.WithOrdererURL(ordererURL))
if err != nil {
log.Logger.Errorf("JoinChannel error :%v ", err)
c.JSON(http.StatusInternalServerError, gin.H{
"err": err.Error(),
})
return
}
log.Logger.Info("JoinChannel SUCCESS!")
1
2
3
4
5
6
7
8
9
10
11
//RefreshClient
for _, peerOrg := range PeerOrgs {
err = context.GetServer().RefreshClient(joinChl.NetId, "Admin", fmt.Sprintf("%s%s", strings.ToUpper(peerOrg.Name[0:1]), peerOrg.Name[1:]))
if err != nil {
log.Logger.Errorln("RefreshClient error:", err)
c.JSON(http.StatusInternalServerError, gin.H{
"err": err.Error(),
})
return
}
}

#3 如果一个peer节点服务器损坏,数据如何恢复

// 如果CA等数据还在,再次加入节点,会自动同步区块

#4 描述Fabric的创世区块的作用,世界状态的作用

创世区块:创世区块文件,需要手动用官方提供的工具configtxgen生成,创建语句为configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block,创世区块的主要作用是定义了系统通道的共识算法,准入的组织名称,策略等信息

世界状态:世界状态代表了所有账本状态当前的值。这个世界状态非常有用,因为程序通常需要某个账本的当前状态值,并且总是很容易就能获取到。你不需要遍历整个区块链去计算账本当前的状态的值(余额),你可以直接从世界状态获取

#5 Fabric中一个区块的数据结构

区块头 包含区块高度,上一个区块的哈希值,本区块的哈希值

交易数据集合,封装了打包的交易集合

区块元数据,封装了如下4个元数据索引项

1
2
3
4
5
6
7
BlockMetadataIndex_SIGNATURES:区块签名;

BlockMetadataIndex_LAST_CONFIG:最新配置区块的区块号;

BlockMetadataIndex_TRANSACTIONS_FILTER:最新交易过滤器,封装了交易数据集合Data中所有交易对应的交易验证码,标识其交易的有效性。

BlockMetadataIndex_ORDERER:Orderer配置信息,如Kafka共识组件的初始化参数。

#6 描述CA 公私钥及常见的加密算法

##Fabric-CA

1
2
3
4
5

https://www.cnblogs.com/kaixinyufeng/p/9803413.html


https://blog.csdn.net/greedystar/article/details/80344984

##公私钥及常见的加密算法

1
2
3
4

https://www.cnblogs.com/charlesblc/p/6130433.html

https://blog.csdn.net/u011531425/article/details/89161392

#7 常用的共识算法

1
https://blog.csdn.net/s_lisheng/article/details/78022645

#8 Merkie tree、GHOST协议、分叉

##Merkie tree

1
https://www.cnblogs.com/fengzhiwu/p/5524324.html

##GHOST协议

1
https://blog.csdn.net/t46414704152abc/article/details/81191804

##分叉

1
2


#9 描述下http协议,session,cookie在其中的作用

1
2
3
https://blog.csdn.net/astro_boy/article/details/84054090

http://m.elecfans.com/article/596778.html

#10 联盟链,Fabric比较其他联盟链的优势

1
http://www.elecfans.com/blockchain/800061.html

#11 链码的事件通知