In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
本篇内容介绍了"怎么用C#开发超级账本Fabric "的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
1、Fabric链码.NET Core开发包
首先创建一个.NET Core项目,在命令行执行如下命令添加对Fabric链码.NET Core开发包的依赖:
dotnet add package Thinktecture.HyperledgerFabric.Chaincode \ --version 1.0.0-prerelease.74
Thinktecture.HyperledgerFabric.Chaincode链码开发包提供了两种不同的方法来开发Hyperledger Fabric链码。
使用底层API:通过实现IChaincode接口来开发超级账本Fabric链码是一种比较底层的途径, 好处是对链码实现的掌控程度最大
使用上层API:通过继承ContractBase类来开发超级账本Fabric链码会更容易一些,但 代价就是丧失部分灵活性
在这个教程中,我们将通过IChaincode接口这一偏底层的途径来实现Fabric链码。如果你对ContractBase继承实现更有兴趣,请等待我们下一篇教程!
2、Hyperledger Fabric链码开发
创建一个类AssetHolding来实现IChaincode接口:
public class AssetHolding : IChaincode{ public async Task Init(IChaincodeStub stub) { throw new NotImplementedException(); } public Task Invoke(IChaincodeStub stub) { throw new NotImplementedException(); }}
Ichaincode接口的两个方法Init和Invoke都需要实现。
Init()方法将在Fabric链码初始化和升级时被调用,可以使用这个方法来初始化资产库,例如, 设置一些默认值。
Invoke()方法将在Fabric链码的整个生命周期中被Peer节点调用,可以使用这个方法来处理可能影响资产状态的业务交易逻辑。
两个方法都有一个类型为IChaincodeStub的参数,该接口封装了Fabric链码实现和Fabric对等节点之间的通信API。例如,使用这个接口可以对资产库进行CRUD操作。
3、实现Hyperledger Fabric链码的Init()方法
如前所述,我们的Fabric链码需要初始化两个账户名并设置账户初始余额。基本上应用在调用Fabric链码时会传递一个数组参数给链码,例如["accountA", "100", "accountB", "50"],为了在Fabric链码初始化时得到这个参数,我们可以使用stub.GetFunctionAndParameters(),该方法的结果时一个List类型的参数对象,其中包含了所有参数。
public async Task Init(IChaincodeStub stub){ var functionAndParameters = stub.GetFunctionAndParameters(); var args = functionAndParameters.Parameters; args.AssertCount(4);}
我们使用Parameters.AssertCount(4)来快速检查参数的数量是否符合要求,如果数量不是4就会抛出异常,从而终止链码的执行。
下一步是将其中两个参数转换为整型。我们可以自己使用int.TryParse()来实现这一步,或者使用args.TryGet()方法。现在我们来完善Init()的实现:
public async Task Init(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个参数转换为整数,如果某个转换失败,我们就返回Shim.Error()通知Fabric链码的调用方初始化失败。
如果转换成功,我们就可以使用stub.PutState()将转换结果存入链码资产库:
public async Task Init(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链码调用者返回成功响应,否则返回一个错误。
4、实现Hyperledger Fabric链码的Invoke()方法
现在我们进入Invoke方法的实现。Invoke()方法在链码整个声明周期中被Fabric的对等节点调用来处理业务逻辑,该方法的参数和Init()一样,因此我们也需要使用该参数接口的GetFunctionAndParameters()方法来获取Fabric链码的调用参数。
public Task Invoke(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实现中可能需要很多if分支或switch分支,因此Faric链码.NET开发包提供了一个辅助类ChaincodeInvocationMap来让代码更干净:
private readonly ChaincodeInvocationMap _invocationMap;public AssetHolding(){ _invocationMap = new ChaincodeInvocationMap { {"Transfer", InternalTransfer}, {"Query", InternalQuery} };}public Task Invoke(IChaincodeStub stub){ return _invocationMap.Invoke(stub);}
需要指出的是,我们还没有实现InternalTransfer()和InternalQuery()方法。
下面实现InternalTransfer()方法:
private async Task InternalTransfer(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链码需要从一个账户向另一个账户转钱,因此需要三个参数:
accountA:转出账户
accountB:转入账户
amount:转账金额
我们可以使用AssertCount(3)来确保得到3个参数,就像在Init()实现中的检查一样。然后,在我们转账之前,需要从Fabric链码资产库中读取当前的账户状态。为此,我们需要使用IChaincodeStub.GetState()方法或IChaincodeStub.TryGetState()方法,两者的区别在于第二个方法不会抛出异常,仅仅在失败时返回false。
从Fabric链码资产库中读取了账户状态后,我们可以从accountA中扣除转账金额,并向accountB加上这个金额。在这一步你可以根据自己的需要进行必要的检查,例如转账金额不可以是负数。
在更新了两个账户的状态变量后,我们还需要将新的状态使用stub.PutState()写入资产库。最后我们返回一个空的ByteString给Fabric链码调用方表示没有发生错误。
InternalQuery()方法用来查询指定账户的余额,因此需要传入一个参数表示要查询的账户。
private async Task InternalQuery(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;}
好了,现在我们完成了Fabric链码的.NET/C#实现,不过别忘了实现作为.NET应用入口的Main()方法,我们需要在这里启动链码:
static async Task Main(string[] args){ using (var provider = ChaincodeProviderConfiguration.Configure(args)) { var shim = provider.GetRequiredService(); await shim.Start(); }}"怎么用C#开发超级账本Fabric "的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 241
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.