Skip to content

Commit c1ac78f

Browse files
committed
feat: add ipniPeerId to PDPOffering in ServiceProviderRegistry
Closes: #226
1 parent 7e78964 commit c1ac78f

8 files changed

+214
-17
lines changed

service_contracts/src/ServiceProviderRegistry.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ contract ServiceProviderRegistry is
4747
/// @notice Maximum length for location field
4848
uint256 private constant MAX_LOCATION_LENGTH = 128;
4949

50+
/// @notice Maximum length for IPNI peer ID
51+
uint256 private constant MAX_IPNI_PEER_ID_LENGTH = 128;
52+
5053
/// @notice Burn actor address for burning FIL
5154
address public constant BURN_ACTOR = 0xff00000000000000000000000000000000000063;
5255

@@ -845,6 +848,7 @@ contract ServiceProviderRegistry is
845848
require(pdpOffering.minProvingPeriodInEpochs > 0, "Min proving period must be greater than 0");
846849
require(bytes(pdpOffering.location).length > 0, "Location cannot be empty");
847850
require(bytes(pdpOffering.location).length <= MAX_LOCATION_LENGTH, "Location too long");
851+
require(pdpOffering.ipniPeerId.length <= MAX_IPNI_PEER_ID_LENGTH, "IPNI peer ID too long");
848852
}
849853

850854
/// @notice Validate capability key-value pairs

service_contracts/src/ServiceProviderRegistryStorage.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ contract ServiceProviderRegistryStorage {
4444
uint256 minProvingPeriodInEpochs; // Minimum proving period in epochs
4545
string location; // Geographic location of the service provider
4646
IERC20 paymentTokenAddress; // Token contract for payment (IERC20(address(0)) for FIL)
47+
bytes ipniPeerId; // IPNI peer ID (max 128 bytes, can be empty)
4748
}
4849

4950
/// @notice Combined provider and product information for detailed queries

service_contracts/test/FilecoinWarmStorageService.t.sol

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ contract FilecoinWarmStorageServiceTest is Test {
165165
storagePricePerTibPerMonth: 1 ether,
166166
minProvingPeriodInEpochs: 2880,
167167
location: "US-Central",
168-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
168+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
169+
ipniPeerId: hex""
169170
})
170171
),
171172
new string[](0),
@@ -188,7 +189,8 @@ contract FilecoinWarmStorageServiceTest is Test {
188189
storagePricePerTibPerMonth: 1 ether,
189190
minProvingPeriodInEpochs: 2880,
190191
location: "US-Central",
191-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
192+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
193+
ipniPeerId: hex""
192194
})
193195
),
194196
new string[](0),
@@ -211,7 +213,8 @@ contract FilecoinWarmStorageServiceTest is Test {
211213
storagePricePerTibPerMonth: 1 ether,
212214
minProvingPeriodInEpochs: 2880,
213215
location: "US-Central",
214-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
216+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
217+
ipniPeerId: hex""
215218
})
216219
),
217220
new string[](0),
@@ -234,7 +237,8 @@ contract FilecoinWarmStorageServiceTest is Test {
234237
storagePricePerTibPerMonth: 1 ether,
235238
minProvingPeriodInEpochs: 2880,
236239
location: "US-Central",
237-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
240+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
241+
ipniPeerId: hex""
238242
})
239243
),
240244
new string[](0),

service_contracts/test/FilecoinWarmStorageServiceOwner.t.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ contract FilecoinWarmStorageServiceOwnerTest is Test {
149149
storagePricePerTibPerMonth: 5 * 10 ** 6, // 5 USDFC per TiB per month
150150
minProvingPeriodInEpochs: 2880,
151151
location: "US",
152-
paymentTokenAddress: IERC20(address(0))
152+
paymentTokenAddress: IERC20(address(0)),
153+
ipniPeerId: hex""
153154
})
154155
),
155156
capabilityKeys,

service_contracts/test/ProviderValidation.t.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ contract ProviderValidationTest is Test {
125125
storagePricePerTibPerMonth: 1 ether,
126126
minProvingPeriodInEpochs: 2880,
127127
location: "US-West",
128-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
128+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
129+
ipniPeerId: hex""
129130
})
130131
),
131132
new string[](0),
@@ -163,7 +164,8 @@ contract ProviderValidationTest is Test {
163164
storagePricePerTibPerMonth: 1 ether,
164165
minProvingPeriodInEpochs: 2880,
165166
location: "US-West",
166-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
167+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
168+
ipniPeerId: hex""
167169
})
168170
),
169171
new string[](0),

