-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #288 from hyperledger-labs/fix-port-identifier-val…
…idation Fix port identifier validation and add tests Signed-off-by: Jun Kimura <[email protected]>
- Loading branch information
Showing
5 changed files
with
143 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.20; | ||
|
||
library IBCHostLib { | ||
/** | ||
* @dev validatePortIdentifier validates a port identifier string | ||
* check if the string consist of characters in one of the following categories only: | ||
* - Alphanumeric | ||
* - `.`, `_`, `+`, `-`, `#` | ||
* - `[`, `]`, `<`, `>` | ||
* | ||
* The validation is based on the ibc-go implementation: | ||
* https://github.com/cosmos/ibc-go/blob/b0ed0b412ea75e66091cc02746c95f9e6cf4445d/modules/core/24-host/validate.go#L86 | ||
*/ | ||
function validatePortIdentifier(bytes memory portId) internal pure returns (bool) { | ||
uint256 portIdLength = portId.length; | ||
if (portIdLength < 2 || portIdLength > 128) { | ||
return false; | ||
} | ||
unchecked { | ||
for (uint256 i = 0; i < portIdLength; i++) { | ||
uint256 c = uint256(uint8(portId[i])); | ||
if ( | ||
// a-z | ||
!(c >= 0x61 && c <= 0x7A) | ||
// 0-9 | ||
&& !(c >= 0x30 && c <= 0x39) | ||
// A-Z | ||
&& !(c >= 0x41 && c <= 0x5A) | ||
// ".", "_", "+", "-" | ||
&& !(c == 0x2E || c == 0x5F || c == 0x2B || c == 0x2D) | ||
// "#", "[", "]", "<", ">" | ||
&& !(c == 0x23 || c == 0x5B || c == 0x5D || c == 0x3C || c == 0x3E) | ||
) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import "./helpers/IBCTestHelper.t.sol"; | ||
import {IBCHostLib} from "../../../contracts/core/24-host/IBCHostLib.sol"; | ||
|
||
contract ICS24HostTest is IBCTestHelper { | ||
struct ValidatePortIdentifierTestCase { | ||
string m; | ||
string id; | ||
bool expPass; | ||
} | ||
|
||
function testValidatePortIdentifier() public { | ||
// The following test cases are based on the test cases of ibc-go: | ||
// https://github.com/cosmos/ibc-go/blob/e443a88e0f2c84c131c5a1de47945a5733ff9c91/modules/core/24-host/validate_test.go#L57 | ||
ValidatePortIdentifierTestCase[] memory testCases = new ValidatePortIdentifierTestCase[](12); | ||
testCases[0] = ValidatePortIdentifierTestCase({ | ||
m: "valid lowercase", | ||
id: "transfer", | ||
expPass: true | ||
}); | ||
testCases[1] = ValidatePortIdentifierTestCase({ | ||
m: "valid id special chars", | ||
id: "._+-#[]<>._+-#[]<>", | ||
expPass: true | ||
}); | ||
testCases[2] = ValidatePortIdentifierTestCase({ | ||
m: "valid id lower and special chars", | ||
id: "lower._+-#[]<>", | ||
expPass: true | ||
}); | ||
testCases[3] = ValidatePortIdentifierTestCase({ | ||
m: "numeric id", | ||
id: "1234567890", | ||
expPass: true | ||
}); | ||
testCases[4] = ValidatePortIdentifierTestCase({ | ||
m: "uppercase id", | ||
id: "NOTLOWERCASE", | ||
expPass: true | ||
}); | ||
testCases[5] = ValidatePortIdentifierTestCase({ | ||
m: "numeric id", | ||
id: "1234567890", | ||
expPass: true | ||
}); | ||
testCases[6] = ValidatePortIdentifierTestCase({ | ||
m: "blank id", | ||
id: " ", | ||
expPass: false | ||
}); | ||
testCases[7] = ValidatePortIdentifierTestCase({ | ||
m: "id length out of range", | ||
id: "1", | ||
expPass: false | ||
}); | ||
testCases[8] = ValidatePortIdentifierTestCase({ | ||
m: "id is too long", | ||
id: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis eros neque, ultricies vel ligula ac, convallis porttitor elit. Maecenas tincidunt turpis elit, vel faucibus nisl pellentesque sodales", | ||
expPass: false | ||
}); | ||
testCases[9] = ValidatePortIdentifierTestCase({ | ||
m: "path-like id", | ||
id: "lower/case/id", | ||
expPass: false | ||
}); | ||
testCases[10] = ValidatePortIdentifierTestCase({ | ||
m: "invalid id", | ||
id: "(clientid)", | ||
expPass: false | ||
}); | ||
testCases[11] = ValidatePortIdentifierTestCase({ | ||
m: "empty string", | ||
id: "", | ||
expPass: false | ||
}); | ||
|
||
for (uint i = 0; i < testCases.length; i++) { | ||
ValidatePortIdentifierTestCase memory tc = testCases[i]; | ||
bool res = IBCHostLib.validatePortIdentifier(bytes(tc.id)); | ||
if (tc.expPass) { | ||
require(res, tc.m); | ||
} else { | ||
require(!res, tc.m); | ||
} | ||
} | ||
} | ||
} |