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(store,world): combine schema and metadata registration, rename getSchema to getValueSchema, change Schema table id #1182

Merged
merged 23 commits into from
Aug 16, 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
32 changes: 32 additions & 0 deletions .changeset/modern-hornets-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
"@latticexyz/cli": major
"@latticexyz/store": major
"@latticexyz/world": major
"@latticexyz/store-sync": major
"create-mud": patch
---

- `Store`'s internal schema table is now a normal table instead of using special code paths. It is renamed to Tables, and the table ID changed from `mudstore:schema` to `mudstore:Tables`
- `Store`'s `registerSchema` and `setMetadata` are combined into a single `registerTable` method. This means metadata (key names, field names) is immutable and indexers can create tables with this metadata when a new table is registered on-chain.

```diff
- function registerSchema(bytes32 table, Schema schema, Schema keySchema) external;
-
- function setMetadata(bytes32 table, string calldata tableName, string[] calldata fieldNames) external;

+ function registerTable(
+ bytes32 table,
+ Schema keySchema,
+ Schema valueSchema,
+ string[] calldata keyNames,
+ string[] calldata fieldNames
+ ) external;
```

- `World`'s `registerTable` method is updated to match the `Store` interface, `setMetadata` is removed
- The `getSchema` method is renamed to `getValueSchema` on all interfaces
```diff
- function getSchema(bytes32 table) external view returns (Schema schema);
+ function getValueSchema(bytes32 table) external view returns (Schema valueSchema);
```
- The `store-sync` and `cli` packages are updated to integrate the breaking protocol changes. Downstream projects only need to manually integrate these changes if they access low level `Store` or `World` functions. Otherwise, a fresh deploy with the latest MUD will get you these changes.
8 changes: 2 additions & 6 deletions docs/pages/store/internals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,5 @@ It is called within `StoreRead`'s constructor (which is implemented by `World`).

### Tables

- `SCHEMA_TABLE` - a very low-level table with no library for it.
All table schemas are stored here.
Directly using it is not recommended, table libraries generated via `tablegen` have schema methods like `registerSchema`.
Alternatively, `StoreCore` exposes `getSchema`, `getKeySchema`, `hasTable`, `registerSchema`, `setMetadata`, most of which are used by table libraries internally.
- `Hooks` - maps tableId to an array of table hooks
- `StoreMetadata` - maps tableId to optional metadata, like table and field names
- `Tables` - maps table ID to the table's key schema, value schema, key names, and field names.
- `Hooks` - maps table ID to an array of table hooks
83 changes: 40 additions & 43 deletions e2e/packages/contracts/src/codegen/tables/Multi.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,7 @@ struct MultiData {
}

