Skip to content

Commit 32ec6ba

Browse files
committed
feat: add ipniPeerId to PDPOffering in ServiceProviderRegistry
Closes: #226
1 parent e52706b commit 32ec6ba

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

@@ -821,6 +824,7 @@ contract ServiceProviderRegistry is
821824
require(pdpOffering.minProvingPeriodInEpochs > 0, "Min proving period must be greater than 0");
822825
require(bytes(pdpOffering.location).length > 0, "Location cannot be empty");
823826
require(bytes(pdpOffering.location).length <= MAX_LOCATION_LENGTH, "Location too long");
827+
require(pdpOffering.ipniPeerId.length <= MAX_IPNI_PEER_ID_LENGTH, "IPNI peer ID too long");
824828
}
825829

826830
/// @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
@@ -149,7 +149,8 @@ contract FilecoinWarmStorageServiceTest is Test {
149149
storagePricePerTibPerMonth: 1 ether,
150150
minProvingPeriodInEpochs: 2880,
151151
location: "US-Central",
152-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
152+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
153+
ipniPeerId: hex""
153154
})
154155
),
155156
new string[](0),
@@ -172,7 +173,8 @@ contract FilecoinWarmStorageServiceTest is Test {
172173
storagePricePerTibPerMonth: 1 ether,
173174
minProvingPeriodInEpochs: 2880,
174175
location: "US-Central",
175-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
176+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
177+
ipniPeerId: hex""
176178
})
177179
),
178180
new string[](0),
@@ -195,7 +197,8 @@ contract FilecoinWarmStorageServiceTest is Test {
195197
storagePricePerTibPerMonth: 1 ether,
196198
minProvingPeriodInEpochs: 2880,
197199
location: "US-Central",
198-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
200+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
201+
ipniPeerId: hex""
199202
})
200203
),
201204
new string[](0),
@@ -218,7 +221,8 @@ contract FilecoinWarmStorageServiceTest is Test {
218221
storagePricePerTibPerMonth: 1 ether,
219222
minProvingPeriodInEpochs: 2880,
220223
location: "US-Central",
221-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
224+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
225+
ipniPeerId: hex""
222226
})
223227
),
224228
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
@@ -61,7 +61,8 @@ contract ServiceProviderRegistryFullTest is Test {
6161
storagePricePerTibPerMonth: 1000000000000000000, // 1 FIL per TiB per month
6262
minProvingPeriodInEpochs: 2880, // 1 day in epochs (30 second blocks)
6363
location: "North America",
64-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
64+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
65+
ipniPeerId: hex""
6566
});
6667

6768
updatedPDPData = ServiceProviderRegistryStorage.PDPOffering({
@@ -73,7 +74,8 @@ contract ServiceProviderRegistryFullTest is Test {
7374
storagePricePerTibPerMonth: 2000000000000000000, // 2 FIL per TiB per month
7475
minProvingPeriodInEpochs: 1440, // 12 hours in epochs
7576
location: "Europe",
76-
paymentTokenAddress: IERC20(address(0)) // Payment in FIL
77+
paymentTokenAddress: IERC20(address(0)), // Payment in FIL
78+
ipniPeerId: hex""
7779
});
7880

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

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 = abi.encode(defaultPDPData);

0 commit comments

Comments
 (0)