From 9c355016623ce56e4d4cc0113ab60c1e0832d744 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Wed, 13 Nov 2013 18:30:14 +0100 Subject: [PATCH] Payment channels: bump protocol version. The protocol gained a PAYMENT_ACK message and now requires a min payment up front. Thus, it is incompatible with previous versions. --- .../channels/PaymentChannelClient.java | 4 +-- .../channels/PaymentChannelServer.java | 25 ++++++++----------- .../channels/ChannelConnectionTest.java | 6 ++--- 3 files changed, 16 insertions(+), 19 deletions(-) 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 a10e3c75..1cfcdd2d 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 @@ -243,7 +243,7 @@ public class PaymentChannelClient implements IPaymentChannelClient { checkState(step == InitStep.WAITING_FOR_VERSION_NEGOTIATION && msg.hasServerVersion()); // Server might send back a major version lower than our own if they want to fallback to a // lower version. We can't handle that, so we just close the channel. - if (msg.getServerVersion().getMajor() != 0) { + if (msg.getServerVersion().getMajor() != 1) { errorBuilder = Protos.Error.newBuilder() .setCode(Protos.Error.ErrorCode.NO_ACCEPTABLE_VERSION); closeReason = CloseReason.NO_ACCEPTABLE_VERSION; @@ -399,7 +399,7 @@ public class PaymentChannelClient implements IPaymentChannelClient { step = InitStep.WAITING_FOR_VERSION_NEGOTIATION; Protos.ClientVersion.Builder versionNegotiationBuilder = Protos.ClientVersion.newBuilder() - .setMajor(0).setMinor(1); + .setMajor(1).setMinor(0); if (storedChannel != null) { versionNegotiationBuilder.setPreviousChannelContractHash(ByteString.copyFrom(storedChannel.contract.getHash().getBytes())); diff --git a/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelServer.java b/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelServer.java index 1ac40dd6..9f7fffc0 100644 --- a/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelServer.java +++ b/core/src/main/java/com/google/bitcoin/protocols/channels/PaymentChannelServer.java @@ -169,8 +169,15 @@ public class PaymentChannelServer { @GuardedBy("lock") private void receiveVersionMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { + checkState(step == InitStep.WAITING_ON_CLIENT_VERSION && msg.hasClientVersion()); + if (msg.getClientVersion().getMajor() != 1) { + error("This server needs protocol v1", Protos.Error.ErrorCode.NO_ACCEPTABLE_VERSION, + CloseReason.NO_ACCEPTABLE_VERSION); + return; + } + Protos.ServerVersion.Builder versionNegotiationBuilder = Protos.ServerVersion.newBuilder() - .setMajor(0).setMinor(1); + .setMajor(1).setMinor(0); conn.sendToClient(Protos.TwoWayChannelMessage.newBuilder() .setType(Protos.TwoWayChannelMessage.MessageType.SERVER_VERSION) .setServerVersion(versionNegotiationBuilder) @@ -333,14 +340,6 @@ public class PaymentChannelServer { try { switch (msg.getType()) { case CLIENT_VERSION: - checkState(step == InitStep.WAITING_ON_CLIENT_VERSION && msg.hasClientVersion()); - if (msg.getClientVersion().getMajor() != 0) { - errorBuilder = Protos.Error.newBuilder() - .setCode(Protos.Error.ErrorCode.NO_ACCEPTABLE_VERSION); - closeReason = CloseReason.NO_ACCEPTABLE_VERSION; - break; - } - receiveVersionMessage(msg); return; case PROVIDE_REFUND: @@ -363,11 +362,8 @@ public class PaymentChannelServer { conn.destroyConnection(CloseReason.REMOTE_SENT_ERROR); return; default: - log.error("Got unknown message type or type that doesn't apply to servers."); - errorBuilder = Protos.Error.newBuilder() - .setCode(Protos.Error.ErrorCode.SYNTAX_ERROR); - closeReason = CloseReason.REMOTE_SENT_INVALID_MESSAGE; - break; + final String errorText = "Got unknown message type or type that doesn't apply to servers."; + error(errorText, Protos.Error.ErrorCode.SYNTAX_ERROR, CloseReason.REMOTE_SENT_INVALID_MESSAGE); } } catch (VerificationException e) { log.error("Caught verification exception handling message from client", e); @@ -385,6 +381,7 @@ public class PaymentChannelServer { } private void error(String message, Protos.Error.ErrorCode errorCode, CloseReason closeReason) { + log.error(message); Protos.Error.Builder errorBuilder; errorBuilder = Protos.Error.newBuilder() .setCode(errorCode) 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 b2e157d3..01cceaaf 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 @@ -319,7 +319,7 @@ public class ChannelConnectionTest extends TestWithWallet { .setType(MessageType.CLIENT_VERSION) .setClientVersion(Protos.ClientVersion.newBuilder() .setPreviousChannelContractHash(ByteString.copyFrom(Sha256Hash.create(new byte[]{0x03}).getBytes())) - .setMajor(0).setMinor(42)) + .setMajor(1).setMinor(42)) .build()); pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION); pair.serverRecorder.checkNextMsg(MessageType.INITIATE); @@ -380,7 +380,7 @@ public class ChannelConnectionTest extends TestWithWallet { .setType(MessageType.CLIENT_VERSION) .setClientVersion(Protos.ClientVersion.newBuilder() .setPreviousChannelContractHash(ByteString.copyFrom(contractHash.getBytes())) - .setMajor(0).setMinor(42)) + .setMajor(1).setMinor(42)) .build()); // We get the usual resume sequence. pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION); @@ -440,7 +440,7 @@ public class ChannelConnectionTest extends TestWithWallet { .setType(MessageType.CLIENT_VERSION) .setClientVersion(Protos.ClientVersion.newBuilder() .setPreviousChannelContractHash(ByteString.copyFrom(new byte[]{0x00, 0x01})) - .setMajor(0).setMinor(42)) + .setMajor(1).setMinor(42)) .build()); srv.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION);