Merge pull request #917 from eordano/transaction/updates
Changes to internal transaction and address
This commit is contained in:
commit
50a868cb8c
13
gulpfile.js
13
gulpfile.js
@ -32,19 +32,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var gulp = require('gulp');
|
var gulp = require('gulp');
|
||||||
|
|
||||||
|
var bump = require('gulp-bump');
|
||||||
var coveralls = require('gulp-coveralls');
|
var coveralls = require('gulp-coveralls');
|
||||||
|
var git = require('gulp-git');
|
||||||
|
var gutil = require('gulp-util');
|
||||||
|
var jsdoc2md = require('jsdoc-to-markdown');
|
||||||
var jshint = require('gulp-jshint');
|
var jshint = require('gulp-jshint');
|
||||||
|
var mfs = require('more-fs');
|
||||||
var mocha = require('gulp-mocha');
|
var mocha = require('gulp-mocha');
|
||||||
|
var rename = require('gulp-rename');
|
||||||
var runSequence = require('run-sequence');
|
var runSequence = require('run-sequence');
|
||||||
var shell = require('gulp-shell');
|
var shell = require('gulp-shell');
|
||||||
var through = require('through2');
|
var through = require('through2');
|
||||||
var gutil = require('gulp-util');
|
|
||||||
var jsdoc2md = require('jsdoc-to-markdown');
|
|
||||||
var mfs = require('more-fs');
|
|
||||||
var uglify = require('gulp-uglify');
|
var uglify = require('gulp-uglify');
|
||||||
var rename = require('gulp-rename');
|
|
||||||
var bump = require('gulp-bump');
|
|
||||||
var git = require('gulp-git');
|
|
||||||
|
|
||||||
|
|
||||||
var files = ['lib/**/*.js'];
|
var files = ['lib/**/*.js'];
|
||||||
|
|||||||
@ -715,6 +715,13 @@ Script.prototype.toAddress = function(network) {
|
|||||||
throw new Error('The script type needs to be PayToPublicKeyHash or PayToScriptHash');
|
throw new Error('The script type needs to be PayToPublicKeyHash or PayToScriptHash');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Script}
|
||||||
|
*/
|
||||||
|
Script.prototype.toScriptHashOut = function() {
|
||||||
|
return Script.buildScriptHashOut(this);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analagous to bitcoind's FindAndDelete. Find and delete equivalent chunks,
|
* Analagous to bitcoind's FindAndDelete. Find and delete equivalent chunks,
|
||||||
* typically used with push data chunks. Note that this will find and delete
|
* typically used with push data chunks. Note that this will find and delete
|
||||||
|
|||||||
@ -9,12 +9,13 @@ var $ = require('../../util/preconditions');
|
|||||||
var Script = require('../../script');
|
var Script = require('../../script');
|
||||||
var Signature = require('../../crypto/signature');
|
var Signature = require('../../crypto/signature');
|
||||||
var Sighash = require('../sighash');
|
var Sighash = require('../sighash');
|
||||||
|
var PublicKey = require('../../publickey');
|
||||||
var BufferUtil = require('../../util/buffer');
|
var BufferUtil = require('../../util/buffer');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function MultiSigScriptHashInput(input, pubkeys, threshold) {
|
function MultiSigScriptHashInput(input, pubkeys, threshold, signatures) {
|
||||||
Input.apply(this, arguments);
|
Input.apply(this, arguments);
|
||||||
var self = this;
|
var self = this;
|
||||||
this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); });
|
this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); });
|
||||||
@ -27,10 +28,50 @@ function MultiSigScriptHashInput(input, pubkeys, threshold) {
|
|||||||
});
|
});
|
||||||
this.threshold = threshold;
|
this.threshold = threshold;
|
||||||
// Empty array of signatures
|
// Empty array of signatures
|
||||||
this.signatures = new Array(this.publicKeys.length);
|
this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length);
|
||||||
}
|
}
|
||||||
inherits(MultiSigScriptHashInput, Input);
|
inherits(MultiSigScriptHashInput, Input);
|
||||||
|
|
||||||
|
MultiSigScriptHashInput.prototype.toObject = function() {
|
||||||
|
var obj = Input.prototype.toObject.apply(this, arguments);
|
||||||
|
obj.threshold = this.threshold;
|
||||||
|
obj.publicKeys = _.map(this.publicKeys, function(publicKey) { return publicKey.toString(); });
|
||||||
|
obj.signatures = this._serializeSignatures();
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) {
|
||||||
|
return _.map(signatures, function(signature) {
|
||||||
|
if (!signature) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
publicKey: new PublicKey(signature.publicKey),
|
||||||
|
prevTxId: signature.txId,
|
||||||
|
outputIndex: signature.outputIndex,
|
||||||
|
inputIndex: signature.inputIndex,
|
||||||
|
signature: Signature.fromString(signature.signature),
|
||||||
|
sigtype: signature.sigtype
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiSigScriptHashInput.prototype._serializeSignatures = function() {
|
||||||
|
return _.map(this.signatures, function(signature) {
|
||||||
|
if (!signature) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
publicKey: signature.publicKey.toString(),
|
||||||
|
prevTxId: signature.txId,
|
||||||
|
outputIndex: signature.outputIndex,
|
||||||
|
inputIndex: signature.inputIndex,
|
||||||
|
signature: signature.signature.toString(),
|
||||||
|
sigtype: signature.sigtype
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
MultiSigScriptHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype) {
|
MultiSigScriptHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype) {
|
||||||
$.checkState(this.output instanceof Output);
|
$.checkState(this.output instanceof Output);
|
||||||
sigtype = sigtype || Signature.SIGHASH_ALL;
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
||||||
|
|||||||
@ -249,6 +249,18 @@ Transaction.prototype.toObject = function toObject() {
|
|||||||
Transaction.prototype.fromObject = function(transaction) {
|
Transaction.prototype.fromObject = function(transaction) {
|
||||||
var self = this;
|
var self = this;
|
||||||
_.each(transaction.inputs, function(input) {
|
_.each(transaction.inputs, function(input) {
|
||||||
|
if (input.output.script) {
|
||||||
|
input.output.script = new Script(input.output.script);
|
||||||
|
if (input.output.script.isPublicKeyHashOut()) {
|
||||||
|
self.addInput(new Input.PublicKeyHash(input));
|
||||||
|
return;
|
||||||
|
} else if (input.output.script.isScriptHashOut() && input.publicKeys && input.threshold) {
|
||||||
|
self.addInput(new Input.MultiSigScriptHash(
|
||||||
|
input, input.publicKeys, input.threshold, input.signatures
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
self.addInput(new Input(input));
|
self.addInput(new Input(input));
|
||||||
});
|
});
|
||||||
_.each(transaction.outputs, function(output) {
|
_.each(transaction.outputs, function(output) {
|
||||||
|
|||||||
@ -98,7 +98,7 @@ UnspentOutput.prototype.toJSON = function() {
|
|||||||
*/
|
*/
|
||||||
UnspentOutput.prototype.toObject = function() {
|
UnspentOutput.prototype.toObject = function() {
|
||||||
return {
|
return {
|
||||||
address: this.address.toString(),
|
address: this.address ? this.address.toString() : undefined,
|
||||||
txid: this.txId,
|
txid: this.txId,
|
||||||
vout: this.outputIndex,
|
vout: this.outputIndex,
|
||||||
scriptPubKey: this.script.toBuffer().toString('hex'),
|
scriptPubKey: this.script.toBuffer().toString('hex'),
|
||||||
|
|||||||
@ -222,6 +222,13 @@ describe('Transaction', function() {
|
|||||||
var deserialized = new Transaction(serialized);
|
var deserialized = new Transaction(serialized);
|
||||||
expect(deserialized._change.toString()).to.equal(changeAddress);
|
expect(deserialized._change.toString()).to.equal(changeAddress);
|
||||||
});
|
});
|
||||||
|
it('can avoid checked serialize', function() {
|
||||||
|
var transaction = new Transaction()
|
||||||
|
.from(simpleUtxoWith1BTC)
|
||||||
|
.to(fromAddress, 1);
|
||||||
|
expect(function() { return transaction.serialize(); }).to.throw();
|
||||||
|
expect(function() { return transaction.serialize(true); }).to.not.throw();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('checked serialize', function() {
|
describe('checked serialize', function() {
|
||||||
@ -265,6 +272,30 @@ describe('Transaction', function() {
|
|||||||
expect(JSON.parse(transaction.toJSON()).change).to.equal(changeAddress.toString());
|
expect(JSON.parse(transaction.toJSON()).change).to.equal(changeAddress.toString());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('serialization of inputs', function() {
|
||||||
|
it('can serialize and deserialize a P2PKH input', function() {
|
||||||
|
var transaction = new Transaction()
|
||||||
|
.from(simpleUtxoWith1BTC);
|
||||||
|
var deserialized = new Transaction(transaction.toObject());
|
||||||
|
expect(deserialized.inputs[0] instanceof Transaction.Input.PublicKeyHash).to.equal(true);
|
||||||
|
});
|
||||||
|
it('can serialize and deserialize a P2SH input', function() {
|
||||||
|
var private1 = '6ce7e97e317d2af16c33db0b9270ec047a91bff3eff8558afb5014afb2bb5976';
|
||||||
|
var private2 = 'c9b26b0f771a0d2dad88a44de90f05f416b3b385ff1d989343005546a0032890';
|
||||||
|
var public1 = new PrivateKey(private1).publicKey;
|
||||||
|
var public2 = new PrivateKey(private2).publicKey;
|
||||||
|
var transaction = new Transaction()
|
||||||
|
.from({
|
||||||
|
txId: '0000', // Not relevant
|
||||||
|
outputIndex: 0,
|
||||||
|
script: Script.buildMultisigOut([public1, public2], 2).toScriptHashOut(),
|
||||||
|
satoshis: 10000
|
||||||
|
}, [public1, public2], 2);
|
||||||
|
var deserialized = new Transaction(transaction.toObject());
|
||||||
|
expect(deserialized.inputs[0] instanceof Transaction.Input.MultiSigScriptHash).to.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var tx_empty_hex = '01000000000000000000';
|
var tx_empty_hex = '01000000000000000000';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user