Commit 80f2bde6 authored by shajiaiming's avatar shajiaiming

Merge branch 'feature/cross_chain' into 'master'

Feature/cross chain See merge request !111
parents 17908887 d524195e
......@@ -52,6 +52,7 @@ class CrossChainController extends BaseController
$data['txhex'] = $val['tx'];
$data['transfer_url'] = $val['url'];
$data['step'] = $val['step'];
$data['amount'] = isset($val['amount']) ? $val['amount'] : 0;
$model->load($data, '');
$model->save();
}
......@@ -123,7 +124,7 @@ class CrossChainController extends BaseController
$code = -1;
$msg = 'fail';
$data = null;
$step = 0;
$step = $amount = 0;
$request = Yii::$app->request;
if (!$request->isGet) {
$msg = '请求错误!';
......@@ -146,6 +147,7 @@ class CrossChainController extends BaseController
sort($model);
foreach ($model as $key => $val) {
$amount = $val['amount'];
//未交易
if ('0' == $val['send_result'] && '0' == $val['query_result'] && '0' == $val['msg']) {
$step = $key + 1;
......@@ -189,7 +191,8 @@ class CrossChainController extends BaseController
doEnd :
$data = [
'step' => $step
'step' => $step,
'amount' => (int)$amount
];
return ['code' => $code, 'msg' => $msg, 'data' => $data];
}
......
......@@ -103,11 +103,24 @@ class Curl
*
* @return mixed response
*/
protected $connect_timeout_ms;
protected $timeout_ms;
public function __construct($config = [])
{
if (!empty($config)) {
$this->connect_timeout_ms = isset($config['connect_timeout']) ? $config['connect_timeout'] : 10;
$this->timeout_ms = isset($config['timeout_ms']) ? $config['timeout_ms'] : 100;
}
}
public function get($url, $raw = true)
{
$this->_baseUrl = $url;
return $this->_httpRequest('GET', $raw);
}
/**
* Start performing HEAD-HTTP-Request
*
......@@ -120,6 +133,7 @@ class Curl
$this->_baseUrl = $url;
return $this->_httpRequest('HEAD');
}
/**
* Start performing POST-HTTP-Request
*
......@@ -133,6 +147,7 @@ class Curl
$this->_baseUrl = $url;
return $this->_httpRequest('POST', $raw);
}
/**
* Start performing PUT-HTTP-Request
*
......@@ -146,6 +161,7 @@ class Curl
$this->_baseUrl = $url;
return $this->_httpRequest('PUT', $raw);
}
/**
* Start performing PATCH-HTTP-Request
*
......@@ -160,8 +176,9 @@ class Curl
$this->setHeaders([
'X-HTTP-Method-Override' => 'PATCH'
]);
return $this->_httpRequest('POST',$raw);
return $this->_httpRequest('POST', $raw);
}
/**
* Start performing DELETE-HTTP-Request
*
......@@ -175,6 +192,7 @@ class Curl
$this->_baseUrl = $url;
return $this->_httpRequest('DELETE', $raw);
}
/**
* Set curl option
*
......@@ -194,6 +212,7 @@ class Curl
//return self
return $this;
}
/**
* Set get params
*
......@@ -210,6 +229,7 @@ class Curl
//return self
return $this;
}
/**
* Set get params
*
......@@ -227,6 +247,7 @@ class Curl
//return self
return $this;
}
/**
* Set raw post data allows you to post any data format.
*
......@@ -242,6 +263,7 @@ class Curl
//return self
return $this;
}
/**
* Set get params
*
......@@ -259,6 +281,7 @@ class Curl
//return self
return $this;
}
/**
* Get URL - return URL parsed with given params
*
......@@ -267,11 +290,12 @@ class Curl
public function getUrl()
{
if (Count($this->_getParams) > 0) {
return $this->_baseUrl.'?'.http_build_query($this->_getParams);
return $this->_baseUrl . '?' . http_build_query($this->_getParams);
} else {
return $this->_baseUrl;
}
}
/**
* Set curl options
*
......@@ -284,6 +308,7 @@ class Curl
$this->_options = $options + $this->_options;
return $this;
}
/**
* Set multiple headers for request.
*
......@@ -298,11 +323,11 @@ class Curl
$parsedHeader = [];
//collect currently set headers
foreach ($this->getRequestHeaders() as $header => $value) {
array_push($parsedHeader, $header.':'.$value);
array_push($parsedHeader, $header . ':' . $value);
}
//parse header into right format key:value
foreach ($headers as $header => $value) {
array_push($parsedHeader, $header.':'.$value);
array_push($parsedHeader, $header . ':' . $value);
}
//set headers
$this->setOption(
......@@ -312,6 +337,7 @@ class Curl
}
return $this;
}
/**
* Set a single header for request.
*
......@@ -326,11 +352,11 @@ class Curl
$parsedHeader = [];
//collect currently set headers
foreach ($this->getRequestHeaders() as $headerToSet => $valueToSet) {
array_push($parsedHeader, $headerToSet.':'.$valueToSet);
array_push($parsedHeader, $headerToSet . ':' . $valueToSet);
}
//add override new header
if (strlen($header) > 0) {
array_push($parsedHeader, $header.':'.$value);
array_push($parsedHeader, $header . ':' . $value);
}
//set headers
$this->setOption(
......@@ -339,6 +365,7 @@ class Curl
);
return $this;
}
/**
* Unset a single header.
*
......@@ -353,7 +380,7 @@ class Curl
//collect currently set headers and filter "unset" header param.
foreach ($this->getRequestHeaders() as $headerToSet => $valueToSet) {
if ($header !== $headerToSet) {
array_push($parsedHeader, $headerToSet.':'.$valueToSet);
array_push($parsedHeader, $headerToSet . ':' . $valueToSet);
}
}
//set headers
......@@ -363,6 +390,7 @@ class Curl
);
return $this;
}
/**
* Get all request headers as key:value array
*
......@@ -381,6 +409,7 @@ class Curl
}
return $parsedRequestHeaders;
}
/**
* Get specific request header as key:value array
*
......@@ -394,6 +423,7 @@ class Curl
$parsedRequestHeaders = $this->getRequestHeaders();
return isset($parsedRequestHeaders[$headerKey]) ? $parsedRequestHeaders[$headerKey] : null;
}
/**
* Unset a single curl option
*
......@@ -409,6 +439,7 @@ class Curl
}
return $this;
}
/**
* Unset all curl option, excluding default options.
*
......@@ -422,6 +453,7 @@ class Curl
}
return $this;
}
/**
* Total reset of options, responses, etc.
*
......@@ -449,6 +481,7 @@ class Curl
$this->_getParams = [];
return $this;
}
/**
* Return a single option
*
......@@ -462,6 +495,7 @@ class Curl
//return value or false if key is not set.
return isset($mergesOptions[$key]) ? $mergesOptions[$key] : false;
}
/**
* Return merged curl options and keep keys!
*
......@@ -471,6 +505,7 @@ class Curl
{
return $this->_options + $this->_defaultOptions;
}
/**
* Get curl info according to http://php.net/manual/de/function.curl-getinfo.php
*
......@@ -487,6 +522,7 @@ class Curl
return [];
}
}
/**
* Performs HTTP request
*
......@@ -508,8 +544,8 @@ class Curl
}
//setup error reporting and profiling
if (YII_DEBUG) {
Yii::trace('Start sending cURL-Request: '.$this->getUrl().'\n', __METHOD__);
Yii::beginProfile($method.' '.$this->_baseUrl.'#'.md5(serialize($this->getOption(CURLOPT_POSTFIELDS))), __METHOD__);
Yii::trace('Start sending cURL-Request: ' . $this->getUrl() . '\n', __METHOD__);
Yii::beginProfile($method . ' ' . $this->_baseUrl . '#' . md5(serialize($this->getOption(CURLOPT_POSTFIELDS))), __METHOD__);
}
/**
* proceed curl
......@@ -517,7 +553,12 @@ class Curl
$curlOptions = $this->getOptions();
$this->curl = curl_init($this->getUrl());
curl_setopt_array($this->curl, $curlOptions);
curl_setopt($this->curl, CURLOPT_TIMEOUT,40);
if (true == $this->timeout_ms && true == $this->connect_timeout_ms) {
curl_setopt($this->curl, CURLOPT_TIMEOUT_MS, $this->timeout_ms);
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, $this->timeout_ms);
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT_MS, $this->connect_timeout_ms);
}
//curl_setopt($this->curl, CURLOPT_TIMEOUT,40);
$response = curl_exec($this->curl);
//check if curl was successful
if ($response === false) {
......@@ -547,7 +588,7 @@ class Curl
$this->_extractAdditionalCurlParameter();
//end yii debug profile
if (YII_DEBUG) {
Yii::endProfile($method.' '.$this->getUrl().'#'.md5(serialize($this->getOption(CURLOPT_POSTFIELDS))), __METHOD__);
Yii::endProfile($method . ' ' . $this->getUrl() . '#' . md5(serialize($this->getOption(CURLOPT_POSTFIELDS))), __METHOD__);
}
//check responseCode and return data/status
if ($this->getOption(CURLOPT_CUSTOMREQUEST) === 'HEAD') {
......@@ -557,10 +598,11 @@ class Curl
return $this->response;
}
}
/**
* Extract additional curl params protected class helper
*/
protected function _extractAdditionalCurlParameter ()
protected function _extractAdditionalCurlParameter()
{
/**
* retrieve response code
......@@ -581,27 +623,29 @@ class Curl
* try extract response length
*/
$this->responseLength = curl_getinfo($this->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
if((int)$this->responseLength == -1) {
if ((int)$this->responseLength == -1) {
$this->responseLength = strlen($this->response);
}
}
/**
* Extract body curl data from response
*
* @param string $response
* @return string
*/
protected function _extractCurlBody ($response)
protected function _extractCurlBody($response)
{
return substr($response, $this->getInfo(CURLINFO_HEADER_SIZE));
}
/**
* Extract header curl data from response
*
* @param string $response
* @return array
*/
protected function _extractCurlHeaders ($response)
protected function _extractCurlHeaders($response)
{
//Init
$headers = [];
......
......@@ -10,6 +10,9 @@ class CoinCrossChain extends BaseActiveRecord
const WITHDRAW = 0;
const RECHARGE = 1;
const CROSS_CHAIN_TRANSFERING = 'cross_chain_transfering';
const CROSS_CHAIN_CACHE_FAIL = 'cross_chain_fail';
public static function getDb()
{
return Yii::$app->get('p_sources');
......@@ -28,14 +31,14 @@ class CoinCrossChain extends BaseActiveRecord
{
return [
[['is_with_draw', 'address', 'txhex', 'transfer_url'], 'required'],
[['transfer_number', 'step', 'send_result', 'query_result', 'msg'], 'safe']
[['transfer_number', 'amount', 'step', 'send_result', 'query_result', 'msg'], 'safe']
];
}
public function scenarios()
{
$scenarios = [
self:: SCENARIOS_CREATE => ['is_with_draw', 'address', 'txhex', 'transfer_url', 'transfer_number', 'step', 'send_result', 'query_result', 'msg'],
self:: SCENARIOS_CREATE => ['is_with_draw', 'address', 'txhex', 'transfer_url', 'transfer_number', 'amount', 'step', 'send_result', 'query_result', 'msg'],
];
return array_merge(parent:: scenarios(), $scenarios);
}
......
......@@ -20,7 +20,7 @@ class Chain33Service
public function __construct($parameter = [])
{
if(empty($parameter)){
if (empty($parameter)) {
$this->node_params = Yii::$app->params['chain33'];
} else {
$this->node_params = $parameter;
......@@ -56,7 +56,11 @@ class Chain33Service
public function send($params = [], $method = 'Chain33.Query')
{
$ch = new Curl();
$timeout = [
'connect_timeout' => 50000,
'timeout_ms' => 40000
];
$ch = new Curl($timeout);
$jsonrpc = self::jsonRpcBuild($params, $method);
$ch->setHeader('Content-Type', 'application/json');
$ch->setRawPostData($jsonrpc);
......@@ -203,7 +207,7 @@ class Chain33Service
return $this->send($params, 'Chain33.CreateRawTransaction');
}
public function createRawTransaction($to, $amount, $fee, $note,$execer)
public function createRawTransaction($to, $amount, $fee, $note, $execer)
{
$params = [
"to" => $to,
......@@ -302,6 +306,14 @@ class Chain33Service
return $this->send($params, 'Chain33.SendTransaction');
}
public function getHeight($params = [])
{
$params = [
"data" => 'user.p.game.',
];
return $this->send($params, 'paracross.GetHeight');
}
/**
* 获取最新的区块
*/
......
......@@ -14,14 +14,17 @@ class CrossChainController extends Controller
*
* @return array
*/
public function actionAutoTransfer()
public function actionAutoTransfer($step, $is_with_draw)
{
$model = CoinCrossChain::find()->where(['send_result' => "0"])->limit(20)->groupBy('transfer_number')->orderBy('id')->asArray()->all();
$redis = Yii::$app->redis;
$model = CoinCrossChain::find()->where(['send_result' => "0", 'step' => (int)$step, 'is_with_draw' => (int)$is_with_draw])->asArray()->all();
if (empty($model)) {
echo date('Y-m-d H:i:s') . '暂无跨链交易计划' . PHP_EOL;
echo date('Y-m-d H:i:s') . ' STEP: ' . $step . '暂无跨链交易计划' . PHP_EOL;
return 0;
}
$current_time = time();
foreach ($model as $val) {
if ($step > 1) {
$isExist = CoinCrossChain::find()
->where(['transfer_number' => $val['transfer_number']])
->andWhere(['<', 'id', (int)$val['id']])
......@@ -32,53 +35,67 @@ class CrossChainController extends Controller
if ('success' != $isExist['query_result'] && !empty($isExist)) {
continue;
}
}
$cache_transfering_time = $redis->hget(CoinCrossChain::CROSS_CHAIN_TRANSFERING, $val['address'] . ':' . $val['is_with_draw'] . ':' . $val['id']);
if (true == $cache_transfering_time) {
continue;
}
$redis->hmset(CoinCrossChain::CROSS_CHAIN_TRANSFERING, $val['address'] . ':' . $val['is_with_draw'] . ':' . $val['id'], $current_time);
//go(function () use ($val) {
// \Co::sleep(0.5);
go(function () use ($val, $redis) {
\Co::sleep(0.5);
$transfer_url = $val['transfer_url'];
$transfer_url = explode(':', $transfer_url);
$node_params = [
'scheme' => $transfer_url[0],
'host' => str_replace('//', '', $transfer_url[1]),
'port' => isset($transfer_url[2]) ? $transfer_url[2] : ''
'port' => isset($transfer_url[2]) ? $transfer_url[2] : '',
];
$service = new Chain33Service($node_params);
$sign_str = $val['txhex'];
$result = $service->sendTransaction($sign_str);
if (0 != $result['code']) {
$msg = $result['msg'];
goto doEnd;
}
if (0 == $result['code']) {
$send_result = $result['result'];
doEnd :
$currentModel = CoinCrossChain::findOne($val['id']);
if (isset($msg)) {
$currentModel->msg = $msg;
}
if (isset($send_result)) {
$currentModel->send_result = $send_result;
}
$currentModel->msg = 0;
$currentModel->save();
$redis->hdel(CoinCrossChain::CROSS_CHAIN_TRANSFERING, $val['address'] . ':' . $val['is_with_draw'] . ':' . $val['id']);
}
//});
if (0 != $result['code'] && (false == strstr($result['msg'], 'ErrDupTx'))) {
$redis->hdel(CoinCrossChain::CROSS_CHAIN_TRANSFERING, $val['address'] . ':' . $val['is_with_draw'] . ':' . $val['id']);
}
});
}
echo date('Y-m-d H:i:s') . '跨链交易成功' . PHP_EOL;
echo date('Y-m-d H:i:s') . ' STEP: ' . $step . '跨链交易成功' . PHP_EOL;
return 0;
}
public function actionQueryTransaction()
{
$model = CoinCrossChain::find()->where(['<>', 'send_result', '0'])->andWhere(['msg' => '0'])->limit(20)->asArray()->all();
$redis = Yii::$app->redis;
$model = CoinCrossChain::find()->where(['<>', 'send_result', '0'])->andWhere(['msg' => '0'])->asArray()->all();
if (empty($model)) {
echo date('Y-m-d H:i:s') . '暂无跨链交易计划' . PHP_EOL;
return 0;
}
//查询共识高度
$node_params = [
'scheme' => 'https',
'host' => 'jiedian1.bityuan.com',
'port' => 8801
];
$service = new Chain33Service($node_params);
$result = $service->getHeight();
$consensHeight = $result['result']['consensHeight'];
$current_time = time();
foreach ($model as $val) {
$node_params = $val['transfer_url'];
$node_params = explode(':', $node_params);
......@@ -90,30 +107,53 @@ class CrossChainController extends Controller
$service = new Chain33Service($node_params);
$send_result = $val['send_result'];
$result = $service->QueryTransaction($send_result);
if (-1 == $result['code']) {
if('tx not exist' == $result['msg']) continue;
$msg = $result['msg'];
$query_result = $result['code'];
goto doEnd;
// echo date('Y-m-d H:i:s') . 'ID:' . $val['id'] . '查询错误' . PHP_EOL;
// continue;
}
$switch = true;
if (isset($result['result']['actionName']) && 'unknown' == $result['result']['actionName']) {
$redis->hdel(CoinCrossChain::CROSS_CHAIN_CACHE_FAIL, $val['address'] . ':' . $val['is_with_draw']);
$query_result = 'success';
$msg = 'success';
$height = isset($result['result']['height']) ? $result['result']['height'] : 0;
goto doEnd;
} else if (isset($result['result']['receipt']['ty']) && 2 == $result['result']['receipt']['ty']) {
$redis->hdel(CoinCrossChain::CROSS_CHAIN_CACHE_FAIL, $val['address'] . ':' . $val['is_with_draw']);
$query_result = 'success';
$msg = 'success';
$height = isset($result['result']['height']) ? $result['result']['height'] : 0;
goto doEnd;
} else {
$cache_error_time = $redis->hget(CoinCrossChain::CROSS_CHAIN_CACHE_FAIL, $val['address'] . ':' . $val['is_with_draw']);
if (false == $cache_error_time) {
$redis->hmset(CoinCrossChain::CROSS_CHAIN_CACHE_FAIL, $val['address'] . ':' . $val['is_with_draw'], $current_time);
continue;
}
if (($current_time - $cache_error_time) < 60) {
continue;
}
$redis->hdel(CoinCrossChain::CROSS_CHAIN_CACHE_FAIL, $val['address'] . ':' . $val['is_with_draw']);
if (-1 == $result['code']) {
$msg = $result['msg'];
$query_result = $result['code'];
$switch = false;
goto doEnd;
} else {
$query_result = 'fail';
foreach ($result['result']['receipt']['logs'] as $log) {
if (is_array($log['log'])) continue;
$msg = isset($log['log']) ? $log['log'] : '查询错误';
}
$switch = false;
goto doEnd;
}
}
doEnd :
if (CoinCrossChain::RECHARGE == $val['is_with_draw'] && $val['step'] == 2 && $switch && isset($height) && ($consensHeight < $height)) {
continue;
}
$currentModel = CoinCrossChain::findOne($val['id']);
$currentModel->query_result = $query_result;
$currentModel->msg = $msg;
......@@ -121,7 +161,6 @@ class CrossChainController extends Controller
$count = CoinCrossChain::find()->where(['transfer_number' => $val['transfer_number']])->andWhere(['query_result' => 'success'])->count();
if (3 == $count) {
$redis = Yii::$app->redis;
$key = $val['address'] . '_' . $val['is_with_draw'];
if ($redis->exists($key)) {
$redis->del($key);
......
#!/bin/bash
while true; do php /var/www/html/token_pwallet/yii cross-chain/auto-transfer >> /var/www/html/auto-transfer.log 2>&1; sleep 15; done &
\ No newline at end of file
#!/bin/bash
while true; do php /var/www/html/token_pwallet/yii game-bet/bet-update >> /var/log/bet-update.log 2>&1; sleep 2; done &
\ No newline at end of file
#!/bin/bash
while true; do php /var/www/html/token_pwallet/yii game-bet/game-status >> /var/log/game-status.log 2>&1; sleep 5; done &
\ No newline at end of file
#!/bin/bash
while true; do php /var/www/html/token_pwallet/yii cross-chain/query-transaction >> /var/www/html/query-transaction.log 2>&1; sleep 5; done &
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment