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`
|
||||
argument. This is to prevent bcoin from generating keys and addresses the
|
||||
user can not spend from.
|
||||
- `POST /wallet/:id/create` Now has a `sign` argument for optional signing
|
||||
of transactions.
|
||||
- `POST /wallet/:id/create`
|
||||
- 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
|
||||
|
||||
|
||||
@ -468,13 +468,16 @@ class HTTP extends Server {
|
||||
|
||||
const options = {
|
||||
rate: valid.u64('rate'),
|
||||
blocks: valid.u32('blocks'),
|
||||
maxFee: valid.u64('maxFee'),
|
||||
selection: valid.str('selection'),
|
||||
smart: valid.bool('smart'),
|
||||
account: valid.str('account'),
|
||||
sort: valid.bool('sort'),
|
||||
subtractFee: valid.bool('subtractFee'),
|
||||
subtractIndex: valid.i32('subtractIndex'),
|
||||
depth: valid.u32(['confirmations', 'depth']),
|
||||
template: valid.bool('template', sign),
|
||||
outputs: []
|
||||
};
|
||||
|
||||
|
||||
@ -1236,6 +1236,9 @@ class Wallet extends EventEmitter {
|
||||
* to avoid sorting), set locktime, and template it.
|
||||
* @param {Object} options - See {@link Wallet#fund options}.
|
||||
* @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}.
|
||||
*/
|
||||
|
||||
@ -1281,6 +1284,9 @@ class Wallet extends EventEmitter {
|
||||
assert(mtx.verifyInputs(this.wdb.state.height + 1),
|
||||
'TX failed context check.');
|
||||
|
||||
if (options.template === false)
|
||||
return mtx;
|
||||
|
||||
const total = await this.template(mtx);
|
||||
|
||||
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 () => {
|
||||
consensus.COINBASE_MATURITY = 100;
|
||||
await wallet.close();
|
||||
|
||||
@ -1220,6 +1220,40 @@ describe('Wallet', function() {
|
||||
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 () => {
|
||||
const wallet = currentWallet;
|
||||
const txs = await wallet.getRange(null, {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user