Skip to content

Commit

Permalink
feat(store,world): combine schema and metadata registration, rename g…
Browse files Browse the repository at this point in the history
…etSchema to getValueSchema, change Schema table id (#1182)

Co-authored-by: Kevin Ingersoll <[email protected]>
  • Loading branch information
alvrs and holic authored Aug 16, 2023
1 parent 9781866 commit afaf2f5
Show file tree
Hide file tree
Showing 120 changed files with 4,069 additions and 4,271 deletions.
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

0 comments on commit afaf2f5

Please sign in to comment.