new scripting system.

This commit is contained in:
Christopher Jeffrey 2016-03-14 19:45:11 -07:00
parent bf8475afe1
commit b528965912
13 changed files with 205 additions and 274 deletions

View File

@ -77,7 +77,7 @@ bcoin.ec = require('./bcoin/ec');
bcoin.lru = require('./bcoin/lru'); bcoin.lru = require('./bcoin/lru');
bcoin.protocol = require('./bcoin/protocol'); bcoin.protocol = require('./bcoin/protocol');
bcoin.bloom = require('./bcoin/bloom'); bcoin.bloom = require('./bcoin/bloom');
bcoin.script = require('./bcoin/script'); bcoin.script = require('./bcoin/script2');
bcoin.input = require('./bcoin/input'); bcoin.input = require('./bcoin/input');
bcoin.output = require('./bcoin/output'); bcoin.output = require('./bcoin/output');
bcoin.coin = require('./bcoin/coin'); bcoin.coin = require('./bcoin/coin');

View File

@ -111,13 +111,12 @@ Address.prototype.getScript = function getScript() {
assert(this.keys.length === this.n, 'Not all keys have been added.'); assert(this.keys.length === this.n, 'Not all keys have been added.');
redeem = bcoin.script.createMultisig(this.keys, this.m, this.n); redeem = bcoin.script.createMultisig(this.keys, this.m, this.n);
redeem = bcoin.script.encode(redeem);
if (this.witness) { if (this.witness) {
if (redeem.length > 10000) if (redeem.getSize() > 10000)
throw new Error('Redeem script too large (10000 byte limit).'); throw new Error('Redeem script too large (10000 byte limit).');
} else { } else {
if (redeem.length > 520) if (redeem.getSize() > 520)
throw new Error('Redeem script too large (520 byte limit).'); throw new Error('Redeem script too large (520 byte limit).');
} }
@ -140,12 +139,12 @@ Address.prototype.getProgram = function getProgram() {
0, Address.hash160(this.getPublicKey())); 0, Address.hash160(this.getPublicKey()));
} else if (this.type === 'multisig') { } else if (this.type === 'multisig') {
program = bcoin.script.createWitnessProgram( program = bcoin.script.createWitnessProgram(
0, Address.sha256(this.getScript())); 0, Address.sha256(this.getScript().encode()));
} }
assert(program); assert(program);
this._program = bcoin.script.encode(program); this._program = program;
return this._program; return this._program;
}; };
@ -157,7 +156,7 @@ Address.prototype.getProgramHash = function getProgramHash() {
if (this._programHash) if (this._programHash)
return this._programHash; return this._programHash;
this._programHash = Address.hash160(this.getProgram()); this._programHash = Address.hash160(this.getProgram().encode());
return this._programHash; return this._programHash;
}; };
@ -186,7 +185,7 @@ Address.prototype.getScriptHash160 = function getScriptHash256() {
if (this._scriptHash160) if (this._scriptHash160)
return this._scriptHash160; return this._scriptHash160;
this._scriptHash160 = Address.hash160(this.getScript()); this._scriptHash160 = Address.hash160(this.getScript().encode());
return this._scriptHash160; return this._scriptHash160;
}; };
@ -198,7 +197,7 @@ Address.prototype.getScriptHash256 = function getScriptHash256() {
if (this._scriptHash256) if (this._scriptHash256)
return this._scriptHash256; return this._scriptHash256;
this._scriptHash256 = Address.sha256(this.getScript()); this._scriptHash256 = Address.sha256(this.getScript().encode());
return this._scriptHash256; return this._scriptHash256;
}; };

View File

