Added lots of comments, cleaned up a some code
This commit is contained in:
parent
11338e0f16
commit
e02b265d13
|
@ -1,14 +1,17 @@
|
||||||
var binpack = require('binpack');
|
var binpack = require('binpack');
|
||||||
|
var bignum = require('bignum');
|
||||||
|
|
||||||
var merkleTree = require('./merkleTree.js');
|
var merkleTree = require('./merkleTree.js');
|
||||||
var transactions = require('./transactions.js');
|
var transactions = require('./transactions.js');
|
||||||
var util = require('./util.js');
|
var util = require('./util.js');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The BlockTemplate class holds a single job.
|
* The BlockTemplate class holds a single job.
|
||||||
* and provides serveral methods to validate and submit it to the daemon coin
|
* and provides serveral methods to validate and submit it to the daemon coin
|
||||||
**/
|
**/
|
||||||
var BlockTemplate = module.exports = function BlockTemplate(rpcData, publicKey, extraNoncePlaceholder){
|
var BlockTemplate = module.exports = function BlockTemplate(jobId, rpcData, publicKey, extraNoncePlaceholder){
|
||||||
|
|
||||||
//private members
|
//private members
|
||||||
|
|
||||||
|
@ -31,8 +34,15 @@ var BlockTemplate = module.exports = function BlockTemplate(rpcData, publicKey,
|
||||||
//public members
|
//public members
|
||||||
|
|
||||||
this.rpcData = rpcData;
|
this.rpcData = rpcData;
|
||||||
this.jobId = null;
|
this.jobId = jobId;
|
||||||
this.target = util.bignumFromBits(rpcData.bits);
|
|
||||||
|
/*
|
||||||
|
Use the 'target' field if available, but some daemons only return the 'bits' field
|
||||||
|
*/
|
||||||
|
this.target = rpcData.target ?
|
||||||
|
bignum.fromBuffer(new Buffer(rpcData.target, 'hex')) :
|
||||||
|
util.bignumFromBits(rpcData.bits);
|
||||||
|
|
||||||
this.prevHashReversed = util.reverseByteOrder(new Buffer(rpcData.previousblockhash, 'hex')).toString('hex');
|
this.prevHashReversed = util.reverseByteOrder(new Buffer(rpcData.previousblockhash, 'hex')).toString('hex');
|
||||||
this.transactionData = Buffer.concat(rpcData.transactions.map(function(tx){
|
this.transactionData = Buffer.concat(rpcData.transactions.map(function(tx){
|
||||||
return new Buffer(tx.data, 'hex');
|
return new Buffer(tx.data, 'hex');
|
||||||
|
@ -45,10 +55,6 @@ var BlockTemplate = module.exports = function BlockTemplate(rpcData, publicKey,
|
||||||
extraNoncePlaceholder
|
extraNoncePlaceholder
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setJobId = function (jobId) {
|
|
||||||
this.jobId = jobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.serializeCoinbase = function(extraNonce1, extraNonce2){
|
this.serializeCoinbase = function(extraNonce1, extraNonce2){
|
||||||
return Buffer.concat([
|
return Buffer.concat([
|
||||||
this.generationTransaction[0],
|
this.generationTransaction[0],
|
||||||
|
@ -106,9 +112,5 @@ var BlockTemplate = module.exports = function BlockTemplate(rpcData, publicKey,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return this.jobParams;
|
return this.jobParams;
|
||||||
}
|
};
|
||||||
|
};
|
||||||
//this.jobParams = this.getJobParams();
|
|
||||||
//console.log(JSON.stringify(this.jobParams, null, ' ').replace(/\n/g ,''));
|
|
||||||
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ var startFailedTimeout = 120; //seconds
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The daemon interface interacts with the coin daemon by using the rpc interface.
|
* The daemon interface interacts with the coin daemon by using the rpc interface.
|
||||||
* in otder to make it work it needs, as constructor, an object containing
|
* in order to make it work it needs, as constructor, an object containing
|
||||||
* - 'host' : hostname where the coin lives
|
* - 'host' : hostname where the coin lives
|
||||||
* - 'port' : port where the coin accepts rpc connections
|
* - 'port' : port where the coin accepts rpc connections
|
||||||
* - 'user' : username of the coin for the rpc interface
|
* - 'user' : username of the coin for the rpc interface
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
var net = require('net');
|
var net = require('net');
|
||||||
var fs = require('fs');
|
|
||||||
var events = require('events');
|
var events = require('events');
|
||||||
|
|
||||||
var pool = require('./pool.js');
|
var pool = require('./pool.js');
|
||||||
|
|
|
@ -116,13 +116,9 @@ var JobManager = module.exports = function JobManager(options){
|
||||||
|
|
||||||
this.processTemplate = function(rpcData, publicKey){
|
this.processTemplate = function(rpcData, publicKey){
|
||||||
if (CheckNewIfNewBlock(rpcData.previousblockhash)){
|
if (CheckNewIfNewBlock(rpcData.previousblockhash)){
|
||||||
var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder);
|
var tmpBlockTemplate = new blockTemplate(jobCounter.next(), rpcData, publicKey, _this.extraNoncePlaceholder);
|
||||||
tmpBlockTemplate.setJobId(jobCounter.next());
|
this.currentJob = tmpBlockTemplate;
|
||||||
|
|
||||||
this.currentJob = tmpBlockTemplate;
|
|
||||||
|
|
||||||
_this.emit('newBlock', tmpBlockTemplate);
|
_this.emit('newBlock', tmpBlockTemplate);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,36 +131,36 @@ var JobManager = module.exports = function JobManager(options){
|
||||||
ip: ipAddress,
|
ip: ipAddress,
|
||||||
worker: workerName,
|
worker: workerName,
|
||||||
difficulty: difficulty,
|
difficulty: difficulty,
|
||||||
error: error.error[1]
|
error: error[1]
|
||||||
});
|
});
|
||||||
return error;
|
return {error: error, result: null};
|
||||||
};
|
};
|
||||||
|
|
||||||
var submitTime = Date.now() / 1000 | 0;
|
var submitTime = Date.now() / 1000 | 0;
|
||||||
|
|
||||||
if (extraNonce2.length / 2 !== _this.extraNonce2Size)
|
if (extraNonce2.length / 2 !== _this.extraNonce2Size)
|
||||||
return shareError({error: [20, 'incorrect size of extranonce2']});
|
return shareError([20, 'incorrect size of extranonce2']);
|
||||||
|
|
||||||
var job = this.currentJob;
|
var job = this.currentJob;
|
||||||
if ( job.jobId != jobId ) {
|
if ( job.jobId != jobId ) {
|
||||||
return shareError({error: [21, 'job not found']});
|
return shareError([21, 'job not found']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nTime.length !== 8) {
|
if (nTime.length !== 8) {
|
||||||
return shareError({error: [20, 'incorrect size of ntime']});
|
return shareError([20, 'incorrect size of ntime']);
|
||||||
}
|
}
|
||||||
|
|
||||||
var nTimeInt = parseInt(nTime, 16);
|
var nTimeInt = parseInt(nTime, 16);
|
||||||
if (nTimeInt < job.rpcData.curtime || nTime > submitTime + 7200) {
|
if (nTimeInt < job.rpcData.curtime || nTime > submitTime + 7200) {
|
||||||
return shareError({error: [20, 'ntime out of range']});
|
return shareError([20, 'ntime out of range']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonce.length !== 8) {
|
if (nonce.length !== 8) {
|
||||||
return shareError({error: [20, 'incorrect size of nonce']});
|
return shareError([20, 'incorrect size of nonce']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!job.registerSubmit(extraNonce1, extraNonce2, nTime, nonce)) {
|
if (!job.registerSubmit(extraNonce1, extraNonce2, nTime, nonce)) {
|
||||||
return shareError({error: [22, 'duplicate share']});
|
return shareError([22, 'duplicate share']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,7 +186,7 @@ var JobManager = module.exports = function JobManager(options){
|
||||||
else {
|
else {
|
||||||
var targetUser = bignum(diffDividend / difficulty);
|
var targetUser = bignum(diffDividend / difficulty);
|
||||||
if (headerBigNum.gt(targetUser)){
|
if (headerBigNum.gt(targetUser)){
|
||||||
return shareError({error: [23, 'low difficulty share']});
|
return shareError([23, 'low difficulty share']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,19 +49,10 @@ var MerkleTree = module.exports = function MerkleTree(data){
|
||||||
|
|
||||||
}
|
}
|
||||||
MerkleTree.prototype = {
|
MerkleTree.prototype = {
|
||||||
|
|
||||||
hashSteps: function(){
|
|
||||||
if (!this.stepsHash)
|
|
||||||
this.stepsHash = util.doublesha(Buffer.concat(this.steps));
|
|
||||||
return this.stepsHash;
|
|
||||||
},
|
|
||||||
withFirst: function(f){
|
withFirst: function(f){
|
||||||
this.steps.forEach(function(s){
|
this.steps.forEach(function(s){
|
||||||
f = util.doublesha(Buffer.concat([f, s]));
|
f = util.doublesha(Buffer.concat([f, s]));
|
||||||
});
|
});
|
||||||
return f;
|
return f;
|
||||||
},
|
|
||||||
merkleRoot: function(){
|
|
||||||
return this.withFirst(this.data[0]);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
49
lib/pool.js
49
lib/pool.js
|
@ -1,17 +1,24 @@
|
||||||
var net = require('net');
|
|
||||||
var events = require('events');
|
var events = require('events');
|
||||||
var fs = require('fs');
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var daemon = require('./daemon.js');
|
var daemon = require('./daemon.js');
|
||||||
var stratum = require('./stratum.js');
|
var stratum = require('./stratum.js');
|
||||||
var jobManager = require('./jobManager.js');
|
var jobManager = require('./jobManager.js');
|
||||||
var util = require('./util.js');
|
var util = require('./util.js');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main pool object. It emits the following events:
|
* Main pool object. It emits the following events:
|
||||||
* - 'started'() - when the pool is effectively started.
|
* - started() - when the pool is effectively started
|
||||||
* - 'share'(isValid, dataObj) - In case it's valid the dataObj variable will contain (TODO) and in case it's invalid (TODO)
|
* - share(isValidShare, isValidBlock, shareData) - When a share is submitted
|
||||||
|
* - log(severity, key, text) - for debug, warning, and error messages
|
||||||
|
*
|
||||||
|
* It initializes and connects:
|
||||||
|
* - JobManager - for generating miner work, processing block templates and shares
|
||||||
|
* - DaemonInterface - for RPC communication with daemon
|
||||||
|
* - StratumServer - for TCP socket communication with miners
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var pool = module.exports = function pool(options, authorizeFn){
|
var pool = module.exports = function pool(options, authorizeFn){
|
||||||
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
@ -29,6 +36,9 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Coin daemons either use submitblock or getblocktemplate for submitting new blocks
|
||||||
|
*/
|
||||||
function SubmitBlock(blockHex, callback){
|
function SubmitBlock(blockHex, callback){
|
||||||
if (options.hasSubmitMethod) {
|
if (options.hasSubmitMethod) {
|
||||||
_this.daemon.cmd('submitblock',
|
_this.daemon.cmd('submitblock',
|
||||||
|
@ -62,9 +72,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
address : options.address
|
address : options.address
|
||||||
});
|
});
|
||||||
_this.jobManager.on('newBlock', function(blockTemplate){
|
_this.jobManager.on('newBlock', function(blockTemplate){
|
||||||
if ( typeof(_this.stratumServer ) === 'undefined') {
|
//Check if stratumServer has been initialized yet
|
||||||
emitWarningLog("Stratum server still not started! cannot broadcast block!");
|
if ( typeof(_this.stratumServer ) !== 'undefined') {
|
||||||
} else {
|
|
||||||
emitLog('system', 'Detected new block');
|
emitLog('system', 'Detected new block');
|
||||||
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
||||||
}
|
}
|
||||||
|
@ -116,6 +125,10 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
submitMethod: function(callback){
|
submitMethod: function(callback){
|
||||||
|
/*
|
||||||
|
This checks to see whether the daemon uses submitblock
|
||||||
|
or getblocktemplate for submitting new blocks
|
||||||
|
*/
|
||||||
_this.daemon.cmd('submitblock',
|
_this.daemon.cmd('submitblock',
|
||||||
[],
|
[],
|
||||||
function(error, result){
|
function(error, result){
|
||||||
|
@ -136,9 +149,15 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
util.script_to_address(results.addressInfo.address) :
|
util.script_to_address(results.addressInfo.address) :
|
||||||
util.script_to_pubkey(results.addressInfo.pubkey);
|
util.script_to_pubkey(results.addressInfo.pubkey);
|
||||||
|
|
||||||
StartStratumServer();
|
|
||||||
SetupBlockPolling();
|
|
||||||
|
|
||||||
|
GetBlockTemplate(function(error, result){
|
||||||
|
if (error)
|
||||||
|
emitErrorLog('system', 'Error with initial getblocktemplate');
|
||||||
|
else{
|
||||||
|
StartStratumServer();
|
||||||
|
SetupBlockPolling();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}).on('startFailed', function(){
|
}).on('startFailed', function(){
|
||||||
|
@ -157,6 +176,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
});
|
});
|
||||||
_this.stratumServer.on('started', function(){
|
_this.stratumServer.on('started', function(){
|
||||||
emitLog('system','Stratum server started on port ' + options.stratumPort);
|
emitLog('system','Stratum server started on port ' + options.stratumPort);
|
||||||
|
_this.emit('started');
|
||||||
}).on('client.connected', function(client){
|
}).on('client.connected', function(client){
|
||||||
client.on('subscription', function(params, resultCallback){
|
client.on('subscription', function(params, resultCallback){
|
||||||
|
|
||||||
|
@ -167,13 +187,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
extraNonce2Size
|
extraNonce2Size
|
||||||
);
|
);
|
||||||
|
|
||||||
this.sendAndSetDifficultyIfNew(options.difficulty);
|
this.sendDifficulty(options.difficulty);
|
||||||
if (typeof(_this.jobManager.currentJob) !== 'undefined') {
|
this.sendMiningJob(_this.jobManager.currentJob.getJobParams());
|
||||||
this.sendMiningJob(_this.jobManager.currentJob.getJobParams());
|
|
||||||
} else {
|
|
||||||
emitWarningLog('client', "A miner subscribed but no job to dispatch!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}).on('submit', function(params, resultCallback){
|
}).on('submit', function(params, resultCallback){
|
||||||
var result =_this.jobManager.processShare(
|
var result =_this.jobManager.processShare(
|
||||||
|
@ -209,8 +224,6 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||||
}
|
}
|
||||||
|
|
||||||
var pollingInterval = options.blockRefreshInterval * 1000;
|
var pollingInterval = options.blockRefreshInterval * 1000;
|
||||||
var pollTimeout;
|
|
||||||
var setPoll;
|
|
||||||
|
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
GetBlockTemplate(function(error, result) {
|
GetBlockTemplate(function(error, result) {
|
||||||
|
|
|
@ -190,9 +190,9 @@ var StratumClient = function(options){
|
||||||
* IF the given difficulty is valid and new it'll send it to the client.
|
* IF the given difficulty is valid and new it'll send it to the client.
|
||||||
* returns boolean
|
* returns boolean
|
||||||
**/
|
**/
|
||||||
this.sendAndSetDifficultyIfNew = function(difficulty){
|
this.sendDifficulty = function(difficulty){
|
||||||
if (typeof(difficulty) != 'number') {
|
if (typeof(difficulty) != 'number') {
|
||||||
console.error('[StratumClient.sendAndSetDifficultyIfNew] given difficulty parameter is not a number: ['+difficulty+']');
|
console.error('[StratumClient.sendDifficulty] given difficulty parameter is not a number: ['+difficulty+']');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
146
lib/util.js
146
lib/util.js
|
@ -5,6 +5,10 @@ var base58 = require('base58-native');
|
||||||
var bignum = require('bignum');
|
var bignum = require('bignum');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Used to convert getblocktemplate bits field into target if target is not included.
|
||||||
|
More info: https://en.bitcoin.it/wiki/Target
|
||||||
|
*/
|
||||||
exports.bignumFromBits = function(bitsString){
|
exports.bignumFromBits = function(bitsString){
|
||||||
var bitsBuff = new Buffer(bitsString, 'hex');
|
var bitsBuff = new Buffer(bitsString, 'hex');
|
||||||
var numBytes = bitsBuff.readUInt8(0);
|
var numBytes = bitsBuff.readUInt8(0);
|
||||||
|
@ -19,10 +23,6 @@ exports.bignumFromBits = function(bitsString){
|
||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.bignumFromTarget = function(targetString){
|
|
||||||
return bignum.fromBuffer(new Buffer(targetString, 'hex'));
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.doublesha = function(buffer){
|
exports.doublesha = function(buffer){
|
||||||
var hash1 = crypto.createHash('sha256');
|
var hash1 = crypto.createHash('sha256');
|
||||||
hash1.update(buffer);
|
hash1.update(buffer);
|
||||||
|
@ -69,6 +69,11 @@ exports.hexFromReversedBuffer = function(buffer){
|
||||||
return exports.reverseBuffer(buffer).toString('hex');
|
return exports.reverseBuffer(buffer).toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Defined in bitcoin protocol here:
|
||||||
|
https://en.bitcoin.it/wiki/Protocol_specification#Variable_length_integer
|
||||||
|
*/
|
||||||
exports.varIntBuffer = function(n){
|
exports.varIntBuffer = function(n){
|
||||||
if (n < 0xfd)
|
if (n < 0xfd)
|
||||||
return new Buffer([n]);
|
return new Buffer([n]);
|
||||||
|
@ -92,6 +97,13 @@ exports.varIntBuffer = function(n){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
"serialized CScript" formatting as defined here:
|
||||||
|
https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki#specification
|
||||||
|
Used to format height and date when putting into script signature:
|
||||||
|
https://en.bitcoin.it/wiki/Script
|
||||||
|
*/
|
||||||
exports.serializeNumber = function(n){
|
exports.serializeNumber = function(n){
|
||||||
if (n < 0xfd){
|
if (n < 0xfd){
|
||||||
var buff = new Buffer(2);
|
var buff = new Buffer(2);
|
||||||
|
@ -116,6 +128,10 @@ exports.serializeNumber = function(n){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Used for serializing strings used in script signature
|
||||||
|
*/
|
||||||
exports.serializeString = function(s){
|
exports.serializeString = function(s){
|
||||||
|
|
||||||
if (s.length < 253)
|
if (s.length < 253)
|
||||||
|
@ -143,6 +159,11 @@ exports.serializeString = function(s){
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
An exact copy of python's range feature. Written by Tadeck:
|
||||||
|
http://stackoverflow.com/a/8273091
|
||||||
|
*/
|
||||||
exports.range = function(start, stop, step){
|
exports.range = function(start, stop, step){
|
||||||
if (typeof stop === 'undefined'){
|
if (typeof stop === 'undefined'){
|
||||||
stop = start;
|
stop = start;
|
||||||
|
@ -161,6 +182,7 @@ exports.range = function(start, stop, step){
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
exports.address_to_pubkeyhash = function(addr){
|
exports.address_to_pubkeyhash = function(addr){
|
||||||
addr = base58.decode(addr);
|
addr = base58.decode(addr);
|
||||||
|
|
||||||
|
@ -182,6 +204,10 @@ exports.address_to_pubkeyhash = function(addr){
|
||||||
return [ver, addr.slice(1,-4)];
|
return [ver, addr.slice(1,-4)];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
For POS coins - used to format wallet address for use in generation transaction's output
|
||||||
|
*/
|
||||||
exports.script_to_pubkey = function(key){
|
exports.script_to_pubkey = function(key){
|
||||||
if (key.length === 66) key = new Buffer(key, 'hex');
|
if (key.length === 66) key = new Buffer(key, 'hex');
|
||||||
if (key !== 33) throw 'Invalid address';
|
if (key !== 33) throw 'Invalid address';
|
||||||
|
@ -192,6 +218,10 @@ exports.script_to_pubkey = function(key){
|
||||||
return pubkey;
|
return pubkey;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
For POW coins - used to format wallet address for use in generation transaction's output
|
||||||
|
*/
|
||||||
exports.script_to_address = function(addr){
|
exports.script_to_address = function(addr){
|
||||||
var d = exports.address_to_pubkeyhash(addr)
|
var d = exports.address_to_pubkeyhash(addr)
|
||||||
if (!d)
|
if (!d)
|
||||||
|
@ -200,110 +230,4 @@ exports.script_to_address = function(addr){
|
||||||
var ver = d[0];
|
var ver = d[0];
|
||||||
var pubkeyhash = d[1];
|
var pubkeyhash = d[1];
|
||||||
return Buffer.concat([new Buffer([0x76, 0xa9, 0x14]), pubkeyhash, new Buffer([0x88, 0xac])]);
|
return Buffer.concat([new Buffer([0x76, 0xa9, 0x14]), pubkeyhash, new Buffer([0x88, 0xac])]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
exports.makeBufferReadable = function(buffer){
|
|
||||||
var position = 0;
|
|
||||||
buffer.read = function(length){
|
|
||||||
var section = buffer.slice(position, length ? (position + length) : buffer.length);
|
|
||||||
position += length;
|
|
||||||
return MakeBufferReadable(section);
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
exports.ser_uint256 = function(u){
|
|
||||||
var rs = new Buffer(0);
|
|
||||||
exports.range(8).forEach(function(i){
|
|
||||||
rs = Buffer.concat([
|
|
||||||
rs,
|
|
||||||
binpack.packUInt32(u & 0xFFFFFFFF, 'little')
|
|
||||||
]);
|
|
||||||
u >>= 32;
|
|
||||||
});
|
|
||||||
return rs;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.deser_uint256 = function(f){
|
|
||||||
var r = 0;
|
|
||||||
exports.range(8).forEach(function(i){
|
|
||||||
var t = f.read(4).readUInt32LE(4);
|
|
||||||
r += t << (i * 32);
|
|
||||||
});
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.uint256_from_compact = function(c){
|
|
||||||
var nbytes = (c >> 24) & 0xFF;
|
|
||||||
v = (c & 0xFFFFFF) << (8 * (nbytes - 3))
|
|
||||||
return v;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.uint256_from_str = function(s){
|
|
||||||
var r = 0;
|
|
||||||
var t = binpack.unpack
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.ser_uint256_be = function(u){
|
|
||||||
var rs = new Buffer(0);
|
|
||||||
exports.range(8).forEach(function(i){
|
|
||||||
rs = Buffer.concat([
|
|
||||||
rs,
|
|
||||||
binpack.packUInt32(u & 0xFFFFFFFF, 'big')
|
|
||||||
]);
|
|
||||||
u >>= 32;
|
|
||||||
});
|
|
||||||
return rs;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.deser_string = function(f){
|
|
||||||
var nit = f.read(1).readUInt8(0);
|
|
||||||
if (nit == 253)
|
|
||||||
nit = f.read(2).readUInt16LE(0);
|
|
||||||
else if (nit == 254)
|
|
||||||
nit = f.read(4).readUInt32LE(1);
|
|
||||||
else if (nit == 255)
|
|
||||||
nit = f.read(8).readUInt64LE(1);
|
|
||||||
return f.read(nit);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
exports.ser_vector = function(l){
|
|
||||||
var r;
|
|
||||||
if (l.length < 253)
|
|
||||||
r = new Buffer([l.length]);
|
|
||||||
else if (l.length < 0x10000)
|
|
||||||
r = Buffer.concat([new Buffer([253]), binpack.packUInt16(l.length, 'little')]);
|
|
||||||
else if (l.length < 0x100000000)
|
|
||||||
r = Buffer.concat([new Buffer([254]), binpack.packUInt32(l.length, 'little')]);
|
|
||||||
else
|
|
||||||
r = Buffer.concat([new Buffer([255]), binpack.packUInt64(l.length, 'little')]);
|
|
||||||
|
|
||||||
l.forEach(function(i){
|
|
||||||
r = Buffer.concat([r, i.serialize()]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.deser_vector = function(f, c){
|
|
||||||
var nit = f.read(1).readUInt8(0);
|
|
||||||
if (nit == 253)
|
|
||||||
nit = f.read(2).readUInt16LE(0);
|
|
||||||
else if (nit == 254)
|
|
||||||
nit = f.read(4).readUInt32LE(0);
|
|
||||||
else if (nit == 255)
|
|
||||||
nit = f.read(8).readUInt64LE(0);
|
|
||||||
var r = [];
|
|
||||||
exports.range(nit).forEach(function(i){
|
|
||||||
var t = new c();
|
|
||||||
t.deserialize(f);
|
|
||||||
r.push(t);
|
|
||||||
});
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue