wallet work. consistency.
This commit is contained in:
parent
f3fd85354e
commit
2deccde29e
@ -87,8 +87,8 @@ function Address(options) {
|
|||||||
this.addKey(key);
|
this.addKey(key);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if (options.redeem)
|
if (options.redeem || options.script)
|
||||||
this.setRedeem(options.redeem);
|
this.setRedeem(options.redeem || options.script);
|
||||||
|
|
||||||
this.prefix = 'bt/address/' + this.getKeyAddress() + '/';
|
this.prefix = 'bt/address/' + this.getKeyAddress() + '/';
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ Address.prototype.setRedeem = function setRedeem(redeem) {
|
|||||||
this.type = 'scripthash';
|
this.type = 'scripthash';
|
||||||
this.subtype = null;
|
this.subtype = null;
|
||||||
this.redeem = redeem;
|
this.redeem = redeem;
|
||||||
this.emit('scriptaddress', old, this.getScriptAddress());
|
this.emit('update script', old, this.getScriptAddress());
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.addKey = function addKey(key) {
|
Address.prototype.addKey = function addKey(key) {
|
||||||
@ -124,10 +124,15 @@ Address.prototype.addKey = function addKey(key) {
|
|||||||
|
|
||||||
this.keys = utils.sortKeys(this.keys);
|
this.keys = utils.sortKeys(this.keys);
|
||||||
|
|
||||||
|
delete this._scriptAddress;
|
||||||
|
delete this._scriptHash;
|
||||||
|
delete this._script;
|
||||||
|
this.getScriptAddress();
|
||||||
|
|
||||||
cur = this.getScriptAddress();
|
cur = this.getScriptAddress();
|
||||||
|
|
||||||
if (old !== cur)
|
if (old !== cur)
|
||||||
this.emit('scriptaddress', old, cur);
|
this.emit('update script', old, cur);
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.removeKey = function removeKey(key) {
|
Address.prototype.removeKey = function removeKey(key) {
|
||||||
@ -149,10 +154,15 @@ Address.prototype.removeKey = function removeKey(key) {
|
|||||||
|
|
||||||
this.keys = utils.sortKeys(this.keys);
|
this.keys = utils.sortKeys(this.keys);
|
||||||
|
|
||||||
|
delete this._scriptAddress;
|
||||||
|
delete this._scriptHash;
|
||||||
|
delete this._script;
|
||||||
|
this.getScriptAddress();
|
||||||
|
|
||||||
cur = this.getScriptAddress();
|
cur = this.getScriptAddress();
|
||||||
|
|
||||||
if (old !== cur)
|
if (old !== cur)
|
||||||
this.emit('scriptaddress', old, this.getScriptAddress());
|
this.emit('update script', old, cur);
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getPrivateKey = function getPrivateKey(enc) {
|
Address.prototype.getPrivateKey = function getPrivateKey(enc) {
|
||||||
@ -171,51 +181,82 @@ Address.prototype.getScript = function getScript() {
|
|||||||
if (this.type !== 'scripthash')
|
if (this.type !== 'scripthash')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (this._script)
|
||||||
|
return this._script;
|
||||||
|
|
||||||
if (this.redeem)
|
if (this.redeem)
|
||||||
return this.redeem.slice();
|
return this._script = this.redeem.slice();
|
||||||
|
|
||||||
if (this.subtype === 'pubkey')
|
if (this.subtype === 'pubkey')
|
||||||
return bcoin.script.encode([this.getPublicKey(), 'checksig']);
|
this._script = bcoin.script.createPubkey(this.getPublicKey());
|
||||||
|
else if (this.subtype === 'pubkeyhash' || this.keys.length < this.n)
|
||||||
|
this._script = bcoin.script.createPubkeyhash(this.getKeyHash());
|
||||||
|
else if (this.subtype === 'multisig')
|
||||||
|
this._script = bcoin.script.createMultisig(this.keys, this.m, this.n);
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
|
||||||
if (this.subtype === 'pubkeyhash' || this.keys.length < this.n) {
|
this._script = bcoin.script.encode(this._script);
|
||||||
return bcoin.script.encode([
|
|
||||||
'dup',
|
|
||||||
'hash160',
|
|
||||||
this.getKeyHash(),
|
|
||||||
'equalverify',
|
|
||||||
'checksig'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bcoin.script.encode(
|
return this._script;
|
||||||
bcoin.script.createMultisig(this.keys, this.m, this.n)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getScriptHash = function getScriptHash() {
|
Address.prototype.getScriptHash = function getScriptHash() {
|
||||||
if (this.type !== 'scripthash')
|
if (this.type !== 'scripthash')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
return utils.ripesha(this.getScript());
|
if (this._scriptHash)
|
||||||
|
return this._scriptHash;
|
||||||
|
|
||||||
|
this._scriptHash = utils.ripesha(this.getScript());
|
||||||
|
|
||||||
|
return this._scriptHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getScriptAddress = function getScriptAddress() {
|
Address.prototype.getScriptAddress = function getScriptAddress() {
|
||||||
if (this.type !== 'scripthash')
|
if (this.type !== 'scripthash')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
return Address.hash2addr(this.getScriptHash(), this.type);
|
if (this._scriptAddress)
|
||||||
|
return this._scriptAddress;
|
||||||
|
|
||||||
|
this._scriptAddress = Address.hash2addr(this.getScriptHash(), this.type);
|
||||||
|
|
||||||
|
return this._scriptAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getPublicKey = function getPublicKey(enc) {
|
Address.prototype.getPublicKey = function getPublicKey(enc) {
|
||||||
|
if (!this.key.priv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!enc) {
|
||||||
|
if (this._pub)
|
||||||
|
return this._pub;
|
||||||
|
|
||||||
|
this._pub = this.key.getPublic();
|
||||||
|
|
||||||
|
return this._pub;
|
||||||
|
}
|
||||||
|
|
||||||
return this.key.getPublic(enc);
|
return this.key.getPublic(enc);
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getKeyHash = function getKeyHash() {
|
Address.prototype.getKeyHash = function getKeyHash() {
|
||||||
return Address.key2hash(this.getPublicKey());
|
if (this._hash)
|
||||||
|
return this._hash;
|
||||||
|
|
||||||
|
this._hash = Address.key2hash(this.getPublicKey());
|
||||||
|
|
||||||
|
return this._hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getKeyAddress = function getKeyAddress() {
|
Address.prototype.getKeyAddress = function getKeyAddress() {
|
||||||
return Address.hash2addr(this.getKeyHash(), 'pubkeyhash');
|
if (this._address)
|
||||||
|
return this._address;
|
||||||
|
|
||||||
|
this._address = Address.hash2addr(this.getKeyHash(), 'pubkeyhash');
|
||||||
|
|
||||||
|
return this._address;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getHash = function getHash() {
|
Address.prototype.getHash = function getHash() {
|
||||||
@ -248,6 +289,10 @@ Address.hash2addr = function hash2addr(hash, prefix) {
|
|||||||
return utils.toBase58(addr);
|
return utils.toBase58(addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Address.key2addr = function key2addr(key, prefix) {
|
||||||
|
return Address.hash2addr(Address.key2hash(key), prefix);
|
||||||
|
};
|
||||||
|
|
||||||
Address.__defineGetter__('prefixes', function() {
|
Address.__defineGetter__('prefixes', function() {
|
||||||
if (Address._prefixes)
|
if (Address._prefixes)
|
||||||
return Address._prefixes;
|
return Address._prefixes;
|
||||||
@ -286,7 +331,7 @@ Address.addr2hash = function addr2hash(addr, prefix) {
|
|||||||
return addr.slice(1, -4);
|
return addr.slice(1, -4);
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.validate = function validateAddress(addr, prefix) {
|
Address.validate = function validate(addr, prefix) {
|
||||||
if (!addr || typeof addr !== 'string')
|
if (!addr || typeof addr !== 'string')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -298,12 +343,13 @@ Address.validate = function validateAddress(addr, prefix) {
|
|||||||
Address.validateAddress = Address.validate;
|
Address.validateAddress = Address.validate;
|
||||||
|
|
||||||
Address.prototype.ownOutput = function ownOutput(tx, index) {
|
Address.prototype.ownOutput = function ownOutput(tx, index) {
|
||||||
var scripthash = this.getScriptHash();
|
var scriptHash = this.getScriptHash();
|
||||||
var hash = this.getKeyHash();
|
var hash = this.getKeyHash();
|
||||||
var key = this.getPublicKey();
|
var key = this.getPublicKey();
|
||||||
var keys = this.keys;
|
var keys = this.keys;
|
||||||
|
var outputs;
|
||||||
|
|
||||||
var outputs = tx.outputs.filter(function(output, i) {
|
outputs = tx.outputs.filter(function(output, i) {
|
||||||
var s = output.script;
|
var s = output.script;
|
||||||
|
|
||||||
if (index != null && index !== i)
|
if (index != null && index !== i)
|
||||||
@ -318,8 +364,8 @@ Address.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
if (bcoin.script.isMultisig(s, keys))
|
if (bcoin.script.isMultisig(s, keys))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (scripthash) {
|
if (scriptHash) {
|
||||||
if (bcoin.script.isScripthash(s, scripthash))
|
if (bcoin.script.isScripthash(s, scriptHash))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,13 +379,14 @@ Address.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.ownInput = function ownInput(tx, index) {
|
Address.prototype.ownInput = function ownInput(tx, index) {
|
||||||
var scripthash = this.getScriptHash();
|
var scriptHash = this.getScriptHash();
|
||||||
var hash = this.getKeyHash();
|
var hash = this.getKeyHash();
|
||||||
var key = this.getPublicKey();
|
var key = this.getPublicKey();
|
||||||
var redeem = this.getScript();
|
var redeem = this.getScript();
|
||||||
var keys = this.keys;
|
var keys = this.keys;
|
||||||
|
var inputs;
|
||||||
|
|
||||||
var inputs = tx.inputs.filter(function(input, i) {
|
inputs = tx.inputs.filter(function(input, i) {
|
||||||
var s;
|
var s;
|
||||||
|
|
||||||
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
|
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
|
||||||
@ -376,8 +423,8 @@ Address.prototype.ownInput = function ownInput(tx, index) {
|
|||||||
if (bcoin.script.isMultisig(s, keys))
|
if (bcoin.script.isMultisig(s, keys))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (scripthash) {
|
if (scriptHash) {
|
||||||
if (bcoin.script.isScripthash(s, scripthash))
|
if (bcoin.script.isScripthash(s, scriptHash))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,6 +437,108 @@ Address.prototype.ownInput = function ownInput(tx, index) {
|
|||||||
return inputs;
|
return inputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Address.prototype.scriptInputs = function scriptInputs(tx) {
|
||||||
|
var self = this;
|
||||||
|
var pub = this.getPublicKey();
|
||||||
|
var redeem = this.getScript();
|
||||||
|
|
||||||
|
return tx.inputs.reduce(function(total, input, i) {
|
||||||
|
if (!input.prevout.tx)
|
||||||
|
return total;
|
||||||
|
|
||||||
|
if (!self.ownOutput(input.prevout.tx, input.prevout.index))
|
||||||
|
return total;
|
||||||
|
|
||||||
|
if (tx.scriptInput(i, pub, redeem))
|
||||||
|
total++;
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Address.prototype.signInputs = function signInputs(tx, type) {
|
||||||
|
var self = this;
|
||||||
|
var key = this.key;
|
||||||
|
var total = 0;
|
||||||
|
|
||||||
|
if (!key.priv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return tx.inputs.reduce(function(total, input, i) {
|
||||||
|
if (!input.prevout.tx)
|
||||||
|
return total;
|
||||||
|
|
||||||
|
if (!self.ownOutput(input.prevout.tx, input.prevout.index))
|
||||||
|
return total;
|
||||||
|
|
||||||
|
if (tx.signInput(i, key, type))
|
||||||
|
total++;
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Address.prototype.sign = function sign(tx, type) {
|
||||||
|
var self = this;
|
||||||
|
var pub = this.getPublicKey();
|
||||||
|
var redeem = this.getScript();
|
||||||
|
var key = this.key;
|
||||||
|
|
||||||
|
if (!key.priv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Add signature script to each input
|
||||||
|
return tx.inputs.reduce(function(total, input, i) {
|
||||||
|
// Filter inputs that this wallet own
|
||||||
|
if (!input.prevout.tx)
|
||||||
|
return total;
|
||||||
|
|
||||||
|
if (!self.ownOutput(input.prevout.tx, input.prevout.index))
|
||||||
|
return total;
|
||||||
|
|
||||||
|
if (tx.scriptSig(i, key, pub, redeem, type))
|
||||||
|
total++;
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('script', function() {
|
||||||
|
return this.getScript();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('scriptHash', function() {
|
||||||
|
return this.getScriptHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('scriptAddress', function() {
|
||||||
|
return this.getScriptAddress();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('privateKey', function() {
|
||||||
|
return this.getPrivateKey();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('publicKey', function() {
|
||||||
|
return this.getPublicKey();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('keyHash', function() {
|
||||||
|
return this.getKeyHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('keyAddress', function() {
|
||||||
|
return this.getKeyAddress();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('hash', function() {
|
||||||
|
return this.getHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
Address.prototype.__defineGetter__('address', function() {
|
||||||
|
return this.getAddress();
|
||||||
|
});
|
||||||
|
|
||||||
Address.prototype.toJSON = function toJSON(encrypt) {
|
Address.prototype.toJSON = function toJSON(encrypt) {
|
||||||
return {
|
return {
|
||||||
v: 1,
|
v: 1,
|
||||||
@ -398,7 +547,7 @@ Address.prototype.toJSON = function toJSON(encrypt) {
|
|||||||
label: this.label,
|
label: this.label,
|
||||||
change: this.change,
|
change: this.change,
|
||||||
address: this.getKeyAddress(),
|
address: this.getKeyAddress(),
|
||||||
scriptaddress: this.getScriptAddress(),
|
scriptAddress: this.getScriptAddress(),
|
||||||
key: this.key.toJSON(encrypt),
|
key: this.key.toJSON(encrypt),
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.subtype,
|
subtype: this.subtype,
|
||||||
|
|||||||
@ -21,6 +21,8 @@ function Input(options) {
|
|||||||
|
|
||||||
prevout = options.prevout || options.out;
|
prevout = options.prevout || options.out;
|
||||||
|
|
||||||
|
this.tx = options.tx;
|
||||||
|
|
||||||
this.prevout = {
|
this.prevout = {
|
||||||
tx: prevout.tx || null,
|
tx: prevout.tx || null,
|
||||||
hash: prevout.hash,
|
hash: prevout.hash,
|
||||||
@ -66,8 +68,10 @@ Input.prototype.__defineGetter__('data', function() {
|
|||||||
|
|
||||||
data = Input.getData(this);
|
data = Input.getData(this);
|
||||||
|
|
||||||
if (this.script.length && this.prevout.tx)
|
if (!this.tx || this.tx.ps === 0) {
|
||||||
utils.hidden(this, '_data', data);
|
if (this.script.length && this.prevout.tx)
|
||||||
|
utils.hidden(this, '_data', data);
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
@ -89,11 +93,11 @@ Input.prototype.__defineGetter__('key', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('hash', function() {
|
Input.prototype.__defineGetter__('hash', function() {
|
||||||
return this.data.scripthash || this.hashes[0];
|
return this.data.scriptHash || this.hashes[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('address', function() {
|
Input.prototype.__defineGetter__('address', function() {
|
||||||
return this.data.scriptaddress || this.addresses[0] || this.getID();
|
return this.data.scriptAddress || this.addresses[0] || this.getID();
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('signatures', function() {
|
Input.prototype.__defineGetter__('signatures', function() {
|
||||||
@ -116,12 +120,12 @@ Input.prototype.__defineGetter__('redeem', function() {
|
|||||||
return this.data.redeem;
|
return this.data.redeem;
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('scripthash', function() {
|
Input.prototype.__defineGetter__('scriptHash', function() {
|
||||||
return this.data.scripthash;
|
return this.data.scriptHash;
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('scriptaddress', function() {
|
Input.prototype.__defineGetter__('scriptAddress', function() {
|
||||||
return this.data.scriptaddress;
|
return this.data.scriptAddress;
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('m', function() {
|
Input.prototype.__defineGetter__('m', function() {
|
||||||
@ -132,10 +136,10 @@ Input.prototype.__defineGetter__('n', function() {
|
|||||||
return this.data.n || this.m;
|
return this.data.n || this.m;
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('lockTime', function() {
|
Input.prototype.__defineGetter__('locktime', function() {
|
||||||
if (!this.output)
|
if (!this.output)
|
||||||
return 0;
|
return 0;
|
||||||
return this.output.lockTime;
|
return this.output.locktime;
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('flags', function() {
|
Input.prototype.__defineGetter__('flags', function() {
|
||||||
@ -187,7 +191,7 @@ Input.prototype.__defineGetter__('sigs', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('scriptaddr', function() {
|
Input.prototype.__defineGetter__('scriptaddr', function() {
|
||||||
return this.scriptaddress;
|
return this.scriptAddress;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Schema and defaults for data object:
|
// Schema and defaults for data object:
|
||||||
@ -200,14 +204,14 @@ Input.prototype.__defineGetter__('scriptaddr', function() {
|
|||||||
// hashes: Array,
|
// hashes: Array,
|
||||||
// addresses: Array,
|
// addresses: Array,
|
||||||
// redeem: Array,
|
// redeem: Array,
|
||||||
// scripthash: Array,
|
// scriptHash: Array,
|
||||||
// scriptaddress: String,
|
// scriptAddress: String,
|
||||||
// m: Number,
|
// m: Number,
|
||||||
// n: Number,
|
// n: Number,
|
||||||
// height: Number,
|
// height: Number,
|
||||||
// flags: Array,
|
// flags: Array,
|
||||||
// text: String,
|
// text: String,
|
||||||
// lockTime: Number,
|
// locktime: Number,
|
||||||
// value: bn,
|
// value: bn,
|
||||||
// script: Array,
|
// script: Array,
|
||||||
// seq: Number,
|
// seq: Number,
|
||||||
@ -281,6 +285,49 @@ Input.prototype.getLocktime = function getLocktime() {
|
|||||||
return bcoin.script.getLocktime(redeem);
|
return bcoin.script.getLocktime(redeem);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Input.prototype.createScript = function createScript(pub, redeem) {
|
||||||
|
return this.tx.scriptInput(this, pub, redeem);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.signatureHash = function signatureHash(s, type) {
|
||||||
|
return this.tx.signatureHash(this, s, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.createSignature = function createSignature(key, type) {
|
||||||
|
return this.tx.createSignature(this, key, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.sign = function sign(key, type) {
|
||||||
|
return this.tx.signInput(this, key, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.scriptSig = function scriptSig(key, pub, redeem, type) {
|
||||||
|
return this.tx.scriptSig(this, key, pub, redeem, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.isSigned = function isSigned(required) {
|
||||||
|
return this.tx.isSigned(this, required);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.verify = function verify(force, flags) {
|
||||||
|
return this.tx.verify(this, force, flags);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.isCoinbase = function isCoinbase() {
|
||||||
|
return this.tx.isCoinbase();
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.test = function test(addressTable, collect) {
|
||||||
|
return this.tx.testInputs(addressTable, this, collect);
|
||||||
|
};
|
||||||
|
|
||||||
|
Input.prototype.getSigops = function getSigops(scriptHash, accurate) {
|
||||||
|
var n = bcoin.script.getSigops(this.script, accurate);
|
||||||
|
if (scriptHash && !this.tx.isCoinbase())
|
||||||
|
n += bcoin.script.getScripthashSigops(this.script);
|
||||||
|
return n;
|
||||||
|
};
|
||||||
|
|
||||||
Input.prototype.inspect = function inspect() {
|
Input.prototype.inspect = function inspect() {
|
||||||
var output = this.output
|
var output = this.output
|
||||||
? this.output.inspect()
|
? this.output.inspect()
|
||||||
@ -297,10 +344,10 @@ Input.prototype.inspect = function inspect() {
|
|||||||
keys: this.keys.map(utils.toHex),
|
keys: this.keys.map(utils.toHex),
|
||||||
hashes: this.hashes.map(utils.toHex),
|
hashes: this.hashes.map(utils.toHex),
|
||||||
addresses: this.addresses,
|
addresses: this.addresses,
|
||||||
scriptaddress: this.scriptaddress,
|
scriptAddress: this.scriptAddress,
|
||||||
signatures: this.signatures.map(utils.toHex),
|
signatures: this.signatures.map(utils.toHex),
|
||||||
text: this.text,
|
text: this.text,
|
||||||
lockTime: this.lockTime,
|
locktime: this.locktime,
|
||||||
value: utils.btc(output.value),
|
value: utils.btc(output.value),
|
||||||
script: bcoin.script.format(this.script)[0],
|
script: bcoin.script.format(this.script)[0],
|
||||||
redeem: this.redeem ? bcoin.script.format(this.redeem)[0] : null,
|
redeem: this.redeem ? bcoin.script.format(this.redeem)[0] : null,
|
||||||
|
|||||||
@ -25,6 +25,7 @@ function Output(options) {
|
|||||||
if (typeof value === 'number' && (value | 0) === value)
|
if (typeof value === 'number' && (value | 0) === value)
|
||||||
value = new bn(value);
|
value = new bn(value);
|
||||||
|
|
||||||
|
this.tx = options.tx;
|
||||||
this.value = utils.satoshi(value || new bn(0));
|
this.value = utils.satoshi(value || new bn(0));
|
||||||
this.script = options.script ? options.script.slice() : [];
|
this.script = options.script ? options.script.slice() : [];
|
||||||
|
|
||||||
@ -47,8 +48,10 @@ Output.prototype.__defineGetter__('data', function() {
|
|||||||
|
|
||||||
data = Output.getData(this);
|
data = Output.getData(this);
|
||||||
|
|
||||||
if (this.script.length && this.value.cmpn(0) !== 0)
|
if (!this.tx || this.tx.ps === 0) {
|
||||||
utils.hidden(this, '_data', data);
|
if (this.script.length && this.value.cmpn(0) > 0)
|
||||||
|
utils.hidden(this, '_data', data);
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
@ -66,11 +69,11 @@ Output.prototype.__defineGetter__('key', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('hash', function() {
|
Output.prototype.__defineGetter__('hash', function() {
|
||||||
return this.data.scripthash || this.hashes[0];
|
return this.data.scriptHash || this.hashes[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('address', function() {
|
Output.prototype.__defineGetter__('address', function() {
|
||||||
return this.data.scriptaddress || this.addresses[0] || this.getID();
|
return this.data.scriptAddress || this.addresses[0] || this.getID();
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('signatures', function() {
|
Output.prototype.__defineGetter__('signatures', function() {
|
||||||
@ -89,12 +92,12 @@ Output.prototype.__defineGetter__('addresses', function() {
|
|||||||
return this.data.addresses || [];
|
return this.data.addresses || [];
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('scripthash', function() {
|
Output.prototype.__defineGetter__('scriptHash', function() {
|
||||||
return this.data.scripthash;
|
return this.data.scriptHash;
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('scriptaddress', function() {
|
Output.prototype.__defineGetter__('scriptAddress', function() {
|
||||||
return this.data.scriptaddress;
|
return this.data.scriptAddress;
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('m', function() {
|
Output.prototype.__defineGetter__('m', function() {
|
||||||
@ -105,8 +108,8 @@ Output.prototype.__defineGetter__('n', function() {
|
|||||||
return this.data.n || this.m;
|
return this.data.n || this.m;
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('lockTime', function() {
|
Output.prototype.__defineGetter__('locktime', function() {
|
||||||
return bcoin.script.getLockTime(this.script);
|
return bcoin.script.getLocktime(this.script);
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('flags', function() {
|
Output.prototype.__defineGetter__('flags', function() {
|
||||||
@ -117,6 +120,7 @@ Output.prototype.__defineGetter__('text', function() {
|
|||||||
return this.data.text;
|
return this.data.text;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Legacy
|
||||||
Output.prototype.__defineGetter__('addr', function() {
|
Output.prototype.__defineGetter__('addr', function() {
|
||||||
return this.address;
|
return this.address;
|
||||||
});
|
});
|
||||||
@ -142,7 +146,7 @@ Output.prototype.__defineGetter__('sigs', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('scriptaddr', function() {
|
Output.prototype.__defineGetter__('scriptaddr', function() {
|
||||||
return this.scriptaddress;
|
return this.scriptAddress;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Schema and defaults for data object:
|
// Schema and defaults for data object:
|
||||||
@ -155,14 +159,14 @@ Output.prototype.__defineGetter__('scriptaddr', function() {
|
|||||||
// hashes: Array,
|
// hashes: Array,
|
||||||
// addresses: Array,
|
// addresses: Array,
|
||||||
// redeem: Array,
|
// redeem: Array,
|
||||||
// scripthash: Array,
|
// scriptHash: Array,
|
||||||
// scriptaddress: String,
|
// scriptAddress: String,
|
||||||
// m: Number,
|
// m: Number,
|
||||||
// n: Number,
|
// n: Number,
|
||||||
// height: Number,
|
// height: Number,
|
||||||
// flags: Array,
|
// flags: Array,
|
||||||
// text: String,
|
// text: String,
|
||||||
// lockTime: Number,
|
// locktime: Number,
|
||||||
// value: bn,
|
// value: bn,
|
||||||
// script: Array,
|
// script: Array,
|
||||||
// seq: Number,
|
// seq: Number,
|
||||||
@ -192,6 +196,18 @@ Output.prototype.getID = function getID() {
|
|||||||
return '[' + this.type + ':' + hash.slice(0, 7) + ']';
|
return '[' + this.type + ':' + hash.slice(0, 7) + ']';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Output.prototype.createScript = function createScript(options) {
|
||||||
|
return this.tx.scriptOutput(this, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
Output.prototype.test = function test(addressTable, collect) {
|
||||||
|
return this.tx.testOutputs(addressTable, this, collect);
|
||||||
|
};
|
||||||
|
|
||||||
|
Output.prototype.getSigops = function getSigops(accurate) {
|
||||||
|
return bcoin.script.getSigops(this.script, accurate);
|
||||||
|
};
|
||||||
|
|
||||||
Output.prototype.inspect = function inspect() {
|
Output.prototype.inspect = function inspect() {
|
||||||
return {
|
return {
|
||||||
type: this.type,
|
type: this.type,
|
||||||
@ -199,11 +215,11 @@ Output.prototype.inspect = function inspect() {
|
|||||||
keys: this.keys.map(utils.toHex),
|
keys: this.keys.map(utils.toHex),
|
||||||
hashes: this.hashes.map(utils.toHex),
|
hashes: this.hashes.map(utils.toHex),
|
||||||
addresses: this.addresses,
|
addresses: this.addresses,
|
||||||
scriptaddress: this.scriptaddress,
|
scriptAddress: this.scriptAddress,
|
||||||
m: this.m,
|
m: this.m,
|
||||||
n: this.n,
|
n: this.n,
|
||||||
text: this.text,
|
text: this.text,
|
||||||
lockTime: this.lockTime,
|
locktime: this.locktime,
|
||||||
value: utils.btc(this.value),
|
value: utils.btc(this.value),
|
||||||
script: bcoin.script.format(this.script)[0]
|
script: bcoin.script.format(this.script)[0]
|
||||||
};
|
};
|
||||||
|
|||||||
@ -301,7 +301,7 @@ Framer.tx = function tx(tx) {
|
|||||||
off += utils.writeIntv(p, s.length, off);
|
off += utils.writeIntv(p, s.length, off);
|
||||||
off += utils.copy(s, p, off, true);
|
off += utils.copy(s, p, off, true);
|
||||||
}
|
}
|
||||||
off += utils.writeU32(p, tx.lockTime, off);
|
off += utils.writeU32(p, tx.locktime, off);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -461,7 +461,7 @@ Parser.prototype.parseTX = function parseTX(p) {
|
|||||||
version: utils.read32(p, 0),
|
version: utils.read32(p, 0),
|
||||||
inputs: txIn,
|
inputs: txIn,
|
||||||
outputs: txOut,
|
outputs: txOut,
|
||||||
lockTime: utils.readU32(p, off),
|
locktime: utils.readU32(p, off),
|
||||||
_off: off + 4,
|
_off: off + 4,
|
||||||
_size: p.length
|
_size: p.length
|
||||||
};
|
};
|
||||||
|
|||||||
@ -386,7 +386,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
var key, sig, type, subscript, hash;
|
var key, sig, type, subscript, hash;
|
||||||
var keys, i, j, m;
|
var keys, i, j, m;
|
||||||
var succ;
|
var succ;
|
||||||
var lockTime, threshold;
|
var locktime, threshold;
|
||||||
var evalScript;
|
var evalScript;
|
||||||
|
|
||||||
stack.alt = stack.alt || [];
|
stack.alt = stack.alt || [];
|
||||||
@ -934,28 +934,28 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
if (!tx || stack.length === 0)
|
if (!tx || stack.length === 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
lockTime = stack[stack.length - 1];
|
locktime = stack[stack.length - 1];
|
||||||
|
|
||||||
if (!Array.isArray(lockTime))
|
if (!Array.isArray(locktime))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (lockTime.length > 6)
|
if (locktime.length > 6)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
lockTime = script.num(lockTime, true);
|
locktime = script.num(locktime, true);
|
||||||
|
|
||||||
if (lockTime < 0)
|
if (locktime < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
threshold = constants.locktimeThreshold;
|
threshold = constants.locktimeThreshold;
|
||||||
if (!(
|
if (!(
|
||||||
(tx.lockTime < threshold && lockTime < threshold)
|
(tx.locktime < threshold && locktime < threshold)
|
||||||
|| (tx.lockTime >= threshold && lockTime >= threshold)
|
|| (tx.locktime >= threshold && locktime >= threshold)
|
||||||
)) {
|
)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lockTime > tx.lockTime)
|
if (locktime > tx.locktime)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!tx.inputs[index] || tx.inputs[index].seq === 0xffffffff)
|
if (!tx.inputs[index] || tx.inputs[index].seq === 0xffffffff)
|
||||||
@ -1158,6 +1158,20 @@ script.checkPush = function checkPush(op, value, flags) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.createPubkey = function createPubkey(key) {
|
||||||
|
return [key, 'checksig'];
|
||||||
|
};
|
||||||
|
|
||||||
|
script.createPubkeyhash = function createPubkeyhash(hash) {
|
||||||
|
return [
|
||||||
|
'dup',
|
||||||
|
'hash160',
|
||||||
|
hash,
|
||||||
|
'equalverify',
|
||||||
|
'checksig'
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
script.createMultisig = function createMultisig(keys, m, n) {
|
script.createMultisig = function createMultisig(keys, m, n) {
|
||||||
if (keys.length !== n)
|
if (keys.length !== n)
|
||||||
throw new Error(n + ' keys are required to generate multisig script');
|
throw new Error(n + ' keys are required to generate multisig script');
|
||||||
@ -1171,15 +1185,21 @@ script.createMultisig = function createMultisig(keys, m, n) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
script.createScripthash = function createScripthash(s) {
|
script.createScripthash = function createScripthash(hash) {
|
||||||
assert(Array.isArray(s));
|
|
||||||
return [
|
return [
|
||||||
'hash160',
|
'hash160',
|
||||||
utils.ripesha(script.encode(s)),
|
hash,
|
||||||
'equal'
|
'equal'
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.createNulldata = function createNulldata(flags) {
|
||||||
|
return [
|
||||||
|
'return',
|
||||||
|
flags
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
script.getRedeem = function getRedeem(s) {
|
script.getRedeem = function getRedeem(s) {
|
||||||
if (!Array.isArray(s[s.length - 1]))
|
if (!Array.isArray(s[s.length - 1]))
|
||||||
return;
|
return;
|
||||||
@ -1247,7 +1267,7 @@ script.isEncoded = function isEncoded(s) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
script._lockTime = function _lockTime(s) {
|
script._locktime = function _locktime(s) {
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
if (s.length < 2)
|
if (s.length < 2)
|
||||||
@ -1259,22 +1279,22 @@ script._lockTime = function _lockTime(s) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isLockTime = function isLockTime(s) {
|
script.isLocktime = function isLocktime(s) {
|
||||||
return !!script._lockTime(s);
|
return !!script._locktime(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
script.getLockTime = function getLockTime(s) {
|
script.getLocktime = function getLocktime(s) {
|
||||||
var lockTime = script._lockTime(s);
|
var locktime = script._locktime(s);
|
||||||
|
|
||||||
if (!lockTime)
|
if (!locktime)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lockTime = script.num(lockTime, true);
|
locktime = script.num(locktime, true);
|
||||||
|
|
||||||
if (lockTime < constants.locktimeThreshold)
|
if (locktime < constants.locktimeThreshold)
|
||||||
return { type: 'height', value: lockTime };
|
return { type: 'height', value: locktime };
|
||||||
|
|
||||||
return { type: 'time', value: lockTime };
|
return { type: 'time', value: locktime };
|
||||||
};
|
};
|
||||||
|
|
||||||
script.getInputData = function getData(s, prev) {
|
script.getInputData = function getData(s, prev) {
|
||||||
@ -1320,7 +1340,7 @@ script.getInputData = function getData(s, prev) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
script._getInputData = function _getInputData(s, type) {
|
script._getInputData = function _getInputData(s, type) {
|
||||||
var sig, key, hash, raw, redeem, lockTime, hash, address, input, output;
|
var sig, key, hash, raw, redeem, locktime, hash, address, input, output;
|
||||||
|
|
||||||
assert(typeof type === 'string');
|
assert(typeof type === 'string');
|
||||||
|
|
||||||
@ -1363,7 +1383,7 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
if (type === 'scripthash') {
|
if (type === 'scripthash') {
|
||||||
raw = s[s.length - 1];
|
raw = s[s.length - 1];
|
||||||
redeem = script.decode(raw);
|
redeem = script.decode(raw);
|
||||||
lockTime = script.getLockTime(redeem);
|
locktime = script.getLocktime(redeem);
|
||||||
hash = bcoin.wallet.key2hash(raw);
|
hash = bcoin.wallet.key2hash(raw);
|
||||||
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
||||||
output = script.getOutputData(script.getSubscript(redeem));
|
output = script.getOutputData(script.getSubscript(redeem));
|
||||||
@ -1374,9 +1394,9 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
side: 'input',
|
side: 'input',
|
||||||
subtype: output.type,
|
subtype: output.type,
|
||||||
redeem: redeem,
|
redeem: redeem,
|
||||||
scripthash: hash,
|
scriptHash: hash,
|
||||||
scriptaddress: address,
|
scriptAddress: address,
|
||||||
lockTime: lockTime
|
locktime: locktime
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1433,8 +1453,8 @@ script.getOutputData = function getOutputData(s) {
|
|||||||
return {
|
return {
|
||||||
type: 'scripthash',
|
type: 'scripthash',
|
||||||
side: 'output',
|
side: 'output',
|
||||||
scripthash: hash,
|
scriptHash: hash,
|
||||||
scriptaddress: bcoin.wallet.hash2addr(hash, 'scripthash')
|
scriptAddress: bcoin.wallet.hash2addr(hash, 'scripthash')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -233,6 +233,19 @@ TXPool.prototype._removeTX = function _removeTX(tx, noWrite) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TXPool.prototype.prune = function prune(pruneOrphans) {
|
||||||
|
var unspent = Object.keys(this._unspent).reduce(function(key) {
|
||||||
|
out[key.split('/')[0]] = true;
|
||||||
|
return out;
|
||||||
|
}, {});
|
||||||
|
Object.keys(this._all).forEach(function(key) {
|
||||||
|
if (!unspent[key])
|
||||||
|
delete this._all[key];
|
||||||
|
});
|
||||||
|
if (pruneOrphans)
|
||||||
|
this._orphans = {};
|
||||||
|
};
|
||||||
|
|
||||||
TXPool.prototype.getAll = function getAll() {
|
TXPool.prototype.getAll = function getAll() {
|
||||||
return Object.keys(this._all).map(function(key) {
|
return Object.keys(this._all).map(function(key) {
|
||||||
return this._all[key];
|
return this._all[key];
|
||||||
@ -250,43 +263,6 @@ TXPool.prototype.getUnspent = function getUnspent() {
|
|||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
|
|
||||||
var has;
|
|
||||||
|
|
||||||
if (utils.isBuffer(hash) && hash.length && typeof hash[0] !== 'number') {
|
|
||||||
unspent = this.getUnspent();
|
|
||||||
has = hash.map(function(hash) {
|
|
||||||
var h = this.hasUnspent(hash, unspent);
|
|
||||||
if (!h)
|
|
||||||
return false;
|
|
||||||
return h[0];
|
|
||||||
}, this).filter(Boolean);
|
|
||||||
if (has.length !== hash.length)
|
|
||||||
return null;
|
|
||||||
return has;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utils.isBuffer(hash))
|
|
||||||
hash = utils.toHex(hash);
|
|
||||||
else if (hash.prevout)
|
|
||||||
hash = hash.prevout.hash;
|
|
||||||
else if (hash.tx)
|
|
||||||
hash = hash.tx.hash('hex');
|
|
||||||
else if (hash instanceof bcoin.tx)
|
|
||||||
hash = hash.hash('hex');
|
|
||||||
|
|
||||||
unspent = unspent || this.getUnspent();
|
|
||||||
|
|
||||||
has = unspent.filter(function(item) {
|
|
||||||
return item.tx.hash('hex') === hash;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!has.length)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return has;
|
|
||||||
};
|
|
||||||
|
|
||||||
TXPool.prototype.getPending = function getPending() {
|
TXPool.prototype.getPending = function getPending() {
|
||||||
return Object.keys(this._all).map(function(key) {
|
return Object.keys(this._all).map(function(key) {
|
||||||
return this._all[key];
|
return this._all[key];
|
||||||
|
|||||||
140
lib/bcoin/tx.js
140
lib/bcoin/tx.js
@ -26,14 +26,14 @@ function TX(data, block) {
|
|||||||
this.version = data.version || 1;
|
this.version = data.version || 1;
|
||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
this.outputs = [];
|
this.outputs = [];
|
||||||
this.lockTime = data.lockTime || 0;
|
this.locktime = data.locktime || 0;
|
||||||
this.ts = data.ts || 0;
|
this.ts = data.ts || 0;
|
||||||
this.block = data.block || null;
|
this.block = data.block || null;
|
||||||
this._hash = null;
|
this._hash = null;
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
if (data.lock != null)
|
if (data.lock != null)
|
||||||
this.lockTime = data.lock;
|
this.locktime = data.lock;
|
||||||
|
|
||||||
this._raw = data._raw || null;
|
this._raw = data._raw || null;
|
||||||
this._size = data._size || 0;
|
this._size = data._size || 0;
|
||||||
@ -73,19 +73,23 @@ function TX(data, block) {
|
|||||||
|
|
||||||
// ps = Pending Since
|
// ps = Pending Since
|
||||||
this.ps = this.ts === 0 ? utils.now() : 0;
|
this.ps = this.ts === 0 ? utils.now() : 0;
|
||||||
|
|
||||||
// Discourage fee snipping a la bitcoind
|
|
||||||
// if (data.lockTime == null && data.lock == null)
|
|
||||||
// this.avoidFeeSnipping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
TX.prototype.__defineSetter__('lock', function(lockTime) {
|
TX.prototype.__defineSetter__('lock', function(locktime) {
|
||||||
return this.lockTime = lockTime;
|
return this.locktime = locktime;
|
||||||
});
|
});
|
||||||
|
|
||||||
TX.prototype.__defineGetter__('lock', function() {
|
TX.prototype.__defineGetter__('lock', function() {
|
||||||
return this.lockTime;
|
return this.locktime;
|
||||||
|
});
|
||||||
|
|
||||||
|
TX.prototype.__defineSetter__('lockTime', function(locktime) {
|
||||||
|
return this.locktime = locktime;
|
||||||
|
});
|
||||||
|
|
||||||
|
TX.prototype.__defineGetter__('lockTime', function() {
|
||||||
|
return this.locktime;
|
||||||
});
|
});
|
||||||
|
|
||||||
TX.prototype.clone = function clone() {
|
TX.prototype.clone = function clone() {
|
||||||
@ -530,10 +534,9 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
||||||
var input;
|
var input;
|
||||||
|
|
||||||
if (typeof index !== 'number')
|
if (index && typeof index === 'object')
|
||||||
index = this.inputs.indexOf(index);
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
// Get the input
|
|
||||||
input = this.inputs[index];
|
input = this.inputs[index];
|
||||||
assert(input);
|
assert(input);
|
||||||
|
|
||||||
@ -551,6 +554,12 @@ TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
|||||||
TX.prototype.isSigned = function isSigned(index, required) {
|
TX.prototype.isSigned = function isSigned(index, required) {
|
||||||
var i, input, s, len, m, j, total;
|
var i, input, s, len, m, j, total;
|
||||||
|
|
||||||
|
if (index && typeof index === 'object')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
|
if (index != null)
|
||||||
|
assert(this.inputs[index]);
|
||||||
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
input = this.inputs[i];
|
input = this.inputs[i];
|
||||||
|
|
||||||
@ -716,25 +725,19 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
script = bcoin.script.createMultisig(keys, m, n);
|
script = bcoin.script.createMultisig(keys, m, n);
|
||||||
} else if (bcoin.wallet.validateAddress(options.address, 'scripthash')) {
|
} else if (bcoin.address.validate(options.address, 'scripthash')) {
|
||||||
// P2SH Transaction
|
// P2SH Transaction
|
||||||
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
|
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
|
||||||
// hash160 [20-byte-redeemscript-hash] equal
|
// hash160 [20-byte-redeemscript-hash] equal
|
||||||
script = [
|
script = bcoin.script.createScripthash(
|
||||||
'hash160',
|
bcoin.wallet.addr2hash(options.address, 'scripthash')
|
||||||
bcoin.wallet.addr2hash(options.address, 'scripthash'),
|
);
|
||||||
'equal'
|
|
||||||
];
|
|
||||||
} else if (options.address) {
|
} else if (options.address) {
|
||||||
// P2PKH Transaction
|
// P2PKH Transaction
|
||||||
// dup hash160 [pubkey-hash] equalverify checksig
|
// dup hash160 [pubkey-hash] equalverify checksig
|
||||||
script = [
|
script = bcoin.script.createPubkeyhash(
|
||||||
'dup',
|
bcoin.wallet.addr2hash(options.address, 'pubkeyhash')
|
||||||
'hash160',
|
);
|
||||||
bcoin.wallet.addr2hash(options.address, 'pubkeyhash'),
|
|
||||||
'equalverify',
|
|
||||||
'checksig'
|
|
||||||
];
|
|
||||||
} else if (options.key) {
|
} else if (options.key) {
|
||||||
// P2PK Transaction
|
// P2PK Transaction
|
||||||
// [pubkey] checksig
|
// [pubkey] checksig
|
||||||
@ -750,36 +753,37 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
flags = utils.ascii2array(flags);
|
flags = utils.ascii2array(flags);
|
||||||
assert(utils.isBuffer(flags));
|
assert(utils.isBuffer(flags));
|
||||||
assert(flags.length <= constants.script.maxOpReturn);
|
assert(flags.length <= constants.script.maxOpReturn);
|
||||||
script = [
|
script = bcoin.script.createNulldata(flags);
|
||||||
'return',
|
|
||||||
flags
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2SH Transaction
|
// P2SH Transaction
|
||||||
// hash160 [hash] eq
|
// hash160 [hash] eq
|
||||||
if (options.scripthash) {
|
if (options.scripthash) {
|
||||||
if (options.lockTime != null) {
|
if (options.locktime != null) {
|
||||||
script = [
|
script = [
|
||||||
bcoin.script.array(options.lockTime),
|
bcoin.script.array(options.locktime),
|
||||||
'checklocktimeverify',
|
'checklocktimeverify',
|
||||||
'drop',
|
'drop',
|
||||||
'codeseparator'
|
'codeseparator'
|
||||||
].concat(script);
|
].concat(script);
|
||||||
}
|
}
|
||||||
hash = utils.ripesha(bcoin.script.encode(script));
|
hash = utils.ripesha(bcoin.script.encode(script));
|
||||||
script = [
|
script = bcoin.script.createScripthash(hash);
|
||||||
'hash160',
|
|
||||||
hash,
|
|
||||||
'equal'
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output.script = script;
|
output.script = script;
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.getSubscript = function getSubscript(index) {
|
TX.prototype.getSubscript = function getSubscript(index) {
|
||||||
var script = this.outputs[index].script;
|
var script;
|
||||||
|
|
||||||
|
if (typeof index !== 'number')
|
||||||
|
index = this.outputs.indexOf(index);
|
||||||
|
|
||||||
|
assert(this.outputs[index]);
|
||||||
|
|
||||||
|
script = this.outputs[index].script;
|
||||||
|
|
||||||
return bcoin.script.getSubscript(script);
|
return bcoin.script.getSubscript(script);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -877,8 +881,10 @@ TX.prototype.tbsHash = function tbsHash(enc, force) {
|
|||||||
return this.hash(enc);
|
return this.hash(enc);
|
||||||
|
|
||||||
if (!this._tbsHash || force) {
|
if (!this._tbsHash || force) {
|
||||||
for (i = 0; i < copy.inputs.length; i++)
|
for (i = 0; i < copy.inputs.length; i++) {
|
||||||
copy.inputs[i].script = [];
|
if (!copy.isCoinbase())
|
||||||
|
copy.inputs[i].script = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._tbsHash = utils.dsha256(copy.render(true));
|
this._tbsHash = utils.dsha256(copy.render(true));
|
||||||
}
|
}
|
||||||
@ -896,10 +902,16 @@ TX.prototype.verify = function verify(index, force, flags) {
|
|||||||
if (this.inputs.length === 0)
|
if (this.inputs.length === 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (index && typeof index === 'object')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
|
if (index != null)
|
||||||
|
assert(this.inputs[index]);
|
||||||
|
|
||||||
return this.inputs.every(function(input, i) {
|
return this.inputs.every(function(input, i) {
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
if (index != null && index !== i)
|
if (index != null && i !== index)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!input.prevout.tx)
|
if (!input.prevout.tx)
|
||||||
@ -1248,24 +1260,24 @@ TX.prototype.funds = TX.prototype.getFunds;
|
|||||||
|
|
||||||
TX.prototype.getTargetTime = function getTargetTime() {
|
TX.prototype.getTargetTime = function getTargetTime() {
|
||||||
var bestValue = 0;
|
var bestValue = 0;
|
||||||
var i, lockTime, bestType;
|
var i, locktime, bestType;
|
||||||
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
lockTime = this.inputs[i].getLocktime();
|
locktime = this.inputs[i].getLocktime();
|
||||||
|
|
||||||
if (!lockTime)
|
if (!locktime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Incompatible types
|
// Incompatible types
|
||||||
if (bestType && bestType !== lockTime.type)
|
if (bestType && bestType !== locktime.type)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bestType = lockTime.type;
|
bestType = locktime.type;
|
||||||
|
|
||||||
if (lockTime.value < bestValue)
|
if (locktime.value < bestValue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bestValue = lockTime.value;
|
bestValue = locktime.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1288,6 +1300,12 @@ TX.prototype.testInputs = function testInputs(addressTable, index, collect) {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index && typeof index === 'object')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
|
if (index != null)
|
||||||
|
assert(this.inputs[index]);
|
||||||
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
if (index != null && i !== index)
|
if (index != null && i !== index)
|
||||||
continue;
|
continue;
|
||||||
@ -1311,8 +1329,8 @@ TX.prototype.testInputs = function testInputs(addressTable, index, collect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.scriptaddress) {
|
if (data.scriptAddress) {
|
||||||
if (addressTable[data.scriptaddress] != null) {
|
if (addressTable[data.scriptAddress] != null) {
|
||||||
if (!collect)
|
if (!collect)
|
||||||
return true;
|
return true;
|
||||||
inputs.push(input);
|
inputs.push(input);
|
||||||
@ -1343,6 +1361,12 @@ TX.prototype.testOutputs = function testOutputs(addressTable, index, collect) {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index && typeof index === 'object')
|
||||||
|
index = this.outputs.indexOf(index);
|
||||||
|
|
||||||
|
if (index != null)
|
||||||
|
assert(this.outputs[index]);
|
||||||
|
|
||||||
for (i = 0; i < this.outputs.length; i++) {
|
for (i = 0; i < this.outputs.length; i++) {
|
||||||
if (index != null && i !== index)
|
if (index != null && i !== index)
|
||||||
continue;
|
continue;
|
||||||
@ -1361,8 +1385,8 @@ TX.prototype.testOutputs = function testOutputs(addressTable, index, collect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.scriptaddress) {
|
if (data.scriptAddress) {
|
||||||
if (addressTable[data.scriptaddress] != null) {
|
if (addressTable[data.scriptAddress] != null) {
|
||||||
if (!collect)
|
if (!collect)
|
||||||
return true;
|
return true;
|
||||||
outputs.push(output);
|
outputs.push(output);
|
||||||
@ -1383,16 +1407,16 @@ TX.prototype.avoidFeeSnipping = function avoidFeeSnipping() {
|
|||||||
if (!this.chain)
|
if (!this.chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.lockTime = this.chain.height();
|
this.locktime = this.chain.height();
|
||||||
|
|
||||||
if ((Math.random() * 10 | 0) === 0)
|
if ((Math.random() * 10 | 0) === 0)
|
||||||
this.lockTime = Math.max(0, this.lockTime - (Math.random() * 100 | 0));
|
this.locktime = Math.max(0, this.locktime - (Math.random() * 100 | 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.setLockTime = function setLockTime(lockTime) {
|
TX.prototype.setLocktime = function setLocktime(locktime) {
|
||||||
var i, input;
|
var i, input;
|
||||||
|
|
||||||
this.lockTime = lockTime;
|
this.locktime = locktime;
|
||||||
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
input = this.inputs[i];
|
input = this.inputs[i];
|
||||||
@ -1489,10 +1513,10 @@ TX.prototype.isFinal = function isFinal(height, ts) {
|
|||||||
if (!this.chain)
|
if (!this.chain)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (this.lockTime === 0)
|
if (this.locktime === 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (this.lockTime < (this.lockTime < threshold ? height : ts))
|
if (this.locktime < (this.locktime < threshold ? height : ts))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
@ -1503,11 +1527,11 @@ TX.prototype.isFinal = function isFinal(height, ts) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.getSigops = function getSigops(scripthash, accurate) {
|
TX.prototype.getSigops = function getSigops(scriptHash, accurate) {
|
||||||
var n = 0;
|
var n = 0;
|
||||||
this.inputs.forEach(function(input) {
|
this.inputs.forEach(function(input) {
|
||||||
n += bcoin.script.getSigops(input.script, accurate);
|
n += bcoin.script.getSigops(input.script, accurate);
|
||||||
if (scripthash && !this.isCoinbase())
|
if (scriptHash && !this.isCoinbase())
|
||||||
n += bcoin.script.getScripthashSigops(input.script);
|
n += bcoin.script.getScripthashSigops(input.script);
|
||||||
}, this);
|
}, this);
|
||||||
this.outputs.forEach(function(output) {
|
this.outputs.forEach(function(output) {
|
||||||
|
|||||||
@ -133,7 +133,7 @@ Wallet.prototype._init = function init() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.__defineGetter__('address', function() {
|
Wallet.prototype.__defineGetter__('primary', function() {
|
||||||
return this.addresses[0];
|
return this.addresses[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ Wallet.prototype.addAddress = function addAddress(address) {
|
|||||||
|
|
||||||
index = this.addresses.push(address) - 1;
|
index = this.addresses.push(address) - 1;
|
||||||
|
|
||||||
address.on('scriptaddress', address._onUpdate = function(old, cur) {
|
address.on('update script', address._onUpdate = function(old, cur) {
|
||||||
self._addressTable[cur] = self._addressTable[old];
|
self._addressTable[cur] = self._addressTable[old];
|
||||||
delete self._addressTable[old];
|
delete self._addressTable[old];
|
||||||
self.emit('add address', address);
|
self.emit('add address', address);
|
||||||
@ -267,7 +267,7 @@ Wallet.prototype.removeAddress = function removeAddress(address) {
|
|||||||
|
|
||||||
this.addresses.splice(i, 1);
|
this.addresses.splice(i, 1);
|
||||||
|
|
||||||
address.removeListener('scriptaddress', address._onUpdate);
|
address.removeListener('update script', address._onUpdate);
|
||||||
|
|
||||||
this._addressTable = this._getAddressTable();
|
this._addressTable = this._getAddressTable();
|
||||||
|
|
||||||
@ -283,47 +283,51 @@ Wallet.prototype.removeAddress = function removeAddress(address) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.addKey = function addKey(key, i) {
|
Wallet.prototype.addKey = function addKey(key, i) {
|
||||||
return this.address.addKey(key);
|
return this.primary.addKey(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.removeKey = function removeKey(key) {
|
Wallet.prototype.removeKey = function removeKey(key) {
|
||||||
return this.address.removeKey(key);
|
return this.primary.removeKey(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
|
Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
|
||||||
return this.address.getPrivateKey(enc);
|
return this.primary.getPrivateKey(enc);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getScript = function getScript() {
|
Wallet.prototype.getScript = function getScript() {
|
||||||
return this.address.getScript();
|
return this.primary.getScript();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getScriptHash = function getScriptHash() {
|
Wallet.prototype.getScriptHash =
|
||||||
return this.address.getScriptHash();
|
Wallet.prototype.getScripthash = function getScripthash() {
|
||||||
|
return this.primary.getScriptHash();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getScriptAddress = function getScriptAddress() {
|
Wallet.prototype.getScriptAddress =
|
||||||
return this.address.getScriptAddress();
|
Wallet.prototype.getScriptaddress = function getScriptaddress() {
|
||||||
|
return this.primary.getScriptAddress();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getPublicKey = function getPublicKey(enc) {
|
Wallet.prototype.getPublicKey = function getPublicKey(enc) {
|
||||||
return this.address.getPublicKey(enc);
|
return this.primary.getPublicKey(enc);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getKeyHash = function getKeyHash() {
|
Wallet.prototype.getKeyHash =
|
||||||
return this.address.getKeyHash();
|
Wallet.prototype.getKeyhash = function getKeyhash() {
|
||||||
|
return this.primary.getKeyHash();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getKeyAddress = function getKeyAddress() {
|
Wallet.prototype.getKeyAddress =
|
||||||
return this.address.getKeyAddress();
|
Wallet.prototype.getKeyaddress = function getKeyaddress() {
|
||||||
|
return this.primary.getKeyAddress();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getHash = function getHash() {
|
Wallet.prototype.getHash = function getHash() {
|
||||||
return this.address.getHash();
|
return this.primary.getHash();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getAddress = function getAddress() {
|
Wallet.prototype.getAddress = function getAddress() {
|
||||||
return this.address.getAddress();
|
return this.primary.getAddress();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.ownInput = function ownInput(tx, index) {
|
Wallet.prototype.ownInput = function ownInput(tx, index) {
|
||||||
@ -347,12 +351,12 @@ Wallet.prototype.fill = function fill(tx, address, fee) {
|
|||||||
items = unspent.filter(function(item) {
|
items = unspent.filter(function(item) {
|
||||||
var output = item.tx.outputs[item.index];
|
var output = item.tx.outputs[item.index];
|
||||||
if (bcoin.script.isScripthash(output.script)) {
|
if (bcoin.script.isScripthash(output.script)) {
|
||||||
if (this.address.type === 'scripthash')
|
if (this.primary.type === 'scripthash')
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (bcoin.script.isMultisig(output.script)) {
|
if (bcoin.script.isMultisig(output.script)) {
|
||||||
if (this.address.n > 1)
|
if (this.primary.n > 1)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -405,7 +409,7 @@ Wallet.prototype.createTX = function createTX(outputs, fee) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (target.value > 0)
|
if (target.value > 0)
|
||||||
tx.setLockTime(target.value);
|
tx.setLocktime(target.value);
|
||||||
else
|
else
|
||||||
tx.avoidFeeSnipping();
|
tx.avoidFeeSnipping();
|
||||||
|
|
||||||
@ -415,83 +419,23 @@ Wallet.prototype.createTX = function createTX(outputs, fee) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.scriptInputs = function scriptInputs(tx) {
|
Wallet.prototype.scriptInputs = function scriptInputs(tx) {
|
||||||
var self = this;
|
this.fillPrevout(tx);
|
||||||
|
|
||||||
return this.addresses.reduce(function(total, address) {
|
return this.addresses.reduce(function(total, address) {
|
||||||
var pub = address.getPublicKey();
|
return total + address.signInputs(tx);
|
||||||
var redeem = address.getScript();
|
|
||||||
|
|
||||||
tx.inputs.forEach(function(input, i) {
|
|
||||||
if (!input.prevout.tx && self.tx._all[input.prevout.hash])
|
|
||||||
input.prevout.tx = self.tx._all[input.prevout.hash];
|
|
||||||
|
|
||||||
if (!input.prevout.tx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!address.ownOutput(input.prevout.tx, input.prevout.index))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tx.scriptInput(i, pub, redeem))
|
|
||||||
total++;
|
|
||||||
});
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.signInputs = function signInputs(tx, type) {
|
Wallet.prototype.signInputs = function signInputs(tx, type) {
|
||||||
var self = this;
|
this.fillPrevout(tx);
|
||||||
|
|
||||||
return this.addresses.reduce(function(total, address) {
|
return this.addresses.reduce(function(total, address) {
|
||||||
if (!address.key.priv)
|
return total + address.signInputs(tx, type);
|
||||||
return total;
|
|
||||||
|
|
||||||
tx.inputs.forEach(function(input, i) {
|
|
||||||
if (!input.prevout.tx && self.tx._all[input.prevout.hash])
|
|
||||||
input.prevout.tx = self.tx._all[input.prevout.hash];
|
|
||||||
|
|
||||||
if (!input.prevout.tx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!address.ownOutput(input.prevout.tx, input.prevout.index))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tx.signInput(i, address.key, type))
|
|
||||||
total++;
|
|
||||||
});
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.sign = function sign(tx, type) {
|
Wallet.prototype.sign = function sign(tx, type) {
|
||||||
var self = this;
|
this.fillPrevout(tx);
|
||||||
|
|
||||||
return this.addresses.reduce(function(total, address) {
|
return this.addresses.reduce(function(total, address) {
|
||||||
var pub = address.getPublicKey();
|
return total + address.sign(tx, type);
|
||||||
var redeem = address.getScript();
|
|
||||||
var key = address.key;
|
|
||||||
|
|
||||||
if (!key.priv)
|
|
||||||
return total;
|
|
||||||
|
|
||||||
// Add signature script to each input
|
|
||||||
tx.inputs.forEach(function(input, i) {
|
|
||||||
if (!input.prevout.tx && self.tx._all[input.prevout.hash])
|
|
||||||
input.prevout.tx = self.tx._all[input.prevout.hash];
|
|
||||||
|
|
||||||
// Filter inputs that this wallet own
|
|
||||||
if (!input.prevout.tx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!address.ownOutput(input.prevout.tx, input.prevout.index))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tx.scriptSig(i, key, pub, redeem, type))
|
|
||||||
total++;
|
|
||||||
});
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -552,6 +496,42 @@ Wallet.prototype.toAddress = function toAddress() {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('script', function() {
|
||||||
|
return this.getScript();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('scriptHash', function() {
|
||||||
|
return this.getScriptHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('scriptAddress', function() {
|
||||||
|
return this.getScriptAddress();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('privateKey', function() {
|
||||||
|
return this.getPrivateKey();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('publicKey', function() {
|
||||||
|
return this.getPublicKey();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('keyHash', function() {
|
||||||
|
return this.getKeyHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('keyAddress', function() {
|
||||||
|
return this.getKeyAddress();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('hash', function() {
|
||||||
|
return this.getHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
Wallet.prototype.__defineGetter__('address', function() {
|
||||||
|
return this.getAddress();
|
||||||
|
});
|
||||||
|
|
||||||
Wallet.prototype.toJSON = function toJSON(encrypt) {
|
Wallet.prototype.toJSON = function toJSON(encrypt) {
|
||||||
return {
|
return {
|
||||||
v: 3,
|
v: 3,
|
||||||
|
|||||||
@ -286,6 +286,7 @@ describe('Wallet', function() {
|
|||||||
n: 3
|
n: 3
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
w3 = bcoin.wallet.fromJSON(w3.toJSON());
|
||||||
|
|
||||||
var receive = bcoin.wallet();
|
var receive = bcoin.wallet();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user