Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(world): use ResourceId namespaceId for all methods acting on the namespace as a resource #1555

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .changeset/mean-seals-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@latticexyz/world": patch
"@latticexyz/store": patch
---

The `ResourceType` table is removed.
It was previously used to store the resource type for each resource ID in a `World`. This is no longer necessary as the [resource type is now encoded in the resource ID](https://github.com/latticexyz/mud/pull/1544).

To still be able to determine whether a given resource ID exists, a `ResourceIds` table has been added.
The previous `ResourceType` table was part of `World` and missed tables that were registered directly via `StoreCore.registerTable` instead of via `World.registerTable` (e.g. when a table was registered as part of a root module).
This problem is solved by the new table `ResourceIds` being part of `Store`.

`StoreCore`'s `hasTable` function was removed in favor of using `ResourceIds.getExists(tableId)` directly.

```diff
- import { ResourceType } from "@latticexyz/world/src/tables/ResourceType.sol";
- import { StoreCore } from "@latticexyz/store/src/StoreCore.sol";
+ import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol";

- bool tableExists = StoreCore.hasTable(tableId);
+ bool tableExists = ResourceIds.getExists(tableId);

- bool systemExists = ResourceType.get(systemId) != Resource.NONE;
+ bool systemExists = ResourceIds.getExists(systemId);
```
25 changes: 25 additions & 0 deletions .changeset/real-students-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@latticexyz/world": major
---

All `World` methods acting on namespaces as resources have been updated to use `ResourceId namespaceId` as parameter instead of `bytes14 namespace`.
The reason for this change is to make it clearer when a namespace is used as resource, as opposed to being part of another resource's ID.

```diff
+ import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";

IBaseWorld {
- function registerNamespace(bytes14 namespace) external;
+ function registerNamespace(ResourceId namespaceId) external;

- function transferOwnership(bytes14 namespace, address newOwner) external;
+ function transferOwnership(ResourceId namespaceId, address newOwner) external;

- function transferBalanceToNamespace(bytes14 fromNamespace, bytes14 toNamespace, uint256 amount) external;
+ function transferBalanceToNamespace(ResourceId fromNamespaceId, ResourceId toNamespaceId, uint256 amount) external;

- function transferBalanceToAddress(bytes14 fromNamespace, address toAddress, uint256 amount) external;
+ function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) external;
}

```
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dist
**/.next
.next
templates/phaser/packages/art
CODEOWNERS
out
76 changes: 38 additions & 38 deletions packages/store/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@
"file": "test/KeyEncoding.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "register KeyEncoding table",
"gasUsed": 687862
"gasUsed": 720275
},
{
"file": "test/Mixed.t.sol",
Expand All @@ -363,19 +363,19 @@
"file": "test/Mixed.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "register Mixed table",
"gasUsed": 549680
"gasUsed": 582100
},
{
"file": "test/Mixed.t.sol",
"test": "testSetAndGet",
"name": "set record in Mixed",
"gasUsed": 103940
"gasUsed": 103942
},
{
"file": "test/Mixed.t.sol",
"test": "testSetAndGet",
"name": "get record from Mixed",
"gasUsed": 7023
"gasUsed": 7025
},
{
"file": "test/PackedCounter.t.sol",
Expand Down Expand Up @@ -627,31 +627,31 @@
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromSecondField",
"name": "pop from field (cold, 1 slot, 1 uint32 item)",
"gasUsed": 19429
"gasUsed": 19440
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromSecondField",
"name": "pop from field (warm, 1 slot, 1 uint32 item)",
"gasUsed": 13439
"gasUsed": 13450
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromThirdField",
"name": "pop from field (cold, 2 slots, 10 uint32 items)",
"gasUsed": 17197
"gasUsed": 17208
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromThirdField",
"name": "pop from field (warm, 2 slots, 10 uint32 items)",
"gasUsed": 13208
"gasUsed": 13219
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testAccessEmptyData",
"name": "access non-existing record",
"gasUsed": 7041
"gasUsed": 7042
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -663,7 +663,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testAccessEmptyData",
"name": "access dynamic field of non-existing record",
"gasUsed": 2033
"gasUsed": 2034
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -675,25 +675,25 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testAccessEmptyData",
"name": "access slice of dynamic field of non-existing record",
"gasUsed": 1483
"gasUsed": 1484
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testDeleteData",
"name": "delete record (complex data, 3 slots)",
"gasUsed": 6699
"gasUsed": 6700
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testHasFieldLayout",
"name": "Check for existence of table (existent)",
"gasUsed": 1281
"gasUsed": 1249
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testHasFieldLayout",
"name": "check for existence of table (non-existent)",
"gasUsed": 3282
"gasUsed": 3249
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -747,19 +747,19 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testPushToField",
"name": "push to field (1 slot, 1 uint32 item)",
"gasUsed": 10262
"gasUsed": 10264
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testPushToField",
"name": "push to field (2 slots, 10 uint32 items)",
"gasUsed": 32939
"gasUsed": 32940
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "StoreCore: register table",
"gasUsed": 609810
"gasUsed": 642237
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -771,19 +771,19 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "StoreCore: get value schema (warm)",
"gasUsed": 1803
"gasUsed": 1804
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "StoreCore: get key schema (warm)",
"gasUsed": 2858
"gasUsed": 2827
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicData",
"name": "set complex record with dynamic data (4 slots)",
"gasUsed": 101839
"gasUsed": 101840
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -801,7 +801,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicData",
"name": "compare: Set complex record with dynamic data using abi.encode",
"gasUsed": 267368
"gasUsed": 267369
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -813,19 +813,19 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicDataLength",
"name": "set dynamic length of dynamic index 1",
"gasUsed": 970
"gasUsed": 971
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicDataLength",
"name": "reduce dynamic length of dynamic index 0",
"gasUsed": 960
"gasUsed": 961
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set static field (1 slot)",
"gasUsed": 31600
"gasUsed": 31601
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -837,19 +837,19 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set static field (overlap 2 slot)",
"gasUsed": 30240
"gasUsed": 30241
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "get static field (overlap 2 slot)",
"gasUsed": 1844
"gasUsed": 1845
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set dynamic field (1 slot, first dynamic field)",
"gasUsed": 53963
"gasUsed": 53966
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -861,13 +861,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set dynamic field (1 slot, second dynamic field)",
"gasUsed": 32190
"gasUsed": 32192
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "get dynamic field (1 slot, second dynamic field)",
"gasUsed": 2203
"gasUsed": 2204
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -885,25 +885,25 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetStaticDataSpanningWords",
"name": "set static record (2 slots)",
"gasUsed": 54649
"gasUsed": 54650
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetStaticDataSpanningWords",
"name": "get static record (2 slots)",
"gasUsed": 1709
"gasUsed": 1711
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testUpdateInField",
"name": "update in field (1 slot, 1 uint32 item)",
"gasUsed": 9606
"gasUsed": 9608
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testUpdateInField",
"name": "push to field (2 slots, 6 uint64 items)",
"gasUsed": 10043
"gasUsed": 10045
},
{
"file": "test/StoreHook.t.sol",
Expand Down Expand Up @@ -945,7 +945,7 @@
"file": "test/tables/Callbacks.t.sol",
"test": "testSetAndGet",
"name": "Callbacks: set field",
"gasUsed": 57050
"gasUsed": 57052
},
{
"file": "test/tables/Callbacks.t.sol",
Expand All @@ -957,7 +957,7 @@
"file": "test/tables/Callbacks.t.sol",
"test": "testSetAndGet",
"name": "Callbacks: push 1 element",
"gasUsed": 33334
"gasUsed": 33337
},
{
"file": "test/tables/StoreHooks.t.sol",
Expand Down Expand Up @@ -987,7 +987,7 @@
"file": "test/tables/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: pop 1 element (warm)",
"gasUsed": 10728
"gasUsed": 10739
},
{
"file": "test/tables/StoreHooks.t.sol",
Expand Down Expand Up @@ -1113,7 +1113,7 @@
"file": "test/Vector2.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "register Vector2 field layout",
"gasUsed": 411103
"gasUsed": 443543
},
{
"file": "test/Vector2.t.sol",
Expand All @@ -1125,6 +1125,6 @@
"file": "test/Vector2.t.sol",
"test": "testSetAndGet",
"name": "get Vector2 record",
"gasUsed": 2513
"gasUsed": 2514
}
]
8 changes: 8 additions & 0 deletions packages/store/mud.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ export default mudConfig({
abiEncodedFieldNames: "bytes",
},
},
ResourceIds: {
keySchema: {
resourceId: "bytes32",
},
valueSchema: {
exists: "bool",
},
},
// The Hooks table is a generic table used by the `filterFromList` util in `Hook.sol`
Hooks: {
valueSchema: "bytes21[]",
Expand Down
1 change: 1 addition & 0 deletions packages/store/src/IStoreErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface IStoreErrors {
// Errors include a stringified version of the tableId for easier debugging if cleartext tableIds are used
error StoreCore_TableAlreadyExists(ResourceId tableId, string tableIdString);
error StoreCore_TableNotFound(ResourceId tableId, string tableIdString);
error StoreCore_InvalidResourceType(string resourceType);

error StoreCore_NotImplemented();
error StoreCore_NotDynamicField();
Expand Down
2 changes: 1 addition & 1 deletion packages/store/src/ResourceId.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ library ResourceIdInstance {
return bytes2(ResourceId.unwrap(resourceId) << (NAME_BYTES * BYTES_TO_BITS));
}

function isType(ResourceId resourceId, bytes2 resourceType) internal view returns (bool) {
function isType(ResourceId resourceId, bytes2 resourceType) internal pure returns (bool) {
return ResourceId.unwrap(resourceId) & TYPE_MASK == bytes32(resourceType) >> (NAME_BYTES * BYTES_TO_BITS);
}
}
Loading