service_contracts/test/ServiceProviderRegistry.t.sol

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ contract ServiceProviderRegistryTest is Test {
6868
storagePricePerTibPerMonth: 500000000000000000, // 0.5 FIL per TiB per month
6969
minProvingPeriodInEpochs: 2880,
7070
location: "US-East",
71-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
71+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
72+
ipniPeerId: hex""
7273
});
7374

7475
// Encode PDP data
@@ -111,7 +112,8 @@ contract ServiceProviderRegistryTest is Test {
111112
storagePricePerTibPerMonth: 500000000000000000, // 0.5 FIL per TiB per month
112113
minProvingPeriodInEpochs: 2880,
113114
location: "US-East",
114-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
115+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
116+
ipniPeerId: hex""
115117
});
116118

117119
// Encode PDP data
@@ -182,7 +184,8 @@ contract ServiceProviderRegistryTest is Test {
182184
storagePricePerTibPerMonth: 500000000000000000, // 0.5 FIL per TiB per month
183185
minProvingPeriodInEpochs: 2880,
184186
location: "US-East",
185-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
187+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
188+
ipniPeerId: hex""
186189
});
187190

188191
bytes memory encodedData = abi.encode(pdpData);
@@ -224,7 +227,8 @@ contract ServiceProviderRegistryTest is Test {
224227
storagePricePerTibPerMonth: 500000000000000000,
225228
minProvingPeriodInEpochs: 2880,
226229
location: "US-East",
227-
paymentTokenAddress: IERC20(address(0))
230+
paymentTokenAddress: IERC20(address(0)),
231+
ipniPeerId: hex""
228232
});
229233

230234
bytes memory encodedData = abi.encode(pdpData);
@@ -259,7 +263,8 @@ contract ServiceProviderRegistryTest is Test {
259263
storagePricePerTibPerMonth: 750000000000000000, // 0.75 FIL per TiB per month
260264
minProvingPeriodInEpochs: 2880,
261265
location: "US-East",
262-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
266+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
267+
ipniPeerId: hex""
263268
});
264269

265270
bytes memory encodedData = abi.encode(pdpData);
@@ -323,7 +328,8 @@ contract ServiceProviderRegistryTest is Test {
323328
storagePricePerTibPerMonth: 500000000000000000, // 0.5 FIL per TiB per month
324329
minProvingPeriodInEpochs: 2880,
325330
location: "US-East",
326-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
331+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
332+
ipniPeerId: hex""
327333
});
328334

329335
// Encode PDP data
@@ -561,7 +567,8 @@ contract ServiceProviderRegistryTest is Test {
561567
storagePricePerTibPerMonth: 1000,
562568
minProvingPeriodInEpochs: 1,
563569
location: "US",
564-
paymentTokenAddress: IERC20(address(0))
570+
paymentTokenAddress: IERC20(address(0)),
571+
ipniPeerId: hex""
565572
});
566573
return abi.encode(pdpOffering);
567574
}

service_contracts/test/ServiceProviderRegistryFull.t.sol

Lines changed: 179 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ contract ServiceProviderRegistryFullTest is Test {
8282
storagePricePerTibPerMonth: 1000000000000000000, // 1 FIL per TiB per month
8383
minProvingPeriodInEpochs: 2880, // 1 day in epochs (30 second blocks)
8484
location: "North America",
85-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
85+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
86+
ipniPeerId: hex""
8687
});
8788

