Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 82fc51b

Browse files
committed
initial commit
0 parents  commit 82fc51b

7 files changed

Lines changed: 5873 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/.settings
2+
.buildpath
3+
/.git

.project

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>bitcoin-php</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.wst.validation.validationbuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>org.eclipse.dltk.core.scriptbuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
</buildSpec>
19+
<natures>
20+
<nature>org.eclipse.php.core.PHPNature</nature>
21+
</natures>
22+
</projectDescription>

src/bitcoin.inc

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
<?php
2+
3+
define("BITCOIN_ADDRESS_VERSION", "00");// this is a hex byte
4+
/**
5+
* Bitcoin utility functions class
6+
* @author theymos (functionality)
7+
* @author Mike Gogulski (encapsulation, string abstraction, PHPDoc)
8+
*/
9+
class Bitcoin {
10+
11+
/*
12+
* Bitcoin utility functions by theymos
13+
* Via http://www.bitcoin.org/smf/index.php?topic=1844.0
14+
* hex input must be in uppercase, with no leading 0x
15+
*/
16+
private static $hexchars = "0123456789ABCDEF";
17+
private static $base58chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
18+
19+
/**
20+
* Convert a hex string into a (big) integer
21+
* @param string $hex
22+
* @return int
23+
* @access private
24+
*/
25+
private function decodeHex($hex) {
26+
$hex = strtoupper($hex);
27+
$return = "0";
28+
for ($i = 0; $i < strlen($hex); $i++) {
29+
$current = (string) strpos(self::$hexchars, $hex[$i]);
30+
$return = (string) bcmul($return, "16", 0);
31+
$return = (string) bcadd($return, $current, 0);
32+
}
33+
return $return;
34+
}
35+
36+
/**
37+
* Convert an integer into a hex string
38+
* @param int $dec
39+
* @return string
40+
* @access private
41+
*/
42+
private function encodeHex($dec) {
43+
$return = "";
44+
while (bccomp($dec, 0) == 1) {
45+
$dv = (string) bcdiv($dec, "16", 0);
46+
$rem = (integer) bcmod($dec, "16");
47+
$dec = $dv;
48+
$return = $return . self::$hexchars[$rem];
49+
}
50+
return strrev($return);
51+
}
52+
53+
/**
54+
* Convert a Base58-encoded integer into the equivalent hex string representation
55+
* @param string $base58
56+
* @return string
57+
* @access private
58+
*/
59+
private function decodeBase58($base58) {
60+
$origbase58 = $base58;
61+
62+
$return = "0";
63+
for ($i = 0; $i < strlen($base58); $i++) {
64+
$current = (string) strpos(Bitcoin::$base58chars, $base58[$i]);
65+
$return = (string) bcmul($return, "58", 0);
66+
$return = (string) bcadd($return, $current, 0);
67+
}
68+
69+
$return = self::encodeHex($return);
70+
71+
//leading zeros
72+
for ($i = 0; $i < strlen($origbase58) && $origbase58[$i] == "1"; $i++) {
73+
$return = "00" . $return;
74+
}
75+
76+
if (strlen($return) % 2 != 0) {
77+
$return = "0" . $return;
78+
}
79+
80+
return $return;
81+
}
82+
83+
/**
84+
* Convert a hex string representation of an integer into the equivalent Base58 representation
85+
* @param string $hex
86+
* @return string
87+
* @access private
88+
*/
89+
private function encodeBase58($hex) {
90+
if (strlen($hex) % 2 != 0) {
91+
die("encodeBase58: uneven number of hex characters");
92+
}
93+
$orighex = $hex;
94+
95+
$hex = self::decodeHex($hex);
96+
$return = "";
97+
while (bccomp($hex, 0) == 1) {
98+
$dv = (string) bcdiv($hex, "58", 0);
99+
$rem = (integer) bcmod($hex, "58");
100+
$hex = $dv;
101+
$return = $return . self::$base58chars[$rem];
102+
}
103+
$return = strrev($return);
104+
105+
//leading zeros
106+
for ($i = 0; $i < strlen($orighex) && substr($orighex, $i, 2) == "00"; $i += 2) {
107+
$return = "1" . $return;
108+
}
109+
110+
return $return;
111+
}
112+
113+
/**
114+
* Convert a 160-bit Bitcoin hash to a Bitcoin address
115+
* @author theymos
116+
* @param string $hash160
117+
* @param string $addressversion
118+
* @return string Bitcoin address
119+
* @access public
120+
*/
121+
public static function hash160ToAddress($hash160, $addressversion = BITCOIN_ADDRESS_VERSION) {
122+
$hash160 = $addressversion . $hash160;
123+
$check = pack("H*", $hash160);
124+
$check = hash("sha256", hash("sha256", $check, true));
125+
$check = substr($check, 0, 8);
126+
$hash160 = strtoupper($hash160 . $check);
127+
return self::encodeBase58($hash160);
128+
}
129+
130+
/**
131+
* Convert a Bitcoin address to a 160-bit Bitcoin hash
132+
* @author theymos
133+
* @param string $addr
134+
* @return string Bitcoin hash
135+
* @access public
136+
*/
137+
public static function addressToHash160($addr) {
138+
$addr = self::decodeBase58($addr);
139+
$addr = substr($addr, 2, strlen($addr) - 10);
140+
return $addr;
141+
}
142+
143+
/**
144+
* Determine if a string is a valid Bitcoin address
145+
* @author theymos
146+
* @param string $addr String to test
147+
* @param string $addressversion
148+
* @return boolean
149+
* @access public
150+
*/
151+
public static function checkAddress($addr, $addressversion = BITCOIN_ADDRESS_VERSION) {
152+
$addr = self::decodeBase58($addr);
153+
if (strlen($addr) != 50) {
154+
return false;
155+
}
156+
$version = substr($addr, 0, 2);
157+
if (hexdec($version) > hexdec($addressversion)) {
158+
return false;
159+
}
160+
$check = substr($addr, 0, strlen($addr) - 8);
161+
$check = pack("H*", $check);
162+
$check = strtoupper(hash("sha256", hash("sha256", $check, true)));
163+
$check = substr($check, 0, 8);
164+
return $check == substr($addr, strlen($addr) - 8);
165+
}
166+
167+
/**
168+
* Convert the input to its 160-bit Bitcoin hash
169+
* @param string $data
170+
* @return string
171+
* @access private
172+
*/
173+
private function hash160($data) {
174+
$data = pack("H*", $data);
175+
return strtoupper(hash("ripemd160", hash("sha256", $data, true)));
176+
}
177+
178+
/**
179+
* Convert a Bitcoin public key to a 160-bit Bitcoin hash
180+
* @param string $pubkey
181+
* @return string
182+
* @access public
183+
*/
184+
public static function pubKeyToAddress($pubkey) {
185+
return self::hash160ToAddress($this->hash160($pubkey));
186+
}
187+
188+
/**
189+
* Remove leading "0x" from a hex value if present.
190+
* @param string $string
191+
* @return string
192+
* @access public
193+
*/
194+
public static function remove0x($string) {
195+
if (substr($string, 0, 2) == "0x" || substr($string, 0, 2) == "0X") {
196+
$string = substr($string, 2);
197+
}
198+
return $string;
199+
}
200+
}
201+
202+
class BitcoinClientException extends ErrorException {
203+
// Redefine the exception so message and severity aren't optional
204+
public function __construct($message, $code = 0, $severity = E_USER_NOTICE, Exception $previous = null) {
205+
parent::__construct($message, $code, $severity, $previous);
206+
}
207+
208+
public function __toString() {
209+
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
210+
}
211+
}
212+
213+
require_once(dirname(__FILE__) . "/includes/xmlrpc.inc");
214+
require_once(dirname(__FILE__) . "/includes/jsonrpc.inc");
215+
216+
/**
217+
* Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S]
218+
* @author Mike Gogulski
219+
*/
220+
class BitcoinClient extends jsonrpc_client {
221+
222+
/**
223+
* Create a jsonrpc_client object to talk to the bitcoin server and return it, or false on failure.
224+
* @param string $scheme "http" or "https"
225+
* @param string $username User name to use in connection the Bitcoin server's JSON-RPC interface
226+
* @param string $password Server password
227+
* @param string $address Server hostname or IP address
228+
* @param mixed $port Server port (string or integer)
229+
* @param string $certificate_path Path on the local filesystem to server's PEM certificate (ignored if $scheme != "https")
230+
* @param integer $debug_level 0 (default) = no debugging; 1 = echo JSON-RPC messages received to stdout; 2 = log transmitted messages also
231+
* @return jsonrpc_client
232+
* @access public
233+
* @throws BitcoinClientException
234+
*/
235+
public function __construct($scheme, $username, $password, $address = "localhost", $port = 8332, $certificate_path = '', $debug_level = 0) {
236+
$scheme = strtolower($scheme);
237+
if ($scheme != "http" && $scheme != "https")
238+
throw new BitcoinClientException("Scheme must be http or https");
239+
if (empty($username))
240+
throw new BitcoinClientException("Username must be non-blank");
241+
if (empty($password))
242+
throw new BitcoinClientException("Password must be non-blank");
243+
$port = (string) $port;
244+
if (empty($port) || !is_numeric($port) || $port < 0 || $port > 65535 || floatval($port) != intval($port))
245+
throw new BitcoinClientException("Port must be an integer and between 0 and 65535");
246+
if (!empty($certificate_path) && !is_readable($certificate_path))
247+
throw new BitcoinClientException("Certificate file " . $certificate_path . " is not readable");
248+
$uri = $scheme . "://" . $username . ":" . $password . "@" . $address . ":" . $port . "/";
249+
parent::__construct($uri);
250+
$this->setDebug($debug_level);
251+
$this->setSSLVerifyHost(0);
252+
if ($scheme == "https")
253+
if (!empty($certificate_path))
254+
$this->setCaCertificate($certificate_path);
255+
else
256+
$this->setSSLVerifyPeer(false);
257+
}
258+
259+
/**
260+
* Test if the connection to the Bitcoin JSON-RPC server is working
261+
*
262+
* The check is done by calling the server's getinfo() method and checking for a fault.
263+
* @return mixed boolean TRUE if successful, cURL fault string otherwise
264+
* @access public
265+
* @throws none
266+
*/
267+
public function can_connect() {
268+
try {
269+
$r = $this->query("getinfo");
270+
} catch (BitcoinClientException $e) {
271+
return $e->getMessage();
272+
}
273+
return true;
274+
}
275+
276+
/**
277+
* Convert a Bitcoin server query argument to a jsonrpcval
278+
* @param mixed $a
279+
* @return jsonrpcval
280+
* @throws none
281+
*/
282+
private function query_arg_to_parameter($a) {
283+
$type = "";// "string" is encoded as this default type value in xmlrpc.inc
284+
if (is_numeric($a)) {
285+
if (intval($a) != floatval($a)) {
286+
$a = intval($a);
287+
$type = "int";
288+
} else {
289+
$a = floatval($a);
290+
$type = "double";
291+
}
292+
}
293+
if (is_bool($a))
294+
$type = "boolean";
295+
if (is_int($a))
296+
$type = "int";
297+
if (is_float($a))
298+
$type = "double";
299+
if (is_array($a))
300+
$type = "array";
301+
return new jsonrpcval($a, $type);
302+
}
303+
304+
/**
305+
* Send a JSON-RPC message and optional parameter arguments to the server
306+
* @param string $message
307+
* @param mixed $args ...
308+
* @return mixed
309+
* @throws BitcoinClientException
310+
* @see xmlrpc.inc:php_xmlrpc_decode()
311+
*/
312+
public function query($message) {
313+
if (!$message || empty($message))
314+
throw new BitcoinClientException("Client query requires a message");
315+
$msg = new jsonrpcmsg($message);
316+
if (func_num_args() > 1) {
317+
array_shift($func_get_args());
318+
foreach ($func_get_args() as $a) {
319+
$msg->addParam(query_arg_to_parameter($a));
320+
}
321+
}
322+
$response = $this->send($msg);
323+
if ($response->faultCode()) {
324+
throw new BitcoinClientException($response->faultString());
325+
}
326+
return php_xmlrpc_decode($response->value());
327+
}
328+
}

0 commit comments

Comments
 (0)