日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

oracle连接外部数据库_使用Oracle验证外部数据

發布時間:2023/12/3 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oracle连接外部数据库_使用Oracle验证外部数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

oracle連接外部數據庫

我經常在Corda Slack頻道中閑逛,并盡可能回答問題。 我嘗試回答的合理數量的問題與Oracle有關。 更具體地說,何時使用。 我覺得我可以回答,“當您需要驗證可能經常更改的外部數據時使用Oracle”。 我大概在某個時候寫了一個類似的答案。 我沒辦法做的...告訴某人如何實施。 因此,要糾正這一點。 我寫這篇文章的目的是學習如何實現自己,并與您和我未來的自我分享這些知識。

何時使用Oracle

讓我們從擴展何時使用Oracle開始。 就像我剛才提到的那樣,當您需要驗證可能經常更改的外部數據時,應該使用Oracle。 這可能是諸如匯率,股票價格之類的數據,甚至是我的博客當前處于上升還是下降狀態(盡管我還沒有看到它下降過!)。 我認為經常性部分在這里很重要。 如果數據很少更改,則針對包含與Oracle自己檢索的相同類型的值的附件驗證某些數據可能是可行的。 這就是為什么我認為僅應由Oracle來驗證匯率等數據的原因。 話雖如此,它實際上取決于您的特定用例。

如何使用Oracle

Oracle如何進行此驗證? 好吧,這取決于您。 但是,它可能會遵循以下步驟:

  • 從節點接收數據
  • 檢索外部數據
  • 根據外部數據驗證接收到的數據
  • 提供交易簽名

這些是我認為大多數Oracle實現將包含的步驟。 可以添加更多步驟,并且完成的驗證可以與用例要求一樣復雜或簡單。 盡管可以增加更多的步驟,但我真的懷疑,排除上面顯示的任何步驟的Oracle是否會有很多用途。

上面顯示的所有步驟僅從Oracle的角度顯示了該過程。 還有很多事情要做,所以我認為一個好的圖表可以幫助我們。 它還將繼續介紹我將在本文中使用的示例。


序列圖顯示了與Oracle交互的過程

這些步驟中有很多是通用步驟,無論您將其放在何處,都將執行這些步驟。 在本節中,我將擴展并顯示實現圖中所示流程所涉及的代碼。 因此,值得一看。。。我也花了很多時間使它看起來不錯,所以請看一下!!

哦,在我繼續之前還有一點。 我想強調一下將時序圖組合起來對Corda Flows建模有多大幫助。 它確實突出顯示了參與人員,需要進行多少次網絡跳躍以及每個參與者進行了多少工作。 此外,它們是向只對您正在設計和/或實現的更高層次的流程感興趣的人解釋發生了什么的好方法。

客戶端/不是Oracle端

如前所述,這里的某些代碼是通用代碼,您很可能會將其放入編寫的任何Flow中。 我已經展示了所有內容,因此對于正在發生的事情沒有任何歧義,但是我將僅針對需要突出顯示的點進行擴展,因為它們包含特定于與Oracle交互的代碼。

