Merge branch 'generators'
This commit is contained in:
commit
74fde4bc51
141 changed files with 18147 additions and 17841 deletions
9
.babelrc
Normal file
9
.babelrc
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"presets": ["es2015"],
|
||||
"plugins": [
|
||||
["transform-runtime", {
|
||||
"polyfill": true,
|
||||
"regenerator": true
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"bitwise": false,
|
||||
"esversion": 6,
|
||||
"curly": false,
|
||||
"eqeqeq": true,
|
||||
"freeze": true,
|
||||
|
|
|
|||
167
README.md
167
README.md
|
|
@ -114,30 +114,19 @@ var miner = new bcoin.miner({ chain: chain, mempool: mempool });
|
|||
|
||||
// Open the miner (initialize the databases, etc).
|
||||
// Miner will implicitly call `open` on chain and mempool.
|
||||
miner.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
miner.open().then(function() {
|
||||
// Create a block "attempt".
|
||||
miner.createBlock(function(err, attempt) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// Mine the block on the worker pool (use mine() for the master process)
|
||||
attempt.mineAsync(function(err, block) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// Add the block to the chain
|
||||
chain.add(block, function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
console.log('Added %s to the blockchain.', block.rhash);
|
||||
console.log(block);
|
||||
});
|
||||
});
|
||||
});
|
||||
return miner.createBlock();
|
||||
}).then(function(attempt) {
|
||||
// Mine the block on the worker pool (use mine() for the master process)
|
||||
return attempt.mineAsync();
|
||||
}).then(function(block) {
|
||||
// Add the block to the chain
|
||||
console.log('Adding %s to the blockchain.', block.rhash);
|
||||
console.log(block);
|
||||
return chain.add(block);
|
||||
}).then(function() {
|
||||
console.log('Added block!');
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -157,10 +146,7 @@ var mempool = new bcoin.mempool({ chain: chain });
|
|||
var pool = new bcoin.pool({ chain: chain, mempool: mempool, maxPeers: 8 });
|
||||
|
||||
// Open the pool (implicitly opens mempool and chain).
|
||||
pool.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
pool.open().then(function() {
|
||||
// Connect, start retrieving and relaying txs
|
||||
pool.connect();
|
||||
|
||||
|
|
@ -204,10 +190,7 @@ var tpool = new bcoin.pool({
|
|||
size: 8
|
||||
});
|
||||
|
||||
tpool.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
tpool.open().then(function() {
|
||||
// Connect, start retrieving and relaying txs
|
||||
tpool.connect();
|
||||
|
||||
|
|
@ -252,38 +235,29 @@ var pool = new bcoin.pool({
|
|||
|
||||
var walletdb = new bcoin.walletdb({ db: 'memory' });
|
||||
|
||||
pool.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
pool.open().then(function() {
|
||||
return walletdb.open();
|
||||
}).then(function() {
|
||||
return walletdb.create();
|
||||
}).then(function(wallet) {
|
||||
console.log('Created wallet with address %s', wallet.getAddress('base58'));
|
||||
|
||||
walletdb.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
// Add our address to the spv filter.
|
||||
pool.watchAddress(wallet.getAddress());
|
||||
|
||||
walletdb.create(function(err, wallet) {
|
||||
if (err)
|
||||
throw err;
|
||||
// Connect, start retrieving and relaying txs
|
||||
pool.connect();
|
||||
|
||||
console.log('Created wallet with address %s', wallet.getAddress('base58'));
|
||||
// Start the blockchain sync.
|
||||
pool.startSync();
|
||||
|
||||
// Add our address to the spv filter.
|
||||
pool.watchAddress(wallet.getAddress());
|
||||
pool.on('tx', function(tx) {
|
||||
wallet.addTX(tx);
|
||||
});
|
||||
|
||||
// Connect, start retrieving and relaying txs
|
||||
pool.connect();
|
||||
|
||||
// Start the blockchain sync.
|
||||
pool.startSync();
|
||||
|
||||
pool.on('tx', function(tx) {
|
||||
wallet.addTX(tx);
|
||||
});
|
||||
|
||||
wallet.on('balance', function(balance) {
|
||||
console.log('Balance updated.');
|
||||
console.log(bcoin.utils.btc(balance.unconfirmed));
|
||||
});
|
||||
});
|
||||
wallet.on('balance', function(balance) {
|
||||
console.log('Balance updated.');
|
||||
console.log(bcoin.utils.btc(balance.unconfirmed));
|
||||
});
|
||||
});
|
||||
```
|
||||
|
|
@ -310,10 +284,7 @@ node.on('error', function(err) {
|
|||
});
|
||||
|
||||
// Start the node
|
||||
node.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
node.open().then(function() {
|
||||
// Create a new wallet (or get an existing one with the same ID)
|
||||
var options = {
|
||||
id: 'mywallet',
|
||||
|
|
@ -322,48 +293,33 @@ node.open(function(err) {
|
|||
type: 'pubkeyhash'
|
||||
};
|
||||
|
||||
node.walletdb.create(options, function(err, wallet) {
|
||||
if (err)
|
||||
throw err;
|
||||
return node.walletdb.create(options);
|
||||
}).then(function(wallet) {
|
||||
console.log('Created wallet with address: %s', wallet.getAddress('base58'));
|
||||
|
||||
console.log('Created wallet with address: %s', wallet.getAddress('base58'));
|
||||
// Start syncing the blockchain
|
||||
node.startSync();
|
||||
|
||||
// Start syncing the blockchain
|
||||
node.startSync();
|
||||
|
||||
// Wait for balance and send it to a new address.
|
||||
wallet.once('balance', function(balance) {
|
||||
// Create a transaction, fill
|
||||
// it with coins, and sign it.
|
||||
var options = {
|
||||
subtractFee: true,
|
||||
outputs: [{
|
||||
address: newReceiving,
|
||||
value: balance.total
|
||||
}]
|
||||
};
|
||||
wallet.createTX(options, function(err, tx) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// Need to pass our passphrase back in to sign!
|
||||
wallet.sign(tx, 'foo', function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
console.log('sending tx:');
|
||||
console.log(tx);
|
||||
|
||||
node.sendTX(tx, function(err) {
|
||||
if (err) {
|
||||
// Could be a reject
|
||||
// packet or a timeout.
|
||||
return console.log(err);
|
||||
}
|
||||
console.log('tx sent!');
|
||||
});
|
||||
});
|
||||
});
|
||||
// Wait for balance and send it to a new address.
|
||||
wallet.once('balance', function(balance) {
|
||||
// Create a transaction, fill
|
||||
// it with coins, and sign it.
|
||||
var options = {
|
||||
subtractFee: true,
|
||||
outputs: [{
|
||||
address: newReceiving,
|
||||
value: balance.total
|
||||
}]
|
||||
};
|
||||
wallet.createTX(options).then(function(tx) {
|
||||
// Need to pass our passphrase back in to sign!
|
||||
return wallet.sign(tx, 'foo');
|
||||
}).then(function(tx) {
|
||||
console.log('sending tx:');
|
||||
console.log(tx);
|
||||
return node.sendTX(tx);
|
||||
}).then(function() {
|
||||
console.log('tx sent!');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -377,12 +333,7 @@ node.mempool.on('tx', function(tx) {
|
|||
});
|
||||
|
||||
node.chain.on('full', function() {
|
||||
node.mempool.getHistory(function(err, txs) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
console.log(txs);
|
||||
});
|
||||
node.mempool.getHistory().then(console.log);
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
var bn = require('bn.js');
|
||||
var bcoin = require('../').set('main');
|
||||
var constants = bcoin.constants;
|
||||
var utils = bcoin.utils;
|
||||
var constants = require('../lib/protocol/constants');
|
||||
var utils = require('../lib/utils/utils');
|
||||
var assert = require('assert');
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
var bench = require('./bench');
|
||||
var fs = require('fs');
|
||||
|
||||
bcoin.cache();
|
||||
var Coins = require('../lib/chain/coins');
|
||||
var TX = require('../lib/primitives/tx');
|
||||
|
||||
var wtx = fs.readFileSync(__dirname + '/../test/data/wtx.hex', 'utf8');
|
||||
wtx = bcoin.tx.fromRaw(wtx.trim(), 'hex');
|
||||
wtx = tx.fromRaw(wtx.trim(), 'hex');
|
||||
|
||||
var coins = bcoin.coins.fromTX(wtx);
|
||||
var coins = Coins.fromTX(wtx);
|
||||
var raw;
|
||||
|
||||
var end = bench('serialize');
|
||||
|
|
@ -24,16 +23,16 @@ end(i);
|
|||
|
||||
var end = bench('parse');
|
||||
for (var i = 0; i < 10000; i++)
|
||||
bcoin.coins.fromRaw(raw);
|
||||
Coins.fromRaw(raw);
|
||||
end(i);
|
||||
|
||||
var end = bench('parse-single');
|
||||
var hash = wtx.hash('hex');
|
||||
for (var i = 0; i < 10000; i++)
|
||||
bcoin.coins.parseCoin(raw, hash, 5);
|
||||
Coins.parseCoin(raw, hash, 5);
|
||||
end(i);
|
||||
|
||||
var coins = bcoin.coins.fromRaw(raw);
|
||||
var coins = Coins.fromRaw(raw);
|
||||
var end = bench('get');
|
||||
var j;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ var utils = bcoin.utils;
|
|||
var assert = require('assert');
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
var bench = require('./bench');
|
||||
var co = require('../lib/utils/co');
|
||||
|
||||
bcoin.cache();
|
||||
|
||||
|
|
@ -35,115 +36,85 @@ var walletdb = new bcoin.walletdb({
|
|||
// db: 'leveldb'
|
||||
db: 'memory'
|
||||
});
|
||||
var wallet;
|
||||
var addrs = [];
|
||||
|
||||
function runBench(callback) {
|
||||
utils.serial([
|
||||
function(next) {
|
||||
walletdb.create(function(err, w) {
|
||||
assert.ifError(err);
|
||||
wallet = w;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
var end = bench('accounts');
|
||||
utils.forRange(0, 1000, function(i, next) {
|
||||
wallet.createAccount({}, function(err, account) {
|
||||
assert.ifError(err);
|
||||
addrs.push(account.receiveAddress.getAddress());
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
assert.ifError(err);
|
||||
end(1000);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
var end = bench('addrs');
|
||||
utils.forRange(0, 1000, function(i, next) {
|
||||
utils.forRange(0, 10, function(j, next) {
|
||||
wallet.createReceive(i, function(err, addr) {
|
||||
assert.ifError(err);
|
||||
addrs.push(addr);
|
||||
next();
|
||||
});
|
||||
}, next);
|
||||
}, function(err) {
|
||||
assert.ifError(err);
|
||||
end(1000 * 10);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
var nonce = new bn(0);
|
||||
var end;
|
||||
utils.forRange(0, 10000, function(i, next) {
|
||||
var t1 = bcoin.mtx()
|
||||
.addOutput(addrs[(i + 0) % addrs.length], 50460)
|
||||
.addOutput(addrs[(i + 1) % addrs.length], 50460)
|
||||
.addOutput(addrs[(i + 2) % addrs.length], 50460)
|
||||
.addOutput(addrs[(i + 3) % addrs.length], 50460);
|
||||
var runBench = co(function* runBench() {
|
||||
var i, j, wallet, addrs, jobs, end;
|
||||
var result, nonce, tx, options;
|
||||
|
||||
t1.addInput(dummyInput);
|
||||
nonce.addn(1);
|
||||
t1.inputs[0].script.set(0, nonce);
|
||||
t1.inputs[0].script.compile();
|
||||
// Open and Create
|
||||
yield walletdb.open();
|
||||
wallet = yield walletdb.create();
|
||||
addrs = [];
|
||||
|
||||
walletdb.addTX(t1.toTX(), function(err) {
|
||||
assert.ifError(err);
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
assert.ifError(err);
|
||||
end(10000);
|
||||
next();
|
||||
});
|
||||
end = bench('tx');
|
||||
},
|
||||
function(next) {
|
||||
var end = bench('balance');
|
||||
wallet.getBalance(function(err, balance) {
|
||||
assert.ifError(err);
|
||||
end(1);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
var end = bench('coins');
|
||||
wallet.getCoins(function(err) {
|
||||
assert.ifError(err);
|
||||
end(1);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
var end = bench('create');
|
||||
var options = {
|
||||
rate: 10000,
|
||||
outputs: [{
|
||||
value: 50460,
|
||||
address: addrs[0]
|
||||
}]
|
||||
};
|
||||
wallet.createTX(options, function(err) {
|
||||
assert.ifError(err);
|
||||
end(1);
|
||||
next();
|
||||
});
|
||||
}
|
||||
], function(err) {
|
||||
assert.ifError(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
// Accounts
|
||||
jobs = [];
|
||||
for (i = 0; i < 1000; i++)
|
||||
jobs.push(wallet.createAccount({}));
|
||||
|
||||
walletdb.open(function(err) {
|
||||
assert.ifError(err);
|
||||
runBench(function(err) {
|
||||
assert.ifError(err);
|
||||
process.exit(0);
|
||||
});
|
||||
end = bench('accounts');
|
||||
result = yield Promise.all(jobs);
|
||||
end(1000);
|
||||
|
||||
for (i = 0; i < result.length; i++)
|
||||
addrs.push(result[i].receive.getAddress());
|
||||
|
||||
// Addresses
|
||||
jobs = [];
|
||||
for (i = 0; i < 1000; i++) {
|
||||
for (j = 0; j < 10; j++)
|
||||
jobs.push(wallet.createReceive(i));
|
||||
}
|
||||
|
||||
end = bench('addrs');
|
||||
result = yield Promise.all(jobs);
|
||||
end(1000 * 10);
|
||||
|
||||
for (i = 0; i < result.length; i++)
|
||||
addrs.push(result[i].getAddress());
|
||||
|
||||
// TX
|
||||
jobs = [];
|
||||
nonce = new bn(0);
|
||||
for (i = 0; i < 10000; i++) {
|
||||
tx = bcoin.mtx()
|
||||
.addOutput(addrs[(i + 0) % addrs.length], 50460)
|
||||
.addOutput(addrs[(i + 1) % addrs.length], 50460)
|
||||
.addOutput(addrs[(i + 2) % addrs.length], 50460)
|
||||
.addOutput(addrs[(i + 3) % addrs.length], 50460);
|
||||
|
||||
tx.addInput(dummyInput);
|
||||
nonce.addn(1);
|
||||
tx.inputs[0].script.set(0, nonce);
|
||||
tx.inputs[0].script.compile();
|
||||
|
||||
jobs.push(walletdb.addTX(tx.toTX()));
|
||||
}
|
||||
|
||||
end = bench('tx');
|
||||
result = yield Promise.all(jobs);
|
||||
end(10000);
|
||||
|
||||
// Balance
|
||||
end = bench('balance');
|
||||
result = yield wallet.getBalance();
|
||||
end(1);
|
||||
|
||||
// Coins
|
||||
end = bench('coins');
|
||||
result = yield wallet.getCoins();
|
||||
end(1);
|
||||
|
||||
// Create
|
||||
end = bench('create');
|
||||
options = {
|
||||
rate: 10000,
|
||||
outputs: [{
|
||||
value: 50460,
|
||||
address: addrs[0]
|
||||
}]
|
||||
};
|
||||
yield wallet.createTX(options);
|
||||
end(1);
|
||||
});
|
||||
|
||||
runBench().then(process.exit);
|
||||
|
|
|
|||
622
bin/cli
622
bin/cli
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
var config = require('../lib/node/config');
|
||||
var utils = require('../lib/utils/utils');
|
||||
var co = require('../lib/utils/co');
|
||||
var Client = require('../lib/http/client');
|
||||
var Wallet = require('../lib/http/wallet');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var main;
|
||||
|
||||
function CLI() {
|
||||
this.config = config({
|
||||
|
|
@ -26,9 +28,9 @@ CLI.prototype.log = function log(json) {
|
|||
console.log(JSON.stringify(json, null, 2));
|
||||
};
|
||||
|
||||
CLI.prototype.createWallet = function createWallet(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.createWallet = co(function* createWallet() {
|
||||
var options = { id: this.argv[0] };
|
||||
var wallet;
|
||||
|
||||
if (this.config.type)
|
||||
options.type = this.config.type;
|
||||
|
|
@ -51,170 +53,118 @@ CLI.prototype.createWallet = function createWallet(callback) {
|
|||
if (this.config.passphrase)
|
||||
options.passphrase = this.config.passphrase;
|
||||
|
||||
this.client.createWallet(options, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(wallet);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
wallet = yield this.client.createWallet(options);
|
||||
this.log(wallet);
|
||||
});
|
||||
|
||||
CLI.prototype.addKey = function addKey(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.addKey = co(function* addKey() {
|
||||
var key = this.argv[0];
|
||||
this.wallet.addKey(this.config.account, key, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log('added');
|
||||
callback();
|
||||
});
|
||||
};
|
||||
yield this.wallet.addKey(this.config.account, key);
|
||||
this.log('added');
|
||||
});
|
||||
|
||||
CLI.prototype.removeKey = function removeKey(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.removeKey = co(function* removeKey() {
|
||||
var key = this.argv[0];
|
||||
this.wallet.removeKey(this.config.account, key, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log('removed');
|
||||
callback();
|
||||
});
|
||||
};
|
||||
yield this.wallet.removeKey(this.config.account, key);
|
||||
this.log('removed');
|
||||
});
|
||||
|
||||
CLI.prototype.getAccount = function getAccount(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.getAccount = co(function* getAccount() {
|
||||
var account = this.argv[0] || this.config.account;
|
||||
this.wallet.getAccount(account, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(account);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
yield this.wallet.getAccount(account);
|
||||
this.log(account);
|
||||
});
|
||||
|
||||
CLI.prototype.createAccount = function createAccount(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.createAccount = co(function* createAccount() {
|
||||
var name = this.argv[0];
|
||||
var account = yield this.wallet.createAccount(name);
|
||||
this.log(account);
|
||||
});
|
||||
|
||||
CLI.prototype.createAddress = co(function* createAddress() {
|
||||
var account = this.argv[0];
|
||||
this.wallet.createAccount(account, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(account);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
var addr = yield this.wallet.createAddress(account);
|
||||
this.log(addr);
|
||||
});
|
||||
|
||||
CLI.prototype.createAddress = function createAddress(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.createNested = co(function* createNested() {
|
||||
var account = this.argv[0];
|
||||
this.wallet.createAddress(account, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(account);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
var addr = yield this.wallet.createNested(account);
|
||||
this.log(addr);
|
||||
});
|
||||
|
||||
CLI.prototype.getAccounts = function getAccounts(callback) {
|
||||
var self = this;
|
||||
this.wallet.getAccounts(function(err, accounts) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(accounts);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
CLI.prototype.getAccounts = co(function* getAccounts() {
|
||||
var accounts = yield this.wallet.getAccounts();
|
||||
this.log(accounts);
|
||||
});
|
||||
|
||||
CLI.prototype.getWallet = function getWallet(callback) {
|
||||
var self = this;
|
||||
this.wallet.getInfo(function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(wallet);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
CLI.prototype.getWallet = co(function* getWallet() {
|
||||
var info = yield this.wallet.getInfo();
|
||||
this.log(info);
|
||||
});
|
||||
|
||||
CLI.prototype.getTX = function getTX(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.getTX = co(function* getTX() {
|
||||
var hash = this.argv[0];
|
||||
var txs, tx;
|
||||
|
||||
if (utils.isBase58(hash)) {
|
||||
return this.client.getTXByAddress(hash, function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(txs);
|
||||
callback();
|
||||
});
|
||||
txs = yield this.client.getTXByAddress(hash);
|
||||
this.log(txs);
|
||||
return;
|
||||
}
|
||||
this.client.getTX(hash, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!tx) {
|
||||
self.log('TX not found.');
|
||||
return callback();
|
||||
}
|
||||
tx = yield this.client.getTX(hash);
|
||||
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
if (!tx) {
|
||||
this.log('TX not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
CLI.prototype.getBlock = function getBlock(callback) {
|
||||
var self = this;
|
||||
this.log(tx);
|
||||
});
|
||||
|
||||
CLI.prototype.getBlock = co(function* getBlock() {
|
||||
var hash = this.argv[0];
|
||||
if (hash.length !== 64)
|
||||
hash = +hash;
|
||||
this.client.getBlock(hash, function(err, block) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!block) {
|
||||
self.log('Block not found.');
|
||||
return callback();
|
||||
}
|
||||
block = yield this.client.getBlock(hash);
|
||||
|
||||
self.log(block);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
if (!block) {
|
||||
this.log('Block not found.');
|
||||
return
|
||||
}
|
||||
|
||||
CLI.prototype.getCoin = function getCoin(callback) {
|
||||
var self = this;
|
||||
this.log(block);
|
||||
});
|
||||
|
||||
CLI.prototype.getCoin = co(function* getCoin() {
|
||||
var hash = this.argv[0];
|
||||
var index = this.argv[1];
|
||||
var coins, coin;
|
||||
|
||||
if (utils.isBase58(hash)) {
|
||||
return this.client.getCoinsByAddress(hash, function(err, coins) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(coins);
|
||||
callback();
|
||||
});
|
||||
coins = yield this.client.getCoinsByAddress(hash);
|
||||
this.log(coins);
|
||||
return;
|
||||
}
|
||||
this.client.getCoin(hash, index, function(err, coin) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!coin) {
|
||||
self.log('Coin not found.');
|
||||
return callback();
|
||||
}
|
||||
coin = yield this.client.getCoin(hash, index);
|
||||
|
||||
self.log(coin);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
if (!coin) {
|
||||
this.log('Coin not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
CLI.prototype.getWalletHistory = function getWalletHistory(callback) {
|
||||
var self = this;
|
||||
this.wallet.getHistory(this.config.account, function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(txs);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
this.log(coin);
|
||||
});
|
||||
|
||||
CLI.prototype.listenWallet = function listenWallet(callback) {
|
||||
CLI.prototype.getWalletHistory = co(function* getWalletHistory() {
|
||||
var txs = yield this.wallet.getHistory(this.config.account);
|
||||
this.log(txs);
|
||||
});
|
||||
|
||||
CLI.prototype.listenWallet = function listenWallet() {
|
||||
var self = this;
|
||||
this.wallet.on('tx', function(details) {
|
||||
self.log('TX:');
|
||||
|
|
@ -240,32 +190,22 @@ CLI.prototype.listenWallet = function listenWallet(callback) {
|
|||
self.log('Balance:');
|
||||
self.log(balance);
|
||||
});
|
||||
return new Promise(function() {});
|
||||
};
|
||||
|
||||
CLI.prototype.getBalance = function getBalance(callback) {
|
||||
var self = this;
|
||||
this.wallet.getBalance(this.config.account, function(err, balance) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(balance);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
CLI.prototype.getBalance = co(function* getBalance() {
|
||||
var balance = yield this.wallet.getBalance(this.config.account);
|
||||
this.log(balance);
|
||||
});
|
||||
|
||||
CLI.prototype.getMempool = function getMempool(callback) {
|
||||
var self = this;
|
||||
this.client.getMempool(function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(txs);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
CLI.prototype.getMempool = co(function* getMempool() {
|
||||
var txs = yield this.client.getMempool();
|
||||
this.log(txs);
|
||||
});
|
||||
|
||||
CLI.prototype.sendTX = function sendTX(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.sendTX = co(function* sendTX() {
|
||||
var output = {};
|
||||
var options;
|
||||
var options, tx;
|
||||
|
||||
if (this.config.script) {
|
||||
output.script = this.config.script;
|
||||
|
|
@ -281,18 +221,14 @@ CLI.prototype.sendTX = function sendTX(callback) {
|
|||
outputs: [output]
|
||||
};
|
||||
|
||||
this.wallet.send(options, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
tx = yield this.wallet.send(options);
|
||||
|
||||
CLI.prototype.createTX = function createTX(callback) {
|
||||
var self = this;
|
||||
this.log(tx);
|
||||
});
|
||||
|
||||
CLI.prototype.createTX = co(function* createTX() {
|
||||
var output = {};
|
||||
var options;
|
||||
var options, tx;
|
||||
|
||||
if (this.config.script) {
|
||||
output.script = this.config.script;
|
||||
|
|
@ -308,86 +244,53 @@ CLI.prototype.createTX = function createTX(callback) {
|
|||
outputs: [output]
|
||||
};
|
||||
|
||||
this.wallet.createTX(options, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
tx = yield this.wallet.createTX(options);
|
||||
|
||||
CLI.prototype.signTX = function signTX(callback) {
|
||||
var self = this;
|
||||
this.log(tx);
|
||||
});
|
||||
|
||||
CLI.prototype.signTX = co(function* signTX() {
|
||||
var options = { passphrase: this.config.passphrase };
|
||||
var tx = options.tx || this.argv[0];
|
||||
this.wallet.sign(tx, options, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
var raw = options.tx || this.argv[0];
|
||||
var tx = yield this.wallet.sign(raw, options);
|
||||
this.log(tx);
|
||||
});
|
||||
|
||||
CLI.prototype.zap = function zap(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.zap = co(function* zap() {
|
||||
var age = (this.config.age >>> 0) || 72 * 60 * 60;
|
||||
this.wallet.zap(this.config.account, age, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log('Zapped!');
|
||||
callback();
|
||||
});
|
||||
};
|
||||
yield this.wallet.zap(this.config.account, age);
|
||||
this.log('Zapped!');
|
||||
});
|
||||
|
||||
CLI.prototype.broadcast = function broadcast(callback) {
|
||||
CLI.prototype.broadcast = co(function* broadcast() {
|
||||
var self = this;
|
||||
var tx = this.argv[0] || this.config.tx;
|
||||
this.client.broadcast(tx, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log('Broadcasted:');
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
var raw = this.argv[0] || this.config.tx;
|
||||
var tx = yield this.client.broadcast(raw);
|
||||
this.log('Broadcasted:');
|
||||
this.log(tx);
|
||||
});
|
||||
|
||||
CLI.prototype.viewTX = function viewTX(callback) {
|
||||
var self = this;
|
||||
var tx = this.argv[0] || this.config.tx;
|
||||
this.wallet.fill(tx, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
CLI.prototype.viewTX = co(function* viewTX() {
|
||||
var raw = this.argv[0] || this.config.tx;
|
||||
var tx = yield this.wallet.fill(raw);
|
||||
this.log(tx);
|
||||
});
|
||||
|
||||
CLI.prototype.getDetails = function getDetails(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.getDetails = co(function* getDetails() {
|
||||
var hash = this.argv[0];
|
||||
this.wallet.getTX(hash, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(tx);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
var details = yield this.wallet.getTX(hash);
|
||||
this.log(details);
|
||||
});
|
||||
|
||||
CLI.prototype.retoken = function retoken(callback) {
|
||||
var self = this;
|
||||
this.wallet.retoken(function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(result);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
CLI.prototype.retoken = co(function* retoken() {
|
||||
var result = yield this.wallet.retoken();
|
||||
this.log(result);
|
||||
});
|
||||
|
||||
CLI.prototype.rpc = function rpc(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.rpc = co(function* rpc() {
|
||||
var method = this.argv.shift();
|
||||
var params = [];
|
||||
var i, arg, param;
|
||||
var i, arg, param, result;
|
||||
|
||||
for (i = 0; i < this.argv.length; i++) {
|
||||
arg = this.argv[i];
|
||||
|
|
@ -399,17 +302,12 @@ CLI.prototype.rpc = function rpc(callback) {
|
|||
params.push(param);
|
||||
}
|
||||
|
||||
this.client.rpc.call(method, params, function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.log(result);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
result = yield this.client.rpc.call(method, params);
|
||||
|
||||
CLI.prototype.handleWallet = function handleWallet(callback) {
|
||||
var self = this;
|
||||
this.log(result);
|
||||
});
|
||||
|
||||
CLI.prototype.handleWallet = co(function* handleWallet() {
|
||||
var options = {
|
||||
id: this.config.id || 'primary',
|
||||
token: this.config.token
|
||||
|
|
@ -421,81 +319,81 @@ CLI.prototype.handleWallet = function handleWallet(callback) {
|
|||
network: this.config.network
|
||||
});
|
||||
|
||||
this.wallet.open(options, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
yield this.wallet.open(options);
|
||||
|
||||
switch (self.argv.shift()) {
|
||||
case 'listen':
|
||||
return self.listenWallet(callback);
|
||||
case 'get':
|
||||
return self.getWallet(callback);
|
||||
case 'addkey':
|
||||
return self.addKey(callback);
|
||||
case 'rmkey':
|
||||
return self.removeKey(callback);
|
||||
case 'balance':
|
||||
return self.getBalance(callback);
|
||||
case 'history':
|
||||
return self.getWalletHistory(callback);
|
||||
case 'account':
|
||||
if (self.argv[0] === 'list') {
|
||||
self.argv.shift();
|
||||
return self.getAccounts(callback);
|
||||
}
|
||||
if (self.argv[0] === 'create') {
|
||||
self.argv.shift();
|
||||
return self.createAccount(callback);
|
||||
}
|
||||
if (self.argv[0] === 'get')
|
||||
self.argv.shift();
|
||||
return self.getAccount(callback);
|
||||
case 'address':
|
||||
return self.createAddress(callback);
|
||||
case 'retoken':
|
||||
return self.retoken(callback);
|
||||
case 'sign':
|
||||
return self.signTX(callback);
|
||||
case 'mktx':
|
||||
return self.createTX(callback);
|
||||
case 'send':
|
||||
return self.sendTX(callback);
|
||||
case 'zap':
|
||||
return self.zap(callback);
|
||||
case 'tx':
|
||||
return self.getDetails(callback);
|
||||
case 'view':
|
||||
return self.viewTX(callback);
|
||||
default:
|
||||
self.log('Unrecognized command.');
|
||||
self.log('Commands:');
|
||||
self.log(' $ listen: Listen for events.');
|
||||
self.log(' $ get: View wallet.');
|
||||
self.log(' $ addkey [xpubkey]: Add key to wallet.');
|
||||
self.log(' $ rmkey [xpubkey]: Remove key from wallet.');
|
||||
self.log(' $ balance: Get wallet balance.');
|
||||
self.log(' $ history: View wallet TX history.');
|
||||
self.log(' $ account list: List account names.');
|
||||
self.log(' $ account create [account-name]: Create account.');
|
||||
self.log(' $ account get [account-name]: Get account details.');
|
||||
self.log(' $ address: Derive new address.');
|
||||
self.log(' $ retoken: Create new api key.');
|
||||
self.log(' $ send [address] [value]: Send transaction.');
|
||||
self.log(' $ mktx [address] [value]: Create transaction.');
|
||||
self.log(' $ sign [tx-hex]: Sign transaction.');
|
||||
self.log(' $ zap --age [age]: Zap pending wallet TXs.');
|
||||
self.log(' $ tx [hash]: View transaction details.');
|
||||
self.log(' $ view [tx-hex]: Parse and view transaction.');
|
||||
self.log('Other Options:');
|
||||
self.log(' --passphrase [passphrase]: For signing and account creation.');
|
||||
self.log(' --account [account-name]: Account name.');
|
||||
return callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
switch (this.argv.shift()) {
|
||||
case 'listen':
|
||||
return yield this.listenWallet();
|
||||
case 'get':
|
||||
return yield this.getWallet();
|
||||
case 'addkey':
|
||||
return yield this.addKey();
|
||||
case 'rmkey':
|
||||
return yield this.removeKey();
|
||||
case 'balance':
|
||||
return yield this.getBalance();
|
||||
case 'history':
|
||||
return yield this.getWalletHistory();
|
||||
case 'account':
|
||||
if (this.argv[0] === 'list') {
|
||||
this.argv.shift();
|
||||
return yield this.getAccounts();
|
||||
}
|
||||
if (this.argv[0] === 'create') {
|
||||
this.argv.shift();
|
||||
return yield this.createAccount();
|
||||
}
|
||||
if (this.argv[0] === 'get')
|
||||
this.argv.shift();
|
||||
return yield this.getAccount();
|
||||
case 'address':
|
||||
return yield this.createAddress();
|
||||
case 'nested':
|
||||
return yield this.createNested();
|
||||
case 'retoken':
|
||||
return yield this.retoken();
|
||||
case 'sign':
|
||||
return yield this.signTX();
|
||||
case 'mktx':
|
||||
return yield this.createTX();
|
||||
case 'send':
|
||||
return yield this.sendTX();
|
||||
case 'zap':
|
||||
return yield this.zap();
|
||||
case 'tx':
|
||||
return yield this.getDetails();
|
||||
case 'view':
|
||||
return yield this.viewTX();
|
||||
default:
|
||||
this.log('Unrecognized command.');
|
||||
this.log('Commands:');
|
||||
this.log(' $ listen: Listen for events.');
|
||||
this.log(' $ get: View wallet.');
|
||||
this.log(' $ addkey [xpubkey]: Add key to wallet.');
|
||||
this.log(' $ rmkey [xpubkey]: Remove key from wallet.');
|
||||
this.log(' $ balance: Get wallet balance.');
|
||||
this.log(' $ history: View wallet TX history.');
|
||||
this.log(' $ account list: List account names.');
|
||||
this.log(' $ account create [account-name]: Create account.');
|
||||
this.log(' $ account get [account-name]: Get account details.');
|
||||
this.log(' $ address: Derive new address.');
|
||||
this.log(' $ nested: Derive new nested address.');
|
||||
this.log(' $ retoken: Create new api key.');
|
||||
this.log(' $ send [address] [value]: Send transaction.');
|
||||
this.log(' $ mktx [address] [value]: Create transaction.');
|
||||
this.log(' $ sign [tx-hex]: Sign transaction.');
|
||||
this.log(' $ zap --age [age]: Zap pending wallet TXs.');
|
||||
this.log(' $ tx [hash]: View transaction details.');
|
||||
this.log(' $ view [tx-hex]: Parse and view transaction.');
|
||||
this.log('Other Options:');
|
||||
this.log(' --passphrase [passphrase]: For signing and account creation.');
|
||||
this.log(' --account [account-name]: Account name.');
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
CLI.prototype.handleNode = function handleNode(callback) {
|
||||
var self = this;
|
||||
CLI.prototype.handleNode = co(function* handleNode() {
|
||||
var info;
|
||||
|
||||
this.client = new Client({
|
||||
uri: this.config.url || this.config.uri,
|
||||
|
|
@ -503,75 +401,67 @@ CLI.prototype.handleNode = function handleNode(callback) {
|
|||
network: this.config.network
|
||||
});
|
||||
|
||||
this.client.getInfo(function(err, info) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
info = yield this.client.getInfo();
|
||||
|
||||
switch (self.argv.shift()) {
|
||||
case 'mkwallet':
|
||||
return self.createWallet(callback);
|
||||
case 'broadcast':
|
||||
return self.broadcast(callback);
|
||||
case 'mempool':
|
||||
return self.getMempool(callback);
|
||||
case 'tx':
|
||||
return self.getTX(callback);
|
||||
case 'coin':
|
||||
return self.getCoin(callback);
|
||||
case 'block':
|
||||
return self.getBlock(callback);
|
||||
case 'rpc':
|
||||
return self.rpc(callback);
|
||||
default:
|
||||
self.log('Unrecognized command.');
|
||||
self.log('Commands:');
|
||||
self.log(' $ wallet create [id]: Create wallet.');
|
||||
self.log(' $ broadcast [tx-hex]: Broadcast transaction.');
|
||||
self.log(' $ mempool: Get mempool snapshot.');
|
||||
self.log(' $ tx [hash/address]: View transactions.');
|
||||
self.log(' $ coin [hash+index/address]: View coins.');
|
||||
self.log(' $ block [hash/height]: View block.');
|
||||
return callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
switch (this.argv.shift()) {
|
||||
case 'mkwallet':
|
||||
return yield this.createWallet();
|
||||
case 'broadcast':
|
||||
return yield this.broadcast();
|
||||
case 'mempool':
|
||||
return yield this.getMempool();
|
||||
case 'tx':
|
||||
return yield this.getTX();
|
||||
case 'coin':
|
||||
return yield this.getCoin();
|
||||
case 'block':
|
||||
return yield this.getBlock();
|
||||
case 'rpc':
|
||||
return yield this.rpc();
|
||||
default:
|
||||
this.log('Unrecognized command.');
|
||||
this.log('Commands:');
|
||||
this.log(' $ wallet create [id]: Create wallet.');
|
||||
this.log(' $ broadcast [tx-hex]: Broadcast transaction.');
|
||||
this.log(' $ mempool: Get mempool snapshot.');
|
||||
this.log(' $ tx [hash/address]: View transactions.');
|
||||
this.log(' $ coin [hash+index/address]: View coins.');
|
||||
this.log(' $ block [hash/height]: View block.');
|
||||
this.log(' $ rpc [command] [args]: Execute RPC command.');
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
CLI.prototype.open = function open(callback) {
|
||||
CLI.prototype.open = co(function* open() {
|
||||
switch (this.argv[0]) {
|
||||
case 'w':
|
||||
case 'wallet':
|
||||
this.argv.shift();
|
||||
if (this.argv[0] === 'create') {
|
||||
this.argv[0] = 'mkwallet';
|
||||
return this.handleNode(callback);
|
||||
return yield this.handleNode();
|
||||
}
|
||||
return this.handleWallet(callback);
|
||||
return yield this.handleWallet();
|
||||
default:
|
||||
return this.handleNode(callback);
|
||||
return yield this.handleNode();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CLI.prototype.destroy = function destroy(callback) {
|
||||
CLI.prototype.destroy = function destroy() {
|
||||
if (this.wallet && !this.wallet.client.loading)
|
||||
this.wallet.client.destroy();
|
||||
if (this.client && !this.client.loading)
|
||||
this.client.destroy();
|
||||
callback();
|
||||
return Promise.resolve(null);
|
||||
};
|
||||
|
||||
function main(callback) {
|
||||
main = co(function* main() {
|
||||
var cli = new CLI();
|
||||
cli.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
cli.destroy(callback);
|
||||
});
|
||||
}
|
||||
|
||||
main(function(err) {
|
||||
if (err) {
|
||||
console.error(err.stack + '');
|
||||
return process.exit(1);
|
||||
}
|
||||
return process.exit(0);
|
||||
yield cli.open();
|
||||
yield cli.destroy();
|
||||
});
|
||||
|
||||
main().then(process.exit).catch(function(err) {
|
||||
console.error(err.stack + '');
|
||||
return process.exit(1);
|
||||
});
|
||||
|
|
|
|||
7
bin/node
7
bin/node
|
|
@ -6,7 +6,7 @@ process.title = 'bcoin';
|
|||
|
||||
var bcoin = require('../');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
|
||||
var options = bcoin.config({
|
||||
config: true,
|
||||
|
|
@ -32,10 +32,7 @@ process.on('uncaughtException', function(err) {
|
|||
process.exit(1);
|
||||
});
|
||||
|
||||
node.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
node.open().then(function() {
|
||||
node.pool.connect();
|
||||
node.startSync();
|
||||
});
|
||||
|
|
|
|||
11
bin/spvnode
11
bin/spvnode
|
|
@ -6,7 +6,7 @@ process.title = 'bcoin';
|
|||
|
||||
var bcoin = require('../');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
|
||||
var options = bcoin.config({
|
||||
config: true,
|
||||
|
|
@ -25,10 +25,13 @@ node.on('error', function(err) {
|
|||
;
|
||||
});
|
||||
|
||||
node.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
process.on('uncaughtException', function(err) {
|
||||
node.logger.debug(err.stack);
|
||||
node.logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
node.open().then(function() {
|
||||
if (process.argv.indexOf('--test') !== -1) {
|
||||
node.pool.watchAddress('1VayNert3x1KzbpzMGt2qdqrAThiRovi8');
|
||||
node.pool.watch(bcoin.outpoint().toRaw());
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
margin-top: 10px;
|
||||
font: 1em monospace;
|
||||
}
|
||||
.send {
|
||||
.rpc, .send {
|
||||
padding: 5px;
|
||||
margin-left: 5px;
|
||||
margin-top: 10px;
|
||||
|
|
@ -84,6 +84,10 @@ more bitcoin magic).</small>
|
|||
<div id="tx"></div>
|
||||
</div>
|
||||
<div id="log" class="log"></div>
|
||||
<form id="rpc" class="rpc" action="#">
|
||||
<input type="text" name="cmd" id="cmd"
|
||||
placeholder="RPC command (e.g. getblockchaininfo)">
|
||||
</form>
|
||||
<div id="wallet" class="wallet"></div>
|
||||
<form id="send" class="send" action="#">
|
||||
<input type="text" name="address" id="address" placeholder="Address">
|
||||
|
|
@ -92,220 +96,6 @@ more bitcoin magic).</small>
|
|||
</form>
|
||||
<input type="button" id="newaddr" value="New Address">
|
||||
<div id="floating" class="floating"></div>
|
||||
<script>
|
||||
;(function() {
|
||||
'use strict';
|
||||
|
||||
var utils = bcoin.utils;
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
var log = document.getElementById('log');
|
||||
var wdiv = document.getElementById('wallet');
|
||||
var tdiv = document.getElementById('tx');
|
||||
var floating = document.getElementById('floating');
|
||||
var send = document.getElementById('send');
|
||||
var newaddr = document.getElementById('newaddr');
|
||||
var chainState = document.getElementById('state');
|
||||
var items = [];
|
||||
var scrollback = 0;
|
||||
var logger, node, options;
|
||||
|
||||
body.onmouseup = function() {
|
||||
floating.style.display = 'none';
|
||||
};
|
||||
|
||||
floating.onmouseup = function(ev) {
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
function show(obj) {
|
||||
floating.innerHTML = escape(utils.inspectify(obj, false));
|
||||
floating.style.display = 'block';
|
||||
}
|
||||
|
||||
logger = new bcoin.logger({ level: 'debug' });
|
||||
logger.writeConsole = function(level, args) {
|
||||
var msg = utils.format(args, false);
|
||||
if (++scrollback > 1000) {
|
||||
log.innerHTML = '';
|
||||
scrollback = 1;
|
||||
}
|
||||
log.innerHTML += '<span style="color:blue;">' + utils.now() + '</span> ';
|
||||
if (level === 'error')
|
||||
log.innerHTML += '<span style="color:red;">[' + level + ']</span> ';
|
||||
else
|
||||
log.innerHTML += '[' + level + '] ';
|
||||
log.innerHTML += escape(msg) + '\n';
|
||||
log.scrollTop = log.scrollHeight;
|
||||
};
|
||||
|
||||
send.onsubmit = function(ev) {
|
||||
var value = document.getElementById('amount').value;
|
||||
var address = document.getElementById('address').value;
|
||||
|
||||
var options = {
|
||||
outputs: [{
|
||||
address: address,
|
||||
value: utils.satoshi(value)
|
||||
}]
|
||||
};
|
||||
|
||||
node.wallet.createTX(options, function(err, tx) {
|
||||
if (err)
|
||||
return node.logger.error(err);
|
||||
|
||||
node.wallet.sign(tx, function(err) {
|
||||
if (err)
|
||||
return node.logger.error(err);
|
||||
|
||||
node.sendTX(tx, function(err) {
|
||||
if (err)
|
||||
return node.logger.error(err);
|
||||
|
||||
show(tx);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
newaddr.onmouseup = function() {
|
||||
node.wallet.createReceive(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
formatWallet(node.wallet);
|
||||
});
|
||||
};
|
||||
|
||||
function kb(size) {
|
||||
size /= 1000;
|
||||
return size.toFixed(2) + 'kb';
|
||||
}
|
||||
|
||||
function create(html) {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = html;
|
||||
return el.firstChild;
|
||||
}
|
||||
|
||||
function escape(html, encode) {
|
||||
return html
|
||||
.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function addItem(tx) {
|
||||
var el;
|
||||
|
||||
if (items.length === 20) {
|
||||
el = items.shift();
|
||||
tdiv.removeChild(el);
|
||||
el.onmouseup = null;
|
||||
}
|
||||
|
||||
el = create('<a style="display:block;" href="#'
|
||||
+ tx.rhash + '">' + tx.rhash + ' (' + tx.height
|
||||
+ ' - ' + kb(tx.getSize()) + ')</a>');
|
||||
tdiv.appendChild(el);
|
||||
|
||||
el.onmouseup = function(ev) {
|
||||
show(tx);
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
items.push(el);
|
||||
|
||||
chainState.innerHTML = ''
|
||||
+ 'tx=' + node.chain.db.state.tx
|
||||
+ ' coin=' + node.chain.db.state.coin
|
||||
+ ' value=' + utils.btc(node.chain.db.state.value);
|
||||
}
|
||||
|
||||
function formatWallet(wallet) {
|
||||
var html = '';
|
||||
var key = wallet.master.toJSON().key;
|
||||
html += '<b>Wallet</b><br>';
|
||||
if (bcoin.network.get().type === 'segnet4') {
|
||||
html += 'Current Address (p2wpkh): <b>' + wallet.getAddress() + '</b><br>';
|
||||
html += 'Current Address (p2wpkh behind p2sh): <b>' + wallet.getProgramAddress() + '</b><br>';
|
||||
} else {
|
||||
html += 'Current Address: <b>' + wallet.getAddress() + '</b><br>';
|
||||
}
|
||||
html += 'Extended Private Key: <b>' + key.xprivkey + '</b><br>';
|
||||
html += 'Mnemonic: <b>' + key.mnemonic.phrase + '</b><br>';
|
||||
wallet.getBalance(function(err, balance) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
html += 'Confirmed Balance: <b>' + utils.btc(balance.confirmed) + '</b><br>';
|
||||
html += 'Unconfirmed Balance: <b>' + utils.btc(balance.unconfirmed) + '</b><br>';
|
||||
html += 'Balance: <b>' + utils.btc(balance.total) + '</b><br>';
|
||||
|
||||
wallet.getHistory(function(err, txs) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
wallet.toDetails(txs, function(err, txs) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
html += 'TXs:\n';
|
||||
wdiv.innerHTML = html;
|
||||
|
||||
txs.forEach(function(tx) {
|
||||
var el = create('<a style="display:block;" href="#' + tx.hash + '">' + tx.hash + '</a>');
|
||||
wdiv.appendChild(el);
|
||||
el.onmouseup = function(ev) {
|
||||
show(tx.toJSON());
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
options = bcoin.config({
|
||||
query: true,
|
||||
network: 'segnet4',
|
||||
db: 'leveldb',
|
||||
useWorkers: true,
|
||||
coinCache: true,
|
||||
logger: logger
|
||||
});
|
||||
|
||||
bcoin.set(options);
|
||||
|
||||
node = new bcoin.fullnode(options);
|
||||
|
||||
node.on('error', function(err) {
|
||||
;
|
||||
});
|
||||
|
||||
node.chain.on('block', addItem);
|
||||
node.mempool.on('tx', addItem);
|
||||
|
||||
node.open(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
node.startSync();
|
||||
|
||||
formatWallet(node.wallet);
|
||||
|
||||
node.wallet.on('update', function() {
|
||||
formatWallet(node.wallet);
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script src="/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
245
browser/index.js
Normal file
245
browser/index.js
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
;(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
var utils = bcoin.utils;
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
var log = document.getElementById('log');
|
||||
var wdiv = document.getElementById('wallet');
|
||||
var tdiv = document.getElementById('tx');
|
||||
var floating = document.getElementById('floating');
|
||||
var send = document.getElementById('send');
|
||||
var newaddr = document.getElementById('newaddr');
|
||||
var chainState = document.getElementById('state');
|
||||
var rpc = document.getElementById('rpc');
|
||||
var cmd = document.getElementById('cmd');
|
||||
var items = [];
|
||||
var scrollback = 0;
|
||||
var logger, node, options;
|
||||
|
||||
body.onmouseup = function() {
|
||||
floating.style.display = 'none';
|
||||
};
|
||||
|
||||
floating.onmouseup = function(ev) {
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
function show(obj) {
|
||||
floating.innerHTML = escape(utils.inspectify(obj, false));
|
||||
floating.style.display = 'block';
|
||||
}
|
||||
|
||||
logger = new bcoin.logger({ level: 'debug' });
|
||||
logger.writeConsole = function(level, args) {
|
||||
var msg = utils.format(args, false);
|
||||
if (++scrollback > 1000) {
|
||||
log.innerHTML = '';
|
||||
scrollback = 1;
|
||||
}
|
||||
log.innerHTML += '<span style="color:blue;">' + utils.now() + '</span> ';
|
||||
if (level === 'error')
|
||||
log.innerHTML += '<span style="color:red;">[' + level + ']</span> ';
|
||||
else
|
||||
log.innerHTML += '[' + level + '] ';
|
||||
log.innerHTML += escape(msg) + '\n';
|
||||
log.scrollTop = log.scrollHeight;
|
||||
};
|
||||
|
||||
rpc.onsubmit = function(ev) {
|
||||
var text = cmd.value || '';
|
||||
var argv = text.trim().split(/\s+/);
|
||||
var method = argv.shift();
|
||||
var params = [];
|
||||
var i, arg, param;
|
||||
|
||||
cmd.value = '';
|
||||
|
||||
for (i = 0; i < argv.length; i++) {
|
||||
arg = argv[i];
|
||||
try {
|
||||
param = JSON.parse(arg);
|
||||
} catch (e) {
|
||||
param = arg;
|
||||
}
|
||||
params.push(param);
|
||||
}
|
||||
|
||||
node.rpc.execute({ method: method, params: params }).then(show, show);
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
send.onsubmit = function(ev) {
|
||||
var value = document.getElementById('amount').value;
|
||||
var address = document.getElementById('address').value;
|
||||
var tx, options;
|
||||
|
||||
options = {
|
||||
outputs: [{
|
||||
address: address,
|
||||
value: utils.satoshi(value)
|
||||
}]
|
||||
};
|
||||
|
||||
node.wallet.createTX(options).then(function(mtx) {
|
||||
tx = mtx;
|
||||
return node.wallet.sign(tx);
|
||||
}).then(function() {
|
||||
return node.sendTX(tx);
|
||||
}).then(function() {
|
||||
show(tx);
|
||||
});
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
newaddr.onmouseup = function() {
|
||||
node.wallet.createReceive().then(function() {
|
||||
formatWallet(node.wallet);
|
||||
});
|
||||
};
|
||||
|
||||
function kb(size) {
|
||||
size /= 1000;
|
||||
return size.toFixed(2) + 'kb';
|
||||
}
|
||||
|
||||
function create(html) {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = html;
|
||||
return el.firstChild;
|
||||
}
|
||||
|
||||
function escape(html, encode) {
|
||||
return html
|
||||
.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function addItem(tx) {
|
||||
var el;
|
||||
|
||||
if (items.length === 20) {
|
||||
el = items.shift();
|
||||
tdiv.removeChild(el);
|
||||
el.onmouseup = null;
|
||||
}
|
||||
|
||||
el = create('<a style="display:block;" href="#'
|
||||
+ tx.rhash + '">' + tx.rhash + ' (' + tx.height
|
||||
+ ' - ' + kb(tx.getSize()) + ')</a>');
|
||||
tdiv.appendChild(el);
|
||||
|
||||
setMouseup(el, tx);
|
||||
|
||||
items.push(el);
|
||||
|
||||
chainState.innerHTML = ''
|
||||
+ 'tx=' + node.chain.db.state.tx
|
||||
+ ' coin=' + node.chain.db.state.coin
|
||||
+ ' value=' + utils.btc(node.chain.db.state.value);
|
||||
}
|
||||
|
||||
function setMouseup(el, obj) {
|
||||
el.onmouseup = function(ev) {
|
||||
show(obj);
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
function formatWallet(wallet) {
|
||||
var html = '';
|
||||
var key = wallet.master.toJSON().key;
|
||||
var i, tx, el;
|
||||
|
||||
html += '<b>Wallet</b><br>';
|
||||
|
||||
if (bcoin.network.primary.witness) {
|
||||
html += 'Current Address (p2wpkh): <b>'
|
||||
+ wallet.getAddress()
|
||||
+ '</b><br>';
|
||||
html += 'Current Address (p2wpkh behind p2sh): <b>'
|
||||
+ wallet.getProgramAddress()
|
||||
+ '</b><br>';
|
||||
} else {
|
||||
html += 'Current Address: <b>' + wallet.getAddress() + '</b><br>';
|
||||
}
|
||||
|
||||
html += 'Extended Private Key: <b>' + key.xprivkey + '</b><br>';
|
||||
html += 'Mnemonic: <b>' + key.mnemonic.phrase + '</b><br>';
|
||||
|
||||
wallet.getBalance().then(function(balance) {
|
||||
html += 'Confirmed Balance: <b>'
|
||||
+ utils.btc(balance.confirmed)
|
||||
+ '</b><br>';
|
||||
|
||||
html += 'Unconfirmed Balance: <b>'
|
||||
+ utils.btc(balance.unconfirmed)
|
||||
+ '</b><br>';
|
||||
|
||||
html += 'Balance: <b>' + utils.btc(balance.total) + '</b><br>';
|
||||
|
||||
return wallet.getHistory();
|
||||
}).then(function(txs) {
|
||||
return wallet.toDetails(txs);
|
||||
}).then(function(txs) {
|
||||
html += 'TXs:\n';
|
||||
wdiv.innerHTML = html;
|
||||
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
|
||||
el = create(
|
||||
'<a style="display:block;" href="#' + tx.hash + '">'
|
||||
+ tx.hash + '</a>');
|
||||
|
||||
wdiv.appendChild(el);
|
||||
setMouseup(el, tx.toJSON());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
options = bcoin.config({
|
||||
query: true,
|
||||
network: 'segnet4',
|
||||
db: 'leveldb',
|
||||
useWorkers: true,
|
||||
coinCache: true,
|
||||
logger: logger
|
||||
});
|
||||
|
||||
bcoin.set(options);
|
||||
|
||||
node = new bcoin.fullnode(options);
|
||||
node.rpc = new bcoin.rpc(node);
|
||||
|
||||
node.on('error', function(err) {
|
||||
;
|
||||
});
|
||||
|
||||
node.chain.on('block', addItem);
|
||||
node.mempool.on('tx', addItem);
|
||||
|
||||
node.open().then(function() {
|
||||
node.startSync();
|
||||
|
||||
formatWallet(node.wallet);
|
||||
|
||||
node.wallet.on('balance', function() {
|
||||
formatWallet(node.wallet);
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
@ -15,22 +15,27 @@ proxy.on('error', function(err) {
|
|||
});
|
||||
|
||||
var index = fs.readFileSync(__dirname + '/index.html');
|
||||
var indexjs = fs.readFileSync(__dirname + '/index.js');
|
||||
var bcoin = fs.readFileSync(__dirname + '/bcoin.js');
|
||||
var worker = fs.readFileSync(__dirname + '/../lib/workers/worker.js');
|
||||
|
||||
server.get('/favicon.ico', function(req, res, next, send) {
|
||||
server.get('/favicon.ico', function(req, res, send, next) {
|
||||
send(404, '', 'text');
|
||||
});
|
||||
|
||||
server.get('/', function(req, res, next, send) {
|
||||
server.get('/', function(req, res, send, next) {
|
||||
send(200, index, 'html');
|
||||
});
|
||||
|
||||
server.get('/bcoin.js', function(req, res, next, send) {
|
||||
server.get('/index.js', function(req, res, send, next) {
|
||||
send(200, indexjs, 'js');
|
||||
});
|
||||
|
||||
server.get('/bcoin.js', function(req, res, send, next) {
|
||||
send(200, bcoin, 'js');
|
||||
});
|
||||
|
||||
server.get('/bcoin-worker.js', function(req, res, next, send) {
|
||||
server.get('/bcoin-worker.js', function(req, res, send, next) {
|
||||
send(200, worker, 'js');
|
||||
});
|
||||
|
||||
|
|
|
|||
75
browser/transform.js
Normal file
75
browser/transform.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
var Transform = require('stream').Transform;
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
var StringDecoder = require('string_decoder').StringDecoder;
|
||||
|
||||
function nil() {
|
||||
var stream = new Transform();
|
||||
|
||||
stream._transform = function(chunk, encoding, callback) {
|
||||
callback(null, chunk);
|
||||
};
|
||||
|
||||
stream._flush = function(callback) {
|
||||
callback();
|
||||
};
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
function processEnv(str) {
|
||||
return str.replace(
|
||||
/^( *)this\.require\('(\w+)', '([^']+)'\)/gm,
|
||||
'$1this.$2 = require(\'$3\')');
|
||||
}
|
||||
|
||||
function processLazy(str) {
|
||||
str.replace(
|
||||
/^( *)lazy\('(\w+)', '([^']+)'\)/gm,
|
||||
function(_, sp, w1, w2) {
|
||||
str += sp + 'if (0) require(\'' + w2 + '\');\n';
|
||||
return '';
|
||||
}
|
||||
);
|
||||
return str;
|
||||
}
|
||||
|
||||
function transformer(file, process) {
|
||||
var stream = new Transform();
|
||||
var decoder = new StringDecoder('utf8');
|
||||
var str = '';
|
||||
|
||||
stream._transform = function(chunk, encoding, callback) {
|
||||
assert(Buffer.isBuffer(chunk));
|
||||
str += decoder.write(chunk);
|
||||
callback(null, new Buffer(0));
|
||||
};
|
||||
|
||||
stream._flush = function(callback) {
|
||||
str = process(str);
|
||||
|
||||
stream.push(new Buffer(str, 'utf8'));
|
||||
|
||||
callback();
|
||||
};
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
function end(file, offset) {
|
||||
return path.normalize(file).split(path.sep).slice(-offset).join('/');
|
||||
}
|
||||
|
||||
module.exports = function(file) {
|
||||
if (end(file, 3) === 'lib/utils/utils.js')
|
||||
return transformer(file, processLazy);
|
||||
|
||||
if (end(file, 3) === 'lib/crypto/crypto.js')
|
||||
return transformer(file, processLazy);
|
||||
|
||||
if (end(file, 2) === 'lib/env.js')
|
||||
return transformer(file, processEnv);
|
||||
|
||||
return nil();
|
||||
};
|
||||
|
|
@ -52,7 +52,6 @@ known-peers: ./known-peers
|
|||
# Miner
|
||||
# payout-address: 1111111111111111111114oLvT2
|
||||
# coinbase-flags: mined by bcoin
|
||||
# parallel: false
|
||||
|
||||
# HTTP
|
||||
# ssl-cert: @/ssl/cert.crt
|
||||
|
|
|
|||
|
|
@ -1,589 +0,0 @@
|
|||
/*!
|
||||
* bip70.js - bip70 for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var assert = require('assert');
|
||||
var utils = bcoin.utils;
|
||||
var crypto = require('../crypto/crypto');
|
||||
var x509 = require('./x509');
|
||||
var asn1 = require('./asn1');
|
||||
var protobuf = require('./protobuf');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
function PaymentRequest(options) {
|
||||
if (!(this instanceof PaymentRequest))
|
||||
return new PaymentRequest(options);
|
||||
|
||||
this.version = -1;
|
||||
this.pkiType = null;
|
||||
this.pkiData = null;
|
||||
this.paymentDetails = new PaymentDetails();
|
||||
this.signature = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
PaymentRequest.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.version != null) {
|
||||
assert(utils.isNumber(options.version));
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
if (options.pkiType != null) {
|
||||
assert(typeof options.pkiType === 'string');
|
||||
this.pkiType = options.pkiType;
|
||||
}
|
||||
|
||||
if (options.pkiData) {
|
||||
assert(Buffer.isBuffer(options.pkiData));
|
||||
this.pkiData = options.pkiData;
|
||||
}
|
||||
|
||||
if (options.paymentDetails)
|
||||
this.paymentDetails.fromOptions(options.paymentDetails);
|
||||
|
||||
if (options.signature) {
|
||||
assert(Buffer.isBuffer(options.signature));
|
||||
this.signature = options.signature;
|
||||
}
|
||||
|
||||
if (options.chain)
|
||||
this.setChain(options.chain);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentRequest.fromOptions = function fromOptions(options) {
|
||||
return new PaymentRequest().fromOptions(options);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
|
||||
this.version = p.readFieldU32(1, true);
|
||||
this.pkiType = p.readFieldString(2, true);
|
||||
this.pkiData = p.readFieldBytes(3, true);
|
||||
this.paymentDetails.fromRaw(p.readFieldBytes(4));
|
||||
this.signature = p.readFieldBytes(5, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentRequest.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new PaymentRequest().fromRaw(data);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
|
||||
if (this.version !== -1)
|
||||
p.writeFieldU32(1, this.version);
|
||||
|
||||
if (this.pkiType != null)
|
||||
p.writeFieldString(2, this.pkiType);
|
||||
|
||||
if (this.pkiData)
|
||||
p.writeFieldBytes(3, this.pkiData);
|
||||
|
||||
p.writeFieldBytes(4, this.paymentDetails.toRaw());
|
||||
|
||||
if (this.signature)
|
||||
p.writeFieldBytes(5, this.signature);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.getAlgorithm = function getAlgorithm() {
|
||||
var parts;
|
||||
|
||||
if (!this.pkiType)
|
||||
return;
|
||||
|
||||
parts = this.pkiType.split('+');
|
||||
|
||||
if (parts.length !== 2)
|
||||
return;
|
||||
|
||||
if (parts[0] !== 'x509')
|
||||
return;
|
||||
|
||||
if (parts[1] !== 'sha1' && parts[1] !== 'sha256')
|
||||
return;
|
||||
|
||||
return { key: parts[0], hash: parts[1] };
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.signatureData = function signatureData() {
|
||||
var signature = this.signature;
|
||||
var data;
|
||||
|
||||
this.signature = new Buffer(0);
|
||||
|
||||
data = this.toRaw();
|
||||
|
||||
this.signature = signature;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.signatureHash = function signatureHash() {
|
||||
var alg = this.getAlgorithm();
|
||||
assert(alg, 'No hash algorithm available.');
|
||||
return crypto.hash(alg.hash, this.signatureData());
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.setChain = function setChain(chain) {
|
||||
var p = new ProtoWriter();
|
||||
var i, cert, pem;
|
||||
|
||||
if (!Array.isArray(chain))
|
||||
chain = [chain];
|
||||
|
||||
for (i = 0; i < chain.length; i++) {
|
||||
cert = chain[i];
|
||||
if (typeof cert === 'string') {
|
||||
pem = asn1.fromPEM(cert);
|
||||
assert(pem.type === 'certificate', 'Bad certificate PEM.');
|
||||
cert = pem.data;
|
||||
}
|
||||
assert(Buffer.isBuffer(cert), 'Certificates must be PEM or DER.');
|
||||
p.writeFieldBytes(1, cert);
|
||||
}
|
||||
|
||||
this.pkiData = p.render();
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.getChain = function getChain() {
|
||||
var chain = [];
|
||||
var p;
|
||||
|
||||
if (!this.pkiData)
|
||||
return chain;
|
||||
|
||||
p = new ProtoReader(this.pkiData);
|
||||
|
||||
while (p.nextTag() === 1)
|
||||
chain.push(p.readFieldBytes(1));
|
||||
|
||||
return chain;
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.sign = function sign(key, chain) {
|
||||
var alg, msg;
|
||||
|
||||
if (chain)
|
||||
this.setChain(chain);
|
||||
|
||||
if (!this.pkiType)
|
||||
this.pkiType = 'x509+sha256';
|
||||
|
||||
alg = this.getAlgorithm();
|
||||
assert(alg, 'No hash algorithm available.');
|
||||
|
||||
msg = this.signatureData();
|
||||
chain = this.getChain();
|
||||
|
||||
this.signature = x509.signSubject(alg.hash, msg, key, chain);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.verify = function verify() {
|
||||
var alg, msg, sig, chain;
|
||||
|
||||
if (!this.pkiType || this.pkiType === 'none')
|
||||
return true;
|
||||
|
||||
if (!this.signature)
|
||||
return false;
|
||||
|
||||
alg = this.getAlgorithm();
|
||||
|
||||
if (!alg)
|
||||
return false;
|
||||
|
||||
msg = this.signatureData();
|
||||
sig = this.signature;
|
||||
chain = this.getChain();
|
||||
|
||||
return x509.verifySubject(alg.hash, msg, sig, chain);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.verifyChain = function verifyChain() {
|
||||
if (!this.pkiType || this.pkiType === 'none')
|
||||
return true;
|
||||
|
||||
return x509.verifyChain(this.getChain());
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.getCA = function getCA() {
|
||||
var chain, root;
|
||||
|
||||
if (!this.pkiType || this.pkiType === 'none')
|
||||
return;
|
||||
|
||||
chain = this.getChain();
|
||||
|
||||
if (chain.length === 0)
|
||||
return;
|
||||
|
||||
root = x509.parse(chain[chain.length - 1]);
|
||||
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
return {
|
||||
name: x509.getCAName(root),
|
||||
trusted: x509.isTrusted(root),
|
||||
cert: root
|
||||
};
|
||||
};
|
||||
|
||||
function PaymentDetails(options) {
|
||||
if (!(this instanceof PaymentDetails))
|
||||
return new PaymentDetails(options);
|
||||
|
||||
this.network = null;
|
||||
this.outputs = [];
|
||||
this.time = utils.now();
|
||||
this.expires = -1;
|
||||
this.memo = null;
|
||||
this.paymentUrl = null;
|
||||
this.merchantData = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
PaymentDetails.prototype.fromOptions = function fromOptions(options) {
|
||||
var i, output;
|
||||
|
||||
if (options.network != null) {
|
||||
assert(typeof options.network === 'string');
|
||||
this.network = options.network;
|
||||
}
|
||||
|
||||
if (options.outputs) {
|
||||
assert(Array.isArray(options.outputs));
|
||||
for (i = 0; i < options.outputs.length; i++) {
|
||||
output = new bcoin.output(options.outputs[i]);
|
||||
this.outputs.push(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.time != null) {
|
||||
assert(utils.isNumber(options.time));
|
||||
this.time = options.time;
|
||||
}
|
||||
|
||||
if (options.expires != null) {
|
||||
assert(utils.isNumber(options.expires));
|
||||
this.expires = options.expires;
|
||||
}
|
||||
|
||||
if (options.memo != null) {
|
||||
assert(typeof options.memo === 'string');
|
||||
this.memo = options.memo;
|
||||
}
|
||||
|
||||
if (options.paymentUrl != null) {
|
||||
assert(typeof options.paymentUrl === 'string');
|
||||
this.paymentUrl = options.paymentUrl;
|
||||
}
|
||||
|
||||
if (options.merchantData)
|
||||
this.setData(options.merchantData);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentDetails.fromOptions = function fromOptions(options) {
|
||||
return new PaymentDetails().fromOptions(options);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.isExpired = function isExpired() {
|
||||
if (this.expires === -1)
|
||||
return false;
|
||||
return utils.now() > this.expires;
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.setData = function setData(data, enc) {
|
||||
if (data == null || Buffer.isBuffer(data)) {
|
||||
this.merchantData = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof data !== 'string') {
|
||||
assert(!enc || enc === 'json');
|
||||
this.merchantData = new Buffer(JSON.stringify(data), 'utf8');
|
||||
return;
|
||||
}
|
||||
|
||||
this.merchantData = new Buffer(data, enc);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.getData = function getData(enc) {
|
||||
var data = this.merchantData;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (!enc)
|
||||
return data;
|
||||
|
||||
if (enc === 'json') {
|
||||
data = data.toString('utf8');
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
return data.toString(enc);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
var op, output;
|
||||
|
||||
this.network = p.readFieldString(1, true);
|
||||
|
||||
while (p.nextTag() === 2) {
|
||||
op = new ProtoReader(p.readFieldBytes(2));
|
||||
output = new bcoin.output();
|
||||
output.value = op.readFieldU64(1, true);
|
||||
output.script.fromRaw(op.readFieldBytes(2, true));
|
||||
this.outputs.push(output);
|
||||
}
|
||||
|
||||
this.time = p.readFieldU64(3);
|
||||
this.expires = p.readFieldU64(4, true);
|
||||
this.memo = p.readFieldString(5, true);
|
||||
this.paymentUrl = p.readFieldString(6, true);
|
||||
this.merchantData = p.readFieldBytes(7, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentDetails.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new PaymentDetails().fromRaw(data);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
var i, op, output;
|
||||
|
||||
if (this.network != null)
|
||||
p.writeFieldString(1, this.network);
|
||||
|
||||
for (i = 0; i < this.outputs.length; i++) {
|
||||
output = this.outputs[i];
|
||||
op = new ProtoWriter();
|
||||
op.writeFieldU64(1, output.value);
|
||||
op.writeFieldBytes(2, output.script.toRaw());
|
||||
p.writeFieldBytes(2, op.render());
|
||||
}
|
||||
|
||||
p.writeFieldU64(3, this.time);
|
||||
|
||||
if (this.expires !== -1)
|
||||
p.writeFieldU64(4, this.expires);
|
||||
|
||||
if (this.memo != null)
|
||||
p.writeFieldString(5, this.memo);
|
||||
|
||||
if (this.paymentUrl != null)
|
||||
p.writeFieldString(6, this.paymentUrl);
|
||||
|
||||
if (this.merchantData)
|
||||
p.writeFieldString(7, this.merchantData);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
function Payment(options) {
|
||||
if (!(this instanceof Payment))
|
||||
return new Payment(options);
|
||||
|
||||
this.merchantData = null;
|
||||
this.transactions = [];
|
||||
this.refundTo = [];
|
||||
this.memo = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
Payment.prototype.fromOptions = function fromOptions(options) {
|
||||
var i, tx, output;
|
||||
|
||||
if (options.merchantData)
|
||||
this.setData(options.merchantData);
|
||||
|
||||
if (options.transactions) {
|
||||
assert(Array.isArray(options.transactions));
|
||||
for (i = 0; i < options.transactions.length; i++) {
|
||||
tx = new bcoin.tx(options.transactions[i]);
|
||||
this.transactions.push(tx);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.refundTo) {
|
||||
assert(Array.isArray(options.refundTo));
|
||||
for (i = 0; i < options.refundTo.length; i++) {
|
||||
output = new bcoin.output(options.refundTo[i]);
|
||||
this.refundTo.push(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.memo != null) {
|
||||
assert(typeof options.memo === 'string');
|
||||
this.memo = options.memo;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Payment.fromOptions = function fromOptions(options) {
|
||||
return new Payment().fromOptions(options);
|
||||
};
|
||||
|
||||
Payment.prototype.setData = PaymentDetails.prototype.setData;
|
||||
Payment.prototype.getData = PaymentDetails.prototype.getData;
|
||||
|
||||
Payment.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
var tx, op, output;
|
||||
|
||||
this.merchantData = p.readFieldBytes(1, true);
|
||||
|
||||
while (p.nextTag() === 2) {
|
||||
tx = bcoin.tx.fromRaw(p.readFieldBytes(2));
|
||||
this.transactions.push(tx);
|
||||
}
|
||||
|
||||
while (p.nextTag() === 3) {
|
||||
op = new ProtoReader(p.readFieldBytes(3));
|
||||
output = new bcoin.output();
|
||||
output.value = op.readFieldU64(1, true);
|
||||
output.script = bcoin.script.fromRaw(op.readFieldBytes(2, true));
|
||||
this.refundTo.push(output);
|
||||
}
|
||||
|
||||
this.memo = p.readFieldString(4, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Payment.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new Payment().fromRaw(data);
|
||||
};
|
||||
|
||||
Payment.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
var i, tx, op, output;
|
||||
|
||||
if (this.merchantData)
|
||||
p.writeFieldBytes(1, this.merchantData);
|
||||
|
||||
for (i = 0; i < this.transactions.length; i++) {
|
||||
tx = this.transactions[i];
|
||||
this.writeFieldBytes(2, tx.toRaw());
|
||||
}
|
||||
|
||||
for (i = 0; i < this.refundTo.length; i++) {
|
||||
op = new ProtoWriter();
|
||||
output = this.refundTo[i];
|
||||
op.writeFieldU64(1, output.value);
|
||||
op.writeFieldBytes(2, output.script.toRaw());
|
||||
p.writeFieldBytes(3, op.render());
|
||||
}
|
||||
|
||||
if (this.memo != null)
|
||||
p.writeFieldString(4, this.memo);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
function PaymentACK(options) {
|
||||
if (!(this instanceof PaymentACK))
|
||||
return new PaymentACK(options);
|
||||
|
||||
this.payment = new Payment();
|
||||
this.memo = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
PaymentACK.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.payment)
|
||||
this.payment.fromOptions(options.payment);
|
||||
|
||||
if (options.memo != null) {
|
||||
assert(typeof options.memo === 'string');
|
||||
this.memo = options.memo;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentACK.fromOptions = function fromOptions(options) {
|
||||
return new PaymentACK().fromOptions(options);
|
||||
};
|
||||
|
||||
PaymentACK.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
|
||||
this.payment.fromRaw(p.readFieldBytes(1));
|
||||
this.memo = p.readFieldString(2, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentACK.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new PaymentACK().fromRaw(data);
|
||||
};
|
||||
|
||||
PaymentACK.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
|
||||
p.writeFieldBytes(1, this.payment.toRaw());
|
||||
|
||||
if (this.memo != null)
|
||||
p.writeFieldString(2, this.memo);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
exports.PaymentRequest = PaymentRequest;
|
||||
exports.PaymentDetails = PaymentDetails;
|
||||
exports.Payment = Payment;
|
||||
exports.PaymentACK = PaymentACK;
|
||||
15
lib/bip70/index.js
Normal file
15
lib/bip70/index.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*!
|
||||
* bip70.js - bip70 for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.PaymentRequest = require('./paymentrequest');
|
||||
exports.PaymentDetails = require('./paymentdetails');
|
||||
exports.Payment = require('./payment');
|
||||
exports.PaymentACK = require('./paymentack');
|
||||
exports.asn1 = require('./asn1');
|
||||
exports.x509 = require('./x509');
|
||||
exports.pk = require('./pk');
|
||||
127
lib/bip70/payment.js
Normal file
127
lib/bip70/payment.js
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*!
|
||||
* payment.js - bip70 payment for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var Output = require('../primitives/output');
|
||||
var TX = require('../primitives/tx');
|
||||
var Script = require('../script/script');
|
||||
var protobuf = require('./protobuf');
|
||||
var PaymentDetails = require('./paymentdetails');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
function Payment(options) {
|
||||
if (!(this instanceof Payment))
|
||||
return new Payment(options);
|
||||
|
||||
this.merchantData = null;
|
||||
this.transactions = [];
|
||||
this.refundTo = [];
|
||||
this.memo = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
Payment.prototype.fromOptions = function fromOptions(options) {
|
||||
var i, tx, output;
|
||||
|
||||
if (options.merchantData)
|
||||
this.setData(options.merchantData);
|
||||
|
||||
if (options.transactions) {
|
||||
assert(Array.isArray(options.transactions));
|
||||
for (i = 0; i < options.transactions.length; i++) {
|
||||
tx = new TX(options.transactions[i]);
|
||||
this.transactions.push(tx);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.refundTo) {
|
||||
assert(Array.isArray(options.refundTo));
|
||||
for (i = 0; i < options.refundTo.length; i++) {
|
||||
output = new Output(options.refundTo[i]);
|
||||
this.refundTo.push(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.memo != null) {
|
||||
assert(typeof options.memo === 'string');
|
||||
this.memo = options.memo;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Payment.fromOptions = function fromOptions(options) {
|
||||
return new Payment().fromOptions(options);
|
||||
};
|
||||
|
||||
Payment.prototype.setData = PaymentDetails.prototype.setData;
|
||||
Payment.prototype.getData = PaymentDetails.prototype.getData;
|
||||
|
||||
Payment.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
var tx, op, output;
|
||||
|
||||
this.merchantData = p.readFieldBytes(1, true);
|
||||
|
||||
while (p.nextTag() === 2) {
|
||||
tx = TX.fromRaw(p.readFieldBytes(2));
|
||||
this.transactions.push(tx);
|
||||
}
|
||||
|
||||
while (p.nextTag() === 3) {
|
||||
op = new ProtoReader(p.readFieldBytes(3));
|
||||
output = new Output();
|
||||
output.value = op.readFieldU64(1, true);
|
||||
output.script = Script.fromRaw(op.readFieldBytes(2, true));
|
||||
this.refundTo.push(output);
|
||||
}
|
||||
|
||||
this.memo = p.readFieldString(4, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Payment.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new Payment().fromRaw(data);
|
||||
};
|
||||
|
||||
Payment.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
var i, tx, op, output;
|
||||
|
||||
if (this.merchantData)
|
||||
p.writeFieldBytes(1, this.merchantData);
|
||||
|
||||
for (i = 0; i < this.transactions.length; i++) {
|
||||
tx = this.transactions[i];
|
||||
this.writeFieldBytes(2, tx.toRaw());
|
||||
}
|
||||
|
||||
for (i = 0; i < this.refundTo.length; i++) {
|
||||
op = new ProtoWriter();
|
||||
output = this.refundTo[i];
|
||||
op.writeFieldU64(1, output.value);
|
||||
op.writeFieldBytes(2, output.script.toRaw());
|
||||
p.writeFieldBytes(3, op.render());
|
||||
}
|
||||
|
||||
if (this.memo != null)
|
||||
p.writeFieldString(4, this.memo);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
module.exports = Payment;
|
||||
71
lib/bip70/paymentack.js
Normal file
71
lib/bip70/paymentack.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*!
|
||||
* paymentack.js - bip70 paymentack for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var protobuf = require('./protobuf');
|
||||
var Payment = require('./payment');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
function PaymentACK(options) {
|
||||
if (!(this instanceof PaymentACK))
|
||||
return new PaymentACK(options);
|
||||
|
||||
this.payment = new Payment();
|
||||
this.memo = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
PaymentACK.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.payment)
|
||||
this.payment.fromOptions(options.payment);
|
||||
|
||||
if (options.memo != null) {
|
||||
assert(typeof options.memo === 'string');
|
||||
this.memo = options.memo;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentACK.fromOptions = function fromOptions(options) {
|
||||
return new PaymentACK().fromOptions(options);
|
||||
};
|
||||
|
||||
PaymentACK.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
|
||||
this.payment.fromRaw(p.readFieldBytes(1));
|
||||
this.memo = p.readFieldString(2, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentACK.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new PaymentACK().fromRaw(data);
|
||||
};
|
||||
|
||||
PaymentACK.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
|
||||
p.writeFieldBytes(1, this.payment.toRaw());
|
||||
|
||||
if (this.memo != null)
|
||||
p.writeFieldString(2, this.memo);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
module.exports = PaymentACK;
|
||||
185
lib/bip70/paymentdetails.js
Normal file
185
lib/bip70/paymentdetails.js
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*!
|
||||
* paymentdetails.js - bip70 paymentdetails for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var Output = require('../primitives/output');
|
||||
var protobuf = require('./protobuf');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
function PaymentDetails(options) {
|
||||
if (!(this instanceof PaymentDetails))
|
||||
return new PaymentDetails(options);
|
||||
|
||||
this.network = null;
|
||||
this.outputs = [];
|
||||
this.time = utils.now();
|
||||
this.expires = -1;
|
||||
this.memo = null;
|
||||
this.paymentUrl = null;
|
||||
this.merchantData = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
PaymentDetails.prototype.fromOptions = function fromOptions(options) {
|
||||
var i, output;
|
||||
|
||||
if (options.network != null) {
|
||||
assert(typeof options.network === 'string');
|
||||
this.network = options.network;
|
||||
}
|
||||
|
||||
if (options.outputs) {
|
||||
assert(Array.isArray(options.outputs));
|
||||
for (i = 0; i < options.outputs.length; i++) {
|
||||
output = new Output(options.outputs[i]);
|
||||
this.outputs.push(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.time != null) {
|
||||
assert(utils.isNumber(options.time));
|
||||
this.time = options.time;
|
||||
}
|
||||
|
||||
if (options.expires != null) {
|
||||
assert(utils.isNumber(options.expires));
|
||||
this.expires = options.expires;
|
||||
}
|
||||
|
||||
if (options.memo != null) {
|
||||
assert(typeof options.memo === 'string');
|
||||
this.memo = options.memo;
|
||||
}
|
||||
|
||||
if (options.paymentUrl != null) {
|
||||
assert(typeof options.paymentUrl === 'string');
|
||||
this.paymentUrl = options.paymentUrl;
|
||||
}
|
||||
|
||||
if (options.merchantData)
|
||||
this.setData(options.merchantData);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentDetails.fromOptions = function fromOptions(options) {
|
||||
return new PaymentDetails().fromOptions(options);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.isExpired = function isExpired() {
|
||||
if (this.expires === -1)
|
||||
return false;
|
||||
return utils.now() > this.expires;
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.setData = function setData(data, enc) {
|
||||
if (data == null || Buffer.isBuffer(data)) {
|
||||
this.merchantData = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof data !== 'string') {
|
||||
assert(!enc || enc === 'json');
|
||||
this.merchantData = new Buffer(JSON.stringify(data), 'utf8');
|
||||
return;
|
||||
}
|
||||
|
||||
this.merchantData = new Buffer(data, enc);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.getData = function getData(enc) {
|
||||
var data = this.merchantData;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (!enc)
|
||||
return data;
|
||||
|
||||
if (enc === 'json') {
|
||||
data = data.toString('utf8');
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
return data.toString(enc);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
var op, output;
|
||||
|
||||
this.network = p.readFieldString(1, true);
|
||||
|
||||
while (p.nextTag() === 2) {
|
||||
op = new ProtoReader(p.readFieldBytes(2));
|
||||
output = new Output();
|
||||
output.value = op.readFieldU64(1, true);
|
||||
output.script.fromRaw(op.readFieldBytes(2, true));
|
||||
this.outputs.push(output);
|
||||
}
|
||||
|
||||
this.time = p.readFieldU64(3);
|
||||
this.expires = p.readFieldU64(4, true);
|
||||
this.memo = p.readFieldString(5, true);
|
||||
this.paymentUrl = p.readFieldString(6, true);
|
||||
this.merchantData = p.readFieldBytes(7, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentDetails.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new PaymentDetails().fromRaw(data);
|
||||
};
|
||||
|
||||
PaymentDetails.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
var i, op, output;
|
||||
|
||||
if (this.network != null)
|
||||
p.writeFieldString(1, this.network);
|
||||
|
||||
for (i = 0; i < this.outputs.length; i++) {
|
||||
output = this.outputs[i];
|
||||
op = new ProtoWriter();
|
||||
op.writeFieldU64(1, output.value);
|
||||
op.writeFieldBytes(2, output.script.toRaw());
|
||||
p.writeFieldBytes(2, op.render());
|
||||
}
|
||||
|
||||
p.writeFieldU64(3, this.time);
|
||||
|
||||
if (this.expires !== -1)
|
||||
p.writeFieldU64(4, this.expires);
|
||||
|
||||
if (this.memo != null)
|
||||
p.writeFieldString(5, this.memo);
|
||||
|
||||
if (this.paymentUrl != null)
|
||||
p.writeFieldString(6, this.paymentUrl);
|
||||
|
||||
if (this.merchantData)
|
||||
p.writeFieldString(7, this.merchantData);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
module.exports = PaymentDetails;
|
||||
252
lib/bip70/paymentrequest.js
Normal file
252
lib/bip70/paymentrequest.js
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/*!
|
||||
* paymentrequest.js - bip70 paymentrequest for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var x509 = require('./x509');
|
||||
var asn1 = require('./asn1');
|
||||
var protobuf = require('./protobuf');
|
||||
var PaymentDetails = require('./paymentdetails');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
function PaymentRequest(options) {
|
||||
if (!(this instanceof PaymentRequest))
|
||||
return new PaymentRequest(options);
|
||||
|
||||
this.version = -1;
|
||||
this.pkiType = null;
|
||||
this.pkiData = null;
|
||||
this.paymentDetails = new PaymentDetails();
|
||||
this.signature = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
PaymentRequest.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.version != null) {
|
||||
assert(utils.isNumber(options.version));
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
if (options.pkiType != null) {
|
||||
assert(typeof options.pkiType === 'string');
|
||||
this.pkiType = options.pkiType;
|
||||
}
|
||||
|
||||
if (options.pkiData) {
|
||||
assert(Buffer.isBuffer(options.pkiData));
|
||||
this.pkiData = options.pkiData;
|
||||
}
|
||||
|
||||
if (options.paymentDetails)
|
||||
this.paymentDetails.fromOptions(options.paymentDetails);
|
||||
|
||||
if (options.signature) {
|
||||
assert(Buffer.isBuffer(options.signature));
|
||||
this.signature = options.signature;
|
||||
}
|
||||
|
||||
if (options.chain)
|
||||
this.setChain(options.chain);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentRequest.fromOptions = function fromOptions(options) {
|
||||
return new PaymentRequest().fromOptions(options);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new ProtoReader(data);
|
||||
|
||||
this.version = p.readFieldU32(1, true);
|
||||
this.pkiType = p.readFieldString(2, true);
|
||||
this.pkiData = p.readFieldBytes(3, true);
|
||||
this.paymentDetails.fromRaw(p.readFieldBytes(4));
|
||||
this.signature = p.readFieldBytes(5, true);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PaymentRequest.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new PaymentRequest().fromRaw(data);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new ProtoWriter(writer);
|
||||
|
||||
if (this.version !== -1)
|
||||
p.writeFieldU32(1, this.version);
|
||||
|
||||
if (this.pkiType != null)
|
||||
p.writeFieldString(2, this.pkiType);
|
||||
|
||||
if (this.pkiData)
|
||||
p.writeFieldBytes(3, this.pkiData);
|
||||
|
||||
p.writeFieldBytes(4, this.paymentDetails.toRaw());
|
||||
|
||||
if (this.signature)
|
||||
p.writeFieldBytes(5, this.signature);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.getAlgorithm = function getAlgorithm() {
|
||||
var parts;
|
||||
|
||||
if (!this.pkiType)
|
||||
return;
|
||||
|
||||
parts = this.pkiType.split('+');
|
||||
|
||||
if (parts.length !== 2)
|
||||
return;
|
||||
|
||||
if (parts[0] !== 'x509')
|
||||
return;
|
||||
|
||||
if (parts[1] !== 'sha1' && parts[1] !== 'sha256')
|
||||
return;
|
||||
|
||||
return { key: parts[0], hash: parts[1] };
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.signatureData = function signatureData() {
|
||||
var signature = this.signature;
|
||||
var data;
|
||||
|
||||
this.signature = new Buffer(0);
|
||||
|
||||
data = this.toRaw();
|
||||
|
||||
this.signature = signature;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.signatureHash = function signatureHash() {
|
||||
var alg = this.getAlgorithm();
|
||||
assert(alg, 'No hash algorithm available.');
|
||||
return crypto.hash(alg.hash, this.signatureData());
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.setChain = function setChain(chain) {
|
||||
var p = new ProtoWriter();
|
||||
var i, cert, pem;
|
||||
|
||||
if (!Array.isArray(chain))
|
||||
chain = [chain];
|
||||
|
||||
for (i = 0; i < chain.length; i++) {
|
||||
cert = chain[i];
|
||||
if (typeof cert === 'string') {
|
||||
pem = asn1.fromPEM(cert);
|
||||
assert(pem.type === 'certificate', 'Bad certificate PEM.');
|
||||
cert = pem.data;
|
||||
}
|
||||
assert(Buffer.isBuffer(cert), 'Certificates must be PEM or DER.');
|
||||
p.writeFieldBytes(1, cert);
|
||||
}
|
||||
|
||||
this.pkiData = p.render();
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.getChain = function getChain() {
|
||||
var chain = [];
|
||||
var p;
|
||||
|
||||
if (!this.pkiData)
|
||||
return chain;
|
||||
|
||||
p = new ProtoReader(this.pkiData);
|
||||
|
||||
while (p.nextTag() === 1)
|
||||
chain.push(p.readFieldBytes(1));
|
||||
|
||||
return chain;
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.sign = function sign(key, chain) {
|
||||
var alg, msg;
|
||||
|
||||
if (chain)
|
||||
this.setChain(chain);
|
||||
|
||||
if (!this.pkiType)
|
||||
this.pkiType = 'x509+sha256';
|
||||
|
||||
alg = this.getAlgorithm();
|
||||
assert(alg, 'No hash algorithm available.');
|
||||
|
||||
msg = this.signatureData();
|
||||
chain = this.getChain();
|
||||
|
||||
this.signature = x509.signSubject(alg.hash, msg, key, chain);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.verify = function verify() {
|
||||
var alg, msg, sig, chain;
|
||||
|
||||
if (!this.pkiType || this.pkiType === 'none')
|
||||
return true;
|
||||
|
||||
if (!this.signature)
|
||||
return false;
|
||||
|
||||
alg = this.getAlgorithm();
|
||||
|
||||
if (!alg)
|
||||
return false;
|
||||
|
||||
msg = this.signatureData();
|
||||
sig = this.signature;
|
||||
chain = this.getChain();
|
||||
|
||||
return x509.verifySubject(alg.hash, msg, sig, chain);
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.verifyChain = function verifyChain() {
|
||||
if (!this.pkiType || this.pkiType === 'none')
|
||||
return true;
|
||||
|
||||
return x509.verifyChain(this.getChain());
|
||||
};
|
||||
|
||||
PaymentRequest.prototype.getCA = function getCA() {
|
||||
var chain, root;
|
||||
|
||||
if (!this.pkiType || this.pkiType === 'none')
|
||||
return;
|
||||
|
||||
chain = this.getChain();
|
||||
|
||||
if (chain.length === 0)
|
||||
return;
|
||||
|
||||
root = x509.parse(chain[chain.length - 1]);
|
||||
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
return {
|
||||
name: x509.getCAName(root),
|
||||
trusted: x509.isTrusted(root),
|
||||
cert: root
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = PaymentRequest;
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
|
||||
|
|
|
|||
2148
lib/chain/chain.js
2148
lib/chain/chain.js
File diff suppressed because it is too large
Load diff
1417
lib/chain/chaindb.js
1417
lib/chain/chaindb.js
File diff suppressed because it is too large
Load diff
|
|
@ -7,14 +7,17 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var bn = require('bn.js');
|
||||
var constants = bcoin.constants;
|
||||
var Network = require('../protocol/network');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var Headers = require('../primitives/headers');
|
||||
var InvItem = require('../primitives/invitem');
|
||||
var co = require('../utils/co');
|
||||
|
||||
/**
|
||||
* Represents an entry in the chain. Unlike
|
||||
|
|
@ -46,7 +49,7 @@ function ChainEntry(chain, options, prev) {
|
|||
return new ChainEntry(chain, options, prev);
|
||||
|
||||
this.chain = chain;
|
||||
this.network = chain ? chain.network : bcoin.network.get();
|
||||
this.network = chain ? chain.network : Network.primary;
|
||||
|
||||
this.hash = constants.NULL_HASH;
|
||||
this.version = 1;
|
||||
|
|
@ -156,10 +159,10 @@ ChainEntry.prototype.isGenesis = function isGenesis() {
|
|||
* majority window. These ancestors will be stored
|
||||
* in the `ancestors` array and enable use of synchronous
|
||||
* ChainEntry methods.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getRetargetAncestors = function getRetargetAncestors(callback) {
|
||||
ChainEntry.prototype.getRetargetAncestors = function getRetargetAncestors() {
|
||||
var majorityWindow = this.network.block.majorityWindow;
|
||||
var medianTimespan = constants.block.MEDIAN_TIMESPAN;
|
||||
var powDiffInterval = this.network.pow.retargetInterval;
|
||||
|
|
@ -167,22 +170,22 @@ ChainEntry.prototype.getRetargetAncestors = function getRetargetAncestors(callba
|
|||
var max = Math.max(majorityWindow, medianTimespan);
|
||||
if ((this.height + 1) % powDiffInterval === 0 || diffReset)
|
||||
max = Math.max(max, powDiffInterval);
|
||||
this.getAncestors(max, callback);
|
||||
return this.getAncestors(max);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect ancestors.
|
||||
* @param {Number} max - Number of ancestors.
|
||||
* @param {Function} callback - Returns [Error, ChainEntry[]].
|
||||
* @returns {Promise} - Returns ChainEntry[].
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getAncestors = function getAncestors(max, callback) {
|
||||
ChainEntry.prototype.getAncestors = co(function* getAncestors(max) {
|
||||
var entry = this;
|
||||
var ancestors = [];
|
||||
var cached;
|
||||
|
||||
if (max === 0)
|
||||
return callback(null, ancestors);
|
||||
return ancestors;
|
||||
|
||||
assert(utils.isNumber(max));
|
||||
|
||||
|
|
@ -192,7 +195,7 @@ ChainEntry.prototype.getAncestors = function getAncestors(max, callback) {
|
|||
ancestors.push(entry);
|
||||
|
||||
if (ancestors.length >= max)
|
||||
return callback(null, ancestors);
|
||||
return ancestors;
|
||||
|
||||
cached = this.chain.db.getCache(entry.prevBlock);
|
||||
|
||||
|
|
@ -204,66 +207,54 @@ ChainEntry.prototype.getAncestors = function getAncestors(max, callback) {
|
|||
entry = cached;
|
||||
}
|
||||
|
||||
(function next(err, entry) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!entry)
|
||||
return callback(null, ancestors);
|
||||
|
||||
while (entry) {
|
||||
ancestors.push(entry);
|
||||
|
||||
if (ancestors.length >= max)
|
||||
return callback(null, ancestors);
|
||||
break;
|
||||
entry = yield entry.getPrevious();
|
||||
}
|
||||
|
||||
entry.getPrevious(next);
|
||||
})(null, entry);
|
||||
};
|
||||
return ancestors;
|
||||
});
|
||||
|
||||
/**
|
||||
* Test whether the entry is in the main chain.
|
||||
* @param {Function} callback - Return [Error, Boolean].
|
||||
* @returns {Promise} - Return Boolean.
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.isMainChain = function isMainChain(callback) {
|
||||
this.chain.db.isMainChain(this, callback);
|
||||
ChainEntry.prototype.isMainChain = function isMainChain() {
|
||||
return this.chain.db.isMainChain(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect ancestors up to `height`.
|
||||
* @param {Number} height
|
||||
* @param {Function} callback - Returns [Error, ChainEntry[]].
|
||||
* @returns {Promise} - Returns ChainEntry[].
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getAncestorByHeight = function getAncestorByHeight(height, callback) {
|
||||
var self = this;
|
||||
ChainEntry.prototype.getAncestorByHeight = co(function* getAncestorByHeight(height) {
|
||||
var main, entry;
|
||||
|
||||
if (height < 0)
|
||||
return utils.nextTick(callback);
|
||||
return yield co.wait();
|
||||
|
||||
assert(height >= 0);
|
||||
assert(height <= this.height);
|
||||
|
||||
this.isMainChain(function(err, main) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
main = yield this.isMainChain();
|
||||
|
||||
if (main)
|
||||
return self.chain.db.get(height, callback);
|
||||
if (main)
|
||||
return yield this.chain.db.get(height);
|
||||
|
||||
self.getAncestor(self.height - height, function(err, entry) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
entry = yield this.getAncestor(this.height - height);
|
||||
|
||||
if (!entry)
|
||||
return callback();
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
assert(entry.height === height);
|
||||
assert(entry.height === height);
|
||||
|
||||
callback(null, entry);
|
||||
});
|
||||
});
|
||||
};
|
||||
return entry;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get a single ancestor by index. Note that index-0 is
|
||||
|
|
@ -273,45 +264,39 @@ ChainEntry.prototype.getAncestorByHeight = function getAncestorByHeight(height,
|
|||
* @returns {Function} callback - Returns [Error, ChainEntry].
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getAncestor = function getAncestor(index, callback) {
|
||||
ChainEntry.prototype.getAncestor = co(function* getAncestor(index) {
|
||||
var ancestors;
|
||||
|
||||
assert(index >= 0);
|
||||
this.getAncestors(index + 1, function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (ancestors.length < index + 1)
|
||||
return callback();
|
||||
ancestors = yield this.getAncestors(index + 1);
|
||||
|
||||
callback(null, ancestors[index]);
|
||||
});
|
||||
};
|
||||
if (ancestors.length < index + 1)
|
||||
return;
|
||||
|
||||
return ancestors[index];
|
||||
});
|
||||
|
||||
/**
|
||||
* Get previous entry.
|
||||
* @param {Function} callback - Returns [Error, ChainEntry].
|
||||
* @returns {Promise} - Returns ChainEntry.
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getPrevious = function getPrevious(callback) {
|
||||
this.chain.db.get(this.prevBlock, callback);
|
||||
ChainEntry.prototype.getPrevious = function getPrevious() {
|
||||
return this.chain.db.get(this.prevBlock);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get next entry.
|
||||
* @param {Function} callback - Returns [Error, ChainEntry].
|
||||
* @returns {Promise} - Returns ChainEntry.
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getNext = function getNext(callback) {
|
||||
var self = this;
|
||||
this.chain.db.getNextHash(this.hash, function(err, hash) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!hash)
|
||||
return callback();
|
||||
|
||||
self.chain.db.get(hash, callback);
|
||||
});
|
||||
};
|
||||
ChainEntry.prototype.getNext = co(function* getNext() {
|
||||
var hash = yield this.chain.db.getNextHash(this.hash);
|
||||
if (!hash)
|
||||
return;
|
||||
return yield this.chain.db.get(hash);
|
||||
});
|
||||
|
||||
/**
|
||||
* Get median time past.
|
||||
|
|
@ -336,20 +321,14 @@ ChainEntry.prototype.getMedianTime = function getMedianTime(ancestors) {
|
|||
|
||||
/**
|
||||
* Get median time past asynchronously (see {@link ChainEntry#getMedianTime}).
|
||||
* @param {Function} callback - Returns [Error, Number].
|
||||
* @returns {Promise} - Returns Number.
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback) {
|
||||
var self = this;
|
||||
ChainEntry.prototype.getMedianTimeAsync = co(function* getMedianTimeAsync() {
|
||||
var MEDIAN_TIMESPAN = constants.block.MEDIAN_TIMESPAN;
|
||||
|
||||
this.getAncestors(MEDIAN_TIMESPAN, function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback(null, self.getMedianTime(ancestors));
|
||||
});
|
||||
};
|
||||
var ancestors = yield this.getAncestors(MEDIAN_TIMESPAN);
|
||||
return this.getMedianTime(ancestors);
|
||||
});
|
||||
|
||||
/**
|
||||
* Check isSuperMajority against majorityRejectOutdated.
|
||||
|
|
@ -367,14 +346,13 @@ ChainEntry.prototype.isOutdated = function isOutdated(version, ancestors) {
|
|||
/**
|
||||
* Check {@link ChainEntry#isUpgraded asynchronously}.
|
||||
* @param {Number} version
|
||||
* @param {Function} callback - Returns [Error, Boolean].
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.isOutdatedAsync = function isOutdatedAsync(version, callback) {
|
||||
this.isSuperMajorityAsync(version,
|
||||
this.network.block.majorityRejectOutdated,
|
||||
callback);
|
||||
ChainEntry.prototype.isOutdatedAsync = function isOutdatedAsync(version) {
|
||||
return this.isSuperMajorityAsync(version,
|
||||
this.network.block.majorityRejectOutdated);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -393,14 +371,13 @@ ChainEntry.prototype.isUpgraded = function isUpgraded(version, ancestors) {
|
|||
/**
|
||||
* Check {@link ChainEntry#isUpgraded} asynchronously.
|
||||
* @param {Number} version
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.isUpgradedAsync = function isUpgradedAsync(version, callback) {
|
||||
this.isSuperMajorityAsync(version,
|
||||
this.network.block.majorityEnforceUpgrade,
|
||||
callback);
|
||||
ChainEntry.prototype.isUpgradedAsync = function isUpgradedAsync(version) {
|
||||
return this.isSuperMajorityAsync(version,
|
||||
this.network.block.majorityEnforceUpgrade);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -430,24 +407,19 @@ ChainEntry.prototype.isSuperMajority = function isSuperMajority(version, require
|
|||
* Calculate {@link ChainEntry#isSuperMajority asynchronously}.
|
||||
* @param {Number} version
|
||||
* @param {Number} required
|
||||
* @param {Function} callback - Returns [Error, Boolean].
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.isSuperMajorityAsync = function isSuperMajorityAsync(version, required, callback) {
|
||||
var self = this;
|
||||
ChainEntry.prototype.isSuperMajorityAsync = co(function* isSuperMajorityAsync(version, required) {
|
||||
var majorityWindow = this.network.block.majorityWindow;
|
||||
|
||||
this.getAncestors(majorityWindow, function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback(null, self.isSuperMajority(version, required, ancestors));
|
||||
});
|
||||
};
|
||||
var ancestors = yield this.getAncestors(majorityWindow);
|
||||
return this.isSuperMajority(version, required, ancestors);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test whether the entry is potentially an ancestor of a checkpoint.
|
||||
* Test whether the entry is potentially
|
||||
* an ancestor of a checkpoint.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
|
|
@ -459,6 +431,19 @@ ChainEntry.prototype.isHistorical = function isHistorical() {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the entry contains a version bit.
|
||||
* @param {Object} deployment
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.hasBit = function hasBit(deployment) {
|
||||
var bits = this.version & constants.versionbits.TOP_MASK;
|
||||
var topBits = constants.versionbits.TOP_BITS;
|
||||
var mask = 1 << deployment.bit;
|
||||
return bits === topBits && (this.version & mask) !== 0;
|
||||
};
|
||||
|
||||
ChainEntry.prototype.__defineGetter__('rhash', function() {
|
||||
return utils.revHex(this.hash);
|
||||
});
|
||||
|
|
@ -506,7 +491,7 @@ ChainEntry.fromBlock = function fromBlock(chain, block, prev) {
|
|||
ChainEntry.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
p.writeHash(this.prevBlock);
|
||||
p.writeHash(this.merkleRoot);
|
||||
p.writeU32(this.ts);
|
||||
|
|
@ -624,7 +609,7 @@ ChainEntry.fromJSON = function fromJSON(chain, json) {
|
|||
*/
|
||||
|
||||
ChainEntry.prototype.toHeaders = function toHeaders() {
|
||||
return bcoin.headers.fromEntry(this);
|
||||
return Headers.fromEntry(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -633,7 +618,7 @@ ChainEntry.prototype.toHeaders = function toHeaders() {
|
|||
*/
|
||||
|
||||
ChainEntry.prototype.toInv = function toInv() {
|
||||
return new bcoin.invitem(constants.inv.BLOCK, this.hash);
|
||||
return new InvItem(constants.inv.BLOCK, this.hash);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
/*!
|
||||
* coins.js - coins object for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var Coin = require('../primitives/coin');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var compressor = require('./compress');
|
||||
var compress = compressor.compress;
|
||||
var decompress = compressor.decompress;
|
||||
|
||||
/**
|
||||
* Represents the outputs for a single transaction.
|
||||
|
|
@ -280,7 +282,7 @@ Coins.prototype.toRaw = function toRaw(writer) {
|
|||
continue;
|
||||
}
|
||||
|
||||
compressScript(output.script, p);
|
||||
compress.script(output.script, p);
|
||||
p.writeVarint(output.value);
|
||||
}
|
||||
|
||||
|
|
@ -449,7 +451,7 @@ Coins.prototype.fromTX = function fromTX(tx) {
|
|||
this.outputs.push(null);
|
||||
continue;
|
||||
}
|
||||
this.outputs.push(bcoin.coin.fromTX(tx, i));
|
||||
this.outputs.push(Coin.fromTX(tx, i));
|
||||
}
|
||||
|
||||
return this;
|
||||
|
|
@ -502,7 +504,7 @@ function CompressedCoin(offset, size, raw) {
|
|||
|
||||
CompressedCoin.prototype.toCoin = function toCoin(coins, index) {
|
||||
var p = new BufferReader(this.raw);
|
||||
var coin = new bcoin.coin();
|
||||
var coin = new Coin();
|
||||
|
||||
// Load in all necessary properties
|
||||
// from the parent Coins object.
|
||||
|
|
@ -515,7 +517,7 @@ CompressedCoin.prototype.toCoin = function toCoin(coins, index) {
|
|||
// Seek to the coin's offset.
|
||||
p.seek(this.offset);
|
||||
|
||||
decompressScript(p, coin.script);
|
||||
decompress.script(p, coin.script);
|
||||
|
||||
coin.value = p.readVarint();
|
||||
|
||||
|
|
@ -532,236 +534,8 @@ CompressedCoin.prototype.toRaw = function toRaw() {
|
|||
return this.raw.slice(this.offset, this.offset + this.size);
|
||||
};
|
||||
|
||||
/*
|
||||
* Compression
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compress a script, write directly to the buffer.
|
||||
* @param {Script} script
|
||||
* @param {BufferWriter} p
|
||||
*/
|
||||
|
||||
function compressScript(script, p) {
|
||||
var prefix = 0;
|
||||
var data;
|
||||
|
||||
// Attempt to compress the output scripts.
|
||||
// We can _only_ ever compress them if
|
||||
// they are serialized as minimaldata, as
|
||||
// we need to recreate them when we read
|
||||
// them.
|
||||
if (script.isPubkeyhash(true)) {
|
||||
prefix = 1;
|
||||
data = script.code[2].data;
|
||||
} else if (script.isScripthash()) {
|
||||
prefix = 2;
|
||||
data = script.code[1].data;
|
||||
} else if (script.isPubkey(true)) {
|
||||
prefix = 3;
|
||||
data = script.code[0].data;
|
||||
|
||||
// Try to compress the key.
|
||||
data = compressKey(data);
|
||||
|
||||
// If we can't compress it,
|
||||
// just store the script.
|
||||
if (!data)
|
||||
prefix = 0;
|
||||
}
|
||||
|
||||
p.writeU8(prefix);
|
||||
|
||||
if (prefix === 0)
|
||||
p.writeVarBytes(script.toRaw());
|
||||
else
|
||||
p.writeBytes(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress a script from buffer reader.
|
||||
* @param {BufferReader} p
|
||||
* @param {Script} script
|
||||
*/
|
||||
|
||||
function decompressScript(p, script) {
|
||||
var key;
|
||||
|
||||
// Decompress the script.
|
||||
switch (p.readU8()) {
|
||||
case 0:
|
||||
script.fromRaw(p.readVarBytes());
|
||||
break;
|
||||
case 1:
|
||||
script.fromPubkeyhash(p.readBytes(20));
|
||||
break;
|
||||
case 2:
|
||||
script.fromScripthash(p.readBytes(20));
|
||||
break;
|
||||
case 3:
|
||||
// Decompress the key. If this fails,
|
||||
// we have database corruption!
|
||||
key = decompressKey(p.readBytes(33));
|
||||
script.fromPubkey(key);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Bad prefix.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress value using an exponent. Takes advantage of
|
||||
* the fact that many bitcoin values are divisible by 10.
|
||||
* @see https://github.com/btcsuite/btcd/blob/master/blockchain/compress.go
|
||||
* @param {Amount} value
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
function compressValue(value) {
|
||||
var exp, last;
|
||||
|
||||
if (value === 0)
|
||||
return 0;
|
||||
|
||||
exp = 0;
|
||||
while (value % 10 === 0 && exp < 9) {
|
||||
value /= 10;
|
||||
exp++;
|
||||
}
|
||||
|
||||
if (exp < 9) {
|
||||
last = value % 10;
|
||||
value = (value - last) / 10;
|
||||
return 1 + 10 * (9 * value + last - 1) + exp;
|
||||
}
|
||||
|
||||
return 10 + 10 * (value - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress value.
|
||||
* @param {Number} value - Compressed value.
|
||||
* @returns {Amount} value
|
||||
*/
|
||||
|
||||
function decompressValue(value) {
|
||||
var exp, n, last;
|
||||
|
||||
if (value === 0)
|
||||
return 0;
|
||||
|
||||
value--;
|
||||
|
||||
exp = value % 10;
|
||||
value = (value - exp) / 10;
|
||||
|
||||
if (exp < 9) {
|
||||
last = value % 9;
|
||||
value = (value - last) / 9;
|
||||
n = value * 10 + last + 1;
|
||||
} else {
|
||||
n = value + 1;
|
||||
}
|
||||
|
||||
while (exp > 0) {
|
||||
n *= 10;
|
||||
exp--;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress a public key to coins compression format.
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function compressKey(key) {
|
||||
var out;
|
||||
|
||||
// We can't compress it if it's not valid.
|
||||
if (!bcoin.ec.publicKeyVerify(key))
|
||||
return;
|
||||
|
||||
switch (key[0]) {
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
// Key is already compressed.
|
||||
out = key;
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
// Compress the key normally.
|
||||
out = bcoin.ec.publicKeyConvert(key, true);
|
||||
// Store the original format (which
|
||||
// may be a hybrid byte) in the hi
|
||||
// 3 bits so we can restore it later.
|
||||
// The hi bits being set also lets us
|
||||
// know that this key was originally
|
||||
// decompressed.
|
||||
out[0] |= key[0] << 2;
|
||||
break;
|
||||
default:
|
||||
throw new Error('Bad point format.');
|
||||
}
|
||||
|
||||
assert(out.length === 33);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress a public key from the coins compression format.
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function decompressKey(key) {
|
||||
var format = key[0] >>> 2;
|
||||
var out;
|
||||
|
||||
assert(key.length === 33);
|
||||
|
||||
// Hi bits are not set. This key
|
||||
// is not meant to be decompressed.
|
||||
if (format === 0)
|
||||
return key;
|
||||
|
||||
// Decompress the key, and off the
|
||||
// low bits so publicKeyConvert
|
||||
// actually understands it.
|
||||
key[0] &= 0x03;
|
||||
out = bcoin.ec.publicKeyConvert(key, false);
|
||||
|
||||
// Reset the hi bits so as not to
|
||||
// mutate the original buffer.
|
||||
key[0] |= format << 2;
|
||||
|
||||
// Set the original format, which
|
||||
// may have been a hybrid prefix byte.
|
||||
out[0] = format;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports = Coins;
|
||||
|
||||
exports.compress = {
|
||||
script: compressScript,
|
||||
value: compressValue,
|
||||
key: compressKey
|
||||
};
|
||||
|
||||
exports.decompress = {
|
||||
script: decompressScript,
|
||||
value: decompressValue,
|
||||
key: decompressKey
|
||||
};
|
||||
|
||||
module.exports = exports;
|
||||
module.exports = Coins;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
/*!
|
||||
* coinview.js - coinview object for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var Coins = require('./coins');
|
||||
|
||||
/**
|
||||
* A collections of {@link Coins} objects.
|
||||
|
|
@ -43,7 +41,7 @@ CoinView.prototype.add = function add(coins) {
|
|||
CoinView.prototype.addCoin = function addCoin(coin) {
|
||||
assert(typeof coin.hash === 'string');
|
||||
if (!this.coins[coin.hash])
|
||||
this.coins[coin.hash] = new bcoin.coins();
|
||||
this.coins[coin.hash] = new Coins();
|
||||
this.coins[coin.hash].add(coin);
|
||||
};
|
||||
|
||||
|
|
@ -53,7 +51,7 @@ CoinView.prototype.addCoin = function addCoin(coin) {
|
|||
*/
|
||||
|
||||
CoinView.prototype.addTX = function addTX(tx) {
|
||||
this.add(bcoin.coins.fromTX(tx));
|
||||
this.add(Coins.fromTX(tx));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
240
lib/chain/compress.js
Normal file
240
lib/chain/compress.js
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*!
|
||||
* compress.js - coin compressor for bcoin
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var ec = require('../crypto/ec');
|
||||
|
||||
/*
|
||||
* Compression
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compress a script, write directly to the buffer.
|
||||
* @param {Script} script
|
||||
* @param {BufferWriter} p
|
||||
*/
|
||||
|
||||
function compressScript(script, p) {
|
||||
var prefix = 0;
|
||||
var data;
|
||||
|
||||
// Attempt to compress the output scripts.
|
||||
// We can _only_ ever compress them if
|
||||
// they are serialized as minimaldata, as
|
||||
// we need to recreate them when we read
|
||||
// them.
|
||||
if (script.isPubkeyhash(true)) {
|
||||
prefix = 1;
|
||||
data = script.code[2].data;
|
||||
} else if (script.isScripthash()) {
|
||||
prefix = 2;
|
||||
data = script.code[1].data;
|
||||
} else if (script.isPubkey(true)) {
|
||||
prefix = 3;
|
||||
data = script.code[0].data;
|
||||
|
||||
// Try to compress the key.
|
||||
data = compressKey(data);
|
||||
|
||||
// If we can't compress it,
|
||||
// just store the script.
|
||||
if (!data)
|
||||
prefix = 0;
|
||||
}
|
||||
|
||||
p.writeU8(prefix);
|
||||
|
||||
if (prefix === 0)
|
||||
p.writeVarBytes(script.toRaw());
|
||||
else
|
||||
p.writeBytes(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress a script from buffer reader.
|
||||
* @param {BufferReader} p
|
||||
* @param {Script} script
|
||||
*/
|
||||
|
||||
function decompressScript(p, script) {
|
||||
var key;
|
||||
|
||||
// Decompress the script.
|
||||
switch (p.readU8()) {
|
||||
case 0:
|
||||
script.fromRaw(p.readVarBytes());
|
||||
break;
|
||||
case 1:
|
||||
script.fromPubkeyhash(p.readBytes(20));
|
||||
break;
|
||||
case 2:
|
||||
script.fromScripthash(p.readBytes(20));
|
||||
break;
|
||||
case 3:
|
||||
// Decompress the key. If this fails,
|
||||
// we have database corruption!
|
||||
key = decompressKey(p.readBytes(33));
|
||||
script.fromPubkey(key);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Bad prefix.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress value using an exponent. Takes advantage of
|
||||
* the fact that many bitcoin values are divisible by 10.
|
||||
* @see https://github.com/btcsuite/btcd/blob/master/blockchain/compress.go
|
||||
* @param {Amount} value
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
function compressValue(value) {
|
||||
var exp, last;
|
||||
|
||||
if (value === 0)
|
||||
return 0;
|
||||
|
||||
exp = 0;
|
||||
while (value % 10 === 0 && exp < 9) {
|
||||
value /= 10;
|
||||
exp++;
|
||||
}
|
||||
|
||||
if (exp < 9) {
|
||||
last = value % 10;
|
||||
value = (value - last) / 10;
|
||||
return 1 + 10 * (9 * value + last - 1) + exp;
|
||||
}
|
||||
|
||||
return 10 + 10 * (value - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress value.
|
||||
* @param {Number} value - Compressed value.
|
||||
* @returns {Amount} value
|
||||
*/
|
||||
|
||||
function decompressValue(value) {
|
||||
var exp, n, last;
|
||||
|
||||
if (value === 0)
|
||||
return 0;
|
||||
|
||||
value--;
|
||||
|
||||
exp = value % 10;
|
||||
value = (value - exp) / 10;
|
||||
|
||||
if (exp < 9) {
|
||||
last = value % 9;
|
||||
value = (value - last) / 9;
|
||||
n = value * 10 + last + 1;
|
||||
} else {
|
||||
n = value + 1;
|
||||
}
|
||||
|
||||
while (exp > 0) {
|
||||
n *= 10;
|
||||
exp--;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress a public key to coins compression format.
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function compressKey(key) {
|
||||
var out;
|
||||
|
||||
// We can't compress it if it's not valid.
|
||||
if (!ec.publicKeyVerify(key))
|
||||
return;
|
||||
|
||||
switch (key[0]) {
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
// Key is already compressed.
|
||||
out = key;
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
// Compress the key normally.
|
||||
out = ec.publicKeyConvert(key, true);
|
||||
// Store the original format (which
|
||||
// may be a hybrid byte) in the hi
|
||||
// 3 bits so we can restore it later.
|
||||
// The hi bits being set also lets us
|
||||
// know that this key was originally
|
||||
// decompressed.
|
||||
out[0] |= key[0] << 2;
|
||||
break;
|
||||
default:
|
||||
throw new Error('Bad point format.');
|
||||
}
|
||||
|
||||
assert(out.length === 33);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress a public key from the coins compression format.
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function decompressKey(key) {
|
||||
var format = key[0] >>> 2;
|
||||
var out;
|
||||
|
||||
assert(key.length === 33);
|
||||
|
||||
// Hi bits are not set. This key
|
||||
// is not meant to be decompressed.
|
||||
if (format === 0)
|
||||
return key;
|
||||
|
||||
// Decompress the key, and off the
|
||||
// low bits so publicKeyConvert
|
||||
// actually understands it.
|
||||
key[0] &= 0x03;
|
||||
out = ec.publicKeyConvert(key, false);
|
||||
|
||||
// Reset the hi bits so as not to
|
||||
// mutate the original buffer.
|
||||
key[0] |= format << 2;
|
||||
|
||||
// Set the original format, which
|
||||
// may have been a hybrid prefix byte.
|
||||
out[0] = format;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports.compress = {
|
||||
script: compressScript,
|
||||
value: compressValue,
|
||||
key: compressKey
|
||||
};
|
||||
|
||||
exports.decompress = {
|
||||
script: decompressScript,
|
||||
value: decompressValue,
|
||||
key: decompressKey
|
||||
};
|
||||
8
lib/chain/index.js
Normal file
8
lib/chain/index.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
exports.Chain = require('./chain');
|
||||
exports.ChainDB = require('./chaindb');
|
||||
exports.ChainEntry = require('./chainentry');
|
||||
exports.Coins = require('./coins');
|
||||
exports.CoinView = require('./coinview');
|
||||
exports.compressor = require('./compress');
|
||||
|
|
@ -490,7 +490,7 @@ AESCipher.prototype.update = function update(data) {
|
|||
var i, len, trailing, block;
|
||||
|
||||
if (this.waiting) {
|
||||
data = Buffer.concat([this.waiting, data]);
|
||||
data = concat(this.waiting, data);
|
||||
this.waiting = null;
|
||||
}
|
||||
|
||||
|
|
@ -529,7 +529,7 @@ AESCipher.prototype.final = function final() {
|
|||
left = 16 - block.length;
|
||||
pad = new Buffer(left);
|
||||
pad.fill(left);
|
||||
block = Buffer.concat([block, pad]);
|
||||
block = concat(block, pad);
|
||||
}
|
||||
|
||||
// Encrypt the last block,
|
||||
|
|
@ -577,7 +577,7 @@ AESDecipher.prototype.update = function update(data) {
|
|||
var i, chunk, block, len, trailing;
|
||||
|
||||
if (this.waiting) {
|
||||
data = Buffer.concat([this.waiting, data]);
|
||||
data = concat(this.waiting, data);
|
||||
this.waiting = null;
|
||||
}
|
||||
|
||||
|
|
@ -656,10 +656,7 @@ AESDecipher.prototype.final = function final() {
|
|||
|
||||
AES.encrypt = function encrypt(data, key, iv, bits, mode) {
|
||||
var cipher = new AESCipher(key, iv, bits, mode);
|
||||
return Buffer.concat([
|
||||
cipher.update(data),
|
||||
cipher.final()
|
||||
]);
|
||||
return concat(cipher.update(data), cipher.final());
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -674,10 +671,7 @@ AES.encrypt = function encrypt(data, key, iv, bits, mode) {
|
|||
|
||||
AES.decrypt = function decrypt(data, key, iv, bits, mode) {
|
||||
var decipher = new AESDecipher(key, iv, bits, mode);
|
||||
return Buffer.concat([
|
||||
decipher.update(data),
|
||||
decipher.final()
|
||||
]);
|
||||
return concat(decipher.update(data), decipher.final());
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -771,6 +765,13 @@ function writeU32(data, value, i) {
|
|||
data[i + 3] = value & 0xff;
|
||||
}
|
||||
|
||||
function concat(a, b) {
|
||||
var data = new Buffer(a.length + b.length);
|
||||
a.copy(data, 0);
|
||||
b.copy(data, a.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tables
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -12,15 +12,17 @@ var random = require('./random');
|
|||
var scrypt = require('./scrypt');
|
||||
var scryptAsync = require('./scrypt-async');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var native = require('../utils/native');
|
||||
var nativeCrypto, hash, aes;
|
||||
var lazy = require('../utils/lazy')(require, exports);
|
||||
var nodeCrypto, hash, aes;
|
||||
|
||||
var isBrowser =
|
||||
(typeof process !== 'undefined' && process.browser)
|
||||
|| typeof window !== 'undefined';
|
||||
|
||||
if (!isBrowser) {
|
||||
nativeCrypto = require('crypto');
|
||||
nodeCrypto = require('crypto');
|
||||
} else {
|
||||
hash = require('hash.js');
|
||||
aes = require('./aes');
|
||||
|
|
@ -40,10 +42,10 @@ var crypto = exports;
|
|||
*/
|
||||
|
||||
crypto.hash = function _hash(alg, data) {
|
||||
if (!nativeCrypto)
|
||||
if (!nodeCrypto)
|
||||
return new Buffer(hash[alg]().update(data).digest());
|
||||
|
||||
return nativeCrypto.createHash(alg).update(data).digest();
|
||||
return nodeCrypto.createHash(alg).update(data).digest();
|
||||
};
|
||||
|
||||
if (native)
|
||||
|
|
@ -129,12 +131,12 @@ crypto.checksum = function checksum(data) {
|
|||
crypto.hmac = function hmac(alg, data, salt) {
|
||||
var hmac;
|
||||
|
||||
if (!nativeCrypto) {
|
||||
if (!nodeCrypto) {
|
||||
hmac = hash.hmac(hash[alg], salt);
|
||||
return new Buffer(hmac.update(data).digest());
|
||||
}
|
||||
|
||||
hmac = nativeCrypto.createHmac(alg, salt);
|
||||
hmac = nodeCrypto.createHmac(alg, salt);
|
||||
return hmac.update(data).digest();
|
||||
};
|
||||
|
||||
|
|
@ -158,8 +160,8 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
|
|||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
if (nativeCrypto && nativeCrypto.pbkdf2Sync)
|
||||
return nativeCrypto.pbkdf2Sync(key, salt, iter, len, alg);
|
||||
if (nodeCrypto && nodeCrypto.pbkdf2Sync)
|
||||
return nodeCrypto.pbkdf2Sync(key, salt, iter, len, alg);
|
||||
|
||||
return crypto._pbkdf2(key, salt, iter, len, alg);
|
||||
};
|
||||
|
|
@ -171,10 +173,10 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
|
|||
* @param {Number} iter
|
||||
* @param {Number} len
|
||||
* @param {String} alg
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg, callback) {
|
||||
crypto.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg) {
|
||||
var result;
|
||||
|
||||
if (typeof key === 'string')
|
||||
|
|
@ -183,16 +185,19 @@ crypto.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg, callback) {
|
|||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
if (nativeCrypto && nativeCrypto.pbkdf2)
|
||||
return nativeCrypto.pbkdf2(key, salt, iter, len, alg, callback);
|
||||
if (nodeCrypto && nodeCrypto.pbkdf2) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
nodeCrypto.pbkdf2(key, salt, iter, len, alg, co.wrap(resolve, reject));
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
result = crypto._pbkdf2(key, salt, iter, len, alg);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
|
||||
return callback(null, result);
|
||||
return Promise.resolve(result);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -224,27 +229,29 @@ crypto.scrypt = function _scrypt(passwd, salt, N, r, p, len) {
|
|||
* @param {Number} r
|
||||
* @param {Number} p
|
||||
* @param {Number} len
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.scryptAsync = function _scrypt(passwd, salt, N, r, p, len, callback) {
|
||||
crypto.scryptAsync = function _scrypt(passwd, salt, N, r, p, len) {
|
||||
if (typeof passwd === 'string')
|
||||
passwd = new Buffer(passwd, 'utf8');
|
||||
|
||||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
return scryptAsync(passwd, salt, N, r, p, len, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
scryptAsync(passwd, salt, N, r, p, len, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Derive a key using pbkdf2 with 50,000 iterations.
|
||||
* @param {Buffer|String} passphrase
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.derive = function derive(passphrase, callback) {
|
||||
crypto.pbkdf2Async(passphrase, 'bcoin', 50000, 32, 'sha256', callback);
|
||||
crypto.derive = function derive(passphrase) {
|
||||
return crypto.pbkdf2Async(passphrase, 'bcoin', 50000, 32, 'sha256');
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -252,30 +259,29 @@ crypto.derive = function derive(passphrase, callback) {
|
|||
* @param {Buffer} data
|
||||
* @param {Buffer|String} passphrase
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.encrypt = function encrypt(data, passphrase, iv, callback) {
|
||||
crypto.encrypt = co(function* encrypt(data, passphrase, iv) {
|
||||
var key;
|
||||
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(passphrase, 'No passphrase.');
|
||||
assert(Buffer.isBuffer(iv));
|
||||
|
||||
crypto.derive(passphrase, function(err, key) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
try {
|
||||
data = crypto.encipher(data, key, iv);
|
||||
} catch (e) {
|
||||
key.fill(0);
|
||||
return callback(e);
|
||||
}
|
||||
key = yield crypto.derive(passphrase);
|
||||
|
||||
try {
|
||||
data = crypto.encipher(data, key, iv);
|
||||
} catch (e) {
|
||||
key.fill(0);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return callback(null, data);
|
||||
});
|
||||
};
|
||||
key.fill(0);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
/**
|
||||
* Encrypt with aes-256-cbc.
|
||||
|
|
@ -288,15 +294,12 @@ crypto.encrypt = function encrypt(data, passphrase, iv, callback) {
|
|||
crypto.encipher = function encipher(data, key, iv) {
|
||||
var cipher;
|
||||
|
||||
if (!nativeCrypto)
|
||||
if (!nodeCrypto)
|
||||
return aes.cbc.encrypt(data, key, iv);
|
||||
|
||||
cipher = nativeCrypto.createCipheriv('aes-256-cbc', key, iv);
|
||||
cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv);
|
||||
|
||||
return Buffer.concat([
|
||||
cipher.update(data),
|
||||
cipher.final()
|
||||
]);
|
||||
return utils.concat(cipher.update(data), cipher.final());
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -304,27 +307,29 @@ crypto.encipher = function encipher(data, key, iv) {
|
|||
* @param {Buffer} data
|
||||
* @param {Buffer|String} passphrase
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.decrypt = function decrypt(data, passphrase, iv, callback) {
|
||||
crypto.decrypt = co(function* decrypt(data, passphrase, iv) {
|
||||
var key;
|
||||
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(passphrase, 'No passphrase.');
|
||||
assert(Buffer.isBuffer(iv));
|
||||
|
||||
crypto.derive(passphrase, function(err, key) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
key = yield crypto.derive(passphrase);
|
||||
|
||||
try {
|
||||
data = crypto.decipher(data, key, iv);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
try {
|
||||
data = crypto.decipher(data, key, iv);
|
||||
} catch (e) {
|
||||
key.fill(0);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return callback(null, data, key);
|
||||
});
|
||||
};
|
||||
key.fill(0);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
/**
|
||||
* Decrypt with aes-256-cbc.
|
||||
|
|
@ -337,15 +342,12 @@ crypto.decrypt = function decrypt(data, passphrase, iv, callback) {
|
|||
crypto.decipher = function decipher(data, key, iv) {
|
||||
var decipher;
|
||||
|
||||
if (!nativeCrypto)
|
||||
if (!nodeCrypto)
|
||||
return aes.cbc.decrypt(data, key, iv);
|
||||
|
||||
decipher = nativeCrypto.createDecipheriv('aes-256-cbc', key, iv);
|
||||
decipher = nodeCrypto.createDecipheriv('aes-256-cbc', key, iv);
|
||||
|
||||
return Buffer.concat([
|
||||
decipher.update(data),
|
||||
decipher.final()
|
||||
]);
|
||||
return utils.concat(decipher.update(data), decipher.final());
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -632,3 +634,13 @@ crypto.randomRange = random.randomRange;
|
|||
*/
|
||||
|
||||
crypto.randomInt = random.randomInt;
|
||||
|
||||
/*
|
||||
* Expose other objects.
|
||||
*/
|
||||
|
||||
lazy('aes', './aes');
|
||||
lazy('chachapoly', './chachapoly');
|
||||
lazy('ec', './ec');
|
||||
lazy('schnorr', './schnorr');
|
||||
lazy('siphash', './siphash');
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ var elliptic = require('elliptic');
|
|||
var bn = require('bn.js');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('./crypto');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var secp256k1;
|
||||
|
||||
try {
|
||||
|
|
@ -21,6 +21,19 @@ try {
|
|||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
var ZERO_S = new Buffer(
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'hex'
|
||||
);
|
||||
|
||||
var HALF_ORDER = new Buffer(
|
||||
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
|
||||
'hex');
|
||||
|
||||
/**
|
||||
* @exports ec
|
||||
*/
|
||||
|
|
@ -173,8 +186,7 @@ ec.ecdh = function ecdh(pub, priv) {
|
|||
|
||||
if (secp256k1) {
|
||||
point = secp256k1.ecdhUnsafe(pub, priv, true);
|
||||
point = ec.curve.decodePoint(point);
|
||||
return point.getX().toArrayLike(Buffer, 'be', 32);
|
||||
return point.slice(1, 33);
|
||||
}
|
||||
|
||||
priv = ec.elliptic.keyPair({ priv: priv });
|
||||
|
|
@ -204,11 +216,13 @@ ec.recover = function recover(msg, sig, j, compressed) {
|
|||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
key = secp256k1.recover(msg, sig, j, compressed);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
|
@ -248,22 +262,16 @@ ec.verify = function verify(msg, sig, key, historical, high) {
|
|||
if (key.length === 0)
|
||||
return false;
|
||||
|
||||
// Attempt to normalize the signature
|
||||
// length before passing to elliptic.
|
||||
// Note: We only do this for historical data!
|
||||
// https://github.com/indutny/elliptic/issues/78
|
||||
if (historical)
|
||||
sig = ec.normalizeLength(sig);
|
||||
|
||||
if (secp256k1) {
|
||||
// secp256k1 fails on high s values. This is
|
||||
// bad for verifying historical data.
|
||||
if (high)
|
||||
sig = ec.toLowS(sig);
|
||||
|
||||
try {
|
||||
// Import from DER.
|
||||
sig = secp256k1.signatureImport(sig);
|
||||
if (historical)
|
||||
sig = secp256k1.signatureImportLax(sig);
|
||||
else
|
||||
sig = secp256k1.signatureImport(sig);
|
||||
|
||||
if (high)
|
||||
sig = secp256k1.signatureNormalize(sig);
|
||||
|
||||
result = secp256k1.verify(msg, sig, key);
|
||||
} catch (e) {
|
||||
result = false;
|
||||
|
|
@ -272,6 +280,13 @@ ec.verify = function verify(msg, sig, key, historical, high) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Attempt to normalize the signature
|
||||
// length before passing to elliptic.
|
||||
// Note: We only do this for historical data!
|
||||
// https://github.com/indutny/elliptic/issues/78
|
||||
if (historical)
|
||||
sig = ec.normalizeLength(sig);
|
||||
|
||||
// Make elliptic mimic secp256k1's
|
||||
// failure with high S values.
|
||||
if (!high && !ec.isLowS(sig))
|
||||
|
|
@ -446,14 +461,36 @@ ec.normalizeLength = function normalizeLength(sig) {
|
|||
*/
|
||||
|
||||
ec.isLowS = function isLowS(sig) {
|
||||
if (Buffer.isBuffer(sig)) {
|
||||
var rs, s;
|
||||
|
||||
if (secp256k1) {
|
||||
try {
|
||||
sig = new ec.signature(sig);
|
||||
rs = secp256k1.signatureImport(sig);
|
||||
s = rs.slice(32, 64);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (utils.equal(s, ZERO_S))
|
||||
return false;
|
||||
|
||||
// If S is greater than half the order,
|
||||
// it's too high.
|
||||
if (utils.cmp(s, HALF_ORDER) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
sig = new ec.signature(sig);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sig.s.cmpn(0) === 0)
|
||||
return false;
|
||||
|
||||
// If S is greater than half the order,
|
||||
// it's too high.
|
||||
if (sig.s.cmp(ec.elliptic.nh) > 0)
|
||||
|
|
@ -462,30 +499,6 @@ ec.isLowS = function isLowS(sig) {
|
|||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lower the S value of a signature (used
|
||||
* for verifying historical data).
|
||||
* @param {Buffer} sig - DER formatted.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.toLowS = function toLowS(sig) {
|
||||
if (Buffer.isBuffer(sig)) {
|
||||
try {
|
||||
sig = new ec.signature(sig);
|
||||
} catch (e) {
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
|
||||
// If S is greater than half the order,
|
||||
// it's too high.
|
||||
if (sig.s.cmp(ec.elliptic.nh) > 0)
|
||||
sig.s = ec.curve.n.sub(sig.s);
|
||||
|
||||
return new Buffer(sig.toDER());
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
|
|
|||
3
lib/crypto/index.js
Normal file
3
lib/crypto/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = require('./crypto');
|
||||
11
lib/db/index.js
Normal file
11
lib/db/index.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
|
||||
exports.ldb = require('./ldb');
|
||||
|
||||
if (utils.isBrowser)
|
||||
exports.level = require('./level');
|
||||
|
||||
exports.LowlevelUp = require('./lowlevelup');
|
||||
exports.RBT = require('./rbt');
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
var LowlevelUp = require('./lowlevelup');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var AsyncObject = require('../utils/async');
|
||||
var co = require('../utils/co');
|
||||
var VERSION_ERROR;
|
||||
|
||||
/**
|
||||
|
|
@ -57,148 +58,193 @@ utils.inherits(LowlevelUp, AsyncObject);
|
|||
/**
|
||||
* Open the database (recallable).
|
||||
* @alias LowlevelUp#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype._open = function open(callback) {
|
||||
this.binding.open(this.options, callback);
|
||||
LowlevelUp.prototype._open = function open() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.open(self.options, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the database (recallable).
|
||||
* @alias LowlevelUp#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype._close = function close(callback) {
|
||||
this.binding.close(callback);
|
||||
LowlevelUp.prototype._close = function close() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.close(co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy the database.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.destroy = function destroy(callback) {
|
||||
LowlevelUp.prototype.destroy = function destroy() {
|
||||
var self = this;
|
||||
|
||||
assert(!this.loading);
|
||||
assert(!this.closing);
|
||||
assert(!this.loaded);
|
||||
|
||||
if (!this.backend.destroy)
|
||||
return utils.asyncify(callback)(new Error('Cannot destroy.'));
|
||||
|
||||
this.backend.destroy(this.location, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!self.backend.destroy)
|
||||
return reject(new Error('Cannot destroy.'));
|
||||
self.backend.destroy(self.location, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Repair the database.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.repair = function repair(callback) {
|
||||
LowlevelUp.prototype.repair = function repair() {
|
||||
var self = this;
|
||||
|
||||
assert(!this.loading);
|
||||
assert(!this.closing);
|
||||
assert(!this.loaded);
|
||||
|
||||
if (!this.backend.repair)
|
||||
return utils.asyncify(callback)(new Error('Cannot repair.'));
|
||||
|
||||
this.backend.repair(this.location, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!self.backend.repair)
|
||||
return reject(new Error('Cannot repair.'));
|
||||
self.backend.repair(self.location, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Backup the database.
|
||||
* @param {String} path
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.backup = function backup(path, callback) {
|
||||
LowlevelUp.prototype.backup = function backup(path) {
|
||||
var self = this;
|
||||
|
||||
assert(!this.loading);
|
||||
assert(!this.closing);
|
||||
assert(this.loaded);
|
||||
|
||||
if (!this.binding.backup)
|
||||
return this.clone(path, callback);
|
||||
return this.clone(path);
|
||||
|
||||
this.binding.backup(path, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.backup(path, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a record from the database.
|
||||
* @param {String} key
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback - Returns [Error, Buffer].
|
||||
* @param {String|Buffer} key
|
||||
* @returns {Promise} - Returns Buffer.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.get = function get(key, options, callback) {
|
||||
LowlevelUp.prototype.get = function get(key) {
|
||||
var self = this;
|
||||
|
||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
this.binding.get(key, options, function(err, result) {
|
||||
if (err) {
|
||||
if (isNotFound(err))
|
||||
return callback();
|
||||
return callback(err);
|
||||
}
|
||||
return callback(null, result);
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.get(key, function(err, result) {
|
||||
if (err) {
|
||||
if (isNotFound(err))
|
||||
return resolve();
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Store a record in the database.
|
||||
* @param {String} key
|
||||
* @param {String|Buffer} key
|
||||
* @param {Buffer} value
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.put = function put(key, value, options, callback) {
|
||||
LowlevelUp.prototype.put = function put(key, value) {
|
||||
var self = this;
|
||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||
this.binding.put(key, value, options, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.put(key, value, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a record from the database.
|
||||
* @param {String} key
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @param {String|Buffer} key
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.del = function del(key, options, callback) {
|
||||
LowlevelUp.prototype.del = function del(key) {
|
||||
var self = this;
|
||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||
this.binding.del(key, options, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.del(key, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an atomic batch.
|
||||
* @param {Array?} ops
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @returns {Leveldown.Batch}
|
||||
* @returns {Batch}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.batch = function batch(ops, options, callback) {
|
||||
LowlevelUp.prototype.batch = function batch(ops) {
|
||||
var self = this;
|
||||
|
||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||
|
||||
if (!ops)
|
||||
return this.binding.batch();
|
||||
return new Batch(this);
|
||||
|
||||
this.binding.batch(ops, options, callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.binding.batch(ops, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an iterator.
|
||||
* @param {Object} options
|
||||
* @returns {Leveldown.Iterator}
|
||||
* @returns {Iterator}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.iterator = function iterator(options) {
|
||||
var opt;
|
||||
|
||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||
return this.db.iterator(options);
|
||||
|
||||
opt = {
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: options.keys !== false,
|
||||
values: options.values || false,
|
||||
fillCache: options.fillCache || false,
|
||||
keyAsBuffer: this.bufferKeys,
|
||||
valueAsBuffer: true,
|
||||
reverse: options.reverse || false,
|
||||
highWaterMark: options.highWaterMark || 16 * 1024
|
||||
};
|
||||
|
||||
// Workaround for a leveldown
|
||||
// bug I haven't fixed yet.
|
||||
if (options.limit != null)
|
||||
opt.limit = options.limit;
|
||||
|
||||
if (options.keyAsBuffer != null)
|
||||
opt.keyAsBuffer = options.keyAsBuffer;
|
||||
|
||||
assert(opt.keys || opt.values, 'Keys and/or values must be chosen.');
|
||||
|
||||
return new Iterator(this, opt);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -220,199 +266,215 @@ LowlevelUp.prototype.getProperty = function getProperty(name) {
|
|||
* Calculate approximate database size.
|
||||
* @param {String} start - Start key.
|
||||
* @param {String} end - End key.
|
||||
* @param {Function} callback - Returns [Error, Number].
|
||||
* @returns {Promise} - Returns Number.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.approximateSize = function approximateSize(start, end, callback) {
|
||||
LowlevelUp.prototype.approximateSize = function approximateSize(start, end) {
|
||||
var self = this;
|
||||
|
||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||
|
||||
if (!this.binding.approximateSize)
|
||||
return utils.asyncify(callback)(new Error('Cannot get size.'));
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!self.binding.approximateSize)
|
||||
return reject(new Error('Cannot get size.'));
|
||||
|
||||
this.binding.approximateSize(start, end, callback);
|
||||
self.binding.approximateSize(start, end, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether a key exists.
|
||||
* @param {String} key
|
||||
* @param {Function} callback - Returns [Error, Boolean].
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.has = function has(key, callback) {
|
||||
this.get(key, function(err, value) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, value != null);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get and deserialize a record with a callback.
|
||||
* @param {String} key
|
||||
* @param {Function} parse - Accepts [Buffer(data), String(key)].
|
||||
* Return value should be the parsed object.
|
||||
* @param {Function} callback - Returns [Error, Object].
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.fetch = function fetch(key, parse, callback) {
|
||||
this.get(key, function(err, value) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!value)
|
||||
return callback();
|
||||
|
||||
try {
|
||||
value = parse(value, key);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
return callback(null, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterate over each record.
|
||||
* @param {Object} options
|
||||
* @param {Function} handler
|
||||
* @param {Function} callback - Returns [Error, Object].
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.each = function each(options, handler, callback) {
|
||||
var i = 0;
|
||||
var opt, iter;
|
||||
|
||||
opt = {
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: options.keys !== false,
|
||||
values: options.values || false,
|
||||
fillCache: options.fillCache || false,
|
||||
keyAsBuffer: this.bufferKeys,
|
||||
valueAsBuffer: true,
|
||||
reverse: options.reverse || false
|
||||
};
|
||||
|
||||
// Workaround for a leveldown
|
||||
// bug I haven't fixed yet.
|
||||
if (options.limit != null)
|
||||
opt.limit = options.limit;
|
||||
|
||||
if (options.keyAsBuffer != null)
|
||||
opt.keyAsBuffer = options.keyAsBuffer;
|
||||
|
||||
assert(opt.keys || opt.values, 'Keys and/or values must be chosen.');
|
||||
|
||||
iter = this.iterator(opt);
|
||||
|
||||
function next(err, key) {
|
||||
if (err && typeof err !== 'boolean') {
|
||||
return iter.end(function() {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
if (err === false)
|
||||
return iter.end(callback);
|
||||
|
||||
if (err === true) {
|
||||
try {
|
||||
iter.seek(key);
|
||||
} catch (e) {
|
||||
return iter.end(function() {
|
||||
callback(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
iter.next(onNext);
|
||||
}
|
||||
|
||||
function onNext(err, key, value) {
|
||||
if (err) {
|
||||
return iter.end(function() {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
if (key === undefined && value === undefined)
|
||||
return iter.end(callback);
|
||||
|
||||
try {
|
||||
handler(key, value, next, i++);
|
||||
} catch (e) {
|
||||
return iter.end(function() {
|
||||
callback(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
LowlevelUp.prototype.has = co(function* has(key) {
|
||||
var value = yield this.get(key);
|
||||
return value != null;
|
||||
});
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @param {Function} callback - Returns [Error, Array].
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.iterate = function iterate(options, callback) {
|
||||
LowlevelUp.prototype.range = co(function* range(options) {
|
||||
var items = [];
|
||||
assert(typeof options.parse === 'function', 'Parse must be a function.');
|
||||
this.each(options, function(key, value, next) {
|
||||
var result = options.parse(key, value);
|
||||
if (result)
|
||||
items.push(result);
|
||||
next();
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
callback(null, items);
|
||||
var parse = options.parse;
|
||||
var iter, item;
|
||||
|
||||
iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: true,
|
||||
values: true
|
||||
});
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
item = yield iter.next();
|
||||
|
||||
if (!item)
|
||||
break;
|
||||
|
||||
if (parse) {
|
||||
try {
|
||||
item = parse(item.key, item.value);
|
||||
} catch (e) {
|
||||
yield iter.end();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (item)
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
return items;
|
||||
});
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.keys = co(function* keys(options) {
|
||||
var keys = [];
|
||||
var parse = options.parse;
|
||||
var iter, item, key;
|
||||
|
||||
iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: true,
|
||||
values: false
|
||||
});
|
||||
|
||||
for (;;) {
|
||||
item = yield iter.next();
|
||||
|
||||
if (!item)
|
||||
break;
|
||||
|
||||
key = item.key;
|
||||
|
||||
if (parse) {
|
||||
try {
|
||||
key = parse(key);
|
||||
} catch (e) {
|
||||
yield iter.end();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (key)
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
return keys;
|
||||
});
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.values = co(function* values(options) {
|
||||
var values = [];
|
||||
var parse = options.parse;
|
||||
var iter, item, value;
|
||||
|
||||
iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: false,
|
||||
values: true
|
||||
});
|
||||
|
||||
for (;;) {
|
||||
item = yield iter.next();
|
||||
|
||||
if (!item)
|
||||
break;
|
||||
|
||||
value = item.value;
|
||||
|
||||
if (parse) {
|
||||
try {
|
||||
value = parse(value);
|
||||
} catch (e) {
|
||||
yield iter.end();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (value)
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
return values;
|
||||
});
|
||||
|
||||
/**
|
||||
* Dump database (for debugging).
|
||||
* @returns {Promise} - Returns Object.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.dump = co(function* dump() {
|
||||
var records = {};
|
||||
var i, items, item, key, value;
|
||||
|
||||
items = yield this.range({
|
||||
gte: new Buffer([0x00]),
|
||||
lte: new Buffer([0xff])
|
||||
});
|
||||
|
||||
for (i = 0; i < items.length; i++) {
|
||||
item = items[i];
|
||||
key = item.key.toString('hex');
|
||||
value = item.value.toString('hex');
|
||||
records[key] = value;
|
||||
}
|
||||
|
||||
return records;
|
||||
});
|
||||
|
||||
/**
|
||||
* Write and assert a version number for the database.
|
||||
* @param {Number} version
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.checkVersion = function checkVersion(key, version, callback) {
|
||||
var self = this;
|
||||
this.get(key, function(err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
LowlevelUp.prototype.checkVersion = co(function* checkVersion(key, version) {
|
||||
var data = yield this.get(key);
|
||||
|
||||
if (!data) {
|
||||
data = new Buffer(4);
|
||||
data.writeUInt32LE(version, 0, true);
|
||||
return self.put(key, data, callback);
|
||||
}
|
||||
if (!data) {
|
||||
data = new Buffer(4);
|
||||
data.writeUInt32LE(version, 0, true);
|
||||
yield this.put(key, data);
|
||||
return;
|
||||
}
|
||||
|
||||
data = data.readUInt32LE(0, true);
|
||||
data = data.readUInt32LE(0, true);
|
||||
|
||||
if (data !== version)
|
||||
return callback(new Error(VERSION_ERROR));
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
if (data !== version)
|
||||
throw new Error(VERSION_ERROR);
|
||||
});
|
||||
|
||||
/**
|
||||
* Clone the database.
|
||||
* @param {String} path
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.clone = function clone(path, callback) {
|
||||
var self = this;
|
||||
var iter = { keys: true, values: true };
|
||||
LowlevelUp.prototype.clone = co(function* clone(path) {
|
||||
var options = utils.merge({}, this.options);
|
||||
var opt = { keys: true, values: true };
|
||||
var hwm = 256 << 20;
|
||||
var total = 0;
|
||||
var tmp, batch;
|
||||
var tmp, batch, iter, item;
|
||||
|
||||
assert(!this.loading);
|
||||
assert(!this.closing);
|
||||
|
|
@ -423,50 +485,159 @@ LowlevelUp.prototype.clone = function clone(path, callback) {
|
|||
|
||||
tmp = new LowlevelUp(path, options);
|
||||
|
||||
function done(err) {
|
||||
tmp.close(function(e) {
|
||||
if (e)
|
||||
return callback(e);
|
||||
callback(err);
|
||||
});
|
||||
yield tmp.open();
|
||||
|
||||
batch = tmp.batch();
|
||||
iter = this.iterator(opt);
|
||||
|
||||
for (;;) {
|
||||
item = yield iter.next();
|
||||
|
||||
if (!item)
|
||||
break;
|
||||
|
||||
batch.put(item.key, item.value);
|
||||
total += item.value.length;
|
||||
|
||||
if (total >= hwm) {
|
||||
total = 0;
|
||||
try {
|
||||
yield batch.write();
|
||||
} catch (e) {
|
||||
yield iter.end();
|
||||
yield tmp.close();
|
||||
throw e;
|
||||
}
|
||||
batch = tmp.batch();
|
||||
}
|
||||
}
|
||||
|
||||
tmp.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
try {
|
||||
yield batch.write();
|
||||
} finally {
|
||||
yield tmp.close();
|
||||
}
|
||||
});
|
||||
|
||||
batch = tmp.batch();
|
||||
/**
|
||||
* Batch
|
||||
* @constructor
|
||||
* @param {LowlevelUp} db
|
||||
*/
|
||||
|
||||
self.each(iter, function(key, value, next) {
|
||||
batch.put(key, value);
|
||||
function Batch(db) {
|
||||
this.batch = db.binding.batch();
|
||||
}
|
||||
|
||||
total += value.length;
|
||||
/**
|
||||
* Write a value to the batch.
|
||||
* @param {String|Buffer} key
|
||||
* @param {Buffer} value
|
||||
*/
|
||||
|
||||
if (total >= hwm) {
|
||||
total = 0;
|
||||
batch.write(function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
batch = tmp.batch();
|
||||
next();
|
||||
Batch.prototype.put = function(key, value) {
|
||||
this.batch.put(key, value);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a value from the batch.
|
||||
* @param {String|Buffer} key
|
||||
*/
|
||||
|
||||
Batch.prototype.del = function del(key) {
|
||||
this.batch.del(key);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write batch to database.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Batch.prototype.write = function write() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.batch.write(co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the batch.
|
||||
*/
|
||||
|
||||
Batch.prototype.clear = function clear() {
|
||||
this.batch.clear();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator
|
||||
* @constructor
|
||||
* @param {LowlevelUp} db
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
function Iterator(db, options) {
|
||||
this.iter = db.db.iterator(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the next key.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Iterator.prototype.next = function() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.iter.next(function(err, key, value) {
|
||||
if (err) {
|
||||
self.iter.end(function() {
|
||||
reject(err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return done(err);
|
||||
if (key === undefined && value === undefined) {
|
||||
self.iter.end(co.wrap(resolve, reject));
|
||||
return;
|
||||
}
|
||||
|
||||
batch.write(done);
|
||||
resolve(new KeyValue(key, value));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Seek to an arbitrary key.
|
||||
* @param {String|Buffer}
|
||||
*/
|
||||
|
||||
Iterator.prototype.seek = function seek(key) {
|
||||
this.iter.seek(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* End the iterator.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Iterator.prototype.end = function end() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.iter.end(co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function KeyValue(key, value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
function isNotFound(err) {
|
||||
if (!err)
|
||||
return false;
|
||||
|
|
|
|||
110
lib/db/rbt.js
110
lib/db/rbt.js
|
|
@ -7,7 +7,7 @@
|
|||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var DUMMY = new Buffer([0]);
|
||||
var RED = 0;
|
||||
var BLACK = 1;
|
||||
|
|
@ -15,9 +15,9 @@ var SENTINEL;
|
|||
|
||||
/**
|
||||
* An iterative red black tree.
|
||||
* Used for the mempool. Many of its
|
||||
* options, parameters, and methods
|
||||
* mimic the leveldown interface.
|
||||
* Many of its options, parameters,
|
||||
* and methods mimic the leveldown
|
||||
* interface.
|
||||
* @exports RBT
|
||||
* @constructor
|
||||
* @param {String?} location - Phony location.
|
||||
|
|
@ -572,7 +572,7 @@ RBT.prototype.range = function range(gte, lte) {
|
|||
/**
|
||||
* Open the database (leveldown method).
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
RBT.prototype.open = function open(options, callback) {
|
||||
|
|
@ -586,23 +586,23 @@ RBT.prototype.open = function open(options, callback) {
|
|||
|
||||
this.options = options;
|
||||
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the database (leveldown method).
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
RBT.prototype.close = function close(callback) {
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a record (leveldown method).
|
||||
* @param {Buffer|String} key
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback - Returns [Error, Buffer].
|
||||
* @returns {Promise} - Returns Buffer.
|
||||
*/
|
||||
|
||||
RBT.prototype.get = function get(key, options, callback) {
|
||||
|
|
@ -622,13 +622,18 @@ RBT.prototype.get = function get(key, options, callback) {
|
|||
err = new Error('RBT_NOTFOUND: Key not found.');
|
||||
err.notFound = true;
|
||||
err.type = 'NotFoundError';
|
||||
return utils.asyncify(callback)(err);
|
||||
utils.nextTick(function() {
|
||||
callback(err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.asBuffer === false)
|
||||
value = value.toString('utf8');
|
||||
|
||||
return utils.asyncify(callback)(null, value);
|
||||
utils.nextTick(function() {
|
||||
callback(null, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -636,7 +641,7 @@ RBT.prototype.get = function get(key, options, callback) {
|
|||
* @param {Buffer|String} key
|
||||
* @param {Buffer} value
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
RBT.prototype.put = function put(key, value, options, callback) {
|
||||
|
|
@ -647,14 +652,14 @@ RBT.prototype.put = function put(key, value, options, callback) {
|
|||
|
||||
this.insert(key, value);
|
||||
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a record (leveldown method).
|
||||
* @param {Buffer|String} key
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
RBT.prototype.del = function del(key, options, callback) {
|
||||
|
|
@ -665,7 +670,7 @@ RBT.prototype.del = function del(key, options, callback) {
|
|||
|
||||
this.remove(key);
|
||||
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -673,7 +678,7 @@ RBT.prototype.del = function del(key, options, callback) {
|
|||
* @see Leveldown.Batch
|
||||
* @param {Object[]?} ops
|
||||
* @param {Object?} options
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
* @returns {Leveldown.Batch}
|
||||
*/
|
||||
|
||||
|
|
@ -722,7 +727,7 @@ RBT.prototype.getProperty = function getProperty(name) {
|
|||
* Calculate approximate database size (leveldown method).
|
||||
* @param {Buffer|String} start - Start key.
|
||||
* @param {Buffer|String} end - End key.
|
||||
* @param {Function} callback - Returns [Error, Number].
|
||||
* @returns {Promise} - Returns Number.
|
||||
*/
|
||||
|
||||
RBT.prototype.approximateSize = function approximateSize(start, end, callback) {
|
||||
|
|
@ -736,27 +741,29 @@ RBT.prototype.approximateSize = function approximateSize(start, end, callback) {
|
|||
size += item.value.length;
|
||||
}
|
||||
|
||||
return utils.asyncify(callback)(null, size);
|
||||
utils.nextTick(function() {
|
||||
callback(null, size);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy the database (leveldown function) (NOP).
|
||||
* @param {String} location
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
RBT.destroy = function destroy(location, callback) {
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Repair the database (leveldown function) (NOP).
|
||||
* @param {String} location
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
RBT.repair = function repair(location, callback) {
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -934,23 +941,34 @@ Batch.prototype.del = function del(key) {
|
|||
|
||||
/**
|
||||
* Commit the batch.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Batch.prototype.write = function write(callback) {
|
||||
var i, op;
|
||||
|
||||
if (!this.tree)
|
||||
return callback(new Error('Already written.'));
|
||||
if (!this.tree) {
|
||||
utils.nextTick(function() {
|
||||
callback(new Error('Already written.'));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < this.ops.length; i++) {
|
||||
op = this.ops[i];
|
||||
if (op.type === 'put')
|
||||
this.tree.insert(op.key, op.value);
|
||||
else if (op.type === 'del')
|
||||
this.tree.remove(op.key);
|
||||
else
|
||||
assert(false);
|
||||
switch (op.type) {
|
||||
case 'put':
|
||||
this.tree.insert(op.key, op.value);
|
||||
break;
|
||||
case 'del':
|
||||
this.tree.remove(op.key);
|
||||
break;
|
||||
default:
|
||||
utils.nextTick(function() {
|
||||
callback(new Error('Bad operation: ' + op.type));
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.ops.length = 0;
|
||||
|
|
@ -1023,14 +1041,18 @@ function Iterator(tree, options) {
|
|||
|
||||
/**
|
||||
* Seek to the next key.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Iterator.prototype.next = function(callback) {
|
||||
var item, key, value;
|
||||
|
||||
if (this.ended)
|
||||
return utils.asyncify(callback)(new Error('Cannot call next after end.'));
|
||||
if (this.ended) {
|
||||
utils.nextTick(function() {
|
||||
callback(new Error('Cannot call next after end.'));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.reverse)
|
||||
item = this.snapshot[this.index--];
|
||||
|
|
@ -1040,13 +1062,15 @@ Iterator.prototype.next = function(callback) {
|
|||
if (this.options.limit != null) {
|
||||
if (this.total++ >= this.options.limit) {
|
||||
this._end();
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
this._end();
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
key = item.key;
|
||||
|
|
@ -1064,7 +1088,9 @@ Iterator.prototype.next = function(callback) {
|
|||
if (this.options.valueAsBuffer === false)
|
||||
value = value.toString('utf8');
|
||||
|
||||
utils.asyncify(callback)(null, key, value);
|
||||
utils.nextTick(function() {
|
||||
callback(null, key, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1105,13 +1131,17 @@ Iterator.prototype._end = function end() {
|
|||
*/
|
||||
|
||||
Iterator.prototype.end = function end(callback) {
|
||||
if (this.ended)
|
||||
return utils.asyncify(callback)(new Error('Already ended.'));
|
||||
if (this.ended) {
|
||||
utils.nextTick(function() {
|
||||
callback(new Error('Already ended.'));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.ended = true;
|
||||
this._end();
|
||||
|
||||
return utils.nextTick(callback);
|
||||
utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
165
lib/env.js
165
lib/env.js
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var utils = require('./utils/utils');
|
||||
var global = utils.global;
|
||||
|
||||
/**
|
||||
* A BCoin "environment" which is used for
|
||||
* bootstrapping the initial `bcoin` module.
|
||||
|
|
@ -126,13 +123,11 @@ function Environment() {
|
|||
this.require('bloom', './utils/bloom');
|
||||
this.require('uri', './utils/uri');
|
||||
this.require('errors', './utils/errors');
|
||||
this.require('co', './utils/co');
|
||||
|
||||
// Crypto
|
||||
this.require('ec', './crypto/ec');
|
||||
this.require('crypto', './crypto/crypto');
|
||||
this.require('chachapoly', './crypto/chachapoly');
|
||||
this.require('scrypt', './crypto/scrypt');
|
||||
this.require('siphash', './crypto/siphash');
|
||||
|
||||
// DB
|
||||
this.require('lowlevelup', './db/lowlevelup');
|
||||
|
|
@ -145,7 +140,6 @@ function Environment() {
|
|||
this.require('stack', './script/stack');
|
||||
this.require('witness', './script/witness');
|
||||
this.require('program', './script/program');
|
||||
this.require('sc', './script/sigcache');
|
||||
|
||||
// Primitives
|
||||
this.require('address', './primitives/address');
|
||||
|
|
@ -156,8 +150,6 @@ function Environment() {
|
|||
this.require('invitem', './primitives/invitem');
|
||||
this.require('tx', './primitives/tx');
|
||||
this.require('mtx', './primitives/mtx');
|
||||
this.require('abstractblock', './primitives/abstractblock');
|
||||
this.require('memblock', './primitives/memblock');
|
||||
this.require('block', './primitives/block');
|
||||
this.require('merkleblock', './primitives/merkleblock');
|
||||
this.require('headers', './primitives/headers');
|
||||
|
|
@ -175,7 +167,7 @@ function Environment() {
|
|||
this.require('fullnode', './node/fullnode');
|
||||
|
||||
// Net
|
||||
this.require('timedata', './net/timedata');
|
||||
this.require('time', './net/timedata');
|
||||
this.require('packets', './net/packets');
|
||||
this.require('bip150', './net/bip150');
|
||||
this.require('bip151', './net/bip151');
|
||||
|
|
@ -184,8 +176,6 @@ function Environment() {
|
|||
this.require('pool', './net/pool');
|
||||
|
||||
// Chain
|
||||
this.require('coins', './chain/coins');
|
||||
this.require('coinview', './chain/coinview');
|
||||
this.require('chainentry', './chain/chainentry');
|
||||
this.require('chaindb', './chain/chaindb');
|
||||
this.require('chain', './chain/chain');
|
||||
|
|
@ -193,7 +183,7 @@ function Environment() {
|
|||
// Mempool
|
||||
this.require('fees', './mempool/fees');
|
||||
this.require('mempool', './mempool/mempool');
|
||||
this.expose('mempoolentry', 'mempool', 'MempoolEntry');
|
||||
this.require('mempoolentry', './mempool/mempoolentry');
|
||||
|
||||
// Miner
|
||||
this.require('miner', './miner/miner');
|
||||
|
|
@ -204,34 +194,18 @@ function Environment() {
|
|||
this.require('account', './wallet/account');
|
||||
this.require('walletdb', './wallet/walletdb');
|
||||
this.require('path', './wallet/path');
|
||||
this.require('masterkey', './wallet/masterkey');
|
||||
this.require('walletkey', './wallet/walletkey');
|
||||
|
||||
// HTTP
|
||||
this.require('http', './http');
|
||||
this.require('rpc', './http/rpc');
|
||||
|
||||
// Workers
|
||||
this.require('workers', './workers/workers');
|
||||
|
||||
// Horrible BIP
|
||||
this.require('bip70', './bip70/bip70');
|
||||
|
||||
// Global Instances
|
||||
this.instance('sigcache', 'sc', 0);
|
||||
this.instance('time', 'timedata');
|
||||
this.instance('defaultLogger', 'logger', 'none');
|
||||
this.instance('workerPool', 'workers');
|
||||
|
||||
// Global Worker Properties
|
||||
this.useWorkers = false;
|
||||
this.master = null;
|
||||
|
||||
// Initialize the environment.
|
||||
this.set({
|
||||
network: process.env.BCOIN_NETWORK || 'main',
|
||||
useWorkers: +process.env.BCOIN_USE_WORKERS === 1,
|
||||
maxWorkers: +process.env.BCOIN_MAX_WORKERS,
|
||||
workerTimeout: +process.env.BCOIN_WORKER_TIMEOUT,
|
||||
sigcacheSize: +process.env.BCOIN_SIGCACHE_SIZE
|
||||
});
|
||||
this.require('bip70', './bip70');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -249,38 +223,6 @@ Environment.prototype.require = function _require(key, path) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign a property for a lazily required module.
|
||||
* @param {String} key
|
||||
* @param {String} object
|
||||
* @param {String} property
|
||||
*/
|
||||
|
||||
Environment.prototype.expose = function expose(key, object, property) {
|
||||
var cache;
|
||||
this.__defineGetter__(key, function() {
|
||||
if (!cache)
|
||||
cache = this[object][property];
|
||||
return cache;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign an object instance for a lazily assigned property.
|
||||
* @param {String} key
|
||||
* @param {String} object
|
||||
* @param {String} property
|
||||
*/
|
||||
|
||||
Environment.prototype.instance = function instance(key, object, arg) {
|
||||
var cache;
|
||||
this.__defineGetter__(key, function() {
|
||||
if (!cache)
|
||||
cache = new this[object](arg);
|
||||
return cache;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the default network.
|
||||
* @param {String} options
|
||||
|
|
@ -296,21 +238,9 @@ Environment.prototype.set = function set(options) {
|
|||
if (options.network)
|
||||
this.network.set(options.network);
|
||||
|
||||
if (typeof options.useWorkers === 'boolean')
|
||||
this.useWorkers = options.useWorkers;
|
||||
this.workers.set(options);
|
||||
|
||||
if (utils.isNumber(options.maxWorkers))
|
||||
this.workerPool.size = options.maxWorkers;
|
||||
|
||||
if (utils.isNumber(options.workerTimeout))
|
||||
this.workerPool.timeout = options.workerTimeout;
|
||||
|
||||
if (utils.isBrowser && this.useWorkers) {
|
||||
this.useWorkers = typeof global.Worker === 'function'
|
||||
|| typeof global.postMessage === 'function';
|
||||
}
|
||||
|
||||
if (utils.isNumber(options.sigcacheSize))
|
||||
if (options.sigcacheSize != null)
|
||||
this.sigcache.resize(options.sigcacheSize);
|
||||
|
||||
return this;
|
||||
|
|
@ -327,80 +257,15 @@ Environment.prototype.now = function now() {
|
|||
|
||||
/**
|
||||
* Cache all necessary modules.
|
||||
* Used for benchmarks and browserify.
|
||||
*/
|
||||
|
||||
Environment.prototype.cache = function cache() {
|
||||
require('bn.js');
|
||||
require('./protocol/constants');
|
||||
require('./protocol/networks');
|
||||
require('./protocol/network');
|
||||
require('./utils/utils');
|
||||
require('./utils/locker');
|
||||
require('./utils/reader');
|
||||
require('./utils/writer');
|
||||
require('./utils/lru');
|
||||
require('./utils/bloom');
|
||||
require('./utils/uri');
|
||||
require('./utils/errors');
|
||||
require('./crypto/ec');
|
||||
require('./crypto/crypto');
|
||||
require('./crypto/chachapoly');
|
||||
require('./crypto/scrypt');
|
||||
require('./crypto/siphash');
|
||||
require('./db/lowlevelup');
|
||||
require('./db/ldb');
|
||||
require('./db/rbt');
|
||||
require('./script/script');
|
||||
require('./script/opcode');
|
||||
require('./script/stack');
|
||||
require('./script/witness');
|
||||
require('./script/program');
|
||||
require('./script/sigcache');
|
||||
require('./primitives/address');
|
||||
require('./primitives/outpoint');
|
||||
require('./primitives/input');
|
||||
require('./primitives/output');
|
||||
require('./primitives/coin');
|
||||
require('./primitives/invitem');
|
||||
require('./primitives/tx');
|
||||
require('./primitives/mtx');
|
||||
require('./primitives/abstractblock');
|
||||
require('./primitives/memblock');
|
||||
require('./primitives/block');
|
||||
require('./primitives/merkleblock');
|
||||
require('./primitives/headers');
|
||||
require('./primitives/keyring');
|
||||
require('./primitives/netaddress');
|
||||
require('./hd/hd');
|
||||
require('./node/logger');
|
||||
require('./node/config');
|
||||
require('./node/node');
|
||||
require('./node/spvnode');
|
||||
require('./node/fullnode');
|
||||
require('./net/timedata');
|
||||
require('./net/packets');
|
||||
require('./net/bip150');
|
||||
require('./net/bip151');
|
||||
require('./net/bip152');
|
||||
require('./net/peer');
|
||||
require('./net/pool');
|
||||
require('./chain/coins');
|
||||
require('./chain/coinview');
|
||||
require('./chain/chainentry');
|
||||
require('./chain/chaindb');
|
||||
require('./chain/chain');
|
||||
require('./mempool/fees');
|
||||
require('./mempool/mempool');
|
||||
require('./miner/miner');
|
||||
require('./miner/minerblock');
|
||||
require('./wallet/wallet');
|
||||
require('./wallet/account');
|
||||
require('./wallet/walletdb');
|
||||
require('./wallet/path');
|
||||
require('./node/spvnode');
|
||||
require('./http');
|
||||
require('./workers/workers');
|
||||
require('./bip70/bip70');
|
||||
require('./crypto/schnorr');
|
||||
require('./utils/uri');
|
||||
require('./bip70');
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -409,12 +274,8 @@ Environment.prototype.cache = function cache() {
|
|||
*/
|
||||
|
||||
exports.require = Environment.prototype.require;
|
||||
exports.expose = Environment.prototype.expose;
|
||||
exports.instance = Environment.prototype.instance;
|
||||
exports.cache = Environment.prototype.cache;
|
||||
exports.set = Environment.prototype.set;
|
||||
exports.now = Environment.prototype.now;
|
||||
|
||||
Environment.call(exports);
|
||||
|
||||
utils.fastProp(exports);
|
||||
|
|
|
|||
27
lib/hd/hd.js
27
lib/hd/hd.js
|
|
@ -6,10 +6,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var LRU = require('../utils/lru');
|
||||
var Mnemonic = require('./mnemonic');
|
||||
var HDPrivateKey = require('./private');
|
||||
|
|
@ -114,26 +112,21 @@ HD.fromExtended = function fromExtended(data) {
|
|||
*/
|
||||
|
||||
HD.from = function from(options, network) {
|
||||
var xkey;
|
||||
|
||||
assert(options, 'Options required.');
|
||||
|
||||
if (options.xkey)
|
||||
xkey = options.xkey;
|
||||
else if (options.xpubkey)
|
||||
xkey = options.xpubkey;
|
||||
else if (options.xprivkey)
|
||||
xkey = options.xprivkey;
|
||||
else
|
||||
xkey = options;
|
||||
if (HD.isHD(options))
|
||||
return options;
|
||||
|
||||
if (HD.isExtended(xkey))
|
||||
return HD.fromBase58(xkey);
|
||||
if (HD.isExtended(options))
|
||||
return HD.fromBase58(options);
|
||||
|
||||
if (HD.hasPrefix(options))
|
||||
return HD.fromRaw(options);
|
||||
|
||||
return HD.fromMnemonic(options, network);
|
||||
if (options && typeof options === 'object')
|
||||
return HD.fromMnemonic(options, network);
|
||||
|
||||
throw new Error('Cannot create HD key from bad options.');
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
3
lib/hd/index.js
Normal file
3
lib/hd/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = require('./hd');
|
||||
|
|
@ -6,11 +6,10 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var ec = require('../crypto/ec');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var networks = bcoin.networks;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var networks = require('../protocol/networks');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
|
|
@ -52,7 +52,7 @@ function HDPrivateKey(options) {
|
|||
if (!(this instanceof HDPrivateKey))
|
||||
return new HDPrivateKey(options);
|
||||
|
||||
this.network = bcoin.network.get();
|
||||
this.network = Network.primary;
|
||||
this.depth = 0;
|
||||
this.parentFingerPrint = FINGER_PRINT;
|
||||
this.childIndex = 0;
|
||||
|
|
@ -89,7 +89,7 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
|||
assert(options.depth <= 0xff, 'Depth is too high.');
|
||||
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.network = Network.get(options.network);
|
||||
|
||||
this.depth = options.depth;
|
||||
this.parentFingerPrint = options.parentFingerPrint;
|
||||
|
|
@ -187,11 +187,19 @@ HDPrivateKey.prototype.destroy = function destroy(pub) {
|
|||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
||||
HDPrivateKey.prototype.derive = function derive(index, hardened, cache) {
|
||||
var p, id, data, hash, left, right, key, child;
|
||||
|
||||
if (typeof hardened !== 'boolean') {
|
||||
cache = hardened;
|
||||
hardened = false;
|
||||
}
|
||||
|
||||
if (!cache)
|
||||
cache = HD.cache;
|
||||
|
||||
if (typeof index === 'string')
|
||||
return this.derivePath(index);
|
||||
return this.derivePath(index, cache);
|
||||
|
||||
hardened = index >= constants.hd.HARDENED ? true : hardened;
|
||||
|
||||
|
|
@ -204,11 +212,12 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||
if (this.depth >= 0xff)
|
||||
throw new Error('Depth too high.');
|
||||
|
||||
id = this.getID(index);
|
||||
child = HD.cache.get(id);
|
||||
|
||||
if (child)
|
||||
return child;
|
||||
if (cache) {
|
||||
id = this.getID(index);
|
||||
child = cache.get(id);
|
||||
if (child)
|
||||
return child;
|
||||
}
|
||||
|
||||
p = new BufferWriter();
|
||||
|
||||
|
|
@ -230,7 +239,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||
try {
|
||||
key = ec.privateKeyTweakAdd(this.privateKey, left);
|
||||
} catch (e) {
|
||||
return this.derive(index + 1);
|
||||
return this.derive(index + 1, cache);
|
||||
}
|
||||
|
||||
if (!this.fingerPrint)
|
||||
|
|
@ -245,7 +254,8 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||
child.privateKey = key;
|
||||
child.publicKey = ec.publicKeyCreate(key, true);
|
||||
|
||||
HD.cache.set(id, child);
|
||||
if (cache)
|
||||
cache.set(id, child);
|
||||
|
||||
return child;
|
||||
};
|
||||
|
|
@ -270,13 +280,13 @@ HDPrivateKey.prototype.getID = function getID(index) {
|
|||
* @throws Error if key is not a master key.
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex) {
|
||||
HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex, cache) {
|
||||
assert(utils.isNumber(accountIndex), 'Account index must be a number.');
|
||||
assert(this.isMaster(), 'Cannot derive account index.');
|
||||
return this
|
||||
.derive(44, true)
|
||||
.derive(this.network.keyPrefix.coinType, true)
|
||||
.derive(accountIndex, true);
|
||||
.derive(44, true, cache)
|
||||
.derive(this.network.keyPrefix.coinType, true, cache)
|
||||
.derive(accountIndex, true, cache);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -284,9 +294,9 @@ HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex)
|
|||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45() {
|
||||
HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45(cache) {
|
||||
assert(this.isMaster(), 'Cannot derive purpose 45.');
|
||||
return this.derive(45, true);
|
||||
return this.derive(45, true, cache);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -395,13 +405,13 @@ HDPrivateKey.isValidPath = function isValidPath(path) {
|
|||
* @throws Error if `path` is not a valid path.
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.derivePath = function derivePath(path) {
|
||||
HDPrivateKey.prototype.derivePath = function derivePath(path, cache) {
|
||||
var indexes = HD.parsePath(path, constants.hd.MAX_INDEX);
|
||||
var key = this;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < indexes.length; i++)
|
||||
key = key.derive(indexes[i]);
|
||||
key = key.derive(indexes[i], cache);
|
||||
|
||||
return key;
|
||||
};
|
||||
|
|
@ -490,7 +500,7 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
|
|||
if (!ec.privateKeyVerify(left))
|
||||
throw new Error('Master private key is invalid.');
|
||||
|
||||
this.network = bcoin.network.get(network);
|
||||
this.network = Network.get(network);
|
||||
this.depth = 0;
|
||||
this.parentFingerPrint = new Buffer([0, 0, 0, 0]);
|
||||
this.childIndex = 0;
|
||||
|
|
@ -549,7 +559,7 @@ HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
|||
HDPrivateKey.prototype.fromKey = function fromKey(key, entropy, network) {
|
||||
assert(Buffer.isBuffer(key) && key.length === 32);
|
||||
assert(Buffer.isBuffer(entropy) && entropy.length === 32);
|
||||
this.network = bcoin.network.get(network);
|
||||
this.network = Network.get(network);
|
||||
this.depth = 0;
|
||||
this.parentFingerPrint = new Buffer([0, 0, 0, 0]);
|
||||
this.childIndex = 0;
|
||||
|
|
@ -624,7 +634,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
|||
assert(i < networks.types.length, 'Network not found.');
|
||||
|
||||
this.publicKey = ec.publicKeyCreate(this.privateKey, true);
|
||||
this.network = bcoin.network.get(type);
|
||||
this.network = Network.get(type);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -651,7 +661,7 @@ HDPrivateKey.prototype.toRaw = function toRaw(network, writer) {
|
|||
if (!network)
|
||||
network = this.network;
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
network = Network.get(network);
|
||||
|
||||
p.writeU32BE(network.keyPrefix.xprivkey);
|
||||
p.writeU8(this.depth);
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var ec = require('../crypto/ec');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var networks = bcoin.networks;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var networks = require('../protocol/networks');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
|
|
@ -47,7 +47,7 @@ function HDPublicKey(options) {
|
|||
if (!(this instanceof HDPublicKey))
|
||||
return new HDPublicKey(options);
|
||||
|
||||
this.network = bcoin.network.get();
|
||||
this.network = Network.primary;
|
||||
this.depth = 0;
|
||||
this.parentFingerPrint = FINGER_PRINT;
|
||||
this.childIndex = 0;
|
||||
|
|
@ -80,7 +80,7 @@ HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
|||
assert(Buffer.isBuffer(options.publicKey));
|
||||
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.network = Network.get(options.network);
|
||||
|
||||
this.depth = options.depth;
|
||||
this.parentFingerPrint = options.parentFingerPrint;
|
||||
|
|
@ -140,11 +140,19 @@ HDPublicKey.prototype.destroy = function destroy() {
|
|||
* @throws on `hardened`
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.derive = function derive(index, hardened) {
|
||||
HDPublicKey.prototype.derive = function derive(index, hardened, cache) {
|
||||
var p, id, data, hash, left, right, key, child;
|
||||
|
||||
if (typeof hardened !== 'boolean') {
|
||||
cache = hardened;
|
||||
hardened = false;
|
||||
}
|
||||
|
||||
if (!cache)
|
||||
cache = HD.cache;
|
||||
|
||||
if (typeof index === 'string')
|
||||
return this.derivePath(index);
|
||||
return this.derivePath(index, cache);
|
||||
|
||||
if (index >= constants.hd.HARDENED || hardened)
|
||||
throw new Error('Index out of range.');
|
||||
|
|
@ -155,11 +163,12 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||
if (this.depth >= 0xff)
|
||||
throw new Error('Depth too high.');
|
||||
|
||||
id = this.getID(index);
|
||||
child = HD.cache.get(id);
|
||||
|
||||
if (child)
|
||||
return child;
|
||||
if (cache) {
|
||||
id = this.getID(index);
|
||||
child = cache.get(id);
|
||||
if (child)
|
||||
return child;
|
||||
}
|
||||
|
||||
p = new BufferWriter();
|
||||
p.writeBytes(this.publicKey);
|
||||
|
|
@ -173,7 +182,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||
try {
|
||||
key = ec.publicKeyTweakAdd(this.publicKey, left, true);
|
||||
} catch (e) {
|
||||
return this.derive(index + 1);
|
||||
return this.derive(index + 1, cache);
|
||||
}
|
||||
|
||||
if (!this.fingerPrint)
|
||||
|
|
@ -187,7 +196,8 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||
child.chainCode = right;
|
||||
child.publicKey = key;
|
||||
|
||||
HD.cache.set(id, child);
|
||||
if (cache)
|
||||
cache.set(id, child);
|
||||
|
||||
return child;
|
||||
};
|
||||
|
|
@ -288,13 +298,13 @@ HDPublicKey.isValidPath = function isValidPath(path) {
|
|||
* @throws Error if hardened.
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.derivePath = function derivePath(path) {
|
||||
HDPublicKey.prototype.derivePath = function derivePath(path, cache) {
|
||||
var indexes = HD.parsePath(path, constants.hd.HARDENED);
|
||||
var key = this;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < indexes.length; i++)
|
||||
key = key.derive(indexes[i]);
|
||||
key = key.derive(indexes[i], cache);
|
||||
|
||||
return key;
|
||||
};
|
||||
|
|
@ -475,7 +485,7 @@ HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
|||
|
||||
assert(i < networks.types.length, 'Network not found.');
|
||||
|
||||
this.network = bcoin.network.get(type);
|
||||
this.network = Network.get(type);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -502,7 +512,7 @@ HDPublicKey.prototype.toRaw = function toRaw(network, writer) {
|
|||
if (!network)
|
||||
network = this.network;
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
network = Network.get(network);
|
||||
|
||||
p.writeU32BE(network.keyPrefix.xpubkey);
|
||||
p.writeU8(this.depth);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
var AsyncObject = require('../utils/async');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
|
||||
/**
|
||||
* HTTPBase
|
||||
|
|
@ -162,7 +162,7 @@ HTTPBase.prototype._initRouter = function _initRouter() {
|
|||
// Avoid stack overflows
|
||||
utils.nextTick(function() {
|
||||
try {
|
||||
callback(req, res, next, _send);
|
||||
callback.call(route.ctx, req, res, _send, next);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
|
|
@ -208,28 +208,36 @@ HTTPBase.prototype._initIO = function _initIO() {
|
|||
/**
|
||||
* Open the server.
|
||||
* @alias HTTPBase#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPBase.prototype._open = function open(callback) {
|
||||
HTTPBase.prototype._open = function open() {
|
||||
assert(typeof this.options.port === 'number', 'Port required.');
|
||||
this.listen(this.options.port, this.options.host, callback);
|
||||
return this.listen(this.options.port, this.options.host);
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the server.
|
||||
* @alias HTTPBase#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPBase.prototype._close = function close(callback) {
|
||||
if (this.io) {
|
||||
this.server.once('close', callback);
|
||||
this.io.close();
|
||||
return;
|
||||
}
|
||||
var self = this;
|
||||
|
||||
this.server.close(callback);
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (self.io) {
|
||||
self.server.once('close', resolve);
|
||||
self.io.close();
|
||||
return;
|
||||
}
|
||||
|
||||
self.server.close(function(err) {
|
||||
if (err)
|
||||
return reject(err);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -237,7 +245,7 @@ HTTPBase.prototype._close = function close(callback) {
|
|||
* @param {HTTPRequest} req
|
||||
* @param {HTTPResponse} res
|
||||
* @param {Function} _send
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
|
@ -256,11 +264,11 @@ HTTPBase.prototype._handle = function _handle(req, res, _send, callback) {
|
|||
handler = self.stack[i++];
|
||||
|
||||
utils.nextTick(function() {
|
||||
if (handler.path && req.pathname.indexOf(handler.path) === -1)
|
||||
if (handler.path && req.pathname.indexOf(handler.path) !== 0)
|
||||
return next();
|
||||
|
||||
try {
|
||||
handler.callback(req, res, next, _send);
|
||||
handler.callback.call(handler.ctx, req, res, _send, next);
|
||||
} catch (e) {
|
||||
next(e);
|
||||
}
|
||||
|
|
@ -283,7 +291,7 @@ HTTPBase.prototype._handle = function _handle(req, res, _send, callback) {
|
|||
* @param {RouteCallback} callback
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.use = function use(path, callback) {
|
||||
HTTPBase.prototype.use = function use(path, callback, ctx) {
|
||||
if (!callback) {
|
||||
callback = path;
|
||||
path = null;
|
||||
|
|
@ -291,12 +299,12 @@ HTTPBase.prototype.use = function use(path, callback) {
|
|||
|
||||
if (Array.isArray(path)) {
|
||||
path.forEach(function(path) {
|
||||
this.use(path, callback);
|
||||
this.use(path, callback, ctx);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
|
||||
this.stack.push({ path: path, callback: callback });
|
||||
this.stack.push({ ctx: ctx, path: path, callback: callback });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -305,14 +313,14 @@ HTTPBase.prototype.use = function use(path, callback) {
|
|||
* @param {RouteCallback} callback
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.get = function get(path, callback) {
|
||||
HTTPBase.prototype.get = function get(path, callback, ctx) {
|
||||
if (Array.isArray(path)) {
|
||||
path.forEach(function(path) {
|
||||
this.get(path, callback);
|
||||
this.get(path, callback, ctx);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
this.routes.get.push({ path: path, callback: callback });
|
||||
this.routes.get.push({ ctx: ctx, path: path, callback: callback });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -321,14 +329,14 @@ HTTPBase.prototype.get = function get(path, callback) {
|
|||
* @param {RouteCallback} callback
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.post = function post(path, callback) {
|
||||
HTTPBase.prototype.post = function post(path, callback, ctx) {
|
||||
if (Array.isArray(path)) {
|
||||
path.forEach(function(path) {
|
||||
this.post(path, callback);
|
||||
this.post(path, callback, ctx);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
this.routes.post.push({ path: path, callback: callback });
|
||||
this.routes.post.push({ ctx: ctx, path: path, callback: callback });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -337,14 +345,14 @@ HTTPBase.prototype.post = function post(path, callback) {
|
|||
* @param {RouteCallback} callback
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.put = function put(path, callback) {
|
||||
HTTPBase.prototype.put = function put(path, callback, ctx) {
|
||||
if (Array.isArray(path)) {
|
||||
path.forEach(function(path) {
|
||||
this.put(path, callback);
|
||||
this.put(path, callback, ctx);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
this.routes.put.push({ path: path, callback: callback });
|
||||
this.routes.put.push({ ctx: ctx, path: path, callback: callback });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -353,14 +361,14 @@ HTTPBase.prototype.put = function put(path, callback) {
|
|||
* @param {RouteCallback} callback
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.del = function del(path, callback) {
|
||||
HTTPBase.prototype.del = function del(path, callback, ctx) {
|
||||
if (Array.isArray(path)) {
|
||||
path.forEach(function(path) {
|
||||
this.del(path, callback);
|
||||
this.del(path, callback, ctx);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
this.routes.del.push({ path: path, callback: callback });
|
||||
this.routes.del.push({ ctx: ctx, path: path, callback: callback });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -376,26 +384,24 @@ HTTPBase.prototype.address = function address() {
|
|||
* Listen on port and host.
|
||||
* @param {Number} port
|
||||
* @param {String?} host
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.listen = function listen(port, host, callback) {
|
||||
HTTPBase.prototype.listen = function listen(port, host) {
|
||||
var self = this;
|
||||
var addr;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var addr;
|
||||
|
||||
this.server.listen(port, host, function(err) {
|
||||
if (err) {
|
||||
if (callback)
|
||||
return callback(err);
|
||||
throw err;
|
||||
}
|
||||
self.server.listen(port, host, function(err) {
|
||||
if (err)
|
||||
return reject(err);
|
||||
|
||||
addr = self.address();
|
||||
addr = self.address();
|
||||
|
||||
self.emit('listening', addr);
|
||||
self.emit('listening', addr);
|
||||
|
||||
if (callback)
|
||||
callback(null, addr);
|
||||
resolve(addr);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ var Network = require('../protocol/network');
|
|||
var AsyncObject = require('../utils/async');
|
||||
var RPCClient = require('./rpcclient');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var request = require('./request');
|
||||
var co = require('../utils/co');
|
||||
var assert = require('assert');
|
||||
var request = require('./request').promise;
|
||||
|
||||
/**
|
||||
* BCoin HTTP client.
|
||||
|
|
@ -44,7 +45,7 @@ function HTTPClient(options) {
|
|||
this.rpc = new RPCClient(options);
|
||||
|
||||
// Open automatically.
|
||||
this.open();
|
||||
// this.open();
|
||||
}
|
||||
|
||||
utils.inherits(HTTPClient, AsyncObject);
|
||||
|
|
@ -52,10 +53,10 @@ utils.inherits(HTTPClient, AsyncObject);
|
|||
/**
|
||||
* Open the client, wait for socket to connect.
|
||||
* @alias HTTPClient#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._open = function _open(callback) {
|
||||
HTTPClient.prototype._open = co(function* _open() {
|
||||
var self = this;
|
||||
var IOClient;
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ HTTPClient.prototype._open = function _open(callback) {
|
|||
}
|
||||
|
||||
if (!IOClient)
|
||||
return callback();
|
||||
return;
|
||||
|
||||
this.socket = new IOClient(this.uri, {
|
||||
transports: ['websocket'],
|
||||
|
|
@ -115,11 +116,24 @@ HTTPClient.prototype._open = function _open(callback) {
|
|||
});
|
||||
});
|
||||
|
||||
this.socket.on('connect', function() {
|
||||
yield this._onConnect();
|
||||
yield this._sendAuth();
|
||||
});
|
||||
|
||||
HTTPClient.prototype._onConnect = function _onConnect() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.socket.once('connect', resolve);
|
||||
});
|
||||
};
|
||||
|
||||
HTTPClient.prototype._sendAuth = function _sendAuth() {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.socket.emit('auth', self.apiKey, function(err) {
|
||||
if (err)
|
||||
return callback(new Error(err.error));
|
||||
callback();
|
||||
return reject(new Error(err.error));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -127,17 +141,17 @@ HTTPClient.prototype._open = function _open(callback) {
|
|||
/**
|
||||
* Close the client, wait for the socket to close.
|
||||
* @alias HTTPClient#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._close = function close(callback) {
|
||||
HTTPClient.prototype._close = function close() {
|
||||
if (!this.socket)
|
||||
return utils.nextTick(callback);
|
||||
return Promise.resolve(null);
|
||||
|
||||
this.socket.disconnect();
|
||||
this.socket = null;
|
||||
|
||||
utils.nextTick(callback);
|
||||
return Promise.resolve(null);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -146,17 +160,11 @@ HTTPClient.prototype._close = function close(callback) {
|
|||
* @param {String} method
|
||||
* @param {String} endpoint - Path.
|
||||
* @param {Object} json - Body or query depending on method.
|
||||
* @param {Function} callback - Returns [Error, Object?].
|
||||
* @returns {Promise} - Returns Object?.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._request = function _request(method, endpoint, json, callback) {
|
||||
var self = this;
|
||||
var query, network, height;
|
||||
|
||||
if (!callback) {
|
||||
callback = json;
|
||||
json = null;
|
||||
}
|
||||
HTTPClient.prototype._request = co(function* _request(method, endpoint, json) {
|
||||
var query, network, height, res;
|
||||
|
||||
if (this.token) {
|
||||
if (!json)
|
||||
|
|
@ -169,7 +177,7 @@ HTTPClient.prototype._request = function _request(method, endpoint, json, callba
|
|||
json = null;
|
||||
}
|
||||
|
||||
request({
|
||||
res = yield request({
|
||||
method: method,
|
||||
uri: this.uri + endpoint,
|
||||
query: query,
|
||||
|
|
@ -179,50 +187,43 @@ HTTPClient.prototype._request = function _request(method, endpoint, json, callba
|
|||
password: this.apiKey || ''
|
||||
},
|
||||
expect: 'json'
|
||||
}, function(err, res, body) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
network = res.headers['x-bcoin-network'];
|
||||
|
||||
if (network !== self.network.type)
|
||||
return callback(new Error('Wrong network.'));
|
||||
|
||||
height = +res.headers['x-bcoin-height'];
|
||||
|
||||
if (utils.isNumber(height))
|
||||
self.network.updateHeight(height);
|
||||
|
||||
if (res.statusCode === 404)
|
||||
return callback();
|
||||
|
||||
if (!body)
|
||||
return callback(new Error('No body.'));
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
if (body.error)
|
||||
return callback(new Error(body.error));
|
||||
return callback(new Error('Status code: ' + res.statusCode));
|
||||
}
|
||||
|
||||
try {
|
||||
return callback(null, body);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
network = res.headers['x-bcoin-network'];
|
||||
|
||||
if (network !== this.network.type)
|
||||
throw new Error('Wrong network.');
|
||||
|
||||
height = +res.headers['x-bcoin-height'];
|
||||
|
||||
if (utils.isNumber(height))
|
||||
this.network.updateHeight(height);
|
||||
|
||||
if (res.statusCode === 404)
|
||||
return;
|
||||
|
||||
if (!res.body)
|
||||
throw new Error('No body.');
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
if (res.body.error)
|
||||
throw new Error(res.body.error);
|
||||
throw new Error('Status code: ' + res.statusCode);
|
||||
}
|
||||
|
||||
return res.body;
|
||||
});
|
||||
|
||||
/**
|
||||
* Make a GET http request to endpoint.
|
||||
* @private
|
||||
* @param {String} endpoint - Path.
|
||||
* @param {Object} json - Querystring.
|
||||
* @param {Function} callback - Returns [Error, Object?].
|
||||
* @returns {Promise} - Returns Object?.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._get = function _get(endpoint, json, callback) {
|
||||
this._request('get', endpoint, json, callback);
|
||||
HTTPClient.prototype._get = function _get(endpoint, json) {
|
||||
return this._request('get', endpoint, json);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -230,11 +231,11 @@ HTTPClient.prototype._get = function _get(endpoint, json, callback) {
|
|||
* @private
|
||||
* @param {String} endpoint - Path.
|
||||
* @param {Object} json - Body.
|
||||
* @param {Function} callback - Returns [Error, Object?].
|
||||
* @returns {Promise} - Returns Object?.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._post = function _post(endpoint, json, callback) {
|
||||
this._request('post', endpoint, json, callback);
|
||||
HTTPClient.prototype._post = function _post(endpoint, json) {
|
||||
return this._request('post', endpoint, json);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -242,11 +243,11 @@ HTTPClient.prototype._post = function _post(endpoint, json, callback) {
|
|||
* @private
|
||||
* @param {String} endpoint - Path.
|
||||
* @param {Object} json - Body.
|
||||
* @param {Function} callback - Returns [Error, Object?].
|
||||
* @returns {Promise} - Returns Object?.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._put = function _put(endpoint, json, callback) {
|
||||
this._request('put', endpoint, json, callback);
|
||||
HTTPClient.prototype._put = function _put(endpoint, json) {
|
||||
return this._request('put', endpoint, json);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -254,41 +255,41 @@ HTTPClient.prototype._put = function _put(endpoint, json, callback) {
|
|||
* @private
|
||||
* @param {String} endpoint - Path.
|
||||
* @param {Object} json - Body.
|
||||
* @param {Function} callback - Returns [Error, Object?].
|
||||
* @returns {Promise} - Returns Object?.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._del = function _del(endpoint, json, callback) {
|
||||
this._request('delete', endpoint, json, callback);
|
||||
HTTPClient.prototype._del = function _del(endpoint, json) {
|
||||
return this._request('delete', endpoint, json);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a mempool snapshot.
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getMempool = function getMempool(callback) {
|
||||
this._get('/mempool', callback);
|
||||
HTTPClient.prototype.getMempool = function getMempool() {
|
||||
return this._get('/mempool');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get some info about the server (network and version).
|
||||
* @param {Function} callback - Returns [Error, Object].
|
||||
* @returns {Promise} - Returns Object.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getInfo = function getInfo(callback) {
|
||||
this._get('/', callback);
|
||||
HTTPClient.prototype.getInfo = function getInfo() {
|
||||
return this._get('/');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get coins that pertain to an address from the mempool or chain database.
|
||||
* Takes into account spent coins in the mempool.
|
||||
* @param {Base58Address|Base58Address[]} addresses
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}[]].
|
||||
* @returns {Promise} - Returns {@link Coin}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getCoinsByAddress = function getCoinsByAddress(address, callback) {
|
||||
HTTPClient.prototype.getCoinsByAddress = function getCoinsByAddress(address) {
|
||||
var body = { address: address };
|
||||
this._post('/coin/address', body, callback);
|
||||
return this._post('/coin/address', body);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -296,56 +297,55 @@ HTTPClient.prototype.getCoinsByAddress = function getCoinsByAddress(address, cal
|
|||
* Takes into account spent coins in the mempool.
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}].
|
||||
* @returns {Promise} - Returns {@link Coin}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
this._get('/coin/' + hash + '/' + index, callback);
|
||||
HTTPClient.prototype.getCoin = function getCoin(hash, index) {
|
||||
return this._get('/coin/' + hash + '/' + index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve transactions pertaining to an
|
||||
* address from the mempool or chain database.
|
||||
* @param {Base58Address|Base58Address[]} addresses
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getTXByAddress = function getTXByAddress(address, callback) {
|
||||
HTTPClient.prototype.getTXByAddress = function getTXByAddress(address) {
|
||||
var body = { address: address };
|
||||
|
||||
this._post('/tx/address', body, callback);
|
||||
return this._post('/tx/address', body);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a transaction from the mempool or chain database.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getTX = function getTX(hash, callback) {
|
||||
this._get('/tx/' + hash, callback);
|
||||
HTTPClient.prototype.getTX = function getTX(hash) {
|
||||
return this._get('/tx/' + hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a block from the chain database.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, {@link Block}].
|
||||
* @returns {Promise} - Returns {@link Block}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getBlock = function getBlock(hash, callback) {
|
||||
this._get('/block/' + hash, callback);
|
||||
HTTPClient.prototype.getBlock = function getBlock(hash) {
|
||||
return this._get('/block/' + hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a transaction to the mempool and broadcast it.
|
||||
* @param {TX} tx
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.broadcast = function broadcast(tx, callback) {
|
||||
HTTPClient.prototype.broadcast = function broadcast(tx) {
|
||||
var body = { tx: toHex(tx) };
|
||||
|
||||
this._post('/broadcast', body, callback);
|
||||
return this._post('/broadcast', body);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -353,11 +353,19 @@ HTTPClient.prototype.broadcast = function broadcast(tx, callback) {
|
|||
* @param {WalletID} id
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.join = function join(id, token, callback) {
|
||||
if (!this.socket)
|
||||
return callback();
|
||||
HTTPClient.prototype.join = function join(id, token) {
|
||||
var self = this;
|
||||
|
||||
this.socket.emit('wallet join', id, token, callback);
|
||||
if (!this.socket)
|
||||
return Promise.resolve(null);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.socket.emit('wallet join', id, token, function(err) {
|
||||
if (err)
|
||||
return reject(new Error(err.error));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -365,145 +373,113 @@ HTTPClient.prototype.join = function join(id, token, callback) {
|
|||
* @param {WalletID} id
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.leave = function leave(id, callback) {
|
||||
if (!this.socket)
|
||||
return callback();
|
||||
HTTPClient.prototype.leave = function leave(id) {
|
||||
var self = this;
|
||||
|
||||
this.socket.emit('wallet leave', id, callback);
|
||||
if (!this.socket)
|
||||
return Promise.resolve(null);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.socket.emit('wallet leave', id, function(err) {
|
||||
if (err)
|
||||
return reject(new Error(err.error));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for events on all wallets.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.all = function all(token, callback) {
|
||||
this.join('!all', token, callback);
|
||||
HTTPClient.prototype.all = function all(token) {
|
||||
return this.join('!all', token);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlisten for events on all wallets.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.none = function none(callback) {
|
||||
this.leave('!all', callback);
|
||||
HTTPClient.prototype.none = function none() {
|
||||
return this.leave('!all');
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the raw wallet JSON (will create wallet if it does not exist).
|
||||
* @private
|
||||
* @param {Object} options - See {@link Wallet}.
|
||||
* @param {Function} callback - Returns [Error, Object].
|
||||
* @returns {Promise} - Returns Object.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createWallet = function createWallet(options, callback) {
|
||||
this._post('/wallet', options, callback);
|
||||
HTTPClient.prototype.createWallet = function createWallet(options) {
|
||||
return this._post('/wallet', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the raw wallet JSON.
|
||||
* @private
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, Object].
|
||||
* @returns {Promise} - Returns Object.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWallet = function getWallet(id, callback) {
|
||||
this._get('/wallet/' + id, callback);
|
||||
HTTPClient.prototype.getWallet = function getWallet(id) {
|
||||
return this._get('/wallet/' + id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get wallet transaction history.
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getHistory = function getHistory(id, account, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof account === 'function') {
|
||||
callback = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account };
|
||||
|
||||
this._get('/wallet/' + id + '/tx/history', options, callback);
|
||||
HTTPClient.prototype.getHistory = function getHistory(id, account) {
|
||||
var options = { account: account };
|
||||
return this._get('/wallet/' + id + '/tx/history', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get wallet coins.
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}[]].
|
||||
* @returns {Promise} - Returns {@link Coin}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getCoins = function getCoins(id, account, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof account === 'function') {
|
||||
callback = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account };
|
||||
|
||||
this._get('/wallet/' + id + '/coin', options, callback);
|
||||
HTTPClient.prototype.getCoins = function getCoins(id, account) {
|
||||
var options = { account: account };
|
||||
return this._get('/wallet/' + id + '/coin', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all unconfirmed transactions.
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getUnconfirmed = function getUnconfirmed(id, account, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof account === 'function') {
|
||||
callback = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account };
|
||||
|
||||
this._get('/wallet/' + id + '/tx/unconfirmed', options, callback);
|
||||
HTTPClient.prototype.getUnconfirmed = function getUnconfirmed(id, account) {
|
||||
var options = { account: account };
|
||||
return this._get('/wallet/' + id + '/tx/unconfirmed', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate wallet balance.
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, {@link Balance}].
|
||||
* @returns {Promise} - Returns {@link Balance}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getBalance = function getBalance(id, account, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof account === 'function') {
|
||||
callback = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account };
|
||||
|
||||
this._get('/wallet/' + id + '/balance', options, callback);
|
||||
HTTPClient.prototype.getBalance = function getBalance(id, account) {
|
||||
var options = { account: account };
|
||||
return this._get('/wallet/' + id + '/balance', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get last N wallet transactions.
|
||||
* @param {WalletID} id
|
||||
* @param {Number} limit - Max number of transactions.
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getLast = function getLast(id, account, limit, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof account === 'function') {
|
||||
callback = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account, limit: limit };
|
||||
|
||||
this._get('/wallet/' + id + '/tx/last', options, callback);
|
||||
HTTPClient.prototype.getLast = function getLast(id, account, limit) {
|
||||
var options = { account: account, limit: limit };
|
||||
return this._get('/wallet/' + id + '/tx/last', options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -514,16 +490,10 @@ HTTPClient.prototype.getLast = function getLast(id, account, limit, callback) {
|
|||
* @param {Number} options.end - End time.
|
||||
* @param {Number?} options.limit - Max number of records.
|
||||
* @param {Boolean?} options.reverse - Reverse order.
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getRange = function getRange(id, account, options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
HTTPClient.prototype.getRange = function getRange(id, account, options) {
|
||||
options = {
|
||||
account: account,
|
||||
start: options.start,
|
||||
|
|
@ -531,8 +501,7 @@ HTTPClient.prototype.getRange = function getRange(id, account, options, callback
|
|||
limit: options.limit,
|
||||
reverse: options.reverse
|
||||
};
|
||||
|
||||
this._get('/wallet/' + id + '/tx/range', options, callback);
|
||||
return this._get('/wallet/' + id + '/tx/range', options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -540,21 +509,12 @@ HTTPClient.prototype.getRange = function getRange(id, account, options, callback
|
|||
* is available in the wallet history).
|
||||
* @param {WalletID} id
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWalletTX = function getWalletTX(id, account, hash, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof hash === 'function') {
|
||||
callback = hash;
|
||||
hash = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account };
|
||||
|
||||
this._get('/wallet/' + id + '/tx/' + hash, options, callback);
|
||||
HTTPClient.prototype.getWalletTX = function getWalletTX(id, account, hash) {
|
||||
var options = { account: account };
|
||||
return this._get('/wallet/' + id + '/tx/' + hash, options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -563,24 +523,13 @@ HTTPClient.prototype.getWalletTX = function getWalletTX(id, account, hash, callb
|
|||
* @param {WalletID} id
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}[]].
|
||||
* @returns {Promise} - Returns {@link Coin}[].
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWalletCoin = function getWalletCoin(id, account, hash, index, callback) {
|
||||
var options, path;
|
||||
|
||||
if (typeof hash === 'function') {
|
||||
callback = index;
|
||||
index = hash;
|
||||
hash = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
options = { account: account };
|
||||
|
||||
path = '/wallet/' + id + '/coin/' + hash + '/' + index;
|
||||
|
||||
this._get(path, options, callback);
|
||||
HTTPClient.prototype.getWalletCoin = function getWalletCoin(id, account, hash, index) {
|
||||
var path = '/wallet/' + id + '/coin/' + hash + '/' + index;
|
||||
var options = { account: account };
|
||||
return this._get(path, options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -589,10 +538,10 @@ HTTPClient.prototype.getWalletCoin = function getWalletCoin(id, account, hash, i
|
|||
* @param {Object} options
|
||||
* @param {Base58Address} options.address
|
||||
* @param {Amount} options.value
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.send = function send(id, options, callback) {
|
||||
HTTPClient.prototype.send = function send(id, options) {
|
||||
options = utils.merge({}, options);
|
||||
options.outputs = options.outputs || [];
|
||||
|
||||
|
|
@ -607,54 +556,41 @@ HTTPClient.prototype.send = function send(id, options, callback) {
|
|||
};
|
||||
});
|
||||
|
||||
this._post('/wallet/' + id + '/send', options, callback);
|
||||
return this._post('/wallet/' + id + '/send', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a new token.
|
||||
* @param {(String|Buffer)?} passphrase
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.retoken = function retoken(id, passphrase, callback) {
|
||||
var options;
|
||||
|
||||
if (typeof passphrase === 'function') {
|
||||
callback = passphrase;
|
||||
passphrase = null;
|
||||
}
|
||||
|
||||
options = { passphrase: passphrase };
|
||||
|
||||
this._post('/wallet/' + id + '/retoken', options, function(err, body) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, body.token);
|
||||
});
|
||||
};
|
||||
HTTPClient.prototype.retoken = co(function* retoken(id, passphrase) {
|
||||
var options = { passphrase: passphrase };
|
||||
var body = yield this._post('/wallet/' + id + '/retoken', options);
|
||||
return body.token;
|
||||
});
|
||||
|
||||
/**
|
||||
* Change or set master key's passphrase.
|
||||
* @param {(String|Buffer)?} old
|
||||
* @param {String|Buffer} new_
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.setPassphrase = function setPassphrase(id, old, new_, callback) {
|
||||
HTTPClient.prototype.setPassphrase = function setPassphrase(id, old, new_) {
|
||||
var options = { old: old, passphrase: new_ };
|
||||
|
||||
this._post('/wallet/' + id + '/passphrase', options, callback);
|
||||
return this._post('/wallet/' + id + '/passphrase', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a transaction, fill.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createTX = function createTX(id, options, callback) {
|
||||
HTTPClient.prototype.createTX = function createTX(id, options) {
|
||||
options = utils.merge({}, options);
|
||||
|
||||
if (options.rate)
|
||||
|
|
@ -668,7 +604,7 @@ HTTPClient.prototype.createTX = function createTX(id, options, callback) {
|
|||
};
|
||||
});
|
||||
|
||||
this._post('/wallet/' + id + '/create', options, callback);
|
||||
return this._post('/wallet/' + id + '/create', options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -676,61 +612,46 @@ HTTPClient.prototype.createTX = function createTX(id, options, callback) {
|
|||
* @param {WalletID} id
|
||||
* @param {TX} tx
|
||||
* @param {Object} options
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.sign = function sign(id, tx, options, callback) {
|
||||
HTTPClient.prototype.sign = function sign(id, tx, options) {
|
||||
var body;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
body = utils.merge({}, options);
|
||||
body.tx = toHex(tx);
|
||||
|
||||
this._post('/wallet/' + id + '/sign', body, callback);
|
||||
return this._post('/wallet/' + id + '/sign', body);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill a transaction with coins.
|
||||
* @param {TX} tx
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.fillCoins = function fillCoins(id, tx, callback) {
|
||||
HTTPClient.prototype.fillCoins = function fillCoins(id, tx) {
|
||||
var body = { tx: toHex(tx) };
|
||||
this._post('/wallet/' + id + '/fill', body, callback);
|
||||
return this._post('/wallet/' + id + '/fill', body);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {WalletID} id
|
||||
* @param {Number} now - Current time.
|
||||
* @param {Number} age - Age delta (delete transactions older than `now - age`).
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.zap = function zap(id, account, age, callback) {
|
||||
var body;
|
||||
|
||||
if (typeof age === 'function') {
|
||||
callback = age;
|
||||
age = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
body = {
|
||||
HTTPClient.prototype.zap = function zap(id, account, age) {
|
||||
var body = {
|
||||
account: account,
|
||||
age: age
|
||||
};
|
||||
|
||||
assert(utils.isNumber(age));
|
||||
|
||||
this._post('/wallet/' + id + '/zap', body, callback);
|
||||
return this._post('/wallet/' + id + '/zap', body);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -739,22 +660,16 @@ HTTPClient.prototype.zap = function zap(id, account, age, callback) {
|
|||
* @param {(String|Number)?} account
|
||||
* @param {HDPublicKey|Base58String} key - Account (bip44) or
|
||||
* Purpose (bip45) key (can be in base58 form).
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.addKey = function addKey(id, account, key, callback) {
|
||||
HTTPClient.prototype.addKey = function addKey(id, account, key) {
|
||||
var options;
|
||||
|
||||
if (typeof key === 'function') {
|
||||
callback = key;
|
||||
key = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
key = key.xpubkey || key;
|
||||
options = { account: account, key: key };
|
||||
|
||||
this._put('/wallet/' + id + '/key', options, callback);
|
||||
return this._put('/wallet/' + id + '/key', options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -763,62 +678,51 @@ HTTPClient.prototype.addKey = function addKey(id, account, key, callback) {
|
|||
* @param {(String|Number)?} account
|
||||
* @param {HDPublicKey|Base58String} key - Account (bip44) or Purpose
|
||||
* (bip45) key (can be in base58 form).
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.removeKey = function removeKey(id, account, key, callback) {
|
||||
HTTPClient.prototype.removeKey = function removeKey(id, account, key) {
|
||||
var options;
|
||||
|
||||
if (typeof key === 'function') {
|
||||
callback = key;
|
||||
key = account;
|
||||
account = null;
|
||||
}
|
||||
|
||||
key = key.xpubkey || key;
|
||||
options = { account: account, key: key };
|
||||
|
||||
this._del('/wallet/' + id + '/key', options, callback);
|
||||
return this._del('/wallet/' + id + '/key', options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get wallet accounts.
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, Array].
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getAccounts = function getAccounts(id, callback) {
|
||||
HTTPClient.prototype.getAccounts = function getAccounts(id) {
|
||||
var path = '/wallet/' + id + '/account';
|
||||
this._get(path, callback);
|
||||
return this._get(path);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get wallet account.
|
||||
* @param {WalletID} id
|
||||
* @param {String} account
|
||||
* @param {Function} callback - Returns [Error, Array].
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getAccount = function getAccount(id, account, callback) {
|
||||
HTTPClient.prototype.getAccount = function getAccount(id, account) {
|
||||
var path = '/wallet/' + id + '/account/' + account;
|
||||
this._get(path, callback);
|
||||
return this._get(path);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create account.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @param {Function} callback - Returns [Error, Array].
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createAccount = function createAccount(id, options, callback) {
|
||||
HTTPClient.prototype.createAccount = function createAccount(id, options) {
|
||||
var path;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
|
|
@ -827,24 +731,19 @@ HTTPClient.prototype.createAccount = function createAccount(id, options, callbac
|
|||
|
||||
path = '/wallet/' + id + '/account';
|
||||
|
||||
this._post(path, options, callback);
|
||||
return this._post(path, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create address.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @param {Function} callback - Returns [Error, Array].
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createAddress = function createAddress(id, options, callback) {
|
||||
HTTPClient.prototype.createAddress = function createAddress(id, options) {
|
||||
var path;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
|
|
@ -853,7 +752,28 @@ HTTPClient.prototype.createAddress = function createAddress(id, options, callbac
|
|||
|
||||
path = '/wallet/' + id + '/address';
|
||||
|
||||
this._post(path, options, callback);
|
||||
return this._post(path, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create address.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createNested = function createNested(id, options) {
|
||||
var path;
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
if (typeof options === 'string')
|
||||
options = { account: options };
|
||||
|
||||
path = '/wallet/' + id + '/nested';
|
||||
|
||||
return this._post(path, options);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -11,8 +11,12 @@ var utils = require('../utils/utils');
|
|||
|
||||
if (!utils.isBrowser) {
|
||||
exports.request = require('./request');
|
||||
exports.client = require('./client');
|
||||
exports.wallet = require('./wallet');
|
||||
exports.base = require('./base');
|
||||
exports.server = require('./server');
|
||||
exports.Client = require('./client');
|
||||
exports.RPCClient = require('./rpcclient');
|
||||
exports.Wallet = require('./wallet');
|
||||
exports.Base = require('./base');
|
||||
exports.RPC = require('./rpc');
|
||||
exports.Server = require('./server');
|
||||
} else {
|
||||
exports.RPC = require('./rpc');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
var Stream = require('stream').Stream;
|
||||
var assert = require('../utils/utils').assert;
|
||||
var assert = require('assert');
|
||||
|
||||
// Spoof by default
|
||||
var USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1)'
|
||||
|
|
@ -301,6 +301,17 @@ request._buffer = function(options, callback) {
|
|||
return stream;
|
||||
};
|
||||
|
||||
request.promise = function promise(options) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
request(options, function(err, res, body) {
|
||||
if (err)
|
||||
return reject(err);
|
||||
res.body = body;
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* ReqStream
|
||||
*/
|
||||
|
|
|
|||
3856
lib/http/rpc.js
3856
lib/http/rpc.js
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
var Network = require('../protocol/network');
|
||||
var request = require('./request');
|
||||
var co = require('../utils/co');
|
||||
|
||||
/**
|
||||
* BCoin RPC client.
|
||||
|
|
@ -40,11 +41,11 @@ function RPCClient(options) {
|
|||
* @private
|
||||
* @param {String} method - RPC method name.
|
||||
* @param {Array} params - RPC parameters.
|
||||
* @param {Function} callback - Returns [Error, Object?].
|
||||
* @returns {Promise} - Returns Object?.
|
||||
*/
|
||||
|
||||
RPCClient.prototype.call = function call(method, params, callback) {
|
||||
request({
|
||||
RPCClient.prototype.call = co(function* call(method, params) {
|
||||
var res = yield request.promise({
|
||||
method: 'POST',
|
||||
uri: this.uri,
|
||||
json: {
|
||||
|
|
@ -57,25 +58,22 @@ RPCClient.prototype.call = function call(method, params, callback) {
|
|||
password: this.apiKey || ''
|
||||
},
|
||||
expect: 'json'
|
||||
}, function(err, res, body) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!body)
|
||||
return callback();
|
||||
|
||||
if (res.statusCode === 400)
|
||||
return callback(null, body.result);
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
if (body.error)
|
||||
return callback(new Error(body.error.message));
|
||||
return callback(new Error('Status code: ' + res.statusCode));
|
||||
}
|
||||
|
||||
return callback(null, body.result);
|
||||
});
|
||||
};
|
||||
|
||||
if (!res.body)
|
||||
return;
|
||||
|
||||
if (res.statusCode === 400)
|
||||
return res.body.result;
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
if (res.body.error)
|
||||
throw new Error(res.body.error.message);
|
||||
throw new Error('Status code: ' + res.statusCode);
|
||||
}
|
||||
|
||||
return res.body.result;
|
||||
});
|
||||
|
||||
/*
|
||||
* Expose
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -11,6 +11,7 @@ var Network = require('../protocol/network');
|
|||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var Client = require('./client');
|
||||
|
||||
/**
|
||||
|
|
@ -85,11 +86,11 @@ HTTPWallet.prototype._init = function _init() {
|
|||
/**
|
||||
* Open the client and get a wallet.
|
||||
* @alias HTTPWallet#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.open = function open(options, callback) {
|
||||
var self = this;
|
||||
HTTPWallet.prototype.open = co(function* open(options) {
|
||||
var wallet;
|
||||
|
||||
this.id = options.id;
|
||||
|
||||
|
|
@ -100,159 +101,143 @@ HTTPWallet.prototype.open = function open(options, callback) {
|
|||
this.client.token = this.token;
|
||||
}
|
||||
|
||||
this.client.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
yield this.client.open();
|
||||
|
||||
self.client.getWallet(self.id, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.client.join(self.id, wallet.token, function(err) {
|
||||
if (err)
|
||||
return callback(new Error(err.error));
|
||||
callback(null, wallet);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
wallet = yield this.client.getWallet(this.id);
|
||||
|
||||
yield this.client.join(this.id, wallet.token);
|
||||
|
||||
return wallet;
|
||||
});
|
||||
|
||||
/**
|
||||
* Open the client and create a wallet.
|
||||
* @alias HTTPWallet#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.create = function create(options, callback) {
|
||||
var self = this;
|
||||
|
||||
this.client.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.client.createWallet(options, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.open({
|
||||
id: wallet.id,
|
||||
token: wallet.token
|
||||
}, callback);
|
||||
});
|
||||
HTTPWallet.prototype.create = co(function* create(options) {
|
||||
var wallet;
|
||||
yield this.client.open();
|
||||
wallet = yield this.client.createWallet(options);
|
||||
return yield this.open({
|
||||
id: wallet.id,
|
||||
token: wallet.token
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Close the client, wait for the socket to close.
|
||||
* @alias HTTPWallet#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.close = function close(callback) {
|
||||
this.client.close(callback);
|
||||
HTTPWallet.prototype.close = function close() {
|
||||
return this.client.close();
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getHistory
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getHistory = function getHistory(account, callback) {
|
||||
this.client.getHistory(this.id, account, callback);
|
||||
HTTPWallet.prototype.getHistory = function getHistory(account) {
|
||||
return this.client.getHistory(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getCoins
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getCoins = function getCoins(account, callback) {
|
||||
this.client.getCoins(this.id, account, callback);
|
||||
HTTPWallet.prototype.getCoins = function getCoins(account) {
|
||||
return this.client.getCoins(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getUnconfirmed
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getUnconfirmed = function getUnconfirmed(account, callback) {
|
||||
this.client.getUnconfirmed(this.id, account, callback);
|
||||
HTTPWallet.prototype.getUnconfirmed = function getUnconfirmed(account) {
|
||||
return this.client.getUnconfirmed(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getBalance
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getBalance = function getBalance(account, callback) {
|
||||
this.client.getBalance(this.id, account, callback);
|
||||
HTTPWallet.prototype.getBalance = function getBalance(account) {
|
||||
return this.client.getBalance(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getLast
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getLast = function getLast(account, limit, callback) {
|
||||
this.client.getLast(this.id, account, limit, callback);
|
||||
HTTPWallet.prototype.getLast = function getLast(account, limit) {
|
||||
return this.client.getLast(this.id, account, limit);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getRange
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getRange = function getRange(account, options, callback) {
|
||||
this.client.getRange(this.id, account, options, callback);
|
||||
HTTPWallet.prototype.getRange = function getRange(account, options) {
|
||||
return this.client.getRange(this.id, account, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getTX
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getTX = function getTX(account, hash, callback) {
|
||||
this.client.getWalletTX(this.id, account, hash, callback);
|
||||
HTTPWallet.prototype.getTX = function getTX(account, hash) {
|
||||
return this.client.getWalletTX(this.id, account, hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getCoin
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getCoin = function getCoin(account, hash, index, callback) {
|
||||
this.client.getWalletCoin(this.id, account, hash, index, callback);
|
||||
HTTPWallet.prototype.getCoin = function getCoin(account, hash, index) {
|
||||
return this.client.getWalletCoin(this.id, account, hash, index);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#zap
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.zap = function zap(account, age, callback) {
|
||||
this.client.zap(this.id, account, age, callback);
|
||||
HTTPWallet.prototype.zap = function zap(account, age) {
|
||||
return this.client.zap(this.id, account, age);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#createTX
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
this.client.createTX(this.id, options, outputs, callback);
|
||||
HTTPWallet.prototype.createTX = function createTX(options, outputs) {
|
||||
return this.client.createTX(this.id, options, outputs);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see HTTPClient#walletSend
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.send = function send(options, callback) {
|
||||
this.client.send(this.id, options, callback);
|
||||
HTTPWallet.prototype.send = function send(options) {
|
||||
return this.client.send(this.id, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#sign
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.sign = function sign(tx, options, callback) {
|
||||
this.client.sign(this.id, tx, options, callback);
|
||||
HTTPWallet.prototype.sign = function sign(tx, options) {
|
||||
return this.client.sign(this.id, tx, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#fillCoins
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.fillCoins = function fillCoins(tx, callback) {
|
||||
this.client.fillCoins(tx, callback);
|
||||
HTTPWallet.prototype.fillCoins = function fillCoins(tx) {
|
||||
return this.client.fillCoins(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -260,7 +245,7 @@ HTTPWallet.prototype.fillCoins = function fillCoins(tx, callback) {
|
|||
*/
|
||||
|
||||
HTTPWallet.prototype.getInfo = function getInfo(callback) {
|
||||
this.client.getWallet(this.id, callback);
|
||||
return this.client.getWallet(this.id);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -268,63 +253,61 @@ HTTPWallet.prototype.getInfo = function getInfo(callback) {
|
|||
*/
|
||||
|
||||
HTTPWallet.prototype.getAccounts = function getAccounts(callback) {
|
||||
this.client.getAccounts(this.id, callback);
|
||||
return this.client.getAccounts(this.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getAccount
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getAccount = function getAccount(account, callback) {
|
||||
this.client.getAccount(this.id, account, callback);
|
||||
HTTPWallet.prototype.getAccount = function getAccount(account) {
|
||||
return this.client.getAccount(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#createAccount
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.createAccount = function createAccount(options, callback) {
|
||||
this.client.createAccount(this.id, options, callback);
|
||||
HTTPWallet.prototype.createAccount = function createAccount(options) {
|
||||
return this.client.createAccount(this.id, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#createAddress
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.createAddress = function createAddress(account, callback) {
|
||||
this.client.createAddress(this.id, account, callback);
|
||||
HTTPWallet.prototype.createAddress = function createAddress(account) {
|
||||
return this.client.createAddress(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#createAddress
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.createNested = function createNested(account) {
|
||||
return this.client.createNested(this.id, account);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#setPassphrase
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) {
|
||||
this.client.setPassphrase(this.id, old, new_, callback);
|
||||
HTTPWallet.prototype.setPassphrase = function setPassphrase(old, new_) {
|
||||
return this.client.setPassphrase(this.id, old, new_);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#retoken
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.retoken = function retoken(passphrase, callback) {
|
||||
var self = this;
|
||||
HTTPWallet.prototype.retoken = co(function* retoken(passphrase) {
|
||||
var token = yield this.client.retoken(this.id, passphrase);
|
||||
|
||||
if (typeof passphrase === 'function') {
|
||||
callback = passphrase;
|
||||
passphrase = null;
|
||||
}
|
||||
this.token = token;
|
||||
this.client.token = token;
|
||||
|
||||
this.client.retoken(this.id, passphrase, function(err, token) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.token = token;
|
||||
self.client.token = token;
|
||||
|
||||
return callback(null, token);
|
||||
});
|
||||
};
|
||||
return token;
|
||||
});
|
||||
|
||||
/*
|
||||
* Expose
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = bcoin.utils;
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var constants = bcoin.constants;
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var global = bcoin.utils.global;
|
||||
var Logger = require('../node/logger');
|
||||
var Network = require('../protocol/network');
|
||||
var global = utils.global;
|
||||
var Float64Array = global.Float64Array || Array;
|
||||
var Int32Array = global.Int32Array || Array;
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ function ConfirmStats(buckets, maxConfirms, decay, type, logger) {
|
|||
if (!(this instanceof ConfirmStats))
|
||||
return new ConfirmStats(buckets, maxConfirms, decay, type, logger);
|
||||
|
||||
this.logger = logger || bcoin.defaultLogger;
|
||||
this.logger = logger || Logger.global;
|
||||
this.maxConfirms = maxConfirms;
|
||||
this.decay = decay;
|
||||
this.type = type;
|
||||
|
|
@ -399,8 +400,8 @@ function PolicyEstimator(minRelay, network, logger) {
|
|||
fee = [];
|
||||
priority = [];
|
||||
|
||||
this.network = bcoin.network.get(network);
|
||||
this.logger = logger || bcoin.defaultLogger;
|
||||
this.network = Network.get(network);
|
||||
this.logger = logger || Logger.global;
|
||||
|
||||
this.minTrackedFee = minRelay < MIN_FEERATE
|
||||
? MIN_FEERATE
|
||||
|
|
@ -776,7 +777,7 @@ PolicyEstimator.prototype.toRaw = function toRaw(writer) {
|
|||
|
||||
PolicyEstimator.fromRaw = function fromRaw(minRelay, data, logger) {
|
||||
var p = new BufferReader(data);
|
||||
var network = bcoin.network.fromMagic(p.readU32());
|
||||
var network = Network.fromMagic(p.readU32());
|
||||
var bestHeight = p.readU32();
|
||||
var estimator = new PolicyEstimator(minRelay, network, logger);
|
||||
var feeStats = ConfirmStats.fromRaw(p.readVarBytes(), 'FeeRate', logger);
|
||||
|
|
|
|||
5
lib/mempool/index.js
Normal file
5
lib/mempool/index.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
exports.Mempool = require('./mempool');
|
||||
exports.MempoolEntry = require('./mempoolentry');
|
||||
exports.Fees = require('./fees');
|
||||
File diff suppressed because it is too large
Load diff
191
lib/mempool/mempoolentry.js
Normal file
191
lib/mempool/mempoolentry.js
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*!
|
||||
* mempoolentry.js - mempool entry object for bcoin
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var TX = require('../primitives/tx');
|
||||
|
||||
/**
|
||||
* Represents a mempool entry.
|
||||
* @exports MempoolEntry
|
||||
* @constructor
|
||||
* @param {Object} options
|
||||
* @param {TX} options.tx - Transaction in mempool.
|
||||
* @param {Number} options.height - Entry height.
|
||||
* @param {Number} options.priority - Entry priority.
|
||||
* @param {Number} options.ts - Entry time.
|
||||
* @param {Amount} options.chainValue - Value of on-chain coins.
|
||||
* @param {Number} options.count - Number of descendants (includes tx).
|
||||
* @param {Number} options.size - TX and descendant modified size.
|
||||
* @param {Amount} options.fees - TX and descendant delta-applied fees.
|
||||
* @property {TX} tx
|
||||
* @property {Number} height
|
||||
* @property {Number} priority
|
||||
* @property {Number} ts
|
||||
* @property {Amount} chainValue
|
||||
* @property {Number} count
|
||||
* @property {Number} size
|
||||
* @property {Amount} fees
|
||||
*/
|
||||
|
||||
function MempoolEntry(options) {
|
||||
if (!(this instanceof MempoolEntry))
|
||||
return new MempoolEntry(options);
|
||||
|
||||
this.tx = null;
|
||||
this.height = -1;
|
||||
this.size = 0;
|
||||
this.priority = 0;
|
||||
this.fee = 0;
|
||||
this.ts = 0;
|
||||
|
||||
this.chainValue = 0;
|
||||
this.count = 0;
|
||||
this.sizes = 0;
|
||||
this.fees = 0;
|
||||
this.dependencies = false;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.fromOptions = function fromOptions(options) {
|
||||
this.tx = options.tx;
|
||||
this.height = options.height;
|
||||
this.size = options.size;
|
||||
this.priority = options.priority;
|
||||
this.fee = options.fee;
|
||||
this.ts = options.ts;
|
||||
|
||||
this.chainValue = options.chainValue;
|
||||
this.count = options.count;
|
||||
this.sizes = options.sizes;
|
||||
this.fees = options.fees;
|
||||
this.dependencies = options.dependencies;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate mempool entry from options.
|
||||
* @param {Object} options
|
||||
* @returns {MempoolEntry}
|
||||
*/
|
||||
|
||||
MempoolEntry.fromOptions = function fromOptions(options) {
|
||||
return new MempoolEntry().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from transaction.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.fromTX = function fromTX(tx, height) {
|
||||
var priority = tx.getPriority(height);
|
||||
var value = tx.getChainValue(height);
|
||||
var dependencies = false;
|
||||
var size = tx.getVirtualSize();
|
||||
var fee = tx.getFee();
|
||||
var i;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
if (tx.inputs[i].coin.height === -1) {
|
||||
dependencies = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.tx = tx;
|
||||
this.height = height;
|
||||
this.size = size;
|
||||
this.priority = priority;
|
||||
this.fee = fee;
|
||||
this.chainValue = value;
|
||||
this.ts = utils.now();
|
||||
this.count = 1;
|
||||
this.sizes = size;
|
||||
this.fees = fee;
|
||||
this.dependencies = dependencies;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a mempool entry from a TX.
|
||||
* @param {TX} tx
|
||||
* @param {Number} height - Entry height.
|
||||
* @returns {MempoolEntry}
|
||||
*/
|
||||
|
||||
MempoolEntry.fromTX = function fromTX(tx, height) {
|
||||
return new MempoolEntry().fromTX(tx, height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate priority, taking into account
|
||||
* the entry height delta, modified size,
|
||||
* and chain value.
|
||||
* @param {Number} height
|
||||
* @returns {Number} Priority.
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.getPriority = function getPriority(height) {
|
||||
var heightDelta = height - this.height;
|
||||
var modSize = this.tx.getModifiedSize(this.size);
|
||||
var deltaPriority = (heightDelta * this.chainValue) / modSize;
|
||||
var result = this.priority + Math.floor(deltaPriority);
|
||||
if (result < 0)
|
||||
result = 0;
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get fee.
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.getFee = function getFee() {
|
||||
return this.fee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate fee rate.
|
||||
* @returns {Rate}
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.getRate = function getRate() {
|
||||
return TX.getRate(this.size, this.fee);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the entry is free with
|
||||
* the current priority (calculated by
|
||||
* current height).
|
||||
* @param {Number} height
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.isFree = function isFree(height) {
|
||||
var priority = this.getPriority(height);
|
||||
return priority > constants.tx.FREE_THRESHOLD;
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = MempoolEntry;
|
||||
4
lib/miner/index.js
Normal file
4
lib/miner/index.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
exports.Miner = require('./miner');
|
||||
exports.MinerBlock = require('./minerblock');
|
||||
|
|
@ -7,11 +7,14 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var co = require('../utils/co');
|
||||
var assert = require('assert');
|
||||
var AsyncObject = require('../utils/async');
|
||||
var MinerBlock = require('./minerblock');
|
||||
var Address = require('../primitives/address');
|
||||
var Workers = require('../workers/workers');
|
||||
var time = require('../net/timedata');
|
||||
|
||||
/**
|
||||
* A bitcoin miner (supports mining witness blocks).
|
||||
|
|
@ -36,7 +39,7 @@ function Miner(options) {
|
|||
options = {};
|
||||
|
||||
this.options = options;
|
||||
this.address = bcoin.address(this.options.address);
|
||||
this.address = Address(this.options.address);
|
||||
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
||||
this.version = null;
|
||||
|
||||
|
|
@ -111,9 +114,9 @@ Miner.prototype._init = function _init() {
|
|||
stat.best);
|
||||
});
|
||||
|
||||
if (bcoin.useWorkers) {
|
||||
this.workerPool = new bcoin.workers({
|
||||
size: this.options.parallel ? 2 : 1,
|
||||
if (Workers.enabled) {
|
||||
this.workerPool = new Workers({
|
||||
size: 1,
|
||||
timeout: -1
|
||||
});
|
||||
|
||||
|
|
@ -130,38 +133,27 @@ Miner.prototype._init = function _init() {
|
|||
/**
|
||||
* Open the miner, wait for the chain and mempool to load.
|
||||
* @alias Miner#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Miner.prototype._open = function open(callback) {
|
||||
var self = this;
|
||||
Miner.prototype._open = co(function* open() {
|
||||
if (this.mempool)
|
||||
yield this.mempool.open();
|
||||
else
|
||||
yield this.chain.open();
|
||||
|
||||
function open(callback) {
|
||||
if (self.mempool)
|
||||
self.mempool.open(callback);
|
||||
else
|
||||
self.chain.open(callback);
|
||||
}
|
||||
|
||||
open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.logger.info('Miner loaded (flags=%s).',
|
||||
self.coinbaseFlags.toString('utf8'));
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
this.logger.info('Miner loaded (flags=%s).',
|
||||
this.coinbaseFlags.toString('utf8'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Close the miner.
|
||||
* @alias Miner#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Miner.prototype._close = function close(callback) {
|
||||
callback();
|
||||
Miner.prototype._close = function close() {
|
||||
return Promise.resolve(null);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -169,53 +161,57 @@ Miner.prototype._close = function close(callback) {
|
|||
* @param {Number?} version - Custom block version.
|
||||
*/
|
||||
|
||||
Miner.prototype.start = function start() {
|
||||
Miner.prototype.start = co(function* start() {
|
||||
var self = this;
|
||||
var attempt, block;
|
||||
|
||||
this.stop();
|
||||
|
||||
this.running = true;
|
||||
|
||||
// Create a new block and start hashing
|
||||
this.createBlock(function(err, attempt) {
|
||||
if (err)
|
||||
return self.emit('error', err);
|
||||
try {
|
||||
attempt = yield this.createBlock();
|
||||
} catch (e) {
|
||||
this.emit('error', e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.running)
|
||||
return;
|
||||
if (!this.running)
|
||||
return;
|
||||
|
||||
self.attempt = attempt;
|
||||
this.attempt = attempt;
|
||||
|
||||
attempt.on('status', function(status) {
|
||||
self.emit('status', status);
|
||||
});
|
||||
|
||||
attempt.mineAsync(function(err, block) {
|
||||
if (err) {
|
||||
if (!self.running)
|
||||
return;
|
||||
self.emit('error', err);
|
||||
return self.start();
|
||||
}
|
||||
|
||||
// Add our block to the chain
|
||||
self.chain.add(block, function(err) {
|
||||
if (err) {
|
||||
if (err.type === 'VerifyError')
|
||||
self.logger.warning('%s could not be added to chain.', block.rhash);
|
||||
self.emit('error', err);
|
||||
return self.start();
|
||||
}
|
||||
|
||||
// Emit our newly found block
|
||||
self.emit('block', block);
|
||||
|
||||
// `tip` will now be emitted by chain
|
||||
// and the whole process starts over.
|
||||
});
|
||||
});
|
||||
attempt.on('status', function(status) {
|
||||
self.emit('status', status);
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
block = yield attempt.mineAsync();
|
||||
} catch (e) {
|
||||
if (!this.running)
|
||||
return;
|
||||
this.emit('error', e);
|
||||
return this.start();
|
||||
}
|
||||
|
||||
// Add our block to the chain
|
||||
try {
|
||||
yield this.chain.add(block);
|
||||
} catch (err) {
|
||||
if (err.type === 'VerifyError')
|
||||
this.logger.warning('%s could not be added to chain.', block.rhash);
|
||||
this.emit('error', err);
|
||||
this.start();
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit our newly found block
|
||||
this.emit('block', block);
|
||||
|
||||
// `tip` will now be emitted by chain
|
||||
// and the whole process starts over.
|
||||
});
|
||||
|
||||
/**
|
||||
* Stop mining.
|
||||
|
|
@ -239,97 +235,67 @@ Miner.prototype.stop = function stop() {
|
|||
/**
|
||||
* Create a block "attempt".
|
||||
* @param {Number?} version - Custom block version.
|
||||
* @param {Function} callback - Returns [Error, {@link MinerBlock}].
|
||||
* @returns {Promise} - Returns {@link MinerBlock}.
|
||||
*/
|
||||
|
||||
Miner.prototype.createBlock = function createBlock(tip, callback) {
|
||||
var self = this;
|
||||
var i, ts, attempt, txs, tx;
|
||||
Miner.prototype.createBlock = co(function* createBlock(tip) {
|
||||
var i, ts, attempt, txs, tx, target, version;
|
||||
|
||||
if (typeof tip === 'function') {
|
||||
callback = tip;
|
||||
tip = null;
|
||||
}
|
||||
if (!this.loaded)
|
||||
yield this.open();
|
||||
|
||||
if (!tip)
|
||||
tip = this.chain.tip;
|
||||
|
||||
ts = Math.max(bcoin.now(), tip.ts + 1);
|
||||
|
||||
function computeVersion(callback) {
|
||||
if (self.version != null)
|
||||
return callback(null, self.version);
|
||||
self.chain.computeBlockVersion(tip, callback);
|
||||
}
|
||||
|
||||
if (!this.loaded) {
|
||||
this.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.createBlock(tip, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
assert(tip);
|
||||
|
||||
ts = Math.max(time.now(), tip.ts + 1);
|
||||
|
||||
// Find target
|
||||
this.chain.getTargetAsync(ts, tip, function(err, target) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
target = yield this.chain.getTargetAsync(ts, tip);
|
||||
|
||||
if (this.version != null) {
|
||||
version = this.version;
|
||||
} else {
|
||||
// Calculate version with versionbits
|
||||
computeVersion(function(err, version) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
version = yield this.chain.computeBlockVersion(tip);
|
||||
}
|
||||
|
||||
attempt = new MinerBlock({
|
||||
workerPool: self.workerPool,
|
||||
tip: tip,
|
||||
version: version,
|
||||
target: target,
|
||||
address: self.address,
|
||||
coinbaseFlags: self.coinbaseFlags,
|
||||
witness: self.chain.segwitActive,
|
||||
parallel: self.options.parallel,
|
||||
network: self.network
|
||||
});
|
||||
|
||||
if (!self.mempool)
|
||||
return callback(null, attempt);
|
||||
|
||||
txs = self.mempool.getHistory();
|
||||
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
attempt.addTX(tx);
|
||||
}
|
||||
|
||||
callback(null, attempt);
|
||||
});
|
||||
attempt = new MinerBlock({
|
||||
workerPool: this.workerPool,
|
||||
tip: tip,
|
||||
version: version,
|
||||
target: target,
|
||||
address: this.address,
|
||||
coinbaseFlags: this.coinbaseFlags,
|
||||
witness: this.chain.segwitActive,
|
||||
network: this.network
|
||||
});
|
||||
};
|
||||
|
||||
if (!this.mempool)
|
||||
return attempt;
|
||||
|
||||
txs = this.mempool.getHistory();
|
||||
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
attempt.addTX(tx);
|
||||
}
|
||||
|
||||
return attempt;
|
||||
});
|
||||
|
||||
/**
|
||||
* Mine a single block.
|
||||
* @param {Number?} version - Custom block version.
|
||||
* @param {Function} callback - Returns [Error, [{@link Block}]].
|
||||
* @returns {Promise} - Returns [{@link Block}].
|
||||
*/
|
||||
|
||||
Miner.prototype.mineBlock = function mineBlock(tip, callback) {
|
||||
if (typeof tip === 'function') {
|
||||
callback = tip;
|
||||
tip = null;
|
||||
}
|
||||
|
||||
Miner.prototype.mineBlock = co(function* mineBlock(tip) {
|
||||
// Create a new block and start hashing
|
||||
this.createBlock(tip, function(err, attempt) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
attempt.mineAsync(callback);
|
||||
});
|
||||
};
|
||||
var attempt = yield this.createBlock(tip);
|
||||
return yield attempt.mineAsync();
|
||||
});
|
||||
|
||||
/*
|
||||
* Expose
|
||||
|
|
|
|||
|
|
@ -7,15 +7,23 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var bn = require('bn.js');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var TX = require('../primitives/tx');
|
||||
var Address = require('../primitives/address');
|
||||
var Block = require('../primitives/block');
|
||||
var Input = require('../primitives/input');
|
||||
var Output = require('../primitives/output');
|
||||
var time = require('../net/timedata');
|
||||
var ChainEntry = require('../chain/chainentry');
|
||||
|
||||
/**
|
||||
* MinerBlock
|
||||
|
|
@ -53,17 +61,16 @@ function MinerBlock(options) {
|
|||
this.coinbaseFlags = options.coinbaseFlags;
|
||||
this.witness = options.witness;
|
||||
this.address = options.address;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.network = Network.get(options.network);
|
||||
this.timeout = null;
|
||||
this.callback = null;
|
||||
|
||||
if (typeof this.coinbaseFlags === 'string')
|
||||
this.coinbaseFlags = new Buffer(this.coinbaseFlags, 'utf8');
|
||||
|
||||
this.coinbase = new bcoin.tx();
|
||||
this.coinbase = new TX();
|
||||
this.coinbase.mutable = true;
|
||||
|
||||
this.block = new bcoin.block();
|
||||
this.block = new Block();
|
||||
this.block.mutable = true;
|
||||
|
||||
this._init();
|
||||
|
|
@ -83,7 +90,7 @@ MinerBlock.prototype._init = function _init() {
|
|||
var i, input, output, hash, witnessNonce;
|
||||
|
||||
// Coinbase input.
|
||||
input = new bcoin.input();
|
||||
input = new Input();
|
||||
|
||||
// Height (required in v2+ blocks)
|
||||
input.script.set(0, new bn(this.height));
|
||||
|
|
@ -108,7 +115,7 @@ MinerBlock.prototype._init = function _init() {
|
|||
cb.inputs.push(input);
|
||||
|
||||
// Reward output.
|
||||
output = new bcoin.output();
|
||||
output = new Output();
|
||||
output.script.fromAddress(this.address);
|
||||
|
||||
cb.outputs.push(output);
|
||||
|
|
@ -126,14 +133,14 @@ MinerBlock.prototype._init = function _init() {
|
|||
input.witness.compile();
|
||||
|
||||
// Commitment output.
|
||||
cb.outputs.push(new bcoin.output());
|
||||
cb.outputs.push(new Output());
|
||||
}
|
||||
|
||||
// Setup our block.
|
||||
block.version = options.version;
|
||||
block.prevBlock = this.tip.hash;
|
||||
block.merkleRoot = constants.NULL_HASH;
|
||||
block.ts = Math.max(bcoin.now(), this.tip.ts + 1);
|
||||
block.ts = Math.max(time.now(), this.tip.ts + 1);
|
||||
block.bits = this.bits;
|
||||
block.nonce = 0;
|
||||
block.height = this.height;
|
||||
|
|
@ -190,7 +197,7 @@ MinerBlock.prototype.updateCoinbase = function updateCoinbase() {
|
|||
*/
|
||||
|
||||
MinerBlock.prototype.updateNonce = function updateNonce() {
|
||||
this.block.ts = Math.max(bcoin.now(), this.tip.ts + 1);
|
||||
this.block.ts = Math.max(time.now(), this.tip.ts + 1);
|
||||
|
||||
// Overflow the nonce and increment the extraNonce.
|
||||
this.block.nonce = 0;
|
||||
|
|
@ -216,7 +223,7 @@ MinerBlock.prototype.updateMerkle = function updateMerkle() {
|
|||
this.updateCommitment();
|
||||
|
||||
// Update timestamp.
|
||||
this.block.ts = Math.max(bcoin.now(), this.tip.ts + 1);
|
||||
this.block.ts = Math.max(time.now(), this.tip.ts + 1);
|
||||
|
||||
// Recalculate merkle root.
|
||||
this.block.merkleRoot = this.block.getMerkleRoot('hex');
|
||||
|
|
@ -306,7 +313,7 @@ MinerBlock.prototype.findNonce = function findNonce() {
|
|||
// update the timestamp. This improves
|
||||
// performance because we do not have to
|
||||
// recalculate the merkle root.
|
||||
now = bcoin.now();
|
||||
now = time.now();
|
||||
if (now > block.ts && now > tip.ts) {
|
||||
block.ts = now;
|
||||
// Overflow the nonce
|
||||
|
|
@ -346,19 +353,34 @@ MinerBlock.prototype.sendStatus = function sendStatus() {
|
|||
/**
|
||||
* Mine until the block is found. Will take a breather
|
||||
* for 100ms every time the nonce overflows.
|
||||
* @param {Function} callback - Returns [Error, {@link Block}].
|
||||
* @returns {Promise} - Returns {@link Block}.
|
||||
*/
|
||||
|
||||
MinerBlock.prototype.mine = function mine(callback) {
|
||||
MinerBlock.prototype.mine = co(function* mine() {
|
||||
yield this.wait(100);
|
||||
|
||||
// Try to find a block: do one iteration of extraNonce
|
||||
if (!this.findNonce()) {
|
||||
yield this.mine();
|
||||
return;
|
||||
}
|
||||
|
||||
return this.block;
|
||||
});
|
||||
|
||||
/**
|
||||
* Wait for a timeout.
|
||||
* @param {Number} time
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
MinerBlock.prototype.wait = function wait(time) {
|
||||
var self = this;
|
||||
|
||||
this.timeout = setTimeout(function() {
|
||||
// Try to find a block: do one iteration of extraNonce
|
||||
if (!self.findNonce())
|
||||
return self.mine(callback);
|
||||
|
||||
callback(null, self.block);
|
||||
}, 100);
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.timeout = setTimeout(function() {
|
||||
resolve();
|
||||
}, time);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -373,33 +395,21 @@ MinerBlock.prototype.mineSync = function mineSync() {
|
|||
|
||||
/**
|
||||
* Attempt to mine the block on the worker pool.
|
||||
* @param {Function} callback - Returns [Error, {@link Block}].
|
||||
* @returns {Promise} - Returns {@link Block}.
|
||||
*/
|
||||
|
||||
MinerBlock.prototype.mineAsync = function mine(callback) {
|
||||
var self = this;
|
||||
MinerBlock.prototype.mineAsync = co(function* mineAsync() {
|
||||
var block;
|
||||
|
||||
if (!this.workerPool)
|
||||
return this.mine(callback);
|
||||
return yield this.mine();
|
||||
|
||||
callback = utils.once(callback);
|
||||
block = yield this.workerPool.mine(this);
|
||||
|
||||
this.callback = callback;
|
||||
this.workerPool.destroy();
|
||||
|
||||
function done(err, block) {
|
||||
self.workerPool.destroy();
|
||||
callback(err, block);
|
||||
}
|
||||
|
||||
if (this.options.parallel) {
|
||||
done = utils.once(done);
|
||||
this.workerPool.mine(this, done);
|
||||
this.workerPool.mine(this, done);
|
||||
return;
|
||||
}
|
||||
|
||||
this.workerPool.mine(this, callback);
|
||||
};
|
||||
return block;
|
||||
});
|
||||
|
||||
/**
|
||||
* Destroy the minerblock. Stop mining. Clear timeout.
|
||||
|
|
@ -410,10 +420,6 @@ MinerBlock.prototype.destroy = function destroy() {
|
|||
clearTimeout(this.timeout);
|
||||
this.timeout = null;
|
||||
}
|
||||
if (this.callback) {
|
||||
this.callback(new Error('Destroyed.'));
|
||||
this.callback = null;
|
||||
}
|
||||
this.block = null;
|
||||
};
|
||||
|
||||
|
|
@ -452,11 +458,11 @@ MinerBlock.prototype.toRaw = function toRaw(writer) {
|
|||
|
||||
MinerBlock.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
var network = bcoin.network.fromMagic(p.readU32());
|
||||
var tip = bcoin.chainentry.fromRaw(null, p);
|
||||
var network = Network.fromMagic(p.readU32());
|
||||
var tip = ChainEntry.fromRaw(null, p);
|
||||
var version = p.readU32();
|
||||
var bits = p.readU32();
|
||||
var address = bcoin.address.fromRaw(p.readVarBytes());
|
||||
var address = Address.fromRaw(p.readVarBytes());
|
||||
var coinbaseFlags = p.readVarBytes();
|
||||
var witness = p.readU8() === 1;
|
||||
var count = p.readVarint();
|
||||
|
|
@ -464,7 +470,7 @@ MinerBlock.fromRaw = function fromRaw(data) {
|
|||
var i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
txs.push(bcoin.tx.fromRaw(p));
|
||||
txs.push(TX.fromRaw(p));
|
||||
|
||||
tip.network = network;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
'use strict';
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var packets = require('./packets');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var ec = require('../crypto/ec');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
|
||||
/**
|
||||
* Represents a BIP150 input and output stream.
|
||||
|
|
@ -54,7 +56,7 @@ function BIP150(bip151, hostname, outbound, db, identity) {
|
|||
|
||||
// Identity keypair
|
||||
this.privateKey = identity;
|
||||
this.publicKey = bcoin.ec.publicKeyCreate(identity, true);
|
||||
this.publicKey = ec.publicKeyCreate(identity, true);
|
||||
|
||||
this.challengeReceived = false;
|
||||
this.replyReceived = false;
|
||||
|
|
@ -95,10 +97,10 @@ BIP150.prototype.challenge = function challenge(hash) {
|
|||
this.emit('auth');
|
||||
}
|
||||
|
||||
sig = bcoin.ec.sign(msg, this.privateKey);
|
||||
sig = ec.sign(msg, this.privateKey);
|
||||
|
||||
// authreply
|
||||
return bcoin.ec.fromDER(sig);
|
||||
return ec.fromDER(sig);
|
||||
};
|
||||
|
||||
BIP150.prototype.reply = function reply(data) {
|
||||
|
|
@ -115,10 +117,10 @@ BIP150.prototype.reply = function reply(data) {
|
|||
if (!this.peerIdentity)
|
||||
return crypto.randomBytes(32);
|
||||
|
||||
sig = bcoin.ec.toDER(data);
|
||||
sig = ec.toDER(data);
|
||||
msg = this.hash(this.output.sid, type, this.peerIdentity);
|
||||
|
||||
result = bcoin.ec.verify(msg, sig, this.peerIdentity);
|
||||
result = ec.verify(msg, sig, this.peerIdentity);
|
||||
|
||||
if (!result)
|
||||
return crypto.randomBytes(32);
|
||||
|
|
@ -247,7 +249,14 @@ BIP150.prototype.complete = function complete(err) {
|
|||
this.callback = null;
|
||||
};
|
||||
|
||||
BIP150.prototype.wait = function wait(timeout, callback) {
|
||||
BIP150.prototype.wait = function wait(timeout) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self._wait(timeout, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
BIP150.prototype._wait = function wait(timeout, callback) {
|
||||
var self = this;
|
||||
|
||||
assert(!this.auth, 'Cannot wait for init after handshake.');
|
||||
|
|
@ -272,7 +281,7 @@ BIP150.prototype.getAddress = function getAddress() {
|
|||
};
|
||||
|
||||
BIP150.address = function address(key) {
|
||||
var p = new bcoin.writer();
|
||||
var p = new BufferWriter();
|
||||
p.writeU8(0x0f);
|
||||
p.writeU16BE(0xff01);
|
||||
p.writeBytes(crypto.hash160(key));
|
||||
|
|
|
|||
|
|
@ -13,13 +13,16 @@
|
|||
'use strict';
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var chachapoly = require('../crypto/chachapoly');
|
||||
var packets = require('./packets');
|
||||
var ec = require('../crypto/ec');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var EncinitPacket = packets.EncinitPacket;
|
||||
var EncackPacket = packets.EncackPacket;
|
||||
|
||||
|
|
@ -58,7 +61,7 @@ function BIP151Stream(cipher) {
|
|||
return new BIP151Stream(cipher);
|
||||
|
||||
this.cipher = cipher || 0;
|
||||
this.privateKey = bcoin.ec.generatePrivateKey();
|
||||
this.privateKey = ec.generatePrivateKey();
|
||||
this.publicKey = null;
|
||||
this.secret = null;
|
||||
this.prk = null;
|
||||
|
|
@ -86,10 +89,10 @@ function BIP151Stream(cipher) {
|
|||
*/
|
||||
|
||||
BIP151Stream.prototype.init = function init(publicKey) {
|
||||
var p = bcoin.writer();
|
||||
var p = new BufferWriter();
|
||||
|
||||
this.publicKey = publicKey;
|
||||
this.secret = bcoin.ec.ecdh(this.publicKey, this.privateKey);
|
||||
this.secret = ec.ecdh(this.publicKey, this.privateKey);
|
||||
|
||||
p.writeBytes(this.secret);
|
||||
p.writeU8(this.cipher);
|
||||
|
|
@ -199,7 +202,7 @@ BIP151Stream.prototype.update = function update() {
|
|||
*/
|
||||
|
||||
BIP151Stream.prototype.getPublicKey = function getPublicKey() {
|
||||
return bcoin.ec.publicKeyCreate(this.privateKey, true);
|
||||
return ec.publicKeyCreate(this.privateKey, true);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -452,10 +455,22 @@ BIP151.prototype.complete = function complete(err) {
|
|||
/**
|
||||
* Set a timeout and wait for handshake to complete.
|
||||
* @param {Number} timeout - Timeout in ms.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
BIP151.prototype.wait = function wait(timeout, callback) {
|
||||
BIP151.prototype.wait = function wait(timeout) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self._wait(timeout, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a timeout and wait for handshake to complete.
|
||||
* @private
|
||||
*/
|
||||
|
||||
BIP151.prototype._wait = function wait(timeout, callback) {
|
||||
var self = this;
|
||||
|
||||
assert(!this.handshake, 'Cannot wait for init after handshake.');
|
||||
|
|
@ -510,7 +525,7 @@ BIP151.prototype.maybeRekey = function maybeRekey(data) {
|
|||
*/
|
||||
|
||||
BIP151.prototype.packet = function packet(cmd, body) {
|
||||
var p = bcoin.writer();
|
||||
var p = new BufferWriter();
|
||||
var payload, packet;
|
||||
|
||||
p.writeVarString(cmd, 'ascii');
|
||||
|
|
@ -652,7 +667,7 @@ BIP151.prototype.parse = function parse(data) {
|
|||
this.input.decrypt(payload);
|
||||
this.input.sequence();
|
||||
|
||||
p = bcoin.reader(payload);
|
||||
p = new BufferReader(payload);
|
||||
|
||||
while (p.left()) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -6,13 +6,17 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var co = require('../utils/co');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var siphash = require('../crypto/siphash');
|
||||
var AbstractBlock = bcoin.abstractblock;
|
||||
var AbstractBlock = require('../primitives/abstractblock');
|
||||
var TX = require('../primitives/tx');
|
||||
var Block = require('../primitives/block');
|
||||
|
||||
/**
|
||||
* Represents a compact block (bip152): `cmpctblock` packet.
|
||||
|
|
@ -39,6 +43,7 @@ function CompactBlock(options) {
|
|||
this.count = 0;
|
||||
this.sipKey = null;
|
||||
this.timeout = null;
|
||||
this.callback = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
|
|
@ -81,7 +86,7 @@ CompactBlock.fromOptions = function fromOptions(options) {
|
|||
};
|
||||
|
||||
CompactBlock.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = new BufferReader(data);
|
||||
var i, count, index, tx;
|
||||
|
||||
this.version = p.readU32(); // Technically signed
|
||||
|
|
@ -110,7 +115,7 @@ CompactBlock.prototype.fromRaw = function fromRaw(data) {
|
|||
index = p.readVarint();
|
||||
assert(index <= 0xffff);
|
||||
assert(index < this.totalTX);
|
||||
tx = bcoin.tx.fromRaw(p);
|
||||
tx = TX.fromRaw(p);
|
||||
this.ptx.push([index, tx]);
|
||||
}
|
||||
|
||||
|
|
@ -134,10 +139,10 @@ CompactBlock.prototype.toNormal = function toNormal(writer) {
|
|||
};
|
||||
|
||||
CompactBlock.prototype.frame = function frame(witness, writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i, id, lo, hi, ptx;
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
p.writeHash(this.prevBlock);
|
||||
p.writeHash(this.merkleRoot);
|
||||
p.writeU32(this.ts);
|
||||
|
|
@ -306,7 +311,7 @@ CompactBlock.prototype.init = function init() {
|
|||
};
|
||||
|
||||
CompactBlock.prototype.toBlock = function toBlock() {
|
||||
var block = new bcoin.block();
|
||||
var block = new Block();
|
||||
var i, tx;
|
||||
|
||||
block.version = this.version;
|
||||
|
|
@ -362,12 +367,31 @@ CompactBlock.fromBlock = function fromBlock(block, nonce) {
|
|||
return new CompactBlock().fromBlock(block, nonce);
|
||||
};
|
||||
|
||||
CompactBlock.prototype.startTimeout = function startTimeout(time, callback) {
|
||||
assert(this.timeout == null);
|
||||
this.timeout = setTimeout(callback, time);
|
||||
CompactBlock.prototype.wait = function wait(time) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
self._wait(time, co.wrap(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
CompactBlock.prototype.stopTimeout = function stopTimeout() {
|
||||
CompactBlock.prototype._wait = function wait(time, callback) {
|
||||
var self = this;
|
||||
assert(this.timeout == null);
|
||||
this.callback = callback;
|
||||
this.timeout = setTimeout(function() {
|
||||
self.complete(new Error('Timed out.'));
|
||||
}, time);
|
||||
};
|
||||
|
||||
CompactBlock.prototype.complete = function complete(err) {
|
||||
if (this.timeout != null) {
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = null;
|
||||
this.callback(err);
|
||||
}
|
||||
};
|
||||
|
||||
CompactBlock.prototype.destroy = function destroy() {
|
||||
if (this.timeout != null) {
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = null;
|
||||
|
|
@ -422,7 +446,7 @@ TXRequest.fromCompact = function fromCompact(block) {
|
|||
};
|
||||
|
||||
TXRequest.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count, index, offset;
|
||||
|
||||
this.hash = p.readHash('hex');
|
||||
|
|
@ -453,7 +477,7 @@ TXRequest.fromRaw = function fromRaw(data) {
|
|||
};
|
||||
|
||||
TXRequest.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i, index;
|
||||
|
||||
p.writeHash(this.hash);
|
||||
|
|
@ -502,7 +526,7 @@ TXResponse.fromOptions = function fromOptions(options) {
|
|||
};
|
||||
|
||||
TXResponse.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
this.hash = p.readHash('hex');
|
||||
|
|
@ -510,7 +534,7 @@ TXResponse.prototype.fromRaw = function fromRaw(data) {
|
|||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
this.txs.push(bcoin.tx.fromRaw(p));
|
||||
this.txs.push(TX.fromRaw(p));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -547,7 +571,7 @@ TXResponse.prototype.toNormal = function toNormal(writer) {
|
|||
};
|
||||
|
||||
TXResponse.prototype.frame = function frame(witness, writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i, tx;
|
||||
|
||||
p.writeHash(this.hash);
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var Network = require('../protocol/network');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
|
||||
/**
|
||||
* Protocol packet framer
|
||||
|
|
@ -28,7 +27,7 @@ function Framer(options) {
|
|||
|
||||
this.options = options;
|
||||
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.network = Network.get(options.network);
|
||||
this.bip151 = options.bip151;
|
||||
}
|
||||
|
||||
|
|
|
|||
12
lib/net/index.js
Normal file
12
lib/net/index.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
exports.bip150 = require('./bip150');
|
||||
exports.bip151 = require('./bip151');
|
||||
exports.bip152 = require('./bip152');
|
||||
exports.Framer = require('./framer');
|
||||
exports.packets = require('./packets');
|
||||
exports.Parser = require('./parser');
|
||||
exports.Peer = require('./peer');
|
||||
exports.Pool = require('./pool');
|
||||
exports.ProxySocket = require('./proxysocket');
|
||||
exports.time = require('./timedata');
|
||||
|
|
@ -7,13 +7,26 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var bn = require('bn.js');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var bn = require('bn.js');
|
||||
var time = require('./timedata');
|
||||
var ec = require('../crypto/ec');
|
||||
var Bloom = require('../utils/bloom');
|
||||
var bip152 = require('./bip152');
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
var assert = utils.assert;
|
||||
var Coin = require('../primitives/coin');
|
||||
var Headers = require('../primitives/headers');
|
||||
var InvItem = require('../primitives/invitem');
|
||||
var MemBlock = require('../primitives/memblock');
|
||||
var MerkleBlock = require('../primitives/merkleblock');
|
||||
var Outpoint = require('../primitives/outpoint');
|
||||
var Output = require('../primitives/output');
|
||||
var TX = require('../primitives/tx');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var DUMMY = new Buffer(0);
|
||||
|
||||
/**
|
||||
|
|
@ -106,7 +119,7 @@ function VersionPacket(options) {
|
|||
|
||||
this.version = constants.VERSION;
|
||||
this.services = constants.LOCAL_SERVICES;
|
||||
this.ts = bcoin.now();
|
||||
this.ts = time.now();
|
||||
this.recv = new NetworkAddress();
|
||||
this.from = new NetworkAddress();
|
||||
this.nonce = new bn(0);
|
||||
|
|
@ -176,7 +189,7 @@ VersionPacket.fromOptions = function fromOptions(options) {
|
|||
*/
|
||||
|
||||
VersionPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU64(this.services);
|
||||
|
|
@ -256,7 +269,7 @@ VersionPacket.prototype.hasCompact = function hasCompact() {
|
|||
*/
|
||||
|
||||
VersionPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.version = p.read32();
|
||||
this.services = p.readU53();
|
||||
|
|
@ -376,7 +389,7 @@ PingPacket.prototype.type = exports.types.PING;
|
|||
*/
|
||||
|
||||
PingPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
if (this.nonce)
|
||||
p.writeU64(this.nonce);
|
||||
|
|
@ -394,7 +407,7 @@ PingPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
PingPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
if (p.left() >= 8)
|
||||
this.nonce = p.readU64();
|
||||
return this;
|
||||
|
|
@ -441,7 +454,7 @@ PongPacket.prototype.type = exports.types.PONG;
|
|||
*/
|
||||
|
||||
PongPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeU64(this.nonce);
|
||||
|
||||
|
|
@ -458,7 +471,7 @@ PongPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
PongPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.nonce = p.readU64();
|
||||
return this;
|
||||
};
|
||||
|
|
@ -498,18 +511,18 @@ PongPacket.fromRaw = function fromRaw(data, enc) {
|
|||
*/
|
||||
|
||||
function AlertPacket(options) {
|
||||
var time;
|
||||
var ts;
|
||||
|
||||
if (!(this instanceof AlertPacket))
|
||||
return new AlertPacket(options);
|
||||
|
||||
Packet.call(this);
|
||||
|
||||
time = bcoin.now() + 7 * 86400;
|
||||
ts = time.now() + 7 * 86400;
|
||||
|
||||
this.version = 1;
|
||||
this.relayUntil = time;
|
||||
this.expiration = time;
|
||||
this.relayUntil = ts;
|
||||
this.expiration = ts;
|
||||
this.id = 1;
|
||||
this.cancel = 0;
|
||||
this.cancels = [];
|
||||
|
|
@ -625,7 +638,7 @@ AlertPacket.prototype.toPayload = function toPayload() {
|
|||
*/
|
||||
|
||||
AlertPacket.prototype.sign = function sign(key) {
|
||||
this.signature = bcoin.ec.sign(this.hash(), key);
|
||||
this.signature = ec.sign(this.hash(), key);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -635,7 +648,7 @@ AlertPacket.prototype.sign = function sign(key) {
|
|||
*/
|
||||
|
||||
AlertPacket.prototype.verify = function verify(key) {
|
||||
return bcoin.ec.verify(this.hash(), this.signature, key);
|
||||
return ec.verify(this.hash(), this.signature, key);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -644,7 +657,7 @@ AlertPacket.prototype.verify = function verify(key) {
|
|||
*/
|
||||
|
||||
AlertPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeVarBytes(this.toPayload());
|
||||
p.writeVarBytes(this.signature);
|
||||
|
|
@ -662,7 +675,7 @@ AlertPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
AlertPacket.prototype.framePayload = function framePayload(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.write32(this.version);
|
||||
|
|
@ -700,13 +713,13 @@ AlertPacket.prototype.framePayload = function framePayload(writer) {
|
|||
*/
|
||||
|
||||
AlertPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
this._payload = p.readVarBytes();
|
||||
this.signature = p.readVarBytes();
|
||||
|
||||
p = bcoin.reader(this._payload);
|
||||
p = BufferReader(this._payload);
|
||||
|
||||
this.version = p.read32();
|
||||
this.relayUntil = p.read53();
|
||||
|
|
@ -824,7 +837,7 @@ AddrPacket.prototype.type = exports.types.ADDR;
|
|||
*/
|
||||
|
||||
AddrPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeVarint(this.items.length);
|
||||
|
|
@ -845,7 +858,7 @@ AddrPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
AddrPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
count = p.readVarint();
|
||||
|
|
@ -897,7 +910,7 @@ InvPacket.prototype.type = exports.types.INV;
|
|||
*/
|
||||
|
||||
InvPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeVarint(this.items.length);
|
||||
|
|
@ -918,13 +931,13 @@ InvPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
InvPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
this.items.push(bcoin.invitem.fromRaw(p));
|
||||
this.items.push(InvItem.fromRaw(p));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -1040,7 +1053,7 @@ GetBlocksPacket.prototype.type = exports.types.GETBLOCKS;
|
|||
*/
|
||||
|
||||
GetBlocksPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeU32(this.version);
|
||||
|
|
@ -1064,7 +1077,7 @@ GetBlocksPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
GetBlocksPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
this.version = p.readU32();
|
||||
|
|
@ -1157,7 +1170,7 @@ HeadersPacket.prototype.type = exports.types.HEADERS;
|
|||
*/
|
||||
|
||||
HeadersPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeVarint(this.items.length);
|
||||
|
|
@ -1178,13 +1191,13 @@ HeadersPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
HeadersPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
this.items.push(bcoin.headers.fromRaw(p));
|
||||
this.items.push(Headers.fromRaw(p));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -1268,7 +1281,7 @@ function BlockPacket(block, witness) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.block = block || new bcoin.memblock();
|
||||
this.block = block || new MemBlock();
|
||||
this.witness = witness || false;
|
||||
}
|
||||
|
||||
|
|
@ -1328,7 +1341,7 @@ function TXPacket(tx, witness) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.tx = tx || new bcoin.tx();
|
||||
this.tx = tx || new TX();
|
||||
this.witness = witness || false;
|
||||
}
|
||||
|
||||
|
|
@ -1450,7 +1463,7 @@ RejectPacket.fromOptions = function fromOptions(options) {
|
|||
*/
|
||||
|
||||
RejectPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
assert(this.message.length <= 12);
|
||||
assert(this.reason.length <= 111);
|
||||
|
|
@ -1475,7 +1488,7 @@ RejectPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
RejectPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.message = p.readVarString('ascii', 12);
|
||||
this.code = p.readU8();
|
||||
|
|
@ -1525,7 +1538,7 @@ RejectPacket.prototype.fromReason = function fromReason(code, reason, obj) {
|
|||
this.reason = reason;
|
||||
|
||||
if (obj) {
|
||||
this.message = (obj instanceof bcoin.tx) ? 'tx' : 'block';
|
||||
this.message = (obj instanceof TX) ? 'tx' : 'block';
|
||||
this.data = obj.hash('hex');
|
||||
}
|
||||
|
||||
|
|
@ -1639,10 +1652,14 @@ function FilterLoadPacket(filter, n, tweak, update) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.filter = filter || DUMMY;
|
||||
this.n = n || 0;
|
||||
this.tweak = tweak || 0;
|
||||
this.update = update || 0;
|
||||
if (filter instanceof Bloom) {
|
||||
this.fromFilter(filter);
|
||||
} else {
|
||||
this.filter = filter || DUMMY;
|
||||
this.n = n || 0;
|
||||
this.tweak = tweak || 0;
|
||||
this.update = update || 0;
|
||||
}
|
||||
}
|
||||
|
||||
utils.inherits(FilterLoadPacket, Packet);
|
||||
|
|
@ -1656,7 +1673,7 @@ FilterLoadPacket.prototype.type = exports.types.FILTERLOAD;
|
|||
*/
|
||||
|
||||
FilterLoadPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeVarBytes(this.filter);
|
||||
p.writeU32(this.n);
|
||||
|
|
@ -1675,7 +1692,7 @@ FilterLoadPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
FilterLoadPacket.prototype.toFilter = function toFilter() {
|
||||
return new bcoin.bloom(this.filter, this.n, this.tweak, this.update);
|
||||
return new Bloom(this.filter, this.n, this.tweak, this.update);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1685,7 +1702,7 @@ FilterLoadPacket.prototype.toFilter = function toFilter() {
|
|||
*/
|
||||
|
||||
FilterLoadPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.filter = p.readVarBytes();
|
||||
this.n = p.readU32();
|
||||
|
|
@ -1778,7 +1795,7 @@ FilterAddPacket.prototype.type = exports.types.FILTERADD;
|
|||
*/
|
||||
|
||||
FilterAddPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeVarBytes(this.data);
|
||||
|
||||
|
|
@ -1795,7 +1812,7 @@ FilterAddPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
FilterAddPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.data = p.readVarBytes();
|
||||
return this;
|
||||
};
|
||||
|
|
@ -1877,7 +1894,7 @@ function MerkleBlockPacket(block) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.block = block || new bcoin.merkleblock();
|
||||
this.block = block || new MerkleBlock();
|
||||
}
|
||||
|
||||
utils.inherits(MerkleBlockPacket, Packet);
|
||||
|
|
@ -1949,7 +1966,7 @@ GetUTXOsPacket.prototype.type = exports.types.GETUTXOS;
|
|||
*/
|
||||
|
||||
GetUTXOsPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeU8(this.mempool ? 1 : 0);
|
||||
|
|
@ -1971,7 +1988,7 @@ GetUTXOsPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
GetUTXOsPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, count;
|
||||
|
||||
this.mempool = p.readU8() === 1;
|
||||
|
|
@ -1979,7 +1996,7 @@ GetUTXOsPacket.prototype.fromRaw = function fromRaw(data) {
|
|||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
this.prevout.push(bcoin.outpoint.fromRaw(p));
|
||||
this.prevout.push(Outpoint.fromRaw(p));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -2075,7 +2092,7 @@ UTXOsPacket.fromOptions = function fromOptions(options) {
|
|||
*/
|
||||
|
||||
UTXOsPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var map = new Buffer((this.hits.length + 7) / 8 | 0);
|
||||
var i, bit, oct, coin, height;
|
||||
|
||||
|
|
@ -2116,7 +2133,7 @@ UTXOsPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
UTXOsPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, bit, oct, coin, output;
|
||||
var version, height, map, count;
|
||||
|
||||
|
|
@ -2135,12 +2152,12 @@ UTXOsPacket.prototype.fromRaw = function fromRaw(data) {
|
|||
for (i = 0; i < count; i++) {
|
||||
version = p.readU32();
|
||||
height = p.readU32();
|
||||
coin = new bcoin.coin();
|
||||
coin = new Coin();
|
||||
|
||||
if (height === 0x7fffffff)
|
||||
height = -1;
|
||||
|
||||
output = bcoin.output.fromRaw(p);
|
||||
output = Output.fromRaw(p);
|
||||
|
||||
coin.version = version;
|
||||
coin.height = height;
|
||||
|
|
@ -2244,7 +2261,7 @@ FeeFilterPacket.prototype.type = exports.types.FEEFILTER;
|
|||
*/
|
||||
|
||||
FeeFilterPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.write64(this.rate);
|
||||
|
||||
|
|
@ -2261,7 +2278,7 @@ FeeFilterPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
FeeFilterPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.rate = p.read64N();
|
||||
return this;
|
||||
};
|
||||
|
|
@ -2310,7 +2327,7 @@ SendCmpctPacket.prototype.type = exports.types.SENDCMPCT;
|
|||
*/
|
||||
|
||||
SendCmpctPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeU8(this.mode);
|
||||
p.writeU64(this.version);
|
||||
|
|
@ -2328,7 +2345,7 @@ SendCmpctPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
SendCmpctPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.mode = p.readU8();
|
||||
this.version = p.readU53();
|
||||
return this;
|
||||
|
|
@ -2363,7 +2380,7 @@ function CmpctBlockPacket(block, witness) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.block = block || new bcoin.bip152.CompactBlock();
|
||||
this.block = block || new bip152.CompactBlock();
|
||||
this.witness = witness || false;
|
||||
}
|
||||
|
||||
|
|
@ -2421,7 +2438,7 @@ function GetBlockTxnPacket(request) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.request = request || new bcoin.bip152.TXRequest();
|
||||
this.request = request || new bip152.TXRequest();
|
||||
}
|
||||
|
||||
utils.inherits(GetBlockTxnPacket, Packet);
|
||||
|
|
@ -2478,7 +2495,7 @@ function BlockTxnPacket(response, witness) {
|
|||
|
||||
Packet.call(this);
|
||||
|
||||
this.response = response || new bcoin.bip152.TXResponse();
|
||||
this.response = response || new bip152.TXResponse();
|
||||
this.witness = witness || false;
|
||||
}
|
||||
|
||||
|
|
@ -2553,7 +2570,7 @@ EncinitPacket.prototype.type = exports.types.ENCINIT;
|
|||
*/
|
||||
|
||||
EncinitPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeBytes(this.publicKey);
|
||||
p.writeU8(this.cipher);
|
||||
|
|
@ -2571,7 +2588,7 @@ EncinitPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
EncinitPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.publicKey = p.readBytes(33);
|
||||
this.cipher = p.readU8();
|
||||
return this;
|
||||
|
|
@ -2618,7 +2635,7 @@ EncackPacket.prototype.type = exports.types.ENCACK;
|
|||
*/
|
||||
|
||||
EncackPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeBytes(this.publicKey);
|
||||
|
||||
|
|
@ -2635,7 +2652,7 @@ EncackPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
EncackPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.publicKey = p.readBytes(33);
|
||||
return this;
|
||||
};
|
||||
|
|
@ -2681,7 +2698,7 @@ AuthChallengePacket.prototype.type = exports.types.AUTHCHALLENGE;
|
|||
*/
|
||||
|
||||
AuthChallengePacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeBytes(this.hash);
|
||||
|
||||
|
|
@ -2698,7 +2715,7 @@ AuthChallengePacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
AuthChallengePacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.hash = p.readHash();
|
||||
return this;
|
||||
};
|
||||
|
|
@ -2744,7 +2761,7 @@ AuthReplyPacket.prototype.type = exports.types.AUTHREPLY;
|
|||
*/
|
||||
|
||||
AuthReplyPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeBytes(this.signature);
|
||||
|
||||
|
|
@ -2761,7 +2778,7 @@ AuthReplyPacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
AuthReplyPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.signature = p.readBytes(64);
|
||||
return this;
|
||||
};
|
||||
|
|
@ -2807,7 +2824,7 @@ AuthProposePacket.prototype.type = exports.types.AUTHPROPOSE;
|
|||
*/
|
||||
|
||||
AuthProposePacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeBytes(this.hash);
|
||||
|
||||
|
|
@ -2824,7 +2841,7 @@ AuthProposePacket.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
AuthProposePacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.hash = p.readHash();
|
||||
return this;
|
||||
};
|
||||
|
|
@ -2872,7 +2889,7 @@ UnknownPacket.prototype.type = exports.types.UNKNOWN;
|
|||
*/
|
||||
|
||||
UnknownPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeBytes(this.data);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var Network = require('../protocol/network');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var packets = require('./packets');
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ function Parser(options) {
|
|||
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.network = Network.get(options.network);
|
||||
this.bip151 = options.bip151;
|
||||
|
||||
this.pending = [];
|
||||
|
|
|
|||
1444
lib/net/peer.js
1444
lib/net/peer.js
File diff suppressed because it is too large
Load diff
810
lib/net/pool.js
810
lib/net/pool.js
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = bcoin.utils;
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var IOClient = require('socket.io-client');
|
||||
|
||||
|
|
@ -18,6 +17,8 @@ function ProxySocket(uri) {
|
|||
|
||||
this.socket = new IOClient(uri, { reconnection: false });
|
||||
this.sendBuffer = [];
|
||||
this.recvBuffer = [];
|
||||
this.paused = false;
|
||||
this.snonce = null;
|
||||
this.bytesWritten = 0;
|
||||
this.bytesRead = 0;
|
||||
|
|
@ -60,6 +61,10 @@ ProxySocket.prototype._init = function _init() {
|
|||
|
||||
this.socket.on('tcp data', function(data) {
|
||||
data = new Buffer(data, 'hex');
|
||||
if (self.paused) {
|
||||
self.recvBuffer.push(data);
|
||||
return;
|
||||
}
|
||||
self.bytesRead += data.length;
|
||||
self.emit('data', data);
|
||||
});
|
||||
|
|
@ -129,9 +134,13 @@ ProxySocket.prototype.connect = function connect(port, host) {
|
|||
this.sendBuffer.length = 0;
|
||||
};
|
||||
|
||||
ProxySocket.prototype.write = function write(data) {
|
||||
ProxySocket.prototype.write = function write(data, callback) {
|
||||
if (!this.info) {
|
||||
this.sendBuffer.push(data);
|
||||
|
||||
if (callback)
|
||||
callback();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -139,9 +148,33 @@ ProxySocket.prototype.write = function write(data) {
|
|||
|
||||
this.socket.emit('tcp data', data.toString('hex'));
|
||||
|
||||
if (callback)
|
||||
callback();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
ProxySocket.prototype.pause = function pause() {
|
||||
this.paused = true;
|
||||
this.socket.emit('tcp pause');
|
||||
};
|
||||
|
||||
ProxySocket.prototype.resume = function resume() {
|
||||
var recv = this.recvBuffer;
|
||||
var i, data;
|
||||
|
||||
this.paused = false;
|
||||
this.recvBuffer = [];
|
||||
|
||||
for (i = 0; i < recv.length; i++) {
|
||||
data = recv[i];
|
||||
this.bytesRead += data.length;
|
||||
this.emit('data', data);
|
||||
}
|
||||
|
||||
this.socket.emit('tcp resume');
|
||||
};
|
||||
|
||||
ProxySocket.prototype.destroy = function destroy() {
|
||||
if (this.closed)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -112,4 +112,4 @@ function compare(a, b) {
|
|||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = TimeData;
|
||||
module.exports = new TimeData();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
var Network = require('../protocol/network');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var fs;
|
||||
|
||||
if (!utils.isBrowser)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,23 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var constants = bcoin.constants;
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var Node = bcoin.node;
|
||||
var co = require('../utils/co');
|
||||
var Node = require('./node');
|
||||
var Chain = require('../chain/chain');
|
||||
var Fees = require('../mempool/fees');
|
||||
var Mempool = require('../mempool/mempool');
|
||||
var Pool = require('../net/pool');
|
||||
var Miner = require('../miner/miner');
|
||||
var WalletDB = require('../wallet/walletdb');
|
||||
var HTTPServer;
|
||||
|
||||
try {
|
||||
HTTPServer = require('../http/server');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fullnode complete with a chain,
|
||||
|
|
@ -53,7 +66,7 @@ function Fullnode(options) {
|
|||
Node.call(this, options);
|
||||
|
||||
// Instantiate blockchain.
|
||||
this.chain = new bcoin.chain({
|
||||
this.chain = new Chain({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
db: this.options.db,
|
||||
|
|
@ -70,13 +83,13 @@ function Fullnode(options) {
|
|||
});
|
||||
|
||||
// Fee estimation.
|
||||
this.fees = new bcoin.fees(
|
||||
this.fees = new Fees(
|
||||
constants.tx.MIN_RELAY,
|
||||
this.network,
|
||||
this.logger);
|
||||
|
||||
// Mempool needs access to the chain.
|
||||
this.mempool = new bcoin.mempool({
|
||||
this.mempool = new Mempool({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
chain: this.chain,
|
||||
|
|
@ -90,7 +103,7 @@ function Fullnode(options) {
|
|||
});
|
||||
|
||||
// Pool needs access to the chain and mempool.
|
||||
this.pool = new bcoin.pool({
|
||||
this.pool = new Pool({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
chain: this.chain,
|
||||
|
|
@ -115,19 +128,18 @@ function Fullnode(options) {
|
|||
});
|
||||
|
||||
// Miner needs access to the chain and mempool.
|
||||
this.miner = new bcoin.miner({
|
||||
this.miner = new Miner({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
chain: this.chain,
|
||||
mempool: this.mempool,
|
||||
fees: this.fees,
|
||||
address: this.options.payoutAddress,
|
||||
coinbaseFlags: this.options.coinbaseFlags,
|
||||
parallel: this.options.parallel
|
||||
coinbaseFlags: this.options.coinbaseFlags
|
||||
});
|
||||
|
||||
// Wallet database needs access to fees.
|
||||
this.walletdb = new bcoin.walletdb({
|
||||
this.walletdb = new WalletDB({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
fees: this.fees,
|
||||
|
|
@ -141,7 +153,7 @@ function Fullnode(options) {
|
|||
|
||||
// HTTP needs access to the node.
|
||||
if (!utils.isBrowser) {
|
||||
this.http = new bcoin.http.server({
|
||||
this.http = new HTTPServer({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
node: this,
|
||||
|
|
@ -185,7 +197,7 @@ Fullnode.prototype._init = function _init() {
|
|||
|
||||
this.mempool.on('tx', function(tx) {
|
||||
self.emit('tx', tx);
|
||||
self.walletdb.addTX(tx, onError);
|
||||
self.walletdb.addTX(tx).catch(onError);
|
||||
});
|
||||
|
||||
this.chain.on('block', function(block) {
|
||||
|
|
@ -193,17 +205,17 @@ Fullnode.prototype._init = function _init() {
|
|||
});
|
||||
|
||||
this.chain.on('connect', function(entry, block) {
|
||||
self.walletdb.addBlock(entry, block.txs, onError);
|
||||
self.walletdb.addBlock(entry, block.txs).catch(onError);
|
||||
|
||||
if (self.chain.synced)
|
||||
self.mempool.addBlock(block, onError);
|
||||
self.mempool.addBlock(block).catch(onError);
|
||||
});
|
||||
|
||||
this.chain.on('disconnect', function(entry, block) {
|
||||
self.walletdb.removeBlock(entry, onError);
|
||||
self.walletdb.removeBlock(entry).catch(onError);
|
||||
|
||||
if (self.chain.synced)
|
||||
self.mempool.removeBlock(block, onError);
|
||||
self.mempool.removeBlock(block).catch(onError);
|
||||
});
|
||||
|
||||
this.miner.on('block', function(block) {
|
||||
|
|
@ -211,7 +223,7 @@ Fullnode.prototype._init = function _init() {
|
|||
});
|
||||
|
||||
this.walletdb.on('send', function(tx) {
|
||||
self.sendTX(tx, onError);
|
||||
self.sendTX(tx).catch(onError);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -219,82 +231,70 @@ Fullnode.prototype._init = function _init() {
|
|||
* Open the node and all its child objects,
|
||||
* wait for the database to load.
|
||||
* @alias Fullnode#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Fullnode.prototype._open = function open(callback) {
|
||||
var self = this;
|
||||
Fullnode.prototype._open = co(function* open() {
|
||||
yield this.chain.open();
|
||||
yield this.mempool.open();
|
||||
yield this.miner.open();
|
||||
yield this.pool.open();
|
||||
yield this.walletdb.open();
|
||||
|
||||
utils.serial([
|
||||
this.chain.open.bind(this.chain),
|
||||
this.mempool.open.bind(this.mempool),
|
||||
this.miner.open.bind(this.miner),
|
||||
this.pool.open.bind(this.pool),
|
||||
this.walletdb.open.bind(this.walletdb),
|
||||
// Ensure primary wallet.
|
||||
this.openWallet.bind(this),
|
||||
// Rescan for any missed transactions.
|
||||
this.rescan.bind(this),
|
||||
// Rebroadcast pending transactions.
|
||||
this.resend.bind(this),
|
||||
function(next) {
|
||||
if (!self.http)
|
||||
return next();
|
||||
self.http.open(next);
|
||||
}
|
||||
], function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
// Ensure primary wallet.
|
||||
yield this.openWallet();
|
||||
|
||||
self.logger.info('Node is loaded.');
|
||||
// Rescan for any missed transactions.
|
||||
yield this.rescan();
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
// Rebroadcast pending transactions.
|
||||
yield this.resend();
|
||||
|
||||
if (this.http)
|
||||
yield this.http.open();
|
||||
|
||||
this.logger.info('Node is loaded.');
|
||||
});
|
||||
|
||||
/**
|
||||
* Close the node, wait for the database to close.
|
||||
* @alias Fullnode#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Fullnode.prototype._close = function close(callback) {
|
||||
var self = this;
|
||||
Fullnode.prototype._close = co(function* close() {
|
||||
if (this.http)
|
||||
yield this.http.close();
|
||||
|
||||
yield this.wallet.destroy();
|
||||
|
||||
this.wallet = null;
|
||||
|
||||
utils.serial([
|
||||
function(next) {
|
||||
if (!self.http)
|
||||
return next();
|
||||
self.http.close(next);
|
||||
},
|
||||
this.walletdb.close.bind(this.walletdb),
|
||||
this.pool.close.bind(this.pool),
|
||||
this.miner.close.bind(this.miner),
|
||||
this.mempool.close.bind(this.mempool),
|
||||
this.chain.close.bind(this.chain)
|
||||
], callback);
|
||||
};
|
||||
yield this.walletdb.close();
|
||||
yield this.pool.close();
|
||||
yield this.miner.close();
|
||||
yield this.mempool.close();
|
||||
yield this.chain.close();
|
||||
|
||||
this.logger.info('Node is closed.');
|
||||
});
|
||||
|
||||
/**
|
||||
* Rescan for any missed transactions.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Fullnode.prototype.rescan = function rescan(callback) {
|
||||
Fullnode.prototype.rescan = function rescan() {
|
||||
if (this.options.noScan) {
|
||||
this.walletdb.setTip(
|
||||
return this.walletdb.setTip(
|
||||
this.chain.tip.hash,
|
||||
this.chain.height,
|
||||
callback);
|
||||
return;
|
||||
this.chain.height);
|
||||
}
|
||||
|
||||
// Always rescan to make sure we didn't
|
||||
// miss anything: there is no atomicity
|
||||
// between the chaindb and walletdb.
|
||||
this.walletdb.rescan(this.chain.db, callback);
|
||||
return this.walletdb.rescan(this.chain.db);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -302,7 +302,7 @@ Fullnode.prototype.rescan = function rescan(callback) {
|
|||
* by the mempool - use with care, lest you get banned from
|
||||
* bitcoind nodes).
|
||||
* @param {TX|Block} item
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Fullnode.prototype.broadcast = function broadcast(item, callback) {
|
||||
|
|
@ -316,53 +316,35 @@ Fullnode.prototype.broadcast = function broadcast(item, callback) {
|
|||
* node.sendTX(tx, callback);
|
||||
* node.sendTX(tx, true, callback);
|
||||
* @param {TX} tx
|
||||
* @param {Boolean?} wait - Wait to execute callback until a node
|
||||
* requests our TX, rejects it, or the broadcast itself times out.
|
||||
* @param {Function} callback - Returns [{@link VerifyError}|Error].
|
||||
*/
|
||||
|
||||
Fullnode.prototype.sendTX = function sendTX(tx, wait, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!callback) {
|
||||
callback = wait;
|
||||
wait = null;
|
||||
Fullnode.prototype.sendTX = co(function* sendTX(tx) {
|
||||
try {
|
||||
yield this.mempool.addTX(tx);
|
||||
} catch (err) {
|
||||
if (err.type === 'VerifyError') {
|
||||
this._error(err);
|
||||
this.logger.warning('Verification failed for tx: %s.', tx.rhash);
|
||||
this.logger.warning('Attempting to broadcast anyway...');
|
||||
yield this.pool.broadcast(tx);
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
this.mempool.addTX(tx, function(err) {
|
||||
if (err) {
|
||||
if (err.type === 'VerifyError') {
|
||||
self._error(err);
|
||||
self.logger.warning('Verification failed for tx: %s.', tx.rhash);
|
||||
self.logger.warning('Attempting to broadcast anyway...');
|
||||
if (!wait) {
|
||||
self.pool.broadcast(tx);
|
||||
return callback();
|
||||
}
|
||||
return self.pool.broadcast(tx, callback);
|
||||
}
|
||||
return callback(err);
|
||||
}
|
||||
if (!this.options.selfish)
|
||||
tx = tx.toInv();
|
||||
|
||||
if (!self.options.selfish)
|
||||
tx = tx.toInv();
|
||||
|
||||
if (!wait) {
|
||||
self.pool.broadcast(tx);
|
||||
return callback();
|
||||
}
|
||||
|
||||
self.pool.broadcast(tx, callback);
|
||||
});
|
||||
};
|
||||
yield this.pool.broadcast(tx);
|
||||
});
|
||||
|
||||
/**
|
||||
* Listen on a server socket on
|
||||
* the p2p network (accepts leech peers).
|
||||
*/
|
||||
|
||||
Fullnode.prototype.listen = function listen(callback) {
|
||||
this.pool.listen(callback);
|
||||
Fullnode.prototype.listen = function listen() {
|
||||
return this.pool.listen();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -392,21 +374,21 @@ Fullnode.prototype.stopSync = function stopSync() {
|
|||
/**
|
||||
* Retrieve a block from the chain database.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, {@link Block}].
|
||||
* @returns {Promise} - Returns {@link Block}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getBlock = function getBlock(hash, callback) {
|
||||
this.chain.db.getBlock(hash, callback);
|
||||
Fullnode.prototype.getBlock = function getBlock(hash) {
|
||||
return this.chain.db.getBlock(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a block from the chain database, filled with coins.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, {@link Block}].
|
||||
* @returns {Promise} - Returns {@link Block}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getFullBlock = function getFullBlock(hash, callback) {
|
||||
this.chain.db.getFullBlock(hash, callback);
|
||||
Fullnode.prototype.getFullBlock = function getFullBlock(hash) {
|
||||
return this.chain.db.getFullBlock(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -414,139 +396,130 @@ Fullnode.prototype.getFullBlock = function getFullBlock(hash, callback) {
|
|||
* Takes into account spent coins in the mempool.
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}].
|
||||
* @returns {Promise} - Returns {@link Coin}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
Fullnode.prototype.getCoin = function getCoin(hash, index) {
|
||||
var coin = this.mempool.getCoin(hash, index);
|
||||
|
||||
if (coin)
|
||||
return callback(null, coin);
|
||||
return Promise.resolve(coin);
|
||||
|
||||
if (this.mempool.isSpent(hash, index))
|
||||
return callback();
|
||||
return Promise.resolve(null);
|
||||
|
||||
this.chain.db.getCoin(hash, index, callback);
|
||||
return this.chain.db.getCoin(hash, index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get coins that pertain to an address from the mempool or chain database.
|
||||
* Takes into account spent coins in the mempool.
|
||||
* @param {Address} addresses
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}[]].
|
||||
* @returns {Promise} - Returns {@link Coin}[].
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, callback) {
|
||||
var self = this;
|
||||
Fullnode.prototype.getCoinsByAddress = co(function* getCoinsByAddress(addresses) {
|
||||
var coins = this.mempool.getCoinsByAddress(addresses);
|
||||
var i, coin, spent;
|
||||
var i, blockCoins, coin, spent;
|
||||
|
||||
this.chain.db.getCoinsByAddress(addresses, function(err, blockCoins) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
blockCoins = yield this.chain.db.getCoinsByAddress(addresses);
|
||||
|
||||
for (i = 0; i < blockCoins.length; i++) {
|
||||
coin = blockCoins[i];
|
||||
spent = self.mempool.isSpent(coin.hash, coin.index);
|
||||
for (i = 0; i < blockCoins.length; i++) {
|
||||
coin = blockCoins[i];
|
||||
spent = this.mempool.isSpent(coin.hash, coin.index);
|
||||
|
||||
if (!spent)
|
||||
coins.push(coin);
|
||||
}
|
||||
if (!spent)
|
||||
coins.push(coin);
|
||||
}
|
||||
|
||||
callback(null, coins);
|
||||
});
|
||||
};
|
||||
return coins;
|
||||
});
|
||||
|
||||
/**
|
||||
* Retrieve transactions pertaining to an
|
||||
* address from the mempool or chain database.
|
||||
* @param {Address} addresses
|
||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getTXByAddress = function getTXByAddress(addresses, callback) {
|
||||
Fullnode.prototype.getTXByAddress = co(function* getTXByAddress(addresses) {
|
||||
var mempool = this.mempool.getTXByAddress(addresses);
|
||||
|
||||
this.chain.db.getTXByAddress(addresses, function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback(null, mempool.concat(txs));
|
||||
});
|
||||
};
|
||||
var txs = yield this.chain.db.getTXByAddress(addresses);
|
||||
return mempool.concat(txs);
|
||||
});
|
||||
|
||||
/**
|
||||
* Retrieve a transaction from the mempool or chain database.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getTX = function getTX(hash, callback) {
|
||||
Fullnode.prototype.getTX = function getTX(hash) {
|
||||
var tx = this.mempool.getTX(hash);
|
||||
|
||||
if (tx)
|
||||
return callback(null, tx);
|
||||
return Promise.resolve(tx);
|
||||
|
||||
this.chain.db.getTX(hash, callback);
|
||||
return this.chain.db.getTX(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the mempool or chain contains a transaction.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} callback - Returns [Error, Boolean].
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.hasTX = function hasTX(hash, callback) {
|
||||
Fullnode.prototype.hasTX = function hasTX(hash) {
|
||||
if (this.mempool.hasTX(hash))
|
||||
return callback(null, true);
|
||||
return Promise.resolve(true);
|
||||
|
||||
this.chain.db.hasTX(hash, callback);
|
||||
return this.chain.db.hasTX(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether a coin has been spent.
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @param {Function} callback - Returns [Error, Boolean].
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
Fullnode.prototype.isSpent = function isSpent(hash, index) {
|
||||
if (this.mempool.isSpent(hash, index))
|
||||
return callback(null, true);
|
||||
return Promise.resolve(true);
|
||||
|
||||
this.chain.db.isSpent(hash, index, callback);
|
||||
return this.chain.db.isSpent(hash, index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill a transaction with coins from the mempool
|
||||
* and chain database (unspent only).
|
||||
* @param {TX} tx
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.fillCoins = function fillCoins(tx, callback) {
|
||||
this.mempool.fillAllCoins(tx, callback);
|
||||
Fullnode.prototype.fillCoins = function fillCoins(tx) {
|
||||
return this.mempool.fillAllCoins(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill a transaction with all historical coins
|
||||
* from the mempool and chain database.
|
||||
* @param {TX} tx
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.fillHistory = function fillHistory(tx, callback) {
|
||||
this.mempool.fillAllHistory(tx, callback);
|
||||
Fullnode.prototype.fillHistory = function fillHistory(tx) {
|
||||
return this.mempool.fillAllHistory(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return bitcoinj-style confidence for a transaction.
|
||||
* @param {Hash|TX} tx
|
||||
* @param {Function} callback - Returns [Error, {@link Confidence}].
|
||||
* @returns {Promise} - Returns {@link Confidence}.
|
||||
*/
|
||||
|
||||
Fullnode.prototype.getConfidence = function getConfidence(tx, callback) {
|
||||
this.mempool.getConfidence(tx, callback);
|
||||
Fullnode.prototype.getConfidence = function getConfidence(tx) {
|
||||
return this.mempool.getConfidence(tx);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
7
lib/node/index.js
Normal file
7
lib/node/index.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
exports.config = require('./config');
|
||||
exports.Fullnode = require('./fullnode');
|
||||
exports.Logger = require('./logger');
|
||||
exports.Node = require('./node');
|
||||
exports.SPVNode = require('./spvnode');
|
||||
|
|
@ -349,6 +349,12 @@ Logger.prototype.memory = function memory() {
|
|||
utils.mb(mem.rss - mem.heapTotal));
|
||||
};
|
||||
|
||||
/*
|
||||
* Default
|
||||
*/
|
||||
|
||||
Logger.global = new Logger('none');
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,10 +7,14 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var AsyncObject = require('../utils/async');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var co = require('../utils/co');
|
||||
var assert = require('assert');
|
||||
var Network = require('../protocol/network');
|
||||
var Logger = require('./logger');
|
||||
var time = require('../net/timedata');
|
||||
var workers = require('../workers/workers');
|
||||
|
||||
/**
|
||||
* Base class from which every other
|
||||
|
|
@ -33,7 +37,7 @@ function Node(options) {
|
|||
this.parseOptions(options);
|
||||
|
||||
this.options = options;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.network = Network.get(options.network);
|
||||
this.prefix = options.prefix;
|
||||
|
||||
this.logger = options.logger;
|
||||
|
|
@ -62,7 +66,7 @@ Node.prototype.__init = function __init() {
|
|||
var self = this;
|
||||
|
||||
if (!this.logger) {
|
||||
this.logger = new bcoin.logger({
|
||||
this.logger = new Logger({
|
||||
level: this.options.logLevel || 'none',
|
||||
console: this.options.logConsole,
|
||||
file: this.options.logFile
|
||||
|
|
@ -87,28 +91,28 @@ Node.prototype._onOpen = function _onOpen() {
|
|||
|
||||
this.logger.open();
|
||||
|
||||
this._bind(bcoin.time, 'offset', function(offset) {
|
||||
this._bind(time, 'offset', function(offset) {
|
||||
self.logger.info('Time offset: %d (%d minutes).', offset, offset / 60 | 0);
|
||||
});
|
||||
|
||||
this._bind(bcoin.time, 'sample', function(sample, total) {
|
||||
this._bind(time, 'sample', function(sample, total) {
|
||||
self.logger.debug('Added time data: samples=%d, offset=%d (%d minutes).',
|
||||
total, sample, sample / 60 | 0);
|
||||
});
|
||||
|
||||
this._bind(bcoin.time, 'mismatch', function() {
|
||||
this._bind(time, 'mismatch', function() {
|
||||
self.logger.warning('Please make sure your system clock is correct!');
|
||||
});
|
||||
|
||||
this._bind(bcoin.workerPool, 'spawn', function(child) {
|
||||
this._bind(workers.pool, 'spawn', function(child) {
|
||||
self.logger.info('Spawning worker process: %d.', child.id);
|
||||
});
|
||||
|
||||
this._bind(bcoin.workerPool, 'exit', function(code, child) {
|
||||
this._bind(workers.pool, 'exit', function(code, child) {
|
||||
self.logger.warning('Worker %d exited: %s.', child.id, code);
|
||||
});
|
||||
|
||||
this._bind(bcoin.workerPool, 'error', function(err, child) {
|
||||
this._bind(workers.pool, 'error', function(err, child) {
|
||||
if (child) {
|
||||
self.logger.error('Worker %d error: %s', child.id, err.message);
|
||||
return;
|
||||
|
|
@ -179,7 +183,7 @@ Node.prototype._error = function _error(err) {
|
|||
*/
|
||||
|
||||
Node.prototype.parseOptions = function parseOptions(options) {
|
||||
options.network = bcoin.network.get(options.network);
|
||||
options.network = Network.get(options.network);
|
||||
|
||||
if (!options.prefix)
|
||||
options.prefix = utils.HOME + '/.bcoin';
|
||||
|
|
@ -229,12 +233,11 @@ Node.prototype.location = function location(name) {
|
|||
|
||||
/**
|
||||
* Open and ensure primary wallet.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Node.prototype.openWallet = function openWallet(callback) {
|
||||
var self = this;
|
||||
var options;
|
||||
Node.prototype.openWallet = co(function* openWallet() {
|
||||
var options, wallet;
|
||||
|
||||
assert(!this.wallet);
|
||||
|
||||
|
|
@ -243,34 +246,29 @@ Node.prototype.openWallet = function openWallet(callback) {
|
|||
passphrase: this.options.passphrase
|
||||
};
|
||||
|
||||
this.walletdb.ensure(options, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
wallet = yield this.walletdb.ensure(options);
|
||||
|
||||
self.logger.info(
|
||||
'Loaded wallet with id=%s wid=%d address=%s',
|
||||
wallet.id, wallet.wid, wallet.getAddress());
|
||||
this.logger.info(
|
||||
'Loaded wallet with id=%s wid=%d address=%s',
|
||||
wallet.id, wallet.wid, wallet.getAddress());
|
||||
|
||||
// Set the miner payout address if the
|
||||
// programmer didn't pass one in.
|
||||
if (self.miner) {
|
||||
if (!self.options.payoutAddress)
|
||||
self.miner.address = wallet.getAddress();
|
||||
}
|
||||
// Set the miner payout address if the
|
||||
// programmer didn't pass one in.
|
||||
if (this.miner) {
|
||||
if (!this.options.payoutAddress)
|
||||
this.miner.address = wallet.getAddress();
|
||||
}
|
||||
|
||||
self.wallet = wallet;
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
this.wallet = wallet;
|
||||
});
|
||||
|
||||
/**
|
||||
* Resend all pending transactions.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Node.prototype.resend = function resend(callback) {
|
||||
this.walletdb.resend(callback);
|
||||
Node.prototype.resend = function resend() {
|
||||
return this.walletdb.resend();
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -7,9 +7,19 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var Node = bcoin.node;
|
||||
var co = require('../utils/co');
|
||||
var Node = require('./node');
|
||||
var Chain = require('../chain/chain');
|
||||
var Pool = require('../net/pool');
|
||||
var WalletDB = require('../wallet/walletdb');
|
||||
var HTTPServer;
|
||||
|
||||
try {
|
||||
HTTPServer = require('../http/server');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an spv node which only maintains
|
||||
|
|
@ -40,7 +50,7 @@ function SPVNode(options) {
|
|||
|
||||
Node.call(this, options);
|
||||
|
||||
this.chain = new bcoin.chain({
|
||||
this.chain = new Chain({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
db: this.options.db,
|
||||
|
|
@ -51,7 +61,7 @@ function SPVNode(options) {
|
|||
spv: true
|
||||
});
|
||||
|
||||
this.pool = new bcoin.pool({
|
||||
this.pool = new Pool({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
chain: this.chain,
|
||||
|
|
@ -69,7 +79,7 @@ function SPVNode(options) {
|
|||
spv: true
|
||||
});
|
||||
|
||||
this.walletdb = new bcoin.walletdb({
|
||||
this.walletdb = new WalletDB({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
db: this.options.db,
|
||||
|
|
@ -80,7 +90,7 @@ function SPVNode(options) {
|
|||
});
|
||||
|
||||
if (!utils.isBrowser) {
|
||||
this.http = new bcoin.http.server({
|
||||
this.http = new HTTPServer({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
node: this,
|
||||
|
|
@ -122,20 +132,20 @@ SPVNode.prototype._init = function _init() {
|
|||
|
||||
this.pool.on('tx', function(tx) {
|
||||
self.emit('tx', tx);
|
||||
self.walletdb.addTX(tx, onError);
|
||||
self.walletdb.addTX(tx).catch(onError);
|
||||
});
|
||||
|
||||
this.chain.on('block', function(block, entry) {
|
||||
self.emit('block', block);
|
||||
self.walletdb.addBlock(entry, block.txs, onError);
|
||||
self.walletdb.addBlock(entry, block.txs).catch(onError);
|
||||
});
|
||||
|
||||
this.walletdb.on('save address', function(address, path) {
|
||||
self.pool.watch(address.getHash());
|
||||
this.walletdb.on('path', function(path) {
|
||||
self.pool.watch(path.hash, 'hex');
|
||||
});
|
||||
|
||||
this.walletdb.on('send', function(tx) {
|
||||
self.sendTX(tx, onError);
|
||||
self.sendTX(tx).catch(onError);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -143,108 +153,88 @@ SPVNode.prototype._init = function _init() {
|
|||
* Open the node and all its child objects,
|
||||
* wait for the database to load.
|
||||
* @alias SPVNode#open
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
SPVNode.prototype._open = function open(callback) {
|
||||
var self = this;
|
||||
SPVNode.prototype._open = co(function* open(callback) {
|
||||
yield this.chain.open();
|
||||
yield this.pool.open();
|
||||
yield this.walletdb.open();
|
||||
|
||||
utils.serial([
|
||||
this.chain.open.bind(this.chain),
|
||||
this.pool.open.bind(this.pool),
|
||||
this.walletdb.open.bind(this.walletdb),
|
||||
// Ensure primary wallet.
|
||||
this.openWallet.bind(this),
|
||||
// Load bloom filter.
|
||||
this.openFilter.bind(this),
|
||||
// Rescan for any missed transactions.
|
||||
this.rescan.bind(this),
|
||||
// Rebroadcast pending transactions.
|
||||
this.resend.bind(this),
|
||||
function(next) {
|
||||
if (!self.http)
|
||||
return next();
|
||||
self.http.open(next);
|
||||
}
|
||||
], function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
// Ensure primary wallet.
|
||||
yield this.openWallet();
|
||||
|
||||
self.logger.info('Node is loaded.');
|
||||
// Load bloom filter.
|
||||
yield this.openFilter();
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
// Rescan for any missed transactions.
|
||||
yield this.rescan();
|
||||
|
||||
// Rebroadcast pending transactions.
|
||||
yield this.resend();
|
||||
|
||||
if (this.http)
|
||||
yield this.http.open();
|
||||
|
||||
this.logger.info('Node is loaded.');
|
||||
});
|
||||
|
||||
/**
|
||||
* Close the node, wait for the database to close.
|
||||
* @alias SPVNode#close
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
SPVNode.prototype._close = function close(callback) {
|
||||
var self = this;
|
||||
SPVNode.prototype._close = co(function* close() {
|
||||
if (this.http)
|
||||
yield this.http.close();
|
||||
|
||||
yield this.wallet.destroy();
|
||||
|
||||
this.wallet = null;
|
||||
|
||||
utils.parallel([
|
||||
function(next) {
|
||||
if (!self.http)
|
||||
return next();
|
||||
self.http.close(next);
|
||||
},
|
||||
this.walletdb.close.bind(this.walletdb),
|
||||
this.pool.close.bind(this.pool),
|
||||
this.chain.close.bind(this.chain)
|
||||
], callback);
|
||||
};
|
||||
yield this.walletdb.close();
|
||||
yield this.pool.close();
|
||||
yield this.chain.close();
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize p2p bloom filter for address watching.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
SPVNode.prototype.openFilter = function openFilter(callback) {
|
||||
var self = this;
|
||||
SPVNode.prototype.openFilter = co(function* openFilter() {
|
||||
var hashes = yield this.walletdb.getAddressHashes();
|
||||
var i;
|
||||
|
||||
this.walletdb.getAddressHashes(function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
if (hashes.length > 0)
|
||||
this.logger.info('Adding %d addresses to filter.', hashes.length);
|
||||
|
||||
if (hashes.length > 0)
|
||||
self.logger.info('Adding %d addresses to filter.', hashes.length);
|
||||
|
||||
for (i = 0; i < hashes.length; i++)
|
||||
self.pool.watch(hashes[i], 'hex');
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
for (i = 0; i < hashes.length; i++)
|
||||
this.pool.watch(hashes[i], 'hex');
|
||||
});
|
||||
|
||||
/**
|
||||
* Rescan for any missed transactions.
|
||||
* Note that this will replay the blockchain sync.
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
SPVNode.prototype.rescan = function rescan(callback) {
|
||||
SPVNode.prototype.rescan = function rescan() {
|
||||
if (this.options.noScan) {
|
||||
this.walletdb.setTip(
|
||||
return this.walletdb.setTip(
|
||||
this.chain.tip.hash,
|
||||
this.chain.height,
|
||||
callback);
|
||||
return;
|
||||
this.chain.height);
|
||||
}
|
||||
|
||||
if (this.walletdb.height === 0)
|
||||
return callback();
|
||||
return Promise.resolve(null);
|
||||
|
||||
// Always replay the last block to make
|
||||
// sure we didn't miss anything: there
|
||||
// is no atomicity between the chaindb
|
||||
// and walletdb.
|
||||
this.chain.reset(this.walletdb.height - 1, callback);
|
||||
return this.chain.reset(this.walletdb.height - 1);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -252,11 +242,11 @@ SPVNode.prototype.rescan = function rescan(callback) {
|
|||
* by the mempool - use with care, lest you get banned from
|
||||
* bitcoind nodes).
|
||||
* @param {TX|Block} item
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
SPVNode.prototype.broadcast = function broadcast(item, callback) {
|
||||
return this.pool.broadcast(item, callback);
|
||||
SPVNode.prototype.broadcast = function broadcast(item) {
|
||||
return this.pool.broadcast(item);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -264,21 +254,11 @@ SPVNode.prototype.broadcast = function broadcast(item, callback) {
|
|||
* by the mempool - use with care, lest you get banned from
|
||||
* bitcoind nodes).
|
||||
* @param {TX} tx
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
SPVNode.prototype.sendTX = function sendTX(tx, wait, callback) {
|
||||
if (!callback) {
|
||||
callback = wait;
|
||||
wait = null;
|
||||
}
|
||||
|
||||
if (!wait) {
|
||||
this.pool.broadcast(tx);
|
||||
return utils.nextTick(callback);
|
||||
}
|
||||
|
||||
this.pool.broadcast(tx, callback);
|
||||
SPVNode.prototype.sendTX = function sendTX(tx) {
|
||||
return this.pool.broadcast(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,12 +7,17 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var constants = bcoin.constants;
|
||||
var utils = bcoin.utils;
|
||||
module.exports = AbstractBlock;
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var time = require('../net/timedata');
|
||||
var InvItem = require('./invitem');
|
||||
var Headers = require('./headers');
|
||||
|
||||
/**
|
||||
* The class which all block-like objects inherit from.
|
||||
|
|
@ -151,9 +156,9 @@ AbstractBlock.prototype.hash = function hash(enc) {
|
|||
*/
|
||||
|
||||
AbstractBlock.prototype.abbr = function abbr(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
p.writeHash(this.prevBlock);
|
||||
p.writeHash(this.merkleRoot);
|
||||
p.writeU32(this.ts);
|
||||
|
|
@ -205,7 +210,7 @@ AbstractBlock.prototype.verifyHeaders = function verifyHeaders(ret) {
|
|||
}
|
||||
|
||||
// Check timestamp against now + 2 hours
|
||||
if (this.ts > bcoin.now() + 2 * 60 * 60) {
|
||||
if (this.ts > time.now() + 2 * 60 * 60) {
|
||||
ret.reason = 'time-too-new';
|
||||
ret.score = 0;
|
||||
return false;
|
||||
|
|
@ -242,7 +247,7 @@ AbstractBlock.prototype.__defineGetter__('rhash', function() {
|
|||
*/
|
||||
|
||||
AbstractBlock.prototype.toInv = function toInv() {
|
||||
return new bcoin.invitem(constants.inv.BLOCK, this.hash('hex'));
|
||||
return new InvItem(constants.inv.BLOCK, this.hash('hex'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -251,7 +256,7 @@ AbstractBlock.prototype.toInv = function toInv() {
|
|||
*/
|
||||
|
||||
AbstractBlock.prototype.toHeaders = function toHeaders() {
|
||||
var headers = new bcoin.headers(this);
|
||||
var headers = new Headers(this);
|
||||
headers._hash = this._hash;
|
||||
headers._valid = true;
|
||||
return headers;
|
||||
|
|
|
|||
|
|
@ -7,16 +7,17 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var networks = bcoin.networks;
|
||||
var constants = bcoin.constants;
|
||||
module.exports = Address;
|
||||
|
||||
var Network = require('../protocol/network');
|
||||
var networks = require('../protocol/networks');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var Script = bcoin.script;
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
var Script = require('../script/script');
|
||||
|
||||
/**
|
||||
* Represents an address.
|
||||
|
|
@ -39,9 +40,9 @@ function Address(options) {
|
|||
return new Address(options);
|
||||
|
||||
this.hash = constants.ZERO_HASH160;
|
||||
this.type = scriptTypes.PUBKEYHASH;
|
||||
this.type = Script.types.PUBKEYHASH;
|
||||
this.version = -1;
|
||||
this.network = bcoin.network.get();
|
||||
this.network = Network.primary;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
|
|
@ -113,7 +114,7 @@ Address.prototype.toRaw = function toRaw(network) {
|
|||
if (!network)
|
||||
network = this.network;
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
network = Network.get(network);
|
||||
prefix = Address.getPrefix(this.type, network);
|
||||
|
||||
assert(prefix !== -1, 'Not a valid address prefix.');
|
||||
|
|
@ -258,42 +259,42 @@ Address.fromBase58 = function fromBase58(address) {
|
|||
Address.prototype.fromScript = function fromScript(script) {
|
||||
if (script.isPubkey()) {
|
||||
this.hash = crypto.hash160(script.get(0));
|
||||
this.type = scriptTypes.PUBKEYHASH;
|
||||
this.type = Script.types.PUBKEYHASH;
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isPubkeyhash()) {
|
||||
this.hash = script.get(2);
|
||||
this.type = scriptTypes.PUBKEYHASH;
|
||||
this.type = Script.types.PUBKEYHASH;
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isScripthash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = scriptTypes.SCRIPTHASH;
|
||||
this.type = Script.types.SCRIPTHASH;
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isWitnessPubkeyhash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = scriptTypes.WITNESSPUBKEYHASH;
|
||||
this.type = Script.types.WITNESSPUBKEYHASH;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isWitnessScripthash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = scriptTypes.WITNESSSCRIPTHASH;
|
||||
this.type = Script.types.WITNESSSCRIPTHASH;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isWitnessMasthash()) {
|
||||
this.hash = script.get(1);
|
||||
this.type = scriptTypes.WITNESSSCRIPTHASH;
|
||||
this.type = Script.types.WITNESSSCRIPTHASH;
|
||||
this.version = 1;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -301,7 +302,7 @@ Address.prototype.fromScript = function fromScript(script) {
|
|||
// Put this last: it's the slowest to check.
|
||||
if (script.isMultisig()) {
|
||||
this.hash = script.hash160();
|
||||
this.type = scriptTypes.SCRIPTHASH;
|
||||
this.type = Script.types.SCRIPTHASH;
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -318,14 +319,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
|
|||
// since we can't get the version.
|
||||
if (witness.isPubkeyhashInput()) {
|
||||
this.hash = crypto.hash160(witness.get(1));
|
||||
this.type = scriptTypes.WITNESSPUBKEYHASH;
|
||||
this.type = Script.types.WITNESSPUBKEYHASH;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (witness.isScripthashInput()) {
|
||||
this.hash = crypto.sha256(witness.get(witness.length - 1));
|
||||
this.type = scriptTypes.WITNESSSCRIPTHASH;
|
||||
this.type = Script.types.WITNESSSCRIPTHASH;
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -340,14 +341,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
|
|||
Address.prototype.fromInputScript = function fromInputScript(script) {
|
||||
if (script.isPubkeyhashInput()) {
|
||||
this.hash = crypto.hash160(script.get(1));
|
||||
this.type = scriptTypes.PUBKEYHASH;
|
||||
this.type = Script.types.PUBKEYHASH;
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (script.isScripthashInput()) {
|
||||
this.hash = crypto.hash160(script.get(script.length - 1));
|
||||
this.type = scriptTypes.SCRIPTHASH;
|
||||
this.type = Script.types.SCRIPTHASH;
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -405,15 +406,15 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) {
|
|||
hash = new Buffer(hash, 'hex');
|
||||
|
||||
if (typeof type === 'string')
|
||||
type = scriptTypes[type.toUpperCase()];
|
||||
type = Script.types[type.toUpperCase()];
|
||||
|
||||
if (type == null)
|
||||
type = scriptTypes.PUBKEYHASH;
|
||||
type = Script.types.PUBKEYHASH;
|
||||
|
||||
if (version == null)
|
||||
version = -1;
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
network = Network.get(network);
|
||||
|
||||
assert(Buffer.isBuffer(hash));
|
||||
assert(utils.isNumber(type));
|
||||
|
|
@ -427,11 +428,11 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) {
|
|||
} else {
|
||||
assert(Address.isWitness(type), 'Wrong version (non-witness).');
|
||||
assert(version >= 0 && version <= 16, 'Bad program version.');
|
||||
if (version === 0 && type === scriptTypes.WITNESSPUBKEYHASH)
|
||||
if (version === 0 && type === Script.types.WITNESSPUBKEYHASH)
|
||||
assert(hash.length === 20, 'Hash is the wrong size.');
|
||||
else if (version === 0 && type === scriptTypes.WITNESSSCRIPTHASH)
|
||||
else if (version === 0 && type === Script.types.WITNESSSCRIPTHASH)
|
||||
assert(hash.length === 32, 'Hash is the wrong size.');
|
||||
else if (version === 1 && type === scriptTypes.WITNESSSCRIPTHASH)
|
||||
else if (version === 1 && type === Script.types.WITNESSSCRIPTHASH)
|
||||
assert(hash.length === 32, 'Hash is the wrong size.');
|
||||
}
|
||||
|
||||
|
|
@ -468,9 +469,9 @@ Address.fromHash = function fromHash(hash, type, version, network) {
|
|||
|
||||
Address.prototype.fromData = function fromData(data, type, version, network) {
|
||||
if (typeof type === 'string')
|
||||
type = scriptTypes[type.toUpperCase()];
|
||||
type = Script.types[type.toUpperCase()];
|
||||
|
||||
if (type === scriptTypes.WITNESSSCRIPTHASH) {
|
||||
if (type === Script.types.WITNESSSCRIPTHASH) {
|
||||
if (version === 0) {
|
||||
assert(Buffer.isBuffer(data));
|
||||
data = crypto.sha256(data);
|
||||
|
|
@ -480,7 +481,7 @@ Address.prototype.fromData = function fromData(data, type, version, network) {
|
|||
} else {
|
||||
throw new Error('Cannot create from version=' + version);
|
||||
}
|
||||
} else if (type === scriptTypes.WITNESSPUBKEYHASH) {
|
||||
} else if (type === Script.types.WITNESSPUBKEYHASH) {
|
||||
if (version !== 0)
|
||||
throw new Error('Cannot create from version=' + version);
|
||||
assert(Buffer.isBuffer(data));
|
||||
|
|
@ -529,7 +530,7 @@ Address.validate = function validate(address, type) {
|
|||
}
|
||||
|
||||
if (typeof type === 'string')
|
||||
type = scriptTypes[type.toUpperCase()];
|
||||
type = Script.types[type.toUpperCase()];
|
||||
|
||||
if (type && address.type !== type)
|
||||
return false;
|
||||
|
|
@ -579,13 +580,13 @@ Address.getHash = function getHash(data, enc) {
|
|||
Address.getPrefix = function getPrefix(type, network) {
|
||||
var prefixes = network.addressPrefix;
|
||||
switch (type) {
|
||||
case scriptTypes.PUBKEYHASH:
|
||||
case Script.types.PUBKEYHASH:
|
||||
return prefixes.pubkeyhash;
|
||||
case scriptTypes.SCRIPTHASH:
|
||||
case Script.types.SCRIPTHASH:
|
||||
return prefixes.scripthash;
|
||||
case scriptTypes.WITNESSPUBKEYHASH:
|
||||
case Script.types.WITNESSPUBKEYHASH:
|
||||
return prefixes.witnesspubkeyhash;
|
||||
case scriptTypes.WITNESSSCRIPTHASH:
|
||||
case Script.types.WITNESSSCRIPTHASH:
|
||||
return prefixes.witnessscripthash;
|
||||
default:
|
||||
return -1;
|
||||
|
|
@ -603,13 +604,13 @@ Address.getType = function getType(prefix, network) {
|
|||
var prefixes = network.addressPrefix;
|
||||
switch (prefix) {
|
||||
case prefixes.pubkeyhash:
|
||||
return scriptTypes.PUBKEYHASH;
|
||||
return Script.types.PUBKEYHASH;
|
||||
case prefixes.scripthash:
|
||||
return scriptTypes.SCRIPTHASH;
|
||||
return Script.types.SCRIPTHASH;
|
||||
case prefixes.witnesspubkeyhash:
|
||||
return scriptTypes.WITNESSPUBKEYHASH;
|
||||
return Script.types.WITNESSPUBKEYHASH;
|
||||
case prefixes.witnessscripthash:
|
||||
return scriptTypes.WITNESSSCRIPTHASH;
|
||||
return Script.types.WITNESSSCRIPTHASH;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -623,9 +624,9 @@ Address.getType = function getType(prefix, network) {
|
|||
|
||||
Address.isWitness = function isWitness(type) {
|
||||
switch (type) {
|
||||
case scriptTypes.WITNESSPUBKEYHASH:
|
||||
case Script.types.WITNESSPUBKEYHASH:
|
||||
return true;
|
||||
case scriptTypes.WITNESSSCRIPTHASH:
|
||||
case Script.types.WITNESSSCRIPTHASH:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -7,13 +7,19 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Block;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var AbstractBlock = bcoin.abstractblock;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var AbstractBlock = require('./abstractblock');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var TX = require('./tx');
|
||||
var MerkleBlock = require('./merkleblock');
|
||||
var Network = require('../protocol/network');
|
||||
|
||||
/**
|
||||
* Represents a full block.
|
||||
|
|
@ -162,7 +168,7 @@ Block.prototype.getSizes = function getSizes() {
|
|||
};
|
||||
}
|
||||
|
||||
writer = new bcoin.writer();
|
||||
writer = new BufferWriter();
|
||||
this.toRaw(writer);
|
||||
|
||||
return {
|
||||
|
|
@ -262,7 +268,7 @@ Block.prototype.hasTX = function hasTX(hash) {
|
|||
Block.prototype.indexOf = function indexOf(hash) {
|
||||
var i;
|
||||
|
||||
if (hash instanceof bcoin.tx)
|
||||
if (hash instanceof TX)
|
||||
hash = hash.hash('hex');
|
||||
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
|
|
@ -534,7 +540,7 @@ Block.reward = function reward(height, network) {
|
|||
|
||||
assert(height >= 0, 'Bad height for reward.');
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
network = Network.get(network);
|
||||
halvings = height / network.halvingInterval | 0;
|
||||
|
||||
// BIP 42 (well, our own version of it,
|
||||
|
|
@ -647,7 +653,7 @@ Block.prototype.fromJSON = function fromJSON(json) {
|
|||
this.parseJSON(json);
|
||||
|
||||
for (i = 0; i < json.txs.length; i++)
|
||||
this.txs.push(bcoin.tx.fromJSON(json.txs[i]));
|
||||
this.txs.push(TX.fromJSON(json.txs[i]));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -669,7 +675,7 @@ Block.fromJSON = function fromJSON(json) {
|
|||
*/
|
||||
|
||||
Block.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, tx, witnessSize;
|
||||
|
||||
p.start();
|
||||
|
|
@ -685,7 +691,7 @@ Block.prototype.fromRaw = function fromRaw(data) {
|
|||
witnessSize = 0;
|
||||
|
||||
for (i = 0; i < this.totalTX; i++) {
|
||||
tx = bcoin.tx.fromRaw(p);
|
||||
tx = TX.fromRaw(p);
|
||||
witnessSize += tx._witnessSize;
|
||||
this.addTX(tx);
|
||||
}
|
||||
|
|
@ -721,7 +727,7 @@ Block.fromRaw = function fromRaw(data, enc) {
|
|||
*/
|
||||
|
||||
Block.prototype.toMerkle = function toMerkle(filter) {
|
||||
return bcoin.merkleblock.fromBlock(this, filter);
|
||||
return MerkleBlock.fromBlock(this, filter);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -733,11 +739,11 @@ Block.prototype.toMerkle = function toMerkle(filter) {
|
|||
*/
|
||||
|
||||
Block.prototype.frame = function frame(witness, writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var witnessSize = 0;
|
||||
var i, tx;
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
p.writeHash(this.prevBlock);
|
||||
p.writeHash(this.merkleRoot);
|
||||
p.writeU32(this.ts);
|
||||
|
|
|
|||
|
|
@ -7,11 +7,20 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Coin;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var constants = bcoin.constants;
|
||||
var assert = utils.assert;
|
||||
var Output = bcoin.output;
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var assert = require('assert');
|
||||
var Output = require('./output');
|
||||
var Script = require('../script/script');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var compressor = require('../chain/compress');
|
||||
var compress = compressor.compress;
|
||||
var decompress = compressor.decompress;
|
||||
|
||||
/**
|
||||
* Represents an unspent output.
|
||||
|
|
@ -36,7 +45,7 @@ function Coin(options) {
|
|||
this.version = 1;
|
||||
this.height = -1;
|
||||
this.value = 0;
|
||||
this.script = new bcoin.script();
|
||||
this.script = new Script();
|
||||
this.coinbase = true;
|
||||
this.hash = constants.NULL_HASH;
|
||||
this.index = 0;
|
||||
|
|
@ -95,7 +104,7 @@ Coin.fromOptions = function fromOptions(options) {
|
|||
|
||||
Coin.prototype.getConfirmations = function getConfirmations(height) {
|
||||
if (height == null)
|
||||
height = bcoin.network.get().height;
|
||||
height = Network.primary.height;
|
||||
|
||||
if (this.height === -1)
|
||||
return 0;
|
||||
|
|
@ -210,7 +219,7 @@ Coin.prototype.fromJSON = function fromJSON(json) {
|
|||
*/
|
||||
|
||||
Coin.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var height = this.height;
|
||||
|
||||
if (height === -1)
|
||||
|
|
@ -235,7 +244,7 @@ Coin.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
Coin.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.version = p.readU32();
|
||||
this.height = p.readU32();
|
||||
|
|
@ -269,8 +278,7 @@ Coin.fromRaw = function fromRaw(data, enc) {
|
|||
*/
|
||||
|
||||
Coin.prototype.toCompressed = function toCompressed(writer) {
|
||||
var compress = bcoin.coins.compress;
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var height = this.height;
|
||||
var bits;
|
||||
|
||||
|
|
@ -303,8 +311,7 @@ Coin.prototype.toCompressed = function toCompressed(writer) {
|
|||
*/
|
||||
|
||||
Coin.prototype.fromCompressed = function fromCompressed(data) {
|
||||
var decompress = bcoin.coins.decompress;
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var bits;
|
||||
|
||||
this.version = p.readVarint();
|
||||
|
|
@ -341,7 +348,7 @@ Coin.fromCompressed = function fromCompressed(data, enc) {
|
|||
*/
|
||||
|
||||
Coin.prototype.toExtended = function toExtended(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
this.toRaw(p);
|
||||
p.writeHash(this.hash);
|
||||
|
|
@ -360,7 +367,7 @@ Coin.prototype.toExtended = function toExtended(writer) {
|
|||
*/
|
||||
|
||||
Coin.prototype.fromExtended = function fromExtended(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.fromRaw(p);
|
||||
this.hash = p.readHash('hex');
|
||||
this.index = p.readU32();
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Headers;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var AbstractBlock = bcoin.abstractblock;
|
||||
var AbstractBlock = require('./abstractblock');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/**
|
||||
* Represents block headers obtained from the network via `headers`.
|
||||
|
|
@ -46,7 +49,7 @@ Headers.prototype._verify = function _verify(ret) {
|
|||
*/
|
||||
|
||||
Headers.prototype.getSize = function getSize() {
|
||||
var writer = new bcoin.writer();
|
||||
var writer = new BufferWriter();
|
||||
this.toRaw(writer);
|
||||
return writer.written;
|
||||
};
|
||||
|
|
@ -80,9 +83,9 @@ Headers.prototype.inspect = function inspect() {
|
|||
*/
|
||||
|
||||
Headers.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
p.writeHash(this.prevBlock);
|
||||
p.writeHash(this.merkleRoot);
|
||||
p.writeU32(this.ts);
|
||||
|
|
@ -103,7 +106,7 @@ Headers.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
Headers.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.version = p.readU32(); // Technically signed
|
||||
this.prevBlock = p.readHash('hex');
|
||||
|
|
@ -136,7 +139,7 @@ Headers.fromRaw = function fromRaw(data, enc) {
|
|||
*/
|
||||
|
||||
Headers.prototype.fromAbbr = function fromAbbr(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.version = p.readU32(); // Technically signed
|
||||
this.prevBlock = p.readHash('hex');
|
||||
|
|
|
|||
17
lib/primitives/index.js
Normal file
17
lib/primitives/index.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
exports.AbstractBlock = require('./abstractblock');
|
||||
exports.Address = require('./address');
|
||||
exports.Block = require('./block');
|
||||
exports.Coin = require('./coin');
|
||||
exports.Headers = require('./headers');
|
||||
exports.Input = require('./input');
|
||||
exports.InvItem = require('./invitem');
|
||||
exports.KeyRing = require('./keyring');
|
||||
exports.MemBlock = require('./memblock');
|
||||
exports.MerkleBlock = require('./merkleblock');
|
||||
exports.MTX = require('./mtx');
|
||||
exports.NetworkAddress = require('./netaddress');
|
||||
exports.Outpoint = require('./outpoint');
|
||||
exports.Output = require('./output');
|
||||
exports.TX = require('./tx');
|
||||
|
|
@ -7,11 +7,17 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Input;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var Script = require('../script/script');
|
||||
var Witness = require('../script/witness');
|
||||
var Outpoint = require('./outpoint');
|
||||
var Coin = require('./coin');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/**
|
||||
* Represents a transaction input.
|
||||
|
|
@ -30,9 +36,9 @@ function Input(options) {
|
|||
return new Input(options);
|
||||
|
||||
this.prevout = new Outpoint();
|
||||
this.script = new bcoin.script();
|
||||
this.script = new Script();
|
||||
this.sequence = 0xffffffff;
|
||||
this.witness = new bcoin.witness();
|
||||
this.witness = new Witness();
|
||||
this.coin = null;
|
||||
this.mutable = false;
|
||||
this._address = null;
|
||||
|
|
@ -65,7 +71,7 @@ Input.prototype.fromOptions = function fromOptions(options) {
|
|||
this.witness.fromOptions(options.witness);
|
||||
|
||||
if (options.coin)
|
||||
this.coin = bcoin.coin(options.coin);
|
||||
this.coin = Coin(options.coin);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
@ -277,7 +283,7 @@ Input.prototype.fromJSON = function fromJSON(json) {
|
|||
assert(json, 'Input data is required.');
|
||||
assert(utils.isNumber(json.sequence));
|
||||
this.prevout.fromJSON(json.prevout);
|
||||
this.coin = json.coin ? bcoin.coin.fromJSON(json.coin) : null;
|
||||
this.coin = json.coin ? Coin.fromJSON(json.coin) : null;
|
||||
this.script.fromJSON(json.script);
|
||||
this.witness.fromJSON(json.witness);
|
||||
this.sequence = json.sequence;
|
||||
|
|
@ -301,7 +307,7 @@ Input.fromJSON = function fromJSON(json) {
|
|||
*/
|
||||
|
||||
Input.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
this.prevout.toRaw(p);
|
||||
p.writeVarBytes(this.script.toRaw());
|
||||
|
|
@ -319,7 +325,7 @@ Input.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
Input.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.prevout.fromRaw(p);
|
||||
this.script.fromRaw(p.readVarBytes());
|
||||
|
|
@ -349,7 +355,7 @@ Input.fromRaw = function fromRaw(data, enc) {
|
|||
*/
|
||||
|
||||
Input.prototype.toExtended = function toExtended(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
this.toRaw(p);
|
||||
this.witness.toRaw(p);
|
||||
|
|
@ -367,7 +373,7 @@ Input.prototype.toExtended = function toExtended(writer) {
|
|||
*/
|
||||
|
||||
Input.prototype.fromExtended = function fromExtended(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.fromRaw(p);
|
||||
this.witness.fromRaw(p);
|
||||
return this;
|
||||
|
|
@ -420,7 +426,7 @@ Input.fromCoin = function fromCoin(coin) {
|
|||
*/
|
||||
|
||||
Input.prototype.fromTX = function fromTX(tx, index) {
|
||||
var coin = bcoin.coin.fromTX(tx, index);
|
||||
var coin = Coin.fromTX(tx, index);
|
||||
return this.fromCoin(coin);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = InvItem;
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/**
|
||||
* Inv Item
|
||||
|
|
@ -32,7 +35,7 @@ function InvItem(type, hash) {
|
|||
*/
|
||||
|
||||
InvItem.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeU32(this.type);
|
||||
p.writeHash(this.hash);
|
||||
|
|
@ -49,7 +52,7 @@ InvItem.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
InvItem.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.type = p.readU32();
|
||||
this.hash = p.readHash('hex');
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -7,44 +7,46 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var constants = bcoin.constants;
|
||||
var utils = bcoin.utils;
|
||||
module.exports = KeyRing;
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var networks = bcoin.networks;
|
||||
var assert = require('assert');
|
||||
var networks = require('../protocol/networks');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
var Script = require('../script/script');
|
||||
var Address = require('./address');
|
||||
var Input = require('./input');
|
||||
var Output = require('./output');
|
||||
var ec = require('../crypto/ec');
|
||||
|
||||
/**
|
||||
* Represents a key ring which amounts to an address.
|
||||
* @exports KeyRing
|
||||
* @constructor
|
||||
* @param {Object} options
|
||||
* @param {HDPrivateKey|HDPublicKey|Buffer} options.key
|
||||
* @param {Buffer[]} options.keys - Shared multisig keys.
|
||||
* @param {Number?} options.m - Multisig `m` value.
|
||||
* @param {Number?} options.n - Multisig `n` value.
|
||||
* @param {Boolean?} options.witness - Whether witness programs are enabled.
|
||||
* @param {Network} network
|
||||
*/
|
||||
|
||||
function KeyRing(options, network) {
|
||||
if (!(this instanceof KeyRing))
|
||||
return new KeyRing(options, network);
|
||||
|
||||
this.network = bcoin.network.get();
|
||||
this.network = Network.primary;
|
||||
this.witness = false;
|
||||
this.nested = false;
|
||||
this.publicKey = constants.ZERO_KEY;
|
||||
this.privateKey = null;
|
||||
this.script = null;
|
||||
this.path = null;
|
||||
|
||||
this._keyHash = null;
|
||||
this._keyAddress = null;
|
||||
this._program = null;
|
||||
this._programHash = null;
|
||||
this._programAddress = null;
|
||||
this._nestedHash = null;
|
||||
this._nestedAddress = null;
|
||||
this._scriptHash160 = null;
|
||||
this._scriptHash256 = null;
|
||||
this._scriptAddress = null;
|
||||
|
|
@ -61,6 +63,11 @@ function KeyRing(options, network) {
|
|||
|
||||
KeyRing.prototype.fromOptions = function fromOptions(options, network) {
|
||||
var key = toKey(options);
|
||||
var script = options.script;
|
||||
var compressed = options.compressed;
|
||||
|
||||
if (!network)
|
||||
network = options.network;
|
||||
|
||||
if (Buffer.isBuffer(key))
|
||||
return this.fromKey(key, network);
|
||||
|
|
@ -73,18 +80,20 @@ KeyRing.prototype.fromOptions = function fromOptions(options, network) {
|
|||
if (options.privateKey)
|
||||
key = toKey(options.privateKey);
|
||||
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network);
|
||||
|
||||
if (options.witness != null) {
|
||||
assert(typeof options.witness === 'boolean');
|
||||
this.witness = options.witness;
|
||||
}
|
||||
|
||||
if (options.script)
|
||||
return this.fromScript(key, options.script, this.network);
|
||||
if (options.nested != null) {
|
||||
assert(typeof options.nested === 'boolean');
|
||||
this.nested = options.nested;
|
||||
}
|
||||
|
||||
this.fromKey(key, this.network);
|
||||
if (script)
|
||||
return this.fromScript(key, script, compressed, network);
|
||||
|
||||
this.fromKey(key, compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -100,59 +109,82 @@ KeyRing.fromOptions = function fromOptions(options) {
|
|||
/**
|
||||
* Inject data from private key.
|
||||
* @private
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Buffer} key
|
||||
* @param {Boolean?} compressed
|
||||
* @param {(NetworkType|Network}) network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromPrivate = function fromPrivate(privateKey, network) {
|
||||
assert(Buffer.isBuffer(privateKey), 'Private key must be a buffer.');
|
||||
assert(bcoin.ec.privateKeyVerify(privateKey), 'Not a valid private key.');
|
||||
this.network = bcoin.network.get(network);
|
||||
this.privateKey = privateKey;
|
||||
this.publicKey = bcoin.ec.publicKeyCreate(this.privateKey, true);
|
||||
KeyRing.prototype.fromPrivate = function fromPrivate(key, compressed, network) {
|
||||
assert(Buffer.isBuffer(key), 'Private key must be a buffer.');
|
||||
assert(ec.privateKeyVerify(key), 'Not a valid private key.');
|
||||
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
}
|
||||
|
||||
this.network = Network.get(network);
|
||||
this.privateKey = key;
|
||||
this.publicKey = ec.publicKeyCreate(key, compressed !== false);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate keyring from a private key.
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Buffer} key
|
||||
* @param {Boolean?} compressed
|
||||
* @param {(NetworkType|Network}) network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromPrivate = function fromPrivate(privateKey, network) {
|
||||
return new KeyRing().fromPrivate(privateKey, network);
|
||||
KeyRing.fromPrivate = function fromPrivate(key, compressed, network) {
|
||||
return new KeyRing().fromPrivate(key, compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject data from public key.
|
||||
* @private
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Buffer} key
|
||||
* @param {(NetworkType|Network}) network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromPublic = function fromPublic(publicKey, network) {
|
||||
assert(Buffer.isBuffer(publicKey), 'Public key must be a buffer.');
|
||||
assert(bcoin.ec.publicKeyVerify(publicKey), 'Not a valid public key.');
|
||||
this.network = bcoin.network.get(network);
|
||||
this.publicKey = publicKey;
|
||||
KeyRing.prototype.fromPublic = function fromPublic(key, network) {
|
||||
assert(Buffer.isBuffer(key), 'Public key must be a buffer.');
|
||||
assert(ec.publicKeyVerify(key), 'Not a valid public key.');
|
||||
this.network = Network.get(network);
|
||||
this.publicKey = key;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a keyring.
|
||||
* @private
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.prototype.generate = function(compressed, network) {
|
||||
var key;
|
||||
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
}
|
||||
|
||||
key = ec.generatePrivateKey();
|
||||
|
||||
return this.fromKey(key, compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a keyring.
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.generate = function(network) {
|
||||
var key = new KeyRing();
|
||||
key.network = bcoin.network.get(network);
|
||||
key.privateKey = bcoin.ec.generatePrivateKey();
|
||||
key.publicKey = bcoin.ec.publicKeyCreate(key.privateKey, true);
|
||||
return key;
|
||||
KeyRing.generate = function(compressed, network) {
|
||||
return new KeyRing().generate(compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -162,8 +194,8 @@ KeyRing.generate = function(network) {
|
|||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromPublic = function fromPublic(publicKey, network) {
|
||||
return new KeyRing().fromPublic(publicKey, network);
|
||||
KeyRing.fromPublic = function fromPublic(key, network) {
|
||||
return new KeyRing().fromPublic(key, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -173,14 +205,18 @@ KeyRing.fromPublic = function fromPublic(publicKey, network) {
|
|||
* @param {(NetworkType|Network}) network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromKey = function fromKey(key, network) {
|
||||
KeyRing.prototype.fromKey = function fromKey(key, compressed, network) {
|
||||
assert(Buffer.isBuffer(key), 'Key must be a buffer.');
|
||||
assert(key.length === 32 || key.length === 33, 'Not a key.');
|
||||
|
||||
if (key.length === 33)
|
||||
return this.fromPublic(key, network);
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
}
|
||||
|
||||
return this.fromPrivate(key, network);
|
||||
if (key.length === 32)
|
||||
return this.fromPrivate(key, compressed !== false, network);
|
||||
|
||||
return this.fromPublic(key, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -190,8 +226,8 @@ KeyRing.prototype.fromKey = function fromKey(key, network) {
|
|||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromKey = function fromKey(key, network) {
|
||||
return new KeyRing().fromKey(key, network);
|
||||
KeyRing.fromKey = function fromKey(key, compressed, network) {
|
||||
return new KeyRing().fromKey(key, compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -202,10 +238,17 @@ KeyRing.fromKey = function fromKey(key, network) {
|
|||
* @param {(NetworkType|Network}) network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromScript = function fromScript(key, script, network) {
|
||||
assert(script instanceof bcoin.script, 'Non-script passed into KeyRing.');
|
||||
this.fromKey(key, network);
|
||||
KeyRing.prototype.fromScript = function fromScript(key, script, compressed, network) {
|
||||
assert(script instanceof Script, 'Non-script passed into KeyRing.');
|
||||
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
}
|
||||
|
||||
this.fromKey(key, compressed, network);
|
||||
this.script = script;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
|
@ -217,8 +260,8 @@ KeyRing.prototype.fromScript = function fromScript(key, script, network) {
|
|||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromScript = function fromScript(key, script, network) {
|
||||
return new KeyRing().fromScript(key, script, network);
|
||||
KeyRing.fromScript = function fromScript(key, script, compressed, network) {
|
||||
return new KeyRing().fromScript(key, script, compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -235,7 +278,8 @@ KeyRing.prototype.toSecret = function toSecret() {
|
|||
p.writeU8(this.network.keyPrefix.privkey);
|
||||
p.writeBytes(this.privateKey);
|
||||
|
||||
p.writeU8(1);
|
||||
if (this.publicKey.length === 33)
|
||||
p.writeU8(1);
|
||||
|
||||
p.writeChecksum();
|
||||
|
||||
|
|
@ -274,9 +318,7 @@ KeyRing.prototype.fromSecret = function fromSecret(data) {
|
|||
|
||||
p.verifyChecksum();
|
||||
|
||||
assert(compressed === false, 'Cannot handle uncompressed.');
|
||||
|
||||
return this.fromPrivate(key, type);
|
||||
return this.fromPrivate(key, compressed, type);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -347,10 +389,10 @@ KeyRing.prototype.getProgram = function getProgram() {
|
|||
if (!this._program) {
|
||||
if (!this.script) {
|
||||
hash = crypto.hash160(this.publicKey);
|
||||
program = bcoin.script.fromProgram(0, hash);
|
||||
program = Script.fromProgram(0, hash);
|
||||
} else {
|
||||
hash = this.script.sha256();
|
||||
program = bcoin.script.fromProgram(0, hash);
|
||||
program = Script.fromProgram(0, hash);
|
||||
}
|
||||
this._program = program;
|
||||
}
|
||||
|
|
@ -365,16 +407,16 @@ KeyRing.prototype.getProgram = function getProgram() {
|
|||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
KeyRing.prototype.getProgramHash = function getProgramHash(enc) {
|
||||
KeyRing.prototype.getNestedHash = function getNestedHash(enc) {
|
||||
if (!this.witness)
|
||||
return;
|
||||
|
||||
if (!this._programHash)
|
||||
this._programHash = this.getProgram().hash160();
|
||||
if (!this._nestedHash)
|
||||
this._nestedHash = this.getProgram().hash160();
|
||||
|
||||
return enc === 'hex'
|
||||
? this._programHash.toString('hex')
|
||||
: this._programHash;
|
||||
? this._nestedHash.toString('hex')
|
||||
: this._nestedHash;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -383,22 +425,22 @@ KeyRing.prototype.getProgramHash = function getProgramHash(enc) {
|
|||
* @returns {Address|Base58Address}
|
||||
*/
|
||||
|
||||
KeyRing.prototype.getProgramAddress = function getProgramAddress(enc) {
|
||||
KeyRing.prototype.getNestedAddress = function getNestedAddress(enc) {
|
||||
var hash, address;
|
||||
|
||||
if (!this.witness)
|
||||
return;
|
||||
|
||||
if (!this._programAddress) {
|
||||
hash = this.getProgramHash();
|
||||
address = this.compile(hash, scriptTypes.SCRIPTHASH);
|
||||
this._programAddress = address;
|
||||
if (!this._nestedAddress) {
|
||||
hash = this.getNestedHash();
|
||||
address = this.compile(hash, Script.types.SCRIPTHASH);
|
||||
this._nestedAddress = address;
|
||||
}
|
||||
|
||||
if (enc === 'base58')
|
||||
return this._programAddress.toBase58();
|
||||
return this._nestedAddress.toBase58();
|
||||
|
||||
return this._programAddress;
|
||||
return this._nestedAddress;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -464,10 +506,10 @@ KeyRing.prototype.getScriptAddress = function getScriptAddress(enc) {
|
|||
if (!this._scriptAddress) {
|
||||
if (this.witness) {
|
||||
hash = this.getScriptHash256();
|
||||
address = this.compile(hash, scriptTypes.WITNESSSCRIPTHASH, 0);
|
||||
address = this.compile(hash, Script.types.WITNESSSCRIPTHASH, 0);
|
||||
} else {
|
||||
hash = this.getScriptHash160();
|
||||
address = this.compile(hash, scriptTypes.SCRIPTHASH);
|
||||
address = this.compile(hash, Script.types.SCRIPTHASH);
|
||||
}
|
||||
this._scriptAddress = address;
|
||||
}
|
||||
|
|
@ -505,9 +547,9 @@ KeyRing.prototype.getKeyAddress = function getKeyAddress(enc) {
|
|||
if (!this._keyAddress) {
|
||||
hash = this.getKeyHash();
|
||||
if (this.witness)
|
||||
address = this.compile(hash, scriptTypes.WITNESSPUBKEYHASH, 0);
|
||||
address = this.compile(hash, Script.types.WITNESSPUBKEYHASH, 0);
|
||||
else
|
||||
address = this.compile(hash, scriptTypes.PUBKEYHASH);
|
||||
address = this.compile(hash, Script.types.PUBKEYHASH);
|
||||
this._keyAddress = address;
|
||||
}
|
||||
|
||||
|
|
@ -528,7 +570,7 @@ KeyRing.prototype.getKeyAddress = function getKeyAddress(enc) {
|
|||
*/
|
||||
|
||||
KeyRing.prototype.compile = function compile(hash, type, version) {
|
||||
return bcoin.address.fromHash(hash, type, version, this.network);
|
||||
return Address.fromHash(hash, type, version, this.network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -538,6 +580,8 @@ KeyRing.prototype.compile = function compile(hash, type, version) {
|
|||
*/
|
||||
|
||||
KeyRing.prototype.getHash = function getHash(enc) {
|
||||
if (this.nested)
|
||||
return this.getNestedHash(enc);
|
||||
if (this.script)
|
||||
return this.getScriptHash(enc);
|
||||
return this.getKeyHash(enc);
|
||||
|
|
@ -550,6 +594,8 @@ KeyRing.prototype.getHash = function getHash(enc) {
|
|||
*/
|
||||
|
||||
KeyRing.prototype.getAddress = function getAddress(enc) {
|
||||
if (this.nested)
|
||||
return this.getNestedAddress(enc);
|
||||
if (this.script)
|
||||
return this.getScriptAddress(enc);
|
||||
return this.getKeyAddress(enc);
|
||||
|
|
@ -572,7 +618,7 @@ KeyRing.prototype.ownHash = function ownHash(hash) {
|
|||
return true;
|
||||
|
||||
if (this.witness) {
|
||||
if (utils.equal(hash, this.programHash))
|
||||
if (utils.equal(hash, this.nestedHash))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -589,7 +635,7 @@ KeyRing.prototype.ownHash = function ownHash(hash) {
|
|||
KeyRing.prototype.ownInput = function ownInput(tx, index) {
|
||||
var input;
|
||||
|
||||
if (tx instanceof bcoin.input) {
|
||||
if (tx instanceof Input) {
|
||||
input = tx;
|
||||
} else {
|
||||
input = tx.inputs[index];
|
||||
|
|
@ -609,7 +655,7 @@ KeyRing.prototype.ownInput = function ownInput(tx, index) {
|
|||
KeyRing.prototype.ownOutput = function ownOutput(tx, index) {
|
||||
var output;
|
||||
|
||||
if (tx instanceof bcoin.output) {
|
||||
if (tx instanceof Output) {
|
||||
output = tx;
|
||||
} else {
|
||||
output = tx.outputs[index];
|
||||
|
|
@ -628,7 +674,7 @@ KeyRing.prototype.ownOutput = function ownOutput(tx, index) {
|
|||
|
||||
KeyRing.prototype.getRedeem = function(hash) {
|
||||
if (this.program) {
|
||||
if (utils.equal(hash, this.programHash))
|
||||
if (utils.equal(hash, this.nestedHash))
|
||||
return this.program;
|
||||
}
|
||||
|
||||
|
|
@ -651,7 +697,7 @@ KeyRing.prototype.getRedeem = function(hash) {
|
|||
|
||||
KeyRing.prototype.sign = function sign(msg) {
|
||||
assert(this.privateKey, 'Cannot sign without private key.');
|
||||
return bcoin.ec.sign(msg, this.privateKey);
|
||||
return ec.sign(msg, this.privateKey);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -662,7 +708,7 @@ KeyRing.prototype.sign = function sign(msg) {
|
|||
*/
|
||||
|
||||
KeyRing.prototype.verify = function verify(msg, sig) {
|
||||
return bcoin.ec.verify(msg, sig, this.publicKey);
|
||||
return ec.verify(msg, sig, this.publicKey);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -670,14 +716,35 @@ KeyRing.prototype.verify = function verify(msg, sig) {
|
|||
* @returns {ScriptType}
|
||||
*/
|
||||
|
||||
KeyRing.prototype.getVersion = function getVersion() {
|
||||
if (!this.witness)
|
||||
return -1;
|
||||
|
||||
if (this.nested)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get address type.
|
||||
* @returns {ScriptType}
|
||||
*/
|
||||
|
||||
KeyRing.prototype.getType = function getType() {
|
||||
if (this.program)
|
||||
return this.program.getType();
|
||||
if (this.nested)
|
||||
return Script.types.SCRIPTHASH;
|
||||
|
||||
if (this.witness) {
|
||||
if (this.script)
|
||||
return Script.types.WITNESSSCRIPTHASH;
|
||||
return Script.types.WITNESSPUBKEYHASH;
|
||||
}
|
||||
|
||||
if (this.script)
|
||||
return this.script.getType();
|
||||
return Script.types.SCRIPTHASH;
|
||||
|
||||
return scriptTypes.PUBKEYHASH;
|
||||
return Script.types.PUBKEYHASH;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -688,6 +755,10 @@ KeyRing.prototype.__defineGetter__('type', function() {
|
|||
return this.getType();
|
||||
});
|
||||
|
||||
KeyRing.prototype.__defineGetter__('version', function() {
|
||||
return this.getVersion();
|
||||
});
|
||||
|
||||
KeyRing.prototype.__defineGetter__('scriptHash', function() {
|
||||
return this.getScriptHash();
|
||||
});
|
||||
|
|
@ -708,12 +779,12 @@ KeyRing.prototype.__defineGetter__('program', function() {
|
|||
return this.getProgram();
|
||||
});
|
||||
|
||||
KeyRing.prototype.__defineGetter__('programHash', function() {
|
||||
return this.getProgramHash();
|
||||
KeyRing.prototype.__defineGetter__('nestedHash', function() {
|
||||
return this.getNestedHash();
|
||||
});
|
||||
|
||||
KeyRing.prototype.__defineGetter__('programAddress', function() {
|
||||
return this.getProgramAddress();
|
||||
KeyRing.prototype.__defineGetter__('nestedAddress', function() {
|
||||
return this.getNestedAddress();
|
||||
});
|
||||
|
||||
KeyRing.prototype.__defineGetter__('keyHash', function() {
|
||||
|
|
@ -750,17 +821,12 @@ KeyRing.prototype.toJSON = function toJSON() {
|
|||
return {
|
||||
network: this.network.type,
|
||||
witness: this.witness,
|
||||
nested: this.nested,
|
||||
publicKey: this.publicKey.toString('hex'),
|
||||
script: this.script ? this.script.toRaw().toString('hex') : null,
|
||||
program: this.program ? this.program.toRaw().toString('hex') : null,
|
||||
type: constants.scriptTypesByVal[this.type].toLowerCase(),
|
||||
wid: this.path ? this.path.wid : undefined,
|
||||
id: this.path ? this.path.id : undefined,
|
||||
name: this.path ? this.path.name : undefined,
|
||||
account: this.path ? this.path.account : undefined,
|
||||
change: this.path ? this.path.change : undefined,
|
||||
index: this.path ? this.path.index : undefined,
|
||||
address: this.getAddress('base58'),
|
||||
programAddress: this.getProgramAddress('base58')
|
||||
address: this.getAddress('base58')
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -774,11 +840,13 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
|
|||
assert(json);
|
||||
assert(typeof json.network === 'string');
|
||||
assert(typeof json.witness === 'boolean');
|
||||
assert(typeof json.nested === 'boolean');
|
||||
assert(typeof json.publicKey === 'string');
|
||||
assert(!json.script || typeof json.script === 'string');
|
||||
|
||||
this.nework = bcoin.network.get(json.network);
|
||||
this.nework = Network.get(json.network);
|
||||
this.witness = json.witness;
|
||||
this.nested = json.nested;
|
||||
this.publicKey = new Buffer(json.publicKey, 'hex');
|
||||
|
||||
if (json.script)
|
||||
|
|
@ -804,13 +872,22 @@ KeyRing.fromJSON = function fromJSON(json) {
|
|||
|
||||
KeyRing.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
var field = 0;
|
||||
|
||||
p.writeU8(this.witness ? 1 : 0);
|
||||
if (this.witness)
|
||||
field |= 1;
|
||||
|
||||
if (this.privateKey)
|
||||
if (this.nested)
|
||||
field |= 2;
|
||||
|
||||
p.writeU8(field);
|
||||
|
||||
if (this.privateKey) {
|
||||
p.writeVarBytes(this.privateKey);
|
||||
else
|
||||
p.writeU8(this.publicKey.length === 33);
|
||||
} else {
|
||||
p.writeVarBytes(this.publicKey);
|
||||
}
|
||||
|
||||
if (this.script)
|
||||
p.writeVarBytes(this.script.toRaw());
|
||||
|
|
@ -831,24 +908,30 @@ KeyRing.prototype.toRaw = function toRaw(writer) {
|
|||
|
||||
KeyRing.prototype.fromRaw = function fromRaw(data, network) {
|
||||
var p = new BufferReader(data);
|
||||
var key, script;
|
||||
var field, compressed, key, script;
|
||||
|
||||
this.network = bcoin.network.get(network);
|
||||
this.witness = p.readU8() === 1;
|
||||
this.network = Network.get(network);
|
||||
|
||||
field = p.readU8();
|
||||
|
||||
this.witness = (field & 1) !== 0;
|
||||
this.nested = (field & 2) !== 0;
|
||||
|
||||
key = p.readVarBytes();
|
||||
|
||||
if (key.length === 32) {
|
||||
compressed = p.readU8() === 1;
|
||||
this.privateKey = key;
|
||||
this.publicKey = bcoin.ec.publicKeyCreate(key, true);
|
||||
this.publicKey = ec.publicKeyCreate(key, compressed);
|
||||
} else {
|
||||
this.publicKey = key;
|
||||
assert(ec.publicKeyVerify(key), 'Invalid public key.');
|
||||
}
|
||||
|
||||
script = p.readVarBytes();
|
||||
|
||||
if (script.length > 0)
|
||||
this.script = bcoin.script.fromRaw(script);
|
||||
this.script = Script.fromRaw(script);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,9 +7,13 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = MemBlock;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var AbstractBlock = bcoin.abstractblock;
|
||||
var AbstractBlock = require('./abstractblock');
|
||||
var Block = require('./block');
|
||||
var Script = require('../script/script');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/**
|
||||
* A block object which is essentially a "placeholder"
|
||||
|
|
@ -113,7 +117,7 @@ MemBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||
*/
|
||||
|
||||
MemBlock.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data, true);
|
||||
var p = BufferReader(data, true);
|
||||
var height = -1;
|
||||
var inCount, input;
|
||||
|
||||
|
|
@ -137,7 +141,7 @@ MemBlock.prototype.fromRaw = function fromRaw(data) {
|
|||
if (inCount > 0) {
|
||||
p.seek(36);
|
||||
input = p.readVarBytes();
|
||||
height = bcoin.script.getCoinbaseHeight(input);
|
||||
height = Script.getCoinbaseHeight(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +187,7 @@ MemBlock.prototype.toNormal = function toNormal() {
|
|||
*/
|
||||
|
||||
MemBlock.prototype.toBlock = function toBlock() {
|
||||
var block = bcoin.block.fromRaw(this.raw);
|
||||
var block = Block.fromRaw(this.raw);
|
||||
block._hash = this._hash;
|
||||
block._cbHeight = this.coinbaseHeight;
|
||||
this.raw = null;
|
||||
|
|
|
|||
|
|
@ -7,14 +7,18 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = MerkleBlock;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var DUMMY = new Buffer([0]);
|
||||
var AbstractBlock = bcoin.abstractblock;
|
||||
var AbstractBlock = require('./abstractblock');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var TX = require('./tx');
|
||||
|
||||
/**
|
||||
* Represents a merkle (filtered) block.
|
||||
|
|
@ -91,7 +95,7 @@ MerkleBlock.fromOptions = function fromOptions(data) {
|
|||
*/
|
||||
|
||||
MerkleBlock.prototype.getSize = function getSize() {
|
||||
var writer = new bcoin.writer();
|
||||
var writer = new BufferWriter();
|
||||
this.toRaw(writer);
|
||||
return writer.written;
|
||||
};
|
||||
|
|
@ -131,7 +135,7 @@ MerkleBlock.prototype.hasTX = function hasTX(hash) {
|
|||
MerkleBlock.prototype.indexOf = function indexOf(hash) {
|
||||
var index;
|
||||
|
||||
if (hash instanceof bcoin.tx)
|
||||
if (hash instanceof TX)
|
||||
hash = hash.hash('hex');
|
||||
|
||||
this.verifyPartial();
|
||||
|
|
@ -341,7 +345,7 @@ MerkleBlock.prototype.inspect = function inspect() {
|
|||
*/
|
||||
|
||||
MerkleBlock.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeU32(this.version);
|
||||
|
|
@ -372,7 +376,7 @@ MerkleBlock.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
MerkleBlock.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, hashCount;
|
||||
|
||||
this.version = p.readU32();
|
||||
|
|
|
|||
|
|
@ -7,15 +7,24 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = MTX;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var Script = bcoin.script;
|
||||
var opcodes = constants.opcodes;
|
||||
var FundingError = bcoin.errors.FundingError;
|
||||
var TX = bcoin.tx;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var Script = require('../script/script');
|
||||
var opcodes = Script.opcodes;
|
||||
var FundingError = require('../utils/errors').FundingError;
|
||||
var TX = require('./tx');
|
||||
var Input = require('./input');
|
||||
var Output = require('./output');
|
||||
var Coin = require('./coin');
|
||||
var KeyRing = require('./keyring');
|
||||
var Address = require('./address');
|
||||
var ec = require('../crypto/ec');
|
||||
var workers = require('../workers/workers');
|
||||
|
||||
/**
|
||||
* A mutable transaction object.
|
||||
|
|
@ -150,12 +159,12 @@ MTX.prototype.clone = function clone() {
|
|||
*/
|
||||
|
||||
MTX.prototype.addInput = function addInput(options, index) {
|
||||
var input = new bcoin.input();
|
||||
var input = new Input();
|
||||
input.mutable = true;
|
||||
|
||||
if (options instanceof TX)
|
||||
input.fromTX(options, index);
|
||||
else if (options instanceof bcoin.coin)
|
||||
else if (options instanceof Coin)
|
||||
input.fromCoin(options);
|
||||
else
|
||||
input.fromOptions(options);
|
||||
|
|
@ -179,18 +188,16 @@ MTX.prototype.addInput = function addInput(options, index) {
|
|||
MTX.prototype.addOutput = function addOutput(options, value) {
|
||||
var output;
|
||||
|
||||
if ((options instanceof bcoin.wallet)
|
||||
|| (options instanceof bcoin.keyring)) {
|
||||
if (options instanceof KeyRing)
|
||||
options = options.getAddress();
|
||||
}
|
||||
|
||||
if (typeof options === 'string')
|
||||
options = bcoin.address.fromBase58(options);
|
||||
options = Address.fromBase58(options);
|
||||
|
||||
if (options instanceof bcoin.address)
|
||||
if (options instanceof Address)
|
||||
options = Script.fromAddress(options);
|
||||
|
||||
output = new bcoin.output();
|
||||
output = new Output();
|
||||
output.mutable = true;
|
||||
|
||||
if (options instanceof Script) {
|
||||
|
|
@ -385,6 +392,19 @@ MTX.prototype.scriptVector = function scriptVector(prev, vector, ring) {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign a transaction input on the worker pool
|
||||
* (if workers are enabled).
|
||||
* @param {Number} index
|
||||
* @param {Buffer} key
|
||||
* @param {SighashType?} type
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
MTX.prototype.signInputAsync = function signInputAsync(index, key, type) {
|
||||
return workers.pool.signInput(this, index, key, type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign an input.
|
||||
* @param {Number} index - Index of input being signed.
|
||||
|
|
@ -462,7 +482,7 @@ MTX.prototype.signInput = function signInput(index, key, type) {
|
|||
*/
|
||||
|
||||
MTX.prototype.signVector = function signVector(prev, vector, sig, key) {
|
||||
var pub = bcoin.ec.publicKeyCreate(key, true);
|
||||
var pub = ec.publicKeyCreate(key, true);
|
||||
var i, m, n, keys, keyIndex, total;
|
||||
|
||||
// P2PK
|
||||
|
|
@ -820,6 +840,12 @@ MTX.prototype.template = function template(ring) {
|
|||
var total = 0;
|
||||
var i;
|
||||
|
||||
if (Array.isArray(ring)) {
|
||||
for (i = 0; i < ring.length; i++)
|
||||
total += this.template(ring[i]);
|
||||
return total;
|
||||
}
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
if (!ring.ownInput(this, i))
|
||||
continue;
|
||||
|
|
@ -879,29 +905,12 @@ MTX.prototype.sign = function sign(ring, type) {
|
|||
* (if workers are enabled).
|
||||
* @param {KeyRing} ring
|
||||
* @param {SighashType?} type
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
* @returns {Boolean} Whether the inputs are valid.
|
||||
*/
|
||||
|
||||
MTX.prototype.signAsync = function signAsync(ring, type, callback) {
|
||||
var result;
|
||||
|
||||
if (typeof type === 'function') {
|
||||
callback = type;
|
||||
type = null;
|
||||
}
|
||||
|
||||
if (!bcoin.useWorkers) {
|
||||
callback = utils.asyncify(callback);
|
||||
try {
|
||||
result = this.sign(ring, type);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
return callback(null, result);
|
||||
}
|
||||
|
||||
bcoin.workerPool.sign(this, ring, type, callback);
|
||||
MTX.prototype.signAsync = function signAsync(ring, type) {
|
||||
return workers.pool.sign(this, ring, type);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1002,7 +1011,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
|||
if (redeem) {
|
||||
prev = redeem;
|
||||
sz = prev.getSize();
|
||||
size += bcoin.script.sizePush(sz);
|
||||
size += Script.sizePush(sz);
|
||||
size += sz;
|
||||
}
|
||||
}
|
||||
|
|
@ -1124,8 +1133,8 @@ MTX.prototype._guessRedeem = function guessRedeem(options, hash) {
|
|||
case 20:
|
||||
if (options.witness) {
|
||||
if (options.n > 1)
|
||||
return bcoin.script.fromProgram(0, constants.ZERO_HASH);
|
||||
return bcoin.script.fromProgram(0, constants.ZERO_HASH160);
|
||||
return Script.fromProgram(0, constants.ZERO_HASH);
|
||||
return Script.fromProgram(0, constants.ZERO_HASH160);
|
||||
}
|
||||
return options.script;
|
||||
case 32:
|
||||
|
|
@ -1175,7 +1184,7 @@ MTX.prototype.subtractFee = function subtractFee(fee, index) {
|
|||
if (Array.isArray(index)) {
|
||||
addrs = [];
|
||||
for (i = 0; i < index.length; i++) {
|
||||
hash = bcoin.address.getHash(index[i]);
|
||||
hash = Address.getHash(index[i]);
|
||||
if (hash)
|
||||
addrs.push(hash);
|
||||
}
|
||||
|
|
@ -1308,7 +1317,7 @@ MTX.prototype.sortMembers = function sortMembers() {
|
|||
|
||||
MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
||||
if (height == null)
|
||||
height = bcoin.network.get().height;
|
||||
height = Network.primary.height;
|
||||
|
||||
if (height === -1)
|
||||
height = 0;
|
||||
|
|
@ -1533,9 +1542,9 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
|
|||
if (options.changeAddress) {
|
||||
addr = options.changeAddress;
|
||||
if (typeof addr === 'string') {
|
||||
this.changeAddress = bcoin.address.fromBase58(addr);
|
||||
this.changeAddress = Address.fromBase58(addr);
|
||||
} else {
|
||||
assert(addr instanceof bcoin.address);
|
||||
assert(addr instanceof Address);
|
||||
this.changeAddress = addr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1558,7 +1567,7 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
|
|||
}
|
||||
|
||||
if (options.script) {
|
||||
assert(options.script instanceof bcoin.script);
|
||||
assert(options.script instanceof Script);
|
||||
this.script = options.script;
|
||||
}
|
||||
|
||||
|
|
@ -1660,9 +1669,9 @@ CoinSelector.prototype.getFee = function getFee(size) {
|
|||
var fee;
|
||||
|
||||
if (this.round)
|
||||
fee = bcoin.tx.getRoundFee(size, this.rate);
|
||||
fee = TX.getRoundFee(size, this.rate);
|
||||
else
|
||||
fee = bcoin.tx.getMinFee(size, this.rate);
|
||||
fee = TX.getMinFee(size, this.rate);
|
||||
|
||||
if (fee > constants.tx.MAX_FEE)
|
||||
fee = constants.tx.MAX_FEE;
|
||||
|
|
|
|||
|
|
@ -6,11 +6,16 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = NetworkAddress;
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var time = require('../net/timedata');
|
||||
var utils = require('../utils/utils');
|
||||
var IP = require('../utils/ip');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/**
|
||||
* Represents a network address.
|
||||
|
|
@ -183,14 +188,14 @@ NetworkAddress.prototype.inspect = function inspect() {
|
|||
NetworkAddress.prototype.fromHostname = function fromHostname(hostname, network) {
|
||||
var address = IP.parseHost(hostname);
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
network = Network.get(network);
|
||||
|
||||
this.host = address.host;
|
||||
this.port = address.port || network.port;
|
||||
this.services = constants.services.NETWORK
|
||||
| constants.services.BLOOM
|
||||
| constants.services.WITNESS;
|
||||
this.ts = bcoin.now();
|
||||
this.ts = time.now();
|
||||
|
||||
this.hostname = IP.hostname(this.host, this.port);
|
||||
|
||||
|
|
@ -224,7 +229,7 @@ NetworkAddress.prototype.fromSocket = function fromSocket(socket) {
|
|||
this.services = constants.services.NETWORK
|
||||
| constants.services.BLOOM
|
||||
| constants.services.WITNESS;
|
||||
this.ts = bcoin.now();
|
||||
this.ts = time.now();
|
||||
|
||||
this.hostname = IP.hostname(this.host, this.port);
|
||||
|
||||
|
|
@ -250,8 +255,8 @@ NetworkAddress.fromSocket = function fromSocket(hostname) {
|
|||
*/
|
||||
|
||||
NetworkAddress.prototype.fromRaw = function fromRaw(data, full) {
|
||||
var p = bcoin.reader(data);
|
||||
var now = bcoin.now();
|
||||
var p = BufferReader(data);
|
||||
var now = time.now();
|
||||
|
||||
// only version >= 31402
|
||||
this.ts = full ? p.readU32() : 0;
|
||||
|
|
@ -285,7 +290,7 @@ NetworkAddress.fromRaw = function fromRaw(data, full) {
|
|||
*/
|
||||
|
||||
NetworkAddress.prototype.toRaw = function toRaw(full, writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
if (full)
|
||||
p.writeU32(this.ts);
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Outpoint;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/**
|
||||
* Represents a COutPoint.
|
||||
|
|
@ -69,7 +72,7 @@ Outpoint.prototype.isNull = function isNull() {
|
|||
*/
|
||||
|
||||
Outpoint.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.writeHash(this.hash);
|
||||
p.writeU32(this.index);
|
||||
|
|
@ -87,7 +90,7 @@ Outpoint.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
Outpoint.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
this.hash = p.readHash('hex');
|
||||
this.index = p.readU32();
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,15 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Output;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var constants = bcoin.constants;
|
||||
var assert = utils.assert;
|
||||
var constants = require('../protocol/constants');
|
||||
var Script = require('../script/script');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var assert = require('assert');
|
||||
var TX = require('./tx');
|
||||
|
||||
/**
|
||||
* Represents a transaction output.
|
||||
|
|
@ -26,7 +31,7 @@ function Output(options) {
|
|||
return new Output(options);
|
||||
|
||||
this.value = 0;
|
||||
this.script = new bcoin.script();
|
||||
this.script = new Script();
|
||||
this.mutable = false;
|
||||
this._address = null;
|
||||
|
||||
|
|
@ -165,7 +170,7 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
|
|||
size += 32 + 4 + 1 + 107 + 4;
|
||||
}
|
||||
|
||||
return 3 * bcoin.tx.getMinFee(size, rate);
|
||||
return 3 * TX.getMinFee(size, rate);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -174,7 +179,7 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
|
|||
*/
|
||||
|
||||
Output.prototype.getSize = function getSize() {
|
||||
return this.toRaw(bcoin.writer()).written;
|
||||
return this.toRaw(BufferWriter()).written;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -217,7 +222,7 @@ Output.fromJSON = function fromJSON(json) {
|
|||
*/
|
||||
|
||||
Output.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
|
||||
p.write64(this.value);
|
||||
p.writeVarBytes(this.script.toRaw());
|
||||
|
|
@ -235,7 +240,7 @@ Output.prototype.toRaw = function toRaw(writer) {
|
|||
*/
|
||||
|
||||
Output.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
|
||||
this.value = p.read64N();
|
||||
this.script.fromRaw(p.readVarBytes());
|
||||
|
|
|
|||
|
|
@ -7,15 +7,25 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = TX;
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var Script = bcoin.script;
|
||||
var Stack = bcoin.stack;
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var Script = require('../script/script');
|
||||
var Stack = require('../script/stack');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var Input = require('./input');
|
||||
var Output = require('./output');
|
||||
var Outpoint = require('./outpoint');
|
||||
var Coin = require('./coin');
|
||||
var InvItem = require('./invitem');
|
||||
var workers = require('../workers/workers');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
|
|
@ -117,13 +127,13 @@ TX.prototype.fromOptions = function fromOptions(options) {
|
|||
if (options.inputs) {
|
||||
assert(Array.isArray(options.inputs));
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
this.inputs.push(new bcoin.input(options.inputs[i]));
|
||||
this.inputs.push(new Input(options.inputs[i]));
|
||||
}
|
||||
|
||||
if (options.outputs) {
|
||||
assert(Array.isArray(options.outputs));
|
||||
for (i = 0; i < options.outputs.length; i++)
|
||||
this.outputs.push(new bcoin.output(options.outputs[i]));
|
||||
this.outputs.push(new Output(options.outputs[i]));
|
||||
}
|
||||
|
||||
if (options.locktime != null) {
|
||||
|
|
@ -474,7 +484,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
|||
// Remove all code separators.
|
||||
prev = prev.removeSeparators();
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
|
||||
if (type & constants.hashType.ANYONECANPAY) {
|
||||
p.writeVarint(1);
|
||||
|
|
@ -628,7 +638,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
|
|||
hashOutputs = utils.copy(constants.ZERO_HASH);
|
||||
}
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
p.writeBytes(hashPrevouts);
|
||||
p.writeBytes(hashSequence);
|
||||
p.writeHash(this.inputs[index].prevout.hash);
|
||||
|
|
@ -709,39 +719,39 @@ TX.prototype.verifyInput = function verifyInput(index, flags) {
|
|||
* Verify the transaction inputs on the worker pool
|
||||
* (if workers are enabled).
|
||||
* @param {VerifyFlags?} [flags=STANDARD_VERIFY_FLAGS]
|
||||
* @param {Function} callback
|
||||
* @returns {Promise}
|
||||
* @returns {Boolean} Whether the inputs are valid.
|
||||
*/
|
||||
|
||||
TX.prototype.verifyAsync = function verifyAsync(flags, callback) {
|
||||
var result;
|
||||
TX.prototype.verifyAsync = function verifyAsync(flags) {
|
||||
if (this.inputs.length === 0)
|
||||
return Promise.resolve(false);
|
||||
|
||||
if (typeof flags === 'function') {
|
||||
callback = flags;
|
||||
flags = null;
|
||||
}
|
||||
if (this.isCoinbase())
|
||||
return Promise.resolve(true);
|
||||
|
||||
if (!bcoin.useWorkers) {
|
||||
callback = utils.asyncify(callback);
|
||||
try {
|
||||
result = this.verify(flags);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
return callback(null, result);
|
||||
}
|
||||
return workers.pool.verify(this, flags);
|
||||
};
|
||||
|
||||
if (this.inputs.length === 0) {
|
||||
callback = utils.asyncify(callback);
|
||||
return callback(null, false);
|
||||
}
|
||||
/**
|
||||
* Verify a transaction input asynchronously.
|
||||
* @param {Number} index - Index of output being
|
||||
* verified.
|
||||
* @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS]
|
||||
* @returns {Boolean} Whether the input is valid.
|
||||
*/
|
||||
|
||||
if (this.isCoinbase()) {
|
||||
callback = utils.asyncify(callback);
|
||||
return callback(null, true);
|
||||
}
|
||||
TX.prototype.verifyInputAsync = function verifyInputAsync(index, flags) {
|
||||
var input;
|
||||
|
||||
bcoin.workerPool.verify(this, flags, callback);
|
||||
if (typeof index === 'object')
|
||||
index = this.inputs.indexOf(index);
|
||||
|
||||
input = this.inputs[index];
|
||||
|
||||
assert(input, 'Input does not exist.');
|
||||
|
||||
return workers.pool.verifyInput(this, index, flags);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -968,7 +978,7 @@ TX.prototype.fillCoins = function fillCoins(coins) {
|
|||
var result = true;
|
||||
var i, input, hash, index, map, coin;
|
||||
|
||||
if ((coins instanceof bcoin.coin)
|
||||
if ((coins instanceof Coin)
|
||||
|| (coins instanceof TX)) {
|
||||
coins = [coins];
|
||||
}
|
||||
|
|
@ -979,7 +989,7 @@ TX.prototype.fillCoins = function fillCoins(coins) {
|
|||
coin = coins[i];
|
||||
if (coin instanceof TX) {
|
||||
map[coin.hash('hex')] = coin;
|
||||
} else if (coin instanceof bcoin.coin) {
|
||||
} else if (coin instanceof Coin) {
|
||||
assert(typeof coin.hash === 'string');
|
||||
assert(typeof coin.index === 'number');
|
||||
map[coin.hash + coin.index] = coin;
|
||||
|
|
@ -1001,7 +1011,7 @@ TX.prototype.fillCoins = function fillCoins(coins) {
|
|||
coin = coins[hash];
|
||||
|
||||
if (coin) {
|
||||
input.coin = bcoin.coin.fromTX(coin, index);
|
||||
input.coin = Coin.fromTX(coin, index);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1486,7 +1496,7 @@ TX.prototype.getWitnessStandard = function getWitnessStandard() {
|
|||
ret = BAD_NONSTD_P2WSH;
|
||||
}
|
||||
|
||||
redeem = new bcoin.script(redeem);
|
||||
redeem = new Script(redeem);
|
||||
|
||||
if (redeem.isPubkey()) {
|
||||
if (input.witness.length - 1 !== 1)
|
||||
|
|
@ -1662,7 +1672,7 @@ TX.prototype.getPriority = function getPriority(height, size) {
|
|||
if (height == null) {
|
||||
height = this.height;
|
||||
if (height === -1)
|
||||
height = bcoin.network.get().height;
|
||||
height = Network.primary.height;
|
||||
}
|
||||
|
||||
if (size == null)
|
||||
|
|
@ -1791,7 +1801,7 @@ TX.prototype.getRate = function getRate(size) {
|
|||
|
||||
TX.prototype.getConfirmations = function getConfirmations(height) {
|
||||
if (height == null)
|
||||
height = bcoin.network.get().height;
|
||||
height = Network.primary.height;
|
||||
|
||||
if (this.height === -1)
|
||||
return 0;
|
||||
|
|
@ -1851,11 +1861,11 @@ TX.prototype.isWatched = function isWatched(filter) {
|
|||
// Test the output script
|
||||
if (output.script.test(filter)) {
|
||||
if (filter.update === constants.filterFlags.ALL) {
|
||||
outpoint = bcoin.outpoint.fromTX(this, i);
|
||||
outpoint = Outpoint.fromTX(this, i);
|
||||
filter.add(outpoint.toRaw());
|
||||
} else if (filter.update === constants.filterFlags.PUBKEY_ONLY) {
|
||||
if (output.script.isPubkey() || output.script.isMultisig()) {
|
||||
outpoint = bcoin.outpoint.fromTX(this, i);
|
||||
outpoint = Outpoint.fromTX(this, i);
|
||||
filter.add(outpoint.toRaw());
|
||||
}
|
||||
}
|
||||
|
|
@ -1917,7 +1927,7 @@ TX.prototype.__defineGetter__('wtxid', function() {
|
|||
*/
|
||||
|
||||
TX.prototype.toInv = function toInv() {
|
||||
return new bcoin.invitem(constants.inv.TX, this.hash('hex'));
|
||||
return new InvItem(constants.inv.TX, this.hash('hex'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2074,12 +2084,12 @@ TX.prototype.fromJSON = function fromJSON(json) {
|
|||
|
||||
for (i = 0; i < json.inputs.length; i++) {
|
||||
input = json.inputs[i];
|
||||
this.inputs.push(bcoin.input.fromJSON(input));
|
||||
this.inputs.push(Input.fromJSON(input));
|
||||
}
|
||||
|
||||
for (i = 0; i < json.outputs.length; i++) {
|
||||
output = json.outputs[i];
|
||||
this.outputs.push(bcoin.output.fromJSON(output));
|
||||
this.outputs.push(Output.fromJSON(output));
|
||||
}
|
||||
|
||||
this.locktime = json.locktime;
|
||||
|
|
@ -2118,25 +2128,25 @@ TX.fromRaw = function fromRaw(data, enc) {
|
|||
*/
|
||||
|
||||
TX.prototype.fromRaw = function fromRaw(data) {
|
||||
var p, i, inCount, outCount;
|
||||
var p, i, count;
|
||||
|
||||
if (TX.isWitness(data))
|
||||
return this.fromWitness(data);
|
||||
|
||||
p = bcoin.reader(data);
|
||||
p = BufferReader(data);
|
||||
p.start();
|
||||
|
||||
this.version = p.readU32(); // Technically signed
|
||||
|
||||
inCount = p.readVarint();
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < inCount; i++)
|
||||
this.inputs.push(bcoin.input.fromRaw(p));
|
||||
for (i = 0; i < count; i++)
|
||||
this.inputs.push(Input.fromRaw(p));
|
||||
|
||||
outCount = p.readVarint();
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < outCount; i++)
|
||||
this.outputs.push(bcoin.output.fromRaw(p));
|
||||
for (i = 0; i < count; i++)
|
||||
this.outputs.push(Output.fromRaw(p));
|
||||
|
||||
this.locktime = p.readU32();
|
||||
|
||||
|
|
@ -2159,49 +2169,61 @@ TX.prototype.fromRaw = function fromRaw(data) {
|
|||
*/
|
||||
|
||||
TX.prototype.fromWitness = function fromWitness(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var i, marker, inCount, outCount, input, hasWitness, witnessSize;
|
||||
var p = BufferReader(data);
|
||||
var flag = 0;
|
||||
var witnessSize = 0;
|
||||
var hasWitness = false;
|
||||
var i, count, input;
|
||||
|
||||
p.start();
|
||||
|
||||
this.version = p.readU32(); // Technically signed
|
||||
|
||||
marker = p.readU8();
|
||||
this.flag = p.readU8();
|
||||
assert(p.readU8() === 0, 'Non-zero marker.');
|
||||
|
||||
if (marker !== 0)
|
||||
throw new Error('Invalid witness tx (marker != 0)');
|
||||
flag = p.readU8();
|
||||
|
||||
if (this.flag === 0)
|
||||
throw new Error('Invalid witness tx (flag == 0)');
|
||||
assert(flag !== 0, 'Flag byte is zero.');
|
||||
|
||||
inCount = p.readVarint();
|
||||
this.flag = flag;
|
||||
|
||||
for (i = 0; i < inCount; i++)
|
||||
this.inputs.push(bcoin.input.fromRaw(p));
|
||||
count = p.readVarint();
|
||||
|
||||
outCount = p.readVarint();
|
||||
for (i = 0; i < count; i++)
|
||||
this.inputs.push(Input.fromRaw(p));
|
||||
|
||||
for (i = 0; i < outCount; i++)
|
||||
this.outputs.push(bcoin.output.fromRaw(p));
|
||||
count = p.readVarint();
|
||||
|
||||
p.start();
|
||||
for (i = 0; i < count; i++)
|
||||
this.outputs.push(Output.fromRaw(p));
|
||||
|
||||
for (i = 0; i < inCount; i++) {
|
||||
input = this.inputs[i];
|
||||
input.witness.fromRaw(p);
|
||||
if (input.witness.items.length > 0)
|
||||
hasWitness = true;
|
||||
if (flag & 1) {
|
||||
flag ^= 1;
|
||||
|
||||
p.start();
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
input.witness.fromRaw(p);
|
||||
if (input.witness.items.length > 0)
|
||||
hasWitness = true;
|
||||
}
|
||||
|
||||
witnessSize = p.end() + 2;
|
||||
}
|
||||
|
||||
if (!hasWitness)
|
||||
throw new Error('Witness tx has an empty witness.');
|
||||
if (flag !== 0)
|
||||
throw new Error('Unknown witness flag.');
|
||||
|
||||
witnessSize = p.end() + 2;
|
||||
// We'll never be able to reserialize
|
||||
// this to get the regular txid, and
|
||||
// there's no way it's valid anyway.
|
||||
if (this.inputs.length === 0 && this.outputs.length !== 0)
|
||||
throw new Error('Zero input witness tx.');
|
||||
|
||||
this.locktime = p.readU32();
|
||||
|
||||
if (!this.mutable) {
|
||||
if (!this.mutable && hasWitness) {
|
||||
this._raw = p.endData();
|
||||
this._size = this._raw.length;
|
||||
this._witnessSize = witnessSize;
|
||||
|
|
@ -2212,27 +2234,6 @@ TX.prototype.fromWitness = function fromWitness(data) {
|
|||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether data is a witness transaction.
|
||||
* @param {Buffer|BufferReader} data
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
TX.isWitness = function isWitness(data) {
|
||||
if (Buffer.isBuffer(data)) {
|
||||
if (data.length < 12)
|
||||
return false;
|
||||
|
||||
return data[4] === 0 && data[5] !== 0;
|
||||
}
|
||||
|
||||
if (data.left() < 12)
|
||||
return false;
|
||||
|
||||
return data.data[data.offset + 4] === 0
|
||||
&& data.data[data.offset + 5] !== 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize transaction without witness.
|
||||
* @private
|
||||
|
|
@ -2241,13 +2242,13 @@ TX.isWitness = function isWitness(data) {
|
|||
*/
|
||||
|
||||
TX.prototype.frameNormal = function frameNormal(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
if (this.inputs.length === 0 && this.outputs.length === 1)
|
||||
if (this.inputs.length === 0 && this.outputs.length !== 0)
|
||||
throw new Error('Cannot serialize zero-input tx.');
|
||||
|
||||
p.write32(this.version);
|
||||
p.writeU32(this.version);
|
||||
|
||||
p.writeVarint(this.inputs.length);
|
||||
|
||||
|
|
@ -2278,11 +2279,14 @@ TX.prototype.frameNormal = function frameNormal(writer) {
|
|||
*/
|
||||
|
||||
TX.prototype.frameWitness = function frameWitness(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var witnessSize = 0;
|
||||
var i, start;
|
||||
|
||||
p.write32(this.version);
|
||||
if (this.inputs.length === 0 && this.outputs.length !== 0)
|
||||
throw new Error('Cannot serialize zero-input tx.');
|
||||
|
||||
p.writeU32(this.version);
|
||||
p.writeU8(0);
|
||||
p.writeU8(this.flag);
|
||||
|
||||
|
|
@ -2316,6 +2320,27 @@ TX.prototype.frameWitness = function frameWitness(writer) {
|
|||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether data is a witness transaction.
|
||||
* @param {Buffer|BufferReader} data
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
TX.isWitness = function isWitness(data) {
|
||||
if (Buffer.isBuffer(data)) {
|
||||
if (data.length < 6)
|
||||
return false;
|
||||
|
||||
return data[4] === 0 && data[5] !== 0;
|
||||
}
|
||||
|
||||
if (data.left() < 6)
|
||||
return false;
|
||||
|
||||
return data.data[data.offset + 4] === 0
|
||||
&& data.data[data.offset + 5] !== 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize a transaction to BCoin "extended format".
|
||||
* This is the serialization format BCoin uses internally
|
||||
|
|
@ -2331,7 +2356,7 @@ TX.prototype.frameWitness = function frameWitness(writer) {
|
|||
TX.prototype.toExtended = function toExtended(saveCoins, writer) {
|
||||
var height = this.height;
|
||||
var index = this.index;
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i, input;
|
||||
|
||||
if (height === -1)
|
||||
|
|
@ -2377,7 +2402,7 @@ TX.prototype.toExtended = function toExtended(saveCoins, writer) {
|
|||
*/
|
||||
|
||||
TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var i, coinCount, coin;
|
||||
|
||||
this.fromRaw(p);
|
||||
|
|
@ -2403,7 +2428,7 @@ TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
|
|||
coin = p.readVarBytes();
|
||||
if (coin.length === 0)
|
||||
continue;
|
||||
coin = bcoin.coin.fromRaw(coin);
|
||||
coin = Coin.fromRaw(coin);
|
||||
coin.hash = this.inputs[i].prevout.hash;
|
||||
coin.index = this.inputs[i].prevout.index;
|
||||
this.inputs[i].coin = coin;
|
||||
|
|
|
|||
|
|
@ -775,8 +775,9 @@ exports.flags = {
|
|||
VERIFY_CHECKSEQUENCEVERIFY: (1 << 10),
|
||||
VERIFY_WITNESS: (1 << 11),
|
||||
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 12),
|
||||
VERIFY_MAST: (1 << 13),
|
||||
VERIFY_MINIMALIF: (1 << 13),
|
||||
VERIFY_NULLFAIL: (1 << 14),
|
||||
VERIFY_MAST: (1 << 15), // should be 1 << 13
|
||||
VERIFY_SEQUENCE: (1 << 0),
|
||||
MEDIAN_TIME_PAST: (1 << 1)
|
||||
};
|
||||
|
|
|
|||
5
lib/protocol/index.js
Normal file
5
lib/protocol/index.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
exports.constants = require('./constants');
|
||||
exports.network = require('./network');
|
||||
exports.networks = require('./networks');
|
||||
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var networks = require('./networks');
|
||||
|
||||
/**
|
||||
|
|
@ -16,10 +15,6 @@ var networks = require('./networks');
|
|||
* @exports Network
|
||||
* @constructor
|
||||
* @param {Object|NetworkType} options - See {@link module:network}.
|
||||
* @property {Number} height
|
||||
* @property {Rate} feeRate
|
||||
* @property {Rate} minRelay
|
||||
* @property {PolicyEstimator} fees
|
||||
*/
|
||||
|
||||
function Network(options) {
|
||||
|
|
@ -51,8 +46,6 @@ function Network(options) {
|
|||
this.rpcPort = options.rpcPort;
|
||||
this.minRelay = options.minRelay;
|
||||
this.feeRate = options.feeRate;
|
||||
this.minRate = options.minRate;
|
||||
this.maxRate = options.maxRate;
|
||||
this.selfConnect = options.selfConnect;
|
||||
this.requestMempool = options.requestMempool;
|
||||
this.batchSize = options.batchSize;
|
||||
|
|
@ -60,11 +53,18 @@ function Network(options) {
|
|||
|
||||
/**
|
||||
* Default network.
|
||||
* @type {String}
|
||||
* @type {Network}
|
||||
*/
|
||||
|
||||
Network.primary = null;
|
||||
|
||||
/**
|
||||
* Default network type.
|
||||
* @type {String}
|
||||
*/
|
||||
|
||||
Network.type = null;
|
||||
|
||||
/*
|
||||
* Networks (to avoid hash table mode).
|
||||
*/
|
||||
|
|
@ -85,50 +85,6 @@ Network.prototype.updateHeight = function updateHeight(height) {
|
|||
this.height = height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the estimated fee rate of the network.
|
||||
* @param {Rate} rate
|
||||
*/
|
||||
|
||||
Network.prototype.updateRate = function updateRate(rate) {
|
||||
this.feeRate = rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the minimum relay rate (reject rate) of the network.
|
||||
* @param {Rate} rate
|
||||
*/
|
||||
|
||||
Network.prototype.updateMinRelay = function updateMinRelay(rate) {
|
||||
this.minRelay = rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the minimum relay rate. If the network is
|
||||
* inactive (height=-1), return the default minimum relay.
|
||||
* @return {Rate} Rate
|
||||
*/
|
||||
|
||||
Network.prototype.getMinRelay = function getMinRelay() {
|
||||
if (this.height === -1)
|
||||
return this.minRate;
|
||||
|
||||
return Math.min(this.minRelay, this.maxRate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the normal relay rate. If the network is
|
||||
* inactive (height=-1), return the default rate.
|
||||
* @return {Rate} Rate
|
||||
*/
|
||||
|
||||
Network.prototype.getRate = function getRate() {
|
||||
if (this.height === -1)
|
||||
return this.maxRate;
|
||||
|
||||
return Math.min(this.feeRate, this.maxRate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine how many blocks to request
|
||||
* based on current height of the chain.
|
||||
|
|
@ -187,6 +143,7 @@ Network.create = function create(options) {
|
|||
Network.set = function set(type) {
|
||||
assert(typeof type === 'string', 'Bad network.');
|
||||
Network.primary = Network.get(type);
|
||||
Network.type = type;
|
||||
return Network.primary;
|
||||
};
|
||||
|
||||
|
|
@ -261,6 +218,12 @@ Network.isNetwork = function isNetwork(obj) {
|
|||
&& typeof obj.pow === 'object';
|
||||
};
|
||||
|
||||
/*
|
||||
* Set initial network.
|
||||
*/
|
||||
|
||||
Network.set(process.env.BCOIN_NETWORK || 'main');
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ main.requireStandard = true;
|
|||
main.rpcPort = 8332;
|
||||
|
||||
/**
|
||||
* Default min relay rate (the rate for mempoolRejectFee).
|
||||
* Default min relay rate.
|
||||
* @const {Rate}
|
||||
* @default
|
||||
*/
|
||||
|
|
@ -414,22 +414,6 @@ main.minRelay = 10000;
|
|||
|
||||
main.feeRate = 50000;
|
||||
|
||||
/**
|
||||
* Default min rate.
|
||||
* @const {Rate}
|
||||
* @default
|
||||
*/
|
||||
|
||||
main.minRate = 10000;
|
||||
|
||||
/**
|
||||
* Default max rate.
|
||||
* @const {Rate}
|
||||
* @default
|
||||
*/
|
||||
|
||||
main.maxRate = 50000;
|
||||
|
||||
/**
|
||||
* Whether to allow self-connection.
|
||||
* @const {Boolean}
|
||||
|
|
@ -597,10 +581,6 @@ testnet.minRelay = 10000;
|
|||
|
||||
testnet.feeRate = 20000;
|
||||
|
||||
testnet.minRate = 10000;
|
||||
|
||||
testnet.maxRate = 40000;
|
||||
|
||||
testnet.selfConnect = false;
|
||||
|
||||
testnet.requestMempool = false;
|
||||
|
|
@ -743,10 +723,6 @@ regtest.minRelay = 10000;
|
|||
|
||||
regtest.feeRate = 20000;
|
||||
|
||||
regtest.minRate = 10000;
|
||||
|
||||
regtest.maxRate = 40000;
|
||||
|
||||
regtest.selfConnect = true;
|
||||
|
||||
regtest.requestMempool = true;
|
||||
|
|
@ -863,10 +839,6 @@ segnet3.minRelay = 10000;
|
|||
|
||||
segnet3.feeRate = 20000;
|
||||
|
||||
segnet3.minRate = 10000;
|
||||
|
||||
segnet3.maxRate = 40000;
|
||||
|
||||
segnet3.selfConnect = false;
|
||||
|
||||
segnet3.requestMempool = true;
|
||||
|
|
@ -1002,10 +974,6 @@ segnet4.minRelay = 10000;
|
|||
|
||||
segnet4.feeRate = 20000;
|
||||
|
||||
segnet4.minRate = 10000;
|
||||
|
||||
segnet4.maxRate = 40000;
|
||||
|
||||
segnet4.selfConnect = false;
|
||||
|
||||
segnet4.requestMempool = true;
|
||||
|
|
@ -1149,10 +1117,6 @@ simnet.minRelay = 10000;
|
|||
|
||||
simnet.feeRate = 20000;
|
||||
|
||||
simnet.minRate = 10000;
|
||||
|
||||
simnet.maxRate = 40000;
|
||||
|
||||
simnet.selfConnect = true;
|
||||
|
||||
simnet.requestMempool = false;
|
||||
|
|
|
|||
8
lib/script/index.js
Normal file
8
lib/script/index.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
exports.Opcode = require('./opcode');
|
||||
exports.Program = require('./program');
|
||||
exports.Script = require('./script');
|
||||
exports.SigCache = require('./sigcache');
|
||||
exports.Stack = require('./stack');
|
||||
exports.Witness = require('./witness');
|
||||
|
|
@ -7,11 +7,13 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Opcode;
|
||||
|
||||
var bn = require('bn.js');
|
||||
var constants = bcoin.constants;
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var Script = require('./script');
|
||||
var assert = require('assert');
|
||||
var opcodes = constants.opcodes;
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +41,7 @@ function Opcode(value, data) {
|
|||
*/
|
||||
|
||||
Opcode.prototype.toRaw = function toRaw(writer) {
|
||||
return bcoin.script.encode([this], writer);
|
||||
return Script.encode([this], writer);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -105,7 +107,7 @@ Opcode.fromPush = function fromPush(data) {
|
|||
*/
|
||||
|
||||
Opcode.fromNumber = function fromNumber(num) {
|
||||
return Opcode.fromData(bcoin.script.array(num));
|
||||
return Opcode.fromData(Script.array(num));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var constants = bcoin.constants;
|
||||
module.exports = Program;
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var utils = require('../utils/utils');
|
||||
var ec = require('../crypto/ec');
|
||||
var assert = require('assert');
|
||||
|
||||
/**
|
||||
* Signature cache.
|
||||
|
|
@ -106,14 +106,14 @@ SigCache.prototype.verify = function verify(msg, sig, key, historical, high) {
|
|||
var hash, result;
|
||||
|
||||
if (historical || this.size === 0)
|
||||
return bcoin.ec.verify(msg, sig, key, historical, high);
|
||||
return ec.verify(msg, sig, key, historical, high);
|
||||
|
||||
hash = msg.toString('hex');
|
||||
|
||||
if (this.has(hash, sig, key))
|
||||
return true;
|
||||
|
||||
result = bcoin.ec.verify(msg, sig, key, historical, high);
|
||||
result = ec.verify(msg, sig, key, historical, high);
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
|
@ -152,4 +152,4 @@ SigCacheEntry.prototype.equal = function equal(sig, key) {
|
|||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = SigCache;
|
||||
module.exports = new SigCache(+process.env.BCOIN_SIGCACHE_SIZE || 0);
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
var constants = bcoin.constants;
|
||||
var opcodes = constants.opcodes;
|
||||
var ScriptError = bcoin.errors.ScriptError;
|
||||
module.exports = Stack;
|
||||
|
||||
var Script = require('./script');
|
||||
var Witness = require('./witness');
|
||||
|
||||
/**
|
||||
* Represents the stack of a Script during execution.
|
||||
|
|
@ -51,7 +51,7 @@ Stack.prototype.inspect = function inspect() {
|
|||
*/
|
||||
|
||||
Stack.prototype.toString = function toString() {
|
||||
return bcoin.witness.format(this.items);
|
||||
return Witness.format(this.items);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -61,7 +61,7 @@ Stack.prototype.toString = function toString() {
|
|||
*/
|
||||
|
||||
Stack.prototype.toASM = function toASM(decode) {
|
||||
return bcoin.script.formatASM(this.items, decode);
|
||||
return Script.formatASM(this.items, decode);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -73,7 +73,7 @@ Stack.prototype.getRedeem = function getRedeem() {
|
|||
var redeem = this.items[this.items.length - 1];
|
||||
if (!redeem)
|
||||
return;
|
||||
return new bcoin.script(redeem);
|
||||
return new Script(redeem);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -85,16 +85,6 @@ Stack.prototype.clone = function clone() {
|
|||
return new Stack(this.items.slice());
|
||||
};
|
||||
|
||||
/**
|
||||
* Get total size of the stack, including the alt stack.
|
||||
* @param {Array} alt - Alt stack.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Stack.prototype.getSize = function getSize(alt) {
|
||||
return this.items.length + alt.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Push item onto stack.
|
||||
* @see Array#push
|
||||
|
|
@ -122,11 +112,12 @@ Stack.prototype.unshift = function unshift(item) {
|
|||
* @param {Number} start
|
||||
* @param {Number} end
|
||||
* @see Array#slice
|
||||
* @returns {Buffer[]}
|
||||
* @returns {Stack}
|
||||
*/
|
||||
|
||||
Stack.prototype.slice = function slice(start, end) {
|
||||
return this.items.slice(start, end);
|
||||
this.items = this.items.slice(start, end);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -139,11 +130,62 @@ Stack.prototype.slice = function slice(start, end) {
|
|||
*/
|
||||
|
||||
Stack.prototype.splice = function splice(i, remove, insert) {
|
||||
if (i < 0)
|
||||
i = this.items.length + i;
|
||||
|
||||
if (insert === undefined)
|
||||
return this.items.splice(i, remove);
|
||||
|
||||
return this.items.splice(i, remove, insert);
|
||||
};
|
||||
|
||||
/**
|
||||
* Erase stack items.
|
||||
* @param {Number} start
|
||||
* @param {Number} end
|
||||
* @returns {Buffer[]}
|
||||
*/
|
||||
|
||||
Stack.prototype.erase = function erase(start, end) {
|
||||
if (start < 0)
|
||||
start = this.items.length + start;
|
||||
|
||||
if (end < 0)
|
||||
end = this.items.length + end;
|
||||
|
||||
this.items.splice(start, end - start);
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert an item.
|
||||
* @param {Number} index
|
||||
* @param {Buffer} item
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
Stack.prototype.insert = function insert(i, item) {
|
||||
if (i < 0)
|
||||
i = this.items.length + i;
|
||||
|
||||
this.items.splice(i, 0, item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an item.
|
||||
* @param {Number} index
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
Stack.prototype.remove = function remove(i) {
|
||||
if (i < 0)
|
||||
i = this.items.length + i;
|
||||
|
||||
if (i >= this.items.length)
|
||||
return;
|
||||
|
||||
return this.items.splice(i, 1)[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Pop a stack item.
|
||||
* @see Array#pop
|
||||
|
|
@ -203,21 +245,26 @@ Stack.prototype.clear = function clear() {
|
|||
*/
|
||||
|
||||
Stack.prototype.set = function set(i, value) {
|
||||
if (i < 0)
|
||||
i = this.items.length + i;
|
||||
|
||||
return this.items[i] = value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Swap stack values.
|
||||
* @private
|
||||
* @param {Number} i1 - Index 1.
|
||||
* @param {Number} i2 - Index 2.
|
||||
*/
|
||||
|
||||
Stack.prototype._swap = function _swap(i1, i2) {
|
||||
Stack.prototype.swap = function swap(i1, i2) {
|
||||
var v1, v2;
|
||||
|
||||
i1 = this.items.length + i1;
|
||||
i2 = this.items.length + i2;
|
||||
if (i1 < 0)
|
||||
i1 = this.items.length + i1;
|
||||
|
||||
if (i2 < 0)
|
||||
i2 = this.items.length + i2;
|
||||
|
||||
v1 = this.items[i1];
|
||||
v2 = this.items[i2];
|
||||
|
|
@ -226,300 +273,6 @@ Stack.prototype._swap = function _swap(i1, i2) {
|
|||
this.items[i2] = v1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_TOALTSTACK operation.
|
||||
* @param {Array} alt - Alt stack.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.toalt = function toalt(alt) {
|
||||
if (this.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_TOALTSTACK);
|
||||
|
||||
alt.push(this.pop());
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_FROMALTSTACK operation.
|
||||
* @param {Array} alt - Alt stack.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.fromalt = function fromalt(alt) {
|
||||
if (alt.length === 0)
|
||||
throw new ScriptError('INVALID_ALTSTACK_OPERATION', opcodes.OP_FROMALTSTACK);
|
||||
|
||||
this.push(alt.pop());
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_IFDUP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.ifdup = function ifdup() {
|
||||
if (this.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_IFDUP);
|
||||
|
||||
if (bcoin.script.bool(this.top(-1)))
|
||||
this.push(this.top(-1));
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_DEPTH operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.depth = function depth() {
|
||||
this.push(bcoin.script.array(this.length));
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_DROP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.drop = function drop() {
|
||||
if (this.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_DROP);
|
||||
|
||||
this.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_DUP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.dup = function dup() {
|
||||
if (this.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_DUP);
|
||||
|
||||
this.push(this.top(-1));
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_NIP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.nip = function nip() {
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_NIP);
|
||||
|
||||
this.splice(this.length - 2, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_OVER operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.over = function over() {
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_OVER);
|
||||
|
||||
this.push(this.top(-2));
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_PICK operation.
|
||||
* @param {VerifyFlags} flags
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.pick = function pick(flags) {
|
||||
return this._pickroll(opcodes.OP_PICK, flags);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_ROLL operation.
|
||||
* @param {VerifyFlags} flags
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.roll = function roll(flags) {
|
||||
return this._pickroll(opcodes.OP_ROLL, flags);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform a pick or roll.
|
||||
* @private
|
||||
* @param {Number} op
|
||||
* @param {VerifyFlags} flags
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype._pickroll = function pickroll(op, flags) {
|
||||
var val, n;
|
||||
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', op);
|
||||
|
||||
val = this.pop();
|
||||
n = bcoin.script.num(val, flags).toNumber();
|
||||
|
||||
if (n < 0 || n >= this.length)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', op);
|
||||
|
||||
val = this.top(-n - 1);
|
||||
|
||||
if (op === opcodes.OP_ROLL)
|
||||
this.splice(this.length - n - 1, 1);
|
||||
|
||||
this.push(val);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_ROT operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.rot = function rot() {
|
||||
if (this.length < 3)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_ROT);
|
||||
|
||||
this._swap(-3, -2);
|
||||
this._swap(-2, -1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_SWAP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.swap = function swap() {
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_SWAP);
|
||||
|
||||
this._swap(-2, -1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_TUCK operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.tuck = function tuck() {
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_TUCK);
|
||||
|
||||
this.splice(this.length - 2, 0, this.top(-1));
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_2DROP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.drop2 = function drop2() {
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_2DROP);
|
||||
|
||||
this.pop();
|
||||
this.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_2DUP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.dup2 = function dup2() {
|
||||
var v1, v2;
|
||||
|
||||
if (this.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_2DUP);
|
||||
|
||||
v1 = this.top(-2);
|
||||
v2 = this.top(-1);
|
||||
|
||||
this.push(v1);
|
||||
this.push(v2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_3DUP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.dup3 = function dup3() {
|
||||
var v1, v2, v3;
|
||||
|
||||
if (this.length < 3)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_3DUP);
|
||||
|
||||
v1 = this.top(-3);
|
||||
v2 = this.top(-2);
|
||||
v3 = this.top(-1);
|
||||
|
||||
this.push(v1);
|
||||
this.push(v2);
|
||||
this.push(v3);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_2OVER operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.over2 = function over2() {
|
||||
var v1, v2;
|
||||
|
||||
if (this.length < 4)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_2OVER);
|
||||
|
||||
v1 = this.top(-4);
|
||||
v2 = this.top(-3);
|
||||
|
||||
this.push(v1);
|
||||
this.push(v2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_2ROT operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.rot2 = function rot2() {
|
||||
var v1, v2;
|
||||
|
||||
if (this.length < 6)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_2ROT);
|
||||
|
||||
v1 = this.top(-6);
|
||||
v2 = this.top(-5);
|
||||
|
||||
this.splice(this.length - 6, 2);
|
||||
this.push(v1);
|
||||
this.push(v2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_2SWAP operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.swap2 = function swap2() {
|
||||
if (this.length < 4)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_2SWAP);
|
||||
|
||||
this._swap(-4, -2);
|
||||
this._swap(-3, -1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the OP_SIZE operation.
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Stack.prototype.size = function size() {
|
||||
if (this.length < 1)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_SIZE);
|
||||
|
||||
this.push(bcoin.script.array(this.top(-1).length));
|
||||
};
|
||||
|
||||
/**
|
||||
* Test an object to see if it is a Stack.
|
||||
* @param {Object} obj
|
||||
|
|
@ -527,7 +280,7 @@ Stack.prototype.size = function size() {
|
|||
*/
|
||||
|
||||
Stack.isStack = function isStack(obj) {
|
||||
return obj && Array.isArray(obj.items) && typeof obj.swap2 === 'function';
|
||||
return obj && Array.isArray(obj.items) && typeof obj.swap === 'function';
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -7,17 +7,22 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var bcoin = require('../env');
|
||||
module.exports = Witness;
|
||||
|
||||
var bn = require('bn.js');
|
||||
var constants = bcoin.constants;
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var assert = require('assert');
|
||||
var opcodes = constants.opcodes;
|
||||
var STACK_FALSE = new Buffer([]);
|
||||
var STACK_FALSE = new Buffer(0);
|
||||
var STACK_NEGATE = new Buffer([0x81]);
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
var Script = require('./script');
|
||||
var Opcode = require('./opcode');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var Address = require('../primitives/address');
|
||||
var Stack = require('./stack');
|
||||
|
||||
/**
|
||||
* Refers to the witness field of segregated witness transactions.
|
||||
|
|
@ -159,7 +164,7 @@ Witness.prototype.clone = function clone() {
|
|||
*/
|
||||
|
||||
Witness.prototype.toStack = function toStack() {
|
||||
return new bcoin.stack(this.items.slice());
|
||||
return new Stack(this.items.slice());
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -185,7 +190,7 @@ Witness.prototype.getInputType = function getInputType() {
|
|||
*/
|
||||
|
||||
Witness.prototype.getInputAddress = function getInputAddress() {
|
||||
return bcoin.address.fromWitness(this);
|
||||
return Address.fromWitness(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -301,7 +306,7 @@ Witness.prototype.indexOf = function indexOf(data) {
|
|||
*/
|
||||
|
||||
Witness.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var p = BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeVarint(this.items.length);
|
||||
|
|
@ -515,7 +520,7 @@ Witness.encodeItem = function encodeItem(data) {
|
|||
*/
|
||||
|
||||
Witness.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var p = BufferReader(data);
|
||||
var chunkCount = p.readVarint();
|
||||
var i;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue