segwit parsing and framing.
This commit is contained in:
parent
5d1f6089ed
commit
5a8e2b80f3
@ -122,6 +122,32 @@ Block.prototype.getWitnessRoot = function getWitnessRoot() {
|
|||||||
return utils.toHex(root);
|
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() {
|
Block.prototype._verify = function _verify() {
|
||||||
var uniq = {};
|
var uniq = {};
|
||||||
var i, tx, hash;
|
var i, tx, hash;
|
||||||
@ -275,6 +301,7 @@ Block.prototype.inspect = function inspect() {
|
|||||||
version: this.version,
|
version: this.version,
|
||||||
prevBlock: utils.revHex(this.prevBlock),
|
prevBlock: utils.revHex(this.prevBlock),
|
||||||
merkleRoot: utils.revHex(this.merkleRoot),
|
merkleRoot: utils.revHex(this.merkleRoot),
|
||||||
|
witnessRoot: utils.revHex(this.witnessRoot),
|
||||||
ts: this.ts,
|
ts: this.ts,
|
||||||
bits: this.bits,
|
bits: this.bits,
|
||||||
nonce: this.nonce,
|
nonce: this.nonce,
|
||||||
@ -291,6 +318,7 @@ Block.prototype.toJSON = function toJSON() {
|
|||||||
version: this.version,
|
version: this.version,
|
||||||
prevBlock: utils.revHex(this.prevBlock),
|
prevBlock: utils.revHex(this.prevBlock),
|
||||||
merkleRoot: utils.revHex(this.merkleRoot),
|
merkleRoot: utils.revHex(this.merkleRoot),
|
||||||
|
witnessRoot: utils.revHex(this.witnessRoot),
|
||||||
ts: this.ts,
|
ts: this.ts,
|
||||||
bits: this.bits,
|
bits: this.bits,
|
||||||
nonce: this.nonce,
|
nonce: this.nonce,
|
||||||
|
|||||||
@ -573,19 +573,10 @@ Chain.prototype._verify = function _verify(block, prev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the fucking commitment for segregated shitness
|
|
||||||
if (segwit && block.witness) {
|
if (segwit && block.witness) {
|
||||||
coinbase = block.txs[0];
|
if (block.witnessRoot !== block.getWitnessRoot()) {
|
||||||
for (i = 0; i < coinbase.outputs.length; i++) {
|
utils.debug('Block failed witnessroot test: %s', block.rhash);
|
||||||
commitment = coinbase.outputs[i].script;
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -111,13 +111,21 @@ Framer.prototype.coin = function _coin(coin) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Framer.prototype.tx = function tx(tx) {
|
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) {
|
Framer.prototype.block = function _block(block) {
|
||||||
return this.packet('block', Framer.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) {
|
Framer.prototype.merkleBlock = function merkleBlock(block) {
|
||||||
return this.packet('merkleblock', Framer.merkleBlock(block));
|
return this.packet('merkleblock', Framer.merkleBlock(block));
|
||||||
};
|
};
|
||||||
@ -543,7 +551,7 @@ Framer.witness = function _witness(witness) {
|
|||||||
if (!witness)
|
if (!witness)
|
||||||
return new Buffer([0]);
|
return new Buffer([0]);
|
||||||
|
|
||||||
size += utils.writeIntv(witness.length);
|
size += utils.sizeIntv(witness.length);
|
||||||
|
|
||||||
for (i = 0; i < witness.length; i++) {
|
for (i = 0; i < witness.length; i++) {
|
||||||
chunk = witness[i];
|
chunk = witness[i];
|
||||||
@ -552,6 +560,8 @@ Framer.witness = function _witness(witness) {
|
|||||||
|
|
||||||
p = new Buffer(size);
|
p = new Buffer(size);
|
||||||
|
|
||||||
|
off += utils.writeIntv(p, witness.length, off);
|
||||||
|
|
||||||
for (i = 0; i < witness.length; i++) {
|
for (i = 0; i < witness.length; i++) {
|
||||||
chunk = witness[i];
|
chunk = witness[i];
|
||||||
off += utils.writeIntv(p, chunk.length, off);
|
off += utils.writeIntv(p, chunk.length, off);
|
||||||
@ -576,7 +586,7 @@ Framer._block = function _block(block, witness) {
|
|||||||
var i, tx, p;
|
var i, tx, p;
|
||||||
|
|
||||||
for (i = 0; i < block.txs.length; i++) {
|
for (i = 0; i < block.txs.length; i++) {
|
||||||
tx = witness && block.txs[i].witness
|
tx = witness
|
||||||
? Framer.witnessTX(block.txs[i])
|
? Framer.witnessTX(block.txs[i])
|
||||||
: Framer.tx(block.txs[i]);
|
: Framer.tx(block.txs[i]);
|
||||||
txs.push(tx);
|
txs.push(tx);
|
||||||
|
|||||||
@ -521,9 +521,10 @@ Parser.parseCoin = function parseCoin(p, extended) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Parser.parseTX = function parseTX(p) {
|
Parser.parseTX = function parseTX(p) {
|
||||||
var inCount, off, txIn, tx;
|
var off = 0;
|
||||||
|
var inCount, txIn, tx;
|
||||||
var outCount, txOut;
|
var outCount, txOut;
|
||||||
var i;
|
var version, locktime, i;
|
||||||
|
|
||||||
if (p.length < 10)
|
if (p.length < 10)
|
||||||
throw new Error('Invalid tx size');
|
throw new Error('Invalid tx size');
|
||||||
@ -531,7 +532,10 @@ Parser.parseTX = function parseTX(p) {
|
|||||||
if (Parser.isWitnessTX(p))
|
if (Parser.isWitnessTX(p))
|
||||||
return Parser.parseWitnessTX(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;
|
off = inCount.off;
|
||||||
inCount = inCount.r;
|
inCount = inCount.r;
|
||||||
|
|
||||||
@ -579,14 +583,18 @@ Parser.parseTX = function parseTX(p) {
|
|||||||
throw new Error('Invalid tx_out offset');
|
throw new Error('Invalid tx_out offset');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locktime = utils.readU32(p, off);
|
||||||
|
off += 4;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version: utils.read32(p, 0),
|
witness: false,
|
||||||
|
version: version,
|
||||||
inputs: txIn,
|
inputs: txIn,
|
||||||
outputs: txOut,
|
outputs: txOut,
|
||||||
locktime: utils.readU32(p, off),
|
locktime: locktime,
|
||||||
_cost: (off + 4) * 4,
|
_cost: off * 4,
|
||||||
_raw: p.slice(0, off + 4),
|
_raw: p.length !== off ? p.slice(0, off) : p,
|
||||||
_size: off + 4
|
_size: off
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -599,16 +607,21 @@ Parser.isWitnessTX = function isWitnessTX(p) {
|
|||||||
|
|
||||||
Parser.parseWitnessTX = function parseWitnessTX(p) {
|
Parser.parseWitnessTX = function parseWitnessTX(p) {
|
||||||
var cost = 0;
|
var cost = 0;
|
||||||
var inCount, off, txIn, tx;
|
var off = 0;
|
||||||
|
var inCount, txIn, tx;
|
||||||
var outCount, txOut;
|
var outCount, txOut;
|
||||||
var marker, flag;
|
var marker, flag;
|
||||||
var i;
|
var version, locktime, i;
|
||||||
|
|
||||||
if (p.length < 12)
|
if (p.length < 12)
|
||||||
throw new Error('Invalid witness tx size');
|
throw new Error('Invalid witness tx size');
|
||||||
|
|
||||||
marker = utils.readU8(p, 4);
|
version = utils.readU32(p, off);
|
||||||
flag = utils.readU8(p, 5);
|
off += 4;
|
||||||
|
marker = utils.readU8(p, off);
|
||||||
|
off += 1;
|
||||||
|
flag = utils.readU8(p, off);
|
||||||
|
off += 1;
|
||||||
|
|
||||||
if (marker !== 0)
|
if (marker !== 0)
|
||||||
throw new Error('Invalid witness tx (marker != 0)');
|
throw new Error('Invalid witness tx (marker != 0)');
|
||||||
@ -616,7 +629,7 @@ Parser.parseWitnessTX = function parseWitnessTX(p) {
|
|||||||
if (flag === 0)
|
if (flag === 0)
|
||||||
throw new Error('Invalid witness tx (flag == 0)');
|
throw new Error('Invalid witness tx (flag == 0)');
|
||||||
|
|
||||||
inCount = utils.readIntv(p, 6);
|
inCount = utils.readIntv(p, off);
|
||||||
off = inCount.off;
|
off = inCount.off;
|
||||||
inCount = inCount.r;
|
inCount = inCount.r;
|
||||||
|
|
||||||
@ -682,25 +695,30 @@ Parser.parseWitnessTX = function parseWitnessTX(p) {
|
|||||||
throw new Error('Invalid witness offset');
|
throw new Error('Invalid witness offset');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locktime = utils.readU32(p, off);
|
||||||
|
off += 4;
|
||||||
|
cost += 4 * 4;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
witness: true,
|
witness: true,
|
||||||
version: utils.read32(p, 0),
|
version: version,
|
||||||
marker: marker,
|
marker: marker,
|
||||||
flag: flag,
|
flag: flag,
|
||||||
inputs: txIn,
|
inputs: txIn,
|
||||||
outputs: txOut,
|
outputs: txOut,
|
||||||
locktime: utils.readU32(p, off),
|
locktime: locktime,
|
||||||
_raw: p.slice(0, off + 4),
|
_raw: off !== p.length ? p.slice(0, off) : p,
|
||||||
_size: off + 4,
|
_size: off,
|
||||||
_cost: cost
|
_cost: cost
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.parseWitness = function parseWitness(p) {
|
Parser.parseWitness = function parseWitness(p) {
|
||||||
var witness = [];
|
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;
|
off = chunkCount.off;
|
||||||
chunkCount = chunkCount.r;
|
chunkCount = chunkCount.r;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user