mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 02:12:00 +01:00
Merge branch 'master' into misc-dao-improvements
This commit is contained in:
commit
0198bf4c23
@ -53,29 +53,38 @@ public class Capabilities {
|
||||
this.capabilities.addAll(capabilities);
|
||||
}
|
||||
|
||||
public void resetCapabilities(Capability... capabilities) {
|
||||
resetCapabilities(Arrays.asList(capabilities));
|
||||
public void set(Capability... capabilities) {
|
||||
set(Arrays.asList(capabilities));
|
||||
}
|
||||
|
||||
public void resetCapabilities(Capabilities capabilities) {
|
||||
resetCapabilities(capabilities.capabilities);
|
||||
public void set(Capabilities capabilities) {
|
||||
set(capabilities.capabilities);
|
||||
}
|
||||
|
||||
public void resetCapabilities(Collection<Capability> capabilities) {
|
||||
public void set(Collection<Capability> capabilities) {
|
||||
this.capabilities.clear();
|
||||
this.capabilities.addAll(capabilities);
|
||||
}
|
||||
|
||||
public boolean isCapabilitySupported(final Set<Capability> requiredItems) {
|
||||
public void addAll(Capability... capabilities) {
|
||||
this.capabilities.addAll(Arrays.asList(capabilities));
|
||||
}
|
||||
|
||||
public void addAll(Capabilities capabilities) {
|
||||
if(capabilities != null)
|
||||
this.capabilities.addAll(capabilities.capabilities);
|
||||
}
|
||||
|
||||
public boolean containsAll(final Set<Capability> requiredItems) {
|
||||
return capabilities.containsAll(requiredItems);
|
||||
}
|
||||
|
||||
public boolean isCapabilitySupported(final Capabilities capabilities) {
|
||||
return isCapabilitySupported(capabilities.capabilities);
|
||||
public boolean containsAll(final Capabilities capabilities) {
|
||||
return containsAll(capabilities.capabilities);
|
||||
}
|
||||
|
||||
public boolean hasCapabilities() {
|
||||
return !capabilities.isEmpty();
|
||||
public boolean isEmpty() {
|
||||
return capabilities.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
28
common/src/main/java/bisq/common/app/HasCapabilities.java
Normal file
28
common/src/main/java/bisq/common/app/HasCapabilities.java
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.common.app;
|
||||
|
||||
/**
|
||||
* Holds a set of {@link Capabilities}.
|
||||
*
|
||||
* @author Florian Reimair
|
||||
*/
|
||||
public interface HasCapabilities {
|
||||
|
||||
Capabilities getCapabilities();
|
||||
}
|
@ -31,15 +31,15 @@ public class CapabilitiesTest {
|
||||
public void testNoCapabilitiesAvailable() {
|
||||
Capabilities DUT = new Capabilities();
|
||||
|
||||
assertTrue(DUT.isCapabilitySupported(new HashSet<>()));
|
||||
assertFalse(DUT.isCapabilitySupported(new Capabilities(SEED_NODE)));
|
||||
assertTrue(DUT.containsAll(new HashSet<>()));
|
||||
assertFalse(DUT.containsAll(new Capabilities(SEED_NODE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testO() {
|
||||
Capabilities DUT = new Capabilities(TRADE_STATISTICS);
|
||||
|
||||
assertTrue(DUT.isCapabilitySupported(new HashSet<>()));
|
||||
assertTrue(DUT.containsAll(new HashSet<>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -47,17 +47,17 @@ public class CapabilitiesTest {
|
||||
Capabilities DUT = new Capabilities(TRADE_STATISTICS);
|
||||
|
||||
// single match
|
||||
assertTrue(DUT.isCapabilitySupported(new Capabilities(TRADE_STATISTICS)));
|
||||
assertFalse(DUT.isCapabilitySupported(new Capabilities(SEED_NODE)));
|
||||
assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS)));
|
||||
assertFalse(DUT.containsAll(new Capabilities(SEED_NODE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiMatch() {
|
||||
Capabilities DUT = new Capabilities(TRADE_STATISTICS, TRADE_STATISTICS_2);
|
||||
|
||||
assertTrue(DUT.isCapabilitySupported(new Capabilities(TRADE_STATISTICS)));
|
||||
assertFalse(DUT.isCapabilitySupported(new Capabilities(SEED_NODE)));
|
||||
assertTrue(DUT.isCapabilitySupported(new Capabilities(TRADE_STATISTICS, TRADE_STATISTICS_2)));
|
||||
assertFalse(DUT.isCapabilitySupported(new Capabilities(SEED_NODE, TRADE_STATISTICS_2)));
|
||||
assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS)));
|
||||
assertFalse(DUT.containsAll(new Capabilities(SEED_NODE)));
|
||||
assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS, TRADE_STATISTICS_2)));
|
||||
assertFalse(DUT.containsAll(new Capabilities(SEED_NODE, TRADE_STATISTICS_2)));
|
||||
}
|
||||
}
|
||||
|
@ -168,17 +168,17 @@ public final class RepublishGovernanceDataHandler {
|
||||
Capabilities required = new Capabilities(Capability.DAO_FULL_NODE);
|
||||
|
||||
List<Peer> list = peerManager.getLivePeers(null).stream()
|
||||
.filter(peer -> peer.isCapabilitySupported(required))
|
||||
.filter(peer -> peer.getCapabilities().containsAll(required))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (list.isEmpty())
|
||||
list = peerManager.getReportedPeers().stream()
|
||||
.filter(peer -> peer.isCapabilitySupported(required))
|
||||
.filter(peer -> peer.getCapabilities().containsAll(required))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (list.isEmpty())
|
||||
list = peerManager.getPersistedPeers().stream()
|
||||
.filter(peer -> peer.isCapabilitySupported(required))
|
||||
.filter(peer -> peer.getCapabilities().containsAll(required))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
|
@ -28,24 +28,14 @@ import java.util.Arrays;
|
||||
|
||||
public class CoreNetworkCapabilities {
|
||||
public static void setSupportedCapabilities(BisqEnvironment bisqEnvironment) {
|
||||
final ArrayList<Capability> supportedCapabilities = new ArrayList<>(Arrays.asList(
|
||||
Capability.TRADE_STATISTICS,
|
||||
Capability.TRADE_STATISTICS_2,
|
||||
Capability.ACCOUNT_AGE_WITNESS,
|
||||
Capability.ACK_MSG
|
||||
));
|
||||
Capabilities.app.addAll(Capability.TRADE_STATISTICS, Capability.TRADE_STATISTICS_2, Capability.ACCOUNT_AGE_WITNESS, Capability.ACK_MSG);
|
||||
|
||||
if (BisqEnvironment.isDaoActivated(bisqEnvironment)) {
|
||||
supportedCapabilities.add(Capability.PROPOSAL);
|
||||
supportedCapabilities.add(Capability.BLIND_VOTE);
|
||||
supportedCapabilities.add(Capability.BSQ_BLOCK);
|
||||
supportedCapabilities.add(Capability.DAO_STATE);
|
||||
Capabilities.app.addAll(Capability.PROPOSAL, Capability.BLIND_VOTE, Capability.BSQ_BLOCK, Capability.DAO_STATE);
|
||||
|
||||
String isFullDaoNode = bisqEnvironment.getProperty(DaoOptionKeys.FULL_DAO_NODE, String.class, "");
|
||||
if (isFullDaoNode != null && !isFullDaoNode.isEmpty())
|
||||
supportedCapabilities.add(Capability.DAO_FULL_NODE);
|
||||
Capabilities.app.addAll(Capability.DAO_FULL_NODE);
|
||||
}
|
||||
|
||||
Capabilities.app.resetCapabilities(supportedCapabilities);
|
||||
}
|
||||
}
|
||||
|
@ -138,12 +138,7 @@ public class P2PNetworkLoad extends Metric implements MessageListener, SetupList
|
||||
|
||||
history = Collections.synchronizedMap(new FixedSizeHistoryTracker(Integer.parseInt(configuration.getProperty(HISTORY_SIZE, "200"))));
|
||||
|
||||
// add all capabilities
|
||||
List<Integer> capabilityOrdinals = Capabilities.toIntList(Capabilities.app);
|
||||
if(!capabilityOrdinals.contains(Capability.DAO_FULL_NODE.ordinal())) {
|
||||
capabilityOrdinals.add(Capability.DAO_FULL_NODE.ordinal());
|
||||
Capabilities.app.resetCapabilities(Capabilities.fromIntList(capabilityOrdinals));
|
||||
}
|
||||
Capabilities.app.addAll(Capability.DAO_FULL_NODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -619,10 +619,10 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
|
||||
// it from old versions, so we filter those.
|
||||
Optional<Peer> optionalPeer = allPeers.stream()
|
||||
.filter(peer -> peer.getNodeAddress().equals(peersNodeAddress))
|
||||
.filter(peer -> peer.hasCapabilities())
|
||||
.filter(peer -> !peer.getCapabilities().isEmpty())
|
||||
.findAny();
|
||||
if (optionalPeer.isPresent()) {
|
||||
boolean result = optionalPeer.get().isCapabilitySupported(((CapabilityRequiringPayload) message).getRequiredCapabilities());
|
||||
boolean result = optionalPeer.get().getCapabilities().containsAll(((CapabilityRequiringPayload) message).getRequiredCapabilities());
|
||||
|
||||
if (!result)
|
||||
log.warn("We don't send the message because the peer does not support the required capability. " +
|
||||
|
@ -38,6 +38,7 @@ import bisq.network.p2p.storage.payload.ProtectedStoragePayload;
|
||||
import bisq.common.Proto;
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.Capabilities;
|
||||
import bisq.common.app.HasCapabilities;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.proto.ProtobufferException;
|
||||
import bisq.common.proto.network.NetworkEnvelope;
|
||||
@ -93,7 +94,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
* All handlers are called on User thread.
|
||||
*/
|
||||
@Slf4j
|
||||
public class Connection extends Capabilities implements Runnable, MessageListener {
|
||||
public class Connection implements HasCapabilities, Runnable, MessageListener {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Enums
|
||||
@ -166,6 +167,8 @@ public class Connection extends Capabilities implements Runnable, MessageListene
|
||||
private RuleViolation ruleViolation;
|
||||
private final ConcurrentHashMap<RuleViolation, Integer> ruleViolations = new ConcurrentHashMap<>();
|
||||
|
||||
private Capabilities capabilities = new Capabilities();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
@ -218,6 +221,11 @@ public class Connection extends Capabilities implements Runnable, MessageListene
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public Capabilities getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
// Called from various threads
|
||||
public void sendMessage(NetworkEnvelope networkEnvelope) {
|
||||
log.debug(">> Send networkEnvelope of type: " + networkEnvelope.getClass().getSimpleName());
|
||||
@ -284,14 +292,14 @@ public class Connection extends Capabilities implements Runnable, MessageListene
|
||||
final ProtectedStoragePayload protectedStoragePayload = (((AddDataMessage) msg).getProtectedStorageEntry()).getProtectedStoragePayload();
|
||||
result = !(protectedStoragePayload instanceof CapabilityRequiringPayload);
|
||||
if(!result)
|
||||
result = isCapabilitySupported(((CapabilityRequiringPayload) protectedStoragePayload).getRequiredCapabilities());
|
||||
result = capabilities.containsAll(((CapabilityRequiringPayload) protectedStoragePayload).getRequiredCapabilities());
|
||||
} else if (msg instanceof AddPersistableNetworkPayloadMessage) {
|
||||
final PersistableNetworkPayload persistableNetworkPayload = ((AddPersistableNetworkPayloadMessage) msg).getPersistableNetworkPayload();
|
||||
result = !(persistableNetworkPayload instanceof CapabilityRequiringPayload);
|
||||
if(!result)
|
||||
result = isCapabilitySupported(((CapabilityRequiringPayload) persistableNetworkPayload).getRequiredCapabilities());
|
||||
result = capabilities.containsAll(((CapabilityRequiringPayload) persistableNetworkPayload).getRequiredCapabilities());
|
||||
} else if(msg instanceof CapabilityRequiringPayload) {
|
||||
result = isCapabilitySupported(((CapabilityRequiringPayload) msg).getRequiredCapabilities());
|
||||
result = capabilities.containsAll(((CapabilityRequiringPayload) msg).getRequiredCapabilities());
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
@ -739,7 +747,7 @@ public class Connection extends Capabilities implements Runnable, MessageListene
|
||||
}
|
||||
|
||||
if (networkEnvelope instanceof SupportedCapabilitiesMessage)
|
||||
resetCapabilities(((SupportedCapabilitiesMessage) networkEnvelope).getSupportedCapabilities());
|
||||
capabilities.set(((SupportedCapabilitiesMessage) networkEnvelope).getSupportedCapabilities());
|
||||
|
||||
if (networkEnvelope instanceof CloseConnectionMessage) {
|
||||
// If we get a CloseConnectionMessage we shut down
|
||||
|
@ -282,10 +282,18 @@ public class TorNetworkNode extends NetworkNode {
|
||||
});
|
||||
log.info("It will take some time for the HS to be reachable (~40 seconds). You will be notified about this");
|
||||
} catch (TorCtlException e) {
|
||||
log.error("Tor node creation failed: " + (e.getCause() != null ? e.getCause().toString() : e.toString()));
|
||||
restartTor(e.getMessage());
|
||||
String msg = e.getCause() != null ? e.getCause().toString() : e.toString();
|
||||
log.error("Tor node creation failed: {}", msg);
|
||||
if (e.getCause() instanceof IOException) {
|
||||
// Since we cannot connect to Tor, we cannot do nothing.
|
||||
// Furthermore, we have no hidden services started yet, so there is no graceful
|
||||
// shutdown needed either
|
||||
UserThread.execute(() -> setupListeners.forEach(s -> s.onSetupFailed(new RuntimeException(msg))));
|
||||
} else {
|
||||
restartTor(e.getMessage());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Could not connect to running Tor: " + e.getMessage());
|
||||
log.error("Could not connect to running Tor: {}", e.getMessage());
|
||||
// Since we cannot connect to Tor, we cannot do nothing.
|
||||
// Furthermore, we have no hidden services started yet, so there is no graceful
|
||||
// shutdown needed either
|
||||
|
@ -176,7 +176,7 @@ public class PeerManager implements ConnectionListener, PersistedDataHost {
|
||||
PeerList persistedPeerList = storage.initAndGetPersistedWithFileName("PeerList", 1000);
|
||||
if (persistedPeerList != null) {
|
||||
long peersWithNoCapabilitiesSet = persistedPeerList.getList().stream()
|
||||
.filter(e -> e.hasCapabilities())
|
||||
.filter(e -> e.getCapabilities().isEmpty())
|
||||
.mapToInt(e -> 1)
|
||||
.count();
|
||||
if (peersWithNoCapabilitiesSet > 100) {
|
||||
@ -660,18 +660,18 @@ public class PeerManager implements ConnectionListener, PersistedDataHost {
|
||||
// filter(connection -> connection.getPeersNodeAddressOptional().isPresent())
|
||||
return networkNode.getConfirmedConnections().stream()
|
||||
.map((Connection connection) -> {
|
||||
Capabilities supportedCapabilities = new Capabilities(connection);
|
||||
Capabilities supportedCapabilities = new Capabilities(connection.getCapabilities());
|
||||
// If we have a new connection the supportedCapabilities is empty.
|
||||
// We lookup if we have already stored the supportedCapabilities at the persisted or reported peers
|
||||
// and if so we use that.
|
||||
if (!supportedCapabilities.hasCapabilities()) {
|
||||
if (supportedCapabilities.isEmpty()) {
|
||||
Set<Peer> allPeers = new HashSet<>(getPersistedPeers());
|
||||
allPeers.addAll(getReportedPeers());
|
||||
Optional<Peer> ourPeer = allPeers.stream().filter(peer -> peer.getNodeAddress().equals(connection.getPeersNodeAddressOptional().get()))
|
||||
.filter(peer -> !peer.hasCapabilities())
|
||||
.filter(peer -> !peer.getCapabilities().isEmpty())
|
||||
.findAny();
|
||||
if(ourPeer.isPresent())
|
||||
supportedCapabilities = new Capabilities(ourPeer.get());
|
||||
supportedCapabilities = new Capabilities(ourPeer.get().getCapabilities());
|
||||
}
|
||||
Peer peer = new Peer(connection.getPeersNodeAddressOptional().get(), supportedCapabilities);
|
||||
connection.addWeakCapabilitiesListener(peer);
|
||||
|
@ -158,7 +158,7 @@ public class GetDataRequestHandler {
|
||||
final ProtectedStoragePayload protectedStoragePayload = protectedStorageEntry.getProtectedStoragePayload();
|
||||
boolean doAdd = false;
|
||||
if (protectedStoragePayload instanceof CapabilityRequiringPayload) {
|
||||
if (connection.isCapabilitySupported(((CapabilityRequiringPayload) protectedStoragePayload).getRequiredCapabilities()))
|
||||
if (connection.getCapabilities().containsAll(((CapabilityRequiringPayload) protectedStoragePayload).getRequiredCapabilities()))
|
||||
doAdd = true;
|
||||
else
|
||||
log.debug("We do not send the message to the peer because he does not support the required capability for that message type.\n" +
|
||||
|
@ -21,6 +21,7 @@ import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.network.SupportedCapabilitiesListener;
|
||||
|
||||
import bisq.common.app.Capabilities;
|
||||
import bisq.common.app.HasCapabilities;
|
||||
import bisq.common.proto.network.NetworkPayload;
|
||||
import bisq.common.proto.persistable.PersistablePayload;
|
||||
|
||||
@ -28,7 +29,6 @@ import io.bisq.generated.protobuffer.PB;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -36,10 +36,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode(exclude = {"date"}, callSuper = true)
|
||||
// failedConnectionAttempts is transient and therefore excluded anyway
|
||||
@Slf4j
|
||||
public final class Peer extends Capabilities implements NetworkPayload, PersistablePayload, SupportedCapabilitiesListener {
|
||||
public final class Peer implements HasCapabilities, NetworkPayload, PersistablePayload, SupportedCapabilitiesListener {
|
||||
private static final int MAX_FAILED_CONNECTION_ATTEMPTS = 5;
|
||||
|
||||
private final NodeAddress nodeAddress;
|
||||
@ -48,6 +46,7 @@ public final class Peer extends Capabilities implements NetworkPayload, Persista
|
||||
|
||||
@Setter
|
||||
transient private int failedConnectionAttempts = 0;
|
||||
private Capabilities capabilities = new Capabilities();
|
||||
|
||||
public Peer(NodeAddress nodeAddress, @Nullable Capabilities supportedCapabilities) {
|
||||
this(nodeAddress, new Date().getTime(), supportedCapabilities);
|
||||
@ -58,9 +57,10 @@ public final class Peer extends Capabilities implements NetworkPayload, Persista
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Peer(NodeAddress nodeAddress, long date, Capabilities supportedCapabilities) {
|
||||
super(supportedCapabilities);
|
||||
super();
|
||||
this.nodeAddress = nodeAddress;
|
||||
this.date = date;
|
||||
this.capabilities.addAll(supportedCapabilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,7 +68,7 @@ public final class Peer extends Capabilities implements NetworkPayload, Persista
|
||||
return PB.Peer.newBuilder()
|
||||
.setNodeAddress(nodeAddress.toProtoMessage())
|
||||
.setDate(date)
|
||||
.addAllSupportedCapabilities(Capabilities.toIntList(this))
|
||||
.addAllSupportedCapabilities(Capabilities.toIntList(getCapabilities()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -97,8 +97,8 @@ public final class Peer extends Capabilities implements NetworkPayload, Persista
|
||||
|
||||
@Override
|
||||
public void onChanged(Capabilities supportedCapabilities) {
|
||||
if (supportedCapabilities.hasCapabilities())
|
||||
resetCapabilities(supportedCapabilities);
|
||||
if (!supportedCapabilities.isEmpty())
|
||||
capabilities.set(supportedCapabilities);
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,10 +63,7 @@ public class SeedNodeMain extends ExecutableForAppWithP2p {
|
||||
|
||||
@Override
|
||||
protected void addCapabilities() {
|
||||
// TODO got even worse after refactoring
|
||||
List<Integer> current = Capabilities.toIntList(Capabilities.app);
|
||||
current.add(Capability.SEED_NODE.ordinal());
|
||||
Capabilities.app.resetCapabilities(Capabilities.fromIntList(current));
|
||||
Capabilities.app.addAll(Capability.SEED_NODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user