script refactor.

This commit is contained in:
Christopher Jeffrey 2016-07-01 05:42:04 -07:00
parent 3fb5a36f8d
commit 3a652727c9
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 205 additions and 71 deletions

View File

@ -361,7 +361,6 @@ Coins.fromTX = function fromTX(tx) {
* coin is just a pointer to that coin in the
* Coins buffer, as well as a size. Parsing
* is done only if that coin is being redeemed.
* @exports DeferredCoin
* @constructor
* @private
* @param {Number} offset
@ -387,32 +386,34 @@ function DeferredCoin(offset, size, raw) {
DeferredCoin.prototype.toCoin = function toCoin(coins, index) {
var p = new BufferReader(this.raw);
var prefix, script, value, coin;
p.seek(this.offset);
prefix = p.readU8() & 3;
if (prefix === 0)
script = bcoin.script.fromRaw(p.readVarBytes());
else if (prefix === 1)
script = bcoin.script.fromPubkeyhash(p.readBytes(20));
else if (prefix === 2)
script = bcoin.script.fromScripthash(p.readBytes(20));
else
assert(false, 'Bad prefix.');
value = p.readVarint();
coin = new bcoin.coin();
var coin = new bcoin.coin();
var prefix;
coin.version = coins.version;
coin.coinbase = coins.coinbase;
coin.height = coins.height;
coin.hash = coins.hash;
coin.index = index;
coin.script = script;
coin.value = value;
p.seek(this.offset);
prefix = p.readU8() & 3;
switch (prefix) {
case 0:
coin.script.fromRaw(p.readVarBytes());
break;
case 1:
coin.script.fromPubkeyhash(p.readBytes(20));
break;
case 2:
coin.script.fromScripthash(p.readBytes(20));
break;
default:
assert(false, 'Bad prefix.');
}
coin.value = p.readVarint();
return coin;
};

View File

@ -402,7 +402,7 @@ MinerBlock.prototype._init = function _init() {
// Reward output.
output = new bcoin.output();
output.script = bcoin.script.fromAddress(this.address);
output.script.fromAddress(this.address);
cb.outputs.push(output);

View File

@ -52,7 +52,7 @@ Output.prototype.fromOptions = function fromOptions(options) {
this.script.fromOptions(options.script);
if (options.address)
this.script = bcoin.script.fromAddress(options.address);
this.script.fromAddress(options.address);
return this;
};

View File

@ -90,6 +90,18 @@ Witness.prototype.toArray = function toArray() {
return this.items.slice();
};
/**
* Inject properties from an array of buffers.
* @private
* @param {Buffer[]} items
*/
Witness.prototype.fromArray = function fromArray(items) {
assert(Array.isArray(items));
this.items = items;
return this;
};
/**
* Insantiate witness from an array of buffers.
* @param {Buffer[]} items
@ -97,7 +109,7 @@ Witness.prototype.toArray = function toArray() {
*/
Witness.fromArray = function fromArray(items) {
return new Witness(items);
return new Witness().fromArray(items);
};
/**
@ -442,6 +454,14 @@ Witness.prototype.getString = function getString(i) {
return item.toString('utf8');
};
/**
* Clear the witness items.
*/
Witness.prototype.clear = function clear() {
this.items.length = 0;
};
/**
* Set an item in the witness vector.
* @param {Number} index
@ -749,6 +769,14 @@ Stack.prototype.top = function top(i) {
return this.items[this.items.length + i];
};
/**
* Clear the stack.
*/
Stack.prototype.clear = function clear() {
this.items.length = 0;
};
/**
* Set stack item at index.
* @param {Number} index
@ -1182,6 +1210,19 @@ Script.prototype.toArray = function toArray() {
return code;
};
/**
* Inject properties from an array of
* of buffers and numbers.
* @private
*/
Script.prototype.fromArray = function fromArray(code) {
assert(Array.isArray(code));
this.code = Script.parseArray(code);
this.raw = Script.encode(this.code);
return this;
};
/**
* Instantiate script from an array
* of buffers and numbers.
@ -1189,7 +1230,7 @@ Script.prototype.toArray = function toArray() {
*/
Script.fromArray = function fromArray(code) {
return new Script(code);
return new Script().fromArray(code);
};
/**
@ -2434,6 +2475,17 @@ Script.isCode = function isCode(raw) {
return true;
};
/**
* Inject properties from a pay-to-pubkey script.
* @private
* @param {Buffer} key
*/
Script.prototype.fromPubkey = function fromPubkey(key) {
assert(Buffer.isBuffer(key) && key.length >= 33);
return this.fromArray([key, opcodes.OP_CHECKSIG]);
};
/**
* Create a pay-to-pubkey script.
* @param {Buffer} key
@ -2441,19 +2493,18 @@ Script.isCode = function isCode(raw) {
*/
Script.fromPubkey = function fromPubkey(key) {
assert(Buffer.isBuffer(key) && key.length >= 33);
return Script.fromArray([key, opcodes.OP_CHECKSIG]);
return new Script().fromPubkey(key);
};
/**
* Create a pay-to-pubkeyhash script.
* Inject properties from a pay-to-pubkeyhash script.
* @private
* @param {Buffer} hash
* @returns {Script}
*/
Script.fromPubkeyhash = function fromPubkeyhash(hash) {
Script.prototype.fromPubkeyhash = function fromPubkeyhash(hash) {
assert(Buffer.isBuffer(hash) && hash.length === 20);
return Script.fromArray([
return this.fromArray([
opcodes.OP_DUP,
opcodes.OP_HASH160,
hash,
@ -2463,14 +2514,24 @@ Script.fromPubkeyhash = function fromPubkeyhash(hash) {
};
/**
* Create a pay-to-multisig script.
* @param {Number} m
* @param {Number} n
* @param {Buffer[]} keys
* Create a pay-to-pubkeyhash script.
* @param {Buffer} hash
* @returns {Script}
*/
Script.fromMultisig = function fromMultisig(m, n, keys) {
Script.fromPubkeyhash = function fromPubkeyhash(hash) {
return new Script().fromPubkeyhash(hash);
};
/**
* Inject properties from pay-to-multisig script.
* @private
* @param {Number} m
* @param {Number} n
* @param {Buffer[]} keys
*/
Script.prototype.fromMultisig = function fromMultisig(m, n, keys) {
var code = [];
var i;
@ -2490,7 +2551,34 @@ Script.fromMultisig = function fromMultisig(m, n, keys) {
code.push(n + 0x50);
code.push(opcodes.OP_CHECKMULTISIG);
return Script.fromArray(code);
return this.fromArray(code);
};
/**
* Create a pay-to-multisig script.
* @param {Number} m
* @param {Number} n
* @param {Buffer[]} keys
* @returns {Script}
*/
Script.fromMultisig = function fromMultisig(m, n, keys) {
return new Script().fromMultisig(m, n, keys);
};
/**
* Inject properties from a pay-to-scripthash script.
* @private
* @param {Buffer} hash
*/
Script.prototype.fromScripthash = function fromScripthash(hash) {
assert(Buffer.isBuffer(hash) && hash.length === 20);
return this.fromArray([
opcodes.OP_HASH160,
hash,
opcodes.OP_EQUAL
]);
};
/**
@ -2500,11 +2588,21 @@ Script.fromMultisig = function fromMultisig(m, n, keys) {
*/
Script.fromScripthash = function fromScripthash(hash) {
assert(Buffer.isBuffer(hash) && hash.length === 20);
return Script.fromArray([
opcodes.OP_HASH160,
hash,
opcodes.OP_EQUAL
return new Script().fromScripthash(hash);
};
/**
* Inject properties from a nulldata/opreturn script.
* @private
* @param {Buffer} flags
*/
Script.prototype.fromNulldata = function fromNulldata(flags) {
assert(Buffer.isBuffer(flags));
assert(flags.length <= constants.script.MAX_OP_RETURN, 'Nulldata too large.');
return this.fromArray([
opcodes.OP_RETURN,
flags
]);
};
@ -2515,12 +2613,20 @@ Script.fromScripthash = function fromScripthash(hash) {
*/
Script.fromNulldata = function fromNulldata(flags) {
assert(Buffer.isBuffer(flags));
assert(flags.length <= constants.script.MAX_OP_RETURN, 'Nulldata too large.');
return Script.fromArray([
opcodes.OP_RETURN,
flags
]);
return new Script().fromNulldata(flags);
};
/**
* Inject properties from a witness program.
* @private
* @param {Number} version
* @param {Buffer} data
*/
Script.prototype.fromProgram = function fromProgram(version, data) {
assert(utils.isNumber(version) && version >= 0 && version <= 16);
assert(Buffer.isBuffer(data) && data.length >= 2 && data.length <= 40);
return this.fromArray([version === 0 ? 0 : version + 0x50, data]);
};
/**
@ -2531,9 +2637,32 @@ Script.fromNulldata = function fromNulldata(flags) {
*/
Script.fromProgram = function fromProgram(version, data) {
assert(utils.isNumber(version) && version >= 0 && version <= 16);
assert(Buffer.isBuffer(data) && data.length >= 2 && data.length <= 40);
return Script.fromArray([version === 0 ? 0 : version + 0x50, data]);
return new Script().fromProgram(version, data);
};
/**
* Inject properties from an address.
* @private
* @param {Address|Base58Address} address
*/
Script.prototype.fromAddress = function fromAddress(address) {
if (typeof address === 'string')
address = bcoin.address.fromBase58(address);
if (!address)
throw new Error('Unknown address type.');
if (address.type === 'pubkeyhash')
return this.fromPubkeyhash(address.hash);
if (address.type === 'scripthash')
return this.fromScripthash(address.hash);
if (address.version !== -1)
return this.fromProgram(address.version, address.hash);
assert(false, 'Bad address type.');
};
/**
@ -2543,32 +2672,17 @@ Script.fromProgram = function fromProgram(version, data) {
*/
Script.fromAddress = function fromAddress(address) {
if (typeof address === 'string')
address = bcoin.address.fromBase58(address);
if (!address)
throw new Error('Unknown address type.');
if (address.type === 'pubkeyhash')
return Script.fromPubkeyhash(address.hash);
if (address.type === 'scripthash')
return Script.fromScripthash(address.hash);
if (address.version !== -1)
return Script.fromProgram(address.version, address.hash);
assert(false, 'Bad address type.');
return new Script().fromAddress(address);
};
/**
* Create a witness block commitment.
* Inject properties from a witness block commitment.
* @private
* @param {Buffer} hash
* @param {String|Buffer} flags
* @returns {Script}
*/
Script.fromCommitment = function fromCommitment(hash, flags) {
Script.prototype.fromCommitment = function fromCommitment(hash, flags) {
var p;
if (!flags)
@ -2581,13 +2695,24 @@ Script.fromCommitment = function fromCommitment(hash, flags) {
p.writeU32BE(0xaa21a9ed);
p.writeHash(hash);
return Script.fromArray([
return this.fromArray([
opcodes.OP_RETURN,
p.render(),
flags
]);
};
/**
* Create a witness block commitment.
* @param {Buffer} hash
* @param {String|Buffer} flags
* @returns {Script}
*/
Script.fromCommitment = function fromCommitment(hash, flags) {
return new Script().fromCommitment(hash, flags);
};
/**
* Grab and deserialize the redeem script.
* @returns {Script|null} Redeem script.
@ -3336,6 +3461,14 @@ Script.prototype.getString = function getString(i) {
return op.data.toString('utf8');
};
/**
* Clear the script code.
*/
Script.prototype.clear = function clear() {
this.code.length = 0;
};
/**
* Set an item in the `code` array.
* @param {Number} index