Skip to content

Commit dc2c8ab

Browse files
authored
feat!: Nonsequenial clientDataSetId (#265)
Reviewer @rvagg We want to free this bottleneck so that it is possible to create more datasets simultaneously. I take advantage of the assumption that dataSetId cannot be zero to use a mapping to make the nonces nonsequential. #### Changes * change clientDataSetId to be non-sequential by converting id counter into mapping * fix tests
1 parent 5701658 commit dc2c8ab

13 files changed

+228
-86
lines changed

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
2626
8. FilecoinWarmStorageService Proxy: [0x468342072e0dc86AFFBe15519bc5B1A1aa86e4dc](https://calibration.filfox.info/en/address/0x468342072e0dc86AFFBe15519bc5B1A1aa86e4dc)
2727
9. FilecoinWarmStorageServiceStateView: [0xE4587AAdB97d7B8197aa08E432bAD0D9Cfe3a17F](https://calibration.filfox.info/en/address/0xE4587AAdB97d7B8197aa08E432bAD0D9Cfe3a17F)
2828

29-
Configuration:
29+
Configuration:
3030
- USDFC Token: [0xb3042734b608a1B16e9e86B374A3f3e389B4cDf0](https://calibration.filfox.info/en/address/0xb3042734b608a1B16e9e86B374A3f3e389B4cDf0)
3131
- FILBEAM_BENEFICIARY_ADDRESS: [0x1D60d2F5960Af6341e842C539985FA297E10d6eA](https://calibration.filfox.info/en/address/0x1D60d2F5960Af6341e842C539985FA297E10d6eA)
3232
- FILBEAM_CONTROLLER_ADDRESS: [0x5f7E5E2A756430EdeE781FF6e6F7954254Ef629A](https://calibration.filfox.info/en/address/0x5f7E5E2A756430EdeE781FF6e6F7954254Ef629A)
@@ -62,7 +62,7 @@ Configuration:
6262
8. FilecoinWarmStorageService Proxy: [0x9ef4cAb0aD0D19b8Df28791Df80b29bC784bE91b](https://calibration.filfox.info/en/address/0x9ef4cAb0aD0D19b8Df28791Df80b29bC784bE91b)
6363
9. FilecoinWarmStorageServiceStateView: [0x7175a72479e2B0050ed310f1a49a517C03573547](https://calibration.filfox.info/en/address/0x7175a72479e2B0050ed310f1a49a517C03573547)
6464

65-
Configuration:
65+
Configuration:
6666
- USDFC Token: [0xb3042734b608a1B16e9e86B374A3f3e389B4cDf0](https://calibration.filfox.info/en/address/0xb3042734b608a1B16e9e86B374A3f3e389B4cDf0)
6767
- FILBEAM_BENEFICIARY_ADDRESS: [0x1D60d2F5960Af6341e842C539985FA297E10d6eA](https://calibration.filfox.info/en/address/0x1D60d2F5960Af6341e842C539985FA297E10d6eA)
6868
- FILBEAM_CONTROLLER_ADDRESS: [0x5f7E5E2A756430EdeE781FF6e6F7954254Ef629A](https://calibration.filfox.info/en/address/0x5f7E5E2A756430EdeE781FF6e6F7954254Ef629A)
@@ -197,4 +197,4 @@ The underlying functionality remains unchanged; this release only updates termin
197197

198198
[Unreleased]: https://github.com/filozone/filecoin-services/compare/v0.2.0...HEAD
199199
[0.2.0]: https://github.com/filozone/filecoin-services/releases/tag/v0.2.0
200-
[0.1.0]: https://github.com/filozone/filecoin-services/releases/tag/v0.1.0
200+
[0.1.0]: https://github.com/filozone/filecoin-services/releases/tag/v0.1.0

service_contracts/abi/FilecoinWarmStorageService.abi.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,17 @@
16021602
}
16031603
]
16041604
},
1605+
{
1606+
"type": "error",
1607+
"name": "ClientDataSetAlreadyRegistered",
1608+
"inputs": [
1609+
{
1610+
"name": "clientDataSetId",
1611+
"type": "uint256",
1612+
"internalType": "uint256"
1613+
}
1614+
]
1615+
},
16051616
{
16061617
"type": "error",
16071618
"name": "CommissionExceedsMaximum",

service_contracts/abi/FilecoinWarmStorageServiceStateLibrary.abi.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
{
2222
"type": "function",
23-
"name": "clientDataSetIDs",
23+
"name": "clientDataSetIds",
2424
"inputs": [
2525
{
2626
"name": "service",
@@ -31,6 +31,11 @@
3131
"name": "payer",
3232
"type": "address",
3333
"internalType": "address"
34+
},
35+
{
36+
"name": "clientDataSetId",
37+
"type": "uint256",
38+
"internalType": "uint256"
3439
}
3540
],
3641
"outputs": [

service_contracts/abi/FilecoinWarmStorageServiceStateView.abi.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@
2525
},
2626
{
2727
"type": "function",
28-
"name": "clientDataSetIDs",
28+
"name": "clientDataSetIds",
2929
"inputs": [
3030
{
3131
"name": "payer",
3232
"type": "address",
3333
"internalType": "address"
34+
},
35+
{
36+
"name": "clientDataSetId",
37+
"type": "uint256",
38+
"internalType": "uint256"
3439
}
3540
],
3641
"outputs": [

service_contracts/src/Errors.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ library Errors {
9494
/// @param dataSetId The ID of the data set
9595
error DataSetNotRegistered(uint256 dataSetId);
9696

97+
/// @notice This client dataset ID has already been registered to a dataset
98+
/// @param clientDataSetId The attempted but existing ID
99+
error ClientDataSetAlreadyRegistered(uint256 clientDataSetId);
100+
97101
/// @notice Only one proof of possession allowed per proving period
98102
/// @param dataSetId The data set ID
99103
error ProofAlreadySubmitted(uint256 dataSetId);

service_contracts/src/FilecoinWarmStorageService.sol

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,16 @@ contract FilecoinWarmStorageService is
137137

138138
// Decode structure for data set creation extra data
139139
struct DataSetCreateData {
140+
// The address of the payer who should have signed the message
140141
address payer;
142+
// the unique ID for the client's data set
143+
uint256 clientDataSetId;
144+
// Array of metadata keys
141145
string[] metadataKeys;
146+
// Array of metadata values
142147
string[] metadataValues;
143-
bytes signature; // Authentication signature
148+
// The signature bytes (v, r, s)
149+
bytes signature;
144150
}
145151

146152
// Structure for service pricing information
@@ -253,7 +259,7 @@ contract FilecoinWarmStorageService is
253259
mapping(uint256 dataSetId => bool) private provenThisPeriod;
254260

255261
mapping(uint256 dataSetId => DataSetInfo) private dataSetInfo;
256-
mapping(address payer => uint256) private clientDataSetIds;
262+
mapping(address payer => mapping(uint256 clientDataSetId => uint256)) private clientDataSetIds;
257263
mapping(address payer => uint256[]) private clientDataSets;
258264
mapping(uint256 pdpRailId => uint256) private railToDataSet;
259265

@@ -535,26 +541,23 @@ contract FilecoinWarmStorageService is
535541

536542
address payee = serviceProviderRegistry.getProviderPayee(providerId);
537543

538-
uint256 clientDataSetId = clientDataSetIds[createData.payer]++;
544+
require(
545+
clientDataSetIds[createData.payer][createData.clientDataSetId] == 0,
546+
Errors.ClientDataSetAlreadyRegistered(createData.clientDataSetId)
547+
);
548+
clientDataSetIds[createData.payer][createData.clientDataSetId] = dataSetId;
539549
clientDataSets[createData.payer].push(dataSetId);
540550

541551
// Verify the client's signature
542-
verifyCreateDataSetSignature(
543-
createData.payer,
544-
clientDataSetId,
545-
payee,
546-
createData.metadataKeys,
547-
createData.metadataValues,
548-
createData.signature
549-
);
552+
verifyCreateDataSetSignature(payee, createData);
550553

551554
// Initialize the DataSetInfo struct
552555
DataSetInfo storage info = dataSetInfo[dataSetId];
553556
info.payer = createData.payer;
554557
info.payee = payee; // Using payee address from registry
555558
info.serviceProvider = serviceProvider; // Set the service provider
556559
info.commissionBps = serviceCommissionBps;
557-
info.clientDataSetId = clientDataSetId;
560+
info.clientDataSetId = createData.clientDataSetId;
558561
info.providerId = providerId;
559562

560563
// Store each metadata key-value entry for this data set
@@ -679,6 +682,8 @@ contract FilecoinWarmStorageService is
679682
Errors.PaymentRailsNotFinalized(dataSetId, info.pdpEndEpoch)
680683
);
681684

685+
// NOTE keep clientDataSetIds[payer][clientDataSetId] to prevent replay
686+
682687
// Remove from client's dataset list
683688
uint256[] storage clientDataSetList = clientDataSets[payer];
684689
for (uint256 i = 0; i < clientDataSetList.length; i++) {
@@ -1298,10 +1303,16 @@ contract FilecoinWarmStorageService is
12981303
* @return decoded The decoded DataSetCreateData struct
12991304
*/
13001305
function decodeDataSetCreateData(bytes calldata extraData) internal pure returns (DataSetCreateData memory) {
1301-
(address payer, string[] memory keys, string[] memory values, bytes memory signature) =
1302-
abi.decode(extraData, (address, string[], string[], bytes));
1303-
1304-
return DataSetCreateData({payer: payer, metadataKeys: keys, metadataValues: values, signature: signature});
1306+
(address payer, uint256 clientDataSetId, string[] memory keys, string[] memory values, bytes memory signature) =
1307+
abi.decode(extraData, (address, uint256, string[], string[], bytes));
1308+
1309+
return DataSetCreateData({
1310+
payer: payer,
1311+
clientDataSetId: clientDataSetId,
1312+
metadataKeys: keys,
1313+
metadataValues: values,
1314+
signature: signature
1315+
});
13051316
}
13061317

13071318
/**
@@ -1443,37 +1454,28 @@ contract FilecoinWarmStorageService is
14431454

14441455
/**
14451456
* @notice Verifies a signature for the CreateDataSet operation
1446-
* @param payer The address of the payer who should have signed the message
1447-
* @param clientDataSetId The unique ID for the client's data set
1457+
* @param createData The decoded DataSetCreateData used to build the signature
14481458
* @param payee The service provider address
1449-
* @param metadataKeys Array of metadata keys
1450-
* @param metadataValues Array of metadata values
1451-
* @param signature The signature bytes (v, r, s)
14521459
*/
1453-
function verifyCreateDataSetSignature(
1454-
address payer,
1455-
uint256 clientDataSetId,
1456-
address payee,
1457-
string[] memory metadataKeys,
1458-
string[] memory metadataValues,
1459-
bytes memory signature
1460-
) internal view {
1460+
function verifyCreateDataSetSignature(address payee, DataSetCreateData memory createData) internal view {
14611461
// Hash the metadata entries
1462-
bytes32 metadataHash = hashMetadataEntries(metadataKeys, metadataValues);
1462+
bytes32 metadataHash = hashMetadataEntries(createData.metadataKeys, createData.metadataValues);
14631463

14641464
// Prepare the message hash that was signed
1465-
bytes32 structHash = keccak256(abi.encode(CREATE_DATA_SET_TYPEHASH, clientDataSetId, payee, metadataHash));
1465+
bytes32 structHash =
1466+
keccak256(abi.encode(CREATE_DATA_SET_TYPEHASH, createData.clientDataSetId, payee, metadataHash));
14661467
bytes32 digest = _hashTypedDataV4(structHash);
14671468

14681469
// Recover signer address from the signature
1469-
address recoveredSigner = recoverSigner(digest, signature);
1470+
address recoveredSigner = recoverSigner(digest, createData.signature);
14701471

1471-
if (payer == recoveredSigner) {
1472+
if (createData.payer == recoveredSigner) {
14721473
return;
14731474
}
14741475
require(
1475-
sessionKeyRegistry.authorizationExpiry(payer, recoveredSigner, CREATE_DATA_SET_TYPEHASH) >= block.timestamp,
1476-
Errors.InvalidSignature(payer, recoveredSigner)
1476+
sessionKeyRegistry.authorizationExpiry(createData.payer, recoveredSigner, CREATE_DATA_SET_TYPEHASH)
1477+
>= block.timestamp,
1478+
Errors.InvalidSignature(createData.payer, recoveredSigner)
14771479
);
14781480
}
14791481

service_contracts/src/FilecoinWarmStorageServiceStateView.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ contract FilecoinWarmStorageServiceStateView is IPDPProvingSchedule {
2222
return service.challengeWindow();
2323
}
2424

25-
function clientDataSetIDs(address payer) external view returns (uint256) {
26-
return service.clientDataSetIDs(payer);
25+
function clientDataSetIds(address payer, uint256 clientDataSetId) external view returns (uint256) {
26+
return service.clientDataSetIds(payer, clientDataSetId);
2727
}
2828

2929
function clientDataSets(address payer) external view returns (uint256[] memory dataSetIds) {

service_contracts/src/lib/FilecoinWarmStorageServiceStateInternalLibrary.sol

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,18 @@ library FilecoinWarmStorageServiceStateInternalLibrary {
7878
return CHALLENGES_PER_PROOF;
7979
}
8080

81-
function clientDataSetIDs(FilecoinWarmStorageService service, address payer) internal view returns (uint256) {
82-
return uint256(service.extsload(keccak256(abi.encode(payer, StorageLayout.CLIENT_DATA_SET_IDS_SLOT))));
81+
function clientDataSetIds(FilecoinWarmStorageService service, address payer, uint256 clientDataSetId)
82+
internal
83+
view
84+
returns (uint256)
85+
{
86+
return uint256(
87+
service.extsload(
88+
keccak256(
89+
abi.encode(clientDataSetId, keccak256(abi.encode(payer, StorageLayout.CLIENT_DATA_SET_IDS_SLOT)))
90+
)
91+
)
92+
);
8393
}
8494

8595
function provenThisPeriod(FilecoinWarmStorageService service, uint256 dataSetId) internal view returns (bool) {

service_contracts/src/lib/FilecoinWarmStorageServiceStateLibrary.sol

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,18 @@ library FilecoinWarmStorageServiceStateLibrary {
7474
return CHALLENGES_PER_PROOF;
7575
}
7676

77-
function clientDataSetIDs(FilecoinWarmStorageService service, address payer) public view returns (uint256) {
78-
return uint256(service.extsload(keccak256(abi.encode(payer, StorageLayout.CLIENT_DATA_SET_IDS_SLOT))));
77+
function clientDataSetIds(FilecoinWarmStorageService service, address payer, uint256 clientDataSetId)
78+
public
79+
view
80+
returns (uint256)
81+
{
82+
return uint256(
83+
service.extsload(
84+
keccak256(
85+
abi.encode(clientDataSetId, keccak256(abi.encode(payer, StorageLayout.CLIENT_DATA_SET_IDS_SLOT)))
86+
)
87+
)
88+
);
7989
}
8090

8191
function provenThisPeriod(FilecoinWarmStorageService service, uint256 dataSetId) public view returns (bool) {

0 commit comments

Comments
 (0)