PHP and Ethereum Client interaction using the detailed

Source: Internet
Author: User
Tags http post
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}
    • Method: Methods Name

    • Params: Parameter list

    • ID: A unique identification number for a procedure call

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}
    • From transfer-out address

    • To contract address

    • Data the hexadecimal number obtained by the above operation

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.