如何实现PHP与Ethereum客户端的高效交互?
- 内容介绍
- 文章标签
- 相关推荐
本文共计751个文字,预计阅读时间需要4分钟。
PHP与Ethereum RPC Server通信Json RPCJson RPC是基于JSON的远程过程调用,这种解释比较抽象。简单来说,就是通过发送一个JSON格式的数据来调用RPC Server中的方法。
这个JSON格式是固定的,总的来说就是通过发送一个JSON格式的数据来调用RPC Server中的方法。
php与ethereum rpc server通信
一、Json RPC
Json RPC就是基于json的远程过程调用,这么解释比较抽象。简单来说,就是post一个json格式的数据调用rpc server中的方法. 而这个json格式是固定的, 总的来说有这么几项:
{ "method": "", "params": [], "id": idNumber }
- method: 方法名
- params: 参数列表
- id: 对过程调用的唯一标识号
二、构建一个Json RPC客户端
<?php class jsonRPCClient { /** * Debug state * * @var boolean */ private $debug; /** * The server URL * * @var string */ private $url; /** * The request id * * @var integer */ private $id; /** * If true, notifications are performed instead of requests * * @var boolean */ private $notification = false; /** * Takes the connection parameters * * @param string $url * @param boolean $debug */ public function __construct($url,$debug = false) { // server URL $this->url = $url; // proxy empty($proxy) ? $this->proxy = '' : $this->proxy = $proxy; // debug state empty($debug) ? $this->debug = false : $this->debug = true; // message id $this->id = 1; } /** * Sets the notification state of the object. In this state, notifications are performed, instead of requests. * * @param boolean $notification */ public function setRPCNotification($notification) { empty($notification) ? $this->notification = false : $this->notification = true; } /** * Performs a jsonRCP request and gets the results as an array * * @param string $method * @param array $params * @return array */ public function __call($method,$params) { // check if (!is_scalar($method)) { throw new Exception('Method name has no scalar value'); } // check if (is_array($params)) { // no keys $params = $params[0]; } else { throw new Exception('Params must be given as array'); } // sets notification or request task if ($this->notification) { $currentId = NULL; } else { $currentId = $this->id; } // prepares the request $request = array( 'method' => $method, 'params' => $params, 'id' => $currentId ); $request = json_encode($request); $this->debug && $this->debug.='***** Request *****'."\n".$request."\n".'***** End Of request *****'."\n\n"; // performs the HTTP POST $opts = array ('127.0.0.1:8545', true); } } catch (\Exception $e) { echo $e->getMessage(); } return call_user_func([self::$client, $method], $params); } public static function getBalance($address) { $method_hash = '0x70a08231'; $method_param1_hex = str_pad(substr($address, 2), 64, '0', STR_PAD_LEFT); $data = $method_hash . $method_param1_hex; $params = ['from' => $address, 'to' => self::CONTRACT, 'data' => $data]; $total_balance = self::eth_call([$params, "latest"]); return hexdec($total_balance) / (pow(10, 18)); } public static function transfer($to, $value) { self::personal_unlockAccount([self::COINBASE, "123456", 3600]); $value = bcpow(10, 18) * $value; $method_hash = '0xa9059cbb'; $method_param1_hex =str_pad(substr($to, 2), 64, '0', STR_PAD_LEFT); $method_param2_hex = str_pad(strval(bc_dechex($value)), 64, '0', STR_PAD_LEFT); $data = $method_hash . $method_param1_hex . $method_param2_hex; $params = ['from' => self::COINBASE, 'to' => self::CONTRACT, 'data' => $data]; return self::eth_sendTransaction([$params]); } }
代码比较简单, 要注意几点:
- transfer函数的value单位很小, 是 10 ^ -18, 所以如果你想转1000个,其实是要乘于 10的18次方, 这里的18是decimals.
- 由于第1点, 应该使用bcpow代替pow函数.
- 不能使用php自带的dechex函数. 因为dechex要求整型不能大于 PHP_INT_MAX, 而这个数在32位机上为4294967295。由于第1 点, 所有的数都要乘于10的18次方, 所以得到的数要远远大于PHP_INT_MAX. 建议自己实现10进制转16进制,如果你不知道如何实现,参考上述代码。
- 在运行某些合约方法, 比如transfer时, 要先unlock用户.
- 发送交易之后, 一定要在服务器端启动挖矿, 这样交易才会真的写入到区块, 比如你调用transfer之后,却发现对方没有到账,先别吃惊,启动挖矿试试。如果想启用自动挖码, 在geth --rpc ...最后加上 --mine.
测试:
<?php var_dump(EthereumRPCClient::personal_newAccount(['password'])); var_dump(EthereumRPCClient::personal_unlockAccount([EthereumRPCClient::COINBASE, "password", 3600]); var_dump(EthereumRPCClient::getBalance("0x...."));
本文共计751个文字,预计阅读时间需要4分钟。
PHP与Ethereum RPC Server通信Json RPCJson RPC是基于JSON的远程过程调用,这种解释比较抽象。简单来说,就是通过发送一个JSON格式的数据来调用RPC Server中的方法。
这个JSON格式是固定的,总的来说就是通过发送一个JSON格式的数据来调用RPC Server中的方法。
php与ethereum rpc server通信
一、Json RPC
Json RPC就是基于json的远程过程调用,这么解释比较抽象。简单来说,就是post一个json格式的数据调用rpc server中的方法. 而这个json格式是固定的, 总的来说有这么几项:
{ "method": "", "params": [], "id": idNumber }
- method: 方法名
- params: 参数列表
- id: 对过程调用的唯一标识号
二、构建一个Json RPC客户端
<?php class jsonRPCClient { /** * Debug state * * @var boolean */ private $debug; /** * The server URL * * @var string */ private $url; /** * The request id * * @var integer */ private $id; /** * If true, notifications are performed instead of requests * * @var boolean */ private $notification = false; /** * Takes the connection parameters * * @param string $url * @param boolean $debug */ public function __construct($url,$debug = false) { // server URL $this->url = $url; // proxy empty($proxy) ? $this->proxy = '' : $this->proxy = $proxy; // debug state empty($debug) ? $this->debug = false : $this->debug = true; // message id $this->id = 1; } /** * Sets the notification state of the object. In this state, notifications are performed, instead of requests. * * @param boolean $notification */ public function setRPCNotification($notification) { empty($notification) ? $this->notification = false : $this->notification = true; } /** * Performs a jsonRCP request and gets the results as an array * * @param string $method * @param array $params * @return array */ public function __call($method,$params) { // check if (!is_scalar($method)) { throw new Exception('Method name has no scalar value'); } // check if (is_array($params)) { // no keys $params = $params[0]; } else { throw new Exception('Params must be given as array'); } // sets notification or request task if ($this->notification) { $currentId = NULL; } else { $currentId = $this->id; } // prepares the request $request = array( 'method' => $method, 'params' => $params, 'id' => $currentId ); $request = json_encode($request); $this->debug && $this->debug.='***** Request *****'."\n".$request."\n".'***** End Of request *****'."\n\n"; // performs the HTTP POST $opts = array ('127.0.0.1:8545', true); } } catch (\Exception $e) { echo $e->getMessage(); } return call_user_func([self::$client, $method], $params); } public static function getBalance($address) { $method_hash = '0x70a08231'; $method_param1_hex = str_pad(substr($address, 2), 64, '0', STR_PAD_LEFT); $data = $method_hash . $method_param1_hex; $params = ['from' => $address, 'to' => self::CONTRACT, 'data' => $data]; $total_balance = self::eth_call([$params, "latest"]); return hexdec($total_balance) / (pow(10, 18)); } public static function transfer($to, $value) { self::personal_unlockAccount([self::COINBASE, "123456", 3600]); $value = bcpow(10, 18) * $value; $method_hash = '0xa9059cbb'; $method_param1_hex =str_pad(substr($to, 2), 64, '0', STR_PAD_LEFT); $method_param2_hex = str_pad(strval(bc_dechex($value)), 64, '0', STR_PAD_LEFT); $data = $method_hash . $method_param1_hex . $method_param2_hex; $params = ['from' => self::COINBASE, 'to' => self::CONTRACT, 'data' => $data]; return self::eth_sendTransaction([$params]); } }
代码比较简单, 要注意几点:
- transfer函数的value单位很小, 是 10 ^ -18, 所以如果你想转1000个,其实是要乘于 10的18次方, 这里的18是decimals.
- 由于第1点, 应该使用bcpow代替pow函数.
- 不能使用php自带的dechex函数. 因为dechex要求整型不能大于 PHP_INT_MAX, 而这个数在32位机上为4294967295。由于第1 点, 所有的数都要乘于10的18次方, 所以得到的数要远远大于PHP_INT_MAX. 建议自己实现10进制转16进制,如果你不知道如何实现,参考上述代码。
- 在运行某些合约方法, 比如transfer时, 要先unlock用户.
- 发送交易之后, 一定要在服务器端启动挖矿, 这样交易才会真的写入到区块, 比如你调用transfer之后,却发现对方没有到账,先别吃惊,启动挖矿试试。如果想启用自动挖码, 在geth --rpc ...最后加上 --mine.
测试:
<?php var_dump(EthereumRPCClient::personal_newAccount(['password'])); var_dump(EthereumRPCClient::personal_unlockAccount([EthereumRPCClient::COINBASE, "password", 3600]); var_dump(EthereumRPCClient::getBalance("0x...."));

