這次帶給大家php與ethereum客戶端互動使用詳解,php與ethereum客戶端互動使用的注意事項有哪些,以下就是實戰案例,一起來看一下。
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 ('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格式
{ "method": "eth_accounts", "params": [], "id": 1 }
RPC Server自帶方法的清單
呼叫自帶方法比較簡單,參考上述鏈接,大部分都有示例.
合約方法調用json格式
調用合約方法必須使用自帶方法中的eth_call. 而合約方法名稱和合約方法參數列表則使用params進行體現, 例如: 我們要呼叫合約中的balanceOf方法, 則json資料應該如何建構呢?
首先看看getBalanace的函數實作:
function balanceOf(address _owner) public view returns (uint256 balance)
提煉出函數原型:
balanceOf(address)
在geth控制台下執行指令:
web3.sha3("balanceOf(address)").substring(0, 10)
得到函數hash "0x70a08231"
假設待查詢的位址address _owner = "0x38aabef4cd283ccd5091298dededc88d27c5,ec570"5, ecdc78 0x", 並在左邊補24個零(一般位址長度為42位元, 去掉'0x'後為40位元),構成64位元十六進位參數.
最後得到的參數為"0x70a08231000000000000000000000000000000003852 0 "
假設我們的合約位址為"0xaeab4084194B2a425096fb583Fbcd67385210ac3".
則得到最終的json資料為:
{ "method": "eth_call", "params": [{"from": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": "0xaeab4084194B2a425096fb583Fbcd67385210ac3", "data": "0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750"}, "latest"], "id": 1 }
#
function transfer(address _to, uint256 _value) public returns (bool)json資料以post方式發送給伺服器,就把以上給伺服器可以呼叫合約方法"balanceOf", 查詢給定的地址中的代幣餘額.調用合約中的其他方法也要新遵循上面的方式, 我們再分析一下transfer方法, 加深印象:首先, 看看程式碼中的函數實作:
transfer(address,uint256) //注意逗号后面不能有空格其次, 提煉出函數原型:
web3.sha3("transfer(address,uint256)").substring(0, 10)再次, 在控制台運行sha3函數:
{ "method": "eth_call", "params": [{"from": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": "0xaeab4084194B2a425096fb583Fbcd67385210ac3", "data": "0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750000000000000000000000000000000000000000000000000000000000000ab00"}, "latest"], "id": 1 }得到函數hash "0xa9059cbb"第一個參數假設address _to = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", 則去"0x", 補零到dc88d27c5ec5750", 則去"0x", 補零到dc88d27c5ec5750", 則去"0x", 補零到dc88d27c5ec5750", 則去"0x", 補零到64位元。 _value = 43776, 則化為十六進位"0xab00"後, 去"0x", 補零到64位.連接起來#"0xa9059c000000000000000000000000038 0000000000000000000000000000000000000000000000000000000000ab00"建構json資料:
<?php 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'; public static function callStatic($method, $params) { $params = count($params) < 1 ? [] : $params[0]; try { if (is_null(self::$client)) { self::$client = new jsonRPCClient('http://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]); } }
- from 轉出者位址
- to 合約位址
- data上述運算得到的十六進位數
<?php var_dump(EthereumRPCClient::personal_newAccount(['password'])); var_dump(EthereumRPCClient::personal_unlockAccount([EthereumRPCClient::COINBASE, "password", 3600]); var_dump(EthereumRPCClient::getBalance("0x...."));程式碼比較簡單, 要注意幾點:
- 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...."));
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
PHP使用file_get_contents发送http请求步骤详解
以上是php與ethereum客戶端互動使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

tomakephpapplicationsfaster,關注台詞:1)useopcodeCachingLikeLikeLikeLikeLikePachetoStorePreciledScompiledScriptbyTecode.2)MinimimiedAtabaseSqueriSegrieSqueriSegeriSybysequeryCachingandeffeftExting.3)Leveragephp7 leveragephp7 leveragephp7 leveragephpphp7功能forbettercodeefficy.4)

到ImprovephPapplicationspeed,關注台詞:1)啟用opcodeCachingwithapCutoredUcescriptexecutiontime.2)實現databasequerycachingingusingpdotominiminimizedatabasehits.3)usehttp/2tomultiplexrequlexrequestsandreduceconnection.4 limitesclection.4.4

依赖注入(DI)通过显式传递依赖关系,显著提升了PHP代码的可测试性。1)DI解耦类与具体实现,使测试和维护更灵活。2)三种类型中,构造函数注入明确表达依赖,保持状态一致。3)使用DI容器管理复杂依赖,提升代码质量和开发效率。

DatabasequeryoptimizationinPHPinvolvesseveralstrategiestoenhanceperformance.1)Selectonlynecessarycolumnstoreducedatatransfer.2)Useindexingtospeedupdataretrieval.3)Implementquerycachingtostoreresultsoffrequentqueries.4)Utilizepreparedstatementsforeffi

phpisusedforsenderemailsduetoitsbuilt-inmail()函數andsupportivelibrariesLikePhpMailerAndSwiftMailer.1)usethemail()functionForbasiceMails,butithasimails.2)butithasimail.2)

PHP性能瓶颈可以通过以下步骤解决:1)使用Xdebug或Blackfire进行性能分析,找出问题所在;2)优化数据库查询并使用缓存,如APCu;3)使用array_filter等高效函数优化数组操作;4)配置OPcache进行字节码缓存;5)优化前端,如减少HTTP请求和优化图片;6)持续监控和优化性能。通过这些方法,可以显著提升PHP应用的性能。

依賴性注射(DI)InphpisadesignPatternthatManages和ReducesClassDeptions,增強量強制性,可驗證性和MATIALWINABIOS.ItallowSpasspassingDepentenciesLikEdenciesLikedAbaseConnectionStoclasseconnectionStoclasseSasasasasareTers,interitationAseTestingEaseTestingEaseTestingEaseTestingEasingAndScalability。

cachingimprovesphpermenceByStorcyResultSofComputationsorqucrouctationsorquctationsorquickretrieval,reducingServerLoadAndenHancingResponsetimes.feftectivestrategiesinclude:1)opcodecaching,whereStoresCompiledSinmememorytssinmemorytoskipcompliation; 2)datacaching datacachingsingMemccachingmcachingmcachings


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

禪工作室 13.0.1
強大的PHP整合開發環境

WebStorm Mac版
好用的JavaScript開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver CS6
視覺化網頁開發工具