Maison > Article > développement back-end > Explication détaillée de l'interaction entre le client PHP et Ethereum
Cet article vous indique les points de connaissances pertinents sur l'interaction entre les clients PHP et Ethereum. Il a une certaine valeur de référence. Les amis dans le besoin peuvent le suivre et en tirer des leçons.
php communique avec le serveur Ethereum RPC
1 Json RPC
Json RPC est basé. sur l'appel de procédure distante de json, cette explication est relativement abstraite. Pour faire simple, il s'agit de poster une donnée au format json et d'appeler la méthode dans le serveur rpc. Le format json est fixe. En général, on retrouve les éléments suivants :
{ "method": "", "params": [], "id": idNumber }<.>
2. Créez un client 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; } } } ?>C'est un code relativement simple. Si vous êtes paresseux, prenez-le et utilisez-le. Vous pouvez également aller sur packagist.org pour trouver vous-même un client rpc
3. Deux types de méthodes pour appeler RPC
{ "method": "eth_accounts", "params": [], "id": 1 }Liste des méthodes du serveur RPC avec les méthodes Appeler la méthode intégrée est relativement simple, reportez-vous au lien ci-dessus, la plupart d'entre elles ont des exemples. Appel de méthode de contrat au format json
function balanceOf(address _owner) public view returns (uint256 balance)Extraire le prototype de fonction :
balanceOf(address)Exécutez la commande sous la console Geth :
web3.sha3("balanceOf(address)").substring(0, 10)Obtenez le hachage de fonction "0x70a08231"Supposons que l'adresse à interroger adresse _owner = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", puis supprimez le "0x" devant et ajoutez 24 zéros sur le gauche (la longueur générale de l'adresse est de 42 bits, et elle est de 40 bits après avoir supprimé le « 0x ») pour former un paramètre hexadécimal de 64 bits. 750" Supposons que notre adresse contractuelle soit "0xaeab4084194B2a425 096fb583Fbcd67385210ac3". alors les données json finales obtenues sont :
{ "method": "eth_call", "params": [{"from": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": "0xaeab4084194B2a425096fb583Fbcd67385210ac3", "data": "0x70a0823100000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750"}, "latest"], "id": 1 }Envoyer les données json ci-dessus au serveur en mode post, vous pouvez alors appeler la méthode du contrat "balanceOf" pour interroger le solde du jeton à l'adresse donnée.L'appel d'autres méthodes dans le contrat doit également suivre la méthode ci-dessus. méthode à nouveau pour approfondir notre impression :Tout d'abord, regardez l'implémentation de la fonction dans le code :
function transfer(address _to, uint256 _value) public returns (bool)Deuxièmement, extrayez la fonction prototype :
transfer(address,uint256) //注意逗号后面不能有空格Troisièmement, exécutez la fonction sha3 sur la console :
web3.sha3("transfer(address,uint256)").substring(0, 10)Obtenez le hachage de fonction "0xa9059cbb"Le premier paramètre suppose l'adresse _to = "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", puis allez à "0x", remplissez les zéros à 64 bits.
En supposant que uint256 _value = 43776 pour le deuxième paramètre, il sera converti en "0xab00" hexadécimal, puis supprimera "0x" et complétera les zéros à 64 bits. 83ccd5091298dedc88d27c5ec57500000000000000000000000000000000000000000000000000000000000ab00"
à partir de l'adresse du cédant
{ "method": "eth_call", "params": [{"from": "0x38aabef4cd283ccd5091298dedc88d27c5ec5750", "to": "0xaeab4084194B2a425096fb583Fbcd67385210ac3", "data": "0xa9059cbb00000000000000000000000038aabef4cd283ccd5091298dedc88d27c5ec5750000000000000000000000000000000000000000000000000000000000000ab00"}, "latest"], "id": 1 }adresse du contrat
Le code est relativement simple, il y a quelques points à noter :
<?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]); } }L'unité de valeur de la fonction de transfert est très petite, qui est 10^-18, donc si vous souhaitez transférer 1000 fois, vous devez en fait multiplier par 10 à la puissance 18, 18 ici est une décimale.
En raison du point 1, bcpow doit être utilisé à la place de la fonction pow.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!