library Multi {
/** Get the table's schema */
function getSchema() internal pure returns (Schema) {
SchemaType[] memory _schema = new SchemaType[](2);
_schema[0] = SchemaType.INT256;
_schema[1] = SchemaType.BOOL;

return SchemaLib.encode(_schema);
}

/** Get the table's key schema */
function getKeySchema() internal pure returns (Schema) {
SchemaType[] memory _schema = new SchemaType[](4);
_schema[0] = SchemaType.UINT32;
Expand All @@ -45,34 +37,39 @@ library Multi {
return SchemaLib.encode(_schema);
}

/** Get the table's metadata */
function getMetadata() internal pure returns (string memory, string[] memory) {
string[] memory _fieldNames = new string[](2);
_fieldNames[0] = "num";
_fieldNames[1] = "value";
return ("Multi", _fieldNames);
/** Get the table's value schema */
function getValueSchema() internal pure returns (Schema) {
SchemaType[] memory _schema = new SchemaType[](2);
_schema[0] = SchemaType.INT256;
_schema[1] = SchemaType.BOOL;

return SchemaLib.encode(_schema);
}

/** Register the table's schema */
function registerSchema() internal {
StoreSwitch.registerSchema(_tableId, getSchema(), getKeySchema());
/** Get the table's key names */
function getKeyNames() internal pure returns (string[] memory keyNames) {
keyNames = new string[](4);
keyNames[0] = "a";
keyNames[1] = "b";
keyNames[2] = "c";
keyNames[3] = "d";
}

/** Register the table's schema (using the specified store) */
function registerSchema(IStore _store) internal {
_store.registerSchema(_tableId, getSchema(), getKeySchema());
/** Get the table's field names */
function getFieldNames() internal pure returns (string[] memory fieldNames) {
fieldNames = new string[](2);
fieldNames[0] = "num";
fieldNames[1] = "value";
}

/** Set the table's metadata */
function setMetadata() internal {
(string memory _tableName, string[] memory _fieldNames) = getMetadata();
StoreSwitch.setMetadata(_tableId, _tableName, _fieldNames);
/** Register the table's key schema, value schema, key names and value names */
function register() internal {
StoreSwitch.registerTable(_tableId, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames());
}

/** Set the table's metadata (using the specified store) */
function setMetadata(IStore _store) internal {
(string memory _tableName, string[] memory _fieldNames) = getMetadata();
_store.setMetadata(_tableId, _tableName, _fieldNames);
/** Register the table's key schema, value schema, key names and value names (using the specified store) */
function register(IStore _store) internal {
_store.registerTable(_tableId, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames());
}

/** Get num */
Expand All @@ -83,7 +80,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getSchema());
bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getValueSchema());
return (int256(uint256(Bytes.slice32(_blob, 0))));
}

Expand All @@ -95,7 +92,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getSchema());
bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getValueSchema());
return (int256(uint256(Bytes.slice32(_blob, 0))));
}

Expand All @@ -107,7 +104,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), getSchema());
StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), getValueSchema());
}

/** Set num (using the specified store) */
Expand All @@ -118,7 +115,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

_store.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), getSchema());
_store.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), getValueSchema());
}

/** Get value */
Expand All @@ -129,7 +126,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getSchema());
bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getValueSchema());
return (_toBool(uint8(Bytes.slice1(_blob, 0))));
}

Expand All @@ -141,7 +138,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getSchema());
bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getValueSchema());
return (_toBool(uint8(Bytes.slice1(_blob, 0))));
}

Expand All @@ -153,7 +150,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), getSchema());
StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), getValueSchema());
}

/** Set value (using the specified store) */
Expand All @@ -164,7 +161,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

_store.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), getSchema());
_store.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), getValueSchema());
}

/** Get the full data */
Expand All @@ -175,7 +172,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getSchema());
bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getValueSchema());
return decode(_blob);
}

Expand All @@ -187,7 +184,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getSchema());
bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getValueSchema());
return decode(_blob);
}

Expand All @@ -201,7 +198,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

StoreSwitch.setRecord(_tableId, _keyTuple, _data, getSchema());
StoreSwitch.setRecord(_tableId, _keyTuple, _data, getValueSchema());
}

/** Set the full data using individual values (using the specified store) */
Expand All @@ -214,7 +211,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

_store.setRecord(_tableId, _keyTuple, _data, getSchema());
_store.setRecord(_tableId, _keyTuple, _data, getValueSchema());
}

/** Set the full data using the data struct */
Expand Down Expand Up @@ -258,7 +255,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

StoreSwitch.deleteRecord(_tableId, _keyTuple, getSchema());
StoreSwitch.deleteRecord(_tableId, _keyTuple, getValueSchema());
}

/* Delete all data for given keys (using the specified store) */
Expand All @@ -269,7 +266,7 @@ library Multi {
_keyTuple[2] = bytes32(uint256(c));
_keyTuple[3] = bytes32(uint256(int256(d)));

_store.deleteRecord(_tableId, _keyTuple, getSchema());
_store.deleteRecord(_tableId, _keyTuple, getValueSchema());
}
}

Expand Down
54 changes: 24 additions & 30 deletions e2e/packages/contracts/src/codegen/tables/Number.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,56 +21,50 @@ bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Numbe
bytes32 constant NumberTableId = _tableId;