@InitiatingFlow @StartableByRPC class GiveAwayStockFlow(private val symbol: String,private val amount: Long,private val recipient: String ) :FlowLogic<SignedTransaction>() {@Suspendableoverride fun call(): SignedTransaction {val recipientParty = party()val oracle = oracle()val transaction =collectRecipientSignature(verifyAndSign(transaction(recipientParty, oracle)),recipientParty)val allSignedTransaction = collectOracleSignature(transaction, oracle)return subFlow(FinalityFlow(allSignedTransaction))}private fun party(): Party =serviceHub.networkMapCache.getPeerByLegalName(CordaX500Name.parse(recipient))?: throw IllegalArgumentException("Party does not exist")private fun oracle(): Party = serviceHub.networkMapCache.getPeerByLegalName(CordaX500Name("Oracle","London","GB"))?: throw IllegalArgumentException("Oracle does not exist")@Suspendableprivate fun collectRecipientSignature(transaction: SignedTransaction,party: Party): SignedTransaction {val signature = subFlow(CollectSignatureFlow(transaction,initiateFlow(party),party.owningKey)).single()return transaction.withAdditionalSignature(signature)}private fun verifyAndSign(transaction: TransactionBuilder): SignedTransaction {transaction.verify(serviceHub)return serviceHub.signInitialTransaction(transaction)}private fun transaction(recipientParty: Party, oracle: Party): TransactionBuilder =TransactionBuilder(notary()).apply {val priceOfStock = priceOfStock()addOutputState(state(recipientParty, priceOfStock), StockContract.CONTRACT_ID)addCommand(GiveAway(symbol, priceOfStock),listOf(recipientParty, oracle).map(Party::owningKey))}private fun priceOfStock(): Double =serviceHub.cordaService(StockRetriever::class.java).getCurrent(symbol).priceprivate fun state(party: Party, priceOfStock: Double): StockGiftState =StockGiftState(symbol = symbol,amount = amount,price = priceOfStock * amount,recipient = party)private fun notary(): Party = serviceHub.networkMapCache.notaryIdentities.first()@Suspendableprivate fun collectOracleSignature(transaction: SignedTransaction,oracle: Party): SignedTransaction {val filtered = filteredTransaction(transaction, oracle)val signature = subFlow(CollectOracleStockPriceSignatureFlow(oracle, filtered))return transaction.withAdditionalSignature(signature)}private fun filteredTransaction(transaction: SignedTransaction,oracle: Party): FilteredTransaction =transaction.buildFilteredTransaction(Predicate {when (it) {is Command<*> -> oracle.owningKey in it.signers && it.value is GiveAwayelse -> false}}) }@InitiatedBy(GiveAwayStockFlow::class) class SendMessageResponder(val session: FlowSession) : FlowLogic<Unit>() {@Suspendableoverride fun call() {subFlow(object : SignTransactionFlow(session) {override fun checkTransaction(stx: SignedTransaction) {}})} }

首先,讓我們看一下如何構建事務:

private fun transaction(recipientParty: Party, oracle: Party): TransactionBuilder =TransactionBuilder(notary()).apply {val priceOfStock = priceOfStock()addOutputState(state(recipientParty, priceOfStock), StockContract.CONTRACT_ID)addCommand(GiveAway(symbol, priceOfStock),listOf(recipientParty, oracle).map(Party::owningKey))}private fun priceOfStock(): Double =serviceHub.cordaService(StockRetriever::class.java).getCurrent(symbol).price

這與我創建不涉及Oracle的事務的方式沒有太大不同。 僅有的兩個區別是,從外部來源(隱藏在StockRetriever服務內部)檢索股票價格,并在Command中包括Oracle的簽名。 這些代碼添加與使用Oracle的原因一致。 外部數據包含在事務中,Oracle需要驗證它是否正確。 為了證明Oracle認為交易有效,我們需要其簽名。

我們將仔細研究分別檢索外部數據的方法。

接下來是收集收件人簽名:

@Suspendable private fun collectRecipientSignature(transaction: SignedTransaction,party: Party ): SignedTransaction {val signature = subFlow(CollectSignatureFlow(transaction,initiateFlow(party),party.owningKey)).single()return transaction.withAdditionalSignature(signature) }

收集交易對手的簽名并不是Flow真正不平凡的一步,但CollectSignatureFlow不同的是,使用CollectSignatureFlow而不是通常使用的CollectSignaturesFlow (注意中間缺少“ s”)。 這是由于在事務中需要Oracle的簽名。 將調用CollectSignaturesFlow來從所有必需的簽名者(包括Oracle)中檢索簽名。 這將Oracle視為“正常”參與者。 這不是我們想要的。 取而代之的是,我們需要分別手動獲取接收者和Oracle的簽名。 手動部分是使用transaction.withAdditionalSignature 。

