script and standard transaction types. prefixes.

This commit is contained in:
Christopher Jeffrey 2015-12-17 14:48:59 -08:00
parent 07a6788831
commit 3e608c2cc6
6 changed files with 94 additions and 42 deletions

View File

@ -545,7 +545,7 @@ Pool.prototype.removeWallet = function removeWallet(w) {
}; };
Pool.prototype.watchWallet = function watchWallet(w) { Pool.prototype.watchWallet = function watchWallet(w) {
if (w.type === 'script') { if (w.type === 'scripthash') {
// For the redeem script hash in outputs: // For the redeem script hash in outputs:
this.watch(w.getFullHash()); this.watch(w.getFullHash());
// For the redeem script in inputs: // For the redeem script in inputs:
@ -558,7 +558,7 @@ Pool.prototype.watchWallet = function watchWallet(w) {
}; };
Pool.prototype.unwatchWallet = function unwatchWallet(w) { Pool.prototype.unwatchWallet = function unwatchWallet(w) {
if (w.type === 'script') { if (w.type === 'scripthash') {
// For the redeem script hash in p2sh outputs: // For the redeem script hash in p2sh outputs:
this.unwatch(w.getFullHash()); this.unwatch(w.getFullHash());
// For the redeem script in p2sh inputs: // For the redeem script in p2sh inputs:

View File

@ -20,7 +20,9 @@ var main = network.main = {};
main.prefixes = { main.prefixes = {
pubkey: 0, pubkey: 0,
script: 5, pubkeyhash: 0,
multisig: 0,
scripthash: 5,
privkey: 128, privkey: 128,
xpubkey: 0x0488b21e, xpubkey: 0x0488b21e,
xprivkey: 0x0488ade4 xprivkey: 0x0488ade4
@ -107,7 +109,9 @@ testnet.type = 'testnet';
testnet.prefixes = { testnet.prefixes = {
pubkey: 111, pubkey: 111,
script: 196, pubkeyhash: 111,
multisig: 111,
scripthash: 196,
privkey: 239, privkey: 239,
xpubkey: 0x043587cf, xpubkey: 0x043587cf,
xprivkey: 0x04358394 xprivkey: 0x04358394

View File

@ -783,7 +783,27 @@ script.multisig = function(keys, m, n) {
); );
}; };
script.standard = function standard(s) {
return (script.isPubkey(s) && 'pubkey')
|| (script.isPubkeyhash(s) && 'pubkeyhash')
|| (script.isMultisig(s) && 'multisig')
|| (script.isScripthash(s) && 'scripthash')
|| (script.isNullData(s) && 'colored')
|| 'nonstandard';
};
script.lockTime = function lockTime(s) {
return s.length > 3
&& Array.isArray(s[0])
&& s[1] === 'checklocktimeverify'
&& s[2] === 'drop'
&& new bn(s[0]);
};
script.isPubkeyhash = function isPubkeyhash(s, hash) { script.isPubkeyhash = function isPubkeyhash(s, hash) {
if (script.lockTime(s))
s = s.slice(3);
if (s.length !== 5) if (s.length !== 5)
return false; return false;
@ -801,7 +821,10 @@ script.isPubkeyhash = function isPubkeyhash(s, hash) {
return s[2]; return s[2];
}; };
script.isSimplePubkeyhash = function isSimplePubkeyhash(s, hash) { script.isPubkey = function isPubkey(s, hash) {
if (script.lockTime(s))
s = s.slice(3);
if (s.length !== 2) if (s.length !== 2)
return false; return false;
@ -816,6 +839,9 @@ script.isSimplePubkeyhash = function isSimplePubkeyhash(s, hash) {
}; };
script.isMultisig = function isMultisig(s, key) { script.isMultisig = function isMultisig(s, key) {
if (script.lockTime(s))
s = s.slice(3);
if (s.length < 4) if (s.length < 4)
return false; return false;
@ -863,6 +889,9 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s) {
}; };
script.isScripthash = function isScripthash(s, hash) { script.isScripthash = function isScripthash(s, hash) {
if (script.lockTime(s))
s = s.slice(3);
if (s.length !== 3) if (s.length !== 3)
return false; return false;

View File

@ -156,8 +156,15 @@ TX.prototype.scriptInput = function(input, pub) {
if (input.script.length) if (input.script.length)
return; return;
// P2PKH and simple tx // P2PK
if (bcoin.script.isPubkeyhash(s) || bcoin.script.isSimplePubkeyhash(s)) { if (bcoin.script.isPubkey(s)) {
input.script = [ [] ];
this._recalculateFee();
return;
}
// P2PKH
if (bcoin.script.isPubkeyhash(s)) {
input.script = [ [], pub ]; input.script = [ [], pub ];
this._recalculateFee(); this._recalculateFee();
return; return;
@ -220,8 +227,14 @@ TX.prototype.signInput = function(input, key, type) {
// Add the sighash as a single byte to the signature // Add the sighash as a single byte to the signature
signature = signature.concat(type); signature = signature.concat(type);
// P2PKH and simple tx // P2PK
if (bcoin.script.isPubkeyhash(s) || bcoin.script.isSimplePubkeyhash(s)) { if (bcoin.script.isPubkey(s)) {
input.script[0] = signature;
return;
}
// P2PKH
if (bcoin.script.isPubkeyhash(s)) {
input.script[0] = signature; input.script[0] = signature;
return; return;
} }
@ -345,7 +358,7 @@ TX.prototype.scriptOutput = function(output, options) {
if (keys === options.address) { if (keys === options.address) {
keys = keys.map(function(address) { keys = keys.map(function(address) {
return bcoin.wallet.addr2hash(address, 'pubkey'); return bcoin.wallet.addr2hash(address, 'pubkeyhash');
}); });
} }
@ -367,13 +380,13 @@ TX.prototype.scriptOutput = function(output, options) {
assert(n >= 1 && n <= 3); assert(n >= 1 && n <= 3);
script = bcoin.script.multisig(keys, m, n); script = bcoin.script.multisig(keys, m, n);
} else if (bcoin.wallet.validateAddress(options.address, 'script')) { } else if (bcoin.wallet.validateAddress(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 = [
'hash160', 'hash160',
bcoin.wallet.addr2hash(options.address, 'script'), bcoin.wallet.addr2hash(options.address, 'scripthash'),
'eq' 'eq'
]; ];
} else if (options.address) { } else if (options.address) {
@ -382,7 +395,7 @@ TX.prototype.scriptOutput = function(output, options) {
script = [ script = [
'dup', 'dup',
'hash160', 'hash160',
bcoin.wallet.addr2hash(options.address, 'pubkey'), bcoin.wallet.addr2hash(options.address, 'pubkeyhash'),
'eqverify', 'eqverify',
'checksig' 'checksig'
]; ];
@ -543,7 +556,13 @@ TX.prototype.maxSize = function maxSize() {
// Get the previous output's subscript // Get the previous output's subscript
var s = input.out.tx.getSubscript(input.out.index); var s = input.out.tx.getSubscript(input.out.index);
if (bcoin.script.isPubkeyhash(s) || bcoin.script.isSimplePubkeyhash(s)) { if (bcoin.script.isPubkey(s)) {
// Signature + len
size += 74;
return;
}
if (bcoin.script.isPubkeyhash(s)) {
// Signature + len // Signature + len
size += 74; size += 74;
// Pub key + len // Pub key + len
@ -760,7 +779,7 @@ TX.prototype.inputAddrs = function inputAddrs() {
}).map(function(input) { }).map(function(input) {
var pub = input.script[1]; var pub = input.script[1];
var hash = utils.ripesha(pub); var hash = utils.ripesha(pub);
return bcoin.wallet.hash2addr(hash, 'pubkey'); return bcoin.wallet.hash2addr(hash, 'pubkeyhash');
}); });
}; };
@ -790,7 +809,7 @@ TX.getInputKey = function(input) {
if (bcoin.script.isScripthash(script)) { if (bcoin.script.isScripthash(script)) {
var pub = script[script.length - 1]; var pub = script[script.length - 1];
var hash = utils.ripesha(pub); var hash = utils.ripesha(pub);
var addr = bcoin.wallet.hash2addr(hash, 'script'); var addr = bcoin.wallet.hash2addr(hash, 'scripthash');
var redeem = bcoin.script.decode(pub); var redeem = bcoin.script.decode(pub);
var keys = TX.getOutputKey({ script: redeem }); var keys = TX.getOutputKey({ script: redeem });
keys.pub = pub; keys.pub = pub;
@ -814,18 +833,7 @@ TX.getOutputKey = function(output) {
var script = output.script; var script = output.script;
if (bcoin.script.isPubkeyhash(script)) { if (bcoin.script.isPubkey(script)) {
var hash = script[2];
var addr = bcoin.wallet.hash2addr(hash);
return {
sig: null,
pub: null,
hash: hash,
addr: addr
};
}
if (bcoin.script.isSimplePubkeyhash(script)) {
var pubKey = script[0]; var pubKey = script[0];
var hash = utils.ripesha(pubKey); var hash = utils.ripesha(pubKey);
var addr = bcoin.wallet.hash2addr(hash); var addr = bcoin.wallet.hash2addr(hash);
@ -837,6 +845,17 @@ TX.getOutputKey = function(output) {
}; };
} }
if (bcoin.script.isPubkeyhash(script)) {
var hash = script[2];
var addr = bcoin.wallet.hash2addr(hash);
return {
sig: null,
pub: null,
hash: hash,
addr: addr
};
}
var pubKeys = bcoin.script.isMultisig(script); var pubKeys = bcoin.script.isMultisig(script);
if (pubKeys) { if (pubKeys) {
var keys = pubKeys.map(function(pubKey) { var keys = pubKeys.map(function(pubKey) {
@ -859,7 +878,7 @@ TX.getOutputKey = function(output) {
if (bcoin.script.isScripthash(script, scriptHash)) { if (bcoin.script.isScripthash(script, scriptHash)) {
var hash = utils.toHex(s[1]); var hash = utils.toHex(s[1]);
var addr = bcoin.wallet.hash2addr(hash, 'script'); var addr = bcoin.wallet.hash2addr(hash, 'scripthash');
return { return {
sig: null, sig: null,
pub: null, pub: null,

View File

@ -66,7 +66,7 @@ function Wallet(options, passphrase) {
this.key = bcoin.ecdsa.genKeyPair(); this.key = bcoin.ecdsa.genKeyPair();
} }
this.type = 'pubkey'; this.type = 'pubkeyhash';
this.keys = []; this.keys = [];
this.m = 1; this.m = 1;
this.n = 1; this.n = 1;
@ -123,12 +123,12 @@ Wallet.prototype.multisig = function multisig(options) {
options.type = options.type || options.prefix; options.type = options.type || options.prefix;
options.keys = options.keys || options.pubkeys || []; options.keys = options.keys || options.pubkeys || [];
this.type = options.type || 'pubkey'; this.type = options.type || 'pubkeyhash';
// this.keys = (options.keys || []).map(utils.toKeyArray); // this.keys = (options.keys || []).map(utils.toKeyArray);
this.keys = []; this.keys = [];
this.m = options.m || 1; this.m = options.m || 1;
this.n = options.n || 1; this.n = options.n || 1;
this.nmax = this.type === 'script' this.nmax = this.type === 'scripthash'
? (this.compressed ? 15 : 7) ? (this.compressed ? 15 : 7)
: 3; : 3;
@ -143,7 +143,7 @@ Wallet.prototype.multisig = function multisig(options) {
// Use p2sh multisig by default // Use p2sh multisig by default
if (!options.type && this.keys.length > 1) if (!options.type && this.keys.length > 1)
this.type = 'script'; this.type = 'scripthash';
if (this.m < 1 || this.m > this.n) if (this.m < 1 || this.m > this.n)
throw new Error('m ranges between 1 and n'); throw new Error('m ranges between 1 and n');
@ -236,7 +236,7 @@ Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
Wallet.prototype.getFullPublicKey = function getFullPublicKey(enc) { Wallet.prototype.getFullPublicKey = function getFullPublicKey(enc) {
var pub = this.getOwnPublicKey(); var pub = this.getOwnPublicKey();
if (this.type === 'script') { if (this.type === 'scripthash') {
var keys = this.getPublicKeys(); var keys = this.getPublicKeys();
pub = bcoin.script.encode(bcoin.script.multisig(keys, this.m, this.n)); pub = bcoin.script.encode(bcoin.script.multisig(keys, this.m, this.n));
} }
@ -308,7 +308,7 @@ Wallet.key2hash = function key2hash(key) {
Wallet.hash2addr = function hash2addr(hash, prefix) { Wallet.hash2addr = function hash2addr(hash, prefix) {
hash = utils.toArray(hash, 'hex'); hash = utils.toArray(hash, 'hex');
prefix = network.prefixes[prefix || 'pubkey']; prefix = network.prefixes[prefix || 'pubkeyhash'];
hash = [ prefix ].concat(hash); hash = [ prefix ].concat(hash);
var addr = hash.concat(utils.checksum(hash)); var addr = hash.concat(utils.checksum(hash));
@ -317,7 +317,7 @@ Wallet.hash2addr = function hash2addr(hash, prefix) {
Wallet.__defineGetter__('prefixes', function() { Wallet.__defineGetter__('prefixes', function() {
if (Wallet._prefixes) return Wallet._prefixes; if (Wallet._prefixes) return Wallet._prefixes;
Wallet._prefixes = ['pubkey', 'script'].reduce(function(out, prefix) { Wallet._prefixes = ['pubkeyhash', 'scripthash'].reduce(function(out, prefix) {
var ch = Wallet.hash2addr(Wallet.key2hash([]), prefix)[0]; var ch = Wallet.hash2addr(Wallet.key2hash([]), prefix)[0];
out[ch] = prefix; out[ch] = prefix;
return out; return out;
@ -332,7 +332,7 @@ Wallet.addr2hash = function addr2hash(addr, prefix) {
if (!Array.isArray(addr)) if (!Array.isArray(addr))
addr = utils.fromBase58(addr); addr = utils.fromBase58(addr);
prefix = network.prefixes[prefix || 'pubkey']; prefix = network.prefixes[prefix || 'pubkeyhash'];
if (addr.length !== 25) if (addr.length !== 25)
return []; return [];
@ -365,10 +365,10 @@ Wallet.prototype.ownOutput = function ownOutput(tx, index) {
var s = output.script; var s = output.script;
if (bcoin.script.isPubkeyhash(s, hash)) if (bcoin.script.isPubkey(s, hash))
return true; return true;
if (bcoin.script.isSimplePubkeyhash(s, hash)) if (bcoin.script.isPubkeyhash(s, hash))
return true; return true;
if (bcoin.script.isMultisig(s, key)) if (bcoin.script.isMultisig(s, key))

View File

@ -280,7 +280,7 @@ describe('Wallet', function() {
var w1 = bcoin.wallet({ var w1 = bcoin.wallet({
key: key1, key: key1,
multisig: { multisig: {
type: 'script', type: 'scripthash',
keys: [pub2, pub3], keys: [pub2, pub3],
m: 2, m: 2,
n: 3 n: 3
@ -289,7 +289,7 @@ describe('Wallet', function() {
var w2 = bcoin.wallet({ var w2 = bcoin.wallet({
key: key2, key: key2,
multisig: { multisig: {
type: 'script', type: 'scripthash',
keys: [pub1, pub3], keys: [pub1, pub3],
m: 2, m: 2,
n: 3 n: 3
@ -298,7 +298,7 @@ describe('Wallet', function() {
var w3 = bcoin.wallet({ var w3 = bcoin.wallet({
key: key3, key: key3,
multisig: { multisig: {
type: 'script', type: 'scripthash',
keys: [pub1, pub2], keys: [pub1, pub2],
m: 2, m: 2,
n: 3 n: 3