From e447a2b60167a85a8deb8f80b1c4a58e08d2e2fc Mon Sep 17 00:00:00 2001 From: Hendrik Ebbers Date: Wed, 17 May 2023 17:51:31 +0200 Subject: [PATCH] Bytes Converter added for Config Signed-off-by: Hendrik Ebbers --- .../node/app/config/ConfigProviderImpl.java | 4 +- hedera-node/hedera-config/build.gradle.kts | 1 + .../node/config/converter/BytesConverter.java | 47 +++++++++++ .../src/main/java/module-info.java | 1 + .../config/PropertySourceBasedConfigTest.java | 2 + .../config/converter/BytesConverterTest.java | 83 +++++++++++++++++++ .../testfixtures/HederaTestConfigBuilder.java | 2 + 7 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/BytesConverter.java create mode 100644 hedera-node/hedera-config/src/test/java/com/hedera/node/config/converter/BytesConverterTest.java diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/config/ConfigProviderImpl.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/config/ConfigProviderImpl.java index 71469bb71c0..e772ae19977 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/config/ConfigProviderImpl.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/config/ConfigProviderImpl.java @@ -20,6 +20,7 @@ import com.hedera.node.config.ConfigProvider; import com.hedera.node.config.VersionedConfiguration; import com.hedera.node.config.converter.AccountIDConverter; +import com.hedera.node.config.converter.BytesConverter; import com.hedera.node.config.converter.CongestionMultipliersConverter; import com.hedera.node.config.converter.ContractIDConverter; import com.hedera.node.config.converter.EntityScaleFactorsConverter; @@ -231,7 +232,8 @@ private ConfigurationBuilder addConverter(@NonNull final ConfigurationBuilder bu .withConverter(new HederaFunctionalityConverter()) .withConverter(new ProfileConverter()) .withConverter(new SidecarTypeConverter()) - .withConverter(new KeyValuePairConverter()); + .withConverter(new KeyValuePairConverter()) + .withConverter(new BytesConverter()); } @NonNull diff --git a/hedera-node/hedera-config/build.gradle.kts b/hedera-node/hedera-config/build.gradle.kts index 5af72a1d7af..e2492f7f5c8 100644 --- a/hedera-node/hedera-config/build.gradle.kts +++ b/hedera-node/hedera-config/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { implementation(project(":hedera-node:hapi-utils")) implementation(libs.swirlds.config) compileOnlyApi(libs.spotbugs.annotations) + implementation(libs.pbj.runtime) testImplementation(testLibs.bundles.testing) diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/BytesConverter.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/BytesConverter.java new file mode 100644 index 00000000000..421195672bd --- /dev/null +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/converter/BytesConverter.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 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.config.converter; + +import static com.swirlds.common.utility.CommonUtils.unhex; + +import com.hedera.pbj.runtime.io.buffer.Bytes; +import com.swirlds.config.api.converter.ConfigConverter; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; + +/** + * Converts a string of hex digits into a {@link Bytes} object. + */ +public class BytesConverter implements ConfigConverter { + @Nullable + @Override + public Bytes convert(@NonNull String value) throws IllegalArgumentException, NullPointerException { + if (value == null) { + throw new NullPointerException("BytesConverter cannot convert null value"); + } else if (!value.startsWith("0x")) { + throw new IllegalArgumentException("Invalid format. Value must start with '0x': " + value); + } else { + try { + final var hex = value.substring(2); + final var bytes = unhex(hex); + return Bytes.wrap(bytes); + } catch (final Exception e) { + throw new IllegalArgumentException("Invalid format: " + value, e); + } + } + } +} diff --git a/hedera-node/hedera-config/src/main/java/module-info.java b/hedera-node/hedera-config/src/main/java/module-info.java index 0130ab9541b..0d296ea8f8a 100644 --- a/hedera-node/hedera-config/src/main/java/module-info.java +++ b/hedera-node/hedera-config/src/main/java/module-info.java @@ -11,4 +11,5 @@ requires com.hedera.node.app.service.mono; requires com.hedera.node.hapi; requires com.hedera.node.app.hapi.utils; + requires com.hedera.pbj.runtime; } diff --git a/hedera-node/hedera-config/src/test/java/com/hedera/node/config/PropertySourceBasedConfigTest.java b/hedera-node/hedera-config/src/test/java/com/hedera/node/config/PropertySourceBasedConfigTest.java index bb481fed94a..dcb3601885d 100644 --- a/hedera-node/hedera-config/src/test/java/com/hedera/node/config/PropertySourceBasedConfigTest.java +++ b/hedera-node/hedera-config/src/test/java/com/hedera/node/config/PropertySourceBasedConfigTest.java @@ -34,6 +34,7 @@ import com.hedera.node.app.service.mono.ledger.accounts.staking.StakeStartupHelper.RecomputeType; import com.hedera.node.app.service.mono.throttling.MapAccessType; import com.hedera.node.config.converter.AccountIDConverter; +import com.hedera.node.config.converter.BytesConverter; import com.hedera.node.config.converter.CongestionMultipliersConverter; import com.hedera.node.config.converter.ContractIDConverter; import com.hedera.node.config.converter.EntityScaleFactorsConverter; @@ -108,6 +109,7 @@ void testConfig() { .withConverter(new HederaFunctionalityConverter()) .withConverter(new ProfileConverter()) .withConverter(new SidecarTypeConverter()) + .withConverter(new BytesConverter()) .withSource(new PropertySourceBasedConfigSource(propertySource)) .build(); diff --git a/hedera-node/hedera-config/src/test/java/com/hedera/node/config/converter/BytesConverterTest.java b/hedera-node/hedera-config/src/test/java/com/hedera/node/config/converter/BytesConverterTest.java new file mode 100644 index 00000000000..94e1e8a9b8f --- /dev/null +++ b/hedera-node/hedera-config/src/test/java/com/hedera/node/config/converter/BytesConverterTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2023 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.config.converter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import com.hedera.pbj.runtime.io.buffer.Bytes; +import java.io.IOException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class BytesConverterTest { + + @Test + void testNull() { + // given + final BytesConverter bytesConverter = new BytesConverter(); + + // then + assertThatThrownBy(() -> bytesConverter.convert(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testConversionResult() throws IOException { + // given + final BytesConverter bytesConverter = new BytesConverter(); + final String value = "0x1234567890abcdef"; + final byte[] expected = new byte[] {0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xab, (byte) 0xcd, (byte) 0xef}; + + // when + final byte[] bytes = bytesConverter.convert(value).toInputStream().readAllBytes(); + + // then + assertArrayEquals(expected, bytes); + } + + @ParameterizedTest + @ValueSource( + strings = { + "0x", + "0xaa", + "0x1234", + "0x111111111111111111111111", + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" + }) + void testValueValues(final String value) { + // given + final BytesConverter bytesConverter = new BytesConverter(); + + // when + final Bytes bytes = bytesConverter.convert(value); + + // then + assertThat(bytes).isNotNull(); + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", " ", "1", "123", "abc", "0xu", "0x1", "0x123", "0x12345"}) + void testInvalidValue(final String value) { + // given + final BytesConverter bytesConverter = new BytesConverter(); + + // then + assertThatThrownBy(() -> bytesConverter.convert(value)).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/hedera-node/hedera-config/src/testFixtures/java/com/hedera/node/config/testfixtures/HederaTestConfigBuilder.java b/hedera-node/hedera-config/src/testFixtures/java/com/hedera/node/config/testfixtures/HederaTestConfigBuilder.java index e9831769bb2..a8b670824f1 100644 --- a/hedera-node/hedera-config/src/testFixtures/java/com/hedera/node/config/testfixtures/HederaTestConfigBuilder.java +++ b/hedera-node/hedera-config/src/testFixtures/java/com/hedera/node/config/testfixtures/HederaTestConfigBuilder.java @@ -17,6 +17,7 @@ package com.hedera.node.config.testfixtures; import com.hedera.node.config.converter.AccountIDConverter; +import com.hedera.node.config.converter.BytesConverter; import com.hedera.node.config.converter.CongestionMultipliersConverter; import com.hedera.node.config.converter.ContractIDConverter; import com.hedera.node.config.converter.EntityScaleFactorsConverter; @@ -85,6 +86,7 @@ public HederaTestConfigBuilder(boolean registerAllTypes) { .withConverter(new ProfileConverter()) .withConverter(new SidecarTypeConverter()) .withConverter(new KeyValuePairConverter()) + .withConverter(new BytesConverter()) .withValidator(new EmulatesMapValidator()); }