現在,收件人已經簽署了交易,Oracle需要對其進行簽名:

@Suspendable private fun collectOracleSignature(transaction: SignedTransaction,oracle: Party ): SignedTransaction {val filtered = filteredTransaction(transaction, oracle)val signature = subFlow(CollectOracleStockPriceSignatureFlow(oracle, filtered))return transaction.withAdditionalSignature(signature) }private fun filteredTransaction(transaction: SignedTransaction,oracle: Party ): FilteredTransaction =transaction.buildFilteredTransaction(Predicate {when (it) {is Command<*> -> oracle.owningKey in it.signers && it.value is GiveAwayelse -> false}})

在將事務發送給Oracle之前,建議對其進行過濾,以刪除Oracle不需要的任何信息。 這可以防止Oracle看到不應共享的信息。 請記住,Oracle可能是另一個組織控制的節點,而不是您試圖與其共享狀態和事務的參與者。

SignedTransaction提供了buildFilteredTransaction函數,該函數僅包含與傳入的謂詞匹配的對象。在上面的示例中,它過濾掉了GiveAway (我創建的命令)命令之外的所有命令,該命令還必須具有Oracle作為簽名者。

這將輸出一個FilteredTransaction ,并傳遞給CollectOracleStockPriceSignatureFlow :

@InitiatingFlow class CollectOracleStockPriceSignatureFlow(private val oracle: Party,private val filtered: FilteredTransaction ) : FlowLogic<TransactionSignature>() {@Suspendableoverride fun call(): TransactionSignature {val session = initiateFlow(oracle)return session.sendAndReceive<TransactionSignature>(filtered).unwrap { it }} }

這些代碼所做的全部工作就是將FilteredTransaction發送到Oracle并等待其簽名。 此處的代碼可以放入主流程中,但是在可以的情況下將代碼拆分出來是非常好的。

最后,從Oracle返回的TransactionSignature會以與接收者的簽名之前添加方式相同的方式添加到事務中。 至此,由于所有必需的簽名者都已經做好了自己的準備,因此可以準備提交交易了。

Oracle方面

既然我們已經涵蓋了代碼的客戶端,我們就需要研究一下Oracle如何驗證事務。 以下是Oracle代碼的內容:

@InitiatedBy(CollectOracleStockPriceSignatureFlow::class) class OracleStockPriceSignatureResponder(private val session: FlowSession) : FlowLogic<Unit>() {@Suspendableoverride fun call() {val transaction = session.receive<FilteredTransaction>().unwrap { it }val key = key()val isValid = transaction.checkWithFun { element: Any ->when {element is Command<*> && element.value is GiveAway -> {val command = element.value as GiveAway(key in element.signers).also {validateStockPrice(command.symbol,command.price)}}else -> false}}if (isValid) {session.send(serviceHub.createSignature(transaction, key))} else {throw InvalidStockPriceFlowException("Transaction: ${transaction.id} is invalid")}}private fun key(): PublicKey = serviceHub.myInfo.legalIdentities.first().owningKeyprivate fun validateStockPrice(symbol: String, price: Double) = try {serviceHub.cordaService(StockPriceValidator::class.java).validate(symbol, price)} catch (e: IllegalArgumentException) {throw InvalidStockPriceFlowException(e.message)} }

StockPriceValidator隱藏了一些應在此處的代碼,該代碼檢索外部股票價格并將其與傳遞給Oracle的價格進行比較。 它沒有太多的代碼,其驗證是基本的,因此我將不對其進行詳細說明。 簡短地說,我不妨現在展示一下:

@CordaService class StockPriceValidator(private val serviceHub: AppServiceHub) :SingletonSerializeAsToken() {fun validate(symbol: String, price: Double) =serviceHub.cordaService(StockRetriever::class.java).getCurrent(symbol).let {require(price == it.price) { "The price of $symbol is ${it.price}, not $price" }} }

