segwit parsing and framing.

This commit is contained in:
Christopher Jeffrey 2016-02-26 15:04:34 -08:00
parent 5d1f6089ed
commit 5a8e2b80f3
4 changed files with 81 additions and 34 deletions

View File

@ -122,6 +122,32 @@ Block.prototype.getWitnessRoot = function getWitnessRoot() {
return utils.toHex(root);
};
Block.prototype.__defineGetter__('witnessRoot', function() {
var coinbase, i, commitment, witnessRoot;
if (!block.witness)
return;
if (this._witnessRoot)
return this._witnessRoot;
coinbase = block.txs[0];
// Find the fucking commitment for segregated shitness
for (i = 0; i < coinbase.outputs.length; i++) {
commitment = coinbase.outputs[i].script;
if (bcoin.script.isCommitment(commitment)) {
witnessRoot = bcoin.script.getWitnessRoot(commitment);
break;
}
}
if (witnessRoot)
this._witnessRoot = utils.toHex(witnessRoot);
return this._witnessRoot;
});
Block.prototype._verify = function _verify() {
var uniq = {};
var i, tx, hash;
@ -275,6 +301,7 @@ Block.prototype.inspect = function inspect() {
version: this.version,
prevBlock: utils.revHex(this.prevBlock),
merkleRoot: utils.revHex(this.merkleRoot),
witnessRoot: utils.revHex(this.witnessRoot),
ts: this.ts,
bits: this.bits,
nonce: this.nonce,
@ -291,6 +318,7 @@ Block.prototype.toJSON = function toJSON() {
version: this.version,
prevBlock: utils.revHex(this.prevBlock),
merkleRoot: utils.revHex(this.merkleRoot),
witnessRoot: utils.revHex(this.witnessRoot),
ts: this.ts,
bits: this.bits,
nonce: this.nonce,

View File

@ -573,19 +573,10 @@ Chain.prototype._verify = function _verify(block, prev) {
}
}
// Find the fucking commitment for segregated shitness
if (segwit && block.witness) {
coinbase = block.txs[0];
for (i = 0; i < coinbase.outputs.length; i++) {
commitment = coinbase.outputs[i].script;
if (bcoin.script.isCommitment(commitment)) {
witnessRoot = bcoin.script.getWitnessRoot(commitment);
if (utils.toHex(witnessRoot) !== block.getWitnessRoot()) {
utils.debug('Block failed witnessroot test: %s', block.rhash);
return false;
}
break;
}
if (block.witnessRoot !== block.getWitnessRoot()) {
utils.debug('Block failed witnessroot test: %s', block.rhash);
return false;
}
}

View File

@ -111,13 +111,21 @@ Framer.prototype.coin = function _coin(coin) {
};
Framer.prototype.tx = function tx(tx) {
return this.packet('tx', Framer.tx(block));
return this.packet('tx', Framer.tx(tx));
};
Framer.prototype.witnessTX = function witnessTX(tx) {
return this.packet('tx', Framer.witnessTX(tx));
};
Framer.prototype.block = function _block(block) {
return this.packet('block', Framer.block(block));
};
Framer.prototype.witnessBlock = function witnessBlock(block) {
return this.packet('block', Framer.witnessBlock(block));
};
Framer.prototype.merkleBlock = function merkleBlock(block) {
return this.packet('merkleblock', Framer.merkleBlock(block));
};
@ -543,7 +551,7 @@ Framer.witness = function _witness(witness) {
if (!witness)
return new Buffer([0]);
size += utils.writeIntv(witness.length);
size += utils.sizeIntv(witness.length);
for (i = 0; i < witness.length; i++) {
chunk = witness[i];
@ -552,6 +560,8 @@ Framer.witness = function _witness(witness) {
p = new Buffer(size);
off += utils.writeIntv(p, witness.length, off);
for (i = 0; i < witness.length; i++) {
chunk = witness[i];
off += utils.writeIntv(p, chunk.length, off);
@ -576,7 +586,7 @@ Framer._block = function _block(block, witness) {
var i, tx, p;
for (i = 0; i < block.txs.length; i++) {
tx = witness && block.txs[i].witness
tx = witness
? Framer.witnessTX(block.txs[i])
: Framer.tx(block.txs[i]);
txs.push(tx);

View File

@ -521,9 +521,10 @@ Parser.parseCoin = function parseCoin(p, extended) {
};
Parser.parseTX = function parseTX(p) {
var inCount, off, txIn, tx;
var off = 0;
var inCount, txIn, tx;
var outCount, txOut;
var i;
var version, locktime, i;
if (p.length < 10)
throw new Error('Invalid tx size');
@ -531,7 +532,10 @@ Parser.parseTX = function parseTX(p) {
if (Parser.isWitnessTX(p))
return Parser.parseWitnessTX(p);
inCount = utils.readIntv(p, 4);
version = utils.readU32(p, off);
off += 4;
inCount = utils.readIntv(p, off);
off = inCount.off;
inCount = inCount.r;
@ -579,14 +583,18 @@ Parser.parseTX = function parseTX(p) {
throw new Error('Invalid tx_out offset');
}
locktime = utils.readU32(p, off);
off += 4;
return {
version: utils.read32(p, 0),
witness: false,
version: version,
inputs: txIn,
outputs: txOut,
locktime: utils.readU32(p, off),
_cost: (off + 4) * 4,
_raw: p.slice(0, off + 4),
_size: off + 4
locktime: locktime,
_cost: off * 4,
_raw: p.length !== off ? p.slice(0, off) : p,
_size: off
};
};
@ -599,16 +607,21 @@ Parser.isWitnessTX = function isWitnessTX(p) {
Parser.parseWitnessTX = function parseWitnessTX(p) {
var cost = 0;
var inCount, off, txIn, tx;
var off = 0;
var inCount, txIn, tx;
var outCount, txOut;
var marker, flag;
var i;
var version, locktime, i;
if (p.length < 12)
throw new Error('Invalid witness tx size');
marker = utils.readU8(p, 4);
flag = utils.readU8(p, 5);
version = utils.readU32(p, off);
off += 4;
marker = utils.readU8(p, off);
off += 1;
flag = utils.readU8(p, off);
off += 1;
if (marker !== 0)
throw new Error('Invalid witness tx (marker != 0)');
@ -616,7 +629,7 @@ Parser.parseWitnessTX = function parseWitnessTX(p) {
if (flag === 0)
throw new Error('Invalid witness tx (flag == 0)');
inCount = utils.readIntv(p, 6);
inCount = utils.readIntv(p, off);
off = inCount.off;
inCount = inCount.r;
@ -682,25 +695,30 @@ Parser.parseWitnessTX = function parseWitnessTX(p) {
throw new Error('Invalid witness offset');
}
locktime = utils.readU32(p, off);
off += 4;
cost += 4 * 4;
return {
witness: true,
version: utils.read32(p, 0),
version: version,
marker: marker,
flag: flag,
inputs: txIn,
outputs: txOut,
locktime: utils.readU32(p, off),
_raw: p.slice(0, off + 4),
_size: off + 4,
locktime: locktime,
_raw: off !== p.length ? p.slice(0, off) : p,
_size: off,
_cost: cost
};
};
Parser.parseWitness = function parseWitness(p) {
var witness = [];
var off, chunkCount, chunkSize, item, i;
var off = 0;
var chunkCount, chunkSize, item, i;
chunkCount = utils.readIntv(p, 0);
chunkCount = utils.readIntv(p, off);
off = chunkCount.off;
chunkCount = chunkCount.r;