diff --git a/application/build.gradle b/application/build.gradle index d29e7371..6ae69207 100644 --- a/application/build.gradle +++ b/application/build.gradle @@ -12,6 +12,7 @@ dependencies { runtimeOnly 'org.postgresql:postgresql' testImplementation testFixtures(project(':model')) testImplementation testFixtures(project(':transactions')) + testRuntimeOnly 'com.h2database:h2' } bootJar { diff --git a/application/src/integrationTest/java/de/cotto/lndmanagej/ApplicationContextIT.java b/application/src/integrationTest/java/de/cotto/lndmanagej/ApplicationContextIT.java new file mode 100644 index 00000000..b55b9d86 --- /dev/null +++ b/application/src/integrationTest/java/de/cotto/lndmanagej/ApplicationContextIT.java @@ -0,0 +1,30 @@ +package de.cotto.lndmanagej; + +import de.cotto.lndmanagej.controller.LegacyController; +import de.cotto.lndmanagej.grpc.GrpcRouterService; +import de.cotto.lndmanagej.grpc.GrpcService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +class ApplicationContextIT { + @Autowired + private LegacyController legacyController; + + @MockBean + @SuppressWarnings("unused") + private GrpcService grpcService; + + @MockBean + @SuppressWarnings("unused") + private GrpcRouterService grpcRouterService; + + @Test + void contextStarts() { + assertThat(legacyController).isNotNull(); + } +} \ No newline at end of file diff --git a/application/src/integrationTest/resources/application.properties b/application/src/integrationTest/resources/application.properties new file mode 100644 index 00000000..9c3813c6 --- /dev/null +++ b/application/src/integrationTest/resources/application.properties @@ -0,0 +1 @@ +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE \ No newline at end of file diff --git a/application/src/main/java/de/cotto/lndmanagej/service/ChannelIdResolver.java b/application/src/main/java/de/cotto/lndmanagej/service/ChannelIdResolverImpl.java similarity index 77% rename from application/src/main/java/de/cotto/lndmanagej/service/ChannelIdResolver.java rename to application/src/main/java/de/cotto/lndmanagej/service/ChannelIdResolverImpl.java index 96d386bc..37ff26a8 100644 --- a/application/src/main/java/de/cotto/lndmanagej/service/ChannelIdResolver.java +++ b/application/src/main/java/de/cotto/lndmanagej/service/ChannelIdResolverImpl.java @@ -1,6 +1,7 @@ package de.cotto.lndmanagej.service; import de.cotto.lndmanagej.model.ChannelId; +import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.model.ChannelPoint; import de.cotto.lndmanagej.transactions.model.Transaction; import de.cotto.lndmanagej.transactions.service.TransactionService; @@ -9,14 +10,15 @@ import org.springframework.stereotype.Component; import java.util.Optional; @Component -public class ChannelIdResolver { +public class ChannelIdResolverImpl implements ChannelIdResolver { private final TransactionService transactionService; - public ChannelIdResolver(TransactionService transactionService) { + public ChannelIdResolverImpl(TransactionService transactionService) { this.transactionService = transactionService; } - public Optional resolve(ChannelPoint channelPoint) { + @Override + public Optional resolveFromChannelPoint(ChannelPoint channelPoint) { return transactionService.getTransaction(channelPoint.getTransactionHash()) .map(transaction -> getChannelId(transaction, channelPoint)); } diff --git a/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java b/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java index 4b0e6c87..63492cd9 100644 --- a/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java +++ b/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java @@ -7,10 +7,8 @@ import de.cotto.lndmanagej.model.ClosedChannel; import de.cotto.lndmanagej.model.LocalChannel; import de.cotto.lndmanagej.model.LocalOpenChannel; import de.cotto.lndmanagej.model.Pubkey; -import de.cotto.lndmanagej.model.UnresolvedClosedChannel; import org.springframework.stereotype.Component; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -22,11 +20,9 @@ public class ChannelService { private final LoadingCache> channelsCache; private final LoadingCache> closedChannelsCache; private final GrpcChannels grpcChannels; - private final ChannelIdResolver channelIdResolver; - public ChannelService(GrpcChannels grpcChannels, ChannelIdResolver channelIdResolver) { + public ChannelService(GrpcChannels grpcChannels) { this.grpcChannels = grpcChannels; - this.channelIdResolver = channelIdResolver; channelsCache = new CacheBuilder() .withExpiryMinutes(CACHE_EXPIRY_MINUTES) .build(this.grpcChannels::getChannels); @@ -35,21 +31,6 @@ public class ChannelService { .build(this::getClosedChannelsWithoutCache); } - private Set getClosedChannelsWithoutCache() { - return grpcChannels.getUnresolvedClosedChannels().stream() - .map(this::toClosedChannel) - .flatMap(Optional::stream) - .collect(Collectors.toSet()); - } - - private Optional toClosedChannel(UnresolvedClosedChannel unresolvedClosedChannel) { - if (unresolvedClosedChannel.getId().isUnresolved()) { - return channelIdResolver.resolve(unresolvedClosedChannel.getChannelPoint()) - .map(channelId -> ClosedChannel.create(unresolvedClosedChannel, channelId)); - } - return Optional.of(ClosedChannel.create(unresolvedClosedChannel)); - } - public Set getOpenChannels() { return channelsCache.getUnchecked(""); } @@ -68,7 +49,11 @@ public class ChannelService { Stream openChannels = getOpenChannelsWith(pubkey).stream(); Stream closedChannels = getClosedChannels().stream() .filter(c -> c.getRemotePubkey().equals(pubkey)); - return Stream.concat(openChannels, closedChannels) + return Stream.of(openChannels, closedChannels).flatMap(s -> s) .collect(Collectors.toSet()); } + + private Set getClosedChannelsWithoutCache() { + return grpcChannels.getClosedChannels(); + } } diff --git a/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java b/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java index 9cd5e515..8de24c64 100644 --- a/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java @@ -1,10 +1,7 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.metrics.Metrics; -import de.cotto.lndmanagej.model.Channel; -import de.cotto.lndmanagej.model.ChannelFixtures; import de.cotto.lndmanagej.model.Coins; -import de.cotto.lndmanagej.model.LocalOpenChannel; import de.cotto.lndmanagej.service.BalanceService; import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.FeeService; @@ -18,11 +15,9 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.util.Set; -import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION; import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_COMPACT; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_COMPACT_3; @@ -185,18 +180,14 @@ class LegacyControllerTest { @Test void getPeerPubkeys() { - Channel channel = ChannelFixtures.create(PUBKEY, PUBKEY_3, CHANNEL_ID_2); - LocalOpenChannel channel2 = new LocalOpenChannel(channel, PUBKEY, BALANCE_INFORMATION); - when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, channel2)); + when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_TO_NODE_3)); assertThat(legacyController.getPeerPubkeys()).isEqualTo(PUBKEY_2 + "\n" + PUBKEY_3); verify(metrics).mark(argThat(name -> name.endsWith(".getPeerPubkeys"))); } @Test void getPeerPubkeys_sorted() { - Channel channel = ChannelFixtures.create(PUBKEY, PUBKEY_3, CHANNEL_ID_2); - LocalOpenChannel channel2 = new LocalOpenChannel(channel, PUBKEY, BALANCE_INFORMATION); - when(channelService.getOpenChannels()).thenReturn(Set.of(channel2, LOCAL_OPEN_CHANNEL)); + when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL_TO_NODE_3, LOCAL_OPEN_CHANNEL)); assertThat(legacyController.getPeerPubkeys()).isEqualTo(PUBKEY_2 + "\n" + PUBKEY_3); } diff --git a/application/src/test/java/de/cotto/lndmanagej/service/ChannelIdResolverTest.java b/application/src/test/java/de/cotto/lndmanagej/service/ChannelIdResolverImplTest.java similarity index 83% rename from application/src/test/java/de/cotto/lndmanagej/service/ChannelIdResolverTest.java rename to application/src/test/java/de/cotto/lndmanagej/service/ChannelIdResolverImplTest.java index c5512359..2f16fac9 100644 --- a/application/src/test/java/de/cotto/lndmanagej/service/ChannelIdResolverTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/service/ChannelIdResolverImplTest.java @@ -20,9 +20,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -class ChannelIdResolverTest { +class ChannelIdResolverImplTest { @InjectMocks - private ChannelIdResolver channelIdResolver; + private ChannelIdResolverImpl channelIdResolver; @Mock private TransactionService transactionService; @@ -30,13 +30,13 @@ class ChannelIdResolverTest { @Test void unknown() { when(transactionService.getTransaction(TRANSACTION_HASH)).thenReturn(Optional.empty()); - assertThat(channelIdResolver.resolve(CHANNEL_POINT)).isEmpty(); + assertThat(channelIdResolver.resolveFromChannelPoint(CHANNEL_POINT)).isEmpty(); } @Test void known() { ChannelId expectedChannelId = ChannelId.fromCompactForm(BLOCK_HEIGHT + ":" + POSITION_IN_BLOCK + ":" + OUTPUT); when(transactionService.getTransaction(TRANSACTION_HASH)).thenReturn(Optional.of(TRANSACTION)); - assertThat(channelIdResolver.resolve(CHANNEL_POINT)).contains(expectedChannelId); + assertThat(channelIdResolver.resolveFromChannelPoint(CHANNEL_POINT)).contains(expectedChannelId); } } \ No newline at end of file diff --git a/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java b/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java index 1afa4e2f..2912430c 100644 --- a/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java @@ -1,37 +1,23 @@ package de.cotto.lndmanagej.service; import de.cotto.lndmanagej.grpc.GrpcChannels; -import de.cotto.lndmanagej.model.Channel; -import de.cotto.lndmanagej.model.ChannelFixtures; -import de.cotto.lndmanagej.model.LocalOpenChannel; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.Optional; import java.util.Set; -import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; -import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL; import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL_2; import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL_3; +import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL_TO_NODE_3; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_2; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_3; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_TO_NODE_3; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.CLOSED_CHANNEL_UNRESOLVED_ID; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_2; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_3; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_TO_NODE_3; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @@ -43,9 +29,6 @@ class ChannelServiceTest { @Mock private GrpcChannels grpcChannels; - @Mock - private ChannelIdResolver channelIdResolver; - @Test void getOpenChannelsWith_by_pubkey() { when(grpcChannels.getChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3)); @@ -55,10 +38,8 @@ class ChannelServiceTest { @Test void getOpenChannelsWith_ignores_channel_to_other_node() { - Channel channel = ChannelFixtures.create(PUBKEY, PUBKEY_3, CHANNEL_ID_2); - LocalOpenChannel localOpenChannel2 = new LocalOpenChannel(channel, PUBKEY, BALANCE_INFORMATION); when(grpcChannels.getChannels()).thenReturn( - Set.of(LOCAL_OPEN_CHANNEL, localOpenChannel2, LOCAL_OPEN_CHANNEL_3) + Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_TO_NODE_3, LOCAL_OPEN_CHANNEL_3) ); assertThat(channelService.getOpenChannelsWith(PUBKEY_2)) .containsExactlyInAnyOrder(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3); @@ -73,34 +54,17 @@ class ChannelServiceTest { @Test void getClosedChannels() { - when(grpcChannels.getUnresolvedClosedChannels()) - .thenReturn(Set.of(UNRESOLVED_CLOSED_CHANNEL, UNRESOLVED_CLOSED_CHANNEL_2)); + when(grpcChannels.getClosedChannels()) + .thenReturn(Set.of(CLOSED_CHANNEL, CLOSED_CHANNEL_2)); assertThat(channelService.getClosedChannels()) .containsExactlyInAnyOrder(CLOSED_CHANNEL, CLOSED_CHANNEL_2); } - @Test - void getClosedChannels_resolves_id() { - when(channelIdResolver.resolve(CHANNEL_POINT)).thenReturn(Optional.of(CHANNEL_ID)); - when(grpcChannels.getUnresolvedClosedChannels()) - .thenReturn(Set.of(UNRESOLVED_CLOSED_CHANNEL_2, CLOSED_CHANNEL_UNRESOLVED_ID)); - assertThat(channelService.getClosedChannels()) - .containsExactlyInAnyOrder(CLOSED_CHANNEL, CLOSED_CHANNEL_2); - } - - @Test - void getClosedChannels_unresolvable_id() { - when(channelIdResolver.resolve(CHANNEL_POINT)).thenReturn(Optional.empty()); - when(grpcChannels.getUnresolvedClosedChannels()) - .thenReturn(Set.of(UNRESOLVED_CLOSED_CHANNEL_2, CLOSED_CHANNEL_UNRESOLVED_ID)); - assertThat(channelService.getClosedChannels()).containsExactlyInAnyOrder(CLOSED_CHANNEL_2); - } - @Test void getAllChannels_by_pubkey() { when(grpcChannels.getChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_TO_NODE_3)); - when(grpcChannels.getUnresolvedClosedChannels()) - .thenReturn(Set.of(UNRESOLVED_CLOSED_CHANNEL_3, UNRESOLVED_CLOSED_CHANNEL_TO_NODE_3)); + when(grpcChannels.getClosedChannels()) + .thenReturn(Set.of(CLOSED_CHANNEL_3, CLOSED_CHANNEL_TO_NODE_3)); assertThat(channelService.getAllChannelsWith(PUBKEY_2)) .containsExactlyInAnyOrder(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_3); } diff --git a/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java b/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java index f5e0c8ae..0cd66539 100644 --- a/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java +++ b/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java @@ -1,13 +1,13 @@ package de.cotto.lndmanagej.grpc; import de.cotto.lndmanagej.model.BalanceInformation; -import de.cotto.lndmanagej.model.Channel; import de.cotto.lndmanagej.model.ChannelId; +import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.model.ChannelPoint; +import de.cotto.lndmanagej.model.ClosedChannel; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.LocalOpenChannel; import de.cotto.lndmanagej.model.Pubkey; -import de.cotto.lndmanagej.model.UnresolvedClosedChannel; import lnrpc.ChannelCloseSummary; import lnrpc.ChannelCloseSummary.ClosureType; import org.springframework.stereotype.Component; @@ -21,13 +21,16 @@ import static java.util.stream.Collectors.toSet; public class GrpcChannels { private final GrpcService grpcService; private final GrpcGetInfo grpcGetInfo; + private final ChannelIdResolver channelIdResolver; public GrpcChannels( GrpcService grpcService, - GrpcGetInfo grpcGetInfo + GrpcGetInfo grpcGetInfo, + ChannelIdResolver channelIdResolver ) { this.grpcService = grpcService; this.grpcGetInfo = grpcGetInfo; + this.channelIdResolver = channelIdResolver; } public Set getChannels() { @@ -37,11 +40,12 @@ public class GrpcChannels { .collect(toSet()); } - public Set getUnresolvedClosedChannels() { + public Set getClosedChannels() { Pubkey ownPubkey = grpcGetInfo.getPubkey(); return grpcService.getClosedChannels().stream() - .filter(this::shouldConsider) - .map(channelCloseSummary -> toUnresolvedClosedChannel(channelCloseSummary, ownPubkey)) + .filter(this::hasSupportedCloseType) + .map(channelCloseSummary -> toClosedChannel(channelCloseSummary, ownPubkey)) + .flatMap(Optional::stream) .collect(toSet()); } @@ -55,45 +59,40 @@ public class GrpcChannels { } private LocalOpenChannel toLocalOpenChannel(lnrpc.Channel lndChannel, Pubkey ownPubkey) { - Channel channel = Channel.builder() - .withChannelId(ChannelId.fromShortChannelId(lndChannel.getChanId())) - .withCapacity(Coins.ofSatoshis(lndChannel.getCapacity())) - .withChannelPoint(ChannelPoint.create(lndChannel.getChannelPoint())) - .withNode1(ownPubkey) - .withNode2(Pubkey.create(lndChannel.getRemotePubkey())) - .build(); + ChannelId channelId = ChannelId.fromShortChannelId(lndChannel.getChanId()); + ChannelPoint channelPoint = ChannelPoint.create(lndChannel.getChannelPoint()); + Pubkey remotePubkey = Pubkey.create(lndChannel.getRemotePubkey()); + Coins capacity = Coins.ofSatoshis(lndChannel.getCapacity()); BalanceInformation balanceInformation = new BalanceInformation( Coins.ofSatoshis(lndChannel.getLocalBalance()), Coins.ofSatoshis(lndChannel.getLocalConstraints().getChanReserveSat()), Coins.ofSatoshis(lndChannel.getRemoteBalance()), Coins.ofSatoshis(lndChannel.getRemoteConstraints().getChanReserveSat()) ); - return new LocalOpenChannel(channel, ownPubkey, balanceInformation); + return new LocalOpenChannel(channelId, channelPoint, capacity, ownPubkey, remotePubkey, balanceInformation); } - private UnresolvedClosedChannel toUnresolvedClosedChannel( + private Optional toClosedChannel( ChannelCloseSummary channelCloseSummary, Pubkey ownPubkey ) { - Channel channel = Channel.builder() - .withChannelId(getChannelId(channelCloseSummary)) - .withChannelPoint(ChannelPoint.create(channelCloseSummary.getChannelPoint())) - .withCapacity(Coins.ofSatoshis(channelCloseSummary.getCapacity())) - .withNode1(ownPubkey) - .withNode2(Pubkey.create(channelCloseSummary.getRemotePubkey())) - .build(); - return new UnresolvedClosedChannel(channel, ownPubkey); + ChannelPoint channelPoint = ChannelPoint.create(channelCloseSummary.getChannelPoint()); + Pubkey remotePubkey = Pubkey.create(channelCloseSummary.getRemotePubkey()); + Coins capacity = Coins.ofSatoshis(channelCloseSummary.getCapacity()); + return getChannelId(channelCloseSummary) + .or(() -> channelIdResolver.resolveFromChannelPoint(channelPoint)) + .map(id -> new ClosedChannel(id, channelPoint, capacity, ownPubkey, remotePubkey)); } - private ChannelId getChannelId(ChannelCloseSummary channelCloseSummary) { + private Optional getChannelId(ChannelCloseSummary channelCloseSummary) { long chanId = channelCloseSummary.getChanId(); if (chanId == 0) { - return ChannelId.UNRESOLVED; + return Optional.empty(); } - return ChannelId.fromShortChannelId(chanId); + return Optional.of(ChannelId.fromShortChannelId(chanId)); } - private boolean shouldConsider(ChannelCloseSummary channelCloseSummary) { + private boolean hasSupportedCloseType(ChannelCloseSummary channelCloseSummary) { ClosureType closeType = channelCloseSummary.getCloseType(); return closeType != ClosureType.ABANDONED && closeType != ClosureType.FUNDING_CANCELED; } diff --git a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java index 4e3e1e75..2f43eeda 100644 --- a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java +++ b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java @@ -1,6 +1,7 @@ package de.cotto.lndmanagej.grpc; import de.cotto.lndmanagej.model.ChannelId; +import de.cotto.lndmanagej.model.ChannelIdResolver; import lnrpc.Channel; import lnrpc.ChannelCloseSummary; import lnrpc.ChannelConstraints; @@ -12,22 +13,27 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; +import java.util.Optional; import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION; import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; +import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL; +import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL_2; +import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL_3; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_2; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.CLOSED_CHANNEL_UNRESOLVED_ID; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_2; import static lnrpc.ChannelCloseSummary.ClosureType.ABANDONED; import static lnrpc.ChannelCloseSummary.ClosureType.FUNDING_CANCELED; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -41,6 +47,9 @@ class GrpcChannelsTest { @Mock private GrpcGetInfo grpcGetInfo; + @Mock + private ChannelIdResolver channelIdResolver; + @BeforeEach void setUp() { when(grpcGetInfo.getPubkey()).thenReturn(PUBKEY); @@ -58,48 +67,54 @@ class GrpcChannelsTest { } @Test - void getUnresolvedClosedChannels_empty() { - assertThat(grpcChannels.getUnresolvedClosedChannels()).isEmpty(); + void getClosedChannels_empty() { + assertThat(grpcChannels.getClosedChannels()).isEmpty(); } @Test - void getUnresolvedClosedChannels() { + void getClosedChannels() { when(grpcService.getClosedChannels()).thenReturn( List.of(closedChannel(CHANNEL_ID.getShortChannelId()), closedChannel(CHANNEL_ID_2.getShortChannelId())) ); - assertThat(grpcChannels.getUnresolvedClosedChannels()) - .containsExactlyInAnyOrder(UNRESOLVED_CLOSED_CHANNEL, UNRESOLVED_CLOSED_CHANNEL_2); + assertThat(grpcChannels.getClosedChannels()) + .containsExactlyInAnyOrder(CLOSED_CHANNEL, CLOSED_CHANNEL_2); + verify(channelIdResolver, never()).resolveFromChannelPoint(any()); } @Test - void getUnresolvedClosedChannels_with_zero_channel_id() { + void getClosedChannels_with_zero_channel_id_not_resolved() { when(grpcService.getClosedChannels()).thenReturn( List.of(closedChannel(CHANNEL_ID.getShortChannelId()), closedChannel(0)) ); - assertThat(grpcChannels.getUnresolvedClosedChannels()).containsExactlyInAnyOrder( - UNRESOLVED_CLOSED_CHANNEL, - CLOSED_CHANNEL_UNRESOLVED_ID - ); + assertThat(grpcChannels.getClosedChannels()).containsExactlyInAnyOrder(CLOSED_CHANNEL); + verify(channelIdResolver).resolveFromChannelPoint(CHANNEL_POINT); } @Test - void getUnresolvedClosedChannels_ignores_abandoned() { + void getClosedChannels_with_zero_channel_id_resolved() { + when(channelIdResolver.resolveFromChannelPoint(CHANNEL_POINT)).thenReturn(Optional.of(CHANNEL_ID_3)); + when(grpcService.getClosedChannels()).thenReturn( + List.of(closedChannel(CHANNEL_ID.getShortChannelId()), closedChannel(0)) + ); + assertThat(grpcChannels.getClosedChannels()).containsExactlyInAnyOrder(CLOSED_CHANNEL, CLOSED_CHANNEL_3); + } + + @Test + void getClosedChannels_ignores_abandoned() { when(grpcService.getClosedChannels()).thenReturn( List.of(closedChannel(CHANNEL_ID.getShortChannelId()), closedChannelWithType(ABANDONED)) ); - assertThat(grpcChannels.getUnresolvedClosedChannels()).containsExactlyInAnyOrder( - UNRESOLVED_CLOSED_CHANNEL - ); + assertThat(grpcChannels.getClosedChannels()).containsExactlyInAnyOrder(CLOSED_CHANNEL); + verify(channelIdResolver, never()).resolveFromChannelPoint(any()); } @Test - void getUnresolvedClosedChannels_ignores_funding_canceled() { + void getClosedChannels_ignores_funding_canceled() { when(grpcService.getClosedChannels()).thenReturn( List.of(closedChannel(CHANNEL_ID.getShortChannelId()), closedChannelWithType(FUNDING_CANCELED)) ); - assertThat(grpcChannels.getUnresolvedClosedChannels()).containsExactlyInAnyOrder( - UNRESOLVED_CLOSED_CHANNEL - ); + assertThat(grpcChannels.getClosedChannels()).containsExactlyInAnyOrder(CLOSED_CHANNEL); + verify(channelIdResolver, never()).resolveFromChannelPoint(any()); } @Test diff --git a/model/src/main/java/de/cotto/lndmanagej/model/Channel.java b/model/src/main/java/de/cotto/lndmanagej/model/Channel.java index 6e890123..8f2b6415 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/Channel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/Channel.java @@ -1,38 +1,22 @@ package de.cotto.lndmanagej.model; -import org.springframework.lang.Nullable; - -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; import java.util.Objects; import java.util.Set; -import static java.util.Objects.requireNonNull; - public class Channel { private final ChannelId channelId; private final Coins capacity; private final ChannelPoint channelPoint; private final Set pubkeys; - private Channel(ChannelId channelId, Coins capacity, ChannelPoint channelPoint, Pubkey pubkey1, Pubkey pubkey2) { - this(channelId, capacity, channelPoint, List.of(pubkey1, pubkey2)); - } - - protected Channel(ChannelId channelId, Coins capacity, ChannelPoint channelPoint, Collection pubkeys) { + protected Channel(ChannelId channelId, ChannelPoint channelPoint, Coins capacity, Pubkey pubkey1, Pubkey pubkey2) { + if (pubkey1.equals(pubkey2)) { + throw new IllegalArgumentException("Pubkeys must not be the same"); + } this.channelId = channelId; - this.capacity = Coins.ofMilliSatoshis(capacity.milliSatoshis()); + this.capacity = capacity; this.channelPoint = channelPoint; - this.pubkeys = new LinkedHashSet<>(pubkeys); - } - - public static Builder builder() { - return new Builder(); - } - - public Channel getWithId(ChannelId channelId) { - return new Channel(channelId, getCapacity(), getChannelPoint(), getPubkeys()); + this.pubkeys = Set.of(pubkey1, pubkey2); } public Coins getCapacity() { @@ -51,61 +35,6 @@ public class Channel { return channelPoint; } - public static class Builder { - @Nullable - private ChannelId channelId; - - @Nullable - private Coins capacity; - - @Nullable - private ChannelPoint channelPoint; - - @Nullable - private Pubkey pubkey1; - - @Nullable - private Pubkey pubkey2; - - public Builder withChannelId(ChannelId channelId) { - this.channelId = channelId; - return this; - } - - public Builder withCapacity(Coins capacity) { - this.capacity = capacity; - return this; - } - - public Builder withChannelPoint(ChannelPoint channelPoint) { - this.channelPoint = channelPoint; - return this; - } - - public Builder withNode1(Pubkey pubkey) { - this.pubkey1 = pubkey; - return this; - } - - public Builder withNode2(Pubkey pubkey) { - pubkey2 = pubkey; - return this; - } - - public Channel build() { - if (requireNonNull(pubkey1).equals(requireNonNull(pubkey2))) { - throw new IllegalArgumentException("Pubkeys must not be the same"); - } - return new Channel( - requireNonNull(channelId), - requireNonNull(capacity), - requireNonNull(channelPoint), - requireNonNull(pubkey1), - requireNonNull(pubkey2) - ); - } - } - @Override public boolean equals(Object other) { if (this == other) { diff --git a/model/src/main/java/de/cotto/lndmanagej/model/ChannelId.java b/model/src/main/java/de/cotto/lndmanagej/model/ChannelId.java index 5efff44f..37327691 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/ChannelId.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/ChannelId.java @@ -4,7 +4,6 @@ import javax.annotation.Nonnull; import java.util.Objects; public final class ChannelId implements Comparable { - public static final ChannelId UNRESOLVED = new ChannelId(-1); private final long shortChannelId; private static final int EXPECTED_NUMBER_OF_SEGMENTS = 3; private static final long NOT_BEFORE = 430_103_660_018_532_352L; // January 1st 2016 @@ -34,9 +33,6 @@ public final class ChannelId implements Comparable { } public String getCompactForm() { - if (isUnresolved()) { - throw new IllegalStateException("Channel ID must be resolved"); - } long block = shortChannelId >> 40; long transaction = shortChannelId >> 16 & 0xFFFFFF; long output = shortChannelId & 0xFFFF; @@ -44,16 +40,9 @@ public final class ChannelId implements Comparable { } public long getShortChannelId() { - if (isUnresolved()) { - throw new IllegalStateException("Channel ID must be resolved"); - } return shortChannelId; } - public boolean isUnresolved() { - return UNRESOLVED.equals(this); - } - @Override public boolean equals(Object other) { if (this == other) { @@ -73,17 +62,11 @@ public final class ChannelId implements Comparable { @Override public String toString() { - if (isUnresolved()) { - return "UNRESOLVED_CHANNEL_ID"; - } return String.valueOf(shortChannelId); } @Override public int compareTo(@Nonnull ChannelId other) { - if ((isUnresolved() || other.isUnresolved()) && !this.equals(other)) { - throw new IllegalStateException("Cannot compare with unresolved channel ID"); - } return Long.compare(shortChannelId, other.shortChannelId); } } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/ChannelIdResolver.java b/model/src/main/java/de/cotto/lndmanagej/model/ChannelIdResolver.java new file mode 100644 index 00000000..f3a04a44 --- /dev/null +++ b/model/src/main/java/de/cotto/lndmanagej/model/ChannelIdResolver.java @@ -0,0 +1,7 @@ +package de.cotto.lndmanagej.model; + +import java.util.Optional; + +public interface ChannelIdResolver { + Optional resolveFromChannelPoint(ChannelPoint channelPoint); +} diff --git a/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java index 4878e68e..2fbcbf64 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java @@ -1,18 +1,13 @@ package de.cotto.lndmanagej.model; public final class ClosedChannel extends LocalChannel { - private ClosedChannel(LocalChannel localChannel, Pubkey ownPubkey) { - super(localChannel, ownPubkey); - } - - public static ClosedChannel create(UnresolvedClosedChannel unresolvedClosedChannel) { - return create(unresolvedClosedChannel, unresolvedClosedChannel.getId()); - } - - public static ClosedChannel create(UnresolvedClosedChannel unresolvedClosedChannel, ChannelId channelId) { - if (channelId.isUnresolved()) { - throw new IllegalArgumentException("Channel ID must be resolved"); - } - return new ClosedChannel(unresolvedClosedChannel.getWithId(channelId), unresolvedClosedChannel.getOwnPubkey()); + public ClosedChannel( + ChannelId channelId, + ChannelPoint channelPoint, + Coins capacity, + Pubkey ownPubkey, + Pubkey remotePubkey + ) { + super(channelId, channelPoint, capacity, ownPubkey, remotePubkey); } } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java index ce358e8f..97edb3f4 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java @@ -1,21 +1,19 @@ package de.cotto.lndmanagej.model; import java.util.Objects; -import java.util.Set; public class LocalChannel extends Channel { private final Pubkey remotePubkey; - protected LocalChannel(Channel channel, Pubkey ownPubkey) { - super(channel.getId(), channel.getCapacity(), channel.getChannelPoint(), channel.getPubkeys()); - Set pubkeys = channel.getPubkeys(); - remotePubkey = pubkeys.stream() - .filter(pubkey -> !ownPubkey.equals(pubkey)) - .findFirst() - .orElseThrow(); - if (!pubkeys.contains(ownPubkey)) { - throw new IllegalArgumentException("Channel must have given pubkey as peer"); - } + protected LocalChannel( + ChannelId channelId, + ChannelPoint channelPoint, + Coins capacity, + Pubkey ownPubkey, + Pubkey remotePubkey + ) { + super(channelId, channelPoint, capacity, ownPubkey, remotePubkey); + this.remotePubkey = remotePubkey; } public Pubkey getRemotePubkey() { @@ -23,6 +21,7 @@ public class LocalChannel extends Channel { } @Override + @SuppressWarnings("CPD-START") public boolean equals(Object other) { if (this == other) { return true; diff --git a/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java index 4743967d..dc85e22d 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java @@ -5,8 +5,15 @@ import java.util.Objects; public class LocalOpenChannel extends LocalChannel { private final BalanceInformation balanceInformation; - public LocalOpenChannel(Channel channel, Pubkey ownPubkey, BalanceInformation balanceInformation) { - super(channel, ownPubkey); + public LocalOpenChannel( + ChannelId channelId, + ChannelPoint channelPoint, + Coins capacity, + Pubkey ownPubkey, + Pubkey remotePubkey, + BalanceInformation balanceInformation + ) { + super(channelId, channelPoint, capacity, ownPubkey, remotePubkey); this.balanceInformation = balanceInformation; } @@ -15,7 +22,6 @@ public class LocalOpenChannel extends LocalChannel { } @Override - @SuppressWarnings("CPD-START") public boolean equals(Object other) { if (this == other) { return true; diff --git a/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java deleted file mode 100644 index 475eca3f..00000000 --- a/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.cotto.lndmanagej.model; - -public class UnresolvedClosedChannel extends LocalChannel { - private final Pubkey ownPubkey; - - public UnresolvedClosedChannel(Channel channel, Pubkey ownPubkey) { - super(channel, ownPubkey); - this.ownPubkey = ownPubkey; - } - - @Override - public LocalChannel getWithId(ChannelId channelId) { - return new UnresolvedClosedChannel(super.getWithId(channelId), ownPubkey); - } - - public Pubkey getOwnPubkey() { - return ownPubkey; - } -} diff --git a/model/src/test/java/de/cotto/lndmanagej/model/ChannelIdTest.java b/model/src/test/java/de/cotto/lndmanagej/model/ChannelIdTest.java index 37f34b70..ca781942 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/ChannelIdTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/ChannelIdTest.java @@ -8,7 +8,6 @@ import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_COMPACT; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; class ChannelIdTest { @@ -133,56 +132,6 @@ class ChannelIdTest { assertThat(CHANNEL_ID.getCompactForm()).isEqualTo(CHANNEL_ID_COMPACT); } - @Test - void isUnresolved_true() { - assertThat(ChannelId.UNRESOLVED.isUnresolved()).isTrue(); - } - - @Test - void isUnresolved_false() { - assertThat(CHANNEL_ID.isUnresolved()).isFalse(); - } - - @Test - void getCompactForm_unresolved() { - assertThatIllegalStateException() - .isThrownBy(ChannelId.UNRESOLVED::getCompactForm) - .withMessage("Channel ID must be resolved"); - } - - @Test - void shortChannelId_unresolved() { - assertThatIllegalStateException() - .isThrownBy(ChannelId.UNRESOLVED::getShortChannelId) - .withMessage("Channel ID must be resolved"); - } - - @Test - void compareTo_unresolved_to_other() { - assertThatIllegalStateException() - .isThrownBy(() -> ChannelId.UNRESOLVED.compareTo(CHANNEL_ID)) - .withMessage("Cannot compare with unresolved channel ID"); - } - - @Test - void compareTo_other_to_unresolved() { - assertThatIllegalStateException() - .isThrownBy(() -> CHANNEL_ID.compareTo(ChannelId.UNRESOLVED)) - .withMessage("Cannot compare with unresolved channel ID"); - } - - @Test - @SuppressWarnings("SelfComparison") - void compareTo_unresolved() { - //noinspection EqualsWithItself - assertThat(ChannelId.UNRESOLVED.compareTo(ChannelId.UNRESOLVED)).isEqualTo(0); - } - - @Test - void toString_unresolved() { - assertThat(ChannelId.UNRESOLVED).hasToString("UNRESOLVED_CHANNEL_ID"); - } - @Test void testEquals() { EqualsVerifier.forClass(ChannelId.class).verify(); diff --git a/model/src/test/java/de/cotto/lndmanagej/model/ChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/ChannelTest.java index ec9dc18b..4d02640a 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/ChannelTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/ChannelTest.java @@ -4,110 +4,24 @@ import nl.jqno.equalsverifier.EqualsVerifier; import org.junit.jupiter.api.Test; import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatNullPointerException; class ChannelTest { - @Test - void builder_without_arguments() { - assertThatNullPointerException().isThrownBy( - () -> Channel.builder().build() - ); - } + + private static final Channel CHANNEL = new TestableChannel(CHANNEL_ID, CAPACITY, CHANNEL_POINT, PUBKEY_2, PUBKEY); @Test - void builder_without_channelId() { - assertThatNullPointerException().isThrownBy( - () -> Channel.builder() - .withCapacity(CAPACITY) - .withChannelPoint(CHANNEL_POINT) - .withNode1(PUBKEY) - .withNode2(PUBKEY_2) - .build() - ); - } - - @Test - void builder_without_capacity() { - assertThatNullPointerException().isThrownBy( - () -> Channel.builder() - .withChannelId(CHANNEL_ID) - .withNode1(PUBKEY) - .withChannelPoint(CHANNEL_POINT) - .withNode2(PUBKEY_2) - .build() - ); - } - - @Test - void builder_without_channel_point() { - assertThatNullPointerException().isThrownBy( - () -> Channel.builder() - .withChannelId(CHANNEL_ID) - .withNode1(PUBKEY) - .withCapacity(CAPACITY) - .withNode2(PUBKEY_2) - .build() - ); - } - - @Test - void builder_without_node1() { - assertThatNullPointerException().isThrownBy( - () -> Channel.builder() - .withChannelId(CHANNEL_ID) - .withCapacity(CAPACITY) - .withChannelPoint(CHANNEL_POINT) - .withNode2(PUBKEY_2) - .build() - ); - } - - @Test - void builder_without_node2() { - assertThatNullPointerException().isThrownBy( - () -> Channel.builder() - .withChannelId(CHANNEL_ID) - .withCapacity(CAPACITY) - .withChannelPoint(CHANNEL_POINT) - .withNode1(PUBKEY) - .build() - ); - } - - @Test - void builder_identical_pubkeys() { + void identical_pubkeys() { assertThatIllegalArgumentException().isThrownBy( - () -> Channel.builder() - .withChannelId(CHANNEL_ID) - .withCapacity(CAPACITY) - .withChannelPoint(CHANNEL_POINT) - .withNode1(PUBKEY) - .withNode2(PUBKEY) - .build() + () -> new TestableChannel(CHANNEL_ID, CAPACITY, CHANNEL_POINT, PUBKEY, PUBKEY) ).withMessage("Pubkeys must not be the same"); } - @Test - void builder_with_all_arguments() { - Channel channel = Channel.builder() - .withChannelId(CHANNEL_ID) - .withCapacity(CAPACITY) - .withNode1(PUBKEY) - .withNode2(PUBKEY_2) - .withChannelPoint(CHANNEL_POINT) - .build(); - assertThat(channel).isEqualTo(CHANNEL); - } - @Test void getId() { assertThat(CHANNEL.getId()).isEqualTo(CHANNEL_ID); @@ -128,11 +42,6 @@ class ChannelTest { assertThat(CHANNEL.getChannelPoint()).isEqualTo(CHANNEL_POINT); } - @Test - void getWithId() { - assertThat(CHANNEL.getWithId(CHANNEL_ID_2)).isEqualTo(CHANNEL_2); - } - @Test void testEquals() { EqualsVerifier.forClass(Channel.class).usingGetClass().verify(); @@ -140,13 +49,19 @@ class ChannelTest { @Test void testEquals_reversed_nodes() { - Channel channel = Channel.builder() - .withChannelId(CHANNEL_ID) - .withCapacity(CAPACITY) - .withChannelPoint(CHANNEL_POINT) - .withNode1(PUBKEY_2) - .withNode2(PUBKEY) - .build(); - assertThat(CHANNEL).isEqualTo(channel); + Channel channel2 = new TestableChannel(CHANNEL_ID, CAPACITY, CHANNEL_POINT, PUBKEY, PUBKEY_2); + assertThat(CHANNEL).isEqualTo(channel2); + } + + private static class TestableChannel extends Channel { + public TestableChannel( + ChannelId channelId, + Coins capacity, + ChannelPoint channelPoint, + Pubkey pubkey1, + Pubkey pubkey2 + ) { + super(channelId, channelPoint, Coins.ofMilliSatoshis(capacity.milliSatoshis()), pubkey1, pubkey2); + } } } \ No newline at end of file diff --git a/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java index 09be21cf..a14c6b23 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java @@ -9,40 +9,12 @@ import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.CLOSED_CHANNEL_UNRESOLVED_ID; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; class ClosedChannelTest { @Test - void create_with_implicit_channel_id() { - assertThat(ClosedChannel.create(UNRESOLVED_CLOSED_CHANNEL)).isEqualTo(CLOSED_CHANNEL); - } - - @Test - void create_with_unresolved_channel_id() { - assertThatIllegalArgumentException() - .isThrownBy(() -> ClosedChannel.create(CLOSED_CHANNEL_UNRESOLVED_ID)) - .withMessage("Channel ID must be resolved"); - } - - @Test - void create_with_explicit_channel_id() { - assertThat(ClosedChannel.create(CLOSED_CHANNEL_UNRESOLVED_ID, CHANNEL_ID)).isEqualTo(CLOSED_CHANNEL); - } - - @Test - void create_with_explicit_channel_id_retains_remote_pubkey() { - ClosedChannel closedChannel = ClosedChannel.create(CLOSED_CHANNEL_UNRESOLVED_ID, CHANNEL_ID); - assertThat(closedChannel.getRemotePubkey()).isEqualTo(CLOSED_CHANNEL_UNRESOLVED_ID.getRemotePubkey()); - } - - @Test - void create_with_explicit_unresolved_channel_id() { - assertThatIllegalArgumentException() - .isThrownBy(() -> ClosedChannel.create(CLOSED_CHANNEL_UNRESOLVED_ID, ChannelId.UNRESOLVED)) - .withMessage("Channel ID must be resolved"); + void create() { + assertThat(new ClosedChannel(CHANNEL_ID, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2)).isEqualTo(CLOSED_CHANNEL); } @Test diff --git a/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java index 7a37b1ad..a98a419f 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java @@ -8,35 +8,25 @@ import static de.cotto.lndmanagej.model.BalanceInformationFixtures.LOCAL_BALANCE import static de.cotto.lndmanagej.model.BalanceInformationFixtures.LOCAL_RESERVE; import static de.cotto.lndmanagej.model.BalanceInformationFixtures.REMOTE_BALANCE; import static de.cotto.lndmanagej.model.BalanceInformationFixtures.REMOTE_RESERVE; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_2; +import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; class LocalOpenChannelTest { @Test void getRemotePubkey() { - Channel channel = ChannelFixtures.create(PUBKEY_2, PUBKEY, CHANNEL_ID); - LocalOpenChannel localOpenChannel = new LocalOpenChannel(channel, PUBKEY, BALANCE_INFORMATION); - assertThat(localOpenChannel.getRemotePubkey()).isEqualTo(PUBKEY_2); + assertThat(LOCAL_OPEN_CHANNEL.getRemotePubkey()).isEqualTo(PUBKEY_2); } @Test void getRemotePubkey_swapped() { - Channel channel = ChannelFixtures.create(PUBKEY_3, PUBKEY_2, CHANNEL_ID); - LocalOpenChannel localOpenChannel = new LocalOpenChannel(channel, PUBKEY_3, BALANCE_INFORMATION); - assertThat(localOpenChannel.getRemotePubkey()).isEqualTo(PUBKEY_2); - } - - @Test - void ownPubkey_not_in_pubkey_set() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new LocalOpenChannel(CHANNEL_2, PUBKEY_3, BALANCE_INFORMATION)) - .withMessage("Channel must have given pubkey as peer"); + LocalOpenChannel localOpenChannel = + new LocalOpenChannel(CHANNEL_ID, CHANNEL_POINT, CAPACITY, PUBKEY_2, PUBKEY, BALANCE_INFORMATION); + assertThat(localOpenChannel.getRemotePubkey()).isEqualTo(PUBKEY); } @Test diff --git a/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java deleted file mode 100644 index f1eb18e3..00000000 --- a/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.cotto.lndmanagej.model; - -import org.junit.jupiter.api.Test; - -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_2; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.CLOSED_CHANNEL_UNRESOLVED_ID; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -class UnresolvedClosedChannelTest { - @Test - void getRemotePubkey() { - Channel channel = ChannelFixtures.create(PUBKEY_2, PUBKEY, CHANNEL_ID); - UnresolvedClosedChannel unresolvedClosedChannel = - new UnresolvedClosedChannel(channel, PUBKEY); - assertThat(unresolvedClosedChannel.getRemotePubkey()).isEqualTo(PUBKEY_2); - } - - @Test - void getRemotePubkey_swapped() { - Channel channel = ChannelFixtures.create(PUBKEY_3, PUBKEY_2, CHANNEL_ID); - UnresolvedClosedChannel unresolvedClosedChannel = - new UnresolvedClosedChannel(channel, PUBKEY_3); - assertThat(unresolvedClosedChannel.getRemotePubkey()).isEqualTo(PUBKEY_2); - } - - @Test - void ownPubkey_not_in_pubkey_set() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new UnresolvedClosedChannel(CHANNEL_2, PUBKEY_3)) - .withMessage("Channel must have given pubkey as peer"); - } - - @Test - void getWithId() { - assertThat(CLOSED_CHANNEL_UNRESOLVED_ID.getWithId(CHANNEL_ID)).isEqualTo(UNRESOLVED_CLOSED_CHANNEL); - } - - @Test - void getOwnPubkey() { - Channel channel = ChannelFixtures.create(PUBKEY_3, PUBKEY_2, CHANNEL_ID); - UnresolvedClosedChannel unresolvedClosedChannel = - new UnresolvedClosedChannel(channel, PUBKEY_3); - assertThat(unresolvedClosedChannel.getOwnPubkey()).isEqualTo(PUBKEY_3); - } -} \ No newline at end of file diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/ChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/ChannelFixtures.java index 26c322a7..d3544918 100644 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/ChannelFixtures.java +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/ChannelFixtures.java @@ -1,39 +1,6 @@ package de.cotto.lndmanagej.model; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; -import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; -import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; - -public final class ChannelFixtures { +public class ChannelFixtures { public static final Coins CAPACITY = Coins.ofSatoshis(21_000_000L); public static final Coins CAPACITY_2 = Coins.ofSatoshis(42_000_000L); - - public static final Channel CHANNEL = create(PUBKEY, PUBKEY_2, CHANNEL_ID); - public static final Channel CHANNEL_UNRESOLVED_ID = create(PUBKEY, PUBKEY_2, ChannelId.UNRESOLVED); - public static final Channel CHANNEL_2 = create(PUBKEY, PUBKEY_2, CHANNEL_ID_2); - public static final Channel CHANNEL_3 = create(PUBKEY, PUBKEY_2, CHANNEL_ID_3); - public static final Channel CHANNEL_TO_NODE_3 = create(PUBKEY, PUBKEY_3, CHANNEL_ID_4, CAPACITY_2); - - private ChannelFixtures() { - // do not instantiate - } - - public static Channel create(Pubkey pubkey1, Pubkey pubkey2, ChannelId channelId) { - return create(pubkey1, pubkey2, channelId, CAPACITY); - } - - public static Channel create(Pubkey pubkey1, Pubkey pubkey2, ChannelId channelId, Coins capacity) { - return Channel.builder() - .withChannelId(channelId) - .withCapacity(capacity) - .withChannelPoint(CHANNEL_POINT) - .withNode1(pubkey1) - .withNode2(pubkey2) - .build(); - } } diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/ClosedChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/ClosedChannelFixtures.java index 1d0d36b9..fcc1cdf5 100644 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/ClosedChannelFixtures.java +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/ClosedChannelFixtures.java @@ -1,11 +1,21 @@ package de.cotto.lndmanagej.model; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_2; -import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_3; +import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; +import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; public class ClosedChannelFixtures { - public static final ClosedChannel CLOSED_CHANNEL = ClosedChannel.create(UNRESOLVED_CLOSED_CHANNEL); - public static final ClosedChannel CLOSED_CHANNEL_2 = ClosedChannel.create(UNRESOLVED_CLOSED_CHANNEL_2); - public static final ClosedChannel CLOSED_CHANNEL_3 = ClosedChannel.create(UNRESOLVED_CLOSED_CHANNEL_3); + public static final ClosedChannel CLOSED_CHANNEL = + new ClosedChannel(CHANNEL_ID, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2); + public static final ClosedChannel CLOSED_CHANNEL_2 + = new ClosedChannel(CHANNEL_ID_2, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2); + public static final ClosedChannel CLOSED_CHANNEL_3 = + new ClosedChannel(CHANNEL_ID_3, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2); + public static final ClosedChannel CLOSED_CHANNEL_TO_NODE_3 = + new ClosedChannel(CHANNEL_ID_3, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_3); } diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java index 4e8c4d41..ac9eec3f 100644 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java @@ -1,19 +1,24 @@ package de.cotto.lndmanagej.model; import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_2; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_3; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_TO_NODE_3; +import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; +import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; +import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; public class LocalOpenChannelFixtures { public static final LocalOpenChannel LOCAL_OPEN_CHANNEL = - new LocalOpenChannel(CHANNEL, PUBKEY, BALANCE_INFORMATION); + new LocalOpenChannel(CHANNEL_ID, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2, BALANCE_INFORMATION); public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_2 = - new LocalOpenChannel(CHANNEL_2, PUBKEY, BALANCE_INFORMATION); + new LocalOpenChannel(CHANNEL_ID_2, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2, BALANCE_INFORMATION); public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_3 = - new LocalOpenChannel(CHANNEL_3, PUBKEY, BALANCE_INFORMATION); + new LocalOpenChannel(CHANNEL_ID_3, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2, BALANCE_INFORMATION); public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_TO_NODE_3 = - new LocalOpenChannel(CHANNEL_TO_NODE_3, PUBKEY, BALANCE_INFORMATION); + new LocalOpenChannel(CHANNEL_ID_4, CHANNEL_POINT, CAPACITY_2, PUBKEY, PUBKEY_3, BALANCE_INFORMATION); } diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java deleted file mode 100644 index 498851a7..00000000 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.cotto.lndmanagej.model; - -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_2; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_3; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_TO_NODE_3; -import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_UNRESOLVED_ID; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; - -public class UnresolvedClosedChannelFixtures { - public static final UnresolvedClosedChannel UNRESOLVED_CLOSED_CHANNEL = - new UnresolvedClosedChannel(CHANNEL, PUBKEY); - public static final UnresolvedClosedChannel CLOSED_CHANNEL_UNRESOLVED_ID = - new UnresolvedClosedChannel(CHANNEL_UNRESOLVED_ID, PUBKEY); - public static final UnresolvedClosedChannel UNRESOLVED_CLOSED_CHANNEL_2 = - new UnresolvedClosedChannel(CHANNEL_2, PUBKEY); - public static final UnresolvedClosedChannel UNRESOLVED_CLOSED_CHANNEL_3 = - new UnresolvedClosedChannel(CHANNEL_3, PUBKEY); - public static final UnresolvedClosedChannel UNRESOLVED_CLOSED_CHANNEL_TO_NODE_3 = - new UnresolvedClosedChannel(CHANNEL_TO_NODE_3, PUBKEY); -}