Add `PublicKeyHashInput` and `ScriptHashInput`.
Remove `_outpoints`, `_utxos` from Transaction, as that info can be efficiently retrieved from the inputs
This commit is contained in:
parent
264a239e5a
commit
af43228daf
|
@ -27,7 +27,10 @@ module.exports = [{
|
||||||
message: format('Invalid network: must be "livenet" or "testnet", got {0}')
|
message: format('Invalid network: must be "livenet" or "testnet", got {0}')
|
||||||
}, {
|
}, {
|
||||||
name: 'InvalidArgument',
|
name: 'InvalidArgument',
|
||||||
message: format('Invalid Argument {0}, {1}'),
|
message: format('Invalid Argument {0}, {1}')
|
||||||
|
}, {
|
||||||
|
name: 'AbstractMethodInvoked',
|
||||||
|
message: format('Abstract Method Invokation: {0}')
|
||||||
}, {
|
}, {
|
||||||
name: 'InvalidArgumentType',
|
name: 'InvalidArgumentType',
|
||||||
message: format('Invalid Argument for {2}, expected {1} but got ') + '+ typeof arguments[0]',
|
message: format('Invalid Argument for {2}, expected {1} but got ') + '+ typeof arguments[0]',
|
||||||
|
|
|
@ -2,4 +2,7 @@
|
||||||
|
|
||||||
var Input = require('./input');
|
var Input = require('./input');
|
||||||
|
|
||||||
|
Input.PublicKeyHash = require('./publicKeyHash');
|
||||||
|
Input.ScriptHash = require('./scriptHash');
|
||||||
|
|
||||||
module.exports = Input;
|
module.exports = Input;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var errors = require('../../errors');
|
||||||
var BufferWriter = require('../../encoding/bufferwriter');
|
var BufferWriter = require('../../encoding/bufferwriter');
|
||||||
var buffer = require('buffer');
|
var buffer = require('buffer');
|
||||||
var bufferUtil = require('../../util/buffer');
|
var bufferUtil = require('../../util/buffer');
|
||||||
|
@ -31,6 +32,7 @@ Input.prototype._fromObject = function(params) {
|
||||||
if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) {
|
if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) {
|
||||||
params.prevTxId = new buffer.Buffer(params.prevTxId, 'hex');
|
params.prevTxId = new buffer.Buffer(params.prevTxId, 'hex');
|
||||||
}
|
}
|
||||||
|
this.output = params.output;
|
||||||
this.prevTxId = params.prevTxId;
|
this.prevTxId = params.prevTxId;
|
||||||
this.outputIndex = params.outputIndex;
|
this.outputIndex = params.outputIndex;
|
||||||
this.sequenceNumber = params.sequenceNumber;
|
this.sequenceNumber = params.sequenceNumber;
|
||||||
|
@ -106,4 +108,19 @@ Input.prototype.setScript = function(script) {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve signatures for the provided PrivateKey.
|
||||||
|
*
|
||||||
|
* @param {Transaction} transaction - the transaction to be signed
|
||||||
|
* @param {PrivateKey} privateKey - the private key to use when signing
|
||||||
|
* @param {number} inputIndex - the index of this input in the provided transaction
|
||||||
|
* @param {number} sigType - defaults to Signature.SIGHASH_ALL
|
||||||
|
* @param {Buffer} addressHash - if provided, don't calculate the hash of the
|
||||||
|
* public key associated with the private key provided
|
||||||
|
* @abstract
|
||||||
|
*/
|
||||||
|
Input.prototype.getSignatures = function() {
|
||||||
|
throw new errors.AbstractMethodInvoked('Input#getSignatures');
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = Input;
|
module.exports = Input;
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var inherits = require('inherits');
|
||||||
|
var Input = require('./input');
|
||||||
|
var Hash = require('../../crypto/hash');
|
||||||
|
var Signature = require('../../crypto/signature');
|
||||||
|
var Sighash = require('../sighash');
|
||||||
|
var BufferUtil = require('../../util/buffer');
|
||||||
|
|
||||||
|
function PublicKeyHashInput() {
|
||||||
|
}
|
||||||
|
inherits(PublicKeyHashInput, Input);
|
||||||
|
|
||||||
|
PublicKeyHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype, hashData) {
|
||||||
|
hashData = hashData || Hash.sha256ripemd160(privateKey.publicKey.toBuffer());
|
||||||
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
||||||
|
if (BufferUtil.equals(hashData, this.output.script.address.hashData)) {
|
||||||
|
return [{
|
||||||
|
address: this.output.script.address,
|
||||||
|
publicKey: privateKey.publicKey,
|
||||||
|
prevTxId: this.txId,
|
||||||
|
outputIndex: this.outputIndex,
|
||||||
|
inputIndex: index,
|
||||||
|
signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script),
|
||||||
|
sigtype: sigtype
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = PublicKeyHashInput;
|
|
@ -0,0 +1,31 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var inherits = require('inherits');
|
||||||
|
var Input = require('./input');
|
||||||
|
var Hash = require('../../crypto/hash');
|
||||||
|
var Signature = require('../../crypto/signature');
|
||||||
|
var Sighash = require('../sighash');
|
||||||
|
var BufferUtil = require('../../util/buffer');
|
||||||
|
|
||||||
|
function ScriptHashInput() {
|
||||||
|
}
|
||||||
|
inherits(ScriptHashInput, Input);
|
||||||
|
|
||||||
|
ScriptHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype, hashData) {
|
||||||
|
hashData = hashData || Hash.sha256ripemd160(privateKey.publicKey.toBuffer());
|
||||||
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
||||||
|
if (BufferUtil.equals(hashData, this.output.script.address.hashData)) {
|
||||||
|
return [{
|
||||||
|
address: this.output.script.address,
|
||||||
|
publicKey: privateKey.publicKey,
|
||||||
|
prevTxId: this.txId,
|
||||||
|
outputIndex: this.outputIndex,
|
||||||
|
inputIndex: index,
|
||||||
|
signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script),
|
||||||
|
sigtype: sigtype
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ScriptHashInput;
|
|
@ -33,10 +33,8 @@ function Transaction(serialized) {
|
||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
this.outputs = [];
|
this.outputs = [];
|
||||||
this._outpoints = [];
|
this._outpoints = [];
|
||||||
this._utxos = {};
|
|
||||||
this._inputAmount = 0;
|
this._inputAmount = 0;
|
||||||
this._outputAmount = 0;
|
this._outputAmount = 0;
|
||||||
this._p2shMap = {};
|
|
||||||
this._signatures = {};
|
this._signatures = {};
|
||||||
|
|
||||||
if (serialized) {
|
if (serialized) {
|
||||||
|
@ -228,12 +226,13 @@ Transaction._isNewUtxo = function(utxo) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Transaction.prototype._fromNewUtxo = function(utxo) {
|
Transaction.prototype._fromNewUtxo = function(utxo) {
|
||||||
var outpoint = Transaction._makeOutpoint(utxo);
|
|
||||||
utxo.address = utxo.address && new Address(utxo.address);
|
utxo.address = utxo.address && new Address(utxo.address);
|
||||||
utxo.script = new Script(util.isHexa(utxo.script) ? new buffer.Buffer(utxo.script, 'hex') : utxo.script);
|
utxo.script = new Script(util.isHexa(utxo.script) ? new buffer.Buffer(utxo.script, 'hex') : utxo.script);
|
||||||
this._utxos[outpoint] = utxo;
|
|
||||||
this._outpoints.push(outpoint);
|
|
||||||
this.inputs.push(new Input({
|
this.inputs.push(new Input({
|
||||||
|
output: new Output({
|
||||||
|
script: utxo.script,
|
||||||
|
satoshis: utxo.satoshis
|
||||||
|
}),
|
||||||
prevTxId: utxo.txId,
|
prevTxId: utxo.txId,
|
||||||
outputIndex: utxo.outputIndex,
|
outputIndex: utxo.outputIndex,
|
||||||
sequenceNumber: DEFAULT_SEQNUMBER,
|
sequenceNumber: DEFAULT_SEQNUMBER,
|
||||||
|
@ -254,9 +253,8 @@ Transaction._makeOutpoint = function(data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Transaction.prototype.hasAllUtxoInfo = function() {
|
Transaction.prototype.hasAllUtxoInfo = function() {
|
||||||
var self = this;
|
return _.all(this.inputs.map(function(input) {
|
||||||
return _.all(this._outpoints.map(function(outpoint) {
|
return !!input.output;
|
||||||
return !!self._utxos[outpoint];
|
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -328,42 +326,22 @@ Transaction.prototype.sign = function(privKey) {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Transaction.prototype._getPrivateKeySignatures = function(privKey) {
|
Transaction.prototype._getPrivateKeySignatures = function(privKey, sigtype) {
|
||||||
privKey = new PrivateKey(privKey);
|
privKey = new PrivateKey(privKey);
|
||||||
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
||||||
var transaction = this;
|
var transaction = this;
|
||||||
var results = [];
|
var results = [];
|
||||||
var hashData = Hash.sha256ripemd160(privKey.publicKey.toBuffer());
|
var hashData = Hash.sha256ripemd160(privKey.publicKey.toBuffer());
|
||||||
_.each(this._outpoints, function forEachOutput(outpoint, index) {
|
_.each(this.inputs, function forEachInput(input, index) {
|
||||||
var utxo = transaction._utxos[outpoint];
|
_.each(input.getSignatures(transaction, privKey, index, sigtype, hashData), function(signature) {
|
||||||
if ((utxo.address && utxo.address.isPayToPublicKeyHash()) || utxo.script.isPublicKeyHashOut()) {
|
results.push(signature);
|
||||||
var address = new Address(utxo.address || utxo.script);
|
|
||||||
if (bufferUtil.equals(hashData, address.hashBuffer)) {
|
|
||||||
results.push({
|
|
||||||
publicKey: privKey.publicKey,
|
|
||||||
prevTxId: utxo.txId,
|
|
||||||
outputIndex: utxo.outputIndex,
|
|
||||||
inputIndex: index,
|
|
||||||
signature: Sighash.sign(transaction, privKey, Signature.SIGHASH_ALL, index, utxo.script),
|
|
||||||
sigtype: Signature.SIGHASH_ALL
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
Transaction.prototype.applySignature = function(signature) {
|
Transaction.prototype.applySignature = function(signature) {
|
||||||
this.inputs[signature.inputIndex].setScript(
|
this.inputs[signature.inputIndex].addSignature(signature);
|
||||||
Script.buildPublicKeyHashIn(
|
|
||||||
signature.publicKey,
|
|
||||||
signature.signature.toDER(),
|
|
||||||
signature.sigtype
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue