十年網(wǎng)站開發(fā)經驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本篇內容介紹了“怎么用C#開發(fā)超級賬本Fabric ”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
創(chuàng)新互聯(lián)專注于企業(yè)全網(wǎng)整合營銷推廣、網(wǎng)站重做改版、汶上網(wǎng)站定制設計、自適應品牌網(wǎng)站建設、H5建站、商城網(wǎng)站制作、集團公司官網(wǎng)建設、成都外貿網(wǎng)站建設公司、高端網(wǎng)站制作、響應式網(wǎng)頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為汶上等各大城市提供網(wǎng)站開發(fā)制作服務。
首先創(chuàng)建一個.NET Core項目,在命令行執(zhí)行如下命令添加對Fabric鏈碼.NET Core開發(fā)包的依賴:
dotnet add package Thinktecture.HyperledgerFabric.Chaincode \ --version 1.0.0-prerelease.74
Thinktecture.HyperledgerFabric.Chaincode
鏈碼開發(fā)包提供了兩種不同的方法來開發(fā)Hyperledger Fabric鏈碼。
使用底層API:通過實現(xiàn)IChaincode接口來開發(fā)超級賬本Fabric鏈碼是一種比較底層的途徑, 好處是對鏈碼實現(xiàn)的掌控程度最大
使用上層API:通過繼承ContractBase類來開發(fā)超級賬本Fabric鏈碼會更容易一些,但 代價就是喪失部分靈活性
在這個教程中,我們將通過IChaincode接口這一偏底層的途徑來實現(xiàn)Fabric鏈碼。如果你對ContractBase繼承實現(xiàn)更有興趣,請等待我們下一篇教程!
創(chuàng)建一個類AssetHolding來實現(xiàn)IChaincode接口:
public class AssetHolding : IChaincode { public async TaskInit(IChaincodeStub stub) { throw new NotImplementedException(); } public Task Invoke(IChaincodeStub stub) { throw new NotImplementedException(); } }
Ichaincode接口的兩個方法Init和Invoke都需要實現(xiàn)。
Init()
方法將在Fabric鏈碼初始化和升級時被調用,可以使用這個方法來初始化資產庫,例如, 設置一些默認值。
Invoke()
方法將在Fabric鏈碼的整個生命周期中被Peer節(jié)點調用,可以使用這個方法來處理可能影響資產狀態(tài)的業(yè)務交易邏輯。
兩個方法都有一個類型為IChaincodeStub的參數(shù),該接口封裝了Fabric鏈碼實現(xiàn)和Fabric對等節(jié)點之間的通信API。例如,使用這個接口可以對資產庫進行CRUD操作。
如前所述,我們的Fabric鏈碼需要初始化兩個賬戶名并設置賬戶初始余額?;旧蠎迷谡{用Fabric鏈碼時會傳遞一個數(shù)組參數(shù)給鏈碼,例如["accountA", "100", "accountB", "50"]
,為了在Fabric鏈碼初始化時得到這個參數(shù),我們可以使用stub.GetFunctionAndParameters()
,該方法的結果時一個List
類型的參數(shù)對象,其中包含了所有參數(shù)。
public async TaskInit(IChaincodeStub stub) { var functionAndParameters = stub.GetFunctionAndParameters(); var args = functionAndParameters.Parameters; args.AssertCount(4); }
我們使用Parameters.AssertCount(4)
來快速檢查參數(shù)的數(shù)量是否符合要求,如果數(shù)量不是4就會拋出異常,從而終止鏈碼的執(zhí)行。
下一步是將其中兩個參數(shù)轉換為整型。我們可以自己使用int.TryParse()
來實現(xiàn)這一步,或者使用args.TryGet
方法?,F(xiàn)在我們來完善Init()
的實現(xiàn):
public async TaskInit(IChaincodeStub stub) { var functionAndParameters = stub.GetFunctionAndParameters(); var args = functionAndParameters.Parameters; args.AssertCount(4); if (!args.TryGet (1, out var aValue) || !args.TryGet (3, out var bValue)) { return Shim.Error("Expecting integer value for asset holding"); } }
在上面的代碼中我們嘗試將第2個和第4個參數(shù)轉換為整數(shù),如果某個轉換失敗,我們就返回Shim.Error()
通知Fabric鏈碼的調用方初始化失敗。
如果轉換成功,我們就可以使用stub.PutState()
將轉換結果存入鏈碼資產庫:
public async TaskInit(IChaincodeStub stub) { var functionAndParameters = stub.GetFunctionAndParameters(); var args = functionAndParameters.Parameters; args.AssertCount(4); if (!args.TryGet (1, out var aValue) || !args.TryGet (3, out var bValue)) { return Shim.Error("Expecting integer value for asset holding"); } if (await stub.PutState(args.Get (0), aValue) && await stub.PutState(args.Get (2), bValue)) { return Shim.Success(); } return Shim.Error("Error during Chaincode init!"); }
在上面的代碼中,我們使用PutState()
來更新Faric鏈碼資產庫中賬戶的初始值。如果一切順利,我們就可以使用Shim.Success()
向Fabric鏈碼調用者返回成功響應,否則返回一個錯誤。
現(xiàn)在我們進入Invoke方法的實現(xiàn)。Invoke()方法在鏈碼整個聲明周期中被Fabric的對等節(jié)點調用來處理業(yè)務邏輯,該方法的參數(shù)和Init()一樣,因此我們也需要使用該參數(shù)接口的GetFunctionAndParameters()
方法來獲取Fabric鏈碼的調用參數(shù)。
public TaskInvoke(IChaincodeStub stub) { var functionAndParameters = stub.GetFunctionAndParamaters(); if (functionAndParameters.Function == 'myfn1') { return MyFn1(stub, functionAndParameters.Parameters); } if (functionAndParameters.Function == 'myfn2') { return MyFn2(stub, functionAndParameters.Parameters); } // Rinse and repeat for every function }
依賴于你的具體設計,在Invoke實現(xiàn)中可能需要很多if分支或switch分支,因此Faric鏈碼.NET開發(fā)包提供了一個輔助類ChaincodeInvocationMap
來讓代碼更干凈:
private readonly ChaincodeInvocationMap _invocationMap; public AssetHolding() { _invocationMap = new ChaincodeInvocationMap { {"Transfer", InternalTransfer}, {"Query", InternalQuery} }; } public TaskInvoke(IChaincodeStub stub) { return _invocationMap.Invoke(stub); }
需要指出的是,我們還沒有實現(xiàn)InternalTransfer()
和InternalQuery()
方法。
下面實現(xiàn)InternalTransfer()
方法:
private async TaskInternalTransfer(IChaincodeStub stub, Parameters args) { args.AssertCount(3); var accountA = args.Get (0); var accountB = args.Get (1); if (string.IsNullOrEmpty(accountA) || string.IsNullOrEmpty(accountB)) throw new Exception("Asset holding must not be empty"); var aValue = await stub.TryGetState (accountA); if (!aValue.HasValue) throw new Exception("Failed to get state of asset holder A"); var bValue = await stub.TryGetState (accountB); if (!bValue.HasValue) throw new Exception("Failed to get state of asset holder B"); if (!args.TryGet (2, out var amount)) throw new Exception("Expecting integer value for amount to be transferred"); aValue -= amount; bValue += amount; await stub.PutState(accountA, aValue); await stub.PutState(accountB, bValue); return ByteString.Empty; }
由于我們的Fabric鏈碼需要從一個賬戶向另一個賬戶轉錢,因此需要三個參數(shù):
accountA:轉出賬戶
accountB:轉入賬戶
amount:轉賬金額
我們可以使用AssertCount(3)
來確保得到3個參數(shù),就像在Init()
實現(xiàn)中的檢查一樣。然后,在我們轉賬之前,需要從Fabric鏈碼資產庫中讀取當前的賬戶狀態(tài)。為此,我們需要使用IChaincodeStub.GetState()
方法或IChaincodeStub.TryGetState()
方法,兩者的區(qū)別在于第二個方法不會拋出異常,僅僅在失敗時返回false。
從Fabric鏈碼資產庫中讀取了賬戶狀態(tài)后,我們可以從accountA中扣除轉賬金額,并向accountB加上這個金額。在這一步你可以根據(jù)自己的需要進行必要的檢查,例如轉賬金額不可以是負數(shù)。
在更新了兩個賬戶的狀態(tài)變量后,我們還需要將新的狀態(tài)使用stub.PutState()
寫入資產庫。最后我們返回一個空的ByteString
給Fabric鏈碼調用方表示沒有發(fā)生錯誤。
InternalQuery()
方法用來查詢指定賬戶的余額,因此需要傳入一個參數(shù)表示要查詢的賬戶。
private async TaskInternalQuery(IChaincodeStub stub, Parameters args) { args.AssertCount(1); var a = args[0]; var aValueBytes = await stub.GetState(a); if (aValueBytes == null) throw new Exception($"Failed to get state of asset holder {a}"); return aValueBytes; }
好了,現(xiàn)在我們完成了Fabric鏈碼的.NET/C#實現(xiàn),不過別忘了實現(xiàn)作為.NET應用入口的Main()
方法,我們需要在這里啟動鏈碼:
static async Task Main(string[] args) { using (var provider = ChaincodeProviderConfiguration.Configure(args)) { var shim = provider.GetRequiredService (); await shim.Start(); } }
“怎么用C#開發(fā)超級賬本Fabric ”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質量的實用文章!