Payment channels: fix a simple thread-affinity bug revealed by a flaky unit test. It does not affect real apps.

Disable signature checking in ChannelTest to make it run faster, especially in the debugger, and bump timeouts so client/server don't timeout when debugging.
This commit is contained in:
Mike Hearn
2013-11-21 13:25:35 +01:00
parent a9469758fd
commit 3569dfe2d4
2 changed files with 19 additions and 7 deletions

View File

@@ -23,7 +23,11 @@ import com.google.bitcoin.script.ScriptBuilder;
import com.google.bitcoin.utils.Threading;
import com.google.bitcoin.wallet.AllowUnconfirmedCoinSelector;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -193,12 +197,19 @@ public class PaymentChannelClientState {
// When we see the close transaction get a few confirmations, we can just delete the record
// of this channel along with the refund tx from the wallet, because we're not going to need
// any of that any more.
storedChannel.close.getConfidence().getDepthFuture(CONFIRMATIONS_FOR_DELETE).addListener(new Runnable() {
final TransactionConfidence confidence = storedChannel.close.getConfidence();
ListenableFuture<Transaction> future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD);
Futures.addCallback(future, new FutureCallback<Transaction>() {
@Override
public void run() {
public void onSuccess(Transaction result) {
deleteChannelFromWallet();
}
}, Threading.SAME_THREAD);
@Override
public void onFailure(Throwable t) {
Throwables.propagate(t);
}
});
}
private synchronized void deleteChannelFromWallet() {

View File

@@ -92,12 +92,15 @@ public class ChannelConnectionTest extends TestWithWallet {
// handlers), we have lots of lock cycles. A normal user shouldn't have this issue as they are probably not both
// client+server running in the same thread.
Threading.warnOnLockCycles();
ECKey.FAKE_SIGNATURES = true;
}
@After
@Override
public void tearDown() throws Exception {
super.tearDown();
ECKey.FAKE_SIGNATURES = false;
}
@After
@@ -112,7 +115,7 @@ public class ChannelConnectionTest extends TestWithWallet {
final SettableFuture<ListenableFuture<PaymentChannelServerState>> serverCloseFuture = SettableFuture.create();
final SettableFuture<Sha256Hash> channelOpenFuture = SettableFuture.create();
final BlockingQueue<BigInteger> q = new LinkedBlockingQueue<BigInteger>();
final PaymentChannelServerListener server = new PaymentChannelServerListener(mockBroadcaster, serverWallet, 1, Utils.COIN,
final PaymentChannelServerListener server = new PaymentChannelServerListener(mockBroadcaster, serverWallet, 30, Utils.COIN,
new PaymentChannelServerListener.HandlerFactory() {
@Nullable
@Override
@@ -138,7 +141,7 @@ public class ChannelConnectionTest extends TestWithWallet {
server.bindAndStart(4243);
PaymentChannelClientConnection client = new PaymentChannelClientConnection(
new InetSocketAddress("localhost", 4243), 1, wallet, myKey, Utils.COIN, "");
new InetSocketAddress("localhost", 4243), 30, wallet, myKey, Utils.COIN, "");
// Wait for the multi-sig tx to be transmitted.
broadcastTxPause.release();
@@ -204,8 +207,6 @@ public class ChannelConnectionTest extends TestWithWallet {
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
assertEquals(1, StoredPaymentChannelClientStates.getFromWallet(wallet).mapChannels.size());
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
assertEquals(1, StoredPaymentChannelClientStates.getFromWallet(wallet).mapChannels.size());
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
assertEquals(0, StoredPaymentChannelClientStates.getFromWallet(wallet).mapChannels.size());
}