[md]
下面是使用web3.php获取节点版本信息的代码:rpc-web3.php
<?php
require('../vendor/autoload.php');
use Web3\Web3;
use EthTool\Callback;
$web3 = new Web3('http://localhost:8545');
$web3->clientVersion(function($err,$result){
if($err) throw $err;
echo $result . PHP_EOL;
});
$cb = new Callback;
$web3->clientVersion($cb);
echo $cb->result . PHP_EOL;
$web3->sha3('hello,ethereum',$cb);
echo $cb->result . PHP_EOL;
$web3->eth->gasPrice($cb);
echo $cb->result . PHP_EOL;
$web3->eth->accounts($cb);
$accounts = $cb->result;
print_r($accounts);
$web3->eth->getBalance($accounts[0],$cb);
echo $cb->result . PHP_EOL;
?>
理解web3.php的命名规则
web3.php的命名空间为Web3,所有的类都定义在该空间内。其中, Web3\Web3是包的入口类,只需指定节点URL就可以进行实例化了。
方法调用的结果是通过回调函数传入的,其第一个参数表示错误对象, 如果非空就意味着执行过程出现了错误,你可以调用其getMessage()方法 获得错误的描述信息,或者像我一样不负责任的抛出异常。第二个参数则表示 JSON RPC响应包中的result字段的内容 —— 注意不是整个响应包。
如果你不喜欢写大量的嵌套回调,或者使用引用来从回调域中返回结果,那么 可以写一个简单的callable类:
<?php
namespace EthTool;
class Callback{
function __invoke($error,$result){
if($error) throw $error;
$this->result = $result;
}
}
?>
然后直接把一个Callback实例对象丢给web3.php的函数做回调:
$cb = new Callback;
$eth->accounts($cb);
print_r($cb->result);
在函数的命名上,web3.php尽量贴近对应的rpc接口名称,例如与web3_clientVersion 对应的,就是Web3类的clientVersion()方法,与web3_sha3对应的就是 Web3类的sha3()方法 —— 横线之前的做类名,横线之后的做方法名:
在web3.php中没有实现db_*相关的接口,如果需要的话你可以自己补上。但是 它在Web3Personal类中实现了geth的管理接口,这个非标扩展接口主要用于 节点账户的管理,例如创建新账户、解锁账户等等,一些非常实用的功能。
Web3入口类
Web3\Web3是一个入口类,通过它即可访问其他类的实例:
例如,上面的代码
(demo:repo\chapter2\rpc-web3.php)
<?php
$web3->eth->accounts($cb);
$accounts = $cb->result;
$web3->eth->getBalance($accounts[0],$cb);
echo 'balance: ' . $cb->result . PHP_EOL;
利用入口类实例的eth对象调用eth->accounts接口获取节点账户列表,然后调用eth->getBalance接口获取第一个账户的余额,Web3\Provider封装了Http请求的细节,而Web3\Utils则封装了一些有用的工具方法,我们在后面会用到。
账户管理
在这一部分,我们将学习如何使用php管理以太坊账户,这包括:
了解私钥、公钥和账户的关系
离线创建以太坊账户
导入其他账户私钥
创建和使用钱包
创建和使用账户凭证
以太坊作为一个去中心化的系统,必然不会采用中心化的账户管理 方案 —— 没有一个中心数据库来保存以太坊平台上的所有账户信息。 事实上,以太坊使用非对称密钥技术来进行身份识别,一个以太坊 账户对应着一对密钥:
我们将使用simplto/elliptic-php和kornrunner/keccak这两个包来创建离线账户,并参考nebulasio的代码实现keystore钱包。
以太坊使用非对称密钥对来进行身份识别,每一个账户都有 对应的私钥和公钥 —— 私钥用来签名、公钥则用来验证签名 —— 从而 在非可信的去中心化环境中实现身份验证。
事实上,在以太坊上账户仅仅是对应于特定非对称密钥对中公钥的20字节 哈希:
从私钥可以得到公钥,然后进一步得到账户地址,而反之则无效。 显然,以太坊不需要一个中心化的账户管理系统,我们可以根据以太坊约定 的算法自由地生成账户。
在php中,可以使用simplto/elliptic-php包的EllipticEC类来创建 密钥对,然后使用kornrunner/keccak包计算账户地址:
例如,demo: repo\chapter3\new-account.php
创建私钥生成账户和公钥
首先创建一个私钥对,然后再利用公钥生成账户地址:
<?php
require('../vendor/autoload.php');
use Elliptic\EC;
use kornrunner\Keccak;
$ec = new EC('secp256k1');
$keyPair = $ec->genKeyPair();
$privateKey = $keyPair->getPrivate()->toString(16,2);
$publicKey = $keyPair->getPublic()->encode('hex');
$address = '0x' . substr(Keccak::hash(substr(hex2bin($publicKey),1),256),24);
echo 'Private Key' . PHP_EOL;
echo $privateKey . PHP_EOL;
echo 'Public Key' . PHP_EOL;
echo $publicKey . PHP_EOL;
echo 'address' .PHP_EOL;
echo $address . PHP_EOL;
?>
我们已经知道,只有私钥是最关键的,公钥和账户都可以从私钥一步步 推导出来。
假如你之前已经通过其他方式有了一个账户,例如使用Metamask创建 的钱包,那么可以把该账户导入php应用,重新生成公钥和账户地址:
利用私钥还原账户和公钥
我们使用EllipticEC类的静态方法keyFromPrivate()来导入 私钥。例如:
demo:repo\chapter3\import-key.php
<?php
require('../vendor/autoload.php');
use Elliptic\EC;
use kornrunner\Keccak;
$ec = new EC('secp256k1');
$keyPair = $ec->keyFromPrivate('0x133be114715e5fe528a1b8adf36792160601a2d63ab59d1fd454275b31328791');
$privateKey = $keyPair->getPrivate()->toString(16,2);
$pubKey = $keyPair->getPublic()->encode('hex');
$address = '0x' . substr(\kornrunner\Keccak::hash(substr(hex2bin($pubKey), 1), 256), 24);
echo 'Private Key' . PHP_EOL;
echo $privateKey . PHP_EOL;
echo 'Public Key' . PHP_EOL;
echo $pubKey . PHP_EOL;
echo 'address' .PHP_EOL;
echo $address . PHP_EOL;
?>
下一篇:php以太坊-keystore文件