diff --git a/core/src/main/java/com/google/bitcoin/protocols/channels/IPaymentChannelClient.java b/core/src/main/java/com/google/bitcoin/protocols/channels/IPaymentChannelClient.java index 49f8249ea..17ff9c17e 100644 --- a/core/src/main/java/com/google/bitcoin/protocols/channels/IPaymentChannelClient.java +++ b/core/src/main/java/com/google/bitcoin/protocols/channels/IPaymentChannelClient.java @@ -117,11 +117,15 @@ public interface IPaymentChannelClient { /** *

Indicates the channel has been successfully opened and - * {@link com.google.bitcoin.protocols.channels.PaymentChannelClient#incrementPayment(java.math.BigInteger)} may be called at will.

+ * {@link com.google.bitcoin.protocols.channels.PaymentChannelClient#incrementPayment(java.math.BigInteger)} + * may be called at will.

* - *

Called while holding a lock on the {@link com.google.bitcoin.protocols.channels.PaymentChannelClient} object - be careful about reentrancy

+ *

Called while holding a lock on the {@link com.google.bitcoin.protocols.channels.PaymentChannelClient} + * object - be careful about reentrancy

+ * + * @param wasInitiated If true, the channel is newly opened. If false, it was resumed. */ - void channelOpen(); + void channelOpen(boolean wasInitiated); } /** diff --git a/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClient.java b/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClient.java index e48008f5b..61709b13f 100644 --- a/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClient.java +++ b/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClient.java @@ -169,12 +169,16 @@ public class PaymentChannelClient implements IPaymentChannelClient { checkState(step == InitStep.WAITING_FOR_CHANNEL_OPEN || (step == InitStep.WAITING_FOR_INITIATE && storedChannel != null), step); log.info("Got CHANNEL_OPEN message, ready to pay"); - if (step == InitStep.WAITING_FOR_INITIATE) + boolean wasInitiated = true; + if (step == InitStep.WAITING_FOR_INITIATE) { + // We skipped the initiate step, because a previous channel that's still valid was resumed. + wasInitiated = false; state = new PaymentChannelClientState(storedChannel, wallet); + } step = InitStep.CHANNEL_OPEN; // channelOpen should disable timeouts, but // TODO accomodate high latency between PROVIDE_CONTRACT and here - conn.channelOpen(); + conn.channelOpen(wasInitiated); } /** diff --git a/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClientConnection.java b/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClientConnection.java index baa67f227..3878b6994 100644 --- a/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClientConnection.java +++ b/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelClientConnection.java @@ -76,7 +76,7 @@ public class PaymentChannelClientConnection { } @Override - public void channelOpen() { + public void channelOpen(boolean wasInitiated) { wireParser.setSocketTimeout(0); // Inform the API user that we're done and ready to roll. channelOpenFuture.set(PaymentChannelClientConnection.this); diff --git a/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java b/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java index debbda114..83bc56c0d 100644 --- a/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java +++ b/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java @@ -282,7 +282,7 @@ public class ChannelConnectionTest extends TestWithWallet { broadcasts.take(); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CHANNEL_OPEN)); Sha256Hash contractHash = (Sha256Hash) pair.serverRecorder.q.take(); - pair.clientRecorder.checkOpened(); + pair.clientRecorder.checkInitiated(); assertNull(pair.serverRecorder.q.poll()); assertNull(pair.clientRecorder.q.poll()); // Send a bitcent. @@ -601,7 +601,7 @@ public class ChannelConnectionTest extends TestWithWallet { broadcasts.take(); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CHANNEL_OPEN)); Sha256Hash contractHash = (Sha256Hash) pair.serverRecorder.q.take(); - pair.clientRecorder.checkOpened(); + pair.clientRecorder.checkInitiated(); assertNull(pair.serverRecorder.q.poll()); assertNull(pair.clientRecorder.q.poll()); // Send the whole channel at once. The server will broadcast the final contract and settle the channel for us. @@ -646,7 +646,7 @@ public class ChannelConnectionTest extends TestWithWallet { broadcasts.take(); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CHANNEL_OPEN)); Sha256Hash contractHash = (Sha256Hash) pair.serverRecorder.q.take(); - pair.clientRecorder.checkOpened(); + pair.clientRecorder.checkInitiated(); assertNull(pair.serverRecorder.q.poll()); assertNull(pair.clientRecorder.q.poll()); ListenableFuture future = client.incrementPayment(Utils.CENT); @@ -699,7 +699,7 @@ public class ChannelConnectionTest extends TestWithWallet { broadcasts.take(); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CHANNEL_OPEN)); Sha256Hash contractHash = (Sha256Hash) pair.serverRecorder.q.take(); - pair.clientRecorder.checkOpened(); + pair.clientRecorder.checkInitiated(); assertNull(pair.serverRecorder.q.poll()); assertNull(pair.clientRecorder.q.poll()); client.incrementPayment(Utils.CENT); diff --git a/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelTestUtils.java b/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelTestUtils.java index 13fd0b1ab..3eff22788 100644 --- a/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelTestUtils.java +++ b/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelTestUtils.java @@ -59,6 +59,7 @@ public class ChannelTestUtils { public BlockingQueue q = new LinkedBlockingQueue(); // An arbitrary sentinel object for equality testing. + public static final Object CHANNEL_INITIATED = new Object(); public static final Object CHANNEL_OPEN = new Object(); @Override @@ -72,7 +73,9 @@ public class ChannelTestUtils { } @Override - public void channelOpen() { + public void channelOpen(boolean wasInitiated) { + if (wasInitiated) + q.add(CHANNEL_INITIATED); q.add(CHANNEL_OPEN); } @@ -89,6 +92,11 @@ public class ChannelTestUtils { public void checkOpened() throws InterruptedException { assertEquals(CHANNEL_OPEN, q.take()); } + + public void checkInitiated() throws InterruptedException { + assertEquals(CHANNEL_INITIATED, q.take()); + checkOpened(); + } } public static class RecordingPair {