mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 09:50:32 +01:00
Support for bundling an optional info Protobuf ByteString with a PaymentAck message
This commit is contained in:
parent
f1dd47443f
commit
eff9ac2ecc
@ -17,7 +17,7 @@ public class NativePaymentChannelServerConnectionEventHandler extends ServerConn
|
||||
public native void channelOpen(Sha256Hash channelId);
|
||||
|
||||
@Override
|
||||
public native void paymentIncrease(Coin by, Coin to, ByteString info);
|
||||
public native ByteString paymentIncrease(Coin by, Coin to, ByteString info);
|
||||
|
||||
@Override
|
||||
public native void channelClosed(PaymentChannelCloseException.CloseReason reason);
|
||||
|
@ -84,7 +84,7 @@ public interface IPaymentChannelClient {
|
||||
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
|
||||
* @return a future that completes when the server acknowledges receipt and acceptance of the payment.
|
||||
*/
|
||||
ListenableFuture<Coin> incrementPayment(Coin size, @Nullable ByteString info) throws ValueOutOfRangeException, IllegalStateException;
|
||||
ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info) throws ValueOutOfRangeException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Implements the connection between this client and the server, providing an interface which allows messages to be
|
||||
|
@ -90,7 +90,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
||||
|
||||
@GuardedBy("lock") private long minPayment;
|
||||
|
||||
@GuardedBy("lock") SettableFuture<Coin> increasePaymentFuture;
|
||||
@GuardedBy("lock") SettableFuture<PaymentIncrementAck> increasePaymentFuture;
|
||||
@GuardedBy("lock") Coin lastPaymentActualAmount;
|
||||
|
||||
/**
|
||||
@ -290,7 +290,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
||||
receiveChannelOpen();
|
||||
return;
|
||||
case PAYMENT_ACK:
|
||||
receivePaymentAck();
|
||||
receivePaymentAck(msg.getPaymentAck());
|
||||
return;
|
||||
case CLOSE:
|
||||
receiveClose(msg);
|
||||
@ -462,13 +462,13 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
||||
* you wait for the previous increase payment future to complete before incrementing the payment again.
|
||||
*
|
||||
* @param size How many satoshis to increment the payment by (note: not the new total).
|
||||
* @return a future that completes when the server acknowledges receipt and acceptance of the payment.
|
||||
* @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
|
||||
* ({@link PaymentChannelClientConnection#state()}.getTotalValue())
|
||||
* @throws IllegalStateException If the channel has been closed or is not yet open
|
||||
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
|
||||
* @return a future that completes when the server acknowledges receipt and acceptance of the payment.
|
||||
*/
|
||||
public ListenableFuture<Coin> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException {
|
||||
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException {
|
||||
return incrementPayment(size, null);
|
||||
}
|
||||
|
||||
@ -481,14 +481,14 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
||||
*
|
||||
* @param size How many satoshis to increment the payment by (note: not the new total).
|
||||
* @param info Information about this update, used to extend this protocol.
|
||||
* @return a future that completes when the server acknowledges receipt and acceptance of the payment.
|
||||
* @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
|
||||
* ({@link PaymentChannelClientConnection#state()}.getTotalValue())
|
||||
* @throws IllegalStateException If the channel has been closed or is not yet open
|
||||
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
|
||||
* @return a future that completes when the server acknowledges receipt and acceptance of the payment.
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<Coin> incrementPayment(Coin size, @Nullable ByteString info) throws ValueOutOfRangeException, IllegalStateException {
|
||||
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info) throws ValueOutOfRangeException, IllegalStateException {
|
||||
lock.lock();
|
||||
try {
|
||||
if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
|
||||
@ -523,8 +523,8 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void receivePaymentAck() {
|
||||
SettableFuture<Coin> future;
|
||||
private void receivePaymentAck(Protos.PaymentAck paymentAck) {
|
||||
SettableFuture<PaymentIncrementAck> future;
|
||||
Coin value;
|
||||
|
||||
lock.lock();
|
||||
@ -539,6 +539,6 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
||||
}
|
||||
|
||||
// Ensure the future runs without the client lock held.
|
||||
future.set(value);
|
||||
future.set(new PaymentIncrementAck(value, paymentAck.getInfo()));
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ public class PaymentChannelClientConnection {
|
||||
* @throws IllegalStateException If the channel has been closed or is not yet open
|
||||
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
|
||||
*/
|
||||
public ListenableFuture<Coin> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException {
|
||||
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException {
|
||||
return channelClient.incrementPayment(size, null);
|
||||
}
|
||||
/**
|
||||
@ -149,7 +149,7 @@ public class PaymentChannelClientConnection {
|
||||
* @throws IllegalStateException If the channel has been closed or is not yet open
|
||||
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
|
||||
*/
|
||||
public ListenableFuture<Coin> incrementPayment(Coin size, ByteString info) throws ValueOutOfRangeException, IllegalStateException {
|
||||
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, ByteString info) throws ValueOutOfRangeException, IllegalStateException {
|
||||
return channelClient.incrementPayment(size, info);
|
||||
}
|
||||
|
||||
|
@ -101,8 +101,10 @@ public class PaymentChannelServer {
|
||||
* @param by The increase in total payment
|
||||
* @param to The new total payment to us (not including fees which may be required to claim the payment)
|
||||
* @param info Information about this payment increase, used to extend this protocol.
|
||||
* @return An ack message that will be included in the PaymentAck message to the client. Use null for no ack message.
|
||||
*/
|
||||
public void paymentIncrease(Coin by, Coin to, @Nullable ByteString info);
|
||||
@Nullable
|
||||
public ByteString paymentIncrease(Coin by, Coin to, @Nullable ByteString info);
|
||||
}
|
||||
private final ServerConnection conn;
|
||||
|
||||
@ -315,14 +317,16 @@ public class PaymentChannelServer {
|
||||
boolean stillUsable = state.incrementPayment(refundSize, msg.getSignature().toByteArray());
|
||||
Coin bestPaymentChange = state.getBestValueToMe().subtract(lastBestPayment);
|
||||
|
||||
ByteString ackInfo = null;
|
||||
if (bestPaymentChange.signum() > 0) {
|
||||
ByteString info = (msg.hasInfo()) ? msg.getInfo() : null;
|
||||
conn.paymentIncrease(bestPaymentChange, state.getBestValueToMe(), info);
|
||||
ackInfo = conn.paymentIncrease(bestPaymentChange, state.getBestValueToMe(), info);
|
||||
}
|
||||
|
||||
if (sendAck) {
|
||||
Protos.TwoWayChannelMessage.Builder ack = Protos.TwoWayChannelMessage.newBuilder();
|
||||
ack.setType(Protos.TwoWayChannelMessage.MessageType.PAYMENT_ACK);
|
||||
if (ackInfo != null) ack.setPaymentAck(ack.getPaymentAckBuilder().setInfo(ackInfo));
|
||||
conn.sendToClient(ack.build());
|
||||
}
|
||||
|
||||
|
@ -83,8 +83,8 @@ public class PaymentChannelServerListener {
|
||||
eventHandler.channelOpen(contractHash);
|
||||
}
|
||||
|
||||
@Override public void paymentIncrease(Coin by, Coin to, @Nullable ByteString info) {
|
||||
eventHandler.paymentIncrease(by, to, info);
|
||||
@Override public ByteString paymentIncrease(Coin by, Coin to, @Nullable ByteString info) {
|
||||
return eventHandler.paymentIncrease(by, to, info);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.google.bitcoin.protocols.channels;
|
||||
|
||||
import com.google.bitcoin.core.Coin;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An acknowledgement of a payment increase
|
||||
*/
|
||||
public class PaymentIncrementAck {
|
||||
private final Coin value;
|
||||
@Nullable private final ByteString info;
|
||||
|
||||
public PaymentIncrementAck(Coin value, @Nullable ByteString info) {
|
||||
this.value = value;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public Coin getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ByteString getInfo() {
|
||||
return info;
|
||||
}
|
||||
}
|
@ -71,8 +71,10 @@ public abstract class ServerConnectionEventHandler {
|
||||
* @param by The increase in total payment
|
||||
* @param to The new total payment to us (not including fees which may be required to claim the payment)
|
||||
* @param info Information about this payment increase, used to extend this protocol.
|
||||
* @return acknowledgment information to be sent to the client.
|
||||
*/
|
||||
public abstract void paymentIncrease(Coin by, Coin to, ByteString info);
|
||||
@Nullable
|
||||
public abstract ByteString paymentIncrease(Coin by, Coin to, ByteString info);
|
||||
|
||||
/**
|
||||
* <p>Called when the channel was closed for some reason. May be called without a call to
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -83,6 +83,7 @@ message TwoWayChannelMessage {
|
||||
optional ReturnRefund return_refund = 6;
|
||||
optional ProvideContract provide_contract = 7;
|
||||
optional UpdatePayment update_payment = 8;
|
||||
optional PaymentAck payment_ack = 11;
|
||||
optional Settlement settlement = 9;
|
||||
|
||||
optional Error error = 10;
|
||||
@ -214,6 +215,12 @@ message UpdatePayment {
|
||||
|
||||
}
|
||||
|
||||
// This message is sent as an acknowledgement of an UpdatePayment message
|
||||
message PaymentAck {
|
||||
// Information about this update. Used to extend this protocol
|
||||
optional bytes info = 1;
|
||||
}
|
||||
|
||||
message Settlement {
|
||||
// A copy of the fully signed final contract that settles the channel. The client can verify
|
||||
// the transaction is correct and then commit it to their wallet.
|
||||
|
@ -130,8 +130,9 @@ public class ChannelConnectionTest extends TestWithWallet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paymentIncrease(Coin by, Coin to, ByteString info) {
|
||||
public ByteString paymentIncrease(Coin by, Coin to, ByteString info) {
|
||||
q.add(new ChannelTestUtils.UpdatePair(to, info));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -682,20 +683,20 @@ public class ChannelConnectionTest extends TestWithWallet {
|
||||
pair.clientRecorder.checkInitiated();
|
||||
assertNull(pair.serverRecorder.q.poll());
|
||||
assertNull(pair.clientRecorder.q.poll());
|
||||
ListenableFuture<Coin> future = client.incrementPayment(CENT);
|
||||
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
|
||||
pair.serverRecorder.q.take();
|
||||
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK));
|
||||
assertTrue(future.isDone());
|
||||
client.incrementPayment(CENT);
|
||||
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
|
||||
pair.serverRecorder.q.take();
|
||||
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK));
|
||||
|
||||
client.incrementPayment(CENT);
|
||||
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
|
||||
pair.serverRecorder.q.take();
|
||||
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ListenableFuture<PaymentIncrementAck> future = client.incrementPayment(CENT);
|
||||
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
|
||||
pair.serverRecorder.q.take();
|
||||
final Protos.TwoWayChannelMessage msg = pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK);
|
||||
final Protos.PaymentAck paymentAck = msg.getPaymentAck();
|
||||
assertTrue("No PaymentAck.Info", paymentAck.hasInfo());
|
||||
assertEquals("Wrong PaymentAck info", ByteString.copyFromUtf8(CENT.toPlainString()), paymentAck.getInfo());
|
||||
client.receiveMessage(msg);
|
||||
assertTrue(future.isDone());
|
||||
final PaymentIncrementAck paymentIncrementAck = future.get();
|
||||
assertEquals("Wrong value returned from increasePayment", CENT, paymentIncrementAck.getValue());
|
||||
assertEquals("Wrong info returned from increasePayment", ByteString.copyFromUtf8(CENT.toPlainString()), paymentIncrementAck.getInfo());
|
||||
}
|
||||
|
||||
// Settle it and verify it's considered to be settled.
|
||||
broadcastTxPause.release();
|
||||
|
@ -37,8 +37,9 @@ public class ChannelTestUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paymentIncrease(Coin by, Coin to, @Nullable ByteString info) {
|
||||
public ByteString paymentIncrease(Coin by, Coin to, @Nullable ByteString info) {
|
||||
q.add(new UpdatePair(to, info));
|
||||
return ByteString.copyFromUtf8(by.toPlainString());
|
||||
}
|
||||
|
||||
public Protos.TwoWayChannelMessage getNextMsg() throws InterruptedException {
|
||||
|
@ -102,8 +102,9 @@ public class ExamplePaymentChannelServer implements PaymentChannelServerListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paymentIncrease(Coin by, Coin to, ByteString info) {
|
||||
public ByteString paymentIncrease(Coin by, Coin to, ByteString info) {
|
||||
log.info("Client {} paid increased payment by {} for a total of " + to.toString(), clientAddress, by);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user