(编辑:jimmy 日期: 2026/1/13 浏览:2)
php与ethereum rpc server通信
一、Json RPC
Json RPC就是基于json的远程过程调用,这么解释比较抽象。简单来说,就是post一个json格式的数据调用rpc server中的方法. 而这个json格式是固定的, 总的来说有这么几项:
{
"method": "",
"params": [],
"id": idNumber
}
二、构建一个Json RPC客户端
<"\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;
}
}
}
"htmlcode">
{
"method": "eth_accounts",
"params": [],
"id": 1
}
RPC Server自带方法的列表
调用自带方法比较简单,参考上述链接,大部分都有示例.
合约方法调用json格式
调用合约方法必须使用自带方法中的eth_call. 而合约方法名称和合约方法参数列表则使用params进行体现, 比如: 我们要调用合约中的balanceOf方法, 则json数据应该如何构造呢"htmlcode">
function balanceOf(address _owner) public view returns (uint256 balance)
提炼出函数原型:
balanceOf(address)
在geth控制台下运行命令:
web3.sha3("balanceOf(address)").substring(0, 10)
得到函数hash "0x70a08231"
假设待查询的地址 address _owner = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", 则去掉前面的"0x", 并在左边补24个零(一般地址长度为42位, 去掉'0x'后为40位),构成64位十六进制参数.
最终得到的参数为 "0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750"
假设我们的合约地址为 "0xaeab4084194B2a425096fb583Fbcd67385210ac3".
则得到最终的json数据为:
{
"method": "eth_call",
"params": [{"from": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": "0xaeab4084194B2a425096fb583Fbcd67385210ac3", "data": "0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750"}, "latest"],
"id": 1
}
把以上json数据以post方式发送给服务器,就可以调用合约方法"balanceOf", 查询给定的地址中的代币余额.
调用合约中的其他方法也要新遵循上面的方式, 我们再分析一下transfer方法, 加深印象:
首先, 看看代码中的函数实现:
function transfer(address _to, uint256 _value) public returns (bool)
其次, 提炼出函数原型:
transfer(address,uint256) //注意逗号后面不能有空格
再次, 在控制台运行sha3函数:
web3.sha3("transfer(address,uint256)").substring(0, 10)
得到函数hash "0xa9059cbb"
第一个参数假设 address _to = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", 则去"0x", 补零到64位.
第二个参数假设 uint256 _value = 43776, 则化为十六进制"0xab00"后, 去"0x", 补零到64位.
连接起来
"0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750000000000000000000000000000000000000000000000000000000000000ab00"
构建json数据:
{
"method": "eth_call",
"params": [{"from": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": "0xaeab4084194B2a425096fb583Fbcd67385210ac3", "data": "0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750000000000000000000000000000000000000000000000000000000000000ab00"}, "latest"],
"id": 1
}
把以上的步骤转化为代码.
构建一个以太坊RPC client
<"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]);
}
}
代码比较简单, 要注意几点:
测试:
<"password", 3600]);
var_dump(EthereumRPCClient::getBalance("0x...."));