mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-12 10:15:52 +00:00
Payment channels: stop clients attempting to resume empty channels.
This commit is contained in:
parent
70590dac16
commit
4f92c24dea
@ -346,7 +346,7 @@ public class PaymentChannelClient {
|
|||||||
|
|
||||||
StoredPaymentChannelClientStates channels = (StoredPaymentChannelClientStates) wallet.getExtensions().get(StoredPaymentChannelClientStates.EXTENSION_ID);
|
StoredPaymentChannelClientStates channels = (StoredPaymentChannelClientStates) wallet.getExtensions().get(StoredPaymentChannelClientStates.EXTENSION_ID);
|
||||||
if (channels != null)
|
if (channels != null)
|
||||||
storedChannel = channels.getInactiveChannelById(serverId);
|
storedChannel = channels.getUsableChannelForServerID(serverId);
|
||||||
|
|
||||||
step = InitStep.WAITING_FOR_VERSION_NEGOTIATION;
|
step = InitStep.WAITING_FOR_VERSION_NEGOTIATION;
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import com.google.common.collect.HashMultimap;
|
|||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import net.jcip.annotations.GuardedBy;
|
import net.jcip.annotations.GuardedBy;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -61,12 +62,16 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
|
|||||||
/**
|
/**
|
||||||
* Finds an inactive channel with the given id and returns it, or returns null.
|
* Finds an inactive channel with the given id and returns it, or returns null.
|
||||||
*/
|
*/
|
||||||
public StoredClientChannel getInactiveChannelById(Sha256Hash id) {
|
@Nullable
|
||||||
|
public StoredClientChannel getUsableChannelForServerID(Sha256Hash id) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
Set<StoredClientChannel> setChannels = mapChannels.get(id);
|
Set<StoredClientChannel> setChannels = mapChannels.get(id);
|
||||||
for (StoredClientChannel channel : setChannels) {
|
for (StoredClientChannel channel : setChannels) {
|
||||||
synchronized (channel) {
|
synchronized (channel) {
|
||||||
|
// Check if the channel is usable (has money, inactive) and if so, activate it.
|
||||||
|
if (channel.valueToMe.equals(BigInteger.ZERO))
|
||||||
|
continue;
|
||||||
if (!channel.active) {
|
if (!channel.active) {
|
||||||
channel.active = true;
|
channel.active = true;
|
||||||
return channel;
|
return channel;
|
||||||
@ -244,7 +249,7 @@ class StoredClientChannel {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final String newline = String.format("%n");
|
final String newline = String.format("%n");
|
||||||
return String.format("Stored client channel %s (%s)%n" +
|
return String.format("Stored client channel for server ID %s (%s)%n" +
|
||||||
" Key: %s%n" +
|
" Key: %s%n" +
|
||||||
" Value to me: %d%n" +
|
" Value to me: %d%n" +
|
||||||
" Refund fees: %d%n" +
|
" Refund fees: %d%n" +
|
||||||
|
@ -575,4 +575,43 @@ public class ChannelConnectionTest extends TestWithWallet {
|
|||||||
assertEquals(Protos.Error.ErrorCode.SYNTAX_ERROR, error.getError().getCode());
|
assertEquals(Protos.Error.ErrorCode.SYNTAX_ERROR, error.getError().getCode());
|
||||||
assertEquals(CloseReason.REMOTE_SENT_INVALID_MESSAGE, pair.clientRecorder.q.take());
|
assertEquals(CloseReason.REMOTE_SENT_INVALID_MESSAGE, pair.clientRecorder.q.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDontResumeEmptyChannels() throws Exception {
|
||||||
|
// Check that if the client has an empty channel that's being kept around in case we need to broadcast the
|
||||||
|
// refund, we don't accidentally try to resume it).
|
||||||
|
|
||||||
|
// Open up a normal channel.
|
||||||
|
Sha256Hash someServerId = Sha256Hash.ZERO_HASH;
|
||||||
|
ChannelTestUtils.RecordingPair pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
|
||||||
|
pair.server.connectionOpen();
|
||||||
|
PaymentChannelClient client = new PaymentChannelClient(wallet, myKey, Utils.COIN, someServerId, pair.clientRecorder);
|
||||||
|
PaymentChannelServer server = pair.server;
|
||||||
|
client.connectionOpen();
|
||||||
|
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.CLIENT_VERSION));
|
||||||
|
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION));
|
||||||
|
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.INITIATE));
|
||||||
|
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.PROVIDE_REFUND));
|
||||||
|
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.RETURN_REFUND));
|
||||||
|
broadcastTxPause.release();
|
||||||
|
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.PROVIDE_CONTRACT));
|
||||||
|
broadcasts.take();
|
||||||
|
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CHANNEL_OPEN));
|
||||||
|
Sha256Hash contractHash = (Sha256Hash) pair.serverRecorder.q.take();
|
||||||
|
pair.clientRecorder.checkOpened();
|
||||||
|
assertNull(pair.serverRecorder.q.poll());
|
||||||
|
assertNull(pair.clientRecorder.q.poll());
|
||||||
|
// Send the whole channel at once.
|
||||||
|
client.incrementPayment(Utils.COIN);
|
||||||
|
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
|
||||||
|
// The channel is now empty.
|
||||||
|
assertEquals(BigInteger.ZERO, client.state().getValueRefunded());
|
||||||
|
client.connectionClosed();
|
||||||
|
|
||||||
|
// Now try opening a new channel with the same server ID and verify the client asks for a new channel.
|
||||||
|
client = new PaymentChannelClient(wallet, myKey, Utils.COIN, someServerId, pair.clientRecorder);
|
||||||
|
client.connectionOpen();
|
||||||
|
Protos.TwoWayChannelMessage msg = pair.clientRecorder.checkNextMsg(MessageType.CLIENT_VERSION);
|
||||||
|
assertFalse(msg.getClientVersion().hasPreviousChannelContractHash());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user