From 2e8fcc931219b06641294630dd3c9b6caee55ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Brandst=C3=A4tter?= Date: Thu, 19 Dec 2024 21:59:03 +0100 Subject: [PATCH 01/12] feat: Support for Yaml configuration and List values (#17088) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timo Brandstätter --- .../node/app/test/grpc/GrpcTestBase.java | 12 + .../node/config/VersionedConfigImpl.java | 5 + .../config/converter/AccountIDConverter.java | 3 +- .../CongestionMultipliersConverter.java | 4 +- .../config/converter/ContractIDConverter.java | 3 +- .../EntityScaleFactorsConverter.java | 4 +- .../config/converter/FileIDConverter.java | 3 +- .../converter/KeyValuePairConverter.java | 3 +- .../converter/KnownBlockValuesConverter.java | 3 +- .../config/converter/LongPairConverter.java | 3 +- .../converter/ScaleFactorConverter.java | 3 +- .../config/sources/DynamicConfigSource.java | 12 + .../config/sources/PropertyConfigSource.java | 12 + .../docs/base/configuration/configuration.md | 20 +- .../com/swirlds/config/api/Configuration.java | 7 + .../config/api/source/ConfigSource.java | 37 +-- .../sources/AbstractConfigSource.java | 19 ++ .../extensions/sources/ConfigMapping.java | 4 - .../sources/MappedConfigSource.java | 111 ++++++-- .../sources/SimpleConfigSource.java | 84 ++++-- .../SystemEnvironmentConfigSource.java | 19 ++ .../sources/SystemPropertiesConfigSource.java | 19 ++ .../extensions/sources/YamlConfigSource.java | 251 ++++++++++++++++++ .../src/main/java/module-info.java | 3 + .../test/MappedConfigSourceTest.java | 15 +- .../test/sources/YamlConfigSourceTest.java | 71 +++++ .../src/test/resources/test.yaml | 17 ++ .../test/fixtures/TestConfigBuilder.java | 2 - .../impl/converters/BigDecimalConverter.java | 3 +- .../impl/converters/BigIntegerConverter.java | 3 +- .../impl/converters/BooleanConverter.java | 3 +- .../config/impl/converters/ByteConverter.java | 3 +- .../impl/converters/ChronoUnitConverter.java | 3 +- .../impl/converters/DoubleConverter.java | 3 +- .../impl/converters/DurationConverter.java | 3 +- .../config/impl/converters/FileConverter.java | 3 +- .../impl/converters/FloatConverter.java | 3 +- .../impl/converters/InetAddressConverter.java | 44 +++ .../impl/converters/IntegerConverter.java | 3 +- .../config/impl/converters/LongConverter.java | 3 +- .../config/impl/converters/PathConverter.java | 3 +- .../impl/converters/ShortConverter.java | 3 +- .../impl/converters/StringConverter.java | 3 +- .../config/impl/converters/UriConverter.java | 3 +- .../config/impl/converters/UrlConverter.java | 3 +- .../converters/ZonedDateTimeConverter.java | 3 +- .../impl/internal/ConfigDataFactory.java | 6 +- .../internal/ConfigPropertiesService.java | 42 ++- .../impl/internal/ConfigurationImpl.java | 34 ++- .../impl/internal/ConverterService.java | 5 + .../swirlds/config/impl/ConfigApiTests.java | 2 +- .../config/impl/TestDateConverter.java | 3 +- 52 files changed, 815 insertions(+), 121 deletions(-) create mode 100644 platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/YamlConfigSource.java create mode 100644 platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/sources/YamlConfigSourceTest.java create mode 100644 platform-sdk/swirlds-config-extensions/src/test/resources/test.yaml create mode 100644 platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/InetAddressConverter.java diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/test/grpc/GrpcTestBase.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/test/grpc/GrpcTestBase.java index 88fcc00be632..e06f66f51325 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/test/grpc/GrpcTestBase.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/test/grpc/GrpcTestBase.java @@ -59,6 +59,7 @@ import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.HashSet; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.Executors; @@ -334,6 +335,17 @@ public String getValue(@NonNull String s) throws NoSuchElementException { }; } + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return false; + } + + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + return List.of(); + } + public int port() { return port; } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/VersionedConfigImpl.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/VersionedConfigImpl.java index 57de26c83404..9c390501b230 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/VersionedConfigImpl.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/VersionedConfigImpl.java @@ -56,6 +56,11 @@ public boolean exists(@NonNull final String s) { return wrappedConfig.exists(s); } + @Override + public boolean isListValue(@NonNull final String propertyName) { + return wrappedConfig.isListValue(propertyName); + } + @Override public String getValue(@NonNull final String s) throws NoSuchElementException { return wrappedConfig.getValue(s); diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/AccountIDConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/AccountIDConverter.java index 43d4f4b70516..3a191eb0d962 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/AccountIDConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/AccountIDConverter.java @@ -18,6 +18,7 @@ import com.hedera.hapi.node.base.AccountID; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.util.stream.Stream; /** @@ -26,7 +27,7 @@ public class AccountIDConverter implements ConfigConverter { @Override - public AccountID convert(final String value) throws IllegalArgumentException, NullPointerException { + public AccountID convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/CongestionMultipliersConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/CongestionMultipliersConverter.java index a5c957a2e178..1b123f182991 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/CongestionMultipliersConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/CongestionMultipliersConverter.java @@ -18,6 +18,7 @@ import com.hedera.node.config.types.CongestionMultipliers; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Config api {@link ConfigConverter} implementation for the type {@link CongestionMultipliers}. @@ -25,7 +26,8 @@ public class CongestionMultipliersConverter implements ConfigConverter { @Override - public CongestionMultipliers convert(final String value) throws IllegalArgumentException, NullPointerException { + public CongestionMultipliers convert(@NonNull final String value) + throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ContractIDConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ContractIDConverter.java index f0ac1580dc1d..3b23efb9ef02 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ContractIDConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ContractIDConverter.java @@ -18,6 +18,7 @@ import com.hedera.hapi.node.base.ContractID; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.util.stream.Stream; /** @@ -26,7 +27,7 @@ public class ContractIDConverter implements ConfigConverter { @Override - public ContractID convert(final String value) throws IllegalArgumentException, NullPointerException { + public ContractID convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/EntityScaleFactorsConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/EntityScaleFactorsConverter.java index 11f884161131..d6e57f2baba1 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/EntityScaleFactorsConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/EntityScaleFactorsConverter.java @@ -18,6 +18,7 @@ import com.hedera.node.config.types.EntityScaleFactors; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Config api {@link ConfigConverter} implementation for the type {@link EntityScaleFactors}. @@ -25,7 +26,8 @@ public class EntityScaleFactorsConverter implements ConfigConverter { @Override - public EntityScaleFactors convert(final String value) throws IllegalArgumentException, NullPointerException { + public EntityScaleFactors convert(@NonNull final String value) + throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/FileIDConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/FileIDConverter.java index fce0b94aba2d..5c7703e874aa 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/FileIDConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/FileIDConverter.java @@ -18,6 +18,7 @@ import com.hedera.hapi.node.base.FileID; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.util.stream.Stream; /** @@ -26,7 +27,7 @@ public class FileIDConverter implements ConfigConverter { @Override - public FileID convert(final String value) throws IllegalArgumentException, NullPointerException { + public FileID convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KeyValuePairConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KeyValuePairConverter.java index f6c28ee1570b..b21df2adb40a 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KeyValuePairConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KeyValuePairConverter.java @@ -18,6 +18,7 @@ import com.hedera.node.config.types.KeyValuePair; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Objects; import java.util.regex.Pattern; @@ -29,7 +30,7 @@ public class KeyValuePairConverter implements ConfigConverter { private static final String PATTERN = Pattern.quote("="); @Override - public KeyValuePair convert(final String value) throws IllegalArgumentException, NullPointerException { + public KeyValuePair convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { Objects.requireNonNull(value, "Parameter 'value' cannot be null"); final String[] split = value.split(PATTERN, 2); if (split.length == 1) { diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KnownBlockValuesConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KnownBlockValuesConverter.java index 0cd5ce932798..5047cf1f7c7a 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KnownBlockValuesConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/KnownBlockValuesConverter.java @@ -18,6 +18,7 @@ import com.hedera.node.app.hapi.utils.sysfiles.domain.KnownBlockValues; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Config api {@link ConfigConverter} implementation for the type {@link KnownBlockValues}. @@ -25,7 +26,7 @@ public class KnownBlockValuesConverter implements ConfigConverter { @Override - public KnownBlockValues convert(final String value) throws IllegalArgumentException, NullPointerException { + public KnownBlockValues convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/LongPairConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/LongPairConverter.java index 272456f0b04b..e769b8aa339e 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/LongPairConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/LongPairConverter.java @@ -18,6 +18,7 @@ import com.hedera.node.config.types.LongPair; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Objects; import java.util.regex.Pattern; @@ -29,7 +30,7 @@ public class LongPairConverter implements ConfigConverter { private static final String PATTERN = Pattern.quote("-"); @Override - public LongPair convert(final String value) throws IllegalArgumentException, NullPointerException { + public LongPair convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { Objects.requireNonNull(value, "Parameter 'value' cannot be null"); final String[] split = value.split(PATTERN, 2); if (split.length <= 1) { diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ScaleFactorConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ScaleFactorConverter.java index 6212c631b631..8a0c76177a60 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ScaleFactorConverter.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/ScaleFactorConverter.java @@ -18,6 +18,7 @@ import com.hedera.node.app.hapi.utils.sysfiles.domain.throttling.ScaleFactor; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Config api {@link ConfigConverter} implementation for the type {@link ScaleFactor}. @@ -25,7 +26,7 @@ public class ScaleFactorConverter implements ConfigConverter { @Override - public ScaleFactor convert(final String value) throws IllegalArgumentException, NullPointerException { + public ScaleFactor convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/DynamicConfigSource.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/DynamicConfigSource.java index 6cf7434cfbff..87163df11674 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/DynamicConfigSource.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/DynamicConfigSource.java @@ -19,6 +19,7 @@ import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; +import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Properties; @@ -54,6 +55,17 @@ public String getValue(@NonNull final String s) throws NoSuchElementException { return properties.getProperty(s); } + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return false; + } + + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + return List.of(); + } + @Override public int getOrdinal() { return 500; diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/PropertyConfigSource.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/PropertyConfigSource.java index 4046f6240bed..907d5233ee4b 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/PropertyConfigSource.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/sources/PropertyConfigSource.java @@ -23,6 +23,7 @@ import edu.umd.cs.findbugs.annotations.Nullable; import java.io.IOException; import java.io.UncheckedIOException; +import java.util.List; import java.util.NoSuchElementException; import java.util.Properties; import java.util.Set; @@ -88,6 +89,17 @@ public String getValue(@NonNull String key) throws NoSuchElementException { return properties.getProperty(key); } + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return false; + } + + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + return List.of(); + } + @Override public int getOrdinal() { return ordinal; diff --git a/platform-sdk/docs/base/configuration/configuration.md b/platform-sdk/docs/base/configuration/configuration.md index 47249fcc0736..c77d5575fd93 100644 --- a/platform-sdk/docs/base/configuration/configuration.md +++ b/platform-sdk/docs/base/configuration/configuration.md @@ -119,22 +119,22 @@ final Configuration config = ConfigurationBuilder.create() String value1 = config.getValue("app.var"); // value1 will be null String value2 = config.getValue("app.var", "default"); // value2 will be null String value3 = config.getValue("app.var", String.class); // value3 will be null -String value4 = config.getValue("app.var", String.class, "default"); // value4 will be null - +String value4 = config.getValue("app.var", String.class, "default"); // value4 will be null + String value5 = config.getValue("app.foo"); // expression will throw a NoSuchElementException String value6 = config.getValue("app.foo", "default"); // value6 will be "default" String value7 = config.getValue("app.foo", String.class); // expression will throw a NoSuchElementException -String value8 = config.getValue("app.foo", String.class, "default"); // value8 will be "default" - +String value8 = config.getValue("app.foo", String.class, "default"); // value8 will be "default" + List value9 = config.getValues("app.vars"); // value9 will be null List value10 = config.getValues("app.vars", List.of()); // value10 will be null List value11 = config.getValues("app.vars", String.class); // value11 will be null -List value12 = config.getValues("app.vars", String.class, List.of()); // value12 will be null - +List value12 = config.getValues("app.vars", String.class, List.of()); // value12 will be null + List value13 = config.getValues("app.foos"); // expression will throw a NoSuchElementException -List value14 = config.getValues("app.foos", List.of()); // value14 will be the empty default list +List value14 = config.getValues("app.foos", List.of()); // value14 will be the empty default list List value15 = config.getValues("app.foos", String.class); // expression will throw a NoSuchElementException -List value16 = config.getValues("app.foos", String.class, List.of()); // value16 will be the empty default list +List value16 = config.getValues("app.foos", String.class, List.of()); // value16 will be the empty default list ``` **Note:** if you want to define an empty list as a value for a property you should define it by @@ -171,7 +171,8 @@ The config API supports several datatypes for reading config properties. The fol 1994-11-05T08:15:30-05:00" - `Duration`: the custom format from the old settings is supported; examples are "2ms" or "10s" - `ChronoUnit`: examples are "millis" or "seconds" -- `Enum` +- `Enum` +- `InetAddress` The support for all data types is done by using the `com.swirlds.config.api.converter.ConfigConverter` API. The `com.swirlds.config.api.ConfigurationBuilder` must be used to add support for custom datatypes. The following code @@ -494,4 +495,3 @@ be changed directly. For the platform the config is provided by the `com.swirlds.common.context.PlatformContext`. Like the context the config is defined in the `com.swirlds.platform.Browser` class. - diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/Configuration.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/Configuration.java index 14759a021220..f7f477f1e99b 100644 --- a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/Configuration.java +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/Configuration.java @@ -51,6 +51,13 @@ public interface Configuration { */ boolean exists(@NonNull String propertyName); + /** + * Checks if the property with the given name is a list property. + * @param propertyName the name of the property that should be checked + * @return true if the property is a list property, false otherwise + */ + boolean isListValue(@NonNull String propertyName); + /** * Returns the {@link String} value of the property with the given name. * diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/ConfigSource.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/ConfigSource.java index 6a73b7e92888..e756d4a2a27d 100644 --- a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/ConfigSource.java +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/ConfigSource.java @@ -18,9 +18,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; @@ -49,11 +47,30 @@ public interface ConfigSource { * * @param propertyName the name of the property * @return the string value of the property - * @throws NoSuchElementException if the property with the given name is not defined in the source + * @throws NoSuchElementException if the property with the given name is not defined in the source OR is a list property */ @Nullable String getValue(@NonNull String propertyName) throws NoSuchElementException; + /** + * Checks if the property with the given name is a list property. + * + * @param propertyName the name of the property + * @return {@code true} if the property is a list property, {@code false} otherwise + * @throws NoSuchElementException if the property with the given name is not defined in the source OR is not a list property + */ + boolean isListProperty(@NonNull String propertyName) throws NoSuchElementException; + + /** + * Returns the list value of the property with the given name. + * + * @param propertyName the name of the property + * @return the list value of the property + * @throws NoSuchElementException if the property with the given name is not defined in the source OR is not a list property + */ + @NonNull + List getListValue(@NonNull String propertyName) throws NoSuchElementException; + /** * Returns the ordinal. The ordinal is used to define a priority order of all config sources while the config source * with the highest ordinal has the highest priority. A config source will overwrite values of properties that are @@ -66,18 +83,6 @@ default int getOrdinal() { return DEFAULT_ORDINAL; } - /** - * Returns all properties of this source as an immutable map. - * - * @return the map with all properties - */ - @NonNull - default Map getProperties() { - final Map props = new HashMap<>(); - getPropertyNames().forEach(prop -> props.put(prop, getValue(prop))); - return Collections.unmodifiableMap(props); - } - /** * Returns the name of the config source. A name must not be unique. * diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/AbstractConfigSource.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/AbstractConfigSource.java index 730607974756..50bfd976cba9 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/AbstractConfigSource.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/AbstractConfigSource.java @@ -19,6 +19,7 @@ import com.swirlds.base.ArgumentUtils; import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; @@ -38,6 +39,7 @@ public abstract class AbstractConfigSource implements ConfigSource { /** * {@inheritDoc} */ + @NonNull @Override public final Set getPropertyNames() { return getInternalProperties().keySet(); @@ -54,4 +56,21 @@ public final String getValue(@NonNull final String propertyName) { } return getInternalProperties().get(propertyName); } + + /** + * This implementation always returns {@code false}. + */ + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return false; + } + + /** + * This implementation always returns an empty list. + */ + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + return List.of(); + } } diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/ConfigMapping.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/ConfigMapping.java index 8f7847204353..39382d652d90 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/ConfigMapping.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/ConfigMapping.java @@ -19,8 +19,6 @@ import com.swirlds.base.ArgumentUtils; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Objects; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; /** * Represents a mapping between an original name and a mapped name. This class is used to hold the mapping configuration @@ -31,8 +29,6 @@ */ public record ConfigMapping(@NonNull String mappedName, @NonNull String originalName) { - private static final Logger logger = LogManager.getLogger(MappedConfigSource.class); - /** * Creates a new {@code ConfigMapping}. * diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/MappedConfigSource.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/MappedConfigSource.java index 4b33c46d5456..a94cb8c607d4 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/MappedConfigSource.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/MappedConfigSource.java @@ -18,12 +18,17 @@ import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Collections; +import edu.umd.cs.findbugs.annotations.Nullable; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Queue; +import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -52,7 +57,7 @@ * @see ConfigSource * @see ConfigMapping */ -public class MappedConfigSource extends AbstractConfigSource { +public class MappedConfigSource implements ConfigSource { private static final String PROPERTY_NOT_FOUND = "Property '{}' not found in original config source"; private static final String PROPERTY_ALREADY_DEFINED = "Property '%s' already defined"; private static final String DUPLICATE_PROPERTY = "Property '{}' already found in original config source"; @@ -63,6 +68,7 @@ public class MappedConfigSource extends AbstractConfigSource { private final Queue configMappings; private final Map properties; + private final Map> listProperties; /** * Constructor that takes the wrapped config. @@ -73,6 +79,7 @@ public MappedConfigSource(@NonNull final ConfigSource wrappedSource) { this.wrappedSource = Objects.requireNonNull(wrappedSource, "wrappedSource must not be null"); configMappings = new ConcurrentLinkedQueue<>(); properties = new HashMap<>(); + listProperties = new HashMap<>(); } /** @@ -106,34 +113,90 @@ public void addMapping(@NonNull final ConfigMapping configMapping) { } configMappings.add(configMapping); + properties.clear(); + listProperties.clear(); } - /** - * {@inheritDoc} - */ - @Override - @NonNull - protected Map getInternalProperties() { - if (properties.isEmpty()) { - final Map internalProperties = wrappedSource.getProperties(); - final Map mappedProperties = new HashMap<>(); - - configMappings.forEach(configMapping -> { - if (internalProperties.containsKey(configMapping.mappedName())) { - logger.warn(DUPLICATE_PROPERTY, configMapping.mappedName()); - } else if (!internalProperties.containsKey(configMapping.originalName())) { - logger.warn(PROPERTY_NOT_FOUND, configMapping.originalName()); + private void generateMapping() { + if (!properties.isEmpty() || !listProperties.isEmpty()) { + return; + } + + final Map internalProperties = new HashMap<>(); + final Map> internalListProperties = new HashMap<>(); + wrappedSource.getPropertyNames().forEach(propertyName -> { + if (wrappedSource.isListProperty(propertyName)) { + internalListProperties.put(propertyName, wrappedSource.getListValue(propertyName)); + } else { + internalProperties.put(propertyName, wrappedSource.getValue(propertyName)); + } + }); + + final Map mappedProperties = new HashMap<>(); + final Map> mappedListProperties = new HashMap<>(); + + configMappings.forEach(configMapping -> { + final String mappedName = configMapping.mappedName(); + final String originalName = configMapping.originalName(); + + if (internalProperties.containsKey(mappedName) || internalListProperties.containsKey(mappedName)) { + logger.warn(DUPLICATE_PROPERTY, mappedName); + } else if (!internalProperties.containsKey(originalName) + && !internalListProperties.containsKey(originalName)) { + logger.warn(PROPERTY_NOT_FOUND, originalName); + } else { + if (wrappedSource.isListProperty(originalName)) { + mappedListProperties.put(mappedName, internalListProperties.get(originalName)); } else { - mappedProperties.put( - configMapping.mappedName(), internalProperties.get(configMapping.originalName())); - logger.debug("Added config mapping: {}", configMapping); + mappedProperties.put(mappedName, internalProperties.get(originalName)); } - }); + logger.debug("Added config mapping: {}", configMapping); + } + }); - properties.putAll(internalProperties); - properties.putAll(mappedProperties); + properties.putAll(internalProperties); + properties.putAll(mappedProperties); + listProperties.putAll(internalListProperties); + listProperties.putAll(mappedListProperties); + } + + @NonNull + @Override + public Set getPropertyNames() { + generateMapping(); + return Stream.concat(properties.keySet().stream(), listProperties.keySet().stream()) + .collect(Collectors.toSet()); + } + + @Nullable + @Override + public String getValue(@NonNull final String propertyName) throws NoSuchElementException { + generateMapping(); + Objects.requireNonNull(propertyName, "propertyName must not be null"); + if (isListProperty(propertyName)) { + throw new NoSuchElementException("Property " + propertyName + " is a list property"); } - return Collections.unmodifiableMap(properties); + + return properties.get(propertyName); + } + + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + generateMapping(); + Objects.requireNonNull(propertyName, "propertyName must not be null"); + return listProperties.containsKey(propertyName); + } + + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + generateMapping(); + Objects.requireNonNull(propertyName, "propertyName must not be null"); + if (!isListProperty(propertyName)) { + throw new NoSuchElementException("Property " + propertyName + " is not a list property"); + } + + return listProperties.get(propertyName); } /** diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SimpleConfigSource.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SimpleConfigSource.java index 6d3d2e0d432a..a17fbf941877 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SimpleConfigSource.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SimpleConfigSource.java @@ -19,41 +19,54 @@ import static com.swirlds.config.extensions.sources.ConfigSourceOrdinalConstants.PROGRAMMATIC_VALUES_ORDINAL; import com.swirlds.base.ArgumentUtils; -import com.swirlds.config.api.Configuration; +import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; /** - * A {@link com.swirlds.config.api.source.ConfigSource} implementation that can be used to provide values of properties + * A {@link ConfigSource} implementation that can be used to provide values of properties * programmatically by calling {@link #withValue(String, Long)} (String, String)}. */ -public final class SimpleConfigSource extends AbstractConfigSource { +public final class SimpleConfigSource implements ConfigSource { private final Map internalProperties; + private final Map> internalListProperties; - private int oridinal = PROGRAMMATIC_VALUES_ORDINAL; + private int ordinal = PROGRAMMATIC_VALUES_ORDINAL; /** * Creates an instance without any config properties. */ public SimpleConfigSource() { - this.internalProperties = new HashMap<>(); + internalProperties = new HashMap<>(); + internalListProperties = new HashMap<>(); } /** - * Creates an instance without any config properties. + * Creates an instance with the given config properties and empty list properties. */ public SimpleConfigSource(@NonNull final Map properties) { + this(properties, new HashMap<>()); + } + + /** + * Creates an instance with the given config properties and list properties. + */ + public SimpleConfigSource( + @NonNull final Map properties, @NonNull final Map> listProperties) { // defensive copy - this.internalProperties = new HashMap<>(Objects.requireNonNull(properties)); + internalProperties = new HashMap<>(Objects.requireNonNull(properties)); + internalListProperties = new HashMap<>(Objects.requireNonNull(listProperties)); } /** @@ -67,6 +80,11 @@ public SimpleConfigSource(final String propertyName, final String value) { withValue(propertyName, value); } + public SimpleConfigSource(final String propertyName, final List value) { + this(); + setValues(propertyName, value, Object::toString); + } + /** * Creates an instance and directly adds the given config property. * @@ -259,12 +277,12 @@ private void setValues( ArgumentUtils.throwArgBlank(propertyName, "propertyName"); Objects.requireNonNull(converter, "converter must not be null"); if (values == null) { - internalProperties.put(propertyName, null); + internalListProperties.put(propertyName, null); } else if (values.isEmpty()) { - internalProperties.put(propertyName, Configuration.EMPTY_LIST); + internalListProperties.put(propertyName, List.of()); } else { - String rawValues = values.stream().map(converter).collect(Collectors.joining(",")); - internalProperties.put(propertyName, rawValues); + final List rawValues = values.stream().map(converter).toList(); + internalListProperties.put(propertyName, rawValues); } } @@ -275,7 +293,7 @@ private void setValues( * @return this */ public SimpleConfigSource withOrdinal(final int ordinal) { - this.oridinal = ordinal; + this.ordinal = ordinal; return this; } @@ -289,9 +307,43 @@ public void reset() { /** * {@inheritDoc} */ + @NonNull + @Override + public Set getPropertyNames() { + return Stream.concat(internalProperties.keySet().stream(), internalListProperties.keySet().stream()) + .collect(Collectors.toSet()); + } + + /** + * {@inheritDoc} + */ + @Nullable @Override - protected Map getInternalProperties() { - return Collections.unmodifiableMap(internalProperties); + public String getValue(@NonNull final String propertyName) throws NoSuchElementException { + if (internalProperties.containsKey(propertyName)) { + return internalProperties.get(propertyName); + } + throw new NoSuchElementException("Property " + propertyName + " not found"); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return internalListProperties.containsKey(propertyName); + } + + /** + * {@inheritDoc} + */ + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + if (internalListProperties.containsKey(propertyName)) { + return internalListProperties.get(propertyName); + } + throw new NoSuchElementException("Property " + propertyName + " not found"); } /** @@ -299,6 +351,6 @@ protected Map getInternalProperties() { */ @Override public int getOrdinal() { - return oridinal; + return ordinal; } } diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemEnvironmentConfigSource.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemEnvironmentConfigSource.java index f747ea93d1ba..7702289ff69c 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemEnvironmentConfigSource.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemEnvironmentConfigSource.java @@ -19,6 +19,7 @@ import com.swirlds.base.ArgumentUtils; import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; @@ -52,6 +53,7 @@ public static SystemEnvironmentConfigSource getInstance() { /** * {@inheritDoc} */ + @NonNull @Override public Set getPropertyNames() { return System.getenv().keySet(); @@ -69,6 +71,23 @@ public String getValue(@NonNull final String propertyName) { return System.getenv(propertyName); } + /** + * {@inheritDoc} + */ + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return false; + } + + /** + * {@inheritDoc} + */ + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + return List.of(); + } + /** * {@inheritDoc} */ diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemPropertiesConfigSource.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemPropertiesConfigSource.java index 8c060c08f20f..239aed5869fa 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemPropertiesConfigSource.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/SystemPropertiesConfigSource.java @@ -19,6 +19,7 @@ import com.swirlds.base.ArgumentUtils; import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; @@ -52,6 +53,7 @@ public static SystemPropertiesConfigSource getInstance() { /** * {@inheritDoc} */ + @NonNull @Override public Set getPropertyNames() { return System.getProperties().stringPropertyNames(); @@ -69,6 +71,23 @@ public String getValue(@NonNull final String propertyName) { return System.getProperty(propertyName); } + /** + * {@inheritDoc} + */ + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + return false; + } + + /** + * {@inheritDoc} + */ + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + return List.of(); + } + /** * {@inheritDoc} */ diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/YamlConfigSource.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/YamlConfigSource.java new file mode 100644 index 000000000000..f61911748a5b --- /dev/null +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/sources/YamlConfigSource.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.extensions.sources; + +import static java.util.Objects.requireNonNull; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.swirlds.config.api.source.ConfigSource; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.yaml.snakeyaml.Yaml; + +/** + * A config source that reads properties from a YAML file. + *
+ * The config source reads the properties from the YAML file. + *
+ * The keys of the properties are the full path of the property in the YAML file, separated by dots. + * For example: + * + * a: + * b: + * c: value + * + * For the above YAML file, the key for the property would be "a.b.c" to retrieve the "value". This complies with the way the + * properties are stored and accessed in the {@link ConfigSource} interface. + *
+ * All list elements are stored as JSON strings and can be deserialized in an {@link com.swirlds.config.api.converter.ConfigConverter} + */ +public class YamlConfigSource implements ConfigSource { + + /** + * The {@link ObjectMapper} used to convert maps to JSON. + */ + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + /** + * The map that contains all not-list properties. + */ + private final Map properties; + + /** + * The map that contains all list properties. + */ + private final Map> listProperties; + + /** + * The ordinal of this config source. + */ + private final int ordinal; + + /** + * Creates a new {@link YamlConfigSource} instance with the given file name and default ordinal. + * + * @param fileName the name of the file that contains the properties + * @see ConfigSource#DEFAULT_ORDINAL + */ + public YamlConfigSource(@NonNull final String fileName) { + this(fileName, DEFAULT_ORDINAL); + } + + /** + * Creates a new {@link YamlConfigSource} instance with the given file name and ordinal. + * + * @param fileName the name of the file that contains the properties + * @param ordinal the ordinal of this config source + */ + public YamlConfigSource(@NonNull final String fileName, final int ordinal) { + requireNonNull(fileName, "fileName must not be null"); + this.properties = new HashMap<>(); + this.listProperties = new HashMap<>(); + this.ordinal = ordinal; + + try (InputStream resource = + Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)) { + if (resource == null) { + throw new UncheckedIOException(new IOException("Resource not found: " + fileName)); + } + convertYamlToMaps(resource); + } catch (IOException e) { + throw new UncheckedIOException("Failed to read YAML file " + fileName, e); + } + } + + /** + * Creates a new {@link YamlConfigSource} instance with the given file path and default ordinal. + * + * @param filePath the name of the file that contains the properties + * @see ConfigSource#DEFAULT_ORDINAL + */ + public YamlConfigSource(@NonNull final Path filePath) { + this(filePath, DEFAULT_ORDINAL); + } + + /** + * Creates a new {@link YamlConfigSource} instance with the given file path and ordinal. + * + * @param filePath the name of the file that contains the properties + * @param ordinal the ordinal of this config source + */ + public YamlConfigSource(@NonNull final Path filePath, final int ordinal) { + requireNonNull(filePath, "filePath must not be null"); + this.properties = new HashMap<>(); + this.listProperties = new HashMap<>(); + this.ordinal = ordinal; + + try (InputStream resource = Files.newInputStream(filePath)) { + convertYamlToMaps(resource); + } catch (IOException e) { + throw new UncheckedIOException("Failed to read YAML file " + filePath, e); + } + } + + private void convertYamlToMaps(@NonNull final InputStream resource) { + Objects.requireNonNull(resource, "resource must not be null"); + final Yaml yaml = new Yaml(); + final Object rawData = yaml.load(resource); + processYamlNode("", rawData, properties, listProperties); + } + + @SuppressWarnings("unchecked") + private void processYamlNode( + @NonNull final String prefix, + @NonNull final Object node, + @NonNull final Map simpleProps, + @NonNull final Map> listProps) { + + if (!(node instanceof Map)) { + return; + } + + final Map map = (Map) node; + for (final Map.Entry entry : map.entrySet()) { + final String newPrefix = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey(); + final Object value = entry.getValue(); + + try { + switch (value) { + case final List list -> handleList(listProps, list, newPrefix); + case final Map mapValue -> handleMap(simpleProps, listProps, mapValue, newPrefix); + case null -> simpleProps.put(newPrefix, null); + default -> simpleProps.put(newPrefix, value.toString()); + } + } catch (JsonProcessingException e) { + throw new IllegalStateException("Failed to convert map to JSON for key: " + newPrefix, e); + } + } + } + + private void handleMap( + final @NonNull Map simpleProps, + final @NonNull Map> listProps, + final Map mapValue, + final String newPrefix) + throws JsonProcessingException { + if (mapValue.values().stream().noneMatch(v -> v instanceof Map || v instanceof List)) { + simpleProps.put(newPrefix, OBJECT_MAPPER.writeValueAsString(mapValue)); + } else { + processYamlNode(newPrefix, mapValue, simpleProps, listProps); + } + } + + private void handleList( + final @NonNull Map> listProps, final List list, final String newPrefix) { + if (!list.isEmpty() && list.getFirst() instanceof Map) { + final List jsonList = list.stream() + .map(item -> { + try { + return OBJECT_MAPPER.writeValueAsString(item); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Failed to convert map to JSON", e); + } + }) + .toList(); + listProps.put(newPrefix, jsonList); + } else { + listProps.put(newPrefix, list.stream().map(Object::toString).toList()); + } + } + + /** {@inheritDoc} */ + @NonNull + @Override + public Set getPropertyNames() { + return Stream.concat(properties.keySet().stream(), listProperties.keySet().stream()) + .collect(Collectors.toSet()); + } + + /** {@inheritDoc} */ + @Nullable + @Override + public String getValue(@NonNull String propertyName) throws NoSuchElementException { + requireNonNull(propertyName, "propertyName must not be null"); + if (isListProperty(propertyName)) { + throw new NoSuchElementException("Property " + propertyName + " is a list property"); + } + return properties.get(propertyName); + } + + /** {@inheritDoc} */ + @Override + public boolean isListProperty(@NonNull final String propertyName) throws NoSuchElementException { + requireNonNull(propertyName, "propertyName must not be null"); + return listProperties.containsKey(propertyName); + } + + /** {@inheritDoc} */ + @NonNull + @Override + public List getListValue(@NonNull final String propertyName) throws NoSuchElementException { + requireNonNull(propertyName, "propertyName must not be null"); + if (!isListProperty(propertyName)) { + throw new NoSuchElementException("Property " + propertyName + " is not a list property"); + } + return listProperties.get(propertyName); + } + + /** {@inheritDoc} */ + @Override + public int getOrdinal() { + return ordinal; + } +} diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/module-info.java b/platform-sdk/swirlds-config-extensions/src/main/java/module-info.java index 5c238d8d0cf9..be27eda4e69b 100644 --- a/platform-sdk/swirlds-config-extensions/src/main/java/module-info.java +++ b/platform-sdk/swirlds-config-extensions/src/main/java/module-info.java @@ -7,6 +7,9 @@ requires transitive com.swirlds.config.api; requires com.swirlds.base; + requires com.fasterxml.jackson.core; + requires com.fasterxml.jackson.databind; requires org.apache.logging.log4j; + requires org.yaml.snakeyaml; requires static transitive com.github.spotbugs.annotations; } diff --git a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java index 20b4fb8e9887..22ea64ef2392 100644 --- a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java +++ b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java @@ -19,6 +19,7 @@ import com.swirlds.config.extensions.sources.MappedConfigSource; import com.swirlds.config.extensions.sources.SimpleConfigSource; import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder; +import java.util.HashMap; import java.util.NoSuchElementException; import java.util.Set; import org.junit.jupiter.api.Assertions; @@ -48,7 +49,7 @@ void testNoAlias() { final var mappedConfigSource = new MappedConfigSource(configSource); // when - final var properties = mappedConfigSource.getProperties(); + final var properties = getObjectObjectHashMap(mappedConfigSource); // then Assertions.assertNotNull(properties); @@ -65,7 +66,7 @@ void testAlias() { // when mappedConfigSource.addMapping("b", "a"); - final var properties = mappedConfigSource.getProperties(); + final var properties = getObjectObjectHashMap(mappedConfigSource); // then Assertions.assertNotNull(properties); @@ -97,7 +98,7 @@ void testAliasForNotExistingProperty() { mappedConfigSource.addMapping("b", "not-available"); // then - Assertions.assertEquals(1, mappedConfigSource.getProperties().size()); + Assertions.assertEquals(1, mappedConfigSource.getPropertyNames().size()); Assertions.assertEquals(Set.of("a"), mappedConfigSource.getPropertyNames()); } @@ -177,7 +178,7 @@ void testNoMappingIfAlreadyInSource() { // when mappedConfigSource.addMapping("foo.a", "a"); - final var properties = mappedConfigSource.getProperties(); + final var properties = getObjectObjectHashMap(mappedConfigSource); // then Assertions.assertNotNull(properties); @@ -185,4 +186,10 @@ void testNoMappingIfAlreadyInSource() { Assertions.assertEquals("1", properties.get("a")); Assertions.assertEquals("2", properties.get("foo.a")); } + + private static HashMap getObjectObjectHashMap(final MappedConfigSource mappedConfigSource) { + final var properties = new HashMap<>(); + mappedConfigSource.getPropertyNames().forEach(p -> properties.put(p, mappedConfigSource.getValue(p))); + return properties; + } } diff --git a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/sources/YamlConfigSourceTest.java b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/sources/YamlConfigSourceTest.java new file mode 100644 index 000000000000..81429dd54968 --- /dev/null +++ b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/sources/YamlConfigSourceTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.extensions.test.sources; + +import com.swirlds.config.extensions.sources.YamlConfigSource; +import java.io.UncheckedIOException; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class YamlConfigSourceTest { + + @Test + void testPropertyConfigSourceWhenPropertyFileNotFound() { + // given + final String nonExistentFile = "non-existent-file.yaml"; + + // then + Assertions.assertThrows(UncheckedIOException.class, () -> new YamlConfigSource(nonExistentFile, 1)); + } + + @Test + void testLoadProperties() throws Exception { + // given + final String existingFile = "test.yaml"; + + // when + final YamlConfigSource yamlConfigSource = new YamlConfigSource(existingFile, 1); + + // then + Assertions.assertNotNull(yamlConfigSource); + + Assertions.assertTrue(yamlConfigSource.isListProperty("gossip.interfaceBindings")); + final List interfaceBindings = yamlConfigSource.getListValue("gossip.interfaceBindings"); + Assertions.assertEquals(4, interfaceBindings.size()); + Assertions.assertEquals("{\"nodeId\":0,\"hostname\":\"10.10.10.1\",\"port\":1234}", interfaceBindings.get(0)); + Assertions.assertEquals("{\"nodeId\":0,\"hostname\":\"10.10.10.2\",\"port\":1234}", interfaceBindings.get(1)); + Assertions.assertEquals("{\"nodeId\":1,\"hostname\":\"10.10.10.3\",\"port\":1234}", interfaceBindings.get(2)); + Assertions.assertEquals( + "{\"nodeId\":4,\"hostname\":\"2001:db8:3333:4444:5555:6666:7777:8888\",\"port\":1234}", + interfaceBindings.get(3)); + + Assertions.assertEquals("random", yamlConfigSource.getValue("gossip.randomStringValue")); + Assertions.assertEquals("42", yamlConfigSource.getValue("gossip.randomIntValue")); + Assertions.assertEquals( + "{\"nodeId\":5,\"hostname\":\"10.10.10.45\",\"port\":23424}", + yamlConfigSource.getValue("gossip.randomObj")); + + Assertions.assertTrue(yamlConfigSource.isListProperty("gossip.randomList")); + final List randomList = yamlConfigSource.getListValue("gossip.randomList"); + Assertions.assertEquals(2, randomList.size()); + Assertions.assertEquals("foo", randomList.get(0)); + Assertions.assertEquals("bar", randomList.get(1)); + + Assertions.assertTrue(yamlConfigSource.isListProperty("gossip.randomListOfList")); + } +} diff --git a/platform-sdk/swirlds-config-extensions/src/test/resources/test.yaml b/platform-sdk/swirlds-config-extensions/src/test/resources/test.yaml new file mode 100644 index 000000000000..1451416f62d8 --- /dev/null +++ b/platform-sdk/swirlds-config-extensions/src/test/resources/test.yaml @@ -0,0 +1,17 @@ +gossip: + interfaceBindings: + - { "nodeId": 0, "hostname": "10.10.10.1", "port": 1234 } + - { "nodeId": 0, "hostname": "10.10.10.2", "port": 1234 } + - { "nodeId": 1, "hostname": "10.10.10.3", "port": 1234 } + - { "nodeId": 4, "hostname": "2001:db8:3333:4444:5555:6666:7777:8888", "port": 1234 } + randomStringValue: "random" + randomIntValue: 42 + randomObj: { "nodeId": 5, "hostname": "10.10.10.45", "port": 23424 } + randomList: + - "foo" + - "bar" + randomListOfList: + - - "foo" + - "bar" + - - "baz" + - "qux" diff --git a/platform-sdk/swirlds-config-extensions/src/testFixtures/java/com/swirlds/config/extensions/test/fixtures/TestConfigBuilder.java b/platform-sdk/swirlds-config-extensions/src/testFixtures/java/com/swirlds/config/extensions/test/fixtures/TestConfigBuilder.java index 3d71edbcc53d..0315d13efbcb 100644 --- a/platform-sdk/swirlds-config-extensions/src/testFixtures/java/com/swirlds/config/extensions/test/fixtures/TestConfigBuilder.java +++ b/platform-sdk/swirlds-config-extensions/src/testFixtures/java/com/swirlds/config/extensions/test/fixtures/TestConfigBuilder.java @@ -16,7 +16,6 @@ package com.swirlds.config.extensions.test.fixtures; -import com.swirlds.common.config.singleton.ConfigurationHolder; import com.swirlds.common.threading.locks.AutoClosableLock; import com.swirlds.common.threading.locks.Locks; import com.swirlds.common.threading.locks.locked.Locked; @@ -165,7 +164,6 @@ public Configuration getOrCreateConfig() { try (final Locked ignore = configLock.lock()) { if (configuration == null) { configuration = builder.build(); - ConfigurationHolder.getInstance().setConfiguration(configuration); } return configuration; } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigDecimalConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigDecimalConverter.java index d164a5b853a9..f5cf9ea5cbcf 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigDecimalConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigDecimalConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.math.BigDecimal; /** @@ -29,7 +30,7 @@ public final class BigDecimalConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public BigDecimal convert(final String value) throws IllegalArgumentException { + public BigDecimal convert(@NonNull final String value) throws IllegalArgumentException { return new BigDecimal(value); } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigIntegerConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigIntegerConverter.java index d86dacc3174f..85b164e235e9 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigIntegerConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BigIntegerConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.math.BigInteger; /** @@ -29,7 +30,7 @@ public final class BigIntegerConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public BigInteger convert(final String value) throws IllegalArgumentException { + public BigInteger convert(@NonNull final String value) throws IllegalArgumentException { return new BigInteger(value); } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BooleanConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BooleanConverter.java index 73dfdb43e1e8..530c59c65b0c 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BooleanConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/BooleanConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Boolean} values in the @@ -28,7 +29,7 @@ public final class BooleanConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Boolean convert(final String value) throws IllegalArgumentException { + public Boolean convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ByteConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ByteConverter.java index 02c355055895..88591bdb5e92 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ByteConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ByteConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Byte} values in the @@ -28,7 +29,7 @@ public final class ByteConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Byte convert(final String value) throws IllegalArgumentException { + public Byte convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ChronoUnitConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ChronoUnitConverter.java index 458231c6035c..8f016358dc67 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ChronoUnitConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ChronoUnitConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.Objects; @@ -30,7 +31,7 @@ public class ChronoUnitConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public ChronoUnit convert(final String value) throws IllegalArgumentException { + public ChronoUnit convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DoubleConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DoubleConverter.java index 3852c735bc85..944c372bd62a 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DoubleConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DoubleConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Double} values in the @@ -28,7 +29,7 @@ public final class DoubleConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Double convert(final String value) throws IllegalArgumentException { + public Double convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DurationConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DurationConverter.java index 9e134ed95cc1..2c93d1eeca06 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DurationConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/DurationConverter.java @@ -26,6 +26,7 @@ import static com.swirlds.base.units.UnitConstants.WEEKS_TO_DAYS; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.time.Duration; import java.time.format.DateTimeParseException; import java.util.regex.Matcher; @@ -51,7 +52,7 @@ public final class DurationConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Duration convert(final String value) throws IllegalArgumentException { + public Duration convert(@NonNull final String value) throws IllegalArgumentException { return parseDuration(value); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FileConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FileConverter.java index b116ab0e4f5d..0c8c2367c459 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FileConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FileConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.io.File; /** @@ -29,7 +30,7 @@ public final class FileConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public File convert(final String value) throws IllegalArgumentException { + public File convert(@NonNull final String value) throws IllegalArgumentException { return new File(value); } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FloatConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FloatConverter.java index d687edfba8ec..bb58225afd56 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FloatConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/FloatConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Float} values in the @@ -28,7 +29,7 @@ public final class FloatConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Float convert(final String value) throws IllegalArgumentException { + public Float convert(@NonNull final String value) throws IllegalArgumentException { return Float.valueOf(value); } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/InetAddressConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/InetAddressConverter.java new file mode 100644 index 000000000000..b95aa7570bdd --- /dev/null +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/InetAddressConverter.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.impl.converters; + +import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +/** + * A {@link ConfigConverter} that converts a string to an {@link InetAddress}. + */ +public class InetAddressConverter implements ConfigConverter { + + /** + * {{@inheritDoc}} + */ + @Nullable + @Override + public InetAddress convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { + Objects.requireNonNull(value, "value must not be null"); + try { + return InetAddress.getByName(value); + } catch (UnknownHostException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/IntegerConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/IntegerConverter.java index 41d794ff8596..758e88f3cd84 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/IntegerConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/IntegerConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Integer} values in the @@ -28,7 +29,7 @@ public final class IntegerConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Integer convert(final String value) throws IllegalArgumentException { + public Integer convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/LongConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/LongConverter.java index 5cebe9e9b5c8..51b9fb6a9a94 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/LongConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/LongConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Long} values in the @@ -28,7 +29,7 @@ public final class LongConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Long convert(final String value) throws IllegalArgumentException { + public Long convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/PathConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/PathConverter.java index a640a9736aed..8e48bdda56ce 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/PathConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/PathConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.nio.file.Path; import java.nio.file.Paths; @@ -30,7 +31,7 @@ public final class PathConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Path convert(final String value) throws IllegalArgumentException { + public Path convert(@NonNull final String value) throws IllegalArgumentException { return Paths.get(value); } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ShortConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ShortConverter.java index b76c6442a120..1f566b42cc1f 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ShortConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ShortConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link Short} values in the @@ -28,7 +29,7 @@ public final class ShortConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public Short convert(final String value) throws IllegalArgumentException { + public Short convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/StringConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/StringConverter.java index f8b59e7e5ad7..1fb5cabc2401 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/StringConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/StringConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; /** * Concrete {@link ConfigConverter} implementation that provides the support for {@link String} values in the @@ -28,7 +29,7 @@ public class StringConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public String convert(final String value) throws IllegalArgumentException { + public String convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("value must not be null"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UriConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UriConverter.java index 0e41b09d21a0..1f685f370543 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UriConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UriConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.net.URI; import java.net.URISyntaxException; @@ -30,7 +31,7 @@ public final class UriConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public URI convert(final String value) throws IllegalArgumentException { + public URI convert(@NonNull final String value) throws IllegalArgumentException { try { return new URI(value); } catch (URISyntaxException e) { diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UrlConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UrlConverter.java index 8b51abe8146a..d06b8b6b793f 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UrlConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/UrlConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.net.MalformedURLException; import java.net.URL; @@ -30,7 +31,7 @@ public final class UrlConverter implements ConfigConverter { * {@inheritDoc} */ @Override - public URL convert(final String value) throws IllegalArgumentException { + public URL convert(@NonNull final String value) throws IllegalArgumentException { if (value == null) { throw new NullPointerException("null can not be converted"); } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ZonedDateTimeConverter.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ZonedDateTimeConverter.java index 40ea4731ed81..761fc9f8b028 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ZonedDateTimeConverter.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/converters/ZonedDateTimeConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl.converters; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -30,7 +31,7 @@ public final class ZonedDateTimeConverter implements ConfigConverter genericType = getGenericSetType(component); return configuration.getValueSet(name, genericType); } - return configuration.getValue(name, valueType); + if (configuration.isListValue(name)) { + return configuration.getValues(name, valueType); + } else { + return configuration.getValue(name, valueType); + } } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigPropertiesService.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigPropertiesService.java index b653b2477ae9..0de835917336 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigPropertiesService.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigPropertiesService.java @@ -17,12 +17,13 @@ package com.swirlds.config.impl.internal; import com.swirlds.base.ArgumentUtils; -import com.swirlds.config.api.source.ConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Stream; /** @@ -35,6 +36,11 @@ class ConfigPropertiesService implements ConfigLifecycle { */ private final Map internalProperties; + /** + * stores all config properties. + */ + private final Map> internalListProperties; + /** * The services that is used to load all properties in the correct order. */ @@ -48,22 +54,30 @@ class ConfigPropertiesService implements ConfigLifecycle { ConfigPropertiesService(@NonNull final ConfigSourceService configSourceService) { this.configSourceService = Objects.requireNonNull(configSourceService, "configSourceService must not be null"); internalProperties = new HashMap<>(); + internalListProperties = new HashMap<>(); } @Override public void init() { throwIfInitialized(); - configSourceService - .getSources() - .map(ConfigSource::getProperties) - .flatMap(map -> map.entrySet().stream()) - .forEach(entry -> addProperty(entry.getKey(), entry.getValue())); + configSourceService.getSources().forEach(configSource -> { + final Set propertyNames = configSource.getPropertyNames(); + propertyNames.forEach(propertyName -> { + ArgumentUtils.throwArgBlank(propertyName, "propertyName"); + if (configSource.isListProperty(propertyName)) { + internalListProperties.put(propertyName, configSource.getListValue(propertyName)); + } else { + internalProperties.put(propertyName, configSource.getValue(propertyName)); + } + }); + }); initialized = true; } @Override public void dispose() { internalProperties.clear(); + internalListProperties.clear(); initialized = false; } @@ -75,13 +89,13 @@ public boolean isInitialized() { @NonNull Stream getPropertyNames() { throwIfNotInitialized(); - return internalProperties.keySet().stream(); + return Stream.concat(internalProperties.keySet().stream(), internalListProperties.keySet().stream()); } boolean containsKey(@NonNull final String propertyName) { throwIfNotInitialized(); ArgumentUtils.throwArgBlank(propertyName, "propertyName"); - return internalProperties.containsKey(propertyName); + return internalProperties.containsKey(propertyName) || internalListProperties.containsKey(propertyName); } @Nullable @@ -91,8 +105,16 @@ String getProperty(@NonNull final String propertyName) { return internalProperties.get(propertyName); } - private void addProperty(@NonNull final String propertyName, @Nullable final String propertyValue) { + boolean isListProperty(@NonNull final String propertyName) { + throwIfNotInitialized(); + ArgumentUtils.throwArgBlank(propertyName, "propertyName"); + return internalListProperties.containsKey(propertyName); + } + + @NonNull + List getListProperty(@NonNull final String propertyName) { + throwIfNotInitialized(); ArgumentUtils.throwArgBlank(propertyName, "propertyName"); - internalProperties.put(propertyName, propertyValue); + return internalListProperties.get(propertyName); } } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigurationImpl.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigurationImpl.java index 1c2b9e2285a0..4c3112de006e 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigurationImpl.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConfigurationImpl.java @@ -61,6 +61,11 @@ public boolean exists(@NonNull final String propertyName) { return propertiesService.containsKey(propertyName); } + @Override + public boolean isListValue(@NonNull final String propertyName) { + return propertiesService.isListProperty(propertyName); + } + @SuppressWarnings("unchecked") @Nullable @Override @@ -90,6 +95,9 @@ public T getValue( @Override public String getValue(@NonNull final String propertyName) { ArgumentUtils.throwArgBlank(propertyName, "propertyName"); + if (propertiesService.isListProperty(propertyName)) { + throw new NoSuchElementException("Property '" + propertyName + "' is a list property"); + } if (!exists(propertyName)) { throw new NoSuchElementException("Property '" + propertyName + "' not defined in configuration"); } @@ -100,6 +108,9 @@ public String getValue(@NonNull final String propertyName) { @Override public String getValue(@NonNull final String propertyName, @Nullable final String defaultValue) { ArgumentUtils.throwArgBlank(propertyName, "propertyName"); + if (propertiesService.isListProperty(propertyName)) { + throw new NoSuchElementException("Property '" + propertyName + "' is a list property"); + } if (!exists(propertyName)) { return defaultValue; } @@ -110,21 +121,26 @@ public String getValue(@NonNull final String propertyName, @Nullable final Strin @Override public List getValues(@NonNull final String propertyName) { ArgumentUtils.throwArgBlank(propertyName, "propertyName"); - final String rawValue = getValue(propertyName); - if (rawValue == null) { - return null; + if (!propertiesService.isListProperty(propertyName)) { + throw new NoSuchElementException("Property '" + propertyName + "' is not a list property"); } - return ConfigListUtils.createList(rawValue); + if (!exists(propertyName)) { + throw new NoSuchElementException("Property '" + propertyName + "' not defined in configuration"); + } + return propertiesService.getListProperty(propertyName); } @Nullable @Override public List getValues(@NonNull final String propertyName, @Nullable final List defaultValue) { ArgumentUtils.throwArgBlank(propertyName, "propertyName"); + if (!propertiesService.isListProperty(propertyName)) { + throw new NoSuchElementException("Property '" + propertyName + "' is not a list property"); + } if (!exists(propertyName)) { return defaultValue; } - return getValues(propertyName); + return propertiesService.getListProperty(propertyName); } @Nullable @@ -132,7 +148,13 @@ public List getValues(@NonNull final String propertyName, @Nullable fina public List getValues(@NonNull final String propertyName, @NonNull final Class propertyType) { ArgumentUtils.throwArgBlank(propertyName, "propertyName"); Objects.requireNonNull(propertyType, "propertyType must not be null"); - final List values = getValues(propertyName); + final List values; + if (!propertiesService.isListProperty(propertyName)) { + final String value = getValue(propertyName); + values = ConfigListUtils.createList(value); + } else { + values = getValues(propertyName); + } if (values == null) { return null; } diff --git a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConverterService.java b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConverterService.java index 8307a1284849..0d5723ac7d71 100644 --- a/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConverterService.java +++ b/platform-sdk/swirlds-config-impl/src/main/java/com/swirlds/config/impl/internal/ConverterService.java @@ -27,6 +27,7 @@ import com.swirlds.config.impl.converters.EnumConverter; import com.swirlds.config.impl.converters.FileConverter; import com.swirlds.config.impl.converters.FloatConverter; +import com.swirlds.config.impl.converters.InetAddressConverter; import com.swirlds.config.impl.converters.IntegerConverter; import com.swirlds.config.impl.converters.LongConverter; import com.swirlds.config.impl.converters.PathConverter; @@ -40,6 +41,7 @@ import java.io.File; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.InetAddress; import java.net.URI; import java.net.URL; import java.nio.file.Path; @@ -92,6 +94,8 @@ class ConverterService implements ConfigLifecycle { private static final ConfigConverter CHRONO_UNIT_CONVERTER = new ChronoUnitConverter(); + private static final ConfigConverter INET_ADDRESS_CONFIG_CONVERTER = new InetAddressConverter(); + ConverterService() { this.converters = new ConcurrentHashMap<>(); } @@ -173,6 +177,7 @@ public void init() { addConverter(ZonedDateTime.class, ZONED_DATE_TIME_CONVERTER); addConverter(Duration.class, DURATION_CONVERTER); addConverter(ChronoUnit.class, CHRONO_UNIT_CONVERTER); + addConverter(InetAddress.class, INET_ADDRESS_CONFIG_CONVERTER); initialized = true; } diff --git a/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/ConfigApiTests.java b/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/ConfigApiTests.java index d3285f6a3d33..ca38fef9482e 100644 --- a/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/ConfigApiTests.java +++ b/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/ConfigApiTests.java @@ -446,7 +446,7 @@ void registerCustomConverter() { void testNullList() { // given final Configuration configuration = ConfigurationBuilder.create() - .withSources(new SimpleConfigSource("sample.list", (String) null)) + .withSources(new SimpleConfigSource("sample.list", (List) null)) .build(); // when diff --git a/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/TestDateConverter.java b/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/TestDateConverter.java index 5f2abce11768..cc9727d311d4 100644 --- a/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/TestDateConverter.java +++ b/platform-sdk/swirlds-config-impl/src/test/java/com/swirlds/config/impl/TestDateConverter.java @@ -17,6 +17,7 @@ package com.swirlds.config.impl; import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Date; /** @@ -25,7 +26,7 @@ public class TestDateConverter implements ConfigConverter { @Override - public Date convert(final String value) throws IllegalArgumentException, NullPointerException { + public Date convert(@NonNull final String value) throws IllegalArgumentException, NullPointerException { return new Date(Long.parseLong(value)); } } From 8989ed786d72d1fbbc684a7b412617d4d84a23e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:43:08 -0500 Subject: [PATCH 02/12] build(deps): bump org.junit-pioneer:junit-pioneer from 2.0.1 to 2.3.0 in /hiero-dependency-versions (#17131) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hiero-dependency-versions/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hiero-dependency-versions/build.gradle.kts b/hiero-dependency-versions/build.gradle.kts index 4b3257429d57..c1c57fa46f8b 100644 --- a/hiero-dependency-versions/build.gradle.kts +++ b/hiero-dependency-versions/build.gradle.kts @@ -112,7 +112,7 @@ dependencies.constraints { api("org.json:json:20231013") { because("org.json") } api("org.junit.jupiter:junit-jupiter-api:$junit5") { because("org.junit.jupiter.api") } api("org.junit.jupiter:junit-jupiter-engine:$junit5") { because("org.junit.jupiter.engine") } - api("org.junit-pioneer:junit-pioneer:2.0.1") { because("org.junitpioneer") } + api("org.junit-pioneer:junit-pioneer:2.3.0") { because("org.junitpioneer") } api("org.mockito:mockito-core:$mockito") { because("org.mockito") } api("org.mockito:mockito-junit-jupiter:$mockito") { because("org.mockito.junit.jupiter") } api("org.opentest4j:opentest4j:1.2.0") { because("org.opentest4j") } From ca2e9a89b8f47a62902139534a90570c3a024cf0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:54:26 -0500 Subject: [PATCH 03/12] build(deps): bump io.grpc:protoc-gen-grpc-java from 1.66.0 to 1.69.0 in /hiero-dependency-versions (#17109) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hiero-dependency-versions/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hiero-dependency-versions/build.gradle.kts b/hiero-dependency-versions/build.gradle.kts index c1c57fa46f8b..67e5cd5f4a6a 100644 --- a/hiero-dependency-versions/build.gradle.kts +++ b/hiero-dependency-versions/build.gradle.kts @@ -130,7 +130,7 @@ dependencies.constraints { because("uk.org.webcompere.systemstubs.jupiter") } api("com.google.protobuf:protoc:3.25.4") - api("io.grpc:protoc-gen-grpc-java:1.66.0") + api("io.grpc:protoc-gen-grpc-java:1.69.0") api("com.hedera.cryptography:hedera-cryptography-pairings-api:$hederaCryptography") { because("com.hedera.cryptography.pairings.api") From 89e2f351edcfd41e54115fe7a7f159f614be4a78 Mon Sep 17 00:00:00 2001 From: Mustafa Uzun Date: Fri, 20 Dec 2024 14:58:02 +0200 Subject: [PATCH 04/12] refactor: consumer for system transactions (#17140) Signed-off-by: Mustafa Uzun --- .../com/swirlds/demo/crypto/CryptocurrencyDemoState.java | 4 +--- .../com/swirlds/demo/hello/HelloSwirldDemoState.java | 4 +--- .../main/java/com/swirlds/demo/stats/StatsDemoState.java | 5 +---- .../demo/addressbook/AddressBookTestingToolState.java | 5 +---- .../demo/consistency/ConsistencyTestingToolState.java | 9 ++------- .../java/com/swirlds/demo/iss/ISSTestingToolState.java | 4 +--- .../demo/migration/MigrationTestingToolState.java | 4 +--- .../swirlds/demo/platform/PlatformTestingToolState.java | 8 ++------ .../demo/stats/signing/StatsSigningTestingToolState.java | 8 ++------ .../com/swirlds/demo/stress/StressTestingToolState.java | 9 ++------- .../eventhandling/DefaultTransactionPrehandler.java | 2 +- .../swirlds/platform/state/PlatformMerkleStateRoot.java | 9 ++------- .../com/swirlds/platform/state/SwirldStateManager.java | 2 +- .../java/com/swirlds/platform/system/SwirldState.java | 9 ++++----- .../platform/turtle/runner/TurtleTestingToolState.java | 5 +---- .../test/fixtures/state/BlockingSwirldState.java | 5 +---- 16 files changed, 24 insertions(+), 68 deletions(-) diff --git a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java index 624f1bc15dcf..67bf3acd5581 100644 --- a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java +++ b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java @@ -211,9 +211,7 @@ public synchronized CryptocurrencyDemoState copy() { public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); round.forEachEventTransaction((event, transaction) -> handleTransaction(event.getCreatorId(), transaction)); } diff --git a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java index c7d66c8090df..70d659567fb0 100644 --- a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java +++ b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java @@ -111,9 +111,7 @@ private HelloSwirldDemoState(final HelloSwirldDemoState sourceState) { public synchronized void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); round.forEachTransaction(this::handleTransaction); } diff --git a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java index 64d9e5a976f5..10d59a52847b 100644 --- a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java +++ b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java @@ -36,7 +36,6 @@ import com.swirlds.platform.system.Round; import com.swirlds.platform.system.SoftwareVersion; import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; @@ -83,9 +82,7 @@ private StatsDemoState(final StatsDemoState sourceState) { public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) {} + @NonNull final Consumer> stateSignatureTransaction) {} /** * {@inheritDoc} diff --git a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java index 76f36aafdae0..6614c1624baa 100644 --- a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java +++ b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java @@ -71,7 +71,6 @@ import java.text.ParseException; import java.time.Duration; import java.util.Iterator; -import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -222,9 +221,7 @@ public void init( public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { Objects.requireNonNull(round, "the round cannot be null"); Objects.requireNonNull(platformState, "the platform state cannot be null"); throwIfImmutable(); diff --git a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java index c0313c161976..5e25d3b0eacb 100644 --- a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java +++ b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java @@ -44,7 +44,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; -import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -246,9 +245,7 @@ private void applyTransactionToState(final @NonNull ConsensusTransaction transac @Override public void preHandle( @NonNull final Event event, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { event.forEachTransaction(transaction -> { if (transaction.isSystem()) { return; @@ -272,9 +269,7 @@ public void preHandle( public void handleConsensusRound( final @NonNull Round round, final @NonNull PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { Objects.requireNonNull(round); Objects.requireNonNull(platformState); diff --git a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java index f78d3e6eebc4..78d7515250be 100644 --- a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java +++ b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java @@ -243,9 +243,7 @@ void writeObjectByChildIndex(int index, List lis public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); final Iterator eventIterator = round.iterator(); diff --git a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java index 504679ccff2e..7ec5c81b4690 100644 --- a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java +++ b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java @@ -285,9 +285,7 @@ public void init( public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); for (final Iterator eventIt = round.iterator(); eventIt.hasNext(); ) { final ConsensusEvent event = eventIt.next(); diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java index 48a2b0ea9694..518d1445a862 100644 --- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java +++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java @@ -1056,9 +1056,7 @@ protected void preHandleTransaction(final Transaction transaction) { public synchronized void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); if (!initialized.get()) { throw new IllegalStateException("handleConsensusRound() called before init()"); @@ -1662,9 +1660,7 @@ private static class ChildIndices { @Override public void preHandle( @NonNull final Event event, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { event.forEachTransaction(this::preHandleTransaction); } } diff --git a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java index dabd0b8fff3c..5a2d95eb0f19 100644 --- a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java +++ b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java @@ -115,9 +115,7 @@ public synchronized StatsSigningTestingToolState copy() { @Override public void preHandle( @NonNull final Event event, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { final SttTransactionPool sttTransactionPool = transactionPoolSupplier.get(); if (sttTransactionPool != null) { event.forEachTransaction(transaction -> { @@ -141,9 +139,7 @@ public void preHandle( public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); round.forEachTransaction(this::handleTransaction); } diff --git a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java index 3225ecffe8f3..347b5dfb0cff 100644 --- a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java +++ b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java @@ -43,7 +43,6 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.time.Duration; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; @@ -103,9 +102,7 @@ public void init( @Override public void preHandle( @NonNull final Event event, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { busyWait(config.preHandleTime()); } @@ -116,9 +113,7 @@ public void preHandle( public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); round.forEachTransaction(this::handleTransaction); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionPrehandler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionPrehandler.java index 6ddb39c0aade..884991c5eb80 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionPrehandler.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionPrehandler.java @@ -42,7 +42,7 @@ public class DefaultTransactionPrehandler implements TransactionPrehandler { private static final Logger logger = LogManager.getLogger(DefaultTransactionPrehandler.class); - public static final Consumer>> NO_OP_CONSUMER = + public static final Consumer> NO_OP_CONSUMER = systemTransactions -> {}; /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java index b6c9b1c7fc37..7fff84b01b46 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java @@ -48,7 +48,6 @@ import com.swirlds.state.spi.WritableStates; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; @@ -153,9 +152,7 @@ protected PlatformMerkleStateRoot copyingConstructor() { public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { throwIfImmutable(); lifecycles.onHandleConsensusRound(round, this); } @@ -173,9 +170,7 @@ public void sealConsensusRound(@NonNull final Round round) { @Override public void preHandle( @NonNull final Event event, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { lifecycles.onPreHandle(event, this); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java index ce99739dc690..06a9d89e1456 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java @@ -123,7 +123,7 @@ public void setInitialState(@NonNull final MerkleRoot state) { /** * Handles the events in a consensus round. Implementations are responsible for invoking - * {@link SwirldState#handleConsensusRound(Round, PlatformStateModifier, Consumer>>)}. + * {@link SwirldState#handleConsensusRound(Round, PlatformStateModifier, Consumer>)}. * * @param round the round to handle */ diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldState.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldState.java index a6d0368bea77..c49f3047d4d1 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldState.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldState.java @@ -26,7 +26,6 @@ import com.swirlds.platform.system.transaction.Transaction; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.List; import java.util.Objects; import java.util.function.Consumer; @@ -72,25 +71,25 @@ default void init( * This method is always invoked on an immutable state. * * @param event the event to perform pre-handling on - * @param stateSignatureTransactions a consumer that accepts a list of {@link ScopedSystemTransaction}s that + * @param stateSignatureTransaction a consumer that accepts a list of {@link ScopedSystemTransaction}s that * will be used for callbacks */ default void preHandle( final Event event, - final Consumer>> stateSignatureTransactions) {} + final Consumer> stateSignatureTransaction) {} /** * This method should apply the transactions in the provided round to the state. Only called on mutable states. * * @param round the round to apply * @param platformState the platform state - * @param stateSignatureTransactions a consumer that accepts a list of {@link ScopedSystemTransaction}s that + * @param stateSignatureTransaction a consumer that accepts a list of {@link ScopedSystemTransaction}s that * will be used for callbacks */ void handleConsensusRound( final Round round, final PlatformStateModifier platformState, - final Consumer>> stateSignatureTransactions); + final Consumer> stateSignatureTransaction); /** * Called by the platform after it has made all its changes to this state for the given round. diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java index e1d23cd50e89..f4547d45a1cd 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java @@ -25,7 +25,6 @@ import com.swirlds.platform.system.BasicSoftwareVersion; import com.swirlds.platform.system.Round; import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.List; import java.util.function.Consumer; /** @@ -84,9 +83,7 @@ public int getVersion() { public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { state = NonCryptographicHashing.hash64( state, round.getRoundNum(), diff --git a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java index e5537a738c89..29b3ade2f864 100644 --- a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java +++ b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java @@ -36,7 +36,6 @@ import com.swirlds.state.merkle.singleton.StringLeaf; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; -import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; @@ -86,9 +85,7 @@ private BlockingSwirldState(final BlockingSwirldState that) { public void handleConsensusRound( @NonNull final Round round, @NonNull final PlatformStateModifier platformState, - @NonNull - final Consumer>> - stateSignatureTransactions) { + @NonNull final Consumer> stateSignatureTransaction) { // intentionally does nothing } From 111a2e2d3b3ef0914ca916fdc8e404ee49af57c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:57:46 -0500 Subject: [PATCH 05/12] build(deps): bump actions/upload-artifact from 4.4.3 to 4.5.0 (#17092) Signed-off-by: dependabot[bot] Signed-off-by: Andrew Brandt Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrew Brandt --- .../node-zxc-build-release-artifact.yaml | 19 +++++++++- .../node-zxc-compile-application-code.yaml | 38 +++++++++---------- .../zxc-verify-docker-build-determinism.yaml | 2 +- .../zxc-verify-gradle-build-determinism.yaml | 2 +- .../workflows/zxcron-extended-test-suite.yaml | 2 +- .../workflows/zxf-collect-workflow-logs.yaml | 2 +- 6 files changed, 40 insertions(+), 25 deletions(-) diff --git a/.github/workflows/node-zxc-build-release-artifact.yaml b/.github/workflows/node-zxc-build-release-artifact.yaml index 3d1fe85f9667..bd079e5fc89c 100644 --- a/.github/workflows/node-zxc-build-release-artifact.yaml +++ b/.github/workflows/node-zxc-build-release-artifact.yaml @@ -1,4 +1,19 @@ -# SPDX-License-Identifier: Apache-2.0 +## +# Copyright (C) 2024 Hedera Hashgraph, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## + name: "ZXC: [Node] Deploy Release Artifacts" on: workflow_call: @@ -643,7 +658,7 @@ jobs: fi - name: Upload Manifests - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ (steps.gcp.outcome == 'success' || steps.jfrog.outcome == 'success') && !cancelled() && always() }} with: name: Production Image Manifests diff --git a/.github/workflows/node-zxc-compile-application-code.yaml b/.github/workflows/node-zxc-compile-application-code.yaml index 055047eb0d90..258bac714ab0 100644 --- a/.github/workflows/node-zxc-compile-application-code.yaml +++ b/.github/workflows/node-zxc-compile-application-code.yaml @@ -219,7 +219,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload Unit Test Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-unit-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: Unit Test Report @@ -241,7 +241,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload Unit Test (Timing Sensitive) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-timing-sensitive-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: Unit Test Report (Timing Sensitive) @@ -263,7 +263,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload Unit Test (Time Consuming) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-time-consuming-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: Unit Test Report (Time Consuming) @@ -285,7 +285,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload Hammer Test Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hammer-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: Hammer Test Report @@ -311,7 +311,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Misc) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-misc && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: HAPI Test (Misc) Reports @@ -319,7 +319,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (Misc) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-misc && inputs.enable-network-log-capture && steps.gradle-hapi-misc.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Misc) Network Logs @@ -345,7 +345,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Crypto) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-crypto && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: HAPI Test (Crypto) Report @@ -353,7 +353,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (crypto) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-crypto && inputs.enable-network-log-capture && steps.gradle-hapi-crypto.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Crypto) Network Logs @@ -379,7 +379,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Token) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-token && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: HAPI Test (Token) Report @@ -387,7 +387,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (Token) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-token && inputs.enable-network-log-capture && steps.gradle-hapi-token.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Token) Network Logs @@ -413,7 +413,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Smart Contract) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-smart-contract && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: HAPI Test (Smart Contract) Report @@ -421,7 +421,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (Smart Contract) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-smart-contract && inputs.enable-network-log-capture && steps.gradle-hapi-smart-contract.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Smart Contract) Network Logs @@ -447,7 +447,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Time Consuming) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-time-consuming && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: HAPI Test (Time Consuming) Report @@ -455,7 +455,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (Time Consuming) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-time-consuming && inputs.enable-network-log-capture && steps.gradle-hapi-time-consuming.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Time Consuming) Network Logs @@ -481,7 +481,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Restart) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-restart && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: name: HAPI Test (Restart) Report @@ -489,7 +489,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (Restart) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-restart && inputs.enable-network-log-capture && steps.gradle-hapi-restart.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Restart) Network Logs @@ -516,7 +516,7 @@ jobs: comment_mode: errors # only comment if we could not find or parse the JUnit XML files - name: Upload HAPI Test (Node Death Reconnect) Report Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-nd-reconnect && steps.gradle-build.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Node Death Reconnect) Report @@ -524,7 +524,7 @@ jobs: retention-days: 7 - name: Upload HAPI Test (Node Death Reconnect) Network Logs - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-hapi-tests-nd-reconnect && inputs.enable-network-log-capture && steps.gradle-hapi-nd-reconnect.conclusion == 'failure' && !cancelled() }} with: name: HAPI Test (Node Death Reconnect) Network Logs @@ -547,7 +547,7 @@ jobs: run: bash <(curl -Ls https://coverage.codacy.com/get.sh) report -l Java -r gradle/aggregation/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - name: Upload Test Reports - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ inputs.enable-unit-tests && !cancelled() }} with: name: Test Reports diff --git a/.github/workflows/zxc-verify-docker-build-determinism.yaml b/.github/workflows/zxc-verify-docker-build-determinism.yaml index ea7475d4808c..5c4c1d0876a1 100644 --- a/.github/workflows/zxc-verify-docker-build-determinism.yaml +++ b/.github/workflows/zxc-verify-docker-build-determinism.yaml @@ -499,7 +499,7 @@ jobs: fi - name: Publish Manifests - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ steps.regen-manifest.conclusion == 'success' && failure() && !cancelled() }} with: name: Docker Manifests [${{ join(matrix.os, ', ') }}] diff --git a/.github/workflows/zxc-verify-gradle-build-determinism.yaml b/.github/workflows/zxc-verify-gradle-build-determinism.yaml index e30e60bd93a0..76f00b1f7972 100644 --- a/.github/workflows/zxc-verify-gradle-build-determinism.yaml +++ b/.github/workflows/zxc-verify-gradle-build-determinism.yaml @@ -247,7 +247,7 @@ jobs: fi - name: Publish Manifests - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: ${{ steps.regen-manifest.conclusion == 'success' && failure() && !cancelled() }} with: name: Gradle Manifests [${{ join(matrix.os, ', ') }}] diff --git a/.github/workflows/zxcron-extended-test-suite.yaml b/.github/workflows/zxcron-extended-test-suite.yaml index 0f3e1de0b793..53b467047dfa 100644 --- a/.github/workflows/zxcron-extended-test-suite.yaml +++ b/.github/workflows/zxcron-extended-test-suite.yaml @@ -281,7 +281,7 @@ jobs: done - name: Upload log as artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: path: run.log diff --git a/.github/workflows/zxf-collect-workflow-logs.yaml b/.github/workflows/zxf-collect-workflow-logs.yaml index 812bf49d3305..14d12a8e4a35 100644 --- a/.github/workflows/zxf-collect-workflow-logs.yaml +++ b/.github/workflows/zxf-collect-workflow-logs.yaml @@ -60,7 +60,7 @@ jobs: - name: Upload log as artifact id: upload-log - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: path: workflow-run.log From 83988662ff8810102e529927e6d0963159a3954e Mon Sep 17 00:00:00 2001 From: timfn-hg Date: Fri, 20 Dec 2024 10:27:59 -0600 Subject: [PATCH 06/12] chore: refactor DefaultIssDetector to use rosters (#17141) Signed-off-by: Tim Farber-Newman --- .../builder/PlatformComponentBuilder.java | 20 ++- .../swirlds/platform/metrics/IssMetrics.java | 21 ++-- .../state/iss/DefaultIssDetector.java | 27 ++-- .../platform/test/state/IssDetectorTests.java | 104 +++++++-------- .../platform/test/state/IssMetricsTests.java | 74 +++++------ .../test/state/RoundHashValidatorTests.java | 119 +++++++++--------- 6 files changed, 198 insertions(+), 167 deletions(-) diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java index de3262924a35..eefe64b3d020 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java @@ -1,10 +1,24 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.swirlds.platform.builder; import static com.swirlds.platform.builder.internal.StaticPlatformBuilder.getGlobalMetrics; import static com.swirlds.platform.builder.internal.StaticPlatformBuilder.getMetricsProvider; import static com.swirlds.platform.gui.internal.BrowserWindowManager.getPlatforms; -import static com.swirlds.platform.roster.RosterUtils.buildAddressBook; import static com.swirlds.platform.state.iss.IssDetector.DO_NOT_IGNORE_ROUNDS; import com.swirlds.common.merkle.utility.SerializableLong; @@ -876,7 +890,7 @@ public IssDetector buildIssDetector() { issDetector = new DefaultIssDetector( blocks.platformContext(), - buildAddressBook(blocks.rosterHistory().getCurrentRoster()), + blocks.rosterHistory().getCurrentRoster(), blocks.appVersion().getPbjSemanticVersion(), ignorePreconsensusSignatures, roundToIgnore); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/metrics/IssMetrics.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/metrics/IssMetrics.java index 311d7f16efef..773e184e3b77 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/metrics/IssMetrics.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/metrics/IssMetrics.java @@ -16,13 +16,14 @@ package com.swirlds.platform.metrics; +import com.hedera.hapi.node.state.roster.Roster; +import com.hedera.hapi.node.state.roster.RosterEntry; import com.swirlds.common.crypto.Hash; import com.swirlds.common.platform.NodeId; import com.swirlds.metrics.api.IntegerGauge; import com.swirlds.metrics.api.LongGauge; import com.swirlds.metrics.api.Metrics; -import com.swirlds.platform.system.address.Address; -import com.swirlds.platform.system.address.AddressBook; +import com.swirlds.platform.roster.RosterUtils; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.HashMap; import java.util.Map; @@ -33,7 +34,7 @@ */ public class IssMetrics { - private final AddressBook addressBook; + private final Roster roster; /** * The current number of nodes experiencing an ISS. @@ -109,9 +110,9 @@ public void setRound(final long round) { * @throws IllegalArgumentException * if {@code metrics} is {@code null} */ - public IssMetrics(@NonNull final Metrics metrics, @NonNull final AddressBook addressBook) { + public IssMetrics(@NonNull final Metrics metrics, @NonNull final Roster roster) { Objects.requireNonNull(metrics, "metrics must not be null"); - this.addressBook = Objects.requireNonNull(addressBook, "addressBook must not be null"); + this.roster = Objects.requireNonNull(roster, "roster must not be null"); issCountGauge = metrics.getOrCreate(new IntegerGauge.Config(Metrics.INTERNAL_CATEGORY, "issCount") .withDescription("the number of nodes that currently disagree with the consensus hash")); @@ -119,8 +120,8 @@ public IssMetrics(@NonNull final Metrics metrics, @NonNull final AddressBook add issWeightGage = metrics.getOrCreate(new LongGauge.Config(Metrics.INTERNAL_CATEGORY, "issWeight") .withDescription("the amount of weight tied up by ISS events")); - for (final Address address : addressBook) { - issDataByNode.put(address.getNodeId(), new IssStatus()); + for (final RosterEntry node : roster.rosterEntries()) { + issDataByNode.put(NodeId.of(node.nodeId()), new IssStatus()); } } @@ -176,7 +177,7 @@ public void stateHashValidityObserver( issStatus.setRound(round); if (issStatus.hasIss() != hasIss) { - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = RosterUtils.getRosterEntry(roster, nodeId.id()).weight(); if (hasIss) { issCount++; issWeight += weight; @@ -208,8 +209,8 @@ public void catastrophicIssObserver(final long round) { status.setRound(round); } - issCount = addressBook.getSize(); - issWeight = addressBook.getTotalWeight(); + issCount = roster.rosterEntries().size(); + issWeight = RosterUtils.computeTotalWeight(roster); issCountGauge.set(issCount); issWeightGage.set(issWeight); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/DefaultIssDetector.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/DefaultIssDetector.java index 08f0cd191dc7..bcbedf51a00a 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/DefaultIssDetector.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/DefaultIssDetector.java @@ -21,6 +21,8 @@ import static com.swirlds.logging.legacy.LogMarker.STATE_HASH; import com.hedera.hapi.node.base.SemanticVersion; +import com.hedera.hapi.node.state.roster.Roster; +import com.hedera.hapi.node.state.roster.RosterEntry; import com.hedera.hapi.platform.event.StateSignatureTransaction; import com.swirlds.common.context.PlatformContext; import com.swirlds.common.crypto.Hash; @@ -31,13 +33,13 @@ import com.swirlds.platform.config.StateConfig; import com.swirlds.platform.consensus.ConsensusConfig; import com.swirlds.platform.metrics.IssMetrics; +import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.sequence.map.ConcurrentSequenceMap; import com.swirlds.platform.sequence.map.SequenceMap; import com.swirlds.platform.state.iss.internal.ConsensusHashFinder; import com.swirlds.platform.state.iss.internal.HashValidityStatus; import com.swirlds.platform.state.iss.internal.RoundHashValidator; import com.swirlds.platform.state.signed.ReservedSignedState; -import com.swirlds.platform.system.address.AddressBook; import com.swirlds.platform.system.state.notifications.IssNotification; import com.swirlds.platform.system.state.notifications.IssNotification.IssType; import com.swirlds.platform.util.MarkerFileWriter; @@ -64,9 +66,9 @@ public class DefaultIssDetector implements IssDetector { private long previousRound = -1; /** - * The address book of this network. + * The roster of this network. */ - private final AddressBook addressBook; + private final Roster roster; /** * The current software version @@ -117,7 +119,7 @@ public class DefaultIssDetector implements IssDetector { * Create an object that tracks reported hashes and detects ISS events. * * @param platformContext the platform context - * @param addressBook the address book for the network + * @param roster the roster for the network * @param currentSoftwareVersion the current software version * @param ignorePreconsensusSignatures If true, ignore signatures from the preconsensus event stream, otherwise * validate them like normal. @@ -126,7 +128,7 @@ public class DefaultIssDetector implements IssDetector { */ public DefaultIssDetector( @NonNull final PlatformContext platformContext, - @NonNull final AddressBook addressBook, + @NonNull final Roster roster, @NonNull final SemanticVersion currentSoftwareVersion, final boolean ignorePreconsensusSignatures, final long ignoredRound) { @@ -142,7 +144,7 @@ public DefaultIssDetector( selfIssRateLimiter = new RateLimiter(platformContext.getTime(), timeBetweenIssLogs); catastrophicIssRateLimiter = new RateLimiter(platformContext.getTime(), timeBetweenIssLogs); - this.addressBook = Objects.requireNonNull(addressBook); + this.roster = Objects.requireNonNull(roster); this.currentSoftwareVersion = Objects.requireNonNull(currentSoftwareVersion); this.roundData = new ConcurrentSequenceMap<>( @@ -157,7 +159,7 @@ public DefaultIssDetector( if (ignoredRound != DO_NOT_IGNORE_ROUNDS) { logger.warn(STARTUP.getMarker(), "No ISS detection will be performed for round {}", ignoredRound); } - this.issMetrics = new IssMetrics(platformContext.getMetrics(), addressBook); + this.issMetrics = new IssMetrics(platformContext.getMetrics(), roster); } /** @@ -214,7 +216,8 @@ private List shiftRoundDataWindow(final long roundNumber) { previousRound = roundNumber; - roundData.put(roundNumber, new RoundHashValidator(roundNumber, addressBook.getTotalWeight(), issMetrics)); + roundData.put( + roundNumber, new RoundHashValidator(roundNumber, RosterUtils.computeTotalWeight(roster), issMetrics)); return removedRounds.stream() .map(this::handleRemovedRound) @@ -341,7 +344,9 @@ private IssNotification handlePostconsensusSignature( return null; } - if (!addressBook.contains(signerId)) { + final RosterEntry node = RosterUtils.getRosterEntryOrNull(roster, signerId.id()); + + if (node == null) { // we don't care about nodes not in the address book return null; } @@ -351,8 +356,6 @@ private IssNotification handlePostconsensusSignature( return null; } - final long nodeWeight = addressBook.getAddress(signerId).getWeight(); - final RoundHashValidator roundValidator = roundData.get(signaturePayload.round()); if (roundValidator == null) { // We are being asked to validate a signature from the far future or far past, or a round that has already @@ -361,7 +364,7 @@ private IssNotification handlePostconsensusSignature( } final boolean decided = - roundValidator.reportHashFromNetwork(signerId, nodeWeight, new Hash(signaturePayload.hash())); + roundValidator.reportHashFromNetwork(signerId, node.weight(), new Hash(signaturePayload.hash())); if (decided) { return checkValidity(roundValidator); } diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java index 7e75693d7691..38ad75bf149e 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java @@ -30,6 +30,8 @@ import static org.mockito.Mockito.when; import com.hedera.hapi.node.base.SemanticVersion; +import com.hedera.hapi.node.state.roster.Roster; +import com.hedera.hapi.node.state.roster.RosterEntry; import com.hedera.hapi.platform.event.StateSignatureTransaction; import com.hedera.pbj.runtime.OneOf; import com.hedera.pbj.runtime.io.buffer.Bytes; @@ -41,18 +43,17 @@ import com.swirlds.platform.consensus.ConsensusConfig; import com.swirlds.platform.internal.ConsensusRound; import com.swirlds.platform.internal.EventImpl; +import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.iss.DefaultIssDetector; import com.swirlds.platform.state.iss.IssDetector; import com.swirlds.platform.state.iss.internal.HashValidityStatus; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; -import com.swirlds.platform.system.address.Address; -import com.swirlds.platform.system.address.AddressBook; import com.swirlds.platform.system.state.notifications.IssNotification; import com.swirlds.platform.system.state.notifications.IssNotification.IssType; import com.swirlds.platform.test.PlatformTest; -import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder; +import com.swirlds.platform.test.fixtures.addressbook.RandomRosterBuilder; import com.swirlds.platform.test.fixtures.event.EventImplTestUtils; import com.swirlds.platform.test.fixtures.event.TestingEventBuilder; import com.swirlds.platform.wiring.components.StateAndRound; @@ -62,6 +63,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Random; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -108,20 +110,21 @@ private static List generateEventsContainingSignatures( * consistent hash. * * @param random a source of randomness - * @param addressBook the address book to use to generate the signature transactions + * @param roster the roster to use to generate the signature transactions * @param roundNumber the round that signature transactions will be for * @param roundHash the hash that all signature transactions will be made on * @return a list of events, each containing a signature transaction from a node for the given round */ private static List generateEventsWithConsistentSignatures( @NonNull final Randotron random, - @NonNull final AddressBook addressBook, + @NonNull final Roster roster, final long roundNumber, @NonNull final Hash roundHash) { final List nodeHashInfos = new ArrayList<>(); - addressBook.forEach(address -> nodeHashInfos.add( - new RoundHashValidatorTests.NodeHashInfo(address.getNodeId(), roundHash, roundNumber))); + roster.rosterEntries() + .forEach(node -> nodeHashInfos.add( + new RoundHashValidatorTests.NodeHashInfo(NodeId.of(node.nodeId()), roundHash, roundNumber))); // create signature transactions for this round return generateEventsContainingSignatures( @@ -172,7 +175,7 @@ private static ConsensusRound createRoundWithSignatureEvents( @DisplayName("No ISSes Test") void noIss() { final Randotron random = Randotron.create(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(100) .withAverageWeight(100) .withWeightStandardDeviation(50) @@ -180,8 +183,8 @@ void noIss() { final PlatformContext platformContext = createDefaultPlatformContext(); - final IssDetector issDetector = new DefaultIssDetector( - platformContext, addressBook, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); + final IssDetector issDetector = + new DefaultIssDetector(platformContext, roster, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); final IssDetectorTestHelper issDetectorTestHelper = new IssDetectorTestHelper(issDetector); // signature events are generated for each round when that round is handled, and then are included randomly @@ -196,8 +199,7 @@ void noIss() { final Hash roundHash = randomHash(random); // create signature transactions for this round - signatureEvents.addAll( - generateEventsWithConsistentSignatures(random, addressBook, currentRound, roundHash)); + signatureEvents.addAll(generateEventsWithConsistentSignatures(random, roster, currentRound, roundHash)); // randomly select half of unsubmitted signature events to include in this round final List eventsToInclude = selectRandomEvents(random, signatureEvents); @@ -238,7 +240,7 @@ void noIss() { void mixedOrderTest() { final Randotron random = Randotron.create(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) @@ -246,7 +248,7 @@ void mixedOrderTest() { final PlatformContext platformContext = createDefaultPlatformContext(); - final NodeId selfId = addressBook.getNodeId(0); + final NodeId selfId = NodeId.of(roster.rosterEntries().getFirst().nodeId()); final int roundsNonAncient = platformContext .getConfiguration() .getConfigData(ConsensusConfig.class) @@ -264,7 +266,7 @@ void mixedOrderTest() { if (random.nextDouble() < 2.0 / 3) { // Choose hashes so that there is a valid consensus hash - data = generateRegularNodeHashes(random, addressBook, round); + data = generateRegularNodeHashes(random, roster, round); HashValidityStatus expectedStatus = null; @@ -288,7 +290,7 @@ void mixedOrderTest() { expectedRoundStatus.add(expectedStatus); } else { // Choose hashes that will result in a catastrophic ISS - data = generateCatastrophicNodeHashes(random, addressBook, round); + data = generateCatastrophicNodeHashes(random, roster, round); roundData.add(data); expectedRoundStatus.add(HashValidityStatus.CATASTROPHIC_ISS); expectedCatastrophicIssCount++; @@ -304,8 +306,8 @@ void mixedOrderTest() { } } - final IssDetector issDetector = new DefaultIssDetector( - platformContext, addressBook, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); + final IssDetector issDetector = + new DefaultIssDetector(platformContext, roster, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); final IssDetectorTestHelper issDetectorTestHelper = new IssDetectorTestHelper(issDetector); long currentRound = 0; @@ -387,15 +389,15 @@ void decideForCatastrophicIss() { final Randotron random = Randotron.create(); final PlatformContext platformContext = createDefaultPlatformContext(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(100) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final NodeId selfId = addressBook.getNodeId(0); + final NodeId selfId = NodeId.of(roster.rosterEntries().getFirst().nodeId()); - final IssDetector issDetector = new DefaultIssDetector( - platformContext, addressBook, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); + final IssDetector issDetector = + new DefaultIssDetector(platformContext, roster, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); final IssDetectorTestHelper issDetectorTestHelper = new IssDetectorTestHelper(issDetector); long currentRound = 0; @@ -406,7 +408,7 @@ void decideForCatastrophicIss() { // the round after the initial state will have a catastrophic iss final RoundHashValidatorTests.HashGenerationData catastrophicHashData = - generateCatastrophicNodeHashes(random, addressBook, currentRound); + generateCatastrophicNodeHashes(random, roster, currentRound); final Hash selfHashForCatastrophicRound = catastrophicHashData.nodeList().stream() .filter(info -> info.nodeId() == selfId) .findFirst() @@ -434,13 +436,15 @@ void decideForCatastrophicIss() { mockState(currentRound, randomHash()), anotherRound, systemTransactionsForRoundWithoutSignatures)); } + final Map nodesById = RosterUtils.toMap(roster); + // submit signatures on the ISS round that represent a minority of the weight long submittedWeight = 0; final List signaturesToSubmit = new ArrayList<>(); for (final EventImpl signatureEvent : signaturesOnCatastrophicRound) { final long weight = - addressBook.getAddress(signatureEvent.getCreatorId()).getWeight(); - if (MAJORITY.isSatisfiedBy(submittedWeight + weight, addressBook.getTotalWeight())) { + nodesById.get(signatureEvent.getCreatorId().id()).weight(); + if (MAJORITY.isSatisfiedBy(submittedWeight + weight, RosterUtils.computeTotalWeight(roster))) { // If we add less than a majority then we won't be able to detect the ISS no matter what break; } @@ -482,7 +486,7 @@ void decideForCatastrophicIss() { * signatures being on an incorrect hash. */ private static List generateCatastrophicTimeoutIss( - final Random random, final AddressBook addressBook, final long targetRound) { + final Random random, final Roster roster, final long targetRound) { final List data = new LinkedList<>(); @@ -493,13 +497,13 @@ private static List generateCatastrophicTi final Hash almostConsensusHash = randomHash(random); long almostConsensusWeight = 0; - for (final Address address : addressBook) { - if (MAJORITY.isSatisfiedBy(almostConsensusWeight + address.getWeight(), addressBook.getTotalWeight())) { - data.add(new RoundHashValidatorTests.NodeHashInfo(address.getNodeId(), randomHash(), targetRound)); + for (final RosterEntry node : roster.rosterEntries()) { + final NodeId nodeId = NodeId.of(node.nodeId()); + if (MAJORITY.isSatisfiedBy(almostConsensusWeight + node.weight(), RosterUtils.computeTotalWeight(roster))) { + data.add(new RoundHashValidatorTests.NodeHashInfo(nodeId, randomHash(), targetRound)); } else { - almostConsensusWeight += address.getWeight(); - data.add(new RoundHashValidatorTests.NodeHashInfo( - address.getNodeId(), almostConsensusHash, targetRound)); + almostConsensusWeight += node.weight(); + data.add(new RoundHashValidatorTests.NodeHashInfo(nodeId, almostConsensusHash, targetRound)); } } @@ -521,21 +525,21 @@ void catastrophicShiftBeforeCompleteTest() { .getConfiguration() .getConfigData(ConsensusConfig.class) .roundsNonAncient(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(100) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final NodeId selfId = addressBook.getNodeId(0); + final NodeId selfId = NodeId.of(roster.rosterEntries().getFirst().nodeId()); - final IssDetector issDetector = new DefaultIssDetector( - platformContext, addressBook, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); + final IssDetector issDetector = + new DefaultIssDetector(platformContext, roster, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); final IssDetectorTestHelper issDetectorTestHelper = new IssDetectorTestHelper(issDetector); long currentRound = 0; final List catastrophicData = - generateCatastrophicTimeoutIss(random, addressBook, currentRound); + generateCatastrophicTimeoutIss(random, roster, currentRound); final Hash selfHashForCatastrophicRound = catastrophicData.stream() .filter(info -> info.nodeId() == selfId) .findFirst() @@ -544,18 +548,19 @@ void catastrophicShiftBeforeCompleteTest() { final List signaturesOnCatastrophicRound = generateEventsContainingSignatures( random, currentRound, new RoundHashValidatorTests.HashGenerationData(catastrophicData, null)); + final Map nodesById = RosterUtils.toMap(roster); long submittedWeight = 0; final List signaturesToSubmit = new ArrayList<>(); for (final EventImpl signatureEvent : signaturesOnCatastrophicRound) { final long weight = - addressBook.getAddress(signatureEvent.getCreatorId()).getWeight(); + nodesById.get(signatureEvent.getCreatorId().id()).weight(); signaturesToSubmit.add(signatureEvent); // Stop once we have added >2/3. We should not have decided yet, but will // have gathered enough to declare a catastrophic ISS submittedWeight += weight; - if (SUPER_MAJORITY.isSatisfiedBy(submittedWeight, addressBook.getTotalWeight())) { + if (SUPER_MAJORITY.isSatisfiedBy(submittedWeight, RosterUtils.computeTotalWeight(roster))) { break; } } @@ -619,15 +624,15 @@ void bigShiftTest() { .getConfiguration() .getConfigData(ConsensusConfig.class) .roundsNonAncient(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(100) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final NodeId selfId = addressBook.getNodeId(0); + final NodeId selfId = NodeId.of(roster.rosterEntries().getFirst().nodeId()); - final IssDetector issDetector = new DefaultIssDetector( - platformContext, addressBook, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); + final IssDetector issDetector = + new DefaultIssDetector(platformContext, roster, SemanticVersion.DEFAULT, false, DO_NOT_IGNORE_ROUNDS); final IssDetectorTestHelper issDetectorTestHelper = new IssDetectorTestHelper(issDetector); long currentRound = 0; @@ -637,7 +642,7 @@ void bigShiftTest() { currentRound++; final List catastrophicData = - generateCatastrophicTimeoutIss(random, addressBook, currentRound); + generateCatastrophicTimeoutIss(random, roster, currentRound); final Hash selfHashForCatastrophicRound = catastrophicData.stream() .filter(info -> info.nodeId() == selfId) .findFirst() @@ -656,17 +661,18 @@ void bigShiftTest() { catastrophicRound, systemTransactionsForCatastrophicRound)); + final Map nodesById = RosterUtils.toMap(roster); long submittedWeight = 0; final List signaturesToSubmit = new ArrayList<>(); for (final EventImpl signatureEvent : signaturesOnCatastrophicRound) { final long weight = - addressBook.getAddress(signatureEvent.getCreatorId()).getWeight(); + nodesById.get(signatureEvent.getCreatorId().id()).weight(); // Stop once we have added >2/3. We should not have decided yet, but will have gathered enough to declare a // catastrophic ISS submittedWeight += weight; signaturesToSubmit.add(signatureEvent); - if (SUPER_MAJORITY.isSatisfiedBy(submittedWeight + weight, addressBook.getTotalWeight())) { + if (SUPER_MAJORITY.isSatisfiedBy(submittedWeight + weight, RosterUtils.computeTotalWeight(roster))) { break; } } @@ -702,7 +708,7 @@ void bigShiftTest() { void ignoredRoundTest() { final Randotron random = Randotron.create(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(100) .withAverageWeight(100) .withWeightStandardDeviation(50) @@ -715,7 +721,7 @@ void ignoredRoundTest() { .roundsNonAncient(); final IssDetector issDetector = - new DefaultIssDetector(platformContext, addressBook, SemanticVersion.DEFAULT, false, 1); + new DefaultIssDetector(platformContext, roster, SemanticVersion.DEFAULT, false, 1); final IssDetectorTestHelper issDetectorTestHelper = new IssDetectorTestHelper(issDetector); long currentRound = 0; @@ -724,7 +730,7 @@ void ignoredRoundTest() { currentRound++; final List catastrophicData = - generateCatastrophicTimeoutIss(random, addressBook, currentRound); + generateCatastrophicTimeoutIss(random, roster, currentRound); final List signaturesOnCatastrophicRound = generateEventsContainingSignatures( random, currentRound, new RoundHashValidatorTests.HashGenerationData(catastrophicData, null)); diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssMetricsTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssMetricsTests.java index e39406d869ff..8561e04e3eaf 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssMetricsTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssMetricsTests.java @@ -21,14 +21,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import com.hedera.hapi.node.state.roster.Roster; +import com.hedera.hapi.node.state.roster.RosterEntry; import com.swirlds.common.crypto.Hash; import com.swirlds.common.metrics.noop.NoOpMetrics; import com.swirlds.common.platform.NodeId; import com.swirlds.common.test.fixtures.Randotron; import com.swirlds.platform.metrics.IssMetrics; -import com.swirlds.platform.system.address.Address; -import com.swirlds.platform.system.address.AddressBook; -import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder; +import com.swirlds.platform.roster.RosterUtils; +import com.swirlds.platform.test.fixtures.addressbook.RandomRosterBuilder; import java.util.Random; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -40,16 +41,16 @@ class IssMetricsTests { @DisplayName("Update Non-Existent Node") void updateNonExistentNode() { final Randotron randotron = Randotron.create(); - - final AddressBook addressBook = - RandomAddressBookBuilder.create(randotron).withSize(100).build(); - - final IssMetrics issMetrics = new IssMetrics(new NoOpMetrics(), addressBook); + final Roster roster = + RandomRosterBuilder.create(randotron).withSize(100).build(); + final IssMetrics issMetrics = new IssMetrics(new NoOpMetrics(), roster); + final Hash hashA = randomHash(); + final Hash hashB = randomHash(); + final NodeId nodeId = NodeId.of(Integer.MAX_VALUE); assertThrows( IllegalArgumentException.class, - () -> issMetrics.stateHashValidityObserver( - 0L, NodeId.of(Integer.MAX_VALUE), randomHash(), randomHash()), + () -> issMetrics.stateHashValidityObserver(0L, nodeId, hashA, hashB), "should not be able to update stats for non-existent node"); } @@ -61,10 +62,9 @@ void updateTest() { final Hash hashA = randomHash(random); final Hash hashB = randomHash(random); - final AddressBook addressBook = - RandomAddressBookBuilder.create(random).withSize(100).build(); + final Roster roster = RandomRosterBuilder.create(random).withSize(100).build(); - final IssMetrics issMetrics = new IssMetrics(new NoOpMetrics(), addressBook); + final IssMetrics issMetrics = new IssMetrics(new NoOpMetrics(), roster); assertEquals(0, issMetrics.getIssCount(), "there shouldn't be any nodes in an ISS state"); assertEquals(0, issMetrics.getIssWeight(), "there shouldn't be any weight in an ISS state"); @@ -74,13 +74,14 @@ void updateTest() { long expectedIssweight = 0; // Change even numbered nodes to have an ISS - for (final Address address : addressBook) { - if (address.getNodeId().id() % 2 == 0) { - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hashB); + for (final RosterEntry node : roster.rosterEntries()) { + final NodeId nodeId = NodeId.of(node.nodeId()); + if (node.nodeId() % 2 == 0) { + issMetrics.stateHashValidityObserver(round, nodeId, hashA, hashB); expectedIssCount++; - expectedIssweight += address.getWeight(); + expectedIssweight += node.weight(); } else { - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hashA); + issMetrics.stateHashValidityObserver(round, nodeId, hashA, hashA); } assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); @@ -88,38 +89,39 @@ void updateTest() { // For the next round, report the same statuses. No change is expected. round++; - for (final Address address : addressBook) { - final Hash hash = address.getNodeId().id() % 2 != 0 ? hashA : hashB; - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hash); + for (final RosterEntry node : roster.rosterEntries()) { + final Hash hash = node.nodeId() % 2 != 0 ? hashA : hashB; + issMetrics.stateHashValidityObserver(round, NodeId.of(node.nodeId()), hashA, hash); assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); } // Report data from the same round number. This is expected to be ignored. - for (final Address address : addressBook) { - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hashA); + for (final RosterEntry node : roster.rosterEntries()) { + issMetrics.stateHashValidityObserver(round, NodeId.of(node.nodeId()), hashA, hashA); assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); } // Report data from a lower round number. This is expected to be ignored. - for (final Address address : addressBook) { - issMetrics.stateHashValidityObserver(round - 1, address.getNodeId(), hashA, hashA); + for (final RosterEntry node : roster.rosterEntries()) { + issMetrics.stateHashValidityObserver(round - 1, NodeId.of(node.nodeId()), hashA, hashA); assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); } // Switch the status of each node. round++; - for (final Address address : addressBook) { - if (address.getNodeId().id() % 2 == 0) { - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hashA); + for (final RosterEntry node : roster.rosterEntries()) { + final NodeId nodeId = NodeId.of(node.nodeId()); + if (node.nodeId() % 2 == 0) { + issMetrics.stateHashValidityObserver(round, nodeId, hashA, hashA); expectedIssCount--; - expectedIssweight -= address.getWeight(); + expectedIssweight -= node.weight(); } else { - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hashB); + issMetrics.stateHashValidityObserver(round, nodeId, hashA, hashB); expectedIssCount++; - expectedIssweight += address.getWeight(); + expectedIssweight += node.weight(); } assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); @@ -133,17 +135,17 @@ void updateTest() { // Report a catastrophic ISS. round++; issMetrics.catastrophicIssObserver(round); - expectedIssCount = addressBook.getSize(); - expectedIssweight = addressBook.getTotalWeight(); + expectedIssCount = roster.rosterEntries().size(); + expectedIssweight = RosterUtils.computeTotalWeight(roster); assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); // Heal all nodes. round++; - for (final Address address : addressBook) { - issMetrics.stateHashValidityObserver(round, address.getNodeId(), hashA, hashA); + for (final RosterEntry node : roster.rosterEntries()) { + issMetrics.stateHashValidityObserver(round, NodeId.of(node.nodeId()), hashA, hashA); expectedIssCount--; - expectedIssweight -= address.getWeight(); + expectedIssweight -= node.weight(); assertEquals(expectedIssCount, issMetrics.getIssCount(), "unexpected ISS count"); assertEquals(expectedIssweight, issMetrics.getIssWeight(), "unexpected ISS weight"); } diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/RoundHashValidatorTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/RoundHashValidatorTests.java index 8c6e64f4d5e7..463c394d6b22 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/RoundHashValidatorTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/RoundHashValidatorTests.java @@ -24,17 +24,20 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.hedera.hapi.node.state.roster.Roster; +import com.hedera.hapi.node.state.roster.RosterEntry; import com.swirlds.common.crypto.Hash; import com.swirlds.common.platform.NodeId; import com.swirlds.platform.metrics.IssMetrics; +import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.state.iss.internal.HashValidityStatus; import com.swirlds.platform.state.iss.internal.RoundHashValidator; -import com.swirlds.platform.system.address.AddressBook; -import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder; +import com.swirlds.platform.test.fixtures.addressbook.RandomRosterBuilder; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -75,19 +78,19 @@ record HashGenerationData(List nodeList, Hash consensusHash) {} * Based on the desired network status, generate hashes for all nodes. * * @param random a source of randomness - * @param addressBook the address book for the round + * @param roster the roster for the round * @param desiredValidityStatus the desired validity status * @return a list of node IDs in the order they should be added to the hash validator */ static HashGenerationData generateNodeHashes( final Random random, - final AddressBook addressBook, + final Roster roster, final HashValidityStatus desiredValidityStatus, final long round) { if (desiredValidityStatus == HashValidityStatus.VALID || desiredValidityStatus == HashValidityStatus.SELF_ISS) { - return generateRegularNodeHashes(random, addressBook, round); + return generateRegularNodeHashes(random, roster, round); } else if (desiredValidityStatus == HashValidityStatus.CATASTROPHIC_ISS) { - return generateCatastrophicNodeHashes(random, addressBook, round); + return generateCatastrophicNodeHashes(random, roster, round); } else { throw new IllegalArgumentException("Unsupported case " + desiredValidityStatus); } @@ -96,8 +99,7 @@ static HashGenerationData generateNodeHashes( /** * Generate node hashes without there being a catastrophic ISS. */ - static HashGenerationData generateRegularNodeHashes( - final Random random, final AddressBook addressBook, final long round) { + static HashGenerationData generateRegularNodeHashes(final Random random, final Roster roster, final long round) { // Greater than 1/2 must have the same hash. But all other nodes are free to take whatever other hash // they want. Choose that fraction randomly. @@ -105,10 +107,10 @@ static HashGenerationData generateRegularNodeHashes( final List nodes = new LinkedList<>(); final List randomNodeOrder = new LinkedList<>(); - addressBook.iterator().forEachRemaining(address -> randomNodeOrder.add(address.getNodeId())); + roster.rosterEntries().forEach(node -> randomNodeOrder.add(NodeId.of(node.nodeId()))); Collections.shuffle(randomNodeOrder, random); - final long totalWeight = addressBook.getTotalWeight(); + final long totalWeight = RosterUtils.computeTotalWeight(roster); // This is the hash we want to be chosen for the consensus hash. final Hash consensusHash = randomHash(random); @@ -124,8 +126,9 @@ static HashGenerationData generateRegularNodeHashes( final List randomHashNodes = new LinkedList<>(); // Assign each node to one of the hashing strategies described above. + final Map nodesById = RosterUtils.toMap(roster); for (final NodeId nodeId : randomNodeOrder) { - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); if (!MAJORITY.isSatisfiedBy(correctHashWeight, totalWeight)) { correctHashNodes.add(nodeId); @@ -146,7 +149,7 @@ static HashGenerationData generateRegularNodeHashes( // Now, decide what order the hashes should be processed. Make sure that the // consensus hash is the first to reach a strong minority. - while (nodes.size() < addressBook.getSize()) { + while (nodes.size() < roster.rosterEntries().size()) { final double choice = random.nextDouble(); allowedIterations--; @@ -155,14 +158,14 @@ static HashGenerationData generateRegularNodeHashes( if (choice < 1.0 / 3) { if (!correctHashNodes.isEmpty()) { final NodeId nodeId = correctHashNodes.remove(0); - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); nodes.add(new NodeHashInfo(nodeId, consensusHash, round)); correctHashWeight += weight; } } else if (choice < 2.0 / 3) { if (!otherHashNodes.isEmpty()) { final NodeId nodeId = otherHashNodes.get(0); - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); if (MAJORITY.isSatisfiedBy(otherHashWeight + weight, totalWeight)) { // We don't want to allow the other hash to accumulate >1/2 @@ -172,7 +175,7 @@ static HashGenerationData generateRegularNodeHashes( otherHashNodes.remove(0); nodes.add(new NodeHashInfo(nodeId, otherHash, round)); - otherHashWeight += addressBook.getAddress(nodeId).getWeight(); + otherHashWeight += nodesById.get(nodeId.id()).weight(); } } else { // The random hashes will never reach a majority, so they can go in whenever @@ -190,24 +193,25 @@ static HashGenerationData generateRegularNodeHashes( * Generate node hashes that result in a catastrophic ISS. */ static HashGenerationData generateCatastrophicNodeHashes( - final Random random, final AddressBook addressBook, final long round) { + final Random random, final Roster roster, final long round) { // There should exist no group of nodes with the same hash that >1/2 final List nodes = new ArrayList<>(); - final long totalWeight = addressBook.getTotalWeight(); + final long totalWeight = RosterUtils.computeTotalWeight(roster); final List randomNodeOrder = new LinkedList<>(); - addressBook.iterator().forEachRemaining(address -> randomNodeOrder.add(address.getNodeId())); + roster.rosterEntries().forEach(node -> randomNodeOrder.add(NodeId.of(node.nodeId()))); Collections.shuffle(randomNodeOrder, random); // A large group of nodes may decide to use this hash. But it won't become the consensus hash. final Hash otherHash = randomHash(random); long otherHashWeight = 0; + final Map nodesById = RosterUtils.toMap(roster); for (final NodeId nodeId : randomNodeOrder) { - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final double choice = random.nextDouble(); if (choice < 1.0 / 3 && !MAJORITY.isSatisfiedBy(otherHashWeight + weight, totalWeight)) { @@ -260,24 +264,25 @@ private static NodeHashInfo chooseSelfNode( void selfSignatureLastTest(final HashValidityStatus expectedStatus) { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final HashGenerationData hashGenerationData = generateNodeHashes(random, addressBook, expectedStatus, 0); + final HashGenerationData hashGenerationData = generateNodeHashes(random, roster, expectedStatus, 0); final NodeHashInfo thisNode = chooseSelfNode(random, hashGenerationData, expectedStatus); final long round = random.nextInt(1000); final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + new RoundHashValidator(round, RosterUtils.computeTotalWeight(roster), Mockito.mock(IssMetrics.class)); boolean decided = false; + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; final boolean operationCausedDecision = validator.reportHashFromNetwork(nodeId, weight, hash); @@ -306,18 +311,18 @@ void selfSignatureLastTest(final HashValidityStatus expectedStatus) { void selfSignatureFirstTest(final HashValidityStatus expectedStatus) { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final HashGenerationData hashGenerationData = generateNodeHashes(random, addressBook, expectedStatus, 0); + final HashGenerationData hashGenerationData = generateNodeHashes(random, roster, expectedStatus, 0); final NodeHashInfo thisNode = chooseSelfNode(random, hashGenerationData, expectedStatus); final long round = random.nextInt(1000); final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + new RoundHashValidator(round, RosterUtils.computeTotalWeight(roster), Mockito.mock(IssMetrics.class)); boolean decided = false; @@ -325,9 +330,10 @@ void selfSignatureFirstTest(final HashValidityStatus expectedStatus) { validator.reportSelfHash(thisNode.nodeStateHash), "we should need to gather more data before becoming decided"); + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; final boolean operationCausedDecision = validator.reportHashFromNetwork(nodeId, weight, hash); @@ -350,27 +356,28 @@ void selfSignatureFirstTest(final HashValidityStatus expectedStatus) { void selfSignatureInMiddleTest(final HashValidityStatus expectedStatus) { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final HashGenerationData hashGenerationData = generateNodeHashes(random, addressBook, expectedStatus, 0); + final HashGenerationData hashGenerationData = generateNodeHashes(random, roster, expectedStatus, 0); final NodeHashInfo thisNode = chooseSelfNode(random, hashGenerationData, expectedStatus); final long round = random.nextInt(1000); final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + new RoundHashValidator(round, RosterUtils.computeTotalWeight(roster), Mockito.mock(IssMetrics.class)); boolean decided = false; - final int addSelfHashIndex = random.nextInt(addressBook.getSize() - 1); + final int addSelfHashIndex = random.nextInt(roster.rosterEntries().size() - 1); int index = 0; + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; if (index == addSelfHashIndex) { @@ -400,22 +407,22 @@ void selfSignatureInMiddleTest(final HashValidityStatus expectedStatus) { void timeoutSelfHashTest() { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final HashGenerationData hashGenerationData = - generateNodeHashes(random, addressBook, HashValidityStatus.VALID, 0); + final HashGenerationData hashGenerationData = generateNodeHashes(random, roster, HashValidityStatus.VALID, 0); final long round = random.nextInt(1000); final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + new RoundHashValidator(round, RosterUtils.computeTotalWeight(roster), Mockito.mock(IssMetrics.class)); + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; assertFalse(validator.reportHashFromNetwork(nodeId, weight, hash), "insufficient data to make decision"); @@ -433,25 +440,24 @@ void timeoutSelfHashTest() { void timeoutSelfHashAndSignaturesTest() { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final long totalWeight = addressBook.getTotalWeight(); + final long totalWeight = RosterUtils.computeTotalWeight(roster); - final HashGenerationData hashGenerationData = - generateNodeHashes(random, addressBook, HashValidityStatus.VALID, 0); + final HashGenerationData hashGenerationData = generateNodeHashes(random, roster, HashValidityStatus.VALID, 0); final long round = random.nextInt(1000); - final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + final RoundHashValidator validator = new RoundHashValidator(round, totalWeight, Mockito.mock(IssMetrics.class)); long addedWeight = 0; + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; if (MAJORITY.isSatisfiedBy(addedWeight + weight, totalWeight)) { @@ -474,28 +480,27 @@ void timeoutSelfHashAndSignaturesTest() { void timeoutSignaturesTest() { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final long totalWeight = addressBook.getTotalWeight(); + final long totalWeight = RosterUtils.computeTotalWeight(roster); - final HashGenerationData hashGenerationData = - generateNodeHashes(random, addressBook, HashValidityStatus.VALID, 0); + final HashGenerationData hashGenerationData = generateNodeHashes(random, roster, HashValidityStatus.VALID, 0); final NodeHashInfo thisNode = chooseSelfNode(random, hashGenerationData, HashValidityStatus.VALID); final long round = random.nextInt(1000); - final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + final RoundHashValidator validator = new RoundHashValidator(round, totalWeight, Mockito.mock(IssMetrics.class)); assertFalse(validator.reportSelfHash(thisNode.nodeStateHash), "should not allow a decision"); long addedWeight = 0; + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; if (MAJORITY.isSatisfiedBy(addedWeight + weight, totalWeight)) { @@ -519,28 +524,28 @@ void timeoutSignaturesTest() { void timeoutWithSuperMajorityTest() { final Random random = getRandomPrintSeed(); - final AddressBook addressBook = RandomAddressBookBuilder.create(random) + final Roster roster = RandomRosterBuilder.create(random) .withSize(Math.max(10, random.nextInt(1000))) .withAverageWeight(100) .withWeightStandardDeviation(50) .build(); - final long totalWeight = addressBook.getTotalWeight(); + final long totalWeight = RosterUtils.computeTotalWeight(roster); final HashGenerationData hashGenerationData = - generateNodeHashes(random, addressBook, HashValidityStatus.CATASTROPHIC_ISS, 0); + generateNodeHashes(random, roster, HashValidityStatus.CATASTROPHIC_ISS, 0); final NodeHashInfo thisNode = chooseSelfNode(random, hashGenerationData, HashValidityStatus.CATASTROPHIC_ISS); final long round = random.nextInt(1000); - final RoundHashValidator validator = - new RoundHashValidator(round, addressBook.getTotalWeight(), Mockito.mock(IssMetrics.class)); + final RoundHashValidator validator = new RoundHashValidator(round, totalWeight, Mockito.mock(IssMetrics.class)); assertFalse(validator.reportSelfHash(thisNode.nodeStateHash), "should not allow a decision"); long addedWeight = 0; + final Map nodesById = RosterUtils.toMap(roster); for (final NodeHashInfo nodeHashInfo : hashGenerationData.nodeList) { final NodeId nodeId = nodeHashInfo.nodeId; - final long weight = addressBook.getAddress(nodeId).getWeight(); + final long weight = nodesById.get(nodeId.id()).weight(); final Hash hash = nodeHashInfo.nodeStateHash; boolean decided = validator.reportHashFromNetwork(nodeId, weight, hash); From 0bf0e37aa58a620bc3b334be4d289f434965553f Mon Sep 17 00:00:00 2001 From: Thomas Moran <152873392+thomas-swirlds-labs@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:07:27 +0000 Subject: [PATCH 07/12] chore: schedule release cutting 0.58 (#17120) Signed-off-by: Thomas Moran <152873392+thomas-swirlds-labs@users.noreply.github.com> --- .github/workflows/config/node-release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/config/node-release.yaml b/.github/workflows/config/node-release.yaml index 18a52d366e68..6be706bec502 100644 --- a/.github/workflows/config/node-release.yaml +++ b/.github/workflows/config/node-release.yaml @@ -1,9 +1,9 @@ release: branching: execution: - time: "18:00:00" + time: "20:00:00" schedule: - - on: "2024-12-13" + - on: "2024-12-20" name: release/0.58 initial-tag: create: true From a9692704da783ef3754b84a23fa1b1aa0654f920 Mon Sep 17 00:00:00 2001 From: anthony-swirldslabs <152534762+anthony-swirldslabs@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:41:49 -0800 Subject: [PATCH 08/12] chore: replace setAddressBook with setActiveRoster (#17139) Signed-off-by: Anthony Petrov --- .../cli/GenesisPlatformStateCommand.java | 16 ++++ .../swirlds/platform/roster/RosterUtils.java | 28 ++++++- .../state/service/WritableRosterStore.java | 33 ++++++++- .../state/signed/StartupStateUtils.java | 23 ++++-- .../system/address/AddressBookUtils.java | 74 ++++++++++++------- .../platform/state/SignedStateTests.java | 12 ++- .../addressbook/RandomAddressBuilder.java | 2 +- .../addressbook/RandomRosterEntryBuilder.java | 2 +- .../platform/test/PlatformStateUtils.java | 8 -- 9 files changed, 148 insertions(+), 50 deletions(-) diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java index 77ea6e1959e6..4606b861ed51 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java @@ -22,6 +22,7 @@ import com.swirlds.cli.commands.StateCommand; import com.swirlds.cli.utility.AbstractCommand; import com.swirlds.cli.utility.SubcommandOf; +import com.swirlds.common.RosterStateId; import com.swirlds.common.context.PlatformContext; import com.swirlds.common.merkle.crypto.MerkleCryptoFactory; import com.swirlds.config.api.Configuration; @@ -30,10 +31,14 @@ import com.swirlds.platform.consensus.SyntheticSnapshot; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.PlatformStateModifier; +import com.swirlds.platform.state.service.WritableRosterStore; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.snapshot.DeserializedSignedState; import com.swirlds.platform.state.snapshot.SignedStateFileReader; import com.swirlds.platform.util.BootstrapUtils; +import com.swirlds.state.State; +import com.swirlds.state.spi.CommittableWritableStates; +import com.swirlds.state.spi.WritableStates; import java.io.IOException; import java.nio.file.Path; import java.util.concurrent.ExecutionException; @@ -81,10 +86,21 @@ public Integer call() throws IOException, ExecutionException, InterruptedExcepti System.out.printf("Replacing platform data %n"); v.setRound(PlatformStateAccessor.GENESIS_ROUND); v.setSnapshot(SyntheticSnapshot.getGenesisSnapshot()); + + // FUTURE WORK: remove once the AddressBook setters are deprecated and the fields are nullified. + // For now, we have to keep these calls to ensure RosterRetriever won't fall back to using these values. System.out.printf("Nullifying Address Books %n"); v.setAddressBook(null); v.setPreviousAddressBook(null); }); + { + System.out.printf("Resetting the RosterService state %n"); + final State state = (State) reservedSignedState.get().getState().getSwirldState(); + final WritableStates writableStates = state.getWritableStates(RosterStateId.NAME); + final WritableRosterStore writableRosterStore = new WritableRosterStore(writableStates); + writableRosterStore.resetRosters(); + ((CommittableWritableStates) writableStates).commit(); + } System.out.printf("Hashing state %n"); MerkleCryptoFactory.getInstance() .digestTreeAsync(reservedSignedState.get().getState()) diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/roster/RosterUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/roster/RosterUtils.java index c71747b005d8..28fddcf62c60 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/roster/RosterUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/roster/RosterUtils.java @@ -1,4 +1,19 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.swirlds.platform.roster; import com.hedera.hapi.node.base.ServiceEndpoint; @@ -293,6 +308,17 @@ public static void setActiveRoster(@NonNull final State state, @NonNull final Ro ((CommittableWritableStates) writableStates).commit(); } + /** + * Formats a human-readable Roster representation, currently using its JSON codec, + * or returns {@code null} if the given roster object is null. + * @param roster a roster to format + * @return roster JSON string, or null + */ + @Nullable + public static String toString(@Nullable final Roster roster) { + return roster == null ? null : Roster.JSON.toJSON(roster); + } + /** * Build an Address object out of a given RosterEntry object. * diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/service/WritableRosterStore.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/service/WritableRosterStore.java index cb6da5ceed31..4bd55e8fe99f 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/service/WritableRosterStore.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/service/WritableRosterStore.java @@ -33,6 +33,9 @@ import edu.umd.cs.findbugs.annotations.NonNull; import java.util.LinkedList; import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.StreamSupport; /** * Read-write implementation for accessing rosters states. @@ -114,19 +117,28 @@ public void putActiveRoster(@NonNull final Roster roster, final long round) { requireNonNull(roster); RosterValidator.validate(roster); + final Bytes rosterHash = RosterUtils.hash(roster).getBytes(); + // update the roster state final RosterState previousRosterState = rosterStateOrDefault(); final List roundRosterPairs = new LinkedList<>(previousRosterState.roundRosterPairs()); if (!roundRosterPairs.isEmpty()) { final RoundRosterPair activeRosterPair = roundRosterPairs.getFirst(); + if (activeRosterPair.activeRosterHash().equals(rosterHash)) { + // We're trying to set the exact same active roster, maybe even with the same roundNumber. + // This may happen if, for whatever reason, roster updates come from different code paths. + // This shouldn't be considered an error because the system wants to use the exact same + // roster that is currently active anyway. So we silently ignore such a putActiveRoster request + // because it's a no-op: + return; + } if (round < 0 || round <= activeRosterPair.roundNumber()) { throw new IllegalArgumentException("incoming round number = " + round + " must be greater than the round number of the current active roster = " + activeRosterPair.roundNumber() + "."); } } - final Bytes activeRosterHash = RosterUtils.hash(roster).getBytes(); - roundRosterPairs.addFirst(new RoundRosterPair(round, activeRosterHash)); + roundRosterPairs.addFirst(new RoundRosterPair(round, rosterHash)); if (roundRosterPairs.size() > MAXIMUM_ROSTER_HISTORY_SIZE) { final RoundRosterPair lastRemovedRoster = roundRosterPairs.removeLast(); @@ -149,7 +161,22 @@ public void putActiveRoster(@NonNull final Roster roster, final long round) { // so we remove it if it meets removal criteria. removeRoster(previousRosterState.candidateRosterHash()); rosterState.put(newRosterStateBuilder.build()); - rosterMap.put(ProtoBytes.newBuilder().value(activeRosterHash).build(), roster); + rosterMap.put(ProtoBytes.newBuilder().value(rosterHash).build(), roster); + } + + /** + * Reset the roster state to an empty list and remove all entries from the roster map. + * This method is primarily intended to be used in CLI tools that may need to reset + * the RosterService states to a vanilla state, for example to reproduce the genesis state. + */ + public void resetRosters() { + rosterState.put(RosterState.DEFAULT); + + // To avoid modifying the map while iterating over all the keys, collect them into a list first: + final List keys = StreamSupport.stream( + Spliterators.spliteratorUnknownSize(rosterMap.keys(), Spliterator.ORDERED), false) + .toList(); + keys.forEach(rosterMap::remove); } /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java index 09e1e772815d..60c29102456f 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java @@ -35,6 +35,8 @@ import com.swirlds.platform.config.StateConfig; import com.swirlds.platform.crypto.CryptoStatic; import com.swirlds.platform.internal.SignedStateLoadingException; +import com.swirlds.platform.roster.RosterRetriever; +import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.state.snapshot.DeserializedSignedState; @@ -42,6 +44,7 @@ import com.swirlds.platform.state.snapshot.SignedStateFilePath; import com.swirlds.platform.system.SoftwareVersion; import com.swirlds.platform.system.address.AddressBook; +import com.swirlds.state.State; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.io.IOException; @@ -326,7 +329,12 @@ private static ReservedSignedState buildGenesisState( @NonNull final MerkleRoot stateRoot) { if (!configuration.getConfigData(AddressBookConfig.class).useRosterLifecycle()) { - initGenesisPlatformState(configuration, stateRoot.getWritablePlatformState(), addressBook, appVersion); + initGenesisState( + configuration, + (State) stateRoot.getSwirldState(), + stateRoot.getWritablePlatformState(), + addressBook, + appVersion); } final SignedState signedState = new SignedState( @@ -335,21 +343,24 @@ private static ReservedSignedState buildGenesisState( } /** - * Initializes a genesis platform state. + * Initializes a genesis platform state and RosterService state. * @param configuration the configuration for this node + * @param state the State instance to initialize * @param platformState the platform state to initialize * @param addressBook the current address book * @param appVersion the software version of the app */ - private static void initGenesisPlatformState( + private static void initGenesisState( final Configuration configuration, + final State state, final PlatformStateModifier platformState, final AddressBook addressBook, final SoftwareVersion appVersion) { + final long round = 0L; + platformState.bulkUpdate(v -> { - v.setAddressBook(addressBook.copy()); v.setCreationSoftwareVersion(appVersion); - v.setRound(0); + v.setRound(round); v.setLegacyRunningEventHash(null); v.setConsensusTimestamp(Instant.ofEpochSecond(0L)); @@ -360,5 +371,7 @@ private static void initGenesisPlatformState( v.setFreezeTime(Instant.ofEpochSecond(genesisFreezeTime)); } }); + + RosterUtils.setActiveRoster(state, RosterRetriever.buildRoster(addressBook), round); } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java index 9e5a05e2a175..3e7991e05800 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java @@ -1,18 +1,31 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.swirlds.platform.system.address; -import static com.swirlds.platform.roster.RosterRetriever.retrieveActiveOrGenesisRoster; -import static com.swirlds.platform.roster.RosterUtils.buildAddressBook; import static com.swirlds.platform.util.BootstrapUtils.detectSoftwareUpgrade; import com.hedera.hapi.node.base.ServiceEndpoint; +import com.hedera.hapi.node.state.roster.Roster; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.swirlds.common.context.PlatformContext; import com.swirlds.common.formatting.TextTable; import com.swirlds.common.platform.NodeId; -import com.swirlds.platform.config.AddressBookConfig; -import com.swirlds.platform.state.MerkleRoot; -import com.swirlds.platform.state.PlatformStateModifier; +import com.swirlds.platform.roster.RosterRetriever; +import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.state.address.AddressBookInitializer; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.system.SoftwareVersion; @@ -238,31 +251,38 @@ public static ServiceEndpoint endpointFor(@NonNull final String host, final int // Initialize the address book from the configuration and platform saved state. final AddressBookInitializer addressBookInitializer = new AddressBookInitializer( selfId, version, softwareUpgrade, initialState.get(), bootstrapAddressBook.copy(), platformContext); + final State state = (State) initialState.get().getState().getSwirldState(); + + if (addressBookInitializer.hasAddressBookChanged()) { + if (addressBookInitializer.getPreviousAddressBook() != null) { + // We cannot really "update" the previous roster because we don't know the round number + // at which it became active. And we shouldn't do that anyway because under normal circumstances + // the RosterService tracks the roster history correctly. However, since we're given a non-null + // previous AddressBook, and per the current implementation we know it comes from the state, + // we might as well validate this fact here just to ensure the update is correct. + final Roster previousRoster = + RosterRetriever.buildRoster(addressBookInitializer.getPreviousAddressBook()); + if (!previousRoster.equals(RosterRetriever.retrieveActiveOrGenesisRoster(state)) + && !previousRoster.equals(RosterRetriever.retrievePreviousRoster(state))) { + throw new IllegalStateException( + "The previousRoster in the AddressBookInitializer doesn't match either the active or previous roster in state." + + " AddressBookInitializer previousRoster = " + RosterUtils.toString(previousRoster) + + ", state currentRoster = " + + RosterUtils.toString(RosterRetriever.retrieveActiveOrGenesisRoster(state)) + + ", state previousRoster = " + + RosterUtils.toString(RosterRetriever.retrievePreviousRoster(state))); + } + } - final boolean useRosterLifecycle = platformContext - .getConfiguration() - .getConfigData(AddressBookConfig.class) - .useRosterLifecycle(); - if (!useRosterLifecycle && addressBookInitializer.hasAddressBookChanged()) { - final MerkleRoot state = initialState.get().getState(); - // Update the address book with the current address book read from config.txt. - // Eventually we will not do this, and only transactions will be capable of - // modifying the address book. - final PlatformStateModifier platformState = state.getWritablePlatformState(); - platformState.bulkUpdate(v -> { - v.setAddressBook(addressBookInitializer.getCurrentAddressBook().copy()); - v.setPreviousAddressBook( - addressBookInitializer.getPreviousAddressBook() == null - ? null - : addressBookInitializer - .getPreviousAddressBook() - .copy()); - }); + RosterUtils.setActiveRoster( + state, + RosterRetriever.buildRoster(addressBookInitializer.getCurrentAddressBook()), + RosterRetriever.getRound(state)); } // At this point the initial state must have the current address book set. If not, something is wrong. - final AddressBook addressBook = buildAddressBook(retrieveActiveOrGenesisRoster( - (State) initialState.get().getState().getSwirldState())); + final AddressBook addressBook = + RosterUtils.buildAddressBook(RosterRetriever.retrieveActiveOrGenesisRoster(state)); if (addressBook == null) { throw new IllegalStateException("The current address book of the initial state is null."); } diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SignedStateTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SignedStateTests.java index 96ff4de12905..8be6f986bd77 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SignedStateTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SignedStateTests.java @@ -32,10 +32,11 @@ import com.swirlds.common.test.fixtures.platform.TestPlatformContextBuilder; import com.swirlds.merkledb.MerkleDb; import com.swirlds.platform.crypto.SignatureVerifier; +import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.system.BasicSoftwareVersion; -import com.swirlds.platform.system.address.AddressBook; +import com.swirlds.platform.test.fixtures.addressbook.RandomRosterBuilder; import com.swirlds.platform.test.fixtures.state.RandomSignedStateGenerator; import java.time.Duration; import java.util.ArrayList; @@ -73,14 +74,15 @@ void tearDown() { * @param reserveCallback this method is called when the State is reserved * @param releaseCallback this method is called when the State is released */ - private PlatformMerkleStateRoot buildMockState(final Runnable reserveCallback, final Runnable releaseCallback) { + private PlatformMerkleStateRoot buildMockState( + final Random random, final Runnable reserveCallback, final Runnable releaseCallback) { final var real = new PlatformMerkleStateRoot( FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(version.major())); - FAKE_MERKLE_STATE_LIFECYCLES.initPlatformState(real); + FAKE_MERKLE_STATE_LIFECYCLES.initStates(real); + RosterUtils.setActiveRoster(real, RandomRosterBuilder.create(random).build(), 0L); final PlatformMerkleStateRoot state = spy(real); final PlatformStateModifier platformState = new PlatformState(); - platformState.setAddressBook(mock(AddressBook.class)); when(state.getWritablePlatformState()).thenReturn(platformState); if (reserveCallback != null) { doAnswer(invocation -> { @@ -112,6 +114,7 @@ void reservationTest() throws InterruptedException { final AtomicBoolean released = new AtomicBoolean(false); final PlatformMerkleStateRoot state = buildMockState( + random, () -> { assertFalse(reserved.get(), "should only be reserved once"); reserved.set(true); @@ -173,6 +176,7 @@ void noGarbageCollectorTest() { final Thread mainThread = Thread.currentThread(); final PlatformMerkleStateRoot state = buildMockState( + random, () -> { assertFalse(reserved.get(), "should only be reserved once"); reserved.set(true); diff --git a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomAddressBuilder.java b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomAddressBuilder.java index eba550453381..8172eb2fe2cf 100644 --- a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomAddressBuilder.java +++ b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomAddressBuilder.java @@ -82,7 +82,7 @@ public Address build() { } if (port == null) { - port = random.nextInt(0, 65535); + port = random.nextInt(1, 65535); } if (hostname == null) { diff --git a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomRosterEntryBuilder.java b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomRosterEntryBuilder.java index ea83dc3be459..afe5ce028356 100644 --- a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomRosterEntryBuilder.java +++ b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/addressbook/RandomRosterEntryBuilder.java @@ -79,7 +79,7 @@ public RosterEntry build() { } if (port == null) { - port = random.nextInt(0, 65535); + port = random.nextInt(1, 65535); } if (hostname == null) { diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/main/java/com/swirlds/platform/test/PlatformStateUtils.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/main/java/com/swirlds/platform/test/PlatformStateUtils.java index 2732a4ca36b7..25e7395f8089 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/main/java/com/swirlds/platform/test/PlatformStateUtils.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/main/java/com/swirlds/platform/test/PlatformStateUtils.java @@ -24,9 +24,6 @@ import com.swirlds.platform.state.MinimumJudgeInfo; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.system.BasicSoftwareVersion; -import com.swirlds.platform.system.address.AddressBook; -import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder; -import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder.WeightDistributionStrategy; import java.util.LinkedList; import java.util.List; import java.util.Random; @@ -46,13 +43,8 @@ public static PlatformStateModifier randomPlatformState(PlatformStateModifier pl * Generate a randomized PlatformState object. Values contained internally may be nonsensical. */ public static PlatformStateModifier randomPlatformState(final Random random, PlatformStateModifier platformState) { - final AddressBook addressBook = RandomAddressBookBuilder.create(random) - .withSize(4) - .withWeightDistributionStrategy(WeightDistributionStrategy.BALANCED) - .build(); platformState.bulkUpdate(v -> { - v.setAddressBook(addressBook); v.setLegacyRunningEventHash(randomHash(random)); v.setRound(random.nextLong()); v.setConsensusTimestamp(randomInstant(random)); From aee0358054a31cceddb90b366251c431b845c4a5 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov <23125269+OlegMazurov@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:45:39 -0800 Subject: [PATCH 09/12] perf: enable compaction during reconnects (#17129) Signed-off-by: Oleg Mazurov --- .../src/main/java/com/swirlds/merkledb/MerkleDb.java | 2 +- .../swirlds/virtualmap/internal/merkle/VirtualRootNode.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/platform-sdk/swirlds-merkledb/src/main/java/com/swirlds/merkledb/MerkleDb.java b/platform-sdk/swirlds-merkledb/src/main/java/com/swirlds/merkledb/MerkleDb.java index 3b0b2119199c..c55f121a09ca 100644 --- a/platform-sdk/swirlds-merkledb/src/main/java/com/swirlds/merkledb/MerkleDb.java +++ b/platform-sdk/swirlds-merkledb/src/main/java/com/swirlds/merkledb/MerkleDb.java @@ -398,7 +398,7 @@ public MerkleDbDataSource copyDataSource( final String label = dataSource.getTableName(); final int tableId = getNextTableId(); importDataSource(dataSource, tableId, !makeCopyPrimary, makeCopyPrimary); // import to itself == copy - return getDataSource(tableId, label, false, offlineUse); + return getDataSource(tableId, label, makeCopyPrimary, offlineUse); } private void importDataSource( diff --git a/platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/merkle/VirtualRootNode.java b/platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/merkle/VirtualRootNode.java index 060a182fafdd..94ec0d1c38ca 100644 --- a/platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/merkle/VirtualRootNode.java +++ b/platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/merkle/VirtualRootNode.java @@ -1704,9 +1704,6 @@ public void endLearnerReconnect() { originalMap = null; logger.info(RECONNECT.getMarker(), "call postInit()"); postInit(fullyReconnectedState); - // Start up data source compaction now - logger.info(RECONNECT.getMarker(), "call dataSource.enableBackgroundCompaction()"); - dataSource.enableBackgroundCompaction(); } catch (ExecutionException e) { final var message = "VirtualMap@" + getRoute() + " failed to get hash during learner reconnect"; throw new MerkleSynchronizationException(message, e); From 0679def5e84f19ac75bec401565f61bc59f10b92 Mon Sep 17 00:00:00 2001 From: Ivan Malygin Date: Fri, 20 Dec 2024 16:48:18 -0500 Subject: [PATCH 10/12] refactor: 16436 Removed `MerkleRoot` interface. (#17130) Signed-off-by: Ivan Malygin --- .../main/java/com/hedera/node/app/Hedera.java | 5 +- .../com/hedera/node/app/ServicesMain.java | 33 +++++--- .../app/state/merkle/SerializationTest.java | 4 +- .../block/StateChangesValidator.java | 19 ++++- .../platform/ReconnectStateLoader.java | 7 +- .../swirlds/platform/StateInitializer.java | 8 +- .../com/swirlds/platform/SwirldsPlatform.java | 8 +- .../cli/GenesisPlatformStateCommand.java | 2 +- .../cli/ValidateAddressBookStateCommand.java | 3 +- .../DefaultTransactionHandler.java | 6 +- .../platform/reconnect/ReconnectHelper.java | 8 +- .../platform/reconnect/ReconnectLearner.java | 10 +-- .../reconnect/ReconnectLearnerFactory.java | 6 +- .../platform/reconnect/ReconnectUtils.java | 6 +- .../recovery/EventRecoveryWorkflow.java | 10 +-- .../state/BirthRoundStateMigration.java | 2 +- .../swirlds/platform/state/MerkleRoot.java | 76 ------------------- .../state/PlatformMerkleStateRoot.java | 33 ++++---- .../platform/state/SwirldStateManager.java | 34 ++++----- .../state/SwirldStateManagerUtils.java | 10 +-- .../platform/state/TransactionHandler.java | 6 +- .../state/address/AddressBookInitializer.java | 21 ++++- .../state/hashlogger/DefaultHashLogger.java | 6 +- .../platform/state/signed/SignedState.java | 16 ++-- .../state/signed/StartupStateUtils.java | 17 ++--- .../state/snapshot/SavedStateMetadata.java | 6 +- .../state/snapshot/SignedStateFileReader.java | 6 +- .../state/snapshot/SignedStateFileWriter.java | 13 ++-- .../swirlds/platform/system/SwirldMain.java | 6 +- .../system/address/AddressBookUtils.java | 2 +- .../swirlds/platform/util/BootstrapUtils.java | 6 +- .../platform/AddressBookInitializerTest.java | 37 +++++---- .../platform/SavedStateMetadataTests.java | 13 +--- .../SignedStateFileReadWriteTest.java | 6 +- .../consensus/RoundCalculationUtilsTest.java | 6 +- .../DefaultTransactionHandlerTests.java | 5 +- .../TransactionHandlerTester.java | 8 +- .../reconnect/ReconnectProtocolTests.java | 6 +- .../platform/reconnect/ReconnectTest.java | 4 +- .../platform/state/StateRegistryTests.java | 10 +-- .../state/SwirldStateManagerTests.java | 6 +- .../state/SwirldStateManagerUtilsTests.java | 5 +- .../state/hashlogger/HashLoggerTest.java | 8 +- .../StateHashedNotificationTest.java | 4 +- .../platform/turtle/runner/TurtleNode.java | 4 +- .../turtle/runner/TurtleTestingToolState.java | 2 +- .../wiring/SignedStateReserverTest.java | 6 +- .../fixtures/state/BlockingSwirldState.java | 7 +- .../state/RandomSignedStateGenerator.java | 7 +- .../com/swirlds/platform/test/StateTest.java | 9 +-- .../com/swirlds/platform/test/StateTests.java | 6 +- .../platform/test/state/IssDetectorTests.java | 4 +- 52 files changed, 250 insertions(+), 308 deletions(-) delete mode 100644 platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleRoot.java diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java index ac8a769a966d..0adf358ddf9b 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -133,7 +133,6 @@ import com.swirlds.platform.listeners.ReconnectCompleteListener; import com.swirlds.platform.listeners.ReconnectCompleteNotification; import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener; -import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.service.PlatformStateService; import com.swirlds.platform.state.service.ReadablePlatformStateStore; @@ -505,7 +504,7 @@ public SoftwareVersion getSoftwareVersion() { */ @Override @NonNull - public MerkleRoot newMerkleStateRoot() { + public PlatformMerkleStateRoot newMerkleStateRoot() { return stateRootSupplier.get(); } diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/ServicesMain.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/ServicesMain.java index e4269a149bf5..05b2b2326812 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/ServicesMain.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/ServicesMain.java @@ -1,4 +1,19 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.hedera.node.app; import static com.swirlds.common.io.utility.FileUtils.getAbsolutePath; @@ -60,7 +75,6 @@ import com.swirlds.platform.crypto.CryptoStatic; import com.swirlds.platform.roster.RosterHistory; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.address.AddressBookInitializer; import com.swirlds.platform.state.service.ReadableRosterStore; @@ -130,7 +144,7 @@ public void init(@NonNull final Platform platform, @NonNull final NodeId nodeId) * {@inheritDoc} */ @Override - public @NonNull MerkleRoot newMerkleStateRoot() { + public @NonNull PlatformMerkleStateRoot newMerkleStateRoot() { return hederaOrThrow().newMerkleStateRoot(); } @@ -254,7 +268,7 @@ public static void main(final String... args) throws Exception { version, () -> { isGenesis.set(true); - final var genesisState = (PlatformMerkleStateRoot) hedera.newMerkleStateRoot(); + final var genesisState = hedera.newMerkleStateRoot(); final var genesisNetwork = DiskStartupNetworks.fromLegacyAddressBook(diskAddressBook); hedera.initializeStatesApi( genesisState, @@ -271,17 +285,12 @@ public static void main(final String... args) throws Exception { final var initialState = reservedState.state(); if (!isGenesis.get()) { hedera.initializeStatesApi( - (PlatformMerkleStateRoot) initialState.get().getState().getSwirldState(), - metrics, - InitTrigger.RESTART, - null, - platformConfig, - diskAddressBook); + initialState.get().getState(), metrics, InitTrigger.RESTART, null, platformConfig, diskAddressBook); } hedera.setInitialStateHash(reservedState.hash()); // --- Now build the platform and start it --- - final var stateRoot = (PlatformMerkleStateRoot) initialState.get().getState(); + final var stateRoot = initialState.get().getState(); final RosterHistory rosterHistory; if (hedera.isRosterLifecycleEnabled()) { final var rosterStore = new ReadableStoreFactory(stateRoot).getStore(ReadableRosterStore.class); @@ -461,7 +470,7 @@ private static HashedReservedSignedState loadInitialState( @NonNull final Configuration configuration, @NonNull final RecycleBin recycleBin, @NonNull final SoftwareVersion softwareVersion, - @NonNull final Supplier stateRootSupplier, + @NonNull final Supplier stateRootSupplier, @NonNull final String mainClassName, @NonNull final String swirldName, @NonNull final NodeId selfId) { diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/state/merkle/SerializationTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/state/merkle/SerializationTest.java index e0576d1b7c2e..9194fff928ea 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/state/merkle/SerializationTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/state/merkle/SerializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -326,7 +326,7 @@ private PlatformMerkleStateRoot createMerkleHederaState(Schema schemaV1) { final SignedState randomState = new RandomSignedStateGenerator().setRound(1).build(); - final var originalTree = (PlatformMerkleStateRoot) randomState.getState(); + final var originalTree = randomState.getState(); final var originalRegistry = new MerkleSchemaRegistry(registry, FIRST_SERVICE, DEFAULT_CONFIG, new SchemaApplications()); originalRegistry.register(schemaV1); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/support/validators/block/StateChangesValidator.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/support/validators/block/StateChangesValidator.java index b9250731dfaa..6bfd3b0ba426 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/support/validators/block/StateChangesValidator.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/support/validators/block/StateChangesValidator.java @@ -1,4 +1,19 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.hedera.services.bdd.junit.support.validators.block; import static com.hedera.node.app.blocks.impl.BlockImplUtils.combine; @@ -191,7 +206,7 @@ public StateChangesValidator( final var addressBook = loadLegacyBookWithGeneratedCerts(pathToAddressBook); final var metrics = new NoOpMetrics(); final var hedera = ServicesMain.newHedera(NodeId.of(0L), metrics); - this.state = (PlatformMerkleStateRoot) hedera.newMerkleStateRoot(); + this.state = hedera.newMerkleStateRoot(); final var platformConfig = ServicesMain.buildPlatformConfig(); hedera.initializeStatesApi( state, diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/ReconnectStateLoader.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/ReconnectStateLoader.java index b5b4448f4470..944ef5e116b6 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/ReconnectStateLoader.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/ReconnectStateLoader.java @@ -39,7 +39,6 @@ import com.swirlds.platform.system.status.actions.ReconnectCompleteAction; import com.swirlds.platform.wiring.PlatformWiring; import com.swirlds.state.State; -import com.swirlds.state.merkle.MerkleStateRoot; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Objects; import org.apache.logging.log4j.LogManager; @@ -118,7 +117,7 @@ public void loadReconnectState(@NonNull final SignedState signedState) { } // Before attempting to load the state, verify that the platform roster matches the state roster. - final State state = (MerkleStateRoot) signedState.getState().getSwirldState(); + final State state = signedState.getState(); final Roster stateRoster = RosterRetriever.retrieveActiveOrGenesisRoster(state); if (!roster.equals(stateRoster)) { throw new IllegalStateException("Current roster and state-based roster do not contain the same nodes " @@ -170,9 +169,7 @@ public void loadReconnectState(@NonNull final SignedState signedState) { .getNotifierWiring() .getInputWire(AppNotifier::sendReconnectCompleteNotification) .put(new ReconnectCompleteNotification( - signedState.getRound(), - signedState.getConsensusTimestamp(), - signedState.getState().getSwirldState())); + signedState.getRound(), signedState.getConsensusTimestamp(), signedState.getState())); } catch (final RuntimeException e) { logger.debug(RECONNECT.getMarker(), "`loadReconnectState` : FAILED, reason: {}", e.getMessage()); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/StateInitializer.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/StateInitializer.java index 743639e48fd4..8db8764cbaeb 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/StateInitializer.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/StateInitializer.java @@ -25,7 +25,7 @@ import com.swirlds.common.context.PlatformContext; import com.swirlds.common.merkle.crypto.MerkleCryptoFactory; import com.swirlds.platform.config.StateConfig; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.system.InitTrigger; import com.swirlds.platform.system.Platform; @@ -70,18 +70,18 @@ public static void initializeState( trigger = RESTART; } - final MerkleRoot initialState = signedState.getState(); + final PlatformMerkleStateRoot initialState = signedState.getState(); // Although the state from disk / genesis state is initially hashed, we are actually dealing with a copy // of that state here. That copy should have caused the hash to be cleared. if (initialState.getHash() != null) { throw new IllegalStateException("Expected initial state to be unhashed"); } - if (initialState.getSwirldState().getHash() != null) { + if (initialState.getHash() != null) { throw new IllegalStateException("Expected initial swirld state to be unhashed"); } - initialState.getSwirldState().init(platform, trigger, previousSoftwareVersion); + initialState.init(platform, trigger, previousSoftwareVersion); abortAndThrowIfInterrupted( () -> { diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java index 8ed09fafd540..3363353ec5e0 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,7 @@ import com.swirlds.platform.pool.TransactionPoolNexus; import com.swirlds.platform.publisher.DefaultPlatformPublisher; import com.swirlds.platform.publisher.PlatformPublisher; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.SwirldStateManager; import com.swirlds.platform.state.nexus.DefaultLatestCompleteStateNexus; @@ -365,7 +365,7 @@ private BirthRoundMigrationShim buildBirthRoundMigrationShim( return null; } - final MerkleRoot state = initialState.getState(); + final PlatformMerkleStateRoot state = initialState.getState(); final PlatformStateAccessor platformState = state.getReadablePlatformState(); return new DefaultBirthRoundMigrationShim( @@ -515,6 +515,6 @@ public AutoCloseableWrapper getLatestImmutableState(@ final ReservedSignedState wrapper = latestImmutableStateNexus.getState(reason); return wrapper == null ? AutoCloseableWrapper.empty() - : new AutoCloseableWrapper<>((T) wrapper.get().getState().getSwirldState(), wrapper::close); + : new AutoCloseableWrapper<>((T) wrapper.get().getState(), wrapper::close); } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java index 4606b861ed51..88566146dc68 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/GenesisPlatformStateCommand.java @@ -95,7 +95,7 @@ public Integer call() throws IOException, ExecutionException, InterruptedExcepti }); { System.out.printf("Resetting the RosterService state %n"); - final State state = (State) reservedSignedState.get().getState().getSwirldState(); + final State state = reservedSignedState.get().getState(); final WritableStates writableStates = state.getWritableStates(RosterStateId.NAME); final WritableRosterStore writableRosterStore = new WritableRosterStore(writableStates); writableRosterStore.resetRosters(); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/ValidateAddressBookStateCommand.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/ValidateAddressBookStateCommand.java index 7b4b53bfd771..43be509a695d 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/ValidateAddressBookStateCommand.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/ValidateAddressBookStateCommand.java @@ -31,7 +31,6 @@ import com.swirlds.platform.system.address.AddressBookUtils; import com.swirlds.platform.system.address.AddressBookValidator; import com.swirlds.platform.util.BootstrapUtils; -import com.swirlds.state.State; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -81,7 +80,7 @@ public Integer call() throws IOException, ExecutionException, InterruptedExcepti try (final ReservedSignedState reservedSignedState = deserializedSignedState.reservedSignedState()) { System.out.printf("Extracting the state address book for comparison %n"); stateAddressBook = RosterUtils.buildAddressBook(RosterRetriever.retrieveActiveOrGenesisRoster( - (State) reservedSignedState.get().getState().getSwirldState())); + reservedSignedState.get().getState())); } System.out.printf("Validating address book %n"); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionHandler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionHandler.java index 12e36f6ae397..c01d2b661f9c 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionHandler.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/eventhandling/DefaultTransactionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ import com.swirlds.platform.event.PlatformEvent; import com.swirlds.platform.internal.ConsensusRound; import com.swirlds.platform.metrics.RoundHandlingMetrics; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.state.SwirldStateManager; import com.swirlds.platform.state.signed.ReservedSignedState; @@ -282,7 +282,7 @@ private StateAndRound createSignedState( swirldStateManager.sealConsensusRound(consensusRound); handlerMetrics.setPhase(GETTING_STATE_TO_SIGN); - final MerkleRoot immutableStateCons = swirldStateManager.getStateForSigning(); + final PlatformMerkleStateRoot immutableStateCons = swirldStateManager.getStateForSigning(); handlerMetrics.setPhase(CREATING_SIGNED_STATE); final SignedState signedState = new SignedState( diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectHelper.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectHelper.java index 2268e509265a..5fefc4912583 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectHelper.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import com.swirlds.logging.legacy.payload.ReconnectStartPayload; import com.swirlds.platform.config.StateConfig; import com.swirlds.platform.network.Connection; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.state.signed.SignedStateValidator; @@ -51,7 +51,7 @@ public class ReconnectHelper { /** clears all data that is no longer needed since we fell behind */ private final Clearable clearAll; /** supplier of the initial signed state against which to perform a delta based reconnect */ - private final Supplier workingStateSupplier; + private final Supplier workingStateSupplier; /** provides the latest signed state round for which we have a supermajority of signatures */ private final LongSupplier lastCompleteRoundSupplier; /** throttles reconnect learner attempts */ @@ -66,7 +66,7 @@ public class ReconnectHelper { public ReconnectHelper( final Runnable pauseGossip, final Clearable clearAll, - final Supplier workingStateSupplier, + final Supplier workingStateSupplier, final LongSupplier lastCompleteRoundSupplier, final ReconnectLearnerThrottle reconnectLearnerThrottle, final Consumer loadSignedState, diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearner.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearner.java index c92a02a0f808..67a2b6c4459b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearner.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearner.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import com.swirlds.platform.crypto.CryptoStatic; import com.swirlds.platform.metrics.ReconnectMetrics; import com.swirlds.platform.network.Connection; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SigSet; import com.swirlds.platform.state.signed.SignedState; @@ -57,7 +57,7 @@ public class ReconnectLearner { private final Connection connection; private final Roster roster; - private final MerkleRoot currentState; + private final PlatformMerkleStateRoot currentState; private final Duration reconnectSocketTimeout; private final ReconnectMetrics statistics; private final SignedStateValidationData stateValidationData; @@ -89,7 +89,7 @@ public ReconnectLearner( @NonNull final ThreadManager threadManager, @NonNull final Connection connection, @NonNull final Roster roster, - @NonNull final MerkleRoot currentState, + @NonNull final PlatformMerkleStateRoot currentState, @NonNull final Duration reconnectSocketTimeout, @NonNull final ReconnectMetrics statistics) { @@ -204,7 +204,7 @@ private ReservedSignedState reconnect() throws InterruptedException { platformContext.getMetrics()); synchronizer.synchronize(); - final MerkleRoot state = (MerkleRoot) synchronizer.getRoot(); + final PlatformMerkleStateRoot state = (PlatformMerkleStateRoot) synchronizer.getRoot(); final SignedState newSignedState = new SignedState( platformContext.getConfiguration(), CryptoStatic::verifySignature, diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearnerFactory.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearnerFactory.java index ea1bb9342d0a..47fe3b7bfb34 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearnerFactory.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectLearnerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import com.swirlds.common.threading.manager.ThreadManager; import com.swirlds.platform.metrics.ReconnectMetrics; import com.swirlds.platform.network.Connection; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import edu.umd.cs.findbugs.annotations.NonNull; import java.time.Duration; import java.util.Objects; @@ -63,7 +63,7 @@ public ReconnectLearnerFactory( * @param workingState the state to use to perform a delta based reconnect * @return a new instance */ - public ReconnectLearner create(final Connection conn, final MerkleRoot workingState) { + public ReconnectLearner create(final Connection conn, final PlatformMerkleStateRoot workingState) { return new ReconnectLearner( platformContext, threadManager, conn, roster, workingState, reconnectSocketTimeout, statistics); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectUtils.java index 4a02423aca51..7a187fd6976f 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/reconnect/ReconnectUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import com.swirlds.common.merkle.crypto.MerkleCryptoFactory; import com.swirlds.logging.legacy.payload.ReconnectFailurePayload; import com.swirlds.platform.network.Connection; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; import java.util.concurrent.ExecutionException; @@ -60,7 +60,7 @@ static void endReconnectHandshake(@NonNull final Connection connection) throws I /** * Hash the working state to prepare for reconnect */ - static void hashStateForReconnect(final MerkleRoot workingState) { + static void hashStateForReconnect(final PlatformMerkleStateRoot workingState) { try { MerkleCryptoFactory.getInstance().digestTreeAsync(workingState).get(); } catch (final ExecutionException e) { diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/recovery/EventRecoveryWorkflow.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/recovery/EventRecoveryWorkflow.java index 5acb363bb1fe..a9e67fc85656 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/recovery/EventRecoveryWorkflow.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/recovery/EventRecoveryWorkflow.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,7 +52,7 @@ import com.swirlds.platform.recovery.internal.RecoveredState; import com.swirlds.platform.recovery.internal.RecoveryPlatform; import com.swirlds.platform.recovery.internal.StreamedRound; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.state.signed.ReservedSignedState; @@ -185,7 +185,7 @@ public static void recoverState( resultingStateDirectory); // Make one more copy to force the state in recoveredState to be immutable. - final MerkleRoot mutableStateCopy = + final PlatformMerkleStateRoot mutableStateCopy = recoveredState.state().get().getState().copy(); SignedStateFileWriter.writeSignedStateFilesToDirectory( @@ -376,7 +376,7 @@ private static ReservedSignedState handleNextRound( final Instant currentRoundTimestamp = getRoundTimestamp(round); previousState.get().getState().throwIfImmutable(); - final MerkleRoot newState = previousState.get().getState().copy(); + final PlatformMerkleStateRoot newState = previousState.get().getState().copy(); final PlatformEvent lastEvent = ((CesEvent) getLastEvent(round)).getPlatformEvent(); new DefaultEventHasher().hashEvent(lastEvent); @@ -397,7 +397,7 @@ private static ReservedSignedState handleNextRound( applyTransactions( previousState.get().getSwirldState().cast(), - newState.getSwirldState().cast(), + newState.cast(), newState.getWritablePlatformState(), round); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/BirthRoundStateMigration.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/BirthRoundStateMigration.java index 925a96cb6e25..a1f5772cedf7 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/BirthRoundStateMigration.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/BirthRoundStateMigration.java @@ -63,7 +63,7 @@ public static void modifyStateForBirthRoundMigration( return; } - final MerkleRoot state = initialState.getState(); + final PlatformMerkleStateRoot state = initialState.getState(); final PlatformStateModifier writablePlatformState = state.getWritablePlatformState(); final boolean alreadyMigrated = writablePlatformState.getFirstVersionInBirthRoundMode() != null; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleRoot.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleRoot.java deleted file mode 100644 index a3cf03cf860c..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleRoot.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.state; - -import com.swirlds.common.merkle.MerkleInternal; -import com.swirlds.platform.system.SwirldState; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.file.Path; - -/** - * This interface represents the root node of the Merkle tree. - */ -public interface MerkleRoot extends MerkleInternal { - /** - * Get the application state. - * - * @return the application state - */ - @NonNull - SwirldState getSwirldState(); - /** - * Get readable platform state. - * Works on both - mutable and immutable {@link MerkleRoot} and, therefore, this method should be preferred. - * - * @return immutable platform state - */ - @NonNull - PlatformStateAccessor getReadablePlatformState(); - - /** - * Get writable platform state. Works only on mutable {@link MerkleRoot}. - * Call this method only if you need to modify the platform state. - * - * @return mutable platform state - */ - @NonNull - PlatformStateModifier getWritablePlatformState(); - - /** - * Set the platform state. - * - * @param platformState the platform state - */ - void updatePlatformState(@NonNull final PlatformStateModifier platformState); - - /** - * Generate a string that describes this state. - * - * @param hashDepth the depth of the tree to visit and print - */ - @NonNull - String getInfoString(final int hashDepth); - - /** {@inheritDoc} */ - @NonNull - MerkleRoot copy(); - - /** Creates a snapshots for the state. The state has to be hashed and immutable before calling this method. - * @param targetPath The path to save the snapshot. - */ - void createSnapshot(final @NonNull Path targetPath); -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java index 7fff84b01b46..e4cb5cd77cc1 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/PlatformMerkleStateRoot.java @@ -70,8 +70,7 @@ * consider nesting service nodes in a MerkleMap, or some other such approach to get a binary tree. */ @ConstructableIgnored -public class PlatformMerkleStateRoot extends MerkleStateRoot - implements SwirldState, MerkleRoot { +public class PlatformMerkleStateRoot extends MerkleStateRoot implements SwirldState { private static final long CLASS_ID = 0x8e300b0dfdafbb1aL; /** @@ -157,6 +156,9 @@ public void handleConsensusRound( lifecycles.onHandleConsensusRound(round, this); } + /** + * {@inheritDoc} + */ @Override public void sealConsensusRound(@NonNull final Round round) { requireNonNull(round); @@ -183,10 +185,12 @@ public Function getVersionFactory() { } /** - * {@inheritDoc} + * Get writable platform state. Works only on mutable {@link PlatformMerkleStateRoot}. + * Call this method only if you need to modify the platform state. + * + * @return mutable platform state */ @NonNull - @Override public PlatformStateModifier getWritablePlatformState() { if (isImmutable()) { throw new IllegalStateException("Cannot get writable platform state when state is immutable"); @@ -199,16 +203,17 @@ public PlatformStateModifier getWritablePlatformState() { * * @param accessor a source of values */ - @Override public void updatePlatformState(@NonNull final PlatformStateModifier accessor) { writablePlatformStateStore().setAllFrom(accessor); } /** - * {@inheritDoc} + * Get readable platform state. + * Works on both - mutable and immutable {@link PlatformMerkleStateRoot} and, therefore, this method should be preferred. + * + * @return immutable platform state */ @NonNull - @Override public PlatformStateAccessor getReadablePlatformState() { return getServices().isEmpty() ? new SnapshotPlatformStateAccessor(getPlatformState(), versionFactory) @@ -240,25 +245,17 @@ public long getCurrentRound() { : getPlatformState().consensusSnapshot().round(); } - /** - * {@inheritDoc} - */ - @NonNull - @Override - public SwirldState getSwirldState() { - return this; - } - @Override public long getClassId() { return CLASS_ID; } /** - * {@inheritDoc} + * Generate a string that describes this state. + * + * @param hashDepth the depth of the tree to visit and print */ @NonNull - @Override public String getInfoString(final int hashDepth) { return createInfoString(hashDepth, getReadablePlatformState(), getHash(), this); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java index 06a9d89e1456..7630af120a77 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,12 +53,12 @@ public class SwirldStateManager implements FreezePeriodChecker { /** * reference to the state that reflects all known consensus transactions */ - private final AtomicReference stateRef = new AtomicReference<>(); + private final AtomicReference stateRef = new AtomicReference<>(); /** * The most recent immutable state. No value until the first fast copy is created. */ - private final AtomicReference latestImmutableState = new AtomicReference<>(); + private final AtomicReference latestImmutableState = new AtomicReference<>(); /** * Handle transactions by applying them to a state @@ -107,7 +107,7 @@ public SwirldStateManager( * * @param state the initial state */ - public void setInitialState(@NonNull final MerkleRoot state) { + public void setInitialState(@NonNull final PlatformMerkleStateRoot state) { Objects.requireNonNull(state); state.throwIfDestroyed("state must not be destroyed"); state.throwIfImmutable("state must be mutable"); @@ -128,7 +128,7 @@ public void setInitialState(@NonNull final MerkleRoot state) { * @param round the round to handle */ public List> handleConsensusRound(final ConsensusRound round) { - final MerkleRoot state = stateRef.get(); + final PlatformMerkleStateRoot state = stateRef.get(); uptimeTracker.handleRound(round); transactionHandler.handleRound(round, state); @@ -144,15 +144,15 @@ public List> handleConsensusR */ public void sealConsensusRound(@NonNull final Round round) { Objects.requireNonNull(round); - final MerkleRoot state = stateRef.get(); - state.getSwirldState().sealConsensusRound(round); + final PlatformMerkleStateRoot state = stateRef.get(); + state.sealConsensusRound(round); } /** * Returns the consensus state. The consensus state could become immutable at any time. Modifications must not be * made to the returned state. */ - public MerkleRoot getConsensusState() { + public PlatformMerkleStateRoot getConsensusState() { return stateRef.get(); } @@ -176,7 +176,7 @@ public void savedStateInFreezePeriod() { * @param signedState the signed state to load */ public void loadFromSignedState(@NonNull final SignedState signedState) { - final MerkleRoot state = signedState.getState(); + final PlatformMerkleStateRoot state = signedState.getState(); state.throwIfDestroyed("state must not be destroyed"); state.throwIfImmutable("state must be mutable"); @@ -184,8 +184,8 @@ public void loadFromSignedState(@NonNull final SignedState signedState) { fastCopyAndUpdateRefs(state); } - private void fastCopyAndUpdateRefs(final MerkleRoot state) { - final MerkleRoot consState = fastCopy(state, stats, softwareVersion); + private void fastCopyAndUpdateRefs(final PlatformMerkleStateRoot state) { + final PlatformMerkleStateRoot consState = fastCopy(state, stats, softwareVersion); // Set latest immutable first to prevent the newly immutable state from being deleted between setting the // stateRef and the latestImmutableState @@ -198,8 +198,8 @@ private void fastCopyAndUpdateRefs(final MerkleRoot state) { * * @param state the new mutable state */ - private void setState(final MerkleRoot state) { - final MerkleRoot currVal = stateRef.get(); + private void setState(final PlatformMerkleStateRoot state) { + final PlatformMerkleStateRoot currVal = stateRef.get(); if (currVal != null) { currVal.release(); } @@ -208,8 +208,8 @@ private void setState(final MerkleRoot state) { stateRef.set(state); } - private void setLatestImmutableState(final MerkleRoot immutableState) { - final MerkleRoot currVal = latestImmutableState.get(); + private void setLatestImmutableState(final PlatformMerkleStateRoot immutableState) { + final PlatformMerkleStateRoot currVal = latestImmutableState.get(); if (currVal != null) { currVal.release(); } @@ -237,9 +237,9 @@ public boolean isInFreezePeriod(final Instant timestamp) { * event handling may or may not be blocked depending on the implementation.

* * @return a copy of the state to use for the next signed state - * @see MerkleRoot#copy() + * @see PlatformMerkleStateRoot#copy() */ - public MerkleRoot getStateForSigning() { + public PlatformMerkleStateRoot getStateForSigning() { fastCopyAndUpdateRefs(stateRef.get()); return latestImmutableState.get(); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManagerUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManagerUtils.java index bb42bcd48af6..efbff35b36a4 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManagerUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/SwirldStateManagerUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,15 +34,15 @@ public final class SwirldStateManagerUtils { private SwirldStateManagerUtils() {} /** - * Performs a fast copy on a {@link MerkleRoot}. The {@code state} must not be modified during execution of this method. + * Performs a fast copy on a {@link PlatformMerkleStateRoot}. The {@code state} must not be modified during execution of this method. * * @param state the state object to fast copy * @param stats object to record stats in * @param softwareVersion the current software version * @return the newly created state copy */ - public static MerkleRoot fastCopy( - @NonNull final MerkleRoot state, + public static PlatformMerkleStateRoot fastCopy( + @NonNull final PlatformMerkleStateRoot state, @NonNull final SwirldStateMetrics stats, @NonNull final SoftwareVersion softwareVersion) { @@ -51,7 +51,7 @@ public static MerkleRoot fastCopy( final long copyStart = System.nanoTime(); // Create a fast copy - final MerkleRoot copy = state.copy(); + final PlatformMerkleStateRoot copy = state.copy(); final var platformState = copy.getWritablePlatformState(); platformState.setCreationSoftwareVersion(softwareVersion); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/TransactionHandler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/TransactionHandler.java index 59f7c3374cff..9f40a4671f86 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/TransactionHandler.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/TransactionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,12 +52,12 @@ public TransactionHandler(final NodeId selfId, final SwirldStateMetrics stats) { * @param state * the state to apply {@code round} to */ - public void handleRound(final ConsensusRound round, final MerkleRoot state) { + public void handleRound(final ConsensusRound round, final PlatformMerkleStateRoot state) { try { final Instant timeOfHandle = Instant.now(); final long startTime = System.nanoTime(); - state.getSwirldState().handleConsensusRound(round, state.getWritablePlatformState(), NO_OP_CONSUMER); + state.handleConsensusRound(round, state.getWritablePlatformState(), NO_OP_CONSUMER); final double secondsElapsed = (System.nanoTime() - startTime) * NANOSECONDS_TO_SECONDS; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/address/AddressBookInitializer.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/address/AddressBookInitializer.java index 15cc9a257794..9e174784b375 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/address/AddressBookInitializer.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/address/AddressBookInitializer.java @@ -1,4 +1,19 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.swirlds.platform.state.address; import static com.swirlds.logging.legacy.LogMarker.EXCEPTION; @@ -14,7 +29,6 @@ import com.swirlds.platform.system.address.Address; import com.swirlds.platform.system.address.AddressBook; import com.swirlds.platform.system.address.AddressBookValidator; -import com.swirlds.state.State; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.io.File; @@ -118,8 +132,7 @@ public AddressBookInitializer( platformContext.getConfiguration().getConfigData(AddressBookConfig.class); this.initialState = Objects.requireNonNull(initialState, "The initialState must not be null."); - final var book = buildAddressBook( - retrieveActiveOrGenesisRoster((State) initialState.getState().getSwirldState())); + final var book = buildAddressBook(retrieveActiveOrGenesisRoster(initialState.getState())); this.stateAddressBook = (book == null || book.getSize() == 0) ? null : book; if (stateAddressBook == null && !initialState.isGenesisState()) { throw new IllegalStateException("Only genesis states can have null address books."); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/hashlogger/DefaultHashLogger.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/hashlogger/DefaultHashLogger.java index 27fef2693beb..5c5a0a8b6c40 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/hashlogger/DefaultHashLogger.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/hashlogger/DefaultHashLogger.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import com.swirlds.common.context.PlatformContext; import com.swirlds.platform.config.StateConfig; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; import edu.umd.cs.findbugs.annotations.NonNull; @@ -107,7 +107,7 @@ public void logHashes(@NonNull final ReservedSignedState reservedState) { */ @NonNull private Message generateLogMessage(@NonNull final SignedState signedState) { - final MerkleRoot state = signedState.getState(); + final PlatformMerkleStateRoot state = signedState.getState(); final String platformInfo = state.getInfoString(depth); return MESSAGE_FACTORY.newMessage( diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java index 4b2f9e462f96..0f1da7772bf9 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,12 +39,11 @@ import com.swirlds.platform.crypto.SignatureVerifier; import com.swirlds.platform.roster.RosterRetriever; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.SignedStateHistory.SignedStateAction; import com.swirlds.platform.state.snapshot.StateToDiskReason; import com.swirlds.platform.system.SwirldState; import com.swirlds.platform.system.address.Address; -import com.swirlds.state.merkle.MerkleStateRoot; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.security.cert.X509Certificate; @@ -106,7 +105,7 @@ public class SignedState implements SignedStateInfo { /** * The root of the merkle state. */ - private final MerkleRoot state; + private final PlatformMerkleStateRoot state; /** * The timestamp of when this object was created. @@ -188,7 +187,7 @@ public class SignedState implements SignedStateInfo { public SignedState( @NonNull final Configuration configuration, @NonNull final SignatureVerifier signatureVerifier, - @NonNull final MerkleRoot state, + @NonNull final PlatformMerkleStateRoot state, @NonNull final String reason, final boolean freezeState, final boolean deleteOnBackgroundThread, @@ -270,8 +269,7 @@ public void setSigSet(@NonNull final SigSet sigSet) { Ideally the roster would be captured in the constructor but due to the mutable underlying state, the roster can change from underneath us. Therefore, the roster must be regenerated on each access. */ - final Roster roster = RosterRetriever.retrieveActiveOrGenesisRoster( - (MerkleStateRoot) getState().getSwirldState()); + final Roster roster = RosterRetriever.retrieveActiveOrGenesisRoster(state); return requireNonNull(roster, "Roster stored in signed state is null (this should never happen)"); } @@ -281,7 +279,7 @@ public void setSigSet(@NonNull final SigSet sigSet) { * * @return the state contained in the signed state */ - public @NonNull MerkleRoot getState() { + public @NonNull PlatformMerkleStateRoot getState() { return state; } @@ -484,7 +482,7 @@ public String toString() { * @return the root node of the application's state. */ public @NonNull SwirldState getSwirldState() { - return state.getSwirldState(); + return state; } /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java index 60c29102456f..f6414825dac2 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/StartupStateUtils.java @@ -37,7 +37,7 @@ import com.swirlds.platform.internal.SignedStateLoadingException; import com.swirlds.platform.roster.RosterRetriever; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.state.snapshot.DeserializedSignedState; import com.swirlds.platform.state.snapshot.SavedStateInfo; @@ -85,7 +85,7 @@ public static HashedReservedSignedState getInitialState( @NonNull final Configuration configuration, @NonNull final RecycleBin recycleBin, @NonNull final SoftwareVersion softwareVersion, - @NonNull final Supplier genesisStateBuilder, + @NonNull final Supplier genesisStateBuilder, @NonNull final String mainClassName, @NonNull final String swirldName, @NonNull final NodeId selfId, @@ -172,7 +172,7 @@ public static ReservedSignedState loadStateFile( requireNonNull(configuration); requireNonNull(initialSignedState); - final MerkleRoot stateCopy = initialSignedState.getState().copy(); + final PlatformMerkleStateRoot stateCopy = initialSignedState.getState().copy(); final SignedState signedStateCopy = new SignedState( configuration, CryptoStatic::verifySignature, @@ -266,7 +266,7 @@ private static ReservedSignedState loadStateFile( } } - final MerkleRoot state = + final PlatformMerkleStateRoot state = deserializedSignedState.reservedSignedState().get().getState(); final Hash oldHash = deserializedSignedState.originalHash(); @@ -326,15 +326,10 @@ private static ReservedSignedState buildGenesisState( @NonNull final Configuration configuration, @NonNull final AddressBook addressBook, @NonNull final SoftwareVersion appVersion, - @NonNull final MerkleRoot stateRoot) { + @NonNull final PlatformMerkleStateRoot stateRoot) { if (!configuration.getConfigData(AddressBookConfig.class).useRosterLifecycle()) { - initGenesisState( - configuration, - (State) stateRoot.getSwirldState(), - stateRoot.getWritablePlatformState(), - addressBook, - appVersion); + initGenesisState(configuration, stateRoot, stateRoot.getWritablePlatformState(), addressBook, appVersion); } final SignedState signedState = new SignedState( diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SavedStateMetadata.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SavedStateMetadata.java index f684241e94a2..5325751bd92f 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SavedStateMetadata.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SavedStateMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ import com.swirlds.platform.roster.RosterUtils; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.signed.SignedState; -import com.swirlds.state.State; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.io.BufferedReader; @@ -172,8 +171,7 @@ public static SavedStateMetadata create( Objects.requireNonNull(now, "now must not be null"); final PlatformStateAccessor platformState = signedState.getState().getReadablePlatformState(); - final Roster roster = RosterRetriever.retrieveActiveOrGenesisRoster( - (State) signedState.getState().getSwirldState()); + final Roster roster = RosterRetriever.retrieveActiveOrGenesisRoster(signedState.getState()); final List signingNodes = signedState.getSigSet().getSigningNodes(); Collections.sort(signingNodes); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileReader.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileReader.java index 322e36c5a94a..e98b289cea32 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileReader.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import com.swirlds.common.platform.NodeId; import com.swirlds.config.api.Configuration; import com.swirlds.platform.crypto.CryptoStatic; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.service.PlatformStateService; import com.swirlds.platform.state.service.schemas.V0540PlatformStateSchema; import com.swirlds.platform.state.service.schemas.V0540RosterBaseSchema; @@ -106,7 +106,7 @@ public static List getSavedStateFiles( final SignedState newSignedState = new SignedState( configuration, CryptoStatic::verifySignature, - (MerkleRoot) data.stateRoot(), + (PlatformMerkleStateRoot) data.stateRoot(), "SignedStateFileReader.readStateFile()", false, false, diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileWriter.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileWriter.java index 87407dc7d3f8..972c87c2bdbf 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileWriter.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/snapshot/SignedStateFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,11 +35,10 @@ import com.swirlds.platform.config.StateConfig; import com.swirlds.platform.recovery.emergencyfile.EmergencyRecoveryFile; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.SigSet; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.system.address.AddressBook; -import com.swirlds.state.merkle.MerkleStateRoot; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.io.BufferedWriter; @@ -70,7 +69,7 @@ private SignedStateFileWriter() {} * @param directory the directory where the state is being written */ public static void writeHashInfoFile( - @NonNull final PlatformContext platformContext, final Path directory, final MerkleRoot state) + @NonNull final PlatformContext platformContext, final Path directory, final PlatformMerkleStateRoot state) throws IOException { final StateConfig stateConfig = platformContext.getConfiguration().getConfigData(StateConfig.class); final String platformInfo = state.getInfoString(stateConfig.debugHashDepth()); @@ -151,10 +150,8 @@ public static void writeSignedStateFilesToDirectory( Objects.requireNonNull(directory); Objects.requireNonNull(signedState); - final MerkleRoot state = signedState.getState(); - if (state instanceof MerkleStateRoot merkleStateRoot) { - merkleStateRoot.setTime(platformContext.getTime()); - } + final PlatformMerkleStateRoot state = signedState.getState(); + state.setTime(platformContext.getTime()); state.createSnapshot(directory); writeSignatureSetFile(directory, signedState); writeHashInfoFile(platformContext, directory, signedState.getState()); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldMain.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldMain.java index 588a58b8e530..35a902c9821f 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldMain.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/SwirldMain.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package com.swirlds.platform.system; import com.swirlds.common.platform.NodeId; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.List; @@ -67,7 +67,7 @@ default List> getConfigDataTypes() { * @return merkle state tree root node */ @NonNull - MerkleRoot newMerkleStateRoot(); + PlatformMerkleStateRoot newMerkleStateRoot(); /** *

diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java index 3e7991e05800..8a1d5fd6ed23 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/address/AddressBookUtils.java @@ -251,7 +251,7 @@ public static ServiceEndpoint endpointFor(@NonNull final String host, final int // Initialize the address book from the configuration and platform saved state. final AddressBookInitializer addressBookInitializer = new AddressBookInitializer( selfId, version, softwareUpgrade, initialState.get(), bootstrapAddressBook.copy(), platformContext); - final State state = (State) initialState.get().getState().getSwirldState(); + final State state = initialState.get().getState(); if (addressBookInitializer.hasAddressBookChanged()) { if (addressBookInitializer.getPreviousAddressBook() != null) { diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/BootstrapUtils.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/BootstrapUtils.java index 080f643123a4..71657da66a3b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/BootstrapUtils.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/BootstrapUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ import com.swirlds.platform.health.entropy.OSEntropyChecker; import com.swirlds.platform.health.filesystem.OSFileSystemChecker; import com.swirlds.platform.network.Network; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.address.AddressBookNetworkUtils; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.swirldapp.AppLoaderException; @@ -213,7 +213,7 @@ public static boolean detectSoftwareUpgrade( if (loadedSignedState == null) { loadedSoftwareVersion = null; } else { - MerkleRoot state = loadedSignedState.getState(); + PlatformMerkleStateRoot state = loadedSignedState.getState(); loadedSoftwareVersion = state.getReadablePlatformState().getCreationSoftwareVersion(); } final int versionComparison = loadedSoftwareVersion == null ? 1 : appVersion.compareTo(loadedSoftwareVersion); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/AddressBookInitializerTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/AddressBookInitializerTest.java index 8d2bf9aa94ad..4db717f954be 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/AddressBookInitializerTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/AddressBookInitializerTest.java @@ -1,4 +1,19 @@ -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.swirlds.platform; import static com.swirlds.platform.roster.RosterUtils.buildAddressBook; @@ -16,7 +31,6 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; import com.hedera.hapi.node.state.roster.Roster; import com.swirlds.common.context.PlatformContext; @@ -27,18 +41,16 @@ import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder; import com.swirlds.platform.config.AddressBookConfig_; import com.swirlds.platform.roster.RosterRetriever; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.address.AddressBookInitializer; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.system.SoftwareVersion; -import com.swirlds.platform.system.SwirldState; import com.swirlds.platform.system.address.Address; import com.swirlds.platform.system.address.AddressBook; import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder; import com.swirlds.platform.test.fixtures.addressbook.RandomRosterBuilder; import com.swirlds.platform.test.fixtures.roster.RosterServiceStateMock; -import com.swirlds.state.State; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.io.File; @@ -379,15 +391,14 @@ private SignedState getMockSignedState( boolean fromGenesis) { final SignedState signedState = mock(SignedState.class); final SoftwareVersion softwareVersion = getMockSoftwareVersion(2); - final SwirldState swirldState = getMockSwirldStateSupplier(weightValue).get(); - when(signedState.getSwirldState()).thenReturn(swirldState); + final PlatformMerkleStateRoot state = + getMockSwirldStateSupplier(weightValue).get(); + when(signedState.getSwirldState()).thenReturn(state); final PlatformStateAccessor platformState = mock(PlatformStateAccessor.class); when(platformState.getCreationSoftwareVersion()).thenReturn(softwareVersion); - RosterServiceStateMock.setup( - (State) swirldState, currentRoster, 1L, RosterRetriever.buildRoster(previousAddressBook)); - final MerkleRoot state = mock(MerkleRoot.class); + RosterServiceStateMock.setup(state, currentRoster, 1L, RosterRetriever.buildRoster(previousAddressBook)); + when(state.getReadablePlatformState()).thenReturn(platformState); - when(state.getSwirldState()).thenReturn(swirldState); when(signedState.getState()).thenReturn(state); when(signedState.isGenesisState()).thenReturn(fromGenesis); when(signedState.getRoster()).thenReturn(currentRoster); @@ -400,10 +411,10 @@ private SignedState getMockSignedState( * @param scenario The scenario to load. * @return A SwirldState which behaves according to the input scenario. */ - private Supplier getMockSwirldStateSupplier(int scenario) { + private Supplier getMockSwirldStateSupplier(int scenario) { final AtomicReference configAddressBook = new AtomicReference<>(); - final SwirldState swirldState = mock(SwirldState.class, withSettings().extraInterfaces(State.class)); + final PlatformMerkleStateRoot swirldState = mock(PlatformMerkleStateRoot.class); final OngoingStubbing stub = when(swirldState.updateWeight( argThat(confAB -> { diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SavedStateMetadataTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SavedStateMetadataTests.java index 66d513611c38..9858084d3b14 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SavedStateMetadataTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SavedStateMetadataTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,14 +37,13 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; import com.hedera.hapi.node.state.roster.Roster; import com.swirlds.common.crypto.Hash; import com.swirlds.common.platform.NodeId; import com.swirlds.common.test.fixtures.RandomUtils; import com.swirlds.platform.consensus.ConsensusSnapshot; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.signed.SigSet; import com.swirlds.platform.state.signed.SignedState; @@ -52,9 +51,7 @@ import com.swirlds.platform.state.snapshot.SavedStateMetadataField; import com.swirlds.platform.system.BasicSoftwareVersion; import com.swirlds.platform.system.SoftwareVersion; -import com.swirlds.platform.system.SwirldState; import com.swirlds.platform.test.fixtures.roster.RosterServiceStateMock; -import com.swirlds.state.State; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; import java.nio.file.Files; @@ -209,16 +206,14 @@ void signingNodesSortedTest() { final SignedState signedState = mock(SignedState.class); final SigSet sigSet = mock(SigSet.class); - final MerkleRoot state = mock(MerkleRoot.class); + final PlatformMerkleStateRoot state = mock(PlatformMerkleStateRoot.class); when(state.getHash()).thenReturn(randomHash(random)); final PlatformStateAccessor platformState = mock(PlatformStateAccessor.class); when(platformState.getLegacyRunningEventHash()).thenReturn(randomHash(random)); when(platformState.getSnapshot()).thenReturn(mock(ConsensusSnapshot.class)); final Roster roster = mock(Roster.class); - final State theState = mock(State.class, withSettings().extraInterfaces(SwirldState.class)); - when(state.getSwirldState()).thenReturn((SwirldState) theState); - RosterServiceStateMock.setup(theState, roster); + RosterServiceStateMock.setup(state, roster); when(signedState.getState()).thenReturn(state); when(state.getReadablePlatformState()).thenReturn(platformState); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SignedStateFileReadWriteTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SignedStateFileReadWriteTest.java index b611d823dfff..d48611bafb62 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SignedStateFileReadWriteTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/SignedStateFileReadWriteTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder; import com.swirlds.merkledb.MerkleDb; import com.swirlds.platform.config.StateConfig; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.state.snapshot.DeserializedSignedState; import com.swirlds.platform.state.snapshot.SignedStateFileUtils; @@ -107,7 +107,7 @@ void writeHashInfoFileTest() throws IOException { final SignedState signedState = new RandomSignedStateGenerator() .setSoftwareVersion(new BasicSoftwareVersion(platformVersion.minor())) .build(); - MerkleRoot state = signedState.getState(); + PlatformMerkleStateRoot state = signedState.getState(); writeHashInfoFile(platformContext, testDirectory, state); final StateConfig stateConfig = new TestConfigBuilder().getOrCreateConfig().getConfigData(StateConfig.class); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/consensus/RoundCalculationUtilsTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/consensus/RoundCalculationUtilsTest.java index 5fdda8434044..477d12c0f578 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/consensus/RoundCalculationUtilsTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/consensus/RoundCalculationUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.system.events.EventConstants; @@ -69,7 +69,7 @@ void getMinGenNonAncientFromSignedState() { final Map map = LongStream.range(1, 50).collect(HashMap::new, (m, l) -> m.put(l, l * 10), HashMap::putAll); final SignedState signedState = mock(SignedState.class); - final MerkleRoot state = mock(MerkleRoot.class); + final PlatformMerkleStateRoot state = mock(PlatformMerkleStateRoot.class); final PlatformStateModifier platformState = mock(PlatformStateModifier.class); when(signedState.getState()).thenReturn(state); when(state.getReadablePlatformState()).thenReturn(platformState); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/DefaultTransactionHandlerTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/DefaultTransactionHandlerTests.java index 125d4a27678c..037f5c12b3d4 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/DefaultTransactionHandlerTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/DefaultTransactionHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -156,8 +156,7 @@ void normalOperation(final boolean pcesRound) throws InterruptedException { pcesRound, handlerOutput.reservedSignedState().get().isPcesRound(), "the state should match the PCES boolean"); - verify(tester.getSwirldStateManager().getConsensusState().getSwirldState()) - .sealConsensusRound(consensusRound); + verify(tester.getSwirldStateManager().getConsensusState()).sealConsensusRound(consensusRound); } @Test diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/TransactionHandlerTester.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/TransactionHandlerTester.java index b985df4b09a9..2fac032faca8 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/TransactionHandlerTester.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/eventhandling/TransactionHandlerTester.java @@ -25,7 +25,7 @@ import com.swirlds.common.platform.NodeId; import com.swirlds.common.test.fixtures.platform.TestPlatformContextBuilder; import com.swirlds.platform.roster.RosterRetriever; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.state.SwirldStateManager; import com.swirlds.platform.state.service.PlatformStateValueAccumulator; @@ -59,9 +59,7 @@ public TransactionHandlerTester(final AddressBook addressBook) { TestPlatformContextBuilder.create().build(); platformState = new PlatformStateValueAccumulator(); - final MerkleRoot consensusState = mock(MerkleRoot.class); - final SwirldState swirldState = mock(SwirldState.class); - when(consensusState.getSwirldState()).thenReturn(swirldState); + final PlatformMerkleStateRoot consensusState = mock(PlatformMerkleStateRoot.class); when(consensusState.copy()).thenReturn(consensusState); when(consensusState.getReadablePlatformState()).thenReturn(platformState); when(consensusState.getWritablePlatformState()).thenReturn(platformState); @@ -69,7 +67,7 @@ public TransactionHandlerTester(final AddressBook addressBook) { handledRounds.add(i.getArgument(0)); return null; }) - .when(swirldState) + .when(consensusState) .handleConsensusRound(any(), any(), any()); final StatusActionSubmitter statusActionSubmitter = submittedActions::add; swirldStateManager = new SwirldStateManager( diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectProtocolTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectProtocolTests.java index 9403b24625a0..0c99753b12c3 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectProtocolTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectProtocolTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ import com.swirlds.platform.network.protocol.Protocol; import com.swirlds.platform.network.protocol.ProtocolFactory; import com.swirlds.platform.network.protocol.ReconnectProtocolFactory; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.state.signed.SignedStateValidator; @@ -308,7 +308,7 @@ void testTeacherThrottleReleased() { Time.getCurrent()); final SignedState signedState = spy(new RandomSignedStateGenerator().build()); when(signedState.isComplete()).thenReturn(true); - final MerkleRoot state = mock(MerkleRoot.class); + final PlatformMerkleStateRoot state = mock(PlatformMerkleStateRoot.class); when(signedState.getState()).thenReturn(state); final ReservedSignedState reservedSignedState = signedState.reserve("test"); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectTest.java index dc133ae5adc4..ab823330c2c9 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/ReconnectTest.java @@ -39,7 +39,7 @@ import com.swirlds.platform.metrics.ReconnectMetrics; import com.swirlds.platform.network.Connection; import com.swirlds.platform.network.SocketConnection; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.state.signed.SignedStateValidator; import com.swirlds.platform.test.fixtures.addressbook.RandomRosterBuilder; @@ -182,7 +182,7 @@ private ReconnectTeacher buildSender(final SocketConnection connection, final Re } private ReconnectLearner buildReceiver( - final MerkleRoot state, final Connection connection, final ReconnectMetrics reconnectMetrics) { + final PlatformMerkleStateRoot state, final Connection connection, final ReconnectMetrics reconnectMetrics) { final Roster roster = RandomRosterBuilder.create(getRandomPrintSeed()).withSize(5).build(); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java index 0165713bc1ed..0da53f98a5bb 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,7 +83,7 @@ void activeStateCountTest() throws IOException { RuntimeObjectRegistry.getActiveObjectsCount(PlatformMerkleStateRoot.class), "no states have been created yet"); - final List states = new LinkedList<>(); + final List states = new LinkedList<>(); // Create a bunch of states for (int i = 0; i < 100; i++) { states.add(new PlatformMerkleStateRoot(FAKE_MERKLE_STATE_LIFECYCLES, softwareVersionSupplier)); @@ -94,10 +94,10 @@ void activeStateCountTest() throws IOException { } // Fast copy a state - final MerkleRoot stateToCopy = + final PlatformMerkleStateRoot stateToCopy = new PlatformMerkleStateRoot(FAKE_MERKLE_STATE_LIFECYCLES, softwareVersionSupplier); states.add(stateToCopy); - final MerkleRoot copyOfStateToCopy = stateToCopy.copy(); + final PlatformMerkleStateRoot copyOfStateToCopy = stateToCopy.copy(); states.add(copyOfStateToCopy); assertEquals( states.size(), @@ -120,7 +120,7 @@ void activeStateCountTest() throws IOException { final InputOutputStream io = new InputOutputStream(); io.getOutput().writeMerkleTree(dir, stateToSerialize); io.startReading(); - final MerkleRoot deserializedState = io.getInput().readMerkleTree(dir, 5); + final PlatformMerkleStateRoot deserializedState = io.getInput().readMerkleTree(dir, 5); states.add(deserializedState); assertEquals( states.size(), diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerTests.java index 21238be8a06d..80ccb927b3c7 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ class SwirldStateManagerTests { private SwirldStateManager swirldStateManager; - private MerkleRoot initialState; + private PlatformMerkleStateRoot initialState; @BeforeEach void setup() { @@ -125,7 +125,7 @@ void loadFromSignedStateRefCount() { + "decremented."); } - private static MerkleRoot newState() { + private static PlatformMerkleStateRoot newState() { final PlatformMerkleStateRoot state = new PlatformMerkleStateRoot( FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(version.major())); FAKE_MERKLE_STATE_LIFECYCLES.initPlatformState(state); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerUtilsTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerUtilsTests.java index 76cfe53cde02..4bf8fc0bbed8 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerUtilsTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/SwirldStateManagerUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,8 @@ void testFastCopyIsMutable() { FAKE_MERKLE_STATE_LIFECYCLES.initPlatformState(state); state.reserve(); final SwirldStateMetrics stats = mock(SwirldStateMetrics.class); - final MerkleRoot result = SwirldStateManagerUtils.fastCopy(state, stats, new BasicSoftwareVersion(1)); + final PlatformMerkleStateRoot result = + SwirldStateManagerUtils.fastCopy(state, stats, new BasicSoftwareVersion(1)); assertFalse(result.isImmutable(), "The copy state should be mutable."); assertEquals( diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/hashlogger/HashLoggerTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/hashlogger/HashLoggerTest.java index 09d5beadc45e..3b56272a8e6f 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/hashlogger/HashLoggerTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/hashlogger/HashLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ import com.swirlds.config.api.Configuration; import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder; import com.swirlds.platform.config.StateConfig_; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateAccessor; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; @@ -150,7 +150,8 @@ private ReservedSignedState createSignedState(final long round) { final MerkleNode merkleNode = MerkleTestUtils.buildLessSimpleTree(); MerkleCryptoFactory.getInstance().digestTreeSync(merkleNode); final SignedState signedState = mock(SignedState.class); - final MerkleRoot state = mock(MerkleRoot.class, withSettings().extraInterfaces(State.class, SwirldState.class)); + final PlatformMerkleStateRoot state = + mock(PlatformMerkleStateRoot.class, withSettings().extraInterfaces(State.class, SwirldState.class)); final PlatformStateAccessor platformState = mock(PlatformStateAccessor.class); when(platformState.getRound()).thenReturn(round); @@ -160,7 +161,6 @@ private ReservedSignedState createSignedState(final long round) { when(state.getHash()).thenReturn(merkleNode.getHash()); when(signedState.getState()).thenReturn(state); - when(state.getSwirldState()).thenReturn((SwirldState) state); when(signedState.getRound()).thenReturn(round); ReservedSignedState reservedSignedState = mock(ReservedSignedState.class); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/system/state/notifications/StateHashedNotificationTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/system/state/notifications/StateHashedNotificationTest.java index 3f6c32024fc7..f44c8b942200 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/system/state/notifications/StateHashedNotificationTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/system/state/notifications/StateHashedNotificationTest.java @@ -23,7 +23,7 @@ import com.swirlds.common.crypto.Hash; import com.swirlds.platform.components.transaction.system.ScopedSystemTransaction; import com.swirlds.platform.internal.ConsensusRound; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.wiring.components.StateAndRound; @@ -39,7 +39,7 @@ class StateHashedNotificationTest { private static final Hash HASH = new Hash(new byte[48]); @Mock - private MerkleRoot merkleRoot; + private PlatformMerkleStateRoot merkleRoot; @Mock private SignedState signedState; diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java index b3f17736b056..227ef6dd2588 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java @@ -37,7 +37,7 @@ import com.swirlds.platform.config.BasicConfig_; import com.swirlds.platform.crypto.KeysAndCerts; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.system.BasicSoftwareVersion; import com.swirlds.platform.system.Platform; import com.swirlds.platform.system.address.AddressBook; @@ -103,7 +103,7 @@ public class TurtleNode { model = WiringModelBuilder.create(platformContext) .withDeterministicModeEnabled(true) .build(); - final Supplier genesisStateSupplier = TurtleTestingToolState::getStateRootNode; + final Supplier genesisStateSupplier = TurtleTestingToolState::getStateRootNode; final var version = new BasicSoftwareVersion(1); final var metrics = getMetricsProvider().createPlatformMetrics(nodeId); diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java index f4547d45a1cd..9e9231159cbe 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java @@ -107,7 +107,7 @@ public TurtleTestingToolState copy() { * @return merkle tree root */ @NonNull - public static MerkleRoot getStateRootNode() { + public static PlatformMerkleStateRoot getStateRootNode() { final PlatformMerkleStateRoot state = new TurtleTestingToolState(); FAKE_MERKLE_STATE_LIFECYCLES.initPlatformState(state); return state; diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/SignedStateReserverTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/SignedStateReserverTest.java index 2ac17245facf..a1acab1071d8 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/SignedStateReserverTest.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/SignedStateReserverTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import com.swirlds.common.wiring.wires.input.BindableInputWire; import com.swirlds.common.wiring.wires.output.OutputWire; import com.swirlds.platform.crypto.SignatureVerifier; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.ReservedSignedState; import com.swirlds.platform.state.signed.SignedState; import java.util.List; @@ -51,7 +51,7 @@ void basicTest() { final SignedState signedState = new SignedState( platformContext.getConfiguration(), Mockito.mock(SignatureVerifier.class), - Mockito.mock(MerkleRoot.class), + Mockito.mock(PlatformMerkleStateRoot.class), "create", false, false, diff --git a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java index 29b3ade2f864..7b18be87da68 100644 --- a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java +++ b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/BlockingSwirldState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import com.swirlds.common.io.streams.SerializableDataInputStream; import com.swirlds.common.io.streams.SerializableDataOutputStream; import com.swirlds.platform.components.transaction.system.ScopedSystemTransaction; -import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateModifier; import com.swirlds.platform.system.BasicSoftwareVersion; @@ -41,8 +40,8 @@ import java.util.function.Consumer; /** - * A test implementation of {@link MerkleRoot} and {@link SwirldState} state for SignedStateManager unit tests. - * Node that some of the {@link MerkleRoot} methods are intentionally not implemented. If a test needs these methods, + * A test implementation of {@link PlatformMerkleStateRoot} and {@link SwirldState} state for SignedStateManager unit tests. + * Node that some of the {@link PlatformMerkleStateRoot} methods are intentionally not implemented. If a test needs these methods, * {@link MerkleStateRoot} should be used instead. */ public class BlockingSwirldState extends PlatformMerkleStateRoot { diff --git a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/RandomSignedStateGenerator.java b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/RandomSignedStateGenerator.java index 15069294bd83..80536e8ea87a 100644 --- a/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/RandomSignedStateGenerator.java +++ b/platform-sdk/swirlds-platform-core/src/testFixtures/java/com/swirlds/platform/test/fixtures/state/RandomSignedStateGenerator.java @@ -39,7 +39,6 @@ import com.swirlds.platform.consensus.ConsensusSnapshot; import com.swirlds.platform.crypto.SignatureVerifier; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.MinimumJudgeInfo; import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.PlatformStateModifier; @@ -77,7 +76,7 @@ public class RandomSignedStateGenerator { final Random random; - private MerkleRoot state; + private PlatformMerkleStateRoot state; private Long round; private Hash legacyRunningEventHash; private Roster roster; @@ -138,7 +137,7 @@ public SignedState build() { softwareVersionInstance = softwareVersion; } - final MerkleRoot stateInstance; + final PlatformMerkleStateRoot stateInstance; registerMerkleStateRootClassIds(); if (state == null) { if (useBlockingState) { @@ -147,7 +146,7 @@ public SignedState build() { stateInstance = new PlatformMerkleStateRoot( FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(version.major())); } - ((MerkleStateRoot) stateInstance).setTime(Time.getCurrent()); + stateInstance.setTime(Time.getCurrent()); } else { stateInstance = state; } diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java index 375b1f708f8b..6b6d36b915e8 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ import com.swirlds.common.test.fixtures.junit.tags.TestComponentTags; import com.swirlds.common.test.fixtures.platform.TestPlatformContextBuilder; import com.swirlds.platform.crypto.CryptoStatic; -import com.swirlds.platform.state.MerkleRoot; import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.signed.SignedState; import com.swirlds.platform.system.BasicSoftwareVersion; @@ -45,8 +44,8 @@ class StateTest { @DisplayName("Test Copy") void testCopy() { - final MerkleRoot state = randomSignedState().getState(); - final MerkleRoot copy = state.copy(); + final PlatformMerkleStateRoot state = randomSignedState().getState(); + final PlatformMerkleStateRoot copy = state.copy(); assertNotSame(state, copy, "copy should not return the same object"); @@ -67,7 +66,7 @@ void testCopy() { @Tag(TestComponentTags.MERKLE) @DisplayName("Test Try Reserve") void tryReserveTest() { - final MerkleRoot state = randomSignedState().getState(); + final PlatformMerkleStateRoot state = randomSignedState().getState(); assertEquals( 1, state.getReservationCount(), diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java index 5457d9b685eb..f06478b51f4a 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2024 Hedera Hashgraph, LLC + * Copyright (C) 2024 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ import com.swirlds.common.test.fixtures.io.InputOutputStream; import com.swirlds.common.test.fixtures.junit.tags.TestComponentTags; import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.test.fixtures.state.BlockingSwirldState; import com.swirlds.state.merkle.MerkleStateRoot; import java.io.IOException; @@ -70,7 +70,7 @@ void stateSerializationTest() throws IOException { io.startReading(); - final MerkleRoot decodedState = io.getInput().readMerkleTree(testDirectory, Integer.MAX_VALUE); + final PlatformMerkleStateRoot decodedState = io.getInput().readMerkleTree(testDirectory, Integer.MAX_VALUE); MerkleCryptoFactory.getInstance().digestTreeSync(decodedState); assertEquals(merkleStateRoot.getHash(), decodedState.getHash(), "expected trees to be equal"); diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java index 38ad75bf149e..a8e5a5bc1464 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssDetectorTests.java @@ -44,7 +44,7 @@ import com.swirlds.platform.internal.ConsensusRound; import com.swirlds.platform.internal.EventImpl; import com.swirlds.platform.roster.RosterUtils; -import com.swirlds.platform.state.MerkleRoot; +import com.swirlds.platform.state.PlatformMerkleStateRoot; import com.swirlds.platform.state.iss.DefaultIssDetector; import com.swirlds.platform.state.iss.IssDetector; import com.swirlds.platform.state.iss.internal.HashValidityStatus; @@ -764,7 +764,7 @@ void ignoredRoundTest() { private static ReservedSignedState mockState(final long round, final Hash hash) { final ReservedSignedState rs = mock(ReservedSignedState.class); final SignedState ss = mock(SignedState.class); - final MerkleRoot s = mock(MerkleRoot.class); + final PlatformMerkleStateRoot s = mock(PlatformMerkleStateRoot.class); when(rs.get()).thenReturn(ss); when(ss.getState()).thenReturn(s); when(ss.getRound()).thenReturn(round); From 2f5f838cb48758d9c0533ace5c2547540b0ac65a Mon Sep 17 00:00:00 2001 From: Matt Riben Date: Fri, 20 Dec 2024 16:34:09 -0600 Subject: [PATCH 11/12] fix: move and change value of Dockerfile environment variable (#16239) Signed-off-by: Matt Riben --- .../containers/production-next/consensus-node/Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hedera-node/infrastructure/docker/containers/production-next/consensus-node/Dockerfile b/hedera-node/infrastructure/docker/containers/production-next/consensus-node/Dockerfile index 94d8bc1ef2f6..c165fed92372 100644 --- a/hedera-node/infrastructure/docker/containers/production-next/consensus-node/Dockerfile +++ b/hedera-node/infrastructure/docker/containers/production-next/consensus-node/Dockerfile @@ -227,8 +227,6 @@ ENV JAVA_VERSION "jdk-21.0.4+7" ENV JAVA_HOME /usr/local/java ENV PATH ${JAVA_HOME}/bin:${PATH} -ENV CONTAINER_TSR_ENABLED "true" - # Install Java COPY --from=java-builder ${JAVA_HOME}/ ${JAVA_HOME}/ @@ -285,6 +283,10 @@ ENV MALLOC_ARENA_MAX 4 # Log Folder Name Override ENV LOG_DIR_NAME "" +# If "true" or an integer between 1 & 2^63-1 after running consensus entrypoint.sh will block indefinitely. +# Otherwise entrypoint.sh will return the exit code from consensus. +ENV CONTAINER_TSR_ENABLED "false" + # Define Volume Bindpoints VOLUME "/opt/hgcapp/accountBalances" VOLUME "/opt/hgcapp/eventsStreams" From 1e4a206e62fa64ef9f95ba814c155ba0e78c792e Mon Sep 17 00:00:00 2001 From: Andrew Brandt Date: Fri, 20 Dec 2024 20:44:00 -0500 Subject: [PATCH 12/12] build: Roll hiero gradle conventions to version 0.1.4 (#17149) Signed-off-by: Andrew Brandt --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0630c1461051..f1d55a92049b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,7 +14,7 @@ * limitations under the License. */ -plugins { id("org.hiero.gradle.build") version "0.1.2" } +plugins { id("org.hiero.gradle.build") version "0.1.4" } javaModules { // This "intermediate parent project" should be removed