broadcast witness txs correctly.

This commit is contained in:
Christopher Jeffrey 2016-03-29 16:14:39 -07:00
parent 00e7fcc1ad
commit 5dc7030ac4
5 changed files with 106 additions and 33 deletions

View File

@ -178,6 +178,18 @@ Fullnode.prototype._init = function _init() {
this.http.open(load);
};
Fullnode.prototype.broadcast = function broadcast(item, callback) {
return this.pool.broadcast(item, callback);
};
Fullnode.prototype.sendTX = function sendTX(item, callback) {
return this.pool.sendTX(item, callback);
};
Fullnode.prototype.sendBlock = function sendBlock(item, callback) {
return this.pool.sendBlock(item, callback);
};
Fullnode.prototype.startSync = function startSync() {
return this.pool.startSync();
};

View File

@ -50,6 +50,7 @@ function Mempool(node, options) {
this.relayPriority = this.options.relayPriority !== false;
this.requireStandard = this.options.requireStandard !== false;
this.rejectInsaneFees = this.options.rejectInsaneFees !== false;
this.relay = this.options.relay || false;
Mempool.global = this;
@ -400,6 +401,9 @@ Mempool.prototype.addUnchecked = function addUnchecked(tx, peer, callback) {
utils.debug('Added tx %s to the mempool.', tx.rhash);
if (self.options.relay)
self.node.broadcast(tx);
self.resolveOrphans(tx, function(err, resolved) {
if (err)
return callback(err);

View File

@ -39,6 +39,14 @@ MerkleBlock.prototype.render = function render() {
return this.getRaw();
};
MerkleBlock.prototype.renderNormal = function renderNormal() {
return this.getRaw();
};
MerkleBlock.prototype.renderWitness = function renderWitness() {
return this.getRaw();
};
MerkleBlock.prototype.getSize = function getSize() {
if (this._size == null)
this.getRaw();

View File

@ -212,7 +212,8 @@ Peer.prototype.createSocket = function createSocket(port, host) {
Peer.prototype.broadcast = function broadcast(items) {
var self = this;
var result;
var result = [];
var payload = [];
if (this.destroyed)
return;
@ -220,21 +221,35 @@ Peer.prototype.broadcast = function broadcast(items) {
if (!Array.isArray(items))
items = [items];
result = items.map(function(item) {
items.forEach(function(item) {
var key = item.hash('hex');
var old = this._broadcast.map[key];
var type = item.type;
var entry, packetType;
if (old) {
clearTimeout(old.timer);
clearInterval(old.interval);
}
var inv = this.framer.inv([{
type: item.type,
hash: item.hash()
}]);
if (typeof type === 'string')
type = constants.inv[type];
// INV does not set the witness
// mask (only GETDATA does this).
type &= ~constants.invWitnessMask;
if (type === constants.inv.block)
packetType = 'block';
else if (type === constants.inv.tx)
packetType = 'tx';
else if (type === constants.inv.filtered)
packetType = 'merkleblock';
else
assert(false, 'Bad type.');
// Auto-cleanup broadcast map after timeout
var entry = {
entry = {
e: new EventEmitter(),
timeout: setTimeout(function() {
entry.e.emit('timeout');
@ -244,24 +259,31 @@ Peer.prototype.broadcast = function broadcast(items) {
// Retransmit
interval: setInterval(function() {
self._write(inv);
self._write(entry.inv);
}, this._broadcast.interval),
type: item.type,
value: item.render()
inv: this.framer.inv([{
type: type,
hash: item.hash()
}]),
packetType: packetType,
type: type,
hash: item.hash(),
msg: item
};
this._broadcast.map[key] = entry;
return entry.e;
result.push(entry.e);
payload.push({
type: entry.type,
hash: entry.hash
});
}, this);
this._write(this.framer.inv(items.map(function(item) {
return {
type: item.type,
hash: item.hash()
};
})));
this._write(this.framer.inv(payload));
return result;
};
@ -493,13 +515,41 @@ Peer.prototype._handleGetData = function handleGetData(items) {
items.forEach(function(item) {
// Filter out not broadcasted things
var hash = utils.toHex(item.hash);
var entry = this._broadcast.map[hash];
var isWitness = item.type & constants.invWitnessMask;
var value;
if (!this._broadcast.map[hash])
if (!entry)
return;
var entry = this._broadcast.map[hash];
if ((item.type & ~constants.invWitnessMask) !== entry.type) {
utils.debug(
'Peer %s requested an existing item with the wrong type.',
this.host);
return;
}
this._write(this.framer.packet(entry.type, entry.value));
if (isWitness) {
if (!entry.witnessValue)
entry.witnessValue = entry.msg.renderWitness();
value = entry.witnessValue;
} else {
if (!entry.value)
entry.value = entry.msg.renderNormal();
value = entry.value;
}
utils.debug(
'Peer %s requested %s:%s as a %s packet.',
this.host,
entry.packetType,
utils.revHex(utils.toHex(entry.hash)),
isWitness ? 'witness' : 'normal');
if (entry.value && entry.witnessValue)
delete entry.msg;
this._write(this.framer.packet(entry.packetType, value));
entry.e.emit('request');
}, this);

View File

@ -231,7 +231,6 @@ Parser.parseInvList = function parseInvList(p) {
for (i = 0; i < count; i++) {
items.push({
// type: constants.invByVal[p.readU32()],
type: p.readU32(),
hash: p.readHash()
});
@ -250,8 +249,8 @@ Parser.parseMerkleBlock = function parseMerkleBlock(p) {
p.start();
version = p.read32();
prevBlock = p.readHash('hex');
merkleRoot = p.readHash('hex');
prevBlock = p.readHash();
merkleRoot = p.readHash();
ts = p.readU32();
bits = p.readU32();
nonce = p.readU32();
@ -262,7 +261,7 @@ Parser.parseMerkleBlock = function parseMerkleBlock(p) {
hashes = new Array(hashCount);
for (i = 0; i < hashCount; i++)
hashes[i] = p.readHash('hex');
hashes[i] = p.readHash();
flags = p.readVarBytes();
@ -292,8 +291,8 @@ Parser.parseHeaders = function parseHeaders(p) {
for (i = 0; i < count; i++) {
headers.push({
version: p.read32(),
prevBlock: p.readHash('hex'),
merkleRoot: p.readHash('hex'),
prevBlock: p.readHash(),
merkleRoot: p.readHash(),
ts: p.readU32(),
bits: p.readU32(),
nonce: p.readU32(),
@ -316,8 +315,8 @@ Parser.parseBlock = function parseBlock(p) {
p.start();
version = p.read32();
prevBlock = p.readHash('hex');
merkleRoot = p.readHash('hex');
prevBlock = p.readHash();
merkleRoot = p.readHash();
ts = p.readU32();
bits = p.readU32();
nonce = p.readU32();
@ -351,8 +350,8 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
p.start();
version = p.read32();
prevBlock = p.readHash('hex');
merkleRoot = p.readHash('hex');
prevBlock = p.readHash();
merkleRoot = p.readHash();
ts = p.readU32();
bits = p.readU32();
nonce = p.readU32();
@ -403,7 +402,7 @@ Parser.parseInput = function parseInput(p) {
p = new BufferReader(p);
p.start();
hash = p.readHash('hex');
hash = p.readHash();
index = p.readU32();
script = Parser.parseScript(p);
sequence = p.readU32();
@ -472,7 +471,7 @@ Parser.parseCoin = function parseCoin(p, extended) {
coinbase = p.readU8() === 1;
if (extended) {
hash = p.readHash('hex');
hash = p.readHash();
index = p.readU32();
}
@ -655,7 +654,7 @@ Parser.parseReject = function parseReject(p) {
reason = p.readVarString('ascii');
try {
data = p.readHash('hex');
data = p.readHash();
} catch (e) {
data = null;
}