Repository: rsksmart/rskj
Pull request #3117: Use union increaseLockingCap method in BridgeSupport
Author: login: nathanieliov
Created: 2025-05-08T11:57:23Z | Merged: 2025-05-27T14:44:10Z

- Use union increaseLockingCap method in BridgeSupport
- Added unit tests for increaseUnionBridgeLockingCap method

## How Has This Been Tested?

Unit tests

## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

## Checklist:

- [x] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Requires Activation Code (Hard Fork)


Diff:
diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java b/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
index 8937d0e4214..496d3af8826 100644
--- a/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
+++ b/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
@@ -2833,6 +2833,10 @@ public Coin getUnionBridgeLockingCap() {
         return unionBridgeSupport.getLockingCap().orElse(Coin.NEGATIVE_SATOSHI);
     }
 
+    public UnionResponseCode increaseUnionBridgeLockingCap(Transaction tx, Coin newLockingCap) {
+        return unionBridgeSupport.increaseLockingCap(tx, newLockingCap);
+    }
+
     protected FlyoverFederationInformation createFlyoverFederationInformation(Keccak256 flyoverDerivationHash) {
         return createFlyoverFederationInformation(flyoverDerivationHash, getActiveFederation());
     }
diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
index e34bfee6cba..7d27d59821a 100644
--- a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
+++ b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
@@ -60,6 +60,7 @@
 import co.rsk.peg.union.UnionBridgeSupport;
 import co.rsk.peg.union.UnionBridgeSupportImpl;
 import co.rsk.peg.union.UnionResponseCode;
+import co.rsk.peg.union.constants.UnionBridgeConstants;
 import co.rsk.peg.union.constants.UnionBridgeMainNetConstants;
 import co.rsk.peg.utils.*;
 import co.rsk.peg.utils.NonRefundablePeginReason;