library Number {
/** Get the table's schema */
function getSchema() internal pure returns (Schema) {
/** Get the table's key schema */
function getKeySchema() internal pure returns (Schema) {
SchemaType[] memory _schema = new SchemaType[](1);
_schema[0] = SchemaType.UINT32;

return SchemaLib.encode(_schema);
}

function getKeySchema() internal pure returns (Schema) {
/** Get the table's value schema */
function getValueSchema() internal pure returns (Schema) {
SchemaType[] memory _schema = new SchemaType[](1);
_schema[0] = SchemaType.UINT32;

return SchemaLib.encode(_schema);
}

/** Get the table's metadata */
function getMetadata() internal pure returns (string memory, string[] memory) {
string[] memory _fieldNames = new string[](1);
_fieldNames[0] = "value";
return ("Number", _fieldNames);
}

/** Register the table's schema */
function registerSchema() internal {
StoreSwitch.registerSchema(_tableId, getSchema(), getKeySchema());
/** Get the table's key names */
function getKeyNames() internal pure returns (string[] memory keyNames) {
keyNames = new string[](1);
keyNames[0] = "key";
}

/** Register the table's schema (using the specified store) */
function registerSchema(IStore _store) internal {
_store.registerSchema(_tableId, getSchema(), getKeySchema());
/** Get the table's field names */
function getFieldNames() internal pure returns (string[] memory fieldNames) {
fieldNames = new string[](1);
fieldNames[0] = "value";
}

/** Set the table's metadata */
function setMetadata() internal {
(string memory _tableName, string[] memory _fieldNames) = getMetadata();
StoreSwitch.setMetadata(_tableId, _tableName, _fieldNames);
/** Register the table's key schema, value schema, key names and value names */
function register() internal {
StoreSwitch.registerTable(_tableId, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames());
}

/** Set the table's metadata (using the specified store) */
function setMetadata(IStore _store) internal {
(string memory _tableName, string[] memory _fieldNames) = getMetadata();
_store.setMetadata(_tableId, _tableName, _fieldNames);
/** Register the table's key schema, value schema, key names and value names (using the specified store) */
function register(IStore _store) internal {
_store.registerTable(_tableId, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames());
}

/** Get value */
function get(uint32 key) internal view returns (uint32 value) {
bytes32[] memory _keyTuple = new bytes32[](1);
_keyTuple[0] = bytes32(uint256(key));

bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getSchema());
bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getValueSchema());
return (uint32(Bytes.slice4(_blob, 0)));
}

Expand All @@ -79,7 +73,7 @@ library Number {
bytes32[] memory _keyTuple = new bytes32[](1);
_keyTuple[0] = bytes32(uint256(key));

bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getSchema());
bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getValueSchema());
return (uint32(Bytes.slice4(_blob, 0)));
}

Expand All @@ -88,15 +82,15 @@ library Number {
bytes32[] memory _keyTuple = new bytes32[](1);
_keyTuple[0] = bytes32(uint256(key));

StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getSchema());
StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getValueSchema());
}

/** Set value (using the specified store) */
function set(IStore _store, uint32 key, uint32 value) internal {
bytes32[] memory _keyTuple = new bytes32[](1);
_keyTuple[0] = bytes32(uint256(key));

_store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getSchema());
_store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getValueSchema());
}

/** Tightly pack full data using this table's schema */
Expand All @@ -117,14 +111,14 @@ library Number {
bytes32[] memory _keyTuple = new bytes32[](1);
_keyTuple[0] = bytes32(uint256(key));

StoreSwitch.deleteRecord(_tableId, _keyTuple, getSchema());
StoreSwitch.deleteRecord(_tableId, _keyTuple, getValueSchema());
}

/* Delete all data for given keys (using the specified store) */
function deleteRecord(IStore _store, uint32 key) internal {
bytes32[] memory _keyTuple = new bytes32[](1);
_keyTuple[0] = bytes32(uint256(key));

_store.deleteRecord(_tableId, _keyTuple, getSchema());
_store.deleteRecord(_tableId, _keyTuple, getValueSchema());
}
}
Loading