-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhashnethelper.js
More file actions
353 lines (320 loc) · 12.9 KB
/
hashnethelper.js
File metadata and controls
353 lines (320 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
'use strict';
// const Ice = require("ice").Ice;
// const rpc = require("./Hashnet").one.inve.rpc;
const webHelper = require("./webhelper.js");
const device = require("./device.js");
const secrethelper = require("./secrethelper.js");
var db = require('./db.js');
var mutex = require('./mutex.js');
var _ = require('lodash');
var bignumber = require("bignumber.js");
var config = require('./conf.js')
//运行时存放局部全节点列表
var localfullnodes = {};
//与共识网交互的类
var timeStamp = Math.round(Date.now())
var initGet = true;
class HashnetHelper {
//返回一个局部全节点,供调用。
static async buildSingleLocalfullnode(address) {
if (typeof localfullnodes[address] == 'undefined' || localfullnodes[address].length < 3 || ((Math.round(Date.now()) - timeStamp) / (1000 * 60 * 60)) > 1) {
//从种子节点处获取局部全节点列表
let pubKey = await device.getInfo(address);
let localfullnode = await HashnetHelper.getLocalfullnodeList(address, pubKey);
return localfullnode;
} else if (localfullnodes[address].length >= 3) {
//从列表中随机挑选一个局部全节点。
let localfullnode = localfullnodes[address][secrethelper.random(0, localfullnodes[address].length - 1)];
//console.log("get localfullnode:" + JSON.stringify(localfullnode));
return localfullnode;
}
else {
console.log("localfullnode is null.");
return null;
}
}
//初始化局部全节点列表,列表和数据库中都进行清空。
static async initialLocalfullnodeList() {
localfullnodes = {};
//用队列的方式更新数据库
// await mutex.lock(["write"], async function (unlock) {
// try {
// await db.execute('delete from lfullnode_list');
// }
// catch (e) {
// console.log(e.toString());
// }
// finally {
// //解锁事务队列
// await unlock();
// }
// });
}
//从种子节点获取局部全节点列表
static async getLocalfullnodeList(address, pubkey) {
try {
//从种子节点那里拉取局部全节点列表
let localfullnodeListMessageRes = JSON.parse(await webHelper.httpPost(device.my_device_hashnetseed_url + '/v1/getlocalfullnodes', null, buildData({pubkey})));
let bError = !!JSON.stringify(localfullnodeListMessageRes).match(/^error/i);
if (bError) return [];
let localfullnodeListMessage = localfullnodeListMessageRes;
let localfullnodeList = localfullnodeListMessage.data;
if (localfullnodeListMessage.code == 200 && localfullnodeList != '') {
localfullnodeList = JSON.parse(localfullnodeList);
let list = []
for (let i in localfullnodeList) {
let l = localfullnodeList[i].ip + ':' + localfullnodeList[i].httpPort;
list.push(l)
}
localfullnodes[address] = list;
return localfullnodeList
}
else {
//如果没有拉取到,则返回空数组。
console.log("got no localfullnodeList");
return [];
}
}
catch (e) {
console.log(e.toString());
return [];
}
}
//局部全节点访问失败,从局部全节点列表和数据库中进行删除
static async reloadLocalfullnode(address, localfullnode) {
if (localfullnode) {
_.pull(localfullnodes[address], localfullnode);
//用队列的方式进行数据库更新
// await mutex.lock(["write"], async function (unlock) {
// try {
// await db.execute("delete from lfullnode_list where address = ?", localfullnode.ip + ':' + localfullnode.httpPort);
// }
// catch (e) {
// console.log(e.toString());
// }
// finally {
// //解锁事务队列
// await unlock();
// }
// });
}
//如果局部全节点列表个数小于3个,需要重新初始化局部全节点列表。
// if (localfullnodes.length < 3) {
// let { pubKey } = await device.getInfo();
// let localfullnodeListMessage = await HashnetHelper.getLocalfullnodeList(pubKey);
// let localfullnodeList = localfullnodeListMessage.data;
// if (localfullnodeListMessage.code = 200) {
// localfullnodes = localfullnodeList;
// }
// }
}
//发送交易,会尝试3次
static async sendMessage(unit, retry) {
let resultMessage = '';
retry = retry || 3;
if (retry > 1) {
for (var i = 0; i < retry; i++) {
resultMessage = JSON.parse(await HashnetHelper.sendMessageTry(unit));
if (resultMessage.code == 200) {
break;
}
}
return resultMessage;
}
return await HashnetHelper.sendMessageTry(unit);
}
//直接调用共识网的发送交易接口
static async sendMessageTry(unit) {
try {
// //获取局部全节点
// let address = unit.fromAddress
// let localfullnode = await HashnetHelper.buildSingleLocalfullnode(address);
//
// if (!localfullnode) {
// throw new Error('network error, please try again.');
// }
console.log("sending unit:");
let message = JSON.stringify(unit);
//往共识网发送交易
let result = await webHelper.httpPost(getUrl(config.URL.INVE_TRANSACTION_URL, '/v1/sendmsg'), null, buildData({message}));
// if(JSON.parse(result).code != 200 && JSON.parse(result).data.match(/sender is illegal/g)) {
// await sendMessageTry(unit)
// return
// }
return result;
}
catch (e) {
//处理失效的局部全节点
return JSON.stringify({"code": 500, "data": "network error,please try again."});
}
}
//获取交易记录
static async getTransactionHistory(address, tableIndex, offset, sysTableIndex,sysOffset ) {
//获取局部全节点
// let localfullnode = await HashnetHelper.buildSingleLocalfullnode(address);
let rows = await db.execute("SELECT ti.tableIndex ,ti.offsets, ti.sysTableIndex, ti.sysOffset FROM transactions_index ti WHERE ti.address = ?", address);
if (rows != null && rows.length == 1) {
// console.log("------------------");
// console.log(rows[0].tableIndex);
// console.log(rows[0].offsets);
tableIndex = rows[0].tableIndex;
sysTableIndex = rows[0].sysTableIndex;
offset = initGet ? (rows[0].offsets - 10) >0 ? rows[0].offsets - 10 : 0 : rows[0].offsets;
sysOffset = initGet ? (rows[0].sysOffset - 10) >0 ? rows[0].sysOffset - 10 : 0 : rows[0].sysOffset;
initGet = false;
} else {
await db.execute("INSERT INTO transactions_index (address ,tableIndex,offsets, sysTableIndex, sysOffset) VALUES(?,0,0,0,0)", address);
}
try {
// if (!localfullnode) {
// throw new Error('network error, please try again.');
// }
let type = [1, 2];
//从共识网拉取交易记录
let resultMessage = JSON.parse(await webHelper.httpPost(getUrl(config.URL.INVE_TRANSACTION_getURL, '/v1/gettransactionlistnew'), null, buildData({
address,
tableIndex,
sysTableIndex,
offset,
sysOffset,
type
})));
//let result = resultMessage.data.replace(/"amount":/g,'"amount":"').replace(/,"eHash"/g,'","eHash"').replace(/"fee":/g,'"fee":"').replace(/,"fromAddress"/g,'","fromAddress"');
let result = resultMessage.data;
if (resultMessage.code == 200) {
result = JSON.parse(result);
tableIndex = result.tableIndex ? result.tableIndex : 0;
sysTableIndex = result.sysTableIndex ? result.sysTableIndex : 0;
offset = result.offset ? result.offset : 0;
sysOffset = result.sysOffset ? result.sysOffset : 0;
// await db.execute("UPDATE transactions_index SET tableIndex= ?,offsets= ? WHERE address = ?",tableIndex,offset,address);
return result.list ? {result: result.list, tableIndex, offset, address, sysTableIndex, sysOffset} : {
result: [],
tableIndex,
offset,
address,
sysTableIndex,
sysOffset
};
// }else
// return {result:[],tableIndex,offset,address};
} else {
return {result: [], tableIndex, offset, address, sysTableIndex, sysOffset}
}
// return result ? JSON.parse(result) : [];
} catch (e) {
//处理失效的局部全节点
// if (localfullnode) {
// await HashnetHelper.reloadLocalfullnode(localfullnode);
// }
return {result: [], tableIndex, offset, address, sysTableIndex, sysOffset};
}
}
/**
* 根据交易hash查询交易状态
* @param hash
* @returns {Promise<null>}
*/
static async getHashInfo(hash) {
// let localfullnode = await HashnetHelper.buildSingleLocalfullnode();
// localfullnode = config.TRANSACTION_getURL;
try {
// if (!localfullnode) {
// throw new Error('network error, please try again.');
// }
let result = await webHelper.httpPost(getUrl(config.URL.INVE_TRANSACTION_getURL, '/v1/gettransaction'), null, buildData({hash}));
return result ? JSON.parse(result) : null;
}
catch (e) {
//处理失效的局部全节点
// if (localfullnode) {
// await HashnetHelper.reloadLocalfullnode(localfullnode);
// }
return null;
}
}
/**
* 获取NRG_PRICE
* @returns {Promise<*>}
*/
static async getNRGPrice() {
let url = config.URL.INVE_SEED;
try {
let result = JSON.parse(await webHelper.httpPost(url + '/v1/price/nrg', null, {}));
if (result.code == 200) {
let nrgPrice = JSON.parse(result.data).nrgPrice;
return nrgPrice;
} else {
return null;
}
return result
} catch (e) {
console.log(e.toString())
return null
}
}
/**
* 获取单个地址信息
* @param address
* @returns {Promise<*>}
*/
static async getAccountInfo (address) {
let localfullnode = config.URL.INVE_TRANSACTION_getURL;
let retry = 3;
try {
let result = JSON.parse(await webHelper.httpPost(getUrl(localfullnode, '/v1/account/info'), null, {address:address}));
if (result.code == 200) {
let data = JSON.parse(result.data);
return data;
} else {
return null;
}
} catch (e) {
console.log('getAccountInfo error: ', e.toString());
retry --;
if(!retry) {
return null;
}
else {
return HashnetHelper.getAccountInfo(address)
}
//return e.toString();
}
}
/**
* 获取合约执行结果
* @param address
* @returns {Promise<*>}
*/
static async getReceipt (hash) {
let localfullnode = config.URL.INVE_TRANSACTION_getURL;
let retry = 3;
try {
let result = JSON.parse(await webHelper.httpPost(getUrl(localfullnode, '/v1/getReceipt'), null, {hash:hash}));
if (result.code == 200) {
let data = JSON.parse(result.data);
return data;
} else {
return null;
}
} catch (e) {
console.log('getReceipt error: ', e.toString());
retry --;
if(!retry) {
return null;
} else {
return HashnetHelper.getReceipt(hash)
}
//return e.toString();
}
}
}
//组装访问共识网的url
let getUrl = (localfullnode, suburl) => {
return 'http://' + localfullnode + suburl;
}
//组装往共识网发送数据的对象
let buildData = (data) => {
return JSON.parse(JSON.stringify(data));
}
module.exports = HashnetHelper;