Merge pull request #557 from nodar-chkuaselidze/no-template
Wallet option to skip templates.
This commit is contained in:
commit
1a18040ad4
@ -9,8 +9,13 @@
|
|||||||
- `PUT /wallet/:id` Creating a watch-only wallet now requires an `accountKey`
|
- `PUT /wallet/:id` Creating a watch-only wallet now requires an `accountKey`
|
||||||
argument. This is to prevent bcoin from generating keys and addresses the
|
argument. This is to prevent bcoin from generating keys and addresses the
|
||||||
user can not spend from.
|
user can not spend from.
|
||||||
- `POST /wallet/:id/create` Now has a `sign` argument for optional signing
|
- `POST /wallet/:id/create`
|
||||||
of transactions.
|
- Now has a `sign` argument for optional signing of transactions.
|
||||||
|
- Now has a `template` option, that will skip templating inputs when
|
||||||
|
`sign = false`, but you can enable it if necessary. It does not have an
|
||||||
|
effect when `sign = true`.
|
||||||
|
- Exposes `blocks`, which can will be used if there is no `rate` option.
|
||||||
|
- Exposes `sort` (Default `true`), that can be used to disable BIP69 sorting.
|
||||||
|
|
||||||
#### RPC
|
#### RPC
|
||||||
|
|
||||||
|
|||||||
@ -468,13 +468,16 @@ class HTTP extends Server {
|
|||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
rate: valid.u64('rate'),
|
rate: valid.u64('rate'),
|
||||||
|
blocks: valid.u32('blocks'),
|
||||||
maxFee: valid.u64('maxFee'),
|
maxFee: valid.u64('maxFee'),
|
||||||
selection: valid.str('selection'),
|
selection: valid.str('selection'),
|
||||||
smart: valid.bool('smart'),
|
smart: valid.bool('smart'),
|
||||||
account: valid.str('account'),
|
account: valid.str('account'),
|
||||||
|
sort: valid.bool('sort'),
|
||||||
subtractFee: valid.bool('subtractFee'),
|
subtractFee: valid.bool('subtractFee'),
|
||||||
subtractIndex: valid.i32('subtractIndex'),
|
subtractIndex: valid.i32('subtractIndex'),
|
||||||
depth: valid.u32(['confirmations', 'depth']),
|
depth: valid.u32(['confirmations', 'depth']),
|
||||||
|
template: valid.bool('template', sign),
|
||||||
outputs: []
|
outputs: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1236,6 +1236,9 @@ class Wallet extends EventEmitter {
|
|||||||
* to avoid sorting), set locktime, and template it.
|
* to avoid sorting), set locktime, and template it.
|
||||||
* @param {Object} options - See {@link Wallet#fund options}.
|
* @param {Object} options - See {@link Wallet#fund options}.
|
||||||
* @param {Object[]} options.outputs - See {@link MTX#addOutput}.
|
* @param {Object[]} options.outputs - See {@link MTX#addOutput}.
|
||||||
|
* @param {Boolean} options.sort - Sort inputs and outputs (BIP69).
|
||||||
|
* @param {Boolean} options.template - Build scripts for inputs.
|
||||||
|
* @param {Number} options.locktime - TX locktime
|
||||||
* @returns {Promise} - Returns {@link MTX}.
|
* @returns {Promise} - Returns {@link MTX}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1281,6 +1284,9 @@ class Wallet extends EventEmitter {
|
|||||||
assert(mtx.verifyInputs(this.wdb.state.height + 1),
|
assert(mtx.verifyInputs(this.wdb.state.height + 1),
|
||||||
'TX failed context check.');
|
'TX failed context check.');
|
||||||
|
|
||||||
|
if (options.template === false)
|
||||||
|
return mtx;
|
||||||
|
|
||||||
const total = await this.template(mtx);
|
const total = await this.template(mtx);
|
||||||
|
|
||||||
if (total === 0)
|
if (total === 0)
|
||||||
|
|||||||
@ -264,6 +264,72 @@ describe('HTTP', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const template of [true, false]) {
|
||||||
|
const suffix = template ? 'with template' : 'without template';
|
||||||
|
it(`should create and sign transaction ${suffix}`, async () => {
|
||||||
|
const change = await wallet.createChange('default');
|
||||||
|
const tx = await wallet.createTX({
|
||||||
|
template: template, // should not matter, sign = true
|
||||||
|
sign: true,
|
||||||
|
outputs: [{
|
||||||
|
address: change.address,
|
||||||
|
value: 50000
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
const mtx = MTX.fromJSON(tx);
|
||||||
|
|
||||||
|
for (const input of tx.inputs) {
|
||||||
|
const script = input.script;
|
||||||
|
|
||||||
|
assert.notStrictEqual(script, '',
|
||||||
|
'Input must be signed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.strictEqual(mtx.verify(), true,
|
||||||
|
'Transaction must be signed.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should create transaction without template', async () => {
|
||||||
|
const change = await wallet.createChange('default');
|
||||||
|
const tx = await wallet.createTX({
|
||||||
|
sign: false,
|
||||||
|
outputs: [{
|
||||||
|
address: change.address,
|
||||||
|
value: 50000
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const input of tx.inputs) {
|
||||||
|
const script = input.script;
|
||||||
|
|
||||||
|
assert.strictEqual(script.length, 0,
|
||||||
|
'Input must not be templated.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create transaction with template', async () => {
|
||||||
|
const change = await wallet.createChange('default');
|
||||||
|
const tx = await wallet.createTX({
|
||||||
|
sign: false,
|
||||||
|
template: true,
|
||||||
|
outputs: [{
|
||||||
|
address: change.address,
|
||||||
|
value: 20000
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const input of tx.inputs) {
|
||||||
|
const script = Buffer.from(input.script, 'hex');
|
||||||
|
|
||||||
|
// p2pkh
|
||||||
|
// 1 (OP_0 placeholder) + 1 (length) + 33 (pubkey)
|
||||||
|
assert.strictEqual(script.length, 35);
|
||||||
|
assert.strictEqual(script[0], 0x00,
|
||||||
|
'First item in stack must be a placeholder OP_0');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should cleanup', async () => {
|
it('should cleanup', async () => {
|
||||||
consensus.COINBASE_MATURITY = 100;
|
consensus.COINBASE_MATURITY = 100;
|
||||||
await wallet.close();
|
await wallet.close();
|
||||||
|
|||||||
@ -1220,6 +1220,40 @@ describe('Wallet', function() {
|
|||||||
assert(t3.verify());
|
assert(t3.verify());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const witness of [true, false]) {
|
||||||
|
it(`should create non-templated tx (witness=${witness})`, async () => {
|
||||||
|
const wallet = await wdb.create({ witness });
|
||||||
|
|
||||||
|
// Fund wallet
|
||||||
|
const t1 = new MTX();
|
||||||
|
t1.addInput(dummyInput());
|
||||||
|
t1.addOutput(await wallet.receiveAddress(), 500000);
|
||||||
|
|
||||||
|
await wdb.addTX(t1.toTX());
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
rate: 10000,
|
||||||
|
round: true,
|
||||||
|
outputs: [{
|
||||||
|
address: await wallet.receiveAddress(),
|
||||||
|
value: 7000
|
||||||
|
}],
|
||||||
|
template: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const t2 = await wallet.createTX(options);
|
||||||
|
|
||||||
|
assert(t2, 'Could not create tx.');
|
||||||
|
|
||||||
|
for (const input of t2.inputs) {
|
||||||
|
const {script, witness} = input;
|
||||||
|
|
||||||
|
assert.strictEqual(script.length, 0, 'Input is templated.');
|
||||||
|
assert.strictEqual(witness.length, 0, 'Input is templated.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should get range of txs', async () => {
|
it('should get range of txs', async () => {
|
||||||
const wallet = currentWallet;
|
const wallet = currentWallet;
|
||||||
const txs = await wallet.getRange(null, {
|
const txs = await wallet.getRange(null, {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user