摘要:在 Corda 中的所有資產(chǎn)默認(rèn)是只有交易的參與方所擁有的兄世,那么在 Corda 中可以將一筆交易信息分享給未參與該筆交易的節(jié)點(diǎn)么可婶?答案是可以的映跟,本文就在 Corda 中完成了一個(gè)簡易版的廣播實(shí)現(xiàn)畅卓。
Corda 是一個(gè)基于聯(lián)盟鏈的分布式賬本技術(shù)尉咕,在 Corda 中绊袋,“隱私”是其核心的設(shè)計(jì)毕匀。因此,如果 A 向 B 買了一輛車癌别,那么在鏈上只有 A (Party) 和 B(Party) 能夠看到在這輛車 (State) 之間發(fā)生的交易皂岔,其他節(jié)點(diǎn)都是不知道這筆交易信息的。但是展姐,在現(xiàn)實(shí)生活中躁垛,很多情況下,都會(huì)有監(jiān)管機(jī)構(gòu)的存在圾笨,我們所編寫的 Dapp 還需要滿足監(jiān)管的要求教馆。例如,在 A 向 B 買了一輛車這個(gè)例子中擂达,就還需要向車管所進(jìn)行登記土铺,以讓車管所知道這輛車的信息及其所屬情況,以便將來關(guān)于這輛車發(fā)生的任何問題車管所都能知道它的責(zé)任人是誰板鬓。因此悲敷,在這個(gè)場景中我們還需要將 A 向 B 買車的這筆交易信息共享給第三方,也就是車管所俭令。
(如圖為 Corda 的賬本模型后德,A 節(jié)點(diǎn) 和 B 節(jié)點(diǎn) 之間的交易信息,只會(huì)在 A 和 B 各自的賬本中是可見的抄腔。)
在默認(rèn)情況下瓢湃,Corda 是不會(huì)將交易信息共享給與該筆交易無關(guān)的節(jié)點(diǎn)的,這也是 Corda 和其他 DLT 技術(shù)相比很大的特點(diǎn)妓柜。但這并不意味著 Corda 就沒有能力實(shí)現(xiàn)這件事了箱季,實(shí)際上,Corda 可以在網(wǎng)絡(luò)中的節(jié)點(diǎn)之間發(fā)送任何內(nèi)容棍掐。Corda 的這個(gè)能力也在其官方文檔中有所提及藏雏。本文就在此基礎(chǔ)上實(shí)現(xiàn) Corda 中的廣播。
首先,還是先以上面提到的場景為例掘殴,當(dāng) A 向 B 買了一輛車后赚瘦,將該交易信息共享給車管所。我們需要在 BuyVehicleFlow
的最后奏寨,調(diào)用 subFlow
將交易信息共享給車管所起意。
object BuyVehicleFlow {
@InitiatingFlow
@StartableByRPC
class Initiator(
private val vin: String
) {
@Suspendable
override fun call(): SignedTransaction {
...... // 省略無關(guān)邏輯
val finalTx = subFlow(FinalityFlow(allSignedTransaction))
val vehicleAdministrator = serviceHub.identityService.partiesFromName("VehicleAdministrator", false).single()
subFlow(ReportToVehicleAdministratorFlow(vehicleAdministrator, finalTx))
return finalTx
}
}
這里 ReportToVehicleAdministratorFlow
就是為了向車管所 (vehicleAdministrator
) 共享該筆交易信息的。那么這個(gè) Flow 的具體實(shí)現(xiàn)是什么呢病瞳。
@InitiatingFlow
class ReportToVehicleAdministratorFlow(
private val regulator: Party,
private val finalTx: SignedTransaction
) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
subFlow(SendTransactionFlow(initiateFlow(regulator), finalTx))
}
}
稍微看下這個(gè) flow 就會(huì)發(fā)現(xiàn)揽咕,Corda 幾乎做了所有的事情,我們只用告訴 Corda 要向哪個(gè)節(jié)點(diǎn) (regulator
) 共享哪筆交易的信息 (finalTx
) 就好了套菜。在該 flow 中我們和 regulator
建立了一個(gè) Session 連接亲善,并調(diào)用了 SendTransactionFlow
發(fā)送交易信息。因此逗柴,我們還需要相應(yīng)的響應(yīng)者 (responder
) 來接收并處理 (ReceiveTransactionFlow
) 該交易蛹头。如下:
@InitiatedBy(ReportToVehicleAdministratorFlow::class)
class ReceiveVehicleAdministratorReportFlow(
private val otherSideSession: FlowSession
) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
subFlow(ReceiveTransactionFlow(
otherSideSession = otherSideSession,
checkSufficientSignatures = true,
statesToRecord = StatesToRecord.ALL_VISIBLE
))
}
}
ReceiveTransactionFlow
和 SendTransactionFlow
是相對應(yīng)的,它接收并保存發(fā)送給它的交易信息戏溺。statesToRecord
屬性確定該筆交易中哪些資產(chǎn) (state
) 需要被記錄在保險(xiǎn)庫 (Vault
) 中渣蜗,在該例子中我們希望車管所記錄該筆交易中所有的資產(chǎn)信息,所以我們將 statesToRecord
設(shè)置為 StatesToRecord.ALL_VISIBLE
旷祸。此外耕拷,根據(jù)不同的情景,我們也可以設(shè)置響應(yīng)者存儲(chǔ)不同的資產(chǎn)信息肋僧,只需將其設(shè)置為 StatesToRecord.ONLY_RELEVANT
甚至是 StatesToRecord.NONE
即可斑胜。而對于 checkSufficientSignatures
屬性,它的目的則是檢查分享的這一筆交易中是否所有的參與方都進(jìn)行了簽名嫌吠,一般都是需要檢查的止潘,所有就設(shè)置為默認(rèn)的 true
就好。
但其實(shí)辫诅,到此為止還只是實(shí)現(xiàn)了共享某一筆交易信息給某一個(gè)節(jié)點(diǎn)凭戴,要先實(shí)現(xiàn)廣播,至少要先能夠同時(shí)分享交易給多個(gè)節(jié)點(diǎn)吧炕矮,如下:
@InitiatingFlow
class BroadcastTransactionFlow(
private val recipients: List<Party>,
private val stx: SignedTransaction
) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
for (recipient in recipients) {
val session = initiateFlow(recipient)
subFlow(SendTransactionFlow(session, stx))
}
}
}
@InitiatedBy(BroadcastTransactionFlow::class)
class BroadcastTransactionResponder(private val session: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
subFlow(ReceiveTransactionFlow(session, statesToRecord = StatesToRecord.ALL_VISIBLE))
}
}
稍微看一下 BroadcastTransactionFlow
就會(huì)發(fā)現(xiàn)么夫,我們其實(shí)并沒有改多少代碼,只是將一個(gè) regulator
改為了 recipients: List<Party>
肤视,這樣就可以循環(huán)分享某一筆交易信息給指定的一些節(jié)點(diǎn)了档痪。再進(jìn)一步,能不能分享給全網(wǎng)所有的節(jié)點(diǎn)呢邢滑,其實(shí)也是可以的腐螟,如下:
subFlow(FinalityFlow(stx, sessions)).also {
// sends to everynode in the corda network
val broadcastToParties =
serviceHub.networkMapCache.allNodes.map {
node -> node.legalIdentities.first()
} - message.recipient - message.sender
subFlow(BroadcastTransactionFlow(broadcastToParties, it))
}
可以看到這里我們只是從 serviceHub
中找到所有的節(jié)點(diǎn) allNodes
,減去這筆交易的發(fā)送者 (message.sender
) 和接受者 (message.recipient
) 不用發(fā)送之外,均廣播給全網(wǎng)中其他的所有節(jié)點(diǎn)乐纸。
到了這里衬廷,我們已經(jīng)完成了一個(gè)簡易版的 Corda 廣播實(shí)現(xiàn)。但在這里我們還需要額外注意一個(gè)問題汽绢,我們所廣播到的每一個(gè)節(jié)點(diǎn)都是有權(quán)利使用我們分享給它的這筆交易中的資產(chǎn)的吗跋,所以我們在做與此類問題相關(guān)的設(shè)計(jì)時(shí),即需要共享交易信息給非參與交易方時(shí)宁昭,需要額外考慮到這一點(diǎn)跌宛,是否需要加入必要的資產(chǎn)保護(hù)措施。盡管 Corda 是十分靈活的久窟,但我們一定要對這種靈活性加以控制秩冈,以防出現(xiàn)我們所不期望的結(jié)果。
參考文檔:
· https://docs.corda.net/tutorial-observer-nodes.html
· https://docs.corda.net/key-concepts-ledger.html