EosTool的目的是消除使用PHP开发EOS区块链应用的痛苦,例如:php
能够认为EosTool是PHP版本的eosjs,利用它能够完整地实现EOS官方客户端Cleos的功能, 也能够很方便地在PHP应用中增长对EOS区块链的支持能力,极大地提升开发效率。node
有兴趣的朋友也能够直接访问这里,本文内容即转自该博客:EOS区块链PHP开发包算法
EosTool运行在**Php 7.1+**环境下,当前版本1.0.0,主要代码文件清单以下:json
代码文件 | 说明 |
---|---|
eostool/src/client/NodeClient.php | 节点软件nodeos的rpc接口封装类 |
eostool/src/client/WalletClient.php | 钱包软件keosd的rpc接口封装类 |
eostool/src/client/RpcOutput.php | RPC返回结果封装类 |
eostool/src/Crypto/PrivateKey.php | EOS私钥类 |
eostool/src/Crypto/PublicKey.php | EOS公钥类 |
eostool/src/Crypto/Signature.php | EOS签名类 |
eostool/src/Serializer/AbiType.php | EOS的ABI类型封装类 |
eostool/src/Serializer/AbiTypeFactory.php | ABI类型工厂类 |
eostool/src/Serializer/SerialBuffer.php | 序列化缓冲区实现类 |
eostool/src/Serializer/Serializer.php | 序列化器实现类 |
eostool/src/Signer/Signer.php | 签名器接口 |
eostool/src/Signer/KeosdSigner.php | Keosd签名器实现类 |
eostool/src/Signer/LocalSigner.php | 本地离线签名器实现接口 |
eostool/src/Contract.php | 合约类 |
eostool/src/EosTool.php | 开发包入口类 |
eostool/tests | 单元测试用例目录 |
eostool/phpunit.xml | 单元测试配置文件 |
eostool/vendor | 第三方依赖包 |
eostool/composer.json | composer配置文件 |
使用NodeClient类访问nodeos的rpc接口。例如,下面的代码访问本机运行的 Nodeos节点的chain
插件的get_info
接口:api
use EosTool\Client\NodeClient; $nc = new NodeClient(); $ret = $nc->chain->getInfo(); if($ret->hasError()) throw new Exception($ret->getError()); $info = $ret->getResult();
2.1 RPC调用分组数组
Nodeos采用了插件化架构,不一样的插件的API也纳入不一样的分组,EosTool采用了保持一致的 命名方法,根据api便可推断出NodeClient的调用方法:API分组对应于NodeClient的一个同名 属性,API则对应与No的Client的分组同名属性下的一个通过camelCase转化的方法。例如:安全
插件 | API分组 | RPC API | NodeClient方法 |
---|---|---|---|
chain_api_plugin | chain | get_info | $nc->chain->getInfo() |
history_api_plugin | history | get_transaction | $nc->history->getTransaction() |
net_api_plugin | net | status | $nc->net->status() |
producer_api_plugin | producer | get_runtime_options | $nc->producer->getRunTimeOptions() |
dbsize_api_plugin | dbsize | get | $nc->dbsize->get() |
RPC API的官方文档:https://developers.eos.io/eosio-nodeos/reference服务器
2.2 RPC调用参数架构
对于Nodeos而言,有些调用须要传入额外的参数,例如chain插件的get_block接口, 使用EosTool进行调用时,将参数组织为一个关联数组便可,示例代码以下:composer
$payload = [ 'block_num_or_id' => 1 ]; $ret = $nc->chain->getBlock($payload);
2.3 RPC调用返回值
全部RPC调用的返回结果都是一个RpcOutput实例,调用其hasError()
方法能够 判断是否调用出错,进一步能够利用getError()
方法获取错误信息。
RPC调用的响应则能够经过getResult()
方法获取,它是一个由原始的JSON结果 转化出的StdClass对象,所以能够方便的提取属性信息,例如:
echo 'chain id' . $info->chain_id . PHP_EOL;
2.4 访问主网/测试网节点
在建立NodeClient实例时,能够传入额外的参数执行来制定要访问的EOS主网或测试网节点。 例如,使用下面的代码访问某个主网节点:
$nc = new NodeClient(['base_uri' => 'https://api.eosnewyork.io:443/v1/']);
或者访问jungle测试网的某个节点:
$nc = new NodeClient(['base_uri' => 'https://jungle.eosio.cr:443/v1/']);
新版的Keosd已经不提供RPC API文档,这可能意味着它在EOS软件栈中已经开始滑向边缘地位。 不过能够在这个地址访问老版的文档:https://developers.eos.io/eosio-nodeos/v1.1.0/reference
使用WalletClient类访问Keosd的rpc接口。例如,下面的代码访问本机运行的 Keosd的list_wallets
接口:
use EosTool\Client\WalletClient; $wc = new WalletClient(); $ret = $wc->listWallets(); if($ret->hasError()) throw new Exception($ret->getError()); $wallets = $ret->getResult();
因为Keosd的API再也不分组,所以RPC对应的方法直接挂在WalletClient对象上,这是一个不一样之处。 与NodeClient同样的是,WalletClient的调用返回结果也是一个RpcOutput对象。
1.4版的Keosd默认使用UNIX套接字而不是HTTP提供RPC接口,这多是考虑到绝大多数状况下 Keosd都运行在本机,使用IPC会更安全一些。所以这也是WalletClient的默认实例化选项, 在绝大多数状况下,不须要传入额外的参数来实例化WalletClient。
EOS的密钥算法相似于比特币,但作了一些调整,定义了本身的格式。
使用PrivateKey类的静态方法new()
生成随机私钥。例如:
use EosTool\Crypto\PrivateKey; $prv = PrivateKey::new(); echo $prv->toEos() . PHP_EOL; //相似:5Hu6nxM6s6UQ3nYkr1s1GKA17zPqpceUuWxH3JBwK8ZorMSRqGi
toEos()
方法用来将私钥对象转换为EOS的自定义格式。
4.1 公钥推导
从私钥能够推导出公钥,例如:
$pub = $prv->getPublicKey(); echo $pub->toEos() . PHP_EOL; //相似:EOS6wQ6t3n148GfzLzgxq7cC8ARDKxeaB3hQXdXn7oZYdwEyAXiSv
一样,使用toEos()
方法将公钥转换为EOS的自定义格式。
4.2 导入EOS私钥
能够将一个EOS格式的私钥转化为EosTool的PrivateKey对象,例如,下面的 代码将指定的EOS私钥导入,并显示其对应的EOS公钥:
$prv = PrivateKey::fromEos('5Hu6nxM6s6UQ3nYkr1s1GKA17zPqpceUuWxH3JBwK8ZorMSRqGi'); echo $prv->getPublicKey()->toEos() . PHP_EOL;
4.3 权威签名
PrivateKey的sign()
方法支持普通签名和EOS节点要求的权威签名。例以下面的代码返回一个 普通签名:
$hex = '1234567890abcdef...'; $signature = $prv->sign($hex);
传入额外的参数来得到指定数据的权威签名:
$hex = '1234567890abcdef...'; $signature = $prv->sign($hex,true);
EOS要求交易在提交节点push_transaction
以前先进行序列化,这也是在PHP中操做EOS交易 绕不过去的一个环节。
在EosTool中,使用Serializer类进行序列化操做。例如,下面的代码将一个EOS转帐交易 序列化为能够提交给EOS节点旳16进制码流格式:
use EosTool\Serializer\Serializer; $abi = json_decode(file_get_contents('transaction.abi'),true); $serializer = Serializer::fromAbi($abi); $tx = [ 'expiration'=>'2018-12-04T17:00:00', 'ref_block_num' => 2878, 'ref_block_prefix' => 29012031, 'max_net_usage_words' => 0, 'max_cpu_usage_ms' => 0, 'delay_sec' => 0, 'context_free_actions' => [], 'actions' => [[ 'account' => 'eosio.token', 'name' => 'transfer', 'authorization' => [[ 'actor' => 'eosio', 'permission' => 'active' ]], 'data' => '1122334455667788990011223344556677.....889900' ]], 'transaction_extensions' => [] ]; $hex = $serializer->serialize('transaction',$tx); echo 'serialized tx => ' . $hex . PHP_EOL;
Serializer的静态方法fromAbi()
用来根据一个指定的abi构造序列化器实例,而后 利用实例的serialize()
方法对指定类型的数据进行序列化操做,获得16进制码流。
EosTool提供了两种进行交易签名的方法:利用Keosd进行签名,或者使用本地私钥进行签名。
使用KeosdSigner类来利用钱包服务器完成签名。例如:
use EosTool\Signer\KeosdSigner; $signer = new KeosdSigner(); $signatures = $signer->sign($tx,$pubKeys,$chainId);
利用LocalSigner类,则能够避免使用keosd,直接利用离线私钥签名。例如:
use EosTool\Signer\LocalSigner; $prvKeys = ['5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3']; $signer = new LocalSigner($prvKeys); $signatures = $signer->sign($tx,$pubKeys,$chainId);
一个交易数据,须要通过规范化、序列化、签名、打包一系列操做,才能够提交给 Nodeos节点广播出去。EosTool类提供了transact()
方法来隔离这些繁琐的操做。
例如,下面的代码使用NodeClient和LocalSigner建立一个EosTool实例,而后提交 一个交易:
use EosTool\Client\NodeClient; use EosTool\Signer\LocalSigner; use EosTool\EosTool; $nc = new NodeClient(); $signer = new LocalSigner(['5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3']); $tool = new EosTool($nc,$signer); $tx = [ 'actions' => [[ 'account' => 'eosio.token', 'name' => 'transfer', 'authorization' => [[ 'actor' => 'eosio', 'permission' => 'active' ]], 'data' => [ 'from' => 'eosio', 'to' => 'tommy', 'quantity' => '200.0000 EOS', 'memo' => 'take care' ] ]] ]; $ret = $tool->transact($tx); echo $ret->getResult()->transaction_id . PHP_EOL;
能够很方便地将签名器改成KeosdSigner,例如:
$nc = new NodeClient(); $signer = new KeosdSigner(); $tool = new EosTool($nc,$signer);
使用EosTool的pushAction()
方法调用单个合约动做。例如,下面的代码调用tommy 帐户托管合约的hi()
方法:
$tool = new EosTool(new NodeClient(),new KeosdSigner()); $ret = $tool->pushAction('tommy','hi',['user'=>'tommy']);
使用EosTool的setContract()
方法部署合约,例如:
$tool = new EosTool(new NodeClient(),new KeosdSigner()); $account = 'tommy'; $abi = file_get_contents('hello.abi'); $wasm = file_get_contents('hello.wasm'); $ret = $tool->setContract($account,$abi,$wasm);
有兴趣的朋友能够去这里:EOS区块链PHP开发包