8889
updatedPDPData = ServiceProviderRegistryStorage.PDPOffering({
@@ -94,7 +95,8 @@ contract ServiceProviderRegistryFullTest is Test {
9495
storagePricePerTibPerMonth: 2000000000000000000, // 2 FIL per TiB per month
9596
minProvingPeriodInEpochs: 1440, // 12 hours in epochs
9697
location: "Europe",
97-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
98+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
99+
ipniPeerId: hex""
98100
});
99101

100102
// Encode PDP data
@@ -1804,4 +1806,179 @@ contract ServiceProviderRegistryFullTest is Test {
18041806
assertFalse(tierCleared, "Tier key should not exist after update");
18051807
assertEq(clearedTier, "", "Tier key should be cleared after update");
18061808
}
1809+
1810+
// ========== IPNI Peer ID Validation Tests ==========
1811+
1812+
function testRegisterWithEmptyIpniPeerId() public {
1813+
ServiceProviderRegistryStorage.PDPOffering memory validPDP = defaultPDPData;
1814+
validPDP.ipniPeerId = hex"";
1815+
bytes memory encodedPDP = abi.encode(validPDP);
1816+
string[] memory emptyKeys = new string[](0);
1817+
string[] memory emptyValues = new string[](0);
1818+
1819+
vm.prank(provider1);
1820+
uint256 providerId = registry.registerProvider{value: REGISTRATION_FEE}(
1821+
provider1,
1822+
"",
1823+
"Test provider",
1824+
ServiceProviderRegistryStorage.ProductType.PDP,
1825+
encodedPDP,
1826+
emptyKeys,
1827+
emptyValues
1828+
);
1829+
assertEq(providerId, 1, "Should succeed with empty ipniPeerId");
1830+
1831+
// Verify it was stored correctly
1832+
(ServiceProviderRegistryStorage.PDPOffering memory stored,,) = registry.getPDPService(providerId);
1833+
assertEq(stored.ipniPeerId.length, 0, "Empty IPNI peer ID should be stored");
1834+
}
1835+
1836+
function testRegisterWithMaxLengthIpniPeerId() public {
1837+
bytes memory maxPeerId = new bytes(128);
1838+
for (uint256 i = 0; i < 128; i++) {
1839+
maxPeerId[i] = 0xFF;
1840+
}
1841+
1842+
ServiceProviderRegistryStorage.PDPOffering memory validPDP = defaultPDPData;
1843+
validPDP.ipniPeerId = maxPeerId;
1844+
bytes memory encodedPDP = abi.encode(validPDP);
1845+
string[] memory emptyKeys = new string[](0);
1846+
string[] memory emptyValues = new string[](0);
1847+
1848+
vm.prank(provider1);
1849+
uint256 providerId = registry.registerProvider{value: REGISTRATION_FEE}(
1850+
provider1,
1851+
"",
1852+
"Test provider",
1853+
ServiceProviderRegistryStorage.ProductType.PDP,
1854+
encodedPDP,
1855+
emptyKeys,
1856+
emptyValues
1857+
);
1858+
assertEq(providerId, 1, "Should succeed with 128-byte ipniPeerId");
1859+
1860+
// Verify it was stored correctly
1861+
(ServiceProviderRegistryStorage.PDPOffering memory stored,,) = registry.getPDPService(providerId);
1862+
assertEq(stored.ipniPeerId.length, 128, "128-byte IPNI peer ID should be stored");
1863+
assertEq(stored.ipniPeerId, maxPeerId, "IPNI peer ID should match");
1864+
}
1865+
1866+
function testRegisterWithTooLongIpniPeerId() public {
1867+
bytes memory longPeerId = new bytes(129);
1868+
for (uint256 i = 0; i < 129; i++) {
1869+
longPeerId[i] = 0xFF;
1870+
}
1871+
1872+
ServiceProviderRegistryStorage.PDPOffering memory invalidPDP = defaultPDPData;
1873+
invalidPDP.ipniPeerId = longPeerId;
1874+
bytes memory encodedInvalidPDP = abi.encode(invalidPDP);
1875+
string[] memory emptyKeys = new string[](0);
1876+
string[] memory emptyValues = new string[](0);
1877+
1878+
vm.prank(provider1);
1879+
vm.expectRevert("IPNI peer ID too long");
1880+
registry.registerProvider{value: REGISTRATION_FEE}(
1881+
provider1,
1882+
"",
1883+
"Test provider",
1884+
ServiceProviderRegistryStorage.ProductType.PDP,
1885+
encodedInvalidPDP,
1886+
emptyKeys,
1887+
emptyValues
1888+
);
1889+
}
1890+
1891+
function testRegisterWithRealisticIpniPeerId() public {
1892+
// Typical libp2p peer ID is ~38 bytes (multihash of public key)
1893+
// Format: 0x1220<32-byte sha256 hash> for a total of 34 bytes
1894+
bytes memory realisticPeerId = hex"12205f8bb7e5e0e8e5f8e5e0e8e5f8e5e0e8e5f8e5e0e8e5f8e5e0e8e5f8abcdef01";
1895+
1896+
ServiceProviderRegistryStorage.PDPOffering memory validPDP = defaultPDPData;
1897+
validPDP.ipniPeerId = realisticPeerId;
1898+
bytes memory encodedPDP = abi.encode(validPDP);
1899+
string[] memory emptyKeys = new string[](0);
1900+
string[] memory emptyValues = new string[](0);
1901+
1902+
vm.prank(provider1);
1903+
uint256 providerId = registry.registerProvider{value: REGISTRATION_FEE}(
1904+
provider1,
1905+
"",
1906+
"Test provider",
1907+
ServiceProviderRegistryStorage.ProductType.PDP,
1908+
encodedPDP,
1909+
emptyKeys,
1910+
emptyValues
1911+
);
1912+
1913+
// Verify it was stored correctly
1914+
(ServiceProviderRegistryStorage.PDPOffering memory stored,,) = registry.getPDPService(providerId);
1915+
assertEq(stored.ipniPeerId, realisticPeerId, "IPNI peer ID should be stored correctly");
1916+
assertEq(stored.ipniPeerId.length, 34, "Realistic IPNI peer ID should be 34 bytes");
1917+
}
1918+
1919+
function testUpdateIpniPeerId() public {
1920+
// Register with empty IPNI peer ID
1921+
string[] memory emptyKeys = new string[](0);
1922+
string[] memory emptyValues = new string[](0);
1923+
1924+
vm.prank(provider1);
1925+
uint256 providerId = registry.registerProvider{value: REGISTRATION_FEE}(
1926+
provider1,
1927+
"",
1928+
"Test provider",
1929+
ServiceProviderRegistryStorage.ProductType.PDP,
1930+
encodedDefaultPDPData,
1931+
emptyKeys,
1932+
emptyValues
1933+
);
1934+
1935+
// Verify initial state
1936+
(ServiceProviderRegistryStorage.PDPOffering memory initialStored,,) = registry.getPDPService(providerId);
1937+
assertEq(initialStored.ipniPeerId.length, 0, "Initial IPNI peer ID should be empty");
1938+
1939+
// Update with a peer ID
1940+
bytes memory newPeerId = hex"12205f8bb7e5e0e8e5f8e5e0e8e5f8e5e0e8e5f8e5e0e8e5f8e5e0e8e5f8abcdef01";
1941+
ServiceProviderRegistryStorage.PDPOffering memory updatedData = updatedPDPData;
1942+
updatedData.ipniPeerId = newPeerId;
1943+
bytes memory encodedUpdatedData = abi.encode(updatedData);
1944+
1945+
vm.prank(provider1);
1946+
registry.updateProduct(ServiceProviderRegistryStorage.ProductType.PDP, encodedUpdatedData, emptyKeys, emptyValues);
1947+
1948+
// Verify update
1949+
(ServiceProviderRegistryStorage.PDPOffering memory updatedStored,,) = registry.getPDPService(providerId);
1950+
assertEq(updatedStored.ipniPeerId, newPeerId, "IPNI peer ID should be updated");
1951+
assertEq(updatedStored.ipniPeerId.length, 34, "Updated IPNI peer ID should be 34 bytes");
1952+
}
1953+
1954+
function testUpdateWithTooLongIpniPeerId() public {
1955+
// Register first
1956+
string[] memory emptyKeys = new string[](0);
1957+
string[] memory emptyValues = new string[](0);
1958+
1959+
vm.prank(provider1);
1960+
registry.registerProvider{value: REGISTRATION_FEE}(
1961+
provider1,
1962+
"",
1963+
"Test provider",
1964+
ServiceProviderRegistryStorage.ProductType.PDP,
1965+
encodedDefaultPDPData,
1966+
emptyKeys,
1967+
emptyValues
1968+
);
1969+
1970+
// Try to update with too long peer ID
1971+
bytes memory longPeerId = new bytes(129);
1972+
for (uint256 i = 0; i < 129; i++) {
1973+
longPeerId[i] = 0xAB;
1974+
}
1975+
1976+
ServiceProviderRegistryStorage.PDPOffering memory invalidData = updatedPDPData;
1977+
invalidData.ipniPeerId = longPeerId;
1978+
bytes memory encodedInvalidData = abi.encode(invalidData);
1979+
1980+
vm.prank(provider1);
1981+
vm.expectRevert("IPNI peer ID too long");
1982+
registry.updateProduct(ServiceProviderRegistryStorage.ProductType.PDP, encodedInvalidData, emptyKeys, emptyValues);
1983+
}
18071984
}

service_contracts/test/ServiceProviderRegistryPagination.t.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ contract ServiceProviderRegistryPaginationTest is Test {
4848
storagePricePerTibPerMonth: 100,
4949
minProvingPeriodInEpochs: 10,
5050
location: "US-WEST",
51-
paymentTokenAddress: IERC20(address(0))
51+
paymentTokenAddress: IERC20(address(0)),
52+
ipniPeerId: hex""
5253
});
5354

5455
encodedDefaultPDPData = registry.encodePDPOffering(defaultPDPData);

0 commit comments

Comments
 (0)