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