@@ -790,24 +791,37 @@ class UnionBridgeTest {
         private static final ActivationConfig.ForBlock lovell = ActivationConfigsForTest.lovell700().forBlock(0);
         private static final ActivationConfig.ForBlock allActivations = ActivationConfigsForTest.all().forBlock(0);
 
-        private static final BridgeConstants constants = BridgeMainNetConstants.getInstance();
+        private static final BridgeConstants bridgeConstants = BridgeMainNetConstants.getInstance();
+        private static final UnionBridgeConstants unionBridgeConstants = bridgeConstants.getUnionBridgeConstants();
 
+        private UnionBridgeSupport unionBridgeSupport;
         private BridgeSupport bridgeSupport;
+
+        private static final RskAddress authorizerRskAddress = new RskAddress(
+            ECKey.fromPublicOnly(Hex.decode(
+                    "041fb6d4b421bb14d95b6fb79823d45b777f0e8fd07fe18d0940c0c113d9667911e354d4e8c8073f198d7ae5867d86e3068caff4f6bd7bffccc6757a3d7ee8024a"))
+                .getAddress());
+        private SignatureCache signatureCache;
         private Transaction transaction;
+
         private RskAddress unionBridgeContractAddress;
 
+
         @BeforeEach
         void setUp() {
+            signatureCache = mock(SignatureCache.class);
             unionBridgeSupport = UnionBridgeSupportBuilder.builder()
                 .withActivations(allActivations)
-                .withConstants(constants.getUnionBridgeConstants())
+                .withSignatureCache(signatureCache)
+                .withConstants(unionBridgeConstants)
                 .build();
             bridgeSupport = bridgeSupportBuilder
                 .withUnionBridgeSupport(unionBridgeSupport)
-                .withBridgeConstants(constants)
+                .withBridgeConstants(bridgeConstants)
                 .build();
 
             transaction = mock(Transaction.class);
+            when(transaction.getSender(signatureCache)).thenReturn(authorizerRskAddress);
             unionBridgeContractAddress = TestUtils.generateAddress("unionBridgeContractAddress");
         }
 
@@ -858,7 +872,7 @@ void getUnionBridgeLockingCap_beforeRskip502_shouldReturnNegativeOne() {
                 .withUnionBridgeSupport(
                     UnionBridgeSupportBuilder
                         .builder()
-                        .withConstants(constants.getUnionBridgeConstants())
+                        .withConstants(unionBridgeConstants)
                         .withActivations(lovell)
                         .build()
                 )
@@ -878,7 +892,7 @@ void getUnionBridgeLockingCap_whenNoLockingCapIsStored_shouldReturnInitialConsta
             Coin actualUnionBridgeLockingCap = bridgeSupport.getUnionBridgeLockingCap();
 
             // assert
-            Coin expectedLockingCap = constants.getUnionBridgeConstants().getInitialLockingCap();
+            Coin expectedLockingCap = unionBridgeConstants.getInitialLockingCap();
             assertEquals(expectedLockingCap, actualUnionBridgeLockingCap);
         }
 
@@ -907,6 +921,39 @@ void getUnionBridgeLockingCap_whenStoredLockingCap_shouldReturnStoredLockingCap(
             assertEquals(storedLockingCap, actualUnionBridgeLockingCap);
         }
 
+        @ParameterizedTest
+        @MethodSource("increaseUnionBridgeLockingCapResponseCodeProvider")
+        void increaseUnionBridgeLockingCap_shouldReturnResultedResponseCode(UnionResponseCode expectedUnionResponseCode) {
+            // arrange
+            unionBridgeSupport = mock(UnionBridgeSupport.class);
+            when(unionBridgeSupport.increaseLockingCap(any(),
+                any())).thenReturn(
+                expectedUnionResponseCode
+            );
+            bridgeSupport = bridgeSupportBuilder
+                .withUnionBridgeSupport(unionBridgeSupport)
+                .build();
+
+            Coin initialLockingCap = unionBridgeConstants.getInitialLockingCap();
+            Coin newLockingCap = initialLockingCap.multiply(unionBridgeConstants.getLockingCapIncrementsMultiplier());
+
+            // act
+            UnionResponseCode actualResult = bridgeSupport.increaseUnionBridgeLockingCap(
+                transaction, newLockingCap);
+
+            // assert
+            assertEquals(expectedUnionResponseCode, actualResult);
+            verify(unionBridgeSupport).increaseLockingCap(transaction, newLockingCap);
+        }
+
+        private static Stream<Arguments> increaseUnionBridgeLockingCapResponseCodeProvider() {
+            return Stream.of(
+                Arguments.of(UnionResponseCode.SUCCESS),
+                Arguments.of(UnionResponseCode.INVALID_VALUE),
+                Arguments.of(UnionResponseCode.UNAUTHORIZED_CALLER)
+            );
+        }
+
         @Test
         void save() {
             // arrange


Reviews:
user: login: jeremy-then
body: LGTM.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T14:36:24Z
user: login: marcos-iov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T20:11:16Z
user: login: nathanieliov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T13:42:53Z
user: login: nathanieliov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T13:43:00Z
user: login: nathanieliov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T13:43:17Z
user: login: marcos-iov
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T14:43:59Z

Review comments:
diff_hunk: @@ -1496,7 +1496,7 @@ public int setUnionBridgeContractAddressForTestnet(Object[] args) {
     public long getUnionBridgeLockingCap(Object[] args) {
         logger.trace("getUnionBridgeLockingCap");
 
-        return bridgeSupport.getUnionBridgeLockingCap().getValue();
+        return bridgeSupport.getUnionBridgeLockingCap().orElse(Coin.NEGATIVE_SATOSHI).getValue();
path: rskj-core/src/main/java/co/rsk/peg/Bridge.java
user: login: marcos-iov
body: Wasn't this resolved in https://github.com/rsksmart/rskj/pull/3107?
created_at: 2025-05-26T16:40:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -851,14 +865,14 @@ private static Stream<Arguments> unionResponseCodeProvider() {
         }
 
         @Test
-        void getUnionBridgeLockingCap_beforeRskip502_shouldReturnNegativeOne() {
+        void getUnionBridgeLockingCap_beforeRskip502_shouldReturnEmpty() {
path: rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
user: login: marcos-iov
body: empty? I thought it was no longer Optional
created_at: 2025-05-26T20:10:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -907,6 +921,39 @@ void getUnionBridgeLockingCap_whenStoredLockingCap_shouldReturnStoredLockingCap(
             assertEquals(storedLockingCap, actualUnionBridgeLockingCap);
         }
 
+        @ParameterizedTest
+        @MethodSource("increaseUnionBridgeLockingCapResponseCodeProvider")
+        void increaseUnionBridgeLockingCap_shouldReturnResultedResponseCode(UnionResponseCode expectedUnionResponseCode) {
+            // arrange
+            unionBridgeSupport = mock(UnionBridgeSupport.class);
+            when(unionBridgeSupport.increaseLockingCap(any(),
+                any())).thenReturn(
+                expectedUnionResponseCode
+            );
+            bridgeSupport = bridgeSupportBuilder
+                .withUnionBridgeSupport(unionBridgeSupport)
+                .build();
+
+            Coin initialLockingCap = unionBridgeConstants.getInitialLockingCap();
+            Coin newLockingCap = initialLockingCap.multiply(unionBridgeConstants.getLockingCapIncrementsMultiplier()).minus(Coin.SATOSHI);
path: rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
user: login: marcos-iov
body: minus again?
created_at: 2025-05-26T20:10:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -907,6 +921,39 @@ void getUnionBridgeLockingCap_whenStoredLockingCap_shouldReturnStoredLockingCap(
             assertEquals(storedLockingCap, actualUnionBridgeLockingCap);
         }
 
+        @ParameterizedTest
+        @MethodSource("increaseUnionBridgeLockingCapResponseCodeProvider")
+        void increaseUnionBridgeLockingCap_shouldReturnResultedResponseCode(UnionResponseCode expectedUnionResponseCode) {
+            // arrange
+            unionBridgeSupport = mock(UnionBridgeSupport.class);
+            when(unionBridgeSupport.increaseLockingCap(any(),
+                any())).thenReturn(
+                expectedUnionResponseCode
+            );
+            bridgeSupport = bridgeSupportBuilder
+                .withUnionBridgeSupport(unionBridgeSupport)
+                .build();
+
+            Coin initialLockingCap = unionBridgeConstants.getInitialLockingCap();
+            Coin newLockingCap = initialLockingCap.multiply(unionBridgeConstants.getLockingCapIncrementsMultiplier()).minus(Coin.SATOSHI);
path: rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
user: login: nathanieliov
body: Fixed
created_at: 2025-05-27T13:42:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -851,14 +865,14 @@ private static Stream<Arguments> unionResponseCodeProvider() {
         }
 
         @Test
-        void getUnionBridgeLockingCap_beforeRskip502_shouldReturnNegativeOne() {
+        void getUnionBridgeLockingCap_beforeRskip502_shouldReturnEmpty() {
path: rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
user: login: nathanieliov
body: Renamed
created_at: 2025-05-27T13:43:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1496,7 +1496,7 @@ public int setUnionBridgeContractAddressForTestnet(Object[] args) {
     public long getUnionBridgeLockingCap(Object[] args) {
         logger.trace("getUnionBridgeLockingCap");
 
-        return bridgeSupport.getUnionBridgeLockingCap().getValue();
+        return bridgeSupport.getUnionBridgeLockingCap().orElse(Coin.NEGATIVE_SATOSHI).getValue();
path: rskj-core/src/main/java/co/rsk/peg/Bridge.java
user: login: nathanieliov
body: Fixed
created_at: 2025-05-27T13:43:17Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-08T11:57:40Z
body: <h1>Dependency Review</h1>
✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.<h2>OpenSSF Scorecard</h2>
<table><tr><th>Package</th><th>Version</th><th>Score</th><th>Details</th></tr>
</table><h2>Scanned Files</h2>
<ul>


<!-- dependency-review-pr-comment-marker -->
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-27T13:57:10Z
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=rskj&pullRequest=3117) **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=rskj&pullRequest=3117&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=rskj&pullRequest=3117&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=rskj&pullRequest=3117&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=rskj&pullRequest=3117&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=rskj&pullRequest=3117&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=rskj&pullRequest=3117)


author_association: NONE