This time for you to bring PHP and Ethereum client Interactive use of the details, PHP and Ethereum client interaction use of the note, the following is the actual case, together to see.
PHP and ethereum RPC server communication
One, Json RPC
JSON RPC is a remote procedure call based on JSON, so the explanation is more abstract. Simply put, the post is a JSON-formatted data call method in RPC server. And this JSON format is fixed, in general there are a few items:
{ "method": "", "params": [], "id": IdNumber}
Second, build a JSON RPC client
<?phpclass jsonrpcclient {/** * Debug state * * @var Boolean */private $debug; /** * The server URL * * @var String */private $url; /** * The Request ID * * @var integer */private $id; /** * If True, notifications is performed instead of requests * * @var Boolean */private $notification = false; /** * Takes The connection parameters * * @param string $url * @param boolean $debug */Public Function con struct ($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 the state, notifications is 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 $p Arams * @return Array */Public function call ($method, $params) {//Check if (!is_scalar ($method)) {T Hrow 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.= ' * * * * * * * * * * * *. \ n ". $request." \ n "." End of Request * * * * *. " \ 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 '], tr UE)); } return $response [' result ']; } else {return true; }}}?>
Relatively simple code, if lazy, take the past with the line. You can also find an RPC client on packagist.org yourself.
Third, two kinds of methods of calling RPC
There are two types of methods that need to be called. One is the RPC server self-bringing method, and the other is the contract method.
RPC Server method call JSON format
{ "method": "Eth_accounts", "params": [], "id": 1}
List of RPC server self-brought methods
The call-to-bring method is relatively straightforward, with references to the above links, most of which have examples.
Contract method call JSON format
The calling contract method must use the Eth_call in the self-contained method. The contract method name and the contract method parameter list are represented by the params, such as: we want to invoke the Balanceof method in the contract, how should the JSON data be constructed?
First look at the function implementation of Getbalanace:
function balanceof (address _owner) public view Returns (Uint256 balance)
Refining a function prototype:
Balanceof (Address)
Run the command under the Geth console:
WEB3.SHA3 ("balanceof (Address)"). Substring (0, 10)
Get the function hash "0x70a08231"
Assuming address _owner = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750" To be queried, remove the front "0x" and fill 24 0 on the left (the general address length is 42 bits, and after removing ' 0x ' 40 bits ), which constitutes a 64-bit hexadecimal parameter.
The final parameters are "0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750".
Suppose our contract address is "0XAEAB4084194B2A425096FB583FBCD67385210AC3".
You get the final JSON data as:
{ "method": "Eth_call", "params": [{"From": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": " 0xaeab4084194b2a425096fb583fbcd67385210ac3 "," Data ":" 0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750 "}," latest "], " id ": 1}
To send the above JSON data to the server by post, you can call the contract method "balanceof" to query the token balance in the given address.
Call the other methods in the contract also to follow the new way, we will analyze the transfer method, deepen the impression:
First, look at the function implementations in the code:
function transfer (address _to, uint256 _value) public Returns (BOOL)
Next, refine the function prototype:
Transfer (ADDRESS,UINT256)//note commas cannot be followed by spaces
Again, run the SHA3 function on the console:
WEB3.SHA3 ("Transfer (ADDRESS,UINT256)"). Substring (0, 10)
Get the function hash "0XA9059CBB"
The first parameter assumes address _to = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", then go "0x" and fill 0 to 64 bits.
The second parameter assumes uint256 _value = 43776, then goes to "0x" after the hexadecimal "0xab00", which is 0 to 64 bits.
Link up
"0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec57500000000000000000000000000000000000000000000000 00000000000000ab00 "
To build JSON data:
{ "method": "Eth_call", "params": [{"From": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": " 0xaeab4084194b2a425096fb583fbcd67385210ac3 "," Data ":" 0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec575000000000000000000000000000000000000000000000000 0000000000000ab00 "}," latest "], " id ": 1}
Convert the above steps into code.
Building an Ethereum RPC client
<?php require './jsonrpcclient.php ';//php comes with Dechex cannot convert a large integer to hex 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; The account address of the deployment contract is const COINBASE = ' 0x38aabef4cd283ccd5091298dedc88d27c5ec5750 '; Contract Address 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), 0 ', str_Pad_left); $data = $method _hash. $method _param1_hex; $params = [' from ' + $address, ' to ' and ' = ' 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::p ersonal_unlockaccount ([Self::coinbase, "123456", 3600]); $value = Bcpow (Ten) * $value; $method _hash = ' 0XA9059CBB '; $method _param1_hex =str_pad (substr ($to, 2), 0 ', str_pad_left); $method _param2_hex = Str_pad (Strval (Bc_dechex ($value)), 0 ', str_pad_left); $data = $method _hash. $method _param1_hex. $method _param2_hex; $params = [' from ' + self::coinbase, ' to ' and ' = ' self::contract, ' data ' = $data]; Return Self::eth_sendtransaction ([$params]); }}
The code is relatively simple, to note several points:
The value of the transfer function is small, is 10 ^-18, so if you want to turn 1000, in fact, is to take the 10 18 times, where the 18 is decimals.
Because of the 1th, BCPOW should be used instead of the POW function.
You cannot use the Dechex function that comes with PHP. Because the dechex requires that the integral type cannot be greater than Php_int_max, this number is 4294967295 on 32-bit machines. As a result of the 1th, all the numbers have to be multiplied by 10 of the 18, so the number is far greater than Php_int_max. It is recommended that you implement 10 binary to 16 binary, if you do not know how to implement, refer to the above code.
When you run certain contract methods, such as transfer, you first unlock the user.
After sending a transaction, be sure to start mining on the server side, so that the transaction will be really written to the block, such as you call transfer, but found that the other side did not arrive, first don't be surprised, start mining test. If you want to enable the automatic digging code, Geth--rpc ... Finally add--mine.
Test:
<?php var_dump (ethereumrpcclient::p ersonal_newaccount ([' Password ']); Var_dump (ethereumrpcclient::p Ersonal_ Unlockaccount ([Ethereumrpcclient::coinbase, "password", 3600]); Var_dump (Ethereumrpcclient::getbalance ("0x ...")) ;
Believe that you have read the case of this article you have mastered the method, more exciting please pay attention to the PHP Chinese network other related articles!
Recommended reading:
PHP using file_get_contents to send HTTP request steps in detail
Random culling algorithm for PHP implementation