mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-14 11:15:51 +00:00
Peer: When using GetData for transactions, request witnesses if available.
This commit is contained in:
parent
53a63c43bb
commit
be4245d2dd
@ -46,16 +46,17 @@ public class GetDataMessage extends ListMessage {
|
||||
super(params);
|
||||
}
|
||||
|
||||
public void addTransaction(Sha256Hash hash) {
|
||||
addItem(new InventoryItem(InventoryItem.Type.Transaction, hash));
|
||||
public void addTransaction(Sha256Hash hash, boolean includeWitness) {
|
||||
addItem(new InventoryItem(
|
||||
includeWitness ? InventoryItem.Type.WITNESS_TRANSACTION : InventoryItem.Type.TRANSACTION, hash));
|
||||
}
|
||||
|
||||
public void addBlock(Sha256Hash hash) {
|
||||
addItem(new InventoryItem(InventoryItem.Type.Block, hash));
|
||||
addItem(new InventoryItem(InventoryItem.Type.BLOCK, hash));
|
||||
}
|
||||
|
||||
public void addFilteredBlock(Sha256Hash hash) {
|
||||
addItem(new InventoryItem(InventoryItem.Type.FilteredBlock, hash));
|
||||
addItem(new InventoryItem(InventoryItem.Type.FILTERED_BLOCK, hash));
|
||||
}
|
||||
|
||||
public Sha256Hash getHashOf(int i) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
* Copyright 2019 Andreas Schildbach
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,10 +27,24 @@ public class InventoryItem {
|
||||
static final int MESSAGE_LENGTH = 36;
|
||||
|
||||
public enum Type {
|
||||
Error,
|
||||
Transaction,
|
||||
Block,
|
||||
FilteredBlock
|
||||
ERROR(0x0), TRANSACTION(0x1), BLOCK(0x2),
|
||||
// BIP37 extension:
|
||||
FILTERED_BLOCK(0x3),
|
||||
// BIP44 extensions:
|
||||
WITNESS_TRANSACTION(0x40000001), WITNESS_BLOCK(0x40000002), WITNESS_FILTERED_BLOCK(0x40000003);
|
||||
|
||||
public final int code;
|
||||
|
||||
private Type(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static Type ofCode(int code) {
|
||||
for (Type type : values())
|
||||
if (type.code == code)
|
||||
return type;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public final Type type;
|
||||
|
@ -54,11 +54,11 @@ public class InventoryMessage extends ListMessage {
|
||||
}
|
||||
|
||||
public void addBlock(Block block) {
|
||||
addItem(new InventoryItem(InventoryItem.Type.Block, block.getHash()));
|
||||
addItem(new InventoryItem(InventoryItem.Type.BLOCK, block.getHash()));
|
||||
}
|
||||
|
||||
public void addTransaction(Transaction tx) {
|
||||
addItem(new InventoryItem(InventoryItem.Type.Transaction, tx.getHash()));
|
||||
addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, tx.getHash()));
|
||||
}
|
||||
|
||||
/** Creates a new inv message for the given transactions. */
|
||||
|
@ -85,24 +85,9 @@ public abstract class ListMessage extends Message {
|
||||
throw new ProtocolException("Ran off the end of the INV");
|
||||
}
|
||||
int typeCode = (int) readUint32();
|
||||
InventoryItem.Type type;
|
||||
// See ppszTypeName in net.h
|
||||
switch (typeCode) {
|
||||
case 0:
|
||||
type = InventoryItem.Type.Error;
|
||||
break;
|
||||
case 1:
|
||||
type = InventoryItem.Type.Transaction;
|
||||
break;
|
||||
case 2:
|
||||
type = InventoryItem.Type.Block;
|
||||
break;
|
||||
case 3:
|
||||
type = InventoryItem.Type.FilteredBlock;
|
||||
break;
|
||||
default:
|
||||
throw new ProtocolException("Unknown CInv type: " + typeCode);
|
||||
}
|
||||
InventoryItem.Type type = InventoryItem.Type.ofCode(typeCode);
|
||||
if (type == null)
|
||||
throw new ProtocolException("Unknown CInv type: " + typeCode);
|
||||
InventoryItem item = new InventoryItem(type, readHash());
|
||||
items.add(item);
|
||||
}
|
||||
@ -114,7 +99,7 @@ public abstract class ListMessage extends Message {
|
||||
stream.write(new VarInt(items.size()).encode());
|
||||
for (InventoryItem i : items) {
|
||||
// Write out the type code.
|
||||
Utils.uint32ToByteStreamLE(i.type.ordinal(), stream);
|
||||
Utils.uint32ToByteStreamLE(i.type.code, stream);
|
||||
// And now the hash.
|
||||
stream.write(i.hash.getReversedBytes());
|
||||
}
|
||||
|
@ -931,7 +931,7 @@ public class Peer extends PeerSocketHandler {
|
||||
if (needToRequest.size() > 1)
|
||||
log.info("{}: Requesting {} transactions for depth {} dep resolution", getAddress(), needToRequest.size(), depth + 1);
|
||||
for (Sha256Hash hash : needToRequest) {
|
||||
getdata.addTransaction(hash);
|
||||
getdata.addTransaction(hash, vPeerVersionMessage.isWitnessSupported());
|
||||
GetDataRequest req = new GetDataRequest(hash, SettableFuture.create());
|
||||
futures.add(req.future);
|
||||
getDataFutures.add(req);
|
||||
@ -1194,10 +1194,10 @@ public class Peer extends PeerSocketHandler {
|
||||
|
||||
for (InventoryItem item : items) {
|
||||
switch (item.type) {
|
||||
case Transaction:
|
||||
case TRANSACTION:
|
||||
transactions.add(item);
|
||||
break;
|
||||
case Block:
|
||||
case BLOCK:
|
||||
blocks.add(item);
|
||||
break;
|
||||
default:
|
||||
@ -1243,7 +1243,7 @@ public class Peer extends PeerSocketHandler {
|
||||
it.remove();
|
||||
} else {
|
||||
log.debug("{}: getdata on tx {}", getAddress(), item.hash);
|
||||
getdata.addItem(item);
|
||||
getdata.addTransaction(item.hash, vPeerVersionMessage.isWitnessSupported());
|
||||
// Register with the garbage collector that we care about the confidence data for a while.
|
||||
pendingTxDownloads.add(conf);
|
||||
}
|
||||
@ -1283,7 +1283,7 @@ public class Peer extends PeerSocketHandler {
|
||||
getdata.addFilteredBlock(item.hash);
|
||||
pingAfterGetData = true;
|
||||
} else {
|
||||
getdata.addItem(item);
|
||||
getdata.addBlock(item.hash);
|
||||
}
|
||||
pendingBlockDownloads.add(item.hash);
|
||||
}
|
||||
@ -1339,7 +1339,7 @@ public class Peer extends PeerSocketHandler {
|
||||
// TODO: Unit test this method.
|
||||
log.info("Request to fetch peer mempool tx {}", hash);
|
||||
GetDataMessage getdata = new GetDataMessage(params);
|
||||
getdata.addTransaction(hash);
|
||||
getdata.addTransaction(hash, vPeerVersionMessage.isWitnessSupported());
|
||||
return sendSingleGetData(getdata);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public class BitcoindComparisonTool {
|
||||
System.exit(1);
|
||||
} else if (m instanceof GetDataMessage) {
|
||||
for (InventoryItem item : ((GetDataMessage) m).items)
|
||||
if (item.type == InventoryItem.Type.Block) {
|
||||
if (item.type == InventoryItem.Type.BLOCK) {
|
||||
log.info("Requested " + item.hash);
|
||||
if (currentBlock.block.getHash().equals(item.hash))
|
||||
bitcoind.sendMessage(currentBlock.block);
|
||||
|
@ -176,7 +176,7 @@ public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup {
|
||||
assertTrue(getData instanceof GetDataMessage);
|
||||
assertTrue(((GetDataMessage)getData).getItems().size() == 1);
|
||||
assertTrue(((GetDataMessage)getData).getItems().get(0).hash.equals(block.getHash()));
|
||||
assertTrue(((GetDataMessage)getData).getItems().get(0).type == InventoryItem.Type.FilteredBlock);
|
||||
assertTrue(((GetDataMessage)getData).getItems().get(0).type == InventoryItem.Type.FILTERED_BLOCK);
|
||||
|
||||
// Check that we then immediately pinged.
|
||||
Object ping = outbound(p1);
|
||||
|
@ -1511,8 +1511,8 @@ public class FullBlockTestGenerator {
|
||||
spendableOutputs.offer(b82.getCoinbaseOutput());
|
||||
|
||||
HashSet<InventoryItem> post82Mempool = new HashSet<>();
|
||||
post82Mempool.add(new InventoryItem(InventoryItem.Type.Transaction, b78tx.getHash()));
|
||||
post82Mempool.add(new InventoryItem(InventoryItem.Type.Transaction, b79tx.getHash()));
|
||||
post82Mempool.add(new InventoryItem(InventoryItem.Type.TRANSACTION, b78tx.getHash()));
|
||||
post82Mempool.add(new InventoryItem(InventoryItem.Type.TRANSACTION, b79tx.getHash()));
|
||||
blocks.add(new MemoryPoolState(post82Mempool, "post-b82 tx resurrection"));
|
||||
|
||||
// Check the UTXO query takes mempool into account.
|
||||
|
@ -626,7 +626,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
// p1 requests dep resolution, p2 is quiet.
|
||||
assertTrue(outbound(p1) instanceof GetDataMessage);
|
||||
final Sha256Hash dephash = tx.getInput(0).getOutpoint().getHash();
|
||||
final InventoryItem inv = new InventoryItem(InventoryItem.Type.Transaction, dephash);
|
||||
final InventoryItem inv = new InventoryItem(InventoryItem.Type.TRANSACTION, dephash);
|
||||
inbound(p1, new NotFoundMessage(UNITTEST, ImmutableList.of(inv)));
|
||||
assertNull(outbound(p1));
|
||||
assertNull(outbound(p2));
|
||||
@ -834,7 +834,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
// Await restart of the chain download.
|
||||
GetDataMessage getdata = assertNextMessageIs(p1, GetDataMessage.class);
|
||||
assertEquals(exhaustionPoint.getHash(), getdata.getHashOf(0));
|
||||
assertEquals(InventoryItem.Type.FilteredBlock, getdata.getItems().get(0).type);
|
||||
assertEquals(InventoryItem.Type.FILTERED_BLOCK, getdata.getItems().get(0).type);
|
||||
List<Block> newBlocks = blocks.subList(3, blocks.size());
|
||||
filterAndSend(p1, newBlocks, newFilter);
|
||||
assertNextMessageIs(p1, Ping.class);
|
||||
|
@ -220,7 +220,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
Block b3 = makeSolvedTestBlock(b2);
|
||||
inbound(writeTarget, b3);
|
||||
InventoryMessage inv = new InventoryMessage(UNITTEST);
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b3.getHash());
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.BLOCK, b3.getHash());
|
||||
inv.addItem(item);
|
||||
inbound(writeTarget, inv);
|
||||
|
||||
@ -249,7 +249,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
|
||||
// Receive an inv.
|
||||
InventoryMessage inv = new InventoryMessage(UNITTEST);
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b2.getHash());
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.BLOCK, b2.getHash());
|
||||
inv.addItem(item);
|
||||
inbound(writeTarget, inv);
|
||||
|
||||
@ -266,7 +266,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
Coin value = COIN;
|
||||
Transaction tx = createFakeTx(UNITTEST, value, address);
|
||||
InventoryMessage inv = new InventoryMessage(UNITTEST);
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash());
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.TRANSACTION, tx.getHash());
|
||||
inv.addItem(item);
|
||||
inbound(writeTarget, inv);
|
||||
// Peer hasn't seen it before, so will ask for it.
|
||||
@ -299,7 +299,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
Coin value = COIN;
|
||||
Transaction tx = createFakeTx(UNITTEST, value, this.address);
|
||||
InventoryMessage inv = new InventoryMessage(UNITTEST);
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash());
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.TRANSACTION, tx.getHash());
|
||||
inv.addItem(item);
|
||||
|
||||
inbound(writeTarget, inv);
|
||||
@ -324,7 +324,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
final Block b2 = makeSolvedTestBlock(b1);
|
||||
// Receive notification of a new block.
|
||||
final InventoryMessage inv = new InventoryMessage(UNITTEST);
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b2.getHash());
|
||||
InventoryItem item = new InventoryItem(InventoryItem.Type.BLOCK, b2.getHash());
|
||||
inv.addItem(item);
|
||||
|
||||
final AtomicInteger newBlockMessagesReceived = new AtomicInteger(0);
|
||||
@ -374,7 +374,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
List<InventoryItem> items = getdata.getItems();
|
||||
assertEquals(1, items.size());
|
||||
assertEquals(b2.getHash(), items.get(0).hash);
|
||||
assertEquals(InventoryItem.Type.Block, items.get(0).type);
|
||||
assertEquals(InventoryItem.Type.BLOCK, items.get(0).type);
|
||||
}
|
||||
|
||||
// Check that it starts downloading the block chain correctly on request.
|
||||
@ -497,7 +497,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
assertEquals(Sha256Hash.ZERO_HASH, getblocks.getStopHash());
|
||||
// We're supposed to get an inv here.
|
||||
InventoryMessage inv = new InventoryMessage(UNITTEST);
|
||||
inv.addItem(new InventoryItem(InventoryItem.Type.Block, b3.getHash()));
|
||||
inv.addItem(new InventoryItem(InventoryItem.Type.BLOCK, b3.getHash()));
|
||||
inbound(writeTarget, inv);
|
||||
GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
|
||||
assertEquals(b3.getHash(), getdata.getItems().get(0).hash);
|
||||
@ -621,8 +621,8 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
inbound(writeTarget, t2);
|
||||
inbound(writeTarget, t3);
|
||||
NotFoundMessage notFound = new NotFoundMessage(UNITTEST);
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t7hash));
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t8hash));
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, t7hash));
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, t8hash));
|
||||
inbound(writeTarget, notFound);
|
||||
assertFalse(futures.isDone());
|
||||
// It will recursively ask for the dependencies of t2: t5 and t4, but not t3 because it already found t4.
|
||||
@ -630,7 +630,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
assertEquals(getdata.getItems().get(0).hash, t2.getInput(0).getOutpoint().getHash());
|
||||
// t5 isn't found and t4 is.
|
||||
notFound = new NotFoundMessage(UNITTEST);
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t5hash));
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, t5hash));
|
||||
inbound(writeTarget, notFound);
|
||||
assertFalse(futures.isDone());
|
||||
// Request t4 ...
|
||||
@ -641,7 +641,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
getdata = (GetDataMessage) outbound(writeTarget);
|
||||
assertEquals(t6hash, getdata.getItems().get(0).hash);
|
||||
notFound = new NotFoundMessage(UNITTEST);
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t6hash));
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, t6hash));
|
||||
inbound(writeTarget, notFound);
|
||||
pingAndWait(writeTarget);
|
||||
// That's it, we explored the entire tree.
|
||||
@ -801,7 +801,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
assertEquals(t3, getdata.getItems().get(0).hash);
|
||||
// Can't find it: bottom of tree.
|
||||
NotFoundMessage notFound = new NotFoundMessage(UNITTEST);
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t3));
|
||||
notFound.addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, t3));
|
||||
inbound(writeTarget, notFound);
|
||||
pingAndWait(writeTarget);
|
||||
Threading.waitForUserCode();
|
||||
@ -876,7 +876,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
t2.addInput(t1.getOutput(0));
|
||||
t2.addOutput(COIN, wallet.currentChangeAddress());
|
||||
inbound(writeTarget, t2);
|
||||
final InventoryItem inventoryItem = new InventoryItem(InventoryItem.Type.Transaction, t2.getInput(0).getOutpoint().getHash());
|
||||
final InventoryItem inventoryItem = new InventoryItem(InventoryItem.Type.TRANSACTION, t2.getInput(0).getOutpoint().getHash());
|
||||
final NotFoundMessage nfm = new NotFoundMessage(UNITTEST, Lists.newArrayList(inventoryItem));
|
||||
inbound(writeTarget, nfm);
|
||||
pingAndWait(writeTarget);
|
||||
@ -942,9 +942,9 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
@Override
|
||||
public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
|
||||
// Add some hashes.
|
||||
addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.of(new byte[]{1})));
|
||||
addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.of(new byte[]{2})));
|
||||
addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.of(new byte[]{3})));
|
||||
addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, Sha256Hash.of(new byte[]{1})));
|
||||
addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, Sha256Hash.of(new byte[]{2})));
|
||||
addItem(new InventoryItem(InventoryItem.Type.TRANSACTION, Sha256Hash.of(new byte[]{3})));
|
||||
|
||||
// Write out a copy that's truncated in the middle.
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
Loading…
x
Reference in New Issue
Block a user