Repository: iExecBlockchainComputing/iexec-commons-poco
Pull request #130: Move ValidNonZeroEthereumAddress from common to commons-poco
Author: login: nabil-Tounarti
Created: 2025-03-12T09:50:31Z | Merged: 2025-03-12T13:19:57Z



Diff:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a61987a..424cd5b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.
 - Remove boolean to yes/no conversion methods from `TeeUtils`. (#126)
 - Remove `App` and `Dataset` generated Smart Contract wrappers. (#127)
 - Rename `ChainApp` and `ChainDataset` `uri` field to `multiaddr` to be consistent with Smart Contracts. (#127)
+- Move `ValidNonZeroEthereumAddress` from `iexec-common` to `iexec-commons-poco`. (#130)
 
 ### Dependency Upgrades
 
diff --git a/build.gradle b/build.gradle
index 7e3fe86..cbc824e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -53,6 +53,9 @@ dependencies {
 
     // jakarta annotations like PostConstruct
     implementation 'jakarta.annotation:jakarta.annotation-api'
+
+    // necessary dependencies for validation to work correctly
+    implementation 'jakarta.validation:jakarta.validation-api'
 }
 
 java {
@@ -82,6 +85,9 @@ testing {
                 implementation "org.testcontainers:junit-jupiter:$testContainersVersion"
                 // logback
                 runtimeOnly 'ch.qos.logback:logback-classic'
+
+                runtimeOnly 'org.glassfish.expressly:expressly:5.0.0'
+                runtimeOnly 'org.hibernate.validator:hibernate-validator'
             }
         }
     }
diff --git a/src/main/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidator.java b/src/main/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidator.java
new file mode 100644
index 0000000..94afd36
--- /dev/null
+++ b/src/main/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidator.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2025 IEXEC BLOCKCHAIN TECH
+ *
+ * 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.iexec.commons.poco.chain.validation;
+
+import com.iexec.commons.poco.utils.BytesUtils;
+import com.iexec.commons.poco.utils.EthAddress;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+public class EthereumNonZeroAddressValidator
+        implements ConstraintValidator<ValidNonZeroEthereumAddress, String> {
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        return EthAddress.validate(value)
+                && !BytesUtils.EMPTY_ADDRESS.equals(value);
+    }
+}
diff --git a/src/main/java/com/iexec/commons/poco/chain/validation/ValidNonZeroEthereumAddress.java b/src/main/java/com/iexec/commons/poco/chain/validation/ValidNonZeroEthereumAddress.java
new file mode 100644
index 0000000..34f79d7
--- /dev/null
+++ b/src/main/java/com/iexec/commons/poco/chain/validation/ValidNonZeroEthereumAddress.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2025 IEXEC BLOCKCHAIN TECH
+ *
+ * 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.iexec.commons.poco.chain.validation;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Constraint(validatedBy = EthereumNonZeroAddressValidator.class)
+@Target({ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ValidNonZeroEthereumAddress {
+    String message() default "Invalid non-zero Ethereum address";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}
diff --git a/src/test/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidatorTests.java b/src/test/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidatorTests.java
new file mode 100644
index 0000000..bc8bea8
--- /dev/null
+++ b/src/test/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidatorTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2025 IEXEC BLOCKCHAIN TECH
+ *
+ * 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.iexec.commons.poco.chain.validation;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import jakarta.validation.ValidatorFactory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.Set;
+
+class EthereumNonZeroAddressValidatorTests {
+
+    @Test
+    void shouldValidateAddress() {
+        assertViolations("0x0000000000000000000000000000000000000001", 0);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "0x0000000000000000000000000000000000000000",
+            ""
+    })
+    void shouldNotValidateAddress(String address) {
+        assertViolations(address, 1);
+    }
+
+    private void assertViolations(String address, int i) {
+        final Account account = new Account(address);
+        try (final ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
+            final Validator validator = factory.getValidator();
+            final Set<ConstraintViolation<Account>> violations = validator.validate(account);
+            Assertions.assertEquals(i, violations.size());
+        }
+    }
+
+    static class Account {
+
+        @ValidNonZeroEthereumAddress
+        private final String address;
+
+        public Account(String address) {
+            this.address = address;
+        }
+    }
+}


Reviews:
user: login: Natchica
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:18:23Z
user: login: jbern0rd
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T11:53:40Z
user: login: jbern0rd
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T11:54:04Z
user: login: jbern0rd
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T13:13:28Z

Review comments:
diff_hunk: @@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.
 - Remove boolean to yes/no conversion methods from `TeeUtils`. (#126)
 - Remove `App` and `Dataset` generated Smart Contract wrappers. (#127)
 - Rename `ChainApp` and `ChainDataset` `uri` field to `multiaddr` to be consistent with Smart Contracts. (#127)
+- Move ValidNonZeroEthereumAddress from common to commons-poco. (#130)
path: CHANGELOG.md
user: login: Natchica
body: ```suggestion
- Move ValidNonZeroEthereumAddress from `iexec-common` to `iexec-commons-poco` (#130)
```
created_at: 2025-03-12T10:18:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+/*
+ * Copyright 2025 IEXEC BLOCKCHAIN TECH
+ *
+ * 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.iexec.commons.poco.chain.validation;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.Set;
+
+class EthereumNonZeroAddressValidatorTests {
+
+    private static Validator validator;
+
+    @BeforeEach
+    void beforeEach() {
+        validator = Validation.buildDefaultValidatorFactory().getValidator();
+    }
+
+    @Test
+    void shouldValidateAddress() {
+        assertViolations("0x0000000000000000000000000000000000000001", 0);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "0x0000000000000000000000000000000000000000",
+            ""
+    })
+    void shouldNotValidateAddress(String address) {
+        assertViolations(address, 1);
+    }
+
+    private void assertViolations(String address, int i) {
+        Account account = new Account(address);
+        Set<ConstraintViolation<Account>> violations = validator.validate(account);
+        Assertions.assertEquals(i, violations.size());
path: src/test/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidatorTests.java
user: login: jbern0rd
body: To remove a warning, we can do this
```suggestion
        final Account account = new Account(address);
        try (final ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
            final Validator validator = factory.getValidator();
            final Set<ConstraintViolation<Account>> violations = validator.validate(account);
            final Assertions.assertEquals(i, violations.size());
        }
```
created_at: 2025-03-12T11:53:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+/*
+ * Copyright 2025 IEXEC BLOCKCHAIN TECH
+ *
+ * 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.iexec.commons.poco.chain.validation;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.Set;
+
+class EthereumNonZeroAddressValidatorTests {
+
+    private static Validator validator;
+
+    @BeforeEach
+    void beforeEach() {
+        validator = Validation.buildDefaultValidatorFactory().getValidator();
+    }
+
+    @Test
+    void shouldValidateAddress() {
+        assertViolations("0x0000000000000000000000000000000000000001", 0);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "0x0000000000000000000000000000000000000000",
+            ""
+    })
+    void shouldNotValidateAddress(String address) {
+        assertViolations(address, 1);
+    }
+
+    private void assertViolations(String address, int i) {
+        Account account = new Account(address);
+        Set<ConstraintViolation<Account>> violations = validator.validate(account);
+        Assertions.assertEquals(i, violations.size());
path: src/test/java/com/iexec/commons/poco/chain/validation/EthereumNonZeroAddressValidatorTests.java
user: login: jbern0rd
body: This allows to remove `@BeforeEach` and private field as well
created_at: 2025-03-12T11:54:03Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-03-12T13:11:42Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=com.iexec.commons%3Aiexec-commons-poco&pullRequest=130)


author_association: NONE