3
0
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:
Andreas Schildbach 2019-02-05 11:03:26 +01:00
parent 53a63c43bb
commit be4245d2dd
10 changed files with 58 additions and 57 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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. */

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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();