mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-11-02 05:27:17 +00:00
Delete !notfound code paths.
This commit is contained in:
@@ -130,10 +130,6 @@ public class Peer extends PeerSocketHandler {
|
|||||||
private static class GetDataRequest {
|
private static class GetDataRequest {
|
||||||
Sha256Hash hash;
|
Sha256Hash hash;
|
||||||
SettableFuture future;
|
SettableFuture future;
|
||||||
// If the peer does not support the notfound message, we'll use ping/pong messages to simulate it. This is
|
|
||||||
// a nasty hack that relies on the fact that bitcoin-qt is single threaded and processes messages in order.
|
|
||||||
// The nonce field records which pong should clear this request as "not found".
|
|
||||||
long nonce;
|
|
||||||
}
|
}
|
||||||
private final CopyOnWriteArrayList<GetDataRequest> getDataFutures;
|
private final CopyOnWriteArrayList<GetDataRequest> getDataFutures;
|
||||||
|
|
||||||
@@ -744,7 +740,6 @@ public class Peer extends PeerSocketHandler {
|
|||||||
// Build the request for the missing dependencies.
|
// Build the request for the missing dependencies.
|
||||||
List<ListenableFuture<Transaction>> futures = Lists.newArrayList();
|
List<ListenableFuture<Transaction>> futures = Lists.newArrayList();
|
||||||
GetDataMessage getdata = new GetDataMessage(params);
|
GetDataMessage getdata = new GetDataMessage(params);
|
||||||
final long nonce = (long)(Math.random()*Long.MAX_VALUE);
|
|
||||||
if (needToRequest.size() > 1)
|
if (needToRequest.size() > 1)
|
||||||
log.info("{}: Requesting {} transactions for dep resolution", getAddress(), needToRequest.size());
|
log.info("{}: Requesting {} transactions for dep resolution", getAddress(), needToRequest.size());
|
||||||
for (Sha256Hash hash : needToRequest) {
|
for (Sha256Hash hash : needToRequest) {
|
||||||
@@ -752,9 +747,6 @@ public class Peer extends PeerSocketHandler {
|
|||||||
GetDataRequest req = new GetDataRequest();
|
GetDataRequest req = new GetDataRequest();
|
||||||
req.hash = hash;
|
req.hash = hash;
|
||||||
req.future = SettableFuture.create();
|
req.future = SettableFuture.create();
|
||||||
if (!isNotFoundMessageSupported()) {
|
|
||||||
req.nonce = nonce;
|
|
||||||
}
|
|
||||||
futures.add(req.future);
|
futures.add(req.future);
|
||||||
getDataFutures.add(req);
|
getDataFutures.add(req);
|
||||||
}
|
}
|
||||||
@@ -803,25 +795,6 @@ public class Peer extends PeerSocketHandler {
|
|||||||
});
|
});
|
||||||
// Start the operation.
|
// Start the operation.
|
||||||
sendMessage(getdata);
|
sendMessage(getdata);
|
||||||
if (!isNotFoundMessageSupported()) {
|
|
||||||
// If the peer isn't new enough to support the notfound message, we use a nasty hack instead and
|
|
||||||
// assume if we send a ping message after the getdata message, it'll be processed after all answers
|
|
||||||
// from getdata are done, so we can watch for the pong message as a substitute.
|
|
||||||
log.info("{}: Dep resolution waiting for a pong with nonce {}", this, nonce);
|
|
||||||
ping(nonce).addListener(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// The pong came back so clear out any transactions we requested but didn't get.
|
|
||||||
for (GetDataRequest req : getDataFutures) {
|
|
||||||
if (req.nonce == nonce) {
|
|
||||||
log.info("{}: Bottomed out dep tree at {}", this, req.hash);
|
|
||||||
req.future.cancel(true);
|
|
||||||
getDataFutures.remove(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, Threading.SAME_THREAD);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("{}: Couldn't send getdata in downloadDependencies({})", this, tx.getHash());
|
log.error("{}: Couldn't send getdata in downloadDependencies({})", this, tx.getHash());
|
||||||
resultFuture.setException(e);
|
resultFuture.setException(e);
|
||||||
|
|||||||
@@ -533,18 +533,9 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void recursiveDownloadNew() throws Exception {
|
public void recursiveDependencyDownload() throws Exception {
|
||||||
recursiveDependencyDownload(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void recursiveDownloadOld() throws Exception {
|
|
||||||
recursiveDependencyDownload(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recursiveDependencyDownload(boolean useNotFound) throws Exception {
|
|
||||||
// Using ping or notfound?
|
// Using ping or notfound?
|
||||||
connectWithVersion(useNotFound ? 70001 : 60001);
|
connectWithVersion(70001);
|
||||||
// Check that we can download all dependencies of an unconfirmed relevant transaction from the mempool.
|
// Check that we can download all dependencies of an unconfirmed relevant transaction from the mempool.
|
||||||
ECKey to = new ECKey();
|
ECKey to = new ECKey();
|
||||||
|
|
||||||
@@ -604,8 +595,6 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
assertEquals(someHash, getdata.getItems().get(2).hash);
|
assertEquals(someHash, getdata.getItems().get(2).hash);
|
||||||
assertEquals(anotherHash, getdata.getItems().get(3).hash);
|
assertEquals(anotherHash, getdata.getItems().get(3).hash);
|
||||||
long nonce = -1;
|
long nonce = -1;
|
||||||
if (!useNotFound)
|
|
||||||
nonce = ((Ping) outbound(writeTarget)).getNonce();
|
|
||||||
// For some random reason, t4 is delivered at this point before it's needed - perhaps it was a Bloom filter
|
// For some random reason, t4 is delivered at this point before it's needed - perhaps it was a Bloom filter
|
||||||
// false positive. We do this to check that the mempool is being checked for seen transactions before
|
// false positive. We do this to check that the mempool is being checked for seen transactions before
|
||||||
// requesting them.
|
// requesting them.
|
||||||
@@ -613,37 +602,25 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
// Deliver the requested transactions.
|
// Deliver the requested transactions.
|
||||||
inbound(writeTarget, t2);
|
inbound(writeTarget, t2);
|
||||||
inbound(writeTarget, t3);
|
inbound(writeTarget, t3);
|
||||||
if (useNotFound) {
|
NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
|
||||||
NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
|
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, someHash));
|
||||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, someHash));
|
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, anotherHash));
|
||||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, anotherHash));
|
inbound(writeTarget, notFound);
|
||||||
inbound(writeTarget, notFound);
|
|
||||||
} else {
|
|
||||||
inbound(writeTarget, new Pong(nonce));
|
|
||||||
}
|
|
||||||
assertFalse(futures.isDone());
|
assertFalse(futures.isDone());
|
||||||
// It will recursively ask for the dependencies of t2: t5 and t4, but not t3 because it already found t4.
|
// It will recursively ask for the dependencies of t2: t5 and t4, but not t3 because it already found t4.
|
||||||
getdata = (GetDataMessage) outbound(writeTarget);
|
getdata = (GetDataMessage) outbound(writeTarget);
|
||||||
assertEquals(getdata.getItems().get(0).hash, t2.getInput(0).getOutpoint().getHash());
|
assertEquals(getdata.getItems().get(0).hash, t2.getInput(0).getOutpoint().getHash());
|
||||||
// t5 isn't found and t4 is.
|
// t5 isn't found and t4 is.
|
||||||
if (useNotFound) {
|
notFound = new NotFoundMessage(unitTestParams);
|
||||||
NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
|
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t5));
|
||||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t5));
|
inbound(writeTarget, notFound);
|
||||||
inbound(writeTarget, notFound);
|
|
||||||
} else {
|
|
||||||
bouncePing();
|
|
||||||
}
|
|
||||||
assertFalse(futures.isDone());
|
assertFalse(futures.isDone());
|
||||||
// Continue to explore the t4 branch and ask for t6, which is in the chain.
|
// Continue to explore the t4 branch and ask for t6, which is in the chain.
|
||||||
getdata = (GetDataMessage) outbound(writeTarget);
|
getdata = (GetDataMessage) outbound(writeTarget);
|
||||||
assertEquals(t6, getdata.getItems().get(0).hash);
|
assertEquals(t6, getdata.getItems().get(0).hash);
|
||||||
if (useNotFound) {
|
notFound = new NotFoundMessage(unitTestParams);
|
||||||
NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
|
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t6));
|
||||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t6));
|
inbound(writeTarget, notFound);
|
||||||
inbound(writeTarget, notFound);
|
|
||||||
} else {
|
|
||||||
bouncePing();
|
|
||||||
}
|
|
||||||
pingAndWait(writeTarget);
|
pingAndWait(writeTarget);
|
||||||
// That's it, we explored the entire tree.
|
// That's it, we explored the entire tree.
|
||||||
assertTrue(futures.isDone());
|
assertTrue(futures.isDone());
|
||||||
@@ -653,23 +630,9 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
assertTrue(results.contains(t4));
|
assertTrue(results.contains(t4));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bouncePing() throws Exception {
|
|
||||||
Ping ping = (Ping) outbound(writeTarget);
|
|
||||||
inbound(writeTarget, new Pong(ping.getNonce()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void timeLockedTransactionNew() throws Exception {
|
public void timeLockedTransactionNew() throws Exception {
|
||||||
timeLockedTransaction(true);
|
connectWithVersion(70001);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void timeLockedTransactionOld() throws Exception {
|
|
||||||
timeLockedTransaction(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void timeLockedTransaction(boolean useNotFound) throws Exception {
|
|
||||||
connectWithVersion(useNotFound ? 70001 : 60001);
|
|
||||||
// Test that if we receive a relevant transaction that has a lock time, it doesn't result in a notification
|
// Test that if we receive a relevant transaction that has a lock time, it doesn't result in a notification
|
||||||
// until we explicitly opt in to seeing those.
|
// until we explicitly opt in to seeing those.
|
||||||
Wallet wallet = new Wallet(unitTestParams);
|
Wallet wallet = new Wallet(unitTestParams);
|
||||||
@@ -686,11 +649,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, key);
|
Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, key);
|
||||||
inbound(writeTarget, t1);
|
inbound(writeTarget, t1);
|
||||||
GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
|
GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
|
||||||
if (useNotFound) {
|
inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
|
||||||
inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
|
|
||||||
} else {
|
|
||||||
bouncePing();
|
|
||||||
}
|
|
||||||
pingAndWait(writeTarget);
|
pingAndWait(writeTarget);
|
||||||
Threading.waitForUserCode();
|
Threading.waitForUserCode();
|
||||||
assertNotNull(vtx[0]);
|
assertNotNull(vtx[0]);
|
||||||
@@ -705,45 +664,28 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
wallet.setAcceptRiskyTransactions(true);
|
wallet.setAcceptRiskyTransactions(true);
|
||||||
inbound(writeTarget, t2);
|
inbound(writeTarget, t2);
|
||||||
getdata = (GetDataMessage) outbound(writeTarget);
|
getdata = (GetDataMessage) outbound(writeTarget);
|
||||||
if (useNotFound) {
|
inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
|
||||||
inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
|
|
||||||
} else {
|
|
||||||
bouncePing();
|
|
||||||
}
|
|
||||||
pingAndWait(writeTarget);
|
pingAndWait(writeTarget);
|
||||||
Threading.waitForUserCode();
|
Threading.waitForUserCode();
|
||||||
assertEquals(t2, vtx[0]);
|
assertEquals(t2, vtx[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rejectTimeLockedDependencyNew() throws Exception {
|
public void rejectTimeLockedDependency() throws Exception {
|
||||||
// Check that we also verify the lock times of dependencies. Otherwise an attacker could still build a tx that
|
// Check that we also verify the lock times of dependencies. Otherwise an attacker could still build a tx that
|
||||||
// looks legitimate and useful but won't actually ever confirm, by sending us a normal tx that spends a
|
// looks legitimate and useful but won't actually ever confirm, by sending us a normal tx that spends a
|
||||||
// timelocked tx.
|
// timelocked tx.
|
||||||
checkTimeLockedDependency(false, true);
|
checkTimeLockedDependency(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void acceptTimeLockedDependencyNew() throws Exception {
|
public void acceptTimeLockedDependency() throws Exception {
|
||||||
checkTimeLockedDependency(true, true);
|
checkTimeLockedDependency(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private void checkTimeLockedDependency(boolean shouldAccept) throws Exception {
|
||||||
public void rejectTimeLockedDependencyOld() throws Exception {
|
|
||||||
// Check that we also verify the lock times of dependencies. Otherwise an attacker could still build a tx that
|
|
||||||
// looks legitimate and useful but won't actually ever confirm, by sending us a normal tx that spends a
|
|
||||||
// timelocked tx.
|
|
||||||
checkTimeLockedDependency(false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void acceptTimeLockedDependencyOld() throws Exception {
|
|
||||||
checkTimeLockedDependency(true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkTimeLockedDependency(boolean shouldAccept, boolean useNotFound) throws Exception {
|
|
||||||
// Initial setup.
|
// Initial setup.
|
||||||
connectWithVersion(useNotFound ? 70001 : 60001);
|
connectWithVersion(70001);
|
||||||
Wallet wallet = new Wallet(unitTestParams);
|
Wallet wallet = new Wallet(unitTestParams);
|
||||||
ECKey key = wallet.freshReceiveKey();
|
ECKey key = wallet.freshReceiveKey();
|
||||||
wallet.setAcceptRiskyTransactions(shouldAccept);
|
wallet.setAcceptRiskyTransactions(shouldAccept);
|
||||||
@@ -780,19 +722,13 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
getdata = (GetDataMessage) outbound(writeTarget);
|
getdata = (GetDataMessage) outbound(writeTarget);
|
||||||
assertEquals(t2.getHash(), getdata.getItems().get(0).hash);
|
assertEquals(t2.getHash(), getdata.getItems().get(0).hash);
|
||||||
inbound(writeTarget, t2);
|
inbound(writeTarget, t2);
|
||||||
if (!useNotFound)
|
|
||||||
bouncePing();
|
|
||||||
// We request t3.
|
// We request t3.
|
||||||
getdata = (GetDataMessage) outbound(writeTarget);
|
getdata = (GetDataMessage) outbound(writeTarget);
|
||||||
assertEquals(t3, getdata.getItems().get(0).hash);
|
assertEquals(t3, getdata.getItems().get(0).hash);
|
||||||
// Can't find it: bottom of tree.
|
// Can't find it: bottom of tree.
|
||||||
if (useNotFound) {
|
NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
|
||||||
NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
|
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t3));
|
||||||
notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t3));
|
inbound(writeTarget, notFound);
|
||||||
inbound(writeTarget, notFound);
|
|
||||||
} else {
|
|
||||||
bouncePing();
|
|
||||||
}
|
|
||||||
pingAndWait(writeTarget);
|
pingAndWait(writeTarget);
|
||||||
Threading.waitForUserCode();
|
Threading.waitForUserCode();
|
||||||
// We're done but still not notified because it was timelocked.
|
// We're done but still not notified because it was timelocked.
|
||||||
|
|||||||
Reference in New Issue
Block a user