aelf 通过类GRPC的protobuf服务描述文件定义智能合约,实现了一个性能等价于GRPC Server的智能合约运行环境。
简化目录结构
.
├── AElf.Boilerplate.sln
├── protobuf
│ ├── hello_world.proto
├── src
│ ├── AElf.Boilerplate.Launcher
│ │ ├── bin
│ │ │ └── Debug
│ │ │ └── netcoreapp2.2
│ │ │ ├── AElf.Boilerplate.Launcher.dll
│ └── HelloWorldContract
│ │ ├── bin
│ │ │ └── Debug
│ │ │ └── netcoreapp2.2
│ │ │ ├── HelloWorldContract.dll
│ ├── HelloWorldContract.cs
│ ├── HelloWorldContract.csproj
通过service 定义了对应的rpc方法,通过message来定义了数据格式。更多的内容可以参考protobuf的文档。
在HelloWorldContract.csproj引用了对应的protobuf文件。
在HelloWorldContract.cs中实现了具体的合约逻辑。
这个文件是执行 dotnet build后生成的文件。
在boilerplate这个模板中,dotnet run时会自动发布到我们启动的链上。
如果需要将自己的合约发布到其它基于AELF系统运行的区块链网络上,只需要发布对应dll即可。
// protobuf的定义
syntax = "proto3";
import "aelf_options.proto";
import "google/protobuf/empty.proto";
option csharp_namespace = "HelloWorldContract";
service HelloWorldContract {
option (aelf.csharp_state) = "HelloWorldContractState";
// 定义了合约的方法,和该方法的返回
rpc Hello (google.protobuf.Empty) returns (HelloReturn) { }
}
// 定义了返回数据的数据格式
message HelloReturn {
string Value = 1;
}
// C#中的逻辑实现
using Google.Protobuf.WellKnownTypes;
namespace HelloWorldContract
{
public partial class HelloWorldContract : HelloWorldContractContainer.HelloWorldContractBase
{
// 对应proto文件中的rpc Hello
// 返回为 HelloReturn
public override HelloReturn Hello(Empty input)
{
return new HelloReturn {Value = "Hello world!"};
}
}
下面我们新增一个Add方法,输入两个整型参数 a和b, 输出 a + b
syntax = "proto3";
import "aelf_options.proto";
import "google/protobuf/empty.proto";
option csharp_namespace = "HelloWorldContract";
service HelloWorldContract {
option (aelf.csharp_state) = "HelloWorldContractState";
rpc Hello (google.protobuf.Empty) returns (HelloReturn) { }
// 新增方法Add, 入参为AddInput, 返回为 AddOutput
rpc Add (AddInput) returns (AddOutput) { }
}
message HelloReturn {
string Value = 1;
}
// AddInput的格式定义,根据protobuf的协议规定,Key的首字母须大写
message AddInput {
sint64 A = 1;
sint64 B = 2;
}
// AddOutpu的定义
message AddOutput {
sint64 Value = 1;
}
using Google.Protobuf.WellKnownTypes;
namespace HelloWorldContract
{
public partial class HelloWorldContract : HelloWorldContractContainer.HelloWorldContractBase
{
public override HelloReturn Hello(Empty input)
{
return new HelloReturn {Value = "Hello world!"};
}
// 新增Add方法
public override AddOutput Add(AddInput input) {
return new AddOutput {Value = input.A + input.B};
}
}
}
在src/AElf.Boilerplate.Launcher 下执行 dotnet build 完成编译
dotnet run bin/Debug/netcoreapp2.2/AElf.Boilerplate.Launcher
新的合约会自动发布到链上。
cd web/JSSDK
# 执行node, 进入nodejs的命令行交互界面
node
把下面一段js输入
const AElf = require('aelf-sdk');
const Wallet = AElf.wallet;
const sha256 = AElf.utils.sha256;
// address: 65dDNxzcd35jESiidFXN5JV8Z7pCwaFnepuYQToNefSgqk9
const defaultPrivateKey = 'bdb3b39ef4cd18c2697a920eb6d9e8c3cf1a930570beb37d04fb52400092c42b';
const wallet = Wallet.getWalletByPrivateKey(defaultPrivateKey);
const aelf = new AElf(new AElf.providers.HttpProvider(
'http://127.0.0.1:1235/chain',
null,
null,
null,
[{
name: 'Accept',
value: 'text/plain;v=1.0'
}]
));
const helloWorldContractName = 'HelloWorldContract';
const {
GenesisContractAddress
} = aelf.chain.getChainStatus();
const zeroC = aelf.chain.contractAt(GenesisContractAddress, wallet);
const helloWorldContractAddress = zeroC.GetContractAddressByName.call(sha256(helloWorldContractName));
const helloWorldC = aelf.chain.contractAt(helloWorldContractAddress, wallet);
// 刚新增的方法
helloWorldC.Add.call({A: 1, B:3}, (error, result) => {console.log(error, result);})
稍等一下看到输出结果
null { Value: '4' }
看不到结果
-
确认编译成功。
-
确认链在运行。
-
确认JS代码没输入错。
多学多看多搜索,愿大家在工程师的道路上越走越远。