3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 15:22:16 +00:00

Payment channels: Fix a dumb bug that caused the negotiated channel size to be wrong. Add a test.

This commit is contained in:
Mike Hearn 2013-07-17 21:41:08 +02:00
parent c04708dd1e
commit 7d75e747e0
2 changed files with 30 additions and 10 deletions

View File

@ -1,9 +1,7 @@
package com.google.bitcoin.protocols.channels;
import java.math.BigInteger;
import java.util.concurrent.locks.ReentrantLock;
import com.google.bitcoin.core.*;
import com.google.bitcoin.protocols.channels.PaymentChannelCloseException.CloseReason;
import com.google.bitcoin.utils.Threading;
import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.ByteString;
@ -11,7 +9,9 @@ import net.jcip.annotations.GuardedBy;
import org.bitcoin.paymentchannel.Protos;
import org.slf4j.LoggerFactory;
import com.google.bitcoin.protocols.channels.PaymentChannelCloseException.CloseReason;
import java.math.BigInteger;
import java.util.concurrent.locks.ReentrantLock;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
@ -138,13 +138,12 @@ public class PaymentChannelClient {
}
@GuardedBy("lock")
private void receiveInitiate(Protos.Initiate initiate, BigInteger minChannelSize) throws VerificationException, ValueOutOfRangeException {
private void receiveInitiate(Protos.Initiate initiate, BigInteger contractValue) throws VerificationException, ValueOutOfRangeException {
log.info("Got INITIATE message, providing refund transaction");
state = new PaymentChannelClientState(wallet, myKey,
new ECKey(null, initiate.getMultisigKey().toByteArray()),
minChannelSize,
initiate.getExpireTimeSecs());
contractValue, initiate.getExpireTimeSecs());
state.initiate();
step = InitStep.WAITING_FOR_REFUND_RETURN;
@ -232,14 +231,14 @@ public class PaymentChannelClient {
}
BigInteger minChannelSize = BigInteger.valueOf(initiate.getMinAcceptedChannelSize());
if (minChannelSize.compareTo(maxValue) > 0) {
if (maxValue.compareTo(minChannelSize) < 0) {
errorBuilder = Protos.Error.newBuilder()
.setCode(Protos.Error.ErrorCode.CHANNEL_VALUE_TOO_LARGE);
closeReason = CloseReason.SERVER_REQUESTED_TOO_MUCH_VALUE;
break;
}
receiveInitiate(initiate, minChannelSize);
receiveInitiate(initiate, maxValue);
return;
case RETURN_REFUND:
receiveRefund(msg);

View File

@ -473,7 +473,7 @@ public class ChannelConnectionTest extends TestWithWallet {
}
@Test
public void testClientValueTooLarge() throws Exception {
public void testValuesAreRespected() throws Exception {
ChannelTestUtils.RecordingPair pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
PaymentChannelServer server = pair.server;
PaymentChannelClient client = new PaymentChannelClient(wallet, myKey, Utils.COIN, Sha256Hash.ZERO_HASH, pair.clientRecorder);
@ -493,6 +493,27 @@ public class ChannelConnectionTest extends TestWithWallet {
client.incrementPayment(BigInteger.ONE);
fail();
} catch (IllegalStateException e) { }
// Now check that if the server has a lower min size than what we are willing to spend, we do actually open
// a channel of that size.
sendMoneyToWallet(Utils.COIN.multiply(BigInteger.TEN), AbstractBlockChain.NewBlockType.BEST_CHAIN);
pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
server = pair.server;
final BigInteger myValue = Utils.COIN.multiply(BigInteger.TEN);
client = new PaymentChannelClient(wallet, myKey, myValue, Sha256Hash.ZERO_HASH, pair.clientRecorder);
client.connectionOpen();
server.connectionOpen();
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.CLIENT_VERSION));
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION));
client.receiveMessage(Protos.TwoWayChannelMessage.newBuilder()
.setInitiate(Protos.Initiate.newBuilder().setExpireTimeSecs(Utils.now().getTime() / 1000)
.setMinAcceptedChannelSize(Utils.COIN.add(BigInteger.ONE).longValue())
.setMultisigKey(ByteString.copyFrom(new ECKey().getPubKey())))
.setType(MessageType.INITIATE).build());
final Protos.TwoWayChannelMessage provideRefund = pair.clientRecorder.checkNextMsg(MessageType.PROVIDE_REFUND);
Transaction refund = new Transaction(params, provideRefund.getProvideRefund().getTx().toByteArray());
assertEquals(myValue, refund.getOutput(0).getValue());
}
@Test