• Hyperledger Fabric 区块结构解析


    原文: https://www.cnblogs.com/yimeixiaobai1314/p/14359395.html

    前言

    ​ 最近在搞区块链浏览器,也就是通过网页来查看Fabric区块链的各项信息,主要包含区块、交易、链码、节点信息等等。这些信息主要来源于从Fabric中获取的区块JSON数据。因为网上关于Fabric区块链的各项资料不是很多,故而自己整理了一份简略的资料。同时也希望这份资料能帮助到大家。

    区块结构介绍

    ​ 区块链中的区块结构一般分为区块头和区块体两部分,但是Fabric区块的数据结构分为三大部分:Header(区块头)、Data(区块体,包含所有的交易信息)、MetaData(和当前区块相关的元数据)。区块数据结构如下:

    type Block struct {
        Header *BlockHeader,
        Data *BlockData,
        MetaData *BlockMetaData
    }
    

    ​ 以下三张图来源于网络以及其他博客,第一张是英文版的区块结构图,第二张是中文版的区块结构图,第三张是整个区块数据结构的分解图,仅供大家参考。

    英文版:
    英文版区块结构图

    中文版:
    中文版区块结构图

    区块数据结构:
    区块数据结构图

    下面提供一个区块json数据供大家分析。

    {
    	"header": {
    		"number": "14",
    		"previous_hash": "057935b395be9d6757f61a62eea2fd5c37e7089f3c991a7a9a131aefb255d450",
    		"data_hash": "39ba8f0e54e75980414b301a343f42981ba63f8f105cd72d0e039010843aa920"
    	},
    	"data": {
    		"data": [{
    			"signature": {
    				"type": "Buffer",
    				"data": [48, 68, 2, 32, 53, 212, 86, 141, 134, 170, 144, 75, 132, 68, 229, 103, 122, 240, 21, 201, 139, 191, 77, 193, 50, 192, 31, 9, 15, 187, 65, 112, 239, 36, 205, 182, 2, 32, 98, 217, 249, 62, 93, 24, 158, 247, 180, 186, 122, 237, 141, 54, 228, 20, 218, 234, 24, 246, 118, 205, 134, 187, 250, 198, 255, 79, 129, 159, 164, 220]
    			},
    			"payload": {
    				"header": {
    					"channel_header": {
    						"type": 3,
    						"version": 1,
    						"timestamp": "2021-01-10T12:01:29.673Z",
    						"channel_id": "common",
    						"tx_id": "ff28b4847400b16742245590d908b57a3643e4cc62baf3264dd8751070342314",
    						"epoch": "0",
    						"extension": {
    							"type": "Buffer",
    							"data": [18, 11, 18, 9, 99, 104, 97, 105, 110, 99, 111, 100, 101]
    						},
    						"typeString": "ENDORSER_TRANSACTION"
    					},
    					"signature_header": {
    						"creator": {
    							"Mspid": "org1",
    							"IdBytes": "-----BEGIN CERTIFICATE-----
    MIICcTCCAhegAwIBAgIUbtNpC7qvKr1n5OxgOZiaBRu2VtgwCgYIKoZIzj0EAwIw
    czELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh
    biBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT
    E2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMjEwMTEwMTE1NjAwWhcNMjIwMTEwMTIw
    MTAwWjAvMRwwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMQ8wDQYDVQQDEwZh
    ZG1pbjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASlFdeOOyJRw4/25L62W/KA
    mYpCFsV0CwnezSVEuJL44vC0vqpYUlk1CdR1UO8bkcutgBHXsly+gWyH+GZtSD59X
    o4HMMIHJMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSu
    KGe8YTCjfa0+f+l0Q6Woq+S94zArBgNVHSMEJDAigCA2OH3OJFJR5m75pJceBgqt
    i7zg18hHdCVIjZOnvoUxazBdBggqAwQFBgcIAQRReyJhdHRycyI6eyJoZi5BZmZp
    bGlhdGlvbiI6Im9yZzEiLCJoZi5FbnJvbGxtZW50SUQiOiJhZG1pbjEiLCJoZi5U
    eXBlIjoiY2xpZW50In19MAoGCCqGSM49BAMCA0gAMEUCIQCiNYmu/NaH/pBStOZf
    fa2OcoTmBsJvztFikt/+CGjZ0gIgUJd1Ay3vi1V/WNMoAxr/3uA84qwAP0TRwcQw
    IjyEzZA=
    -----END CERTIFICATE-----
    "
    						},
    						"nonce": {
    							"type": "Buffer",
    							"data": [217, 120, 226, 190, 89, 228, 29, 80, 164, 122, 27, 114, 128, 137, 117, 209, 53, 235, 81, 90, 147, 12, 11, 218]
    						}
    					}
    				},
    				"data": {
    					"actions": [{
    						"header": {
    							"creator": {
    								"Mspid": "org1",
    								"IdBytes": "-----BEGIN CERTIFICATE-----
    MIICcTCCAhegAwIBAgIUbtNpC7qvKr1n5OxgOZiaBRu2VtgwCgYIKoZIzj0EAwIw
    czELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh
    biBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT
    E2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMjEwMTEwMTE1NjAwWhcNMjIwMTEwMTIw
    MTAwWjAvMRwwDQYDVQQLEwZj1bGllbnQwCwYDVQQLEwRvcmcxMQ8wDQYDVQQDEwZh
    ZG1pbjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASlFdeOOyJRw4/25L62W/KA
    mYpCFsV0CwnezSVEuJL44vC0vqpYUlk1CdRUO8bkcutgBHXsly+gWyH+GZtSD59X
    o4HMMIHJMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSu
    KGe8YTCjfa0+f+l0Q6Woq+S94zArBgNVHSMEJDAigCA2OH3OJFJR5m75pJceBgqt
    i7zg18hHdCVIjZOnvoUxazBdBggqAwQFBgcIAQRReyJhdHRycyI6eyJoZi5BZmZp
    bGlhdGlvbiI6Im9yZzEiLCJoZi5FbnJvbGxtZW50SUQiOiJhZG1pbjEiLCJoZi5U
    eXBlIjoiY2xpZW50In19MAoGCCqGSM49BAMCA0gAMEUCIQCiNYmu/NaH/pBStOZf
    fa2OcoTmBsJvztFikt/+CGjZ0gIgUJd1Ay3vi1V/WNMoAxr/3uA84qwAP0TRwcQw
    IjyEzZA=
    -----END CERTIFICATE-----
    "
    							},
    							"nonce": {
    								"type": "Buffer",
    								"data": [217, 120, 226, 190, 89, 228, 29, 80, 164, 122, 27, 114, 128, 137, 117, 209, 53, 235, 81, 90, 147, 12, 11, 218]
    							}
    						},
    						"payload": {
    							"chaincode_proposal_payload": {
    								"input": {
    									"chaincode_spec": {
    										"type": 1,
    										"typeString": "GOLANG",
    										"input": {
    											"args": [{
    												"type": "Buffer",
    												"data": [112, 117, 116]
    											}, {
    												"type": "Buffer",
    												"data": [123, 34, 117, 115, 101, 114, 110, 97, 109, 101, 34, 12, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 34, 97, 99, 116, 105, 111, 110, 34, 58, 34, 115, 116, 111, 114, 101, 34, 44, 34, 109, 111, 110, 101, 121, 34, 58, 34, 50, 48, 48, 34, 125]
    											}],
    											"decorations": {}
    										},
    										"chaincode_id": {
    											"path": "",
    											"name": "chaincode",
    											"version": ""
    										},
    										"timeout": 0
    									}
    								}
    							},
    							"action": {
    								"proposal_response_payload": {
    									"proposal_hash": "932fb85e4b503cfdf2efbd8b9f45df5240da040cacd4c7970659263633c3afc3",
    									"extension": {
    										"results": {
    											"data_model": 0,
    											"ns_rwset": [{
    												"namespace": "chaincode",
    												"rwset": {
    													"reads": [],
    													"range_queries_info": [],
    													"writes": [{
    														"key": "u0000neilu0000storeu0000200u0000",
    														"is_delete": false,
    														"value": "{"username":"neil","action":"store","money":"200"}"
    													}],
    													"metadata_writes": []
    												},
    												"collection_hashed_rwset": []
    											}, {
    												"namespace": "lscc",
    												"rwset": {
    													"reads": [{
    														"key": "chaincode",
    														"version": {
    															"block_num": "5",
    															"tx_num": "0"
    														}
    													}],
    													"range_queries_info": [],
    													"writes": [],
    													"metadata_writes": []
    												},
    												"collection_hashed_rwset": []
    											}]
    										},
    										"events": {
    											"chaincode_id": "",
    											"tx_id": "",
    											"event_name": "",
    											"payload": {
    												"type": "Buffer",
    												"data": []
    											}
    										},
    										"response": {
    											"status": 200,
    											"message": "",
    											"payload": ""
    										},
    										"chaincode_id": {
    											"path": "",
    											"name": "chaincode",
    											"version": "1.0"
    										}
    									}
    								},
    								"endorsements": [{
    									"endorser": {
    										"Mspid": "org1",
    										"IdBytes": "-----BEGIN CERTIFICATE-----
    MIICGTCCAcCgAwIBAgIRAP5eKKLGhfTuzLVPIrPcbTwwCgYIKoZIzj0EAwIwczEL
    MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG
    cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh
    Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjEwMTEwMTA1NTAwWhcNMzEwMTA4MTA1NTAw
    WjBbMQswCQ1YDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN
    U2FuIEZyYW5jaXNjbzEfMB0GA1UEAxMWcGVlcjAub3JnMS5leGFtcGxlLmNvbTBZ
    MBMGByqGSM49AgEGCCqGSM49AwEHA0IABFo3HMBdd10LjYeZwMtR59Byjjp11pd8
    lvWaItRsbrwDvAugdGDZ3KC1FVHLhblCbFp4sDyRDPwJIDnXYIZUpFWjTTBLMA4G
    A1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIDY4fc4kUlHm
    bvmklx4GCq2LvODXyEd0JUiNk6e+hTFrMAoGCCqGSM49BAMCA0cAMEQCIE0PYDKu
    cPYusfTbqem0AwtrqMx/2kUSP9X6/HA5en0lAiB/YePKYDu91h336nNcxal98vNB
    PKyoL+zVCRqL/MYvCQ==
    -----END CERTIFICATE-----
    "
    									},
    									"signature": {
    										"type": "Buffer",
    										"data": [48, 68, 2, 32, 14, 77, 226, 146, 105, 55, 164, 194, 11, 71, 51, 147, 63, 74, 207, 104, 106, 187, 117, 175, 187, 194, 244, 165, 25, 132, 52, 8, 190, 217, 81, 46, 2, 32, 22, 123, 212, 121, 242, 138, 121, 213, 55, 113, 46, 11, 23, 119, 148, 62, 172, 83, 199, 24, 133, 151, 60, 144, 177, 255, 65, 182, 177, 225, 0, 222]
    									}
    								}]
    							}
    						}
    					}]
    				}
    			}
    		}]
    	},
    	"metadata": {
    		"metadata": [{
    				"value": "
    u0002u0003",
    				"signatures": [{
    					"signature_header": {
    						"creator": {
    							"Mspid": "orderer.example.com",
    							"IdBytes": "-----BEGIN CERTIFICATE-----
    MIICDTCCAbOgAwIBAgIRAKZzKwIm1fXv9TbfsLSlJpUwCgYIKoZIzj0EAwIwaTEL
    MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG
    cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt
    cGxlLmNvbTAeFw0yMTAxMTAxMDU1MDBaFw0zMTAxMDgxMDU1MDBaMFgxCzAJBgNV
    BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
    c2NvMRwwGgYDVQQDExNvcmRlcmVyLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYI
    KoZIzj0DAQcDQgAEYh4Kui3YB02J9uUjX7+nn+l5ZT6DFWXjhB6X3fjUjowvySzf
    fqn4s95o6qc0jYCaiC47cfUlJKvlPsBQX8XzyKNNMEswDgYDVR0PAQH/BAQDAgeA
    MAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAg1HCS4tEmcKJX2ttGPCY4mw2VSA5lP
    kVeYrnAulge4U0gwCgYIKoZIzj0EAwIDSAAwRQIhAJQom8NqJdKvG3uYkbcuFRbx
    UxVltC+/OdqLZ2ByCVWzAiAv0mGOCKPogI1QZdowWXsHtS9bZw3ymtwVToLXI+zP
    zg==
    -----END CERTIFICATE-----
    "
    						},
    						"nonce": {
    							"type": "Buffer",
    							"data": [32, 137, 232, 144, 240, 168, 86, 24, 236, 47, 151, 23, 182, 223, 129, 176, 92, 209, 74, 104, 78, 83, 86, 125]
    						}
    					},
    					"signature": {
    						"type": "Buffer",
    						"data": [48, 69, 2, 33, 0, 159, 188, 112, 227, 84, 54, 225, 211, 227, 157, 120, 16, 218, 64, 137, 137, 94, 9, 217, 83, 249, 31, 24, 66, 75, 78, 14, 219, 182, 220, 75, 223, 2, 32, 106, 39, 131, 38, 77, 200, 222, 147, 195, 62, 173, 63, 254, 133, 174, 73, 161, 75, 40, 248, 173, 62, 83, 56, 141, 99, 162, 94, 181, 72, 68, 188]
    					}
    				}]
    			}, {
    				"value": {
    					"index": "3"
    				},
    				"signatures": []
    			},
    			[0]
    		]
    	}
    }
    

    大家可以通过在线json解析工具对json数据进行层次解析后再查看,这样会更加方便。我下面的对具体数据结构以及字段的分析和讲解也会依赖于这个解析工具的部分截图。
    整个区块结构如下图所示:

    区块结构截图

    Block Header部分

    区块头包含三个字段,number(当前区块号)、previous_hash前一个区块头哈希)、data_hash当前区块的数据哈希)。

    值得一提的是data_hash并非当前区块哈希,只是当前区块数据体的哈希值,大家在呈现区块数据时要注意这一点。

    type BlockHeader struct {
    	    Number   	    uint64
    	    PreviousHash    []byte
    	    DataHash        []byte
    }
    

    Block Data部分

    区块体中只有一个data字段,data字段对应的属性值中也只有一个data字段。这个data字段对应是Envelope数据,即一种展示交易信息的数据结构,具体看下面的JSON信息截图。

    Envelope数据

    此数据类型主要用于存储区块中的交易信息。交易信息包括两个字段,signature(交易发送者的签名)、payload(数据载荷)(具体看上方截图和下面的数据类型)。signature是一个buffer数组类型的签名数据,并无其他可用信息,故下面主要分析payload数据载荷字段部分。

    type Envelope struct {
         Payload   []byte 
         Signature []byte
    }
    

    Envelope.payload字段

    Palyload中包含了HeaderData两个字段,其中Header中又包含了ChannelHeaderSignatureHeader。具体看下面的数据结构及JSON信息截图。

    type Payload struct {
         Header *Header 
         Data   []byte 
    }
    
    type Header struct {
        ChannelHeader *ChannelHeader,
        SignatureHeader *SignatureHeader
    }
    
    1. channelHeader

      channelHeader数据包括type(头类型)、version(版本)、timestamp(时间戳,即交易产生时间)、channel_id(通道id)、tx_id(交易id,即交易哈希)、epoch(时期,该字段当前未使用)、extension(可附加的扩展)、typeString(类型字符串,主要包括MESSAGE、CONFIG(表示当前块为区块链配置块)、CONFIG_UPDATE、ENDORSER_TRANSACTION(表示当前块为区块链正常交易块,大多数区块都为此类型)、ORDERER_TRANSACTION、DELIVER_SEEK_INFO、CHAINCODE_PACKAGE等类型)。

    2. SignatureHeader

      SignatureHeader数据包括creator(交易创建者的信息,具体的peer节点信息好像可以通过解析证书来实现,但我还未实现,有已经实现的朋友可以在下面留言告诉我,谢谢大家!)、nonce(随机数),其中creator包括创建者的证书和Mspid(成员服务提供者的身份证书)。

    Envelope.payload.data字段

    data包含一个actions字段,对应的值是一个action数组,每个数组又包含两部分,headerpayloadheader结构都与上面解析过的signature_header相同(目前未搞懂fabric设计者的做此举目的),下面主要讨论payload字段部分。

    Envelope.payload.data.actions.payload字段

    payload字段包括chaincode_proposal_payload(背书提案时调用链码的信息)和action字段,action字段又分为proposal_response_payload(提案时响应信息,也就是是不是提案成功了,成功了返回状态码为200)及endorsements(背书节点信息)字段。

    ​ 下面具体分析chaincode_proposal_payloadproposal_response_payload两个字段:

    1. chaincode_proposal_payload

      chaincode_proposal_payload具体结构参见上面的截图。chaincode_proposal_payload含有一个input字段,该字段中又包含chaincode_spec字段。chaincode_spec字段包含链码信息和调用期间使用的参数。type是链码类型,typeString是链码使用的语言,input是使用链码的参数,decoration字段含义未知(中文含义为装饰物),但对应的值一般为空。chaincode_id字段包含链码的路径、名称和版本信息。

      最后具体说一下input字段,它包含一个args数组,数组中含有两个元素,第一个元素是调用链码的函数名,第二个是函数参数,都为buffer数组,大家可以通过将buffer转换为string来获取到原数据。

    2. proposal_response_payload

      proposal_response_payload字段包含链码模拟执行结果对KV类型状态数据库的读写集,包括proposal_hash(背书哈希值)、results(背书结果)、response(背书响应)、chaincode_id(链码信息)。results包含data_model(数据模型,但含义未知,一般为0)、ns_rwset(读写集数组)。ns_rwset包含namespacerwsetrwset包含read(读集)、writes(写集,包含键、值、删除标志)、range_queries_info(范围查询信息)、metadata_writesresponse包含status(响应状态值)、message(响应信息)、payload(返回的数据,一般是查询时采用此字段)。

    3. endorsements

      该字段包含背书者信息数组,每个背书者包含MspId、证书和此次背书的签名signature。此结构比较简单,就不展开具体分析。大家有需要可以自己通过在线json解析工具进行查看。

    Block MetaData部分

    元数据:和当前区块相关的元数据,用于描述Data的相关信息,包含排序节点的MspId、证书和随机数,以及签名。value的index属性及一些其他的字段含义也不太清楚,但是这些信息大多是空值并且与区块链相关状态信息并不相关,故并未仔细分析。数据结构如下:

    type BlockMetadata struct {
        Metadata   [][]byte 
    }
    

    结语

    上面的信息基本可以满足做区块链浏览器的需要了,但是还是缺少一部分信息,比如区块产生时间等等。目前我是以区块中最后一个交易的产生时间来作为区块产生时间的,这在严格意义上来说是不对,因为产生最后一个交易后需要经过Orderer节点的排序、打包等操作才能产生区块。

    最后衷心希望上述信息能给大家带来帮助!

    本博客中部分信息参考于:https://blog.csdn.net/alextan_/article/details/110826476
    在此感谢此博客的作者!

    type ChannelHeader struct {
       Type      int32
       Version   int32
       Timestamp *google_protobuf.Timestamp
       ChannelId string
       TxId      string
       Epoch     uint64
       Extension []byte
    }

    /*

    Type: It denotes the transaction type used. ["MESSAGE", "CONFIG", "CONFIG_UPDATE", "ENDORSER_TRANSACTION",
     "ORDERER_TRANSACTION", "DELIVER_SEEK_INFO", "CHAINCODE_PACKAGE"]

    Version: The version number for protobuf used for serialization/de-serialization of the structures.

    ChannelId: Channel name for the network

    TxId: The transaction id for processing the transaction

    Epoch: The fields are currently unused.
     
    Extension: It contents Chaincode information that marshalled the ChaincodeHeaderExtension structure.

    */

    https://blog.csdn.net/AlexTan_/article/details/110826476

    type ChaincodeHeaderExtension struct {
    	// The PayloadVisibility field controls to what extent the Proposal's payload
    	// (recall that for the type CHAINCODE, it is ChaincodeProposalPayload
    	// message) field will be visible in the final transaction and in the ledger.
    	// Ideally, it would be configurable, supporting at least 3 main visibility
    	// modes:
    	// 1. all bytes of the payload are visible;
    	// 2. only a hash of the payload is visible;
    	// 3. nothing is visible.
    	// Notice that the visibility function may be potentially part of the ESCC.
    	// In that case it overrides PayloadVisibility field.  Finally notice that
    	// this field impacts the content of ProposalResponsePayload.proposalHash.
    	PayloadVisibility []byte `protobuf:"bytes,1,opt,name=payload_visibility,json=payloadVisibility,proto3" json:"payload_visibility,omitempty"`
    	// The ID of the chaincode to target.
    	ChaincodeId          *ChaincodeID `protobuf:"bytes,2,opt,name=chaincode_id,json=chaincodeId,proto3" json:"chaincode_id,omitempty"`
    	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
    	XXX_unrecognized     []byte       `json:"-"`
    	XXX_sizecache        int32        `json:"-"`
    }



    https://pkg.go.dev/github.com/hyperledger/fabric/protos/peer#ChaincodeHeaderExtension

    Fabric 2.2底层结构设计分析


    https://www.cnblogs.com/veraland/p/13900791.html

  • 相关阅读:
    多线程面试题
    Tcpdump MySQL Query
    Gossip和Redis集群原理
    mysql-table_open_cache_file_limits/
    introducing-backup-locks-percona-server-2/
    MySQL 一致性读 深入研究
    how-to-configure-mysql-masterslave-replication-with-mha-automatic-failover/
    mysqlOOM
    mysql 线程池
    Linux performance monitor tool
  • 原文地址:https://www.cnblogs.com/jiftle/p/15217345.html
Copyright © 2020-2023  润新知