broadcast witness txs correctly.
This commit is contained in:
parent
00e7fcc1ad
commit
5dc7030ac4
@ -178,6 +178,18 @@ Fullnode.prototype._init = function _init() {
|
|||||||
this.http.open(load);
|
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() {
|
Fullnode.prototype.startSync = function startSync() {
|
||||||
return this.pool.startSync();
|
return this.pool.startSync();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -50,6 +50,7 @@ function Mempool(node, options) {
|
|||||||
this.relayPriority = this.options.relayPriority !== false;
|
this.relayPriority = this.options.relayPriority !== false;
|
||||||
this.requireStandard = this.options.requireStandard !== false;
|
this.requireStandard = this.options.requireStandard !== false;
|
||||||
this.rejectInsaneFees = this.options.rejectInsaneFees !== false;
|
this.rejectInsaneFees = this.options.rejectInsaneFees !== false;
|
||||||
|
this.relay = this.options.relay || false;
|
||||||
|
|
||||||
Mempool.global = this;
|
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);
|
utils.debug('Added tx %s to the mempool.', tx.rhash);
|
||||||
|
|
||||||
|
if (self.options.relay)
|
||||||
|
self.node.broadcast(tx);
|
||||||
|
|
||||||
self.resolveOrphans(tx, function(err, resolved) {
|
self.resolveOrphans(tx, function(err, resolved) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|||||||
@ -39,6 +39,14 @@ MerkleBlock.prototype.render = function render() {
|
|||||||
return this.getRaw();
|
return this.getRaw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MerkleBlock.prototype.renderNormal = function renderNormal() {
|
||||||
|
return this.getRaw();
|
||||||
|
};
|
||||||
|
|
||||||
|
MerkleBlock.prototype.renderWitness = function renderWitness() {
|
||||||
|
return this.getRaw();
|
||||||
|
};
|
||||||
|
|
||||||
MerkleBlock.prototype.getSize = function getSize() {
|
MerkleBlock.prototype.getSize = function getSize() {
|
||||||
if (this._size == null)
|
if (this._size == null)
|
||||||
this.getRaw();
|
this.getRaw();
|
||||||
|
|||||||
@ -212,7 +212,8 @@ Peer.prototype.createSocket = function createSocket(port, host) {
|
|||||||
|
|
||||||
Peer.prototype.broadcast = function broadcast(items) {
|
Peer.prototype.broadcast = function broadcast(items) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var result;
|
var result = [];
|
||||||
|
var payload = [];
|
||||||
|
|
||||||
if (this.destroyed)
|
if (this.destroyed)
|
||||||
return;
|
return;
|
||||||
@ -220,21 +221,35 @@ Peer.prototype.broadcast = function broadcast(items) {
|
|||||||
if (!Array.isArray(items))
|
if (!Array.isArray(items))
|
||||||
items = [items];
|
items = [items];
|
||||||
|
|
||||||
result = items.map(function(item) {
|
items.forEach(function(item) {
|
||||||
var key = item.hash('hex');
|
var key = item.hash('hex');
|
||||||
var old = this._broadcast.map[key];
|
var old = this._broadcast.map[key];
|
||||||
|
var type = item.type;
|
||||||
|
var entry, packetType;
|
||||||
|
|
||||||
if (old) {
|
if (old) {
|
||||||
clearTimeout(old.timer);
|
clearTimeout(old.timer);
|
||||||
clearInterval(old.interval);
|
clearInterval(old.interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
var inv = this.framer.inv([{
|
if (typeof type === 'string')
|
||||||
type: item.type,
|
type = constants.inv[type];
|
||||||
hash: item.hash()
|
|
||||||
}]);
|
// 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
|
// Auto-cleanup broadcast map after timeout
|
||||||
var entry = {
|
entry = {
|
||||||
e: new EventEmitter(),
|
e: new EventEmitter(),
|
||||||
timeout: setTimeout(function() {
|
timeout: setTimeout(function() {
|
||||||
entry.e.emit('timeout');
|
entry.e.emit('timeout');
|
||||||
@ -244,24 +259,31 @@ Peer.prototype.broadcast = function broadcast(items) {
|
|||||||
|
|
||||||
// Retransmit
|
// Retransmit
|
||||||
interval: setInterval(function() {
|
interval: setInterval(function() {
|
||||||
self._write(inv);
|
self._write(entry.inv);
|
||||||
}, this._broadcast.interval),
|
}, this._broadcast.interval),
|
||||||
|
|
||||||
type: item.type,
|
inv: this.framer.inv([{
|
||||||
value: item.render()
|
type: type,
|
||||||
|
hash: item.hash()
|
||||||
|
}]),
|
||||||
|
|
||||||
|
packetType: packetType,
|
||||||
|
type: type,
|
||||||
|
hash: item.hash(),
|
||||||
|
msg: item
|
||||||
};
|
};
|
||||||
|
|
||||||
this._broadcast.map[key] = entry;
|
this._broadcast.map[key] = entry;
|
||||||
|
|
||||||
return entry.e;
|
result.push(entry.e);
|
||||||
|
|
||||||
|
payload.push({
|
||||||
|
type: entry.type,
|
||||||
|
hash: entry.hash
|
||||||
|
});
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this._write(this.framer.inv(items.map(function(item) {
|
this._write(this.framer.inv(payload));
|
||||||
return {
|
|
||||||
type: item.type,
|
|
||||||
hash: item.hash()
|
|
||||||
};
|
|
||||||
})));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@ -493,13 +515,41 @@ Peer.prototype._handleGetData = function handleGetData(items) {
|
|||||||
items.forEach(function(item) {
|
items.forEach(function(item) {
|
||||||
// Filter out not broadcasted things
|
// Filter out not broadcasted things
|
||||||
var hash = utils.toHex(item.hash);
|
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;
|
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');
|
entry.e.emit('request');
|
||||||
}, this);
|
}, this);
|
||||||
|
|||||||
@ -231,7 +231,6 @@ Parser.parseInvList = function parseInvList(p) {
|
|||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
items.push({
|
items.push({
|
||||||
// type: constants.invByVal[p.readU32()],
|
|
||||||
type: p.readU32(),
|
type: p.readU32(),
|
||||||
hash: p.readHash()
|
hash: p.readHash()
|
||||||
});
|
});
|
||||||
@ -250,8 +249,8 @@ Parser.parseMerkleBlock = function parseMerkleBlock(p) {
|
|||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
version = p.read32();
|
version = p.read32();
|
||||||
prevBlock = p.readHash('hex');
|
prevBlock = p.readHash();
|
||||||
merkleRoot = p.readHash('hex');
|
merkleRoot = p.readHash();
|
||||||
ts = p.readU32();
|
ts = p.readU32();
|
||||||
bits = p.readU32();
|
bits = p.readU32();
|
||||||
nonce = p.readU32();
|
nonce = p.readU32();
|
||||||
@ -262,7 +261,7 @@ Parser.parseMerkleBlock = function parseMerkleBlock(p) {
|
|||||||
hashes = new Array(hashCount);
|
hashes = new Array(hashCount);
|
||||||
|
|
||||||
for (i = 0; i < hashCount; i++)
|
for (i = 0; i < hashCount; i++)
|
||||||
hashes[i] = p.readHash('hex');
|
hashes[i] = p.readHash();
|
||||||
|
|
||||||
flags = p.readVarBytes();
|
flags = p.readVarBytes();
|
||||||
|
|
||||||
@ -292,8 +291,8 @@ Parser.parseHeaders = function parseHeaders(p) {
|
|||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
headers.push({
|
headers.push({
|
||||||
version: p.read32(),
|
version: p.read32(),
|
||||||
prevBlock: p.readHash('hex'),
|
prevBlock: p.readHash(),
|
||||||
merkleRoot: p.readHash('hex'),
|
merkleRoot: p.readHash(),
|
||||||
ts: p.readU32(),
|
ts: p.readU32(),
|
||||||
bits: p.readU32(),
|
bits: p.readU32(),
|
||||||
nonce: p.readU32(),
|
nonce: p.readU32(),
|
||||||
@ -316,8 +315,8 @@ Parser.parseBlock = function parseBlock(p) {
|
|||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
version = p.read32();
|
version = p.read32();
|
||||||
prevBlock = p.readHash('hex');
|
prevBlock = p.readHash();
|
||||||
merkleRoot = p.readHash('hex');
|
merkleRoot = p.readHash();
|
||||||
ts = p.readU32();
|
ts = p.readU32();
|
||||||
bits = p.readU32();
|
bits = p.readU32();
|
||||||
nonce = p.readU32();
|
nonce = p.readU32();
|
||||||
@ -351,8 +350,8 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
|
|||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
version = p.read32();
|
version = p.read32();
|
||||||
prevBlock = p.readHash('hex');
|
prevBlock = p.readHash();
|
||||||
merkleRoot = p.readHash('hex');
|
merkleRoot = p.readHash();
|
||||||
ts = p.readU32();
|
ts = p.readU32();
|
||||||
bits = p.readU32();
|
bits = p.readU32();
|
||||||
nonce = p.readU32();
|
nonce = p.readU32();
|
||||||
@ -403,7 +402,7 @@ Parser.parseInput = function parseInput(p) {
|
|||||||
p = new BufferReader(p);
|
p = new BufferReader(p);
|
||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
hash = p.readHash('hex');
|
hash = p.readHash();
|
||||||
index = p.readU32();
|
index = p.readU32();
|
||||||
script = Parser.parseScript(p);
|
script = Parser.parseScript(p);
|
||||||
sequence = p.readU32();
|
sequence = p.readU32();
|
||||||
@ -472,7 +471,7 @@ Parser.parseCoin = function parseCoin(p, extended) {
|
|||||||
coinbase = p.readU8() === 1;
|
coinbase = p.readU8() === 1;
|
||||||
|
|
||||||
if (extended) {
|
if (extended) {
|
||||||
hash = p.readHash('hex');
|
hash = p.readHash();
|
||||||
index = p.readU32();
|
index = p.readU32();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,7 +654,7 @@ Parser.parseReject = function parseReject(p) {
|
|||||||
reason = p.readVarString('ascii');
|
reason = p.readVarString('ascii');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
data = p.readHash('hex');
|
data = p.readHash();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
data = null;
|
data = null;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user