mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-23 08:03:54 +00:00
generate bitcoin address using chain.com API
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/**
|
||||
* generate.php
|
||||
*
|
||||
* generate bitcoin address list file for ss-server/shadowsocks-libev.
|
||||
*
|
||||
* @author Pan Zhibiao <panzhibiao@tangpool.com>
|
||||
* @since 2014-03
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
date_default_timezone_set("Etc/GMT+0");
|
||||
|
||||
/*
|
||||
* config settings
|
||||
*/
|
||||
$_CFG = array();
|
||||
// API Key for Chain.com
|
||||
$_CFG['API-KEY-ID'] = "DEMO-4a5e1e4";
|
||||
// server bitcoin address which receive btc transactions from customers
|
||||
$_CFG['server_baddress'] = "1LDjqcu3rSUkWjL219oZTsHg79S9K6vPwP";
|
||||
$_CFG['cache_file'] = "/var/ss/{$_CFG['server_baddress']}-cached_txs.txt";
|
||||
$_CFG['ss_server_file'] = "/var/ss/{$_CFG['server_baddress']}-list-ss-server.txt";
|
||||
// price for one day, unit: satoshi
|
||||
$_CFG['satoshi_per_day'] = 15000;
|
||||
|
||||
// load exist parsed txs
|
||||
$exist_txs = get_exist_txs();
|
||||
// try load new txs
|
||||
$exist_txs = try_load_txs($exist_txs);
|
||||
// write cache
|
||||
put_exist_txs($exist_txs);
|
||||
// dump file for ss-server
|
||||
dump_for_ss_server($exist_txs);
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
|
||||
function dump_for_ss_server($exist_txs) {
|
||||
global $_CFG;
|
||||
|
||||
$address = array();
|
||||
$now = time();
|
||||
foreach ($exist_txs as $_tx) {
|
||||
// total days
|
||||
$days = bcdiv($_tx['value'], $_CFG['satoshi_per_day'], 2);
|
||||
|
||||
// passed days
|
||||
assert($now > $_tx['timestamp']);
|
||||
$passed_days = bcdiv($now - $_tx['timestamp'], 86400, 2);
|
||||
|
||||
if ($days <= $passed_days) {
|
||||
continue; // expired
|
||||
}
|
||||
$address[] = $_tx['address'];
|
||||
}
|
||||
$str = implode("\n", $address)."\n";
|
||||
|
||||
LOGI("dump ".count($address)." address to ss_server_file");
|
||||
if (file_put_contents($_CFG['ss_server_file'], $str) == false) {
|
||||
LOGI("write file fail: {$_CFG['ss_server_file']}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function try_load_txs($exist_txs) {
|
||||
global $_CFG;
|
||||
|
||||
$next_range = "";
|
||||
$run_flag = 1;
|
||||
while ($run_flag) {
|
||||
$res = get_address_list(100/*limit*/, $next_range);
|
||||
// var_dump($res);
|
||||
usleep(500000); // 500ms
|
||||
|
||||
if (empty($res['body'])) {
|
||||
break; // no more records
|
||||
}
|
||||
if (!empty($res['next_range'])) {
|
||||
$next_range = $res['next_range'];
|
||||
} else {
|
||||
$run_flag = 0; // next page is empty
|
||||
}
|
||||
|
||||
$new_cnt = 0;
|
||||
foreach ($res['body'] as $_tx) {
|
||||
if (!empty($exist_txs[$_tx['hash']])) {
|
||||
continue; // already exist
|
||||
}
|
||||
if (empty($_tx['inputs'][0]['addresses'][0])) {
|
||||
continue; // can't get first input address
|
||||
}
|
||||
// use first input address as payment address
|
||||
$input_addr = $_tx['inputs'][0]['addresses'][0];
|
||||
|
||||
// check server address
|
||||
foreach ($_tx['outputs'] as $_output) {
|
||||
if (empty($_output['addresses'][0]) ||
|
||||
$_output['addresses'][0] != $_CFG['server_baddress']) {
|
||||
continue;
|
||||
}
|
||||
$exist_txs[$_tx['hash']] = array(
|
||||
'address' => $input_addr,
|
||||
'value' => $_output['value'],
|
||||
'timestamp' => strtotime($_tx['chain_received_at']),
|
||||
);
|
||||
$new_cnt++;
|
||||
LOGI("find new tx: {$_tx['hash']}, value: {$_output['value']}, address: {$input_addr}, received: {$_tx['chain_received_at']}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($new_cnt == 0 && count($res['body']) > 0) {
|
||||
break; // stop, mean all records are exists
|
||||
}
|
||||
}
|
||||
return $exist_txs;
|
||||
}
|
||||
|
||||
function get_exist_txs() {
|
||||
global $_CFG;
|
||||
if (is_readable($_CFG['cache_file'])) {
|
||||
return json_decode(file_get_contents($_CFG['cache_file']), 1);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
function put_exist_txs($exist_txs) {
|
||||
global $_CFG;
|
||||
if (!file_put_contents($_CFG['cache_file'], json_encode($exist_txs))) {
|
||||
LOGI("file put contents fail, file: {$_CFG['cache_file']}");
|
||||
}
|
||||
}
|
||||
|
||||
function get_address_list($limit, $range) {
|
||||
global $_CFG;
|
||||
|
||||
$res = array();
|
||||
$custom_headers = array();
|
||||
|
||||
$url = "https://api.chain.com/v2/bitcoin/addresses/";
|
||||
$url .= rawurlencode($_CFG['server_baddress'])."/transactions?api-key-id=";
|
||||
$url .= rawurlencode($_CFG['API-KEY-ID']);
|
||||
$url .= "&limit=".intval($limit);
|
||||
if ($range != "") {
|
||||
$custom_headers[] = "Range: ".$range;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
if (!empty($custom_headers)) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $custom_headers);
|
||||
}
|
||||
|
||||
$r = curl_exec($ch);
|
||||
$curl_errno = curl_errno($ch);
|
||||
$curl_error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curl_errno > 0) {
|
||||
LOGI("curl request fail, errno: {$curl_errno}, error: {$curl_error}");
|
||||
return false;
|
||||
}
|
||||
|
||||
list($header, $body) = explode("\r\n\r\n", $r, 2);
|
||||
// find next range
|
||||
preg_match("/Next-Range: ([^\r]*)/", $header, $matches);
|
||||
if (!empty($matches[1])) {
|
||||
$res['next_range'] = $matches[1];
|
||||
}
|
||||
$res['body'] = json_decode($body, 1);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
function LOGI($msg) {
|
||||
echo date("Y-m-d H:i:s"), " $msg\n";
|
||||
}
|
||||
Reference in New Issue
Block a user