@ -215,7 +215,7 @@ Block.prototype._verify = function _verify() {
}; };
Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() { Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
var coinbase, s, height; var coinbase, code, height;
if (this.version < 2) if (this.version < 2)
return -1; return -1;
@ -228,10 +228,10 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
if (!coinbase || coinbase.inputs.length === 0) if (!coinbase || coinbase.inputs.length === 0)
return -1; return -1;
s = coinbase.inputs[0].script; code = coinbase.inputs[0].script.code;
if (Buffer.isBuffer(s[0]) && s[0].length <= 6) if (Buffer.isBuffer(code[0]) && code[0].length <= 6)
height = new bn(s[0], 'le').toNumber(); height = new bn(code[0], 'le').toNumber();
else else
height = -1; height = -1;

View File

@ -60,7 +60,7 @@ function Coin(tx, index) {
assert(typeof this.version === 'number'); assert(typeof this.version === 'number');
assert(utils.isFinite(this.height)); assert(utils.isFinite(this.height));
assert(this.value instanceof bn); assert(this.value instanceof bn);
assert(Array.isArray(this.script)); assert(this.script instanceof bcoin.script);
assert(typeof this.hash === 'string'); assert(typeof this.hash === 'string');
assert(utils.isFinite(this.index)); assert(utils.isFinite(this.index));
assert(typeof this.spent === 'boolean'); assert(typeof this.spent === 'boolean');
@ -73,7 +73,7 @@ Coin.prototype.__defineGetter__('chain', function() {
}); });
Coin.prototype.getSize = function getSize() { Coin.prototype.getSize = function getSize() {
return 4 + 4 + 8 + bcoin.script.getSize(this.script) + 32 + 4 + 1; return 4 + 4 + 8 + this.script.getSize() + 32 + 4 + 1;
}; };
Coin.prototype.getConfirmations = function getConfirmations(height) { Coin.prototype.getConfirmations = function getConfirmations(height) {
@ -136,7 +136,7 @@ Coin.prototype.toJSON = function toJSON() {
version: this.version, version: this.version,
height: this.height, height: this.height,
value: utils.btc(this.value), value: utils.btc(this.value),
script: utils.toHex(bcoin.script.encode(this.script)), script: utils.toHex(this.script.encode()),
hash: utils.revHex(this.hash), hash: utils.revHex(this.hash),
index: this.index, index: this.index,
spent: this.spent spent: this.spent
@ -148,7 +148,7 @@ Coin._fromJSON = function _fromJSON(json) {
version: json.version, version: json.version,
height: json.height, height: json.height,
value: utils.satoshi(json.value), value: utils.satoshi(json.value),
script: bcoin.script.decode(new Buffer(json.script, 'hex')), script: new bcoin.script(new Buffer(json.script, 'hex')),
hash: utils.revHex(json.hash), hash: utils.revHex(json.hash),
index: json.index, index: json.index,
spent: json.spent spent: json.spent

View File

@ -9,6 +9,7 @@ var bcoin = require('../bcoin');
var utils = bcoin.utils; var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
var constants = bcoin.protocol.constants; var constants = bcoin.protocol.constants;
var Script = bcoin.script;
/** /**
* Input * Input
@ -21,7 +22,7 @@ function Input(options, tx) {
assert(typeof options.script !== 'string'); assert(typeof options.script !== 'string');
this.prevout = options.prevout; this.prevout = options.prevout;
this.script = options.script || []; this.script = options.script || new Script([]);
this.sequence = options.sequence == null ? 0xffffffff : options.sequence; this.sequence = options.sequence == null ? 0xffffffff : options.sequence;
this.witness = options.witness || []; this.witness = options.witness || [];
this._size = options._size || 0; this._size = options._size || 0;
@ -61,7 +62,7 @@ Input.prototype.getType = function getType() {
type = bcoin.script.getInputType(this.witness, null, true); type = bcoin.script.getInputType(this.witness, null, true);
if (!type || type === 'unknown') if (!type || type === 'unknown')
type = bcoin.script.getInputType(this.script); type = this.script.getInputType();
if (!this._mutable) if (!this._mutable)
this._type = type; this._type = type;
@ -81,8 +82,10 @@ Input.prototype.getRedeem = function getRedeem() {
return bcoin.script.getRedeem(this.witness); return bcoin.script.getRedeem(this.witness);
if (type === 'scripthash') { if (type === 'scripthash') {
redeem = bcoin.script.getRedeem(this.script); redeem = this.script.getRedeem();
if (bcoin.script.isWitnessScripthash(redeem)) if (!redeem)
return;
if (redeem.isWitnessScripthash())
return bcoin.script.getRedeem(this.witness); return bcoin.script.getRedeem(this.witness);
return redeem; return redeem;
} }
@ -99,7 +102,7 @@ Input.prototype.getSubtype = function getSubtype() {
if (!redeem) if (!redeem)
return; return;
return bcoin.script.getOutputType(redeem); return redeem.getType();
}; };
Input.prototype.getAddress = function getAddress() { Input.prototype.getAddress = function getAddress() {
@ -118,7 +121,7 @@ Input.prototype.getAddress = function getAddress() {
address = bcoin.script.getInputAddress(this.witness, null, true); address = bcoin.script.getInputAddress(this.witness, null, true);
if (!address) if (!address)
address = bcoin.script.getInputAddress(this.script); address = this.script.getInputAddress();
if (!this._mutable) if (!this._mutable)
this._address = address; this._address = address;
@ -142,13 +145,13 @@ Input.prototype.getLocktime = function getLocktime() {
output = this.output; output = this.output;
redeem = output.script; redeem = output.script;
if (bcoin.script.isScripthash(redeem)) if (redeem.isScripthash())
redeem = bcoin.script.getRedeem(this.script); redeem = this.script.getRedeem();
if (redeem[1] !== 'checklocktimeverify') if (redeem[1] !== 'checklocktimeverify')
return; return;
return bcoin.script.getLocktime(redeem); return redeem.getLocktime();
}; };
Input.prototype.isCoinbase = function isCoinbase() { Input.prototype.isCoinbase = function isCoinbase() {
@ -177,51 +180,12 @@ Input.prototype.test = function test(addressTable) {
return false; return false;
}; };
Input.prototype.getSigops = function getSigops(scriptHash, accurate) {
var n = bcoin.script.getSigops(this.script, accurate);
if (scriptHash && !this.isCoinbase())
n += bcoin.script.getScripthashSigops(this.script);
return n;
};
Input.prototype.getID = function getID() { Input.prototype.getID = function getID() {
var data = bcoin.script.encode(this.script); var data = this.script.encode();
var hash = utils.toHex(utils.ripesha(data)); var hash = utils.toHex(utils.ripesha(data));
return '[' + this.type + ':' + hash.slice(0, 7) + ']'; return '[' + this.type + ':' + hash.slice(0, 7) + ']';
}; };
Input.prototype.getData = function getData() {
var def, data;
assert(this instanceof Input);
def = {
side: 'input',
value: new bn(0),
script: this.script,
sequence: this.sequence
};
def.prev = this.prevout.hash;
def.index = this.prevout.index;
if (this.isCoinbase()) {
data = bcoin.script.getCoinbaseData(this.script);
return utils.merge(def, data, {
type: 'coinbase',
none: true
});
}
if (this.output) {
data = bcoin.script.getInputData(this.script, this.output.script);
data.value = this.output.value;
return utils.merge(def, data);
}
return utils.merge(def, bcoin.script.getInputData(this.script));
};
Input.prototype.inspect = function inspect() { Input.prototype.inspect = function inspect() {
var redeem = this.getRedeem(); var redeem = this.getRedeem();
var output; var output;
@ -262,7 +226,7 @@ Input.prototype.toJSON = function toJSON() {
index: this.prevout.index index: this.prevout.index
}, },
output: this.output ? this.output.toJSON() : null, output: this.output ? this.output.toJSON() : null,
script: utils.toHex(bcoin.script.encode(this.script)), script: utils.toHex(this.script.encode()),
witness: utils.toHex(bcoin.protocol.framer.witness(this.witness)), witness: utils.toHex(bcoin.protocol.framer.witness(this.witness)),
sequence: this.sequence sequence: this.sequence
}; };
@ -275,7 +239,7 @@ Input._fromJSON = function _fromJSON(json) {
index: json.prevout.index index: json.prevout.index
}, },
output: json.output ? bcoin.coin._fromJSON(json.output) : null, output: json.output ? bcoin.coin._fromJSON(json.output) : null,
script: bcoin.script.decode(new Buffer(json.script, 'hex')), script: new Script(new Buffer(json.script, 'hex')),
witness: bcoin.protocol.parser.parseWitness(new Buffer(json.witness, 'hex')), witness: bcoin.protocol.parser.parseWitness(new Buffer(json.witness, 'hex')),
sequence: json.sequence sequence: json.sequence
}; };

View File

@ -10,6 +10,7 @@ var bcoin = require('../bcoin');
var utils = bcoin.utils; var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
var constants = bcoin.protocol.constants; var constants = bcoin.protocol.constants;
var Script = bcoin.script;
/** /**
* MTX * MTX
@ -140,7 +141,7 @@ MTX.prototype.addInput = function addInput(options, index) {
input = bcoin.input(options, this); input = bcoin.input(options, this);
if (options.script) if (options.script)
input.script = options.script.slice(); input.script = options.script.clone();
if (options.witness) if (options.witness)
input.witness = options.witness.slice(); input.witness = options.witness.slice();
@ -166,7 +167,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
// Optimization: Don't bother with any below // Optimization: Don't bother with any below
// calculation if the output is already templated. // calculation if the output is already templated.
// Just say this is "our" output. // Just say this is "our" output.
if (input.script.length || input.witness.length) if (input.script.code.length || input.witness.length)
return true; return true;
// Optimization: test output against the // Optimization: test output against the
@ -182,67 +183,67 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
// This is easily the hardest part about building a transaction // This is easily the hardest part about building a transaction
// with segwit: figuring out where the redeem script and witness // with segwit: figuring out where the redeem script and witness
// redeem scripts go. // redeem scripts go.
if (bcoin.script.isScripthash(prev)) { if (prev.isScripthash()) {
if (addr.program && utils.isEqual(prev[1], addr.programHash)) { if (addr.program && utils.isEqual(prev.code[1], addr.programHash)) {
// Witness program nested in regular P2SH. // Witness program nested in regular P2SH.
redeemScript = addr.program; redeemScript = addr.program.encode();
vector = input.witness; vector = input.witness;
dummy = new Buffer([]); dummy = new Buffer([]);
assert(addr.program[0] === 0, 'Non-zero version passed to address.'); assert(addr.program.code[0] === 0, 'Non-zero version passed to address.');
if (addr.program.length === 34) { if (addr.program.code[1].length === 32) {
// P2WSH nested within pay-to-scripthash // P2WSH nested within pay-to-scripthash
// (it had to be this complicated, didn't it?) // (it had to be this complicated, didn't it?)
witnessScript = addr.script; witnessScript = addr.script.encode();
prev = bcoin.script.decode(addr.script); prev = addr.script;
} else if (addr.program.length === 22) { } else if (addr.program.code[1].length === 20) {
// P2WPKH nested within pay-to-scripthash. // P2WPKH nested within pay-to-scripthash.
prev = bcoin.script.createPubkeyhash(addr.keyHash); prev = bcoin.script.createPubkeyhash(addr.keyHash);
} else { } else {
assert(false, 'Unknown program data length passed to address.'); assert(false, 'Unknown program data length passed to address.');
} }
} else if (addr.script && utils.isEqual(prev[1], addr.scriptHash160)) { } else if (addr.script && utils.isEqual(prev.code[1], addr.scriptHash160)) {
// Regular P2SH. // Regular P2SH.
redeemScript = addr.script; redeemScript = addr.script.encode();
prev = bcoin.script.decode(addr.script); vector = input.script.code;
vector = input.script; prev = addr.script;
dummy = 0; dummy = 0;
} else { } else {
return false; return false;
} }
} else if (bcoin.script.isWitnessProgram(prev)) { } else if (prev.isWitnessProgram()) {
// Witness program. // Witness program.
vector = input.witness; vector = input.witness;
dummy = new Buffer([]); dummy = new Buffer([]);
if (prev[0] !== 0) if (prev.code[0] !== 0)
return false; return false;
if (prev[1].length === 32) { if (prev.code[1].length === 32) {
// Bare P2WSH. // Bare P2WSH.
if (!addr.script || !utils.isEqual(prev[1], addr.scriptHash256)) if (!addr.script || !utils.isEqual(prev.code[1], addr.scriptHash256))
return false; return false;
witnessScript = addr.script; witnessScript = addr.script.encode();
prev = bcoin.script.decode(addr.script); prev = addr.script;
} else if (prev[1].length === 20) { } else if (prev.code[1].length === 20) {
// Bare P2WPKH. // Bare P2WPKH.
if (!utils.isEqual(prev[1], addr.keyHash)) if (!utils.isEqual(prev.code[1], addr.keyHash))
return false; return false;
prev = bcoin.script.createPubkeyhash(prev[1]); prev = bcoin.script.createPubkeyhash(prev.code[1]);
} else { } else {
// Bare... who knows? // Bare... who knows?
return false; return false;
} }
} else { } else {
// Wow, a normal output! Praise be to Jengus and Gord. // Wow, a normal output! Praise be to Jengus and Gord.
vector = input.script; vector = input.script.code;
dummy = 0; dummy = 0;
} }
if (bcoin.script.isPubkey(prev)) { if (prev.isPubkey()) {
// P2PK // P2PK
if (!utils.isEqual(prev[0], addr.publicKey)) if (!utils.isEqual(prev.code[0], addr.publicKey))
return false; return false;
// Already has a script template (at least) // Already has a script template (at least)
@ -250,9 +251,9 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
return true; return true;
vector[0] = dummy; vector[0] = dummy;
} else if (bcoin.script.isPubkeyhash(prev)) { } else if (prev.isPubkeyhash()) {
// P2PKH // P2PKH
if (!utils.isEqual(prev[2], addr.keyHash)) if (!utils.isEqual(prev.code[2], addr.keyHash))
return false; return false;
// Already has a script template (at least) // Already has a script template (at least)
@ -261,9 +262,9 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
vector[0] = dummy; vector[0] = dummy;
vector[1] = addr.publicKey; vector[1] = addr.publicKey;
} else if (bcoin.script.isMultisig(prev)) { } else if (prev.isMultisig()) {
// Multisig // Multisig
if (utils.indexOf(prev, addr.publicKey) === -1) if (utils.indexOf(prev.code, addr.publicKey) === -1)
return false; return false;
// Already has a script template (at least) // Already has a script template (at least)
@ -276,13 +277,13 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
vector[0] = dummy; vector[0] = dummy;
// Grab `n` value (number of keys). // Grab `n` value (number of keys).
n = prev[prev.length - 2]; n = prev.code[prev.code.length - 2];
// Fill script with `n` signature slots. // Fill script with `n` signature slots.
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
vector[i + 1] = dummy; vector[i + 1] = dummy;
} else { } else {
if (utils.indexOf(prev, addr.publicKey) === -1) if (utils.indexOf(prev.code, addr.publicKey) === -1)
return false; return false;
// Already has a script template (at least) // Already has a script template (at least)
@ -296,8 +297,8 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
vector[0] = dummy; vector[0] = dummy;
// Fill script with `n` signature slots. // Fill script with `n` signature slots.
for (i = 0; i < prev.length; i++) { for (i = 0; i < prev.code.length; i++) {
if (bcoin.script.isKey(prev[i])) if (bcoin.script.isKey(prev.code[i]))
vector[i + 1] = dummy; vector[i + 1] = dummy;
} }
} }
@ -305,7 +306,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
// P2SH requires the redeem // P2SH requires the redeem
// script after signatures. // script after signatures.
if (redeemScript) if (redeemScript)
input.script.push(redeemScript); input.script.code.push(redeemScript);
// P2WSH requires the witness // P2WSH requires the witness
// script after signatures. // script after signatures.
@ -316,7 +317,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
}; };
MTX.prototype.createSignature = function createSignature(index, prev, key, type, version) { MTX.prototype.createSignature = function createSignature(index, prev, key, type, version) {
var prev, hash, signature; var hash, signature;
if (typeof index !== 'number') if (typeof index !== 'number')
index = this.inputs.indexOf(index); index = this.inputs.indexOf(index);
@ -357,15 +358,15 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
// Get the previous output's subscript // Get the previous output's subscript
prev = input.output.script; prev = input.output.script;
vector = input.script; vector = input.script.code;
len = vector.length; len = vector.length;
dummy = 0; dummy = 0;
version = 0; version = 0;
// We need to grab the redeem script when // We need to grab the redeem script when
// signing p2sh transactions. // signing p2sh transactions.
if (bcoin.script.isScripthash(prev)) { if (prev.isScripthash()) {
prev = bcoin.script.getRedeem(input.script); prev = input.script.getRedeem();
len = vector.length - 1; len = vector.length - 1;
} }
@ -375,14 +376,14 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
// witnesses are stack items, so the `dummy` // witnesses are stack items, so the `dummy`
// _has_ to be an empty buffer (what OP_0 // _has_ to be an empty buffer (what OP_0
// pushes onto the stack). // pushes onto the stack).
if (bcoin.script.isWitnessScripthash(prev)) { if (prev.isWitnessScripthash()) {
prev = bcoin.script.getRedeem(input.witness); prev = bcoin.script.getRedeem(input.witness);
vector = input.witness; vector = input.witness;
len = vector.length - 1; len = vector.length - 1;
dummy = new Buffer([]); dummy = new Buffer([]);
version = 1; version = 1;
} else if (bcoin.script.isWitnessPubkeyhash(prev)) { } else if (prev.isWitnessPubkeyhash()) {
prev = bcoin.script.createPubkeyhash(prev[1]); prev = bcoin.script.createPubkeyhash(prev.code[1]);
vector = input.witness; vector = input.witness;
len = vector.length; len = vector.length;
dummy = new Buffer([]); dummy = new Buffer([]);
@ -393,7 +394,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
signature = this.createSignature(index, prev, addr.key, type, version); signature = this.createSignature(index, prev, addr.key, type, version);
// Add signatures. // Add signatures.
if (bcoin.script.isPubkey(prev)) { if (prev.isPubkey()) {
// P2PK // P2PK
// Already signed. // Already signed.
@ -401,7 +402,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
return true; return true;
// Make sure the pubkey is ours. // Make sure the pubkey is ours.
if (!utils.isEqual(addr.publicKey, prev[0])) if (!utils.isEqual(addr.publicKey, prev.code[0]))
return false; return false;
vector[0] = signature; vector[0] = signature;
@ -409,7 +410,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
return true; return true;
} }
if (bcoin.script.isPubkeyhash(prev)) { if (prev.isPubkeyhash()) {
// P2PKH // P2PKH
// Already signed. // Already signed.
@ -417,7 +418,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
return true; return true;
// Make sure the pubkey hash is ours. // Make sure the pubkey hash is ours.
if (!utils.isEqual(addr.keyHash, prev[2])) if (!utils.isEqual(addr.keyHash, prev.code[2]))
return false; return false;
vector[0] = signature; vector[0] = signature;
@ -425,18 +426,18 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
return true; return true;
} }
if (bcoin.script.isMultisig(prev)) { if (prev.isMultisig()) {
// Multisig // Multisig
// Grab the redeem script's keys to figure // Grab the redeem script's keys to figure
// out where our key should go. // out where our key should go.
keys = prev.slice(1, -2); keys = prev.code.slice(1, -2);
// Grab `m` value (number of sigs required). // Grab `m` value (number of sigs required).
m = prev[0]; m = prev.code[0];
// Grab `n` value (number of keys). // Grab `n` value (number of keys).
n = prev[prev.length - 2]; n = prev.code[prev.code.length - 2];
} else { } else {
// Only allow non-standard signing for // Only allow non-standard signing for
// scripthash. // scripthash.
@ -445,9 +446,9 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
keys = []; keys = [];
for (i = 0; i < prev.length; i++) { for (i = 0; i < prev.code.length; i++) {
if (bcoin.script.isKey(prev[i])) if (bcoin.script.isKey(prev.code[i]))
keys.push(prev[i]); keys.push(prev.code[i]);
} }
// We don't know what m is, so // We don't know what m is, so
@ -573,7 +574,7 @@ MTX.prototype.addOutput = function addOutput(obj, value) {
this.outputs.push(output); this.outputs.push(output);
if (options.script) if (options.script)
output.script = options.script.slice(); output.script = options.script.clone();
this.scriptOutput(this.outputs.length - 1, options); this.scriptOutput(this.outputs.length - 1, options);
@ -629,10 +630,7 @@ MTX.prototype.scriptOutput = function scriptOutput(index, options) {
} else if (options.key) { } else if (options.key) {
// P2PK Transaction // P2PK Transaction
// [pubkey] checksig // [pubkey] checksig
script = [ script = bcoin.script.createPubkey(utils.ensureBuffer(options.key));
utils.ensureBuffer(options.key),
'checksig'
];
} else if (options.flags) { } else if (options.flags) {
// Nulldata Transaction // Nulldata Transaction
// return [data] // return [data]
@ -648,13 +646,13 @@ MTX.prototype.scriptOutput = function scriptOutput(index, options) {
// hash160 [hash] eq // hash160 [hash] eq
if (options.scriptHash) { if (options.scriptHash) {
if (options.locktime != null) { if (options.locktime != null) {
script = [ script = new Script([
bcoin.script.array(options.locktime), bcoin.script.array(options.locktime),
'checklocktimeverify', 'checklocktimeverify',
'drop' 'drop'
].concat(script); ].concat(script.code));
} }
hash = utils.ripesha(bcoin.script.encode(script)); hash = utils.ripesha(bcoin.script.encode(script.code));
script = bcoin.script.createScripthash(hash); script = bcoin.script.createScripthash(hash);
} }
@ -668,7 +666,7 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
// Create copy with 0-script inputs // Create copy with 0-script inputs
for (i = 0; i < copy.inputs.length; i++) { for (i = 0; i < copy.inputs.length; i++) {
copy.inputs[i].script = []; copy.inputs[i].script = new Script([]);
copy.inputs[i].witness = []; copy.inputs[i].witness = [];
} }
@ -687,50 +685,48 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
// If we have access to the redeem script, // If we have access to the redeem script,
// we can use it to calculate size much easier. // we can use it to calculate size much easier.
if (this.inputs[i].script.length && bcoin.script.isScripthash(prev)) { if (this.inputs[i].script.code.length && prev.isScripthash()) {
// Need to add the redeem script size // Need to add the redeem script size
// here since it will be ignored by // here since it will be ignored by
// the isMultisig clause. // the isMultisig clause.
// OP_PUSHDATA2 [redeem] // OP_PUSHDATA2 [redeem]
prev = this.inputs[i].script[this.inputs[i].script.length - 1]; prev = this.inputs[i].getRedeem();
size += utils.sizeIntv(prev.length) + prev.length; size += utils.sizeIntv(prev.getSize()) + prev.getSize();
prev = bcoin.script.decode(prev);
} }
if (bcoin.script.isWitnessProgram(prev)) { if (prev.isWitnessProgram()) {
witness = true; witness = true;
// Now calculating vsize. The regular // Now calculating vsize. The regular
// redeem script (if there was one) // redeem script (if there was one)
// is now worth 4 points. // is now worth 4 points.
size *= 4; size *= 4;
if (this.inputs[i].witness.length && bcoin.script.isWitnessScripthash(prev)) { if (this.inputs[i].witness.length && prev.isWitnessScripthash()) {
prev = this.inputs[i].witness[this.inputs[i].witness.length - 1]; prev = bcoin.script.getRedeem(this.inputs[i].witness);
size += utils.sizeIntv(prev.length) + prev.length; size += utils.sizeIntv(prev.getSize()) + prev.getSize();
prev = bcoin.script.decode(prev); } else if (prev.isWitnessPubkeyhash()) {
} else if (bcoin.script.isWitnessPubkeyhash(prev)) { prev = bcoin.script.createPubkeyhash(prev.code[1]);
prev = bcoin.script.createPubkeyhash(prev[1]);
} }
} }
if (bcoin.script.isPubkey(prev)) { if (prev.isPubkey()) {
// P2PK // P2PK
// OP_PUSHDATA0 [signature] // OP_PUSHDATA0 [signature]
size += 1 + 73; size += 1 + 73;
} else if (bcoin.script.isPubkeyhash(prev)) { } else if (prev.isPubkeyhash()) {
// P2PKH // P2PKH
// OP_PUSHDATA0 [signature] // OP_PUSHDATA0 [signature]
size += 1 + 73; size += 1 + 73;
// OP_PUSHDATA0 [key] // OP_PUSHDATA0 [key]
size += 1 + 33; size += 1 + 33;
} else if (bcoin.script.isMultisig(prev)) { } else if (prev.isMultisig()) {
// Bare Multisig // Bare Multisig
// Get the previous m value: // Get the previous m value:
m = prev[0]; m = prev.code[0];
// OP_0 // OP_0
size += 1; size += 1;
// OP_PUSHDATA0 [signature] ... // OP_PUSHDATA0 [signature] ...
size += (1 + 73) * m; size += (1 + 73) * m;
} else if (bcoin.script.isScripthash(prev)) { } else if (prev.isScripthash()) {
// P2SH Multisig // P2SH Multisig
// This technically won't work well for other // This technically won't work well for other
// kinds of P2SH. It will also over-estimate // kinds of P2SH. It will also over-estimate
@ -760,8 +756,8 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
size += 1; size += 1;
} else { } else {
// OP_PUSHDATA0 [signature] // OP_PUSHDATA0 [signature]
for (j = 0; j < prev.length; j++) { for (j = 0; j < prev.code.length; j++) {
if (bcoin.script.isKey(prev[j])) if (bcoin.script.isKey(prev.code[j]))
size += 1 + 73; size += 1 + 73;
} }
} }
@ -986,8 +982,8 @@ MTX.prototype.sortMembers = function sortMembers() {
if (res !== 0) if (res !== 0)
return res; return res;
a = bcoin.script.encode(a.script); a = a.encode();
b = bcoin.script.encode(b.script); b = b.encode();
return utils.cmp(a, b); return utils.cmp(a, b);
}); });

View File

@ -9,6 +9,7 @@ var bcoin = require('../bcoin');
var utils = bcoin.utils; var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
var constants = bcoin.protocol.constants; var constants = bcoin.protocol.constants;
var Script = bcoin.script;
/** /**
* Output * Output
@ -30,7 +31,7 @@ function Output(options, tx) {
} }
this.value = utils.satoshi(value || new bn(0)); this.value = utils.satoshi(value || new bn(0));
this.script = options.script || []; this.script = options.script || new Script([]);
this._size = options._size || 0; this._size = options._size || 0;
this._offset = options._offset || 0; this._offset = options._offset || 0;
this._mutable = !tx || (tx instanceof bcoin.mtx); this._mutable = !tx || (tx instanceof bcoin.mtx);
@ -57,7 +58,7 @@ Output.prototype.getType = function getType() {
if (this._type) if (this._type)
return this._type; return this._type;
type = bcoin.script.getOutputType(this.script); type = this.script.getType();
if (!this._mutable) if (!this._mutable)
this._type = type; this._type = type;
@ -71,7 +72,7 @@ Output.prototype.getAddress = function getAddress() {
if (this._address) if (this._address)
return this._address; return this._address;
address = bcoin.script.getOutputAddress(this.script); address = this.script.getAddress();
if (!this._mutable) if (!this._mutable)
this._address = address; this._address = address;
@ -101,28 +102,12 @@ Output.prototype.test = function test(addressTable) {
return false; return false;
}; };
Output.prototype.getSigops = function getSigops(accurate) {
return bcoin.script.getSigops(this.script, accurate);
};
Output.prototype.getID = function getID() { Output.prototype.getID = function getID() {
var data = bcoin.script.encode(this.script); var data = this.script.encode();
var hash = utils.toHex(utils.ripesha(data)); var hash = utils.toHex(utils.ripesha(data));
return '[' + this.type + ':' + hash.slice(0, 7) + ']'; return '[' + this.type + ':' + hash.slice(0, 7) + ']';
}; };
Output.prototype.getData = function getData() {
var def;
def = {
side: 'output',
value: this.value,
script: this.script
};
return utils.merge(def, bcoin.script.getOutputData(this.script));
};
Output.prototype.inspect = function inspect() { Output.prototype.inspect = function inspect() {
return { return {
type: this.getType(), type: this.getType(),
@ -135,14 +120,14 @@ Output.prototype.inspect = function inspect() {
Output.prototype.toJSON = function toJSON() { Output.prototype.toJSON = function toJSON() {
return { return {
value: utils.btc(this.value), value: utils.btc(this.value),
script: utils.toHex(bcoin.script.encode(this.script)) script: utils.toHex(this.script.encode())
}; };
}; };
Output._fromJSON = function _fromJSON(json) { Output._fromJSON = function _fromJSON(json) {
return { return {
value: utils.satoshi(json.value), value: utils.satoshi(json.value),
script: bcoin.script.decode(new Buffer(json.script, 'hex')) script: new Script(new Buffer(json.script, 'hex'))
}; };
}; };

View File

@ -380,18 +380,16 @@ Framer._getBlocks = function _getBlocks(hashes, stop) {
Framer.input = function _input(input) { Framer.input = function _input(input) {
var off = 0; var off = 0;
var s, p; var script, p;
s = bcoin.script.encode(input.script); script = input.script.encode();
p = new Buffer(32 + 4 + utils.sizeIntv(s.length) + s.length + 4); p = new Buffer(32 + 4 + utils.sizeIntv(script.length) + script.length + 4);
off += utils.copy(new Buffer(input.prevout.hash, 'hex'), p, off); off += utils.copy(new Buffer(input.prevout.hash, 'hex'), p, off);
off += utils.writeU32(p, input.prevout.index, off); off += utils.writeU32(p, input.prevout.index, off);
off += utils.writeIntv(p, s.length, off); off += utils.writeIntv(p, script.length, off);
if (!s.copy) off += utils.copy(script, p, off);
console.log(s);
off += utils.copy(s, p, off);
off += utils.writeU32(p, input.sequence, off); off += utils.writeU32(p, input.sequence, off);
@ -400,23 +398,23 @@ Framer.input = function _input(input) {
Framer.output = function _output(output) { Framer.output = function _output(output) {
var off = 0; var off = 0;
var s, p; var script, p;
s = bcoin.script.encode(output.script); script = output.script.encode();
p = new Buffer(8 + utils.sizeIntv(s.length) + s.length); p = new Buffer(8 + utils.sizeIntv(script.length) + script.length);
off += utils.write64(p, output.value, off); off += utils.write64(p, output.value, off);
assert(output.value.byteLength() <= 8); assert(output.value.byteLength() <= 8);
off += utils.writeIntv(p, s.length, off); off += utils.writeIntv(p, script.length, off);
off += utils.copy(s, p, off); off += utils.copy(script, p, off);
return p; return p;
}; };
Framer.utxo = Framer.utxo =
Framer.coin = function _coin(coin, extended) { Framer.coin = function _coin(coin, extended) {
var script = bcoin.script.encode(coin.script); var script = coin.script.encode();
var intSize = utils.sizeIntv(script.length); var intSize = utils.sizeIntv(script.length);
var height = coin.height; var height = coin.height;
var off = 0; var off = 0;

View File

@ -356,7 +356,7 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
var height = -1; var height = -1;
var version, prevBlock, merkleRoot, ts, bits, nonce; var version, prevBlock, merkleRoot, ts, bits, nonce;
var i, totalTX, tx; var i, totalTX, tx;
var inCount, input, s, raw; var inCount, input, raw;
p = new BufferReader(p); p = new BufferReader(p);
p.start(); p.start();
@ -379,9 +379,8 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
} }
if (input) { if (input) {
s = input.script; if (Buffer.isBuffer(input.script.code[0]))
if (Buffer.isBuffer(s[0])) height = input.script.code[0];
height = s[0];
} }
raw = p.data; raw = p.data;
@ -411,7 +410,7 @@ Parser.parseInput = function parseInput(p) {
hash = p.readHash(); hash = p.readHash();
index = p.readU32(); index = p.readU32();
script = bcoin.script.decode(p.readVarBytes()); script = new bcoin.script(p.readVarBytes());
sequence = p.readU32(); sequence = p.readU32();
return { return {
@ -432,7 +431,7 @@ Parser.parseOutput = function parseOutput(p) {
p.start(); p.start();
value = p.read64(); value = p.read64();
script = bcoin.script.decode(p.readVarBytes()); script = new bcoin.script(p.readVarBytes());
return { return {
_size: p.end(), _size: p.end(),
@ -443,6 +442,7 @@ Parser.parseOutput = function parseOutput(p) {
Parser.parseCoin = function parseCoin(p, extended) { Parser.parseCoin = function parseCoin(p, extended) {
var version, height, value, script, hash, index, spent; var version, height, value, script, hash, index, spent;
p = new BufferReader(p); p = new BufferReader(p);
version = p.readU32(); version = p.readU32();
@ -453,12 +453,12 @@ Parser.parseCoin = function parseCoin(p, extended) {
value = p.read64(); value = p.read64();
script = bcoin.script.decode(p.readVarBytes()); script = new bcoin.script(p.readVarBytes());
if (extended) { if (extended) {
hash = p.readHash(); hash = p.readHash();
index = p.readU32(); index = p.readU32();
spent = p.readU8(); spent = p.readU8() === 1;
} else { } else {
hash = utils.slice(constants.zeroHash); hash = utils.slice(constants.zeroHash);
index = 0xffffffff; index = 0xffffffff;
@ -527,7 +527,7 @@ Parser.isWitnessTX = function isWitnessTX(p) {
if (p.left() < 12) if (p.left() < 12)
return false; return false;
return p[p.offset + 4] === 0 && p[p.offset + 5] !== 0; return p.data[p.offset + 4] === 0 && p.data[p.offset + 5] !== 0;
}; };
Parser.parseWitnessTX = function parseWitnessTX(p) { Parser.parseWitnessTX = function parseWitnessTX(p) {
@ -822,7 +822,7 @@ BufferReader.prototype.read64BE = function read64BE() {
}; };
BufferReader.prototype.readBytes = function readBytes(size) { BufferReader.prototype.readBytes = function readBytes(size) {
assert(size > 0) assert(size >= 0);
assert(this.offset + size <= this.data.length); assert(this.offset + size <= this.data.length);
var ret = utils.slice(this.data, this.offset, this.offset + size); var ret = utils.slice(this.data, this.offset, this.offset + size);
this.offset += size; this.offset += size;
@ -830,7 +830,7 @@ BufferReader.prototype.readBytes = function readBytes(size) {
}; };
BufferReader.prototype.readString = function readString(enc, size) { BufferReader.prototype.readString = function readString(enc, size) {
assert(size > 0) assert(size >= 0);
assert(this.offset + size <= this.data.length); assert(this.offset + size <= this.data.length);
var ret = this.data.toString(enc, this.offset, this.offset + size); var ret = this.data.toString(enc, this.offset, this.offset + size);
this.offset += size; this.offset += size;

View File

@ -10,6 +10,7 @@ var bcoin = require('../bcoin');
var utils = bcoin.utils; var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
var constants = bcoin.protocol.constants; var constants = bcoin.protocol.constants;
var Script = bcoin.script;
/** /**
* TX * TX
@ -172,19 +173,6 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) {
return -1; return -1;
}; };
TX.prototype.getSubscript = function getSubscript(index) {
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);
};
TX.prototype.signatureHash = function signatureHash(index, s, type, version) { TX.prototype.signatureHash = function signatureHash(index, s, type, version) {
assert(version >= 0 && version <= 1); assert(version >= 0 && version <= 1);
if (version === 0) if (version === 0)
@ -206,7 +194,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
for (i = 0; i < this.inputs.length; i++) { for (i = 0; i < this.inputs.length; i++) {
copy.inputs.push({ copy.inputs.push({
prevout: this.inputs[i].prevout, prevout: this.inputs[i].prevout,
script: this.inputs[i].script.slice(), script: this.inputs[i].script.clone(),
witness: this.inputs[i].witness.slice(), witness: this.inputs[i].witness.slice(),
sequence: this.inputs[i].sequence sequence: this.inputs[i].sequence
}); });
@ -215,7 +203,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
for (i = 0; i < this.outputs.length; i++) { for (i = 0; i < this.outputs.length; i++) {
copy.outputs.push({ copy.outputs.push({
value: this.outputs[i].value, value: this.outputs[i].value,
script: this.outputs[i].script.slice() script: this.outputs[i].script.clone()
}); });
} }
@ -226,7 +214,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
type = constants.hashType[type]; type = constants.hashType[type];
assert(index >= 0 && index < copy.inputs.length) assert(index >= 0 && index < copy.inputs.length)
assert(Array.isArray(s)); assert(s instanceof bcoin.script);
// Disable this for now. We allow null hash types // Disable this for now. We allow null hash types
// because bitcoind allows empty signatures. On // because bitcoind allows empty signatures. On
@ -236,7 +224,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
// Remove all signatures. // Remove all signatures.
for (i = 0; i < copy.inputs.length; i++) for (i = 0; i < copy.inputs.length; i++)
copy.inputs[i].script = []; copy.inputs[i].script = new Script([]);
// Set our input to previous output's script // Set our input to previous output's script
copy.inputs[index].script = s; copy.inputs[index].script = s;
@ -262,7 +250,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
// Null outputs that are not the at current input index. // Null outputs that are not the at current input index.
for (i = 0; i < copy.outputs.length; i++) { for (i = 0; i < copy.outputs.length; i++) {
if (i !== index) { if (i !== index) {
copy.outputs[i].script = []; copy.outputs[i].script = new Script([]);
copy.outputs[i].value = new bn('ffffffffffffffff', 'hex'); copy.outputs[i].value = new bn('ffffffffffffffff', 'hex');
} }
} }
@ -302,7 +290,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, s, type) {
type = constants.hashType[type]; type = constants.hashType[type];
assert(index >= 0 && index < this.inputs.length) assert(index >= 0 && index < this.inputs.length)
assert(Array.isArray(s)); assert(s instanceof bcoin.script);
if (!(type & constants.hashType.anyonecanpay)) { if (!(type & constants.hashType.anyonecanpay)) {
hashPrevouts = new Buffer(36 * this.inputs.length); hashPrevouts = new Buffer(36 * this.inputs.length);
@ -353,7 +341,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, s, type) {
hashOutputs.fill(0); hashOutputs.fill(0);
} }
s = bcoin.script.encode(s); s = s.encode();
msg = new Buffer( msg = new Buffer(
4 + 32 + 32 + 36 4 + 32 + 32 + 36
@ -666,23 +654,23 @@ TX.prototype._getSigops = function _getSigops(scriptHash, accurate) {
prev = input.output.script; prev = input.output.script;
total += bcoin.script.getSigops(input.script, accurate); total += input.script.getSigops(accurate);
if (scriptHash && !this.isCoinbase()) { if (scriptHash && !this.isCoinbase()) {
if (!bcoin.script.isScripthash(prev)) if (!prev.isScripthash())
return; return;
if (!bcoin.script.isPushOnly(input.script)) if (!input.script.isPushOnly())
return; return;
prev = bcoin.script.getRedeem(input.script); prev = input.script.getRedeem();
total += bcoin.script.getSigops(prev, true); total += prev.getSigops(true);
} }
}, this); }, this);
this.outputs.forEach(function(output) { this.outputs.forEach(function(output) {
total += bcoin.script.getSigops(output.script, accurate); total += output.script.getSigops(accurate);
}, this); }, this);
return total; return total;
@ -699,19 +687,19 @@ TX.prototype.getSigops = function getSigops(scriptHash, accurate) {
prev = input.output.script; prev = input.output.script;
if (bcoin.script.isScripthash(prev)) if (prev.isScripthash())
prev = bcoin.script.getRedeem(input.script); prev = input.script.getRedeem();
if (bcoin.script.isWitnessScripthash(prev)) { if (prev.isWitnessScripthash()) {
prev = bcoin.script.getRedeem(input.witness); prev = bcoin.script.getRedeem(input.witness);
cost += bcoin.script.getSigops(prev, true); cost += prev.getSigops(true);
} else { } else {
cost += 0; cost += 0;
} }
}, this); }, this);
this.outputs.forEach(function(output) { this.outputs.forEach(function(output) {
if (bcoin.script.isWitnessPubkeyhash(output.script)) if (output.script.isWitnessPubkeyhash())
cost += 1; cost += 1;
else else
cost += 0; cost += 0;
@ -736,7 +724,7 @@ TX.prototype.isStandard = function isStandard(flags) {
for (i = 0; i < this.inputs.length; i++) { for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i]; input = this.inputs[i];
if (bcoin.script.getSize(input.script) > 1650) if (input.script.getSize() > 1650)
return false; return false;
// Not accurate? // Not accurate?
@ -744,16 +732,16 @@ TX.prototype.isStandard = function isStandard(flags) {
continue; continue;
if (flags & constants.flags.VERIFY_SIGPUSHONLY) { if (flags & constants.flags.VERIFY_SIGPUSHONLY) {
if (!bcoin.script.isPushOnly(input.script)) if (!input.script.isPushOnly())
return false; return false;
} }
} }
for (i = 0; i < this.outputs.length; i++) { for (i = 0; i < this.outputs.length; i++) {
output = this.outputs[i]; output = this.outputs[i];
type = bcoin.script.getType(output.script); type = output.script.getType();
if (!bcoin.script.isStandard(output.script)) if (!output.script.isStandard())
return false; return false;
if (type === 'unknown') if (type === 'unknown')
@ -793,7 +781,7 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) {
if (!input.output) if (!input.output)
return false; return false;
args = bcoin.script.getArgs(input.output.script); args = input.output.script.getArgs();
if (args < 0) if (args < 0)
return false; return false;
@ -803,10 +791,10 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) {
// Bitcoind doesn't do this, but it's possible someone // Bitcoind doesn't do this, but it's possible someone
// could DoS us by sending ridiculous txs to the mempool // could DoS us by sending ridiculous txs to the mempool
// if we don't put this here. // if we don't put this here.
if (!bcoin.script.isPushOnly(input.script)) if (!input.script.isPushOnly())
return false; return false;
res = bcoin.script.execute(input.script, stack, this, i, flags); res = input.script.execute(stack, this, i, flags);
// TODO: Segwit here. // TODO: Segwit here.
@ -814,29 +802,27 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) {
return false; return false;
if ((flags & constants.flags.VERIFY_P2SH) if ((flags & constants.flags.VERIFY_P2SH)
&& bcoin.script.isScripthash(input.output.script)) { && input.output.script.isScripthash()) {
if (stack.length === 0) if (stack.length === 0)
return false; return false;
redeem = stack.pop(); redeem = bcoin.script.getRedeem(stack);
if (!Buffer.isBuffer(redeem)) if (!redeem)
return false; return false;
// Not accurate? // Not accurate?
if (redeem.length > 520) if (redeem.getSize() > 520)
return false; return false;
redeem = bcoin.script.decode(redeem);
// Also consider scripthash "unknown"? // Also consider scripthash "unknown"?
if (bcoin.script.getType(redeem) === 'unknown') { if (redeem.getType() === 'unknown') {
if (bcoin.script.getSigops(redeem, true) > maxSigops) if (redeem.getSigops(true) > maxSigops)
return false; return false;
continue; continue;
} }
targs = bcoin.script.getArgs(redeem); targs = redeem.getArgs();
if (targs < 0) if (targs < 0)
return false; return false;
args += targs; args += targs;
@ -942,11 +928,11 @@ TX.prototype.getValue = function getValue() {
TX.prototype.hasType = function hasType(type) { TX.prototype.hasType = function hasType(type) {
for (var i = 0; i < this.inputs.length; i++) { for (var i = 0; i < this.inputs.length; i++) {
if (bcoin.script.getInputType(this.inputs[i].script) === type) if (this.inputs[i].getInputType() === type)
return true; return true;
} }
for (var i = 0; i < this.outputs.length; i++) { for (var i = 0; i < this.outputs.length; i++) {
if (bcoin.script.getType(this.outputs[i].script) === type) if (this.outputs[i].getType() === type)
return true; return true;
} }
return false; return false;

View File

@ -179,6 +179,6 @@ describe('Protocol', function() {
'de5c0500000017a9141d9ca71efa36d814424ea6ca1437e67287aebe348' + 'de5c0500000017a9141d9ca71efa36d814424ea6ca1437e67287aebe348' +
'700000000', 'hex'); '700000000', 'hex');
var tx = bcoin.protocol.parser.parseTX(rawTwoTxs); var tx = bcoin.protocol.parser.parseTX(rawTwoTxs);
assert.deepEqual(tx._raw, rawFirstTx); assert.deepEqual(bcoin.protocol.framer.tx(tx), rawFirstTx);
}); });
}); });

View File

@ -1,5 +1,6 @@
var assert = require('assert'); var assert = require('assert');
var bcoin = require('../'); var bcoin = require('../');
var Script = bcoin.script;
describe('Script', function() { describe('Script', function() {
it('should encode/decode script', function() { it('should encode/decode script', function() {
@ -34,55 +35,55 @@ describe('Script', function() {
it('should recognize a P2SH output', function () { it('should recognize a P2SH output', function () {
var hex = 'a91419a7d869032368fd1f1e26e5e73a4ad0e474960e87' var hex = 'a91419a7d869032368fd1f1e26e5e73a4ad0e474960e87'
var encoded = new Buffer(hex, 'hex') var encoded = new Buffer(hex, 'hex')
var decoded = bcoin.script.decode(encoded); var decoded = new bcoin.script(encoded);
assert(bcoin.script.isScripthash(decoded)) assert(decoded.isScripthash())
}) })
it('should recognize a Null Data output', function () { it('should recognize a Null Data output', function () {
var hex = '6a28590c080112220a1b353930632e6f7267282a5f5e294f7665726c6179404f7261636c65103b1a010c' var hex = '6a28590c080112220a1b353930632e6f7267282a5f5e294f7665726c6179404f7261636c65103b1a010c'
var encoded = new Buffer(hex, 'hex') var encoded = new Buffer(hex, 'hex')
var decoded = bcoin.script.decode(encoded); var decoded = new Script(encoded);
assert(bcoin.script.isNulldata(decoded)) assert(decoded.isNulldata())
}) })
it('should handle if statements correctly', function () { it('should handle if statements correctly', function () {
var inputScript = [1, 2]; var inputScript = new Script([1, 2]);
var prevOutScript = [2, 'equal', 'if', 3, 'else', 4, 'endif', 5]; var prevOutScript = new Script([2, 'equal', 'if', 3, 'else', 4, 'endif', 5]);
var stack = []; var stack = [];
bcoin.script.execute(inputScript, stack); inputScript.execute(stack);
var res = bcoin.script.execute(prevOutScript, stack); var res = prevOutScript.execute(stack);
assert(res); assert(res);
assert.deepEqual(stack.slice(), [[1], [3], [5]]); assert.deepEqual(stack.slice(), [[1], [3], [5]]);
var inputScript = [1, 2]; var inputScript = new Script([1, 2]);
var prevOutScript = [9, 'equal', 'if', 3, 'else', 4, 'endif', 5]; var prevOutScript = new Script([9, 'equal', 'if', 3, 'else', 4, 'endif', 5]);
var stack = []; var stack = [];
bcoin.script.execute(inputScript, stack); inputScript.execute(stack);
var res = bcoin.script.execute(prevOutScript, stack); var res = prevOutScript.execute(stack);
assert(res); assert(res);
assert.deepEqual(stack.slice(), [[1], [4], [5]]); assert.deepEqual(stack.slice(), [[1], [4], [5]]);
var inputScript = [1, 2]; var inputScript = new Script([1, 2]);
var prevOutScript = [2, 'equal', 'if', 3, 'endif', 5]; var prevOutScript = new Script([2, 'equal', 'if', 3, 'endif', 5]);
var stack = []; var stack = [];
bcoin.script.execute(inputScript, stack); inputScript.execute(stack);
var res = bcoin.script.execute(prevOutScript, stack); var res = prevOutScript.execute(stack);
assert(res); assert(res);
assert.deepEqual(stack.slice(), [[1], [3], [5]]); assert.deepEqual(stack.slice(), [[1], [3], [5]]);
var inputScript = [1, 2]; var inputScript = new Script([1, 2]);
var prevOutScript = [9, 'equal', 'if', 3, 'endif', 5]; var prevOutScript = new Script([9, 'equal', 'if', 3, 'endif', 5]);
var stack = []; var stack = [];
bcoin.script.execute(inputScript, stack); inputScript.execute(stack);
var res = bcoin.script.execute(prevOutScript, stack); var res = prevOutScript.execute(stack);
assert(res); assert(res);
assert.deepEqual(stack.slice(), [[1], [5]]); assert.deepEqual(stack.slice(), [[1], [5]]);
var inputScript = [1, 2]; var inputScript = new Script([1, 2]);
var prevOutScript = [9, 'equal', 'notif', 3, 'endif', 5]; var prevOutScript = new Script([9, 'equal', 'notif', 3, 'endif', 5]);
var stack = []; var stack = [];
bcoin.script.execute(inputScript, stack); inputScript.execute(stack);
var res = bcoin.script.execute(prevOutScript, stack); var res = prevOutScript.execute(stack);
assert(res); assert(res);
assert.deepEqual(stack.slice(), [[1], [3], [5]]); assert.deepEqual(stack.slice(), [[1], [3], [5]]);
}) })

View File

@ -13,12 +13,12 @@ var dummyInput = {
version: 1, version: 1,
height: 0, height: 0,
value: constants.maxMoney.clone(), value: constants.maxMoney.clone(),
script: [], script: new bcoin.script([]),
hash: constants.zeroHash, hash: constants.zeroHash,
index: 0, index: 0,
spent: false spent: false
}, },
script: [], script: new bcoin.script([]),
sequence: 0xffffffff sequence: 0xffffffff
}; };
@ -167,7 +167,7 @@ describe('Wallet', function() {
// Script inputs but do not sign // Script inputs but do not sign
w.scriptInputs(fake); w.scriptInputs(fake);
// Fake signature // Fake signature
fake.inputs[0].script[0] = new Buffer([0,0,0,0,0,0,0,0,0]); fake.inputs[0].script.code[0] = new Buffer([0,0,0,0,0,0,0,0,0]);
// balance: 11000 // balance: 11000
// Just for debugging // Just for debugging
@ -459,6 +459,8 @@ describe('Wallet', function() {
send.addOutput({ address: receive.getAddress(), value: 5460 }); send.addOutput({ address: receive.getAddress(), value: 5460 });
assert(!send.verify(null, true, flags)); assert(!send.verify(null, true, flags));
w1.fill(send, { m: w1.m, n: w1.n }, function(err) { w1.fill(send, { m: w1.m, n: w1.n }, function(err) {
if (err)
throw err;
assert(!err); assert(!err);
w1.sign(send); w1.sign(send);
@ -499,7 +501,7 @@ describe('Wallet', function() {
if (witness) if (witness)
send.inputs[0].witness[2] = new Buffer([]); send.inputs[0].witness[2] = new Buffer([]);
else else
send.inputs[0].script[2] = 0; send.inputs[0].script.code[2] = 0;
assert(!send.verify(null, true, flags)); assert(!send.verify(null, true, flags));
assert.equal(send.getFee().toNumber(), 10000); assert.equal(send.getFee().toNumber(), 10000);