区块链基础知识系列第5课 Hyperledger fabric1.0网络中transaction产生以及流转过程
一、發起transaction
當client想要發起一個transaction時,它會首先發送一個PROPOSE消息到它選擇的一組endorser節點,消息模式有以下兩種,節點可以自由選擇(可能有更多種):
- client首先將<PROPOSE, tx>消息發送給某個單個的endorser,該endorser會產生相應的版本依賴(anchor),以供client稍后作為PROPOSE消息的參數發送給其它endorser節點;
- client直接將<PROPOSE, tx>消息發送給它選擇的這一組endorser節點。
PROPOSE消息的格式為<PROPOSE, tx, [anchor]>,其中anchor參數為可選,表示讀版本依賴,通常是指key-version對,必選的tx參數代表transaction的內容,包括發起該transaction的client唯一標識符clientID,指向transaction所涉及chaincode的chaincodeID,包含所發起的transaction本身的txPayload,一個由client維護的單調遞增的整數timestamp以及client的簽名clientSig。其中txPayload根據transaction的不同而分成兩種不同的類型:
- 喚醒事務(invoke transaction):txPayload=<operation, metadata>,其中operation表示chaincode操作以及傳遞給chaincode的參數,metadata表示與調用相關的屬性;
- 部署事務(deploy transaction):txPayload=<source, metadata, policies>,其中source表示chaincode的源碼,metadata表示與chaincode和應用相關的屬性,policies表示與chaincode相關的策略,包括備書策略等。
二、模擬transaction
- 當endorser接收到一個PROPOSE消息后,它會首先驗證其中的clientSig,通過驗證后會對該transaction進行模擬。如果PROPOSE消息中包含anchor字段,endorser會根據anchor中的key獲取當前本地狀態中對應該key值的version值,從而生成readset(讀集),如當前endorser本地保存的狀態為s,對任意一個transaction中的key k,(k, s(k).version)就會被添加到讀集中,例如s=(k1,1,v1), (k2,1,v2), (k3,1,v3), (k4,1,v4), (k5,1,v5),anchor中包含的key值為k1, k2,則readset={k1: v1, k2: v2},只有在anchor與readset匹配即完全相等時,endorser才會模擬該transaction。模擬transaction基于endorser本地保存的狀態副本,調用對應的chaincode來試探性地執行該transaction,從而生成一個被稱為writeset(寫集)的狀態更新,如任意一個transaction中的key k對應的值被修改成為v,則(k, v)就會被加入到寫集中去。
- endorser內部轉發tran-proposal到它備書transaction的邏輯部分——備書邏輯,默認情況下,備書邏輯會接受該tran-proposal并給它加上簽名,當然,也可以通過任意函數來達成是否備書的決定。
- 如果endorser決定給一個transaction備書,它會給提交的client發送一個<TRANSACTION-ENDORSED, tid, tran-proposal,epSig>消息,其中tid是對PROPOSE消息中的tx進行哈希運算生成的,用來指向某個transaction,epSig是備書節點的簽名,tran-proposal = (epID,tid,chaincodeID,txContentBlob,readset,writeset),其中epID是備書節點的節點ID,txContentBlob是chaincode/transaction的具體信息,作為tx的某種形式進行使用,如txContentBlob = tx.txPayload。
- 如果endorser拒絕給一個transaction備書,它只需要直接給發起該transaction的client發送(TRANSACTION-INVALID, tid, REJECTED)消息。
- 整個過程中,endorser并不會修改它本地狀態,只是對transaction進行模擬。
三、接收備書消息
- 發起transaction的client發出PROPOSE消息后會一直等待接收備書消息,是否備書成功取決于當前的備書策略,如當前client選擇的備書節點集合為{Alice, Bob, Charlie, Dave, Eve, Frank, George},當前的備書策略為有5個備書節點通過即通過,則client在收集到5個TRANSACTION-ENDORSED消息后即認為當前transaction備書成功,接收到的TRANSACTION-ENDORSED消息集被稱為endorsement。
- 之后,client會發送broadcast(blob)(此時blob即為endorsement)消息到Orderer system channel中,通過orderer來將該transaction同步到整個channel內的節點中。orderer會將一段時間內的所有transaction進行排序并打包成block然后通過deliver(seqno, prevhash, blob)消息將block發送給所有節點,其中seqno表示一個非負的序號,prevhash表示最近一次block的哈希值,blob表示一個block區塊。
四、同步transaction
- 當節點收到一個deliver消息時,它會根據chaincode的策略來檢查blob.endorsement是否有效,再檢查readset是否與當前節點的本地狀態一致。
- 如果所有的驗證都通過后,transaction被視為有效的。此時,節點將PeerLedger的位掩碼中將該transaction標記為1,通過blob.endorsement.tran-proposal.writeset 修改本地的帳本狀態。
- 如果blob.endorsement的備書策略驗證失敗,則該transaction被認為是無效的,節點在PeerLedger的位掩碼中將該transaction標記為0。重要的是要注意,無效的交易雖然會被放入區塊中,但不會改變本地的帳本狀態。
通過一個例子來解釋節點如何通過讀寫集來判斷transaction的有效性的:
假設當前本地狀態為s=(k1,1,v1), (k2,1,v2), (k3,1,v3), (k4,1,v4), (k5,1,v5),節點接收到一個包含5個transaction的區塊,分別為T1, T2, T3, T4和T5
T1?->?Write(k1,?v1'), Write(k2, v2'),T2?->?Read(k1),?Write(k3,?v3'),T3?->?Write(k2,?v2''),T4?->?Write(k2,?v2'''), read(k2),T5 -> Write(k6, v6'), read(k5),
- 由于T1沒有執行任何的讀操作,所以被判定為有效,且k1和k1對應的值分別被寫為v1'和v2',
- T2因為讀了已經被修改過的K1的值而被判定為無效,因此k3的值并不發生改變,
- T3也沒有執行任何讀操作,所以有效,k2的值被修改為v2'',
- T4也因為嘗試讀已經被修改過的k2的值而判定為無效,
- T5讀的k5并沒有發生任何修改而被判定為有效,并將k6的值寫為v6'。
總結
以上是生活随笔為你收集整理的区块链基础知识系列第5课 Hyperledger fabric1.0网络中transaction产生以及流转过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 区块链基础知识系列 第四课Hyperle
- 下一篇: Kafka基础知识入门