返回到OracleStockPriceSignatureResponder 。 首先,調用receive來獲取客戶端發送的FilteredTransaction 。 然后使用其checkWithFun函數對其進行檢查。 這是一個方便的函數,它查看每個對象并期望返回Boolean 。 使用此方法,如果事務中包含的所有內容都是GiveAway命令(其中Oracle是簽名者),并且最重要的是檢查該命令中包含的外部數據是否正確,則該事務被視為有效。 如果您回想起以前的代碼,則會傳入正確的命令和簽名者。唯一剩下的驗證是在外部數據上。 如果一切正常,那么Oracle將接受該事務并將其簽名發送回請求該請求的客戶端。

我選擇通過引發異常(連同錯誤消息)來完成驗證,然后將異常傳播到請求方。 我認為,這使您更容易了解出了什么問題,以便可以正確地處理它,而不僅僅是直接的“失敗驗證”消息。 如果Oracle正在執行的驗證很復雜,則這些錯誤消息將變得更加有價值。

檢索外部數據

您應該已經看到StockRetriever類現在彈出兩次。 請求方和Oracle中都使用了它。 我已經在兩種類型的節點(普通節點和Oracle)之間共享了此代碼,但這可能不適合您自己的用例。 此外,您如何選擇檢索外部數據取決于您,我只是提供一種可能的解決方案。

該代碼可以在下面找到:

@CordaService class StockRetriever(serviceHub: AppServiceHub) :SingletonSerializeAsToken() {private val client = OkHttpClient()private val mapper = ObjectMapper()fun getCurrent(symbol: String): Stock {val response = client.newCall(request(symbol)).execute()return response.body()?.let {val json = it.string()require(json != "Unknown symbol") { "Stock with symbol: $symbol does not exist" }val tree = mapper.readTree(json)Stock(symbol = symbol,name = tree["companyName"].asText(),primaryExchange = tree["primaryExchange"].asText(),price = tree["latestPrice"].asDouble())} ?: throw IllegalArgumentException("No response")}private fun request(symbol: String) =Request.Builder().url("https://api.iextrading.com/1.0/stock/$symbol/quote").build() }

StockRetriever是一個很好的小服務,它使用OkHttpClient ( OkHttp )向API(由IEX Trading使用其Java庫提供)發出HTTP請求,該API在提供股票代號時返回股票信息。 您可以使用任何想要發出HTTP請求的客戶端。 我在一個示例CorDapp中看到了這個,并且我自己考慮了它。 就我個人而言,我也已經習慣了Spring,所以除了RestTemplate之外,我真的不認識其他任何客戶。

返回響應后,它將轉換為Stock對象,并傳遞回函數的調用者。 那是所有人。

結論

總之,當您的CorDapp需要頻繁更改的外部數據且需要先進行驗證才能提交事務時,應使用Oracle。 就像狀態中保存的數據一樣,外部數據非常重要,可能是最重要的,因為它很可能確定事務的主要內容。 因此,所有參與者都必須對數據正確無誤感到欣慰,而不僅僅是憑空提出。 為此,Oracle還將檢索外部數據,并根據事務表明數據應具有的內容對其進行驗證。 此時,Oracle將簽署交易或引發異常并將其視為無效。 由于不需要采取很多步驟,因此實現方面相當簡單。 檢索數據,將FilteredTransaction發送到包含將在其中進行驗證的數據的Oracle。 是的,閱讀本文后,您將了解更多內容。 但是,對于基本流程而言,就差不多了。 正如我在剛開始時所說的那樣,Oracle如何進行驗證可以根據需要簡單或復雜。 雖然,我認為大多數將遵循此處所示的相同過程。

現在得出主要結論……總之,您現在已經掌握了在閑聊的渠道中回答有關Oracle的問題的知識,或者知道了如果不能將問題發送到哪里!

