EOS區塊鏈PHP開發包

1. 開發包概述

EosTool的目的是消除使用PHP開發EOS區塊鏈應用的痛苦,例如:

  • 通過Nodeos和Keosd的RPC接口調用其功能
  • 離線生成EOS格式的私鑰和公鑰
  • 使用本地私鑰生成符合EOS要求的交易簽名
  • 將交易對象序列化爲Nodeos要求的packed_trx格式

可以認爲EosTool是PHP版本的eosjs,利用它可以完整地實現EOS官方客戶端Cleos的功能, 也可以很方便地在PHP應用中增加對EOS區塊鏈的支持能力,極大地提高開發效率。

有興趣的朋友也可以直接訪問這裏,本文內容即轉自該博客:EOS區塊鏈PHP開發包

EosTool運行在**Php 7.1+**環境下,當前版本1.0.0,主要代碼文件清單如下:

代碼文件說明
eostool/src/client/NodeClient.php節點軟件nodeos的rpc接口封裝類
eostool/src/client/WalletClient.php錢包軟件keosd的rpc接口封裝類
eostool/src/client/RpcOutput.phpRPC返回結果封裝類
eostool/src/Crypto/PrivateKey.phpEOS私鑰類
eostool/src/Crypto/PublicKey.phpEOS公鑰類
eostool/src/Crypto/Signature.phpEOS簽名類
eostool/src/Serializer/AbiType.phpEOS的ABI類型封裝類
eostool/src/Serializer/AbiTypeFactory.phpABI類型工廠類
eostool/src/Serializer/SerialBuffer.php序列化緩衝區實現類
eostool/src/Serializer/Serializer.php序列化器實現類
eostool/src/Signer/Signer.php簽名器接口
eostool/src/Signer/KeosdSigner.phpKeosd簽名器實現類
eostool/src/Signer/LocalSigner.php本地離線簽名器實現接口
eostool/src/Contract.php合約類
eostool/src/EosTool.php開發包入口類
eostool/tests單元測試用例目錄
eostool/phpunit.xml單元測試配置文件
eostool/vendor第三方依賴包
eostool/composer.jsoncomposer配置文件

2. 訪問節點服務器

使用NodeClient類訪問nodeos的rpc接口。例如,下面的代碼訪問本機運行的 Nodeos節點的chain插件的get_info接口:

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 APINodeClient方法
chain_api_pluginchainget_info$nc->chain->getInfo()
history_api_pluginhistoryget_transaction$nc->history->getTransaction()
net_api_pluginnetstatus$nc->net->status()
producer_api_pluginproducerget_runtime_options$nc->producer->getRunTimeOptions()
dbsize_api_plugindbsizeget$nc->dbsize->get()

RPC API的官方文檔:https://developers.eos.io/eosio-nodeos/reference

2.2 RPC調用參數

對於Nodeos而言,有些調用需要傳入額外的參數,例如chain插件的get_block接口, 使用EosTool進行調用時,將參數組織爲一個關聯數組即可,示例代碼如下:

$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/']);

3、訪問錢包服務器

新版的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。

4. 私鑰與公鑰

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);

5. 序列化

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進制碼流。

6. 簽名

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);

7. 交易提交

一個交易數據,需要經過規範化、序列化、簽名、打包一系列操作,纔可以提交給 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);

8. 調用單個合約動作

使用EosTool的pushAction()方法調用單個合約動作。例如,下面的代碼調用tommy 賬戶託管合約的hi()方法:

$tool = new EosTool(new NodeClient(),new KeosdSigner());
$ret = $tool->pushAction('tommy','hi',['user'=>'tommy']);

9. 部署合約

使用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開發包

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章