Skip to content

Commit 043c6ea

Browse files
authored
feat: Change port binding to be limited to only one module (#382)
1 parent 75b4348 commit 043c6ea

File tree

5 files changed

+39
-37
lines changed

5 files changed

+39
-37
lines changed

contracts/javascore/ibc/src/main/java/ibc/ics05/port/ModuleManager.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public void bindPort(String portId, Address moduleAddress) {
2222
* lookupModuleByPort will return the IBCModule along with the capability associated with a given portID
2323
*/
2424
public IIBCModuleScoreInterface lookupModuleByPort(String portId) {
25-
ArrayDB<Address> modules = lookupModules(portCapabilityPath(portId));
26-
return new IIBCModuleScoreInterface(modules.get(0));
25+
Address module = lookupModules(portCapabilityPath(portId));
26+
return new IIBCModuleScoreInterface(module);
2727

2828
}
2929

@@ -32,8 +32,8 @@ public IIBCModuleScoreInterface lookupModuleByPort(String portId) {
3232
* defined by its portID and channelID
3333
*/
3434
public IIBCModuleScoreInterface lookupModuleByChannel(String portId, String channelId) {
35-
ArrayDB<Address> modules = lookupModules(channelCapabilityPath(portId, channelId));
36-
return new IIBCModuleScoreInterface(modules.get(0));
35+
Address module = lookupModules(channelCapabilityPath(portId, channelId));
36+
return new IIBCModuleScoreInterface(module);
3737
}
3838

3939
/**
@@ -66,6 +66,6 @@ public byte[] channelCapabilityPath(String portId, String channelId) {
6666
* lookupModule will return the IBCModule address bound to a given name. Currently, the function returns only one
6767
* module.
6868
*/
69-
public abstract ArrayDB<Address> lookupModules(byte[] name);
69+
public abstract Address lookupModules(byte[] name);
7070

7171
}

contracts/javascore/ibc/src/main/java/ibc/ics24/host/IBCHost.java

+8-21
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,9 @@ public class IBCHost extends IBCStore {
2121
*
2222
*/
2323
public void claimCapability(byte[] name, Address addr) {
24-
ArrayDB<Address> capability = capabilities.at(name);
25-
int capabilitiesCount = capability.size();
26-
if (capabilitiesCount == 0) {
27-
portIds.add(name);
28-
}
29-
for (int i = 0; i < capabilitiesCount; i++) {
30-
Context.require(!capability.get(i).equals(addr), TAG + "Capability already claimed");
31-
}
32-
capability.add(addr);
24+
Context.require(capabilities.get(name) == null, TAG + "Capability already claimed");
25+
portIds.add(name);
26+
capabilities.set(name, addr);
3327
}
3428

3529
/**
@@ -42,14 +36,7 @@ public void claimCapability(byte[] name, Address addr) {
4236
*/
4337
public boolean authenticateCapability(byte[] name) {
4438
Address caller = Context.getCaller();
45-
ArrayDB<Address> capability = capabilities.at(name);
46-
int capabilitiesCount = capability.size();
47-
for (int i = 0; i < capabilitiesCount; i++) {
48-
if (capability.get(i).equals(caller)) {
49-
return Boolean.TRUE;
50-
}
51-
}
52-
return Boolean.FALSE;
39+
return caller.equals(capabilities.get(name));
5340
}
5441

5542
/**
@@ -58,10 +45,10 @@ public boolean authenticateCapability(byte[] name) {
5845
* @param name Name of the capability
5946
* @return ArrayDB of addresses having the capability
6047
*/
61-
public ArrayDB<Address> lookupModules(byte[] name) {
62-
ArrayDB<Address> modules = capabilities.at(name);
63-
Context.require(modules.size() > 0, "Module not found");
64-
return modules;
48+
public Address lookupModules(byte[] name) {
49+
Address module = capabilities.get(name);
50+
Context.require(module != null, "Module not found");
51+
return module;
6552
}
6653

6754
/**

contracts/javascore/ibc/src/main/java/ibc/ics24/host/IBCStore.java

+3-10
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public abstract class IBCStore extends ModuleManager implements IIBCHost {
5656
public static final BranchDB<String, BranchDB<String, DictDB<BigInteger, Boolean>>> packetReceipts = Context
5757
.newBranchDB(PACKET_RECEIPTS, Boolean.class);
5858

59-
public static final BranchDB<byte[], ArrayDB<Address>> capabilities = Context.newBranchDB(CAPABILITIES, Address.class);
59+
public static final DictDB<byte[],Address> capabilities = Context.newDictDB(CAPABILITIES, Address.class);
6060
public static final ArrayDB<byte[]> portIds = Context.newArrayDB(PORT_IDS, byte[].class);
6161
// Host Parameters
6262
public static final VarDB<BigInteger> expectedTimePerBlock = Context.newVarDB(EXPECTED_TIME_PER_BLOCK, BigInteger.class);
@@ -120,15 +120,8 @@ public boolean getPacketReceipt(String portId, String channelId, BigInteger sequ
120120
}
121121

122122
@External(readonly = true)
123-
public String[] getCapability(byte[] name) {
124-
ArrayDB<Address> arrayDB = capabilities.at(name);
125-
final int size = arrayDB.size();
126-
String[] capability = new String[size];
127-
for (int i = 0; i < size; i++) {
128-
capability[i] = arrayDB.get(i).toString();
129-
}
130-
131-
return capability;
123+
public Address getCapability(byte[] name) {
124+
return capabilities.get(name);
132125
}
133126

134127
@External(readonly = true)

contracts/javascore/ibc/src/test/java/ibc/ics25/handler/IBCHandlerTest.java

+22
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static org.mockito.Mockito.verify;
1010

1111
import java.math.BigInteger;
12+
import java.util.List;
1213

1314
import org.junit.jupiter.api.BeforeEach;
1415
import org.junit.jupiter.api.Test;
@@ -17,6 +18,7 @@
1718
import com.iconloop.score.test.Account;
1819

1920
import ibc.icon.structs.messages.*;
21+
import score.Address;
2022
import test.proto.core.channel.ChannelOuterClass.Packet;
2123

2224
public class IBCHandlerTest extends IBCHandlerTestBase {
@@ -237,6 +239,26 @@ void handlerAdminPermissions() {
237239
assertOnlyCallableBy(owner, "setExpectedTimePerBlock", BigInteger.TWO);
238240
}
239241

242+
@Test
243+
@SuppressWarnings("unchecked")
244+
void bindPort() {
245+
// Arrange
246+
handler.invoke(owner, "bindPort", portId, module.getAddress());
247+
248+
// Act & Assert
249+
String expectedErrorMessage = "Capability already claimed";
250+
Executable alreadyClaimed = () -> handler.invoke(owner, "bindPort", portId, sm.createAccount().getAddress());
251+
AssertionError e = assertThrows(AssertionError.class, alreadyClaimed);
252+
assertTrue(e.getMessage().contains(expectedErrorMessage));
253+
254+
// Assert
255+
List<byte[]> ports = (List<byte[]>)handler.call("getBindPorts");
256+
Address portModule = (Address)handler.call("getCapability", ports.get(0));
257+
258+
assertEquals(1, ports.size());
259+
assertEquals(module.getAddress(), portModule);
260+
}
261+
240262
private void assertOnlyCallableBy(Account authorizedCaller, String method, Object... params) {
241263
Account nonOwner = sm.createAccount();
242264
String expectedErrorMessage = "Reverted(0): SenderNotScoreOwner: Sender=" + nonOwner.getAddress()

contracts/javascore/lib/src/main/java/ibc/icon/interfaces/IIBCHost.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public interface IIBCHost {
3939
boolean getPacketReceipt(String portId, String channelId, BigInteger sequence);
4040

4141
@External(readonly = true)
42-
String[] getCapability(byte[] name);
42+
Address getCapability(byte[] name);
4343

4444
@External(readonly = true)
4545
BigInteger getExpectedTimePerBlock();

0 commit comments

Comments
 (0)