這篇文章中使用的代碼可以在我的GitHub上找到 。

如果您發現此帖子有幫助,可以在Twitter上@LankyDanDev關注我,以了解我的新帖子。

翻譯自: https://www.javacodegeeks.com/2019/01/validating-external-data-oracle.html

oracle連接外部數據庫

總結

以上是生活随笔為你收集整理的oracle连接外部数据库_使用Oracle验证外部数据的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人福利视频导航 | 中文字幕777 | 九九一级片 | 成人国产毛片 | 午夜aaa | 欧美成人第一页 | 国产欧美一区二区三区白浆喷水 | 精品人妻一区二区免费视频 | 青青草超碰在线 | 国产老头和老头xxxx× | 深夜在线观看 | 女人扒开屁股让我添 | 国产精品天天干 | 日本一二三不卡视频 | 国产又爽又黄视频 | 日韩在线观看精品 | 视频一区二区三区在线观看 | 怎么可能高潮了就结束漫画 | 国产精品毛片一区二区在线看舒淇 | 亚洲国产中文字幕在线观看 | 91精品免费在线观看 | 中文字幕有码av | 国产妇女馒头高清泬20p多 | 在线播放www | 色婷婷aⅴ一区二区三区 | 夜夜嗨老熟女av一区二区三区 | 精品一性一色一乱农村 | 欧美日韩高清一区二区 | 日韩欧美中文在线观看 | 国产精品igao视频 | 亚洲三级欧美 | 亚洲激情影院 | 91在线欧美| 毛片毛片毛片毛片毛片 | 琪琪色在线观看 | 国产精品免费看久久久无码 | 日日操操 | 久草午夜 | 日韩三级国产精品 | 欧美啪啪网站 | 成人福利影院 | 国产香蕉精品视频 | 最新一区二区三区 | 好吊色青青草 | 国产最新视频在线 | 亚洲国产aⅴ精品一区二区 日韩黄色在线视频 | 亚洲天堂精品在线观看 | 无码人妻aⅴ一区二区三区日本 | 四虎影院国产精品 | 久久久久久伊人 | 99国产精品视频免费观看一公开 | 波多野结衣中文字幕一区二区 | 欧洲做受高潮欧美裸体艺术 | 中文字幕一区二区三区在线不卡 | 日韩电影一区二区三区四区 | 午夜视频免费在线观看 | 日本老师巨大bbw丰满 | mm1313亚洲国产精品无码试看 | 一级片黑人 | 超碰人人澡 | 日本在线视频观看 | 草逼视频免费看 | 韩国主播青草55部完整 | 女女同性女同一区二区三区按摩 | 日韩亚洲国产欧美 | 精品日本一区二区三区在线观看 | 国产无遮挡aaa片爽爽 | 无码精品人妻一区二区三区影院 | 精品女厕偷拍一区二区 | 亚洲经典在线 | 懂色av中文一区二区三区天美 | 久久久久久久久久久福利 | 99蜜桃臀久久久欧美精品网站 | 麻豆疯狂做受xxxx高潮视频 | 一级性视频 | 欧美黄色大片免费观看 | 亚洲综合一区二区三区 | 亚洲蜜桃精久久久久久久久久久久 | 97爱爱爱| 最新色站 | 欧美日韩综合 | 成人在线不卡 | 国产性精品 | 在线视频日韩欧美 | 黄色片网站免费在线观看 | 极品人妻一区二区三区 | 午夜国产免费 | 狠狠干中文字幕 | 人妻丰满熟妇岳av无码区hd | aa亚洲| 一级特黄aaa| 精品久久蜜桃 | 日本不卡一区二区三区视频 | 福利视频在线导航 | 在线观看你懂的视频 | 国产激情网 | 日本精品在线一区 | 男人手机天堂 | 嫩草懂你 |