加入收藏 | 设为首页 | 会员中心 | 我要投稿 草根网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > PHP > 正文

详解php与ethereum客户端 交互

发布时间:2023-02-15 11:12:43 所属栏目:PHP 来源:
导读:  php与ethereum rpc server通信
  一、Json RPC
  Json RPC就是基于json的远程过程调用,这么解释比较抽象。简单来说,就是post一个json格式的数据调用rpc server中的方法. 而这个json格式是固定的,总的来说
  php与ethereum rpc server通信
  一、Json RPC
  Json RPC就是基于json的远程过程调用,这么解释比较抽象。简单来说,就是post一个json格式的数据调用rpc server中的方法. 而这个json格式是固定的,总的来说有这么几项:
 
  method: 方法名
  params: 参数列表
  id: 对过程调用的唯一标识号
  二、构建一个Json RPC客户端
  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 ('http' => array (
            'method' => 'POST','header' => 'Content-type: application/json','content' => $request
            ));
  $context = stream_context_create($opts);
  if ($fp = fopen($this->url,'r',false,$context)) {
    $response = '';
    while($row = fgets($fp)) {
      $response.= trim($row)."\n";
    }
    $this->debug && $this->debug.='***** Server response *****'."\n".$response.'***** End of server response *****'."\n";
    $response = json_decode($response,true);
  } else {
    throw new Exception('Unable to connect to '.$this->url);
  }
 
  // debug output
  if ($this->debug) {
    echo nl2br($debug);
  }
 
  // final checks and return
  if (!$this->notification) {
    // check
    if ($response['id'] != $currentId) {
      throw new Exception('Incorrect response id (request id: '.$currentId.',response id: '.$response['id'].')');
    }
    if (!is_null($response['error'])) {
      throw new Exception('Request error: '. var_export($response['error'],true));
    }
 
    return $response['result'];
 
  } else {
    return true;
  }
  }
  }
  ?>
 
  比较简单的代码,如果比较懒,拿过去用就行了。也可以上packagist.org自己找一个rpc client.
 
  三、调用RPC的两类方法
  有两类方法需要调用. 一类是RPC server自带方法,另一类就是合约方法.
 
  RPC server方法调用json格式
 
  RPC Server自带方法的列表
 
  调用自带方法比较简单,参考上述链接,大部分都有示例.
 
  合约方法调用json格式
 
  调用合约方法必须使用自带方法中的eth_call. 而合约方法名称和合约方法参数列表则使用params进行体现,比如: 我们要调用合约中的balanceOf方法,则json数据应该如何构造呢?
 
  首先看看getBalanace的函数实现:
 
  提炼出函数原型:
 
  在geth控制台下运行命令:
 
  得到函数hash "0x70a08231"
 
  假设待查询的地址 address _owner = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750",则去掉前面的"0x",并在左边补24个零(一般地址长度为42位,去掉'0x'后为40位),构成64位十六进制参数.
 
  最终得到的参数为 "0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750"
 
  假设我们的合约地址为 "0xaeab4084194B2a425096fb583Fbcd67385210ac3".
 
  则得到最终的json数据为:
 
  把以上json数据以post方式发送给服务器,就可以调用合约方法"balanceOf",查询给定的地址中的代币余额.
 
  调用合约中的其他方法也要新遵循上面的方式,我们再分析一下transfer方法,加深印象:
 
  首先,看看代码中的函数实现:
 
  其次,提炼出函数原型:
 
  再次,在控制台运行sha3函数:
 
  得到函数hash "0xa9059cbb"
 
  第一个参数假设 address _to = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750",则去"0x",补零到64位.
 
  第二个参数假设 uint256 _value = 43776,则化为十六进制"0xab00"后,去"0x",补零到64位.
 
  连接起来
 
  "0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750000000000000000000000000000000000000000000000000000000000000ab00"
 
  构建json数据:
 
  from 转出者地址
  to 合约地址
  data 上述操作得到的十六进制数
  把以上的步骤转化为代码.
 
  构建一个以太坊RPC client
 
  require './jsonRPCClient.php';
  //php自带的dechex无法把大整型转换为十六进制
  function bc_dechex($decimal)
  {
  $result = [];
 
  while ($decimal != 0) {
  $mod = $decimal % 16;
  $decimal = floor($decimal / 16);
  array_push($result,dechex($mod));
  }
 
  return join(array_reverse($result));
  }
 
  class EthereumRPCClient
  {
  public static $client = null;
 
  //布署合约的账户地址
  const COINBASE = '0x38aabef4cd283ccd5091298dedc88d27c5ec5750';
 
  //合约地址
  const CONTRACT = '0xaeab4084194B2a425096fb583Fbcd67385210ac3';
 

(编辑:草根网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章