Hyperledger Fabric 區塊結構解析

Hyperledger Fabric 區塊結構解析

前言

​ 最近在搞區塊鏈瀏覽器,也就是經過網頁來查看Fabric區塊鏈的各項信息,主要包含區塊、交易、鏈碼、節點信息等等。這些信息主要來源於從Fabric中獲取的區塊JSON數據。由於網上關於Fabric區塊鏈的各項資料不是不少,故而本身整理了一份簡略的資料。同時也但願這份資料能幫助到你們。數據庫

區塊結構介紹

​ 區塊鏈中的區塊結構通常分爲區塊頭和區塊體兩部分,可是Fabric區塊的數據結構分爲三大部分:Header(區塊頭)、Data(區塊體,包含全部的交易信息)、MetaData(和當前區塊相關的元數據)。區塊數據結構以下:json

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-----\nMIICcTCCAhegAwIBAgIUbtNpC7qvKr1n5OxgOZiaBRu2VtgwCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMjEwMTEwMTE1NjAwWhcNMjIwMTEwMTIw\nMTAwWjAvMRwwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMQ8wDQYDVQQDEwZh\nZG1pbjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASlFdeOOyJRw4/25L62W/KA\nmYpCFsV0CwnezSVEuJL44vC0vqpYUlk1CdR1UO8bkcutgBHXsly+gWyH+GZtSD59X\no4HMMIHJMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSu\nKGe8YTCjfa0+f+l0Q6Woq+S94zArBgNVHSMEJDAigCA2OH3OJFJR5m75pJceBgqt\ni7zg18hHdCVIjZOnvoUxazBdBggqAwQFBgcIAQRReyJhdHRycyI6eyJoZi5BZmZp\nbGlhdGlvbiI6Im9yZzEiLCJoZi5FbnJvbGxtZW50SUQiOiJhZG1pbjEiLCJoZi5U\neXBlIjoiY2xpZW50In19MAoGCCqGSM49BAMCA0gAMEUCIQCiNYmu/NaH/pBStOZf\nfa2OcoTmBsJvztFikt/+CGjZ0gIgUJd1Ay3vi1V/WNMoAxr/3uA84qwAP0TRwcQw\nIjyEzZA=\n-----END CERTIFICATE-----\n"
						},
						"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-----\nMIICcTCCAhegAwIBAgIUbtNpC7qvKr1n5OxgOZiaBRu2VtgwCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMjEwMTEwMTE1NjAwWhcNMjIwMTEwMTIw\nMTAwWjAvMRwwDQYDVQQLEwZj1bGllbnQwCwYDVQQLEwRvcmcxMQ8wDQYDVQQDEwZh\nZG1pbjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASlFdeOOyJRw4/25L62W/KA\nmYpCFsV0CwnezSVEuJL44vC0vqpYUlk1CdRUO8bkcutgBHXsly+gWyH+GZtSD59X\no4HMMIHJMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSu\nKGe8YTCjfa0+f+l0Q6Woq+S94zArBgNVHSMEJDAigCA2OH3OJFJR5m75pJceBgqt\ni7zg18hHdCVIjZOnvoUxazBdBggqAwQFBgcIAQRReyJhdHRycyI6eyJoZi5BZmZp\nbGlhdGlvbiI6Im9yZzEiLCJoZi5FbnJvbGxtZW50SUQiOiJhZG1pbjEiLCJoZi5U\neXBlIjoiY2xpZW50In19MAoGCCqGSM49BAMCA0gAMEUCIQCiNYmu/NaH/pBStOZf\nfa2OcoTmBsJvztFikt/+CGjZ0gIgUJd1Ay3vi1V/WNMoAxr/3uA84qwAP0TRwcQw\nIjyEzZA=\n-----END CERTIFICATE-----\n"
							},
							"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": "\u0000neil\u0000store\u0000200\u0000",
														"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-----\nMIICGTCCAcCgAwIBAgIRAP5eKKLGhfTuzLVPIrPcbTwwCgYIKoZIzj0EAwIwczEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjEwMTEwMTA1NTAwWhcNMzEwMTA4MTA1NTAw\nWjBbMQswCQ1YDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN\nU2FuIEZyYW5jaXNjbzEfMB0GA1UEAxMWcGVlcjAub3JnMS5leGFtcGxlLmNvbTBZ\nMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFo3HMBdd10LjYeZwMtR59Byjjp11pd8\nlvWaItRsbrwDvAugdGDZ3KC1FVHLhblCbFp4sDyRDPwJIDnXYIZUpFWjTTBLMA4G\nA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIDY4fc4kUlHm\nbvmklx4GCq2LvODXyEd0JUiNk6e+hTFrMAoGCCqGSM49BAMCA0cAMEQCIE0PYDKu\ncPYusfTbqem0AwtrqMx/2kUSP9X6/HA5en0lAiB/YePKYDu91h336nNcxal98vNB\nPKyoL+zVCRqL/MYvCQ==\n-----END CERTIFICATE-----\n"
									},
									"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": "\n\u0002\b\u0003",
				"signatures": [{
					"signature_header": {
						"creator": {
							"Mspid": "orderer.example.com",
							"IdBytes": "-----BEGIN CERTIFICATE-----\nMIICDTCCAbOgAwIBAgIRAKZzKwIm1fXv9TbfsLSlJpUwCgYIKoZIzj0EAwIwaTEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt\ncGxlLmNvbTAeFw0yMTAxMTAxMDU1MDBaFw0zMTAxMDgxMDU1MDBaMFgxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp\nc2NvMRwwGgYDVQQDExNvcmRlcmVyLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYI\nKoZIzj0DAQcDQgAEYh4Kui3YB02J9uUjX7+nn+l5ZT6DFWXjhB6X3fjUjowvySzf\nfqn4s95o6qc0jYCaiC47cfUlJKvlPsBQX8XzyKNNMEswDgYDVR0PAQH/BAQDAgeA\nMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAg1HCS4tEmcKJX2ttGPCY4mw2VSA5lP\nkVeYrnAulge4U0gwCgYIKoZIzj0EAwIDSAAwRQIhAJQom8NqJdKvG3uYkbcuFRbx\nUxVltC+/OdqLZ2ByCVWzAiAv0mGOCKPogI1QZdowWXsHtS9bZw3ymtwVToLXI+zP\nzg==\n-----END CERTIFICATE-----\n"
						},
						"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並不是當前區塊哈希,只是當前區塊數據體的哈希值,你們在呈現區塊數據時要注意這一點。ui

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 在此感謝此博客的做者!

相關文章
相關標籤/搜索