Skip to content

Commit

Permalink
feat: rename key to keyTuple (#1492)
Browse files Browse the repository at this point in the history
Co-authored-by: Kevin Ingersoll <[email protected]>
  • Loading branch information
alvrs and holic authored Sep 15, 2023
1 parent 6573e38 commit 6e66c5b
Show file tree
Hide file tree
Showing 30 changed files with 884 additions and 804 deletions.
39 changes: 39 additions & 0 deletions .changeset/nice-glasses-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
"@latticexyz/block-logs-stream": patch
"@latticexyz/store-sync": patch
"@latticexyz/store": patch
"@latticexyz/world": patch
---

Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`.
This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries.

```diff
event StoreSetRecord(
bytes32 tableId,
- bytes32[] key,
+ bytes32[] keyTuple,
bytes data
);

event StoreSetField(
bytes32 tableId,
- bytes32[] key,
+ bytes32[] keyTuple,
uint8 fieldIndex,
bytes data
);

event StoreDeleteRecord(
bytes32 tableId,
- bytes32[] key,
+ bytes32[] keyTuple,
);

event StoreEphemeralRecord(
bytes32 tableId,
- bytes32[] key,
+ bytes32[] keyTuple,
bytes data
);
```
12 changes: 6 additions & 6 deletions docs/pages/store/advanced-features.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,19 @@ contract MirrorSubscriber is IStoreHook {
_tableId = tableId;
}
function onSetRecord(bytes32 tableId, bytes32[] memory key, bytes memory data) public {
function onSetRecord(bytes32 tableId, bytes32[] memory keyTuple, bytes memory data) public {
if (_tableId != tableId) revert("invalid tableId");
StoreSwitch.setRecord(indexerTableId, key, data);
StoreSwitch.setRecord(indexerTableId, keyTuple, data);
}
function onSetField(bytes32 tableId, bytes32[] memory key, uint8 schemaIndex, bytes memory data) public {
function onSetField(bytes32 tableId, bytes32[] memory keyTuple, uint8 schemaIndex, bytes memory data) public {
if (_tableId != tableId) revert("invalid tableId");
StoreSwitch.setField(indexerTableId, key, schemaIndex, data);
StoreSwitch.setField(indexerTableId, keyTuple, schemaIndex, data);
}
function onDeleteRecord(bytes32 tableId, bytes32[] memory key) public {
function onDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple) public {
if (_tableId != tableId) revert("invalid tableId");
StoreSwitch.deleteRecord(indexerTableId, key);
StoreSwitch.deleteRecord(indexerTableId, keyTuple);
}
}
```
Expand Down
58 changes: 29 additions & 29 deletions docs/pages/store/reading-and-writing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,55 +41,55 @@ barArray[0] = 69;
barArray[1] = 85;
fooArray[0] = 42;
// args: key, foo, bar, fooArray, staticArray
MyTable.set(keccak256("some.key"), 45, false, fooArray, barArray);
MyTable.set("some.key", 45, false, fooArray, barArray);
```

**Setting a field**

```solidity
// Setting foo
MyTable.setFoo(keccak256("some.key"), 33);
MyTable.setFoo("some.key", 33);
// Setting bar
MyTable.setBar(keccak256("some.key"), false);
MyTable.setBar("some.key", false);
// Setting fooArray
uint256[] memory fooArray = new uint256[](3);
fooArray[0] = 42;
fooArray[1] = 15;
fooArray[2] = 3;
MyTable.setFooArray(keccak256("some.key"), fooArray);
MyTable.setFooArray("some.key", fooArray);
```

**Operations on dynamic arrays**

```solidity
MyTable.pushFooArray(keccak256("some.key"), 4242); // adds 4242 at end of fooArray
MyTable.popFooArray(keccak256("some.key")); // pop fooArray
MyTable.setItemFooArray(keccak256("some.key"), 0, 123); // set fooArray[0] to 123
MyTable.pushFooArray("some.key", 4242); // adds 4242 at end of fooArray
MyTable.popFooArray("some.key"); // pop fooArray
MyTable.setItemFooArray("some.key", 0, 123); // set fooArray[0] to 123
```

**Retrieving a record**

```solidity
// Retrieving a record
MyTable.get(keccak256("some.key"));
MyTable.get("some.key");
```

**Retrieving a field**

```solidity
// Retrieve foo
MyTable.getFoo(keccak256("some.key"));
MyTable.getFoo("some.key");
// Retrieve bar
MyTable.getBar(keccak256("some.key"));
MyTable.getBar("some.key");
// Retrieve an element of fooArray
MyTable.getItemFooArray(keccak256("some.key"), 0); // get fooArray[0]
MyTable.getItemFooArray("some.key", 0); // get fooArray[0]
```

**Deleting a record**

```solidity
// Deleting a record
MyTable.deleteRecord(keccak256("some.key"));
MyTable.deleteRecord("some.key");
```

### Access to Store via low-level API
Expand Down Expand Up @@ -120,10 +120,10 @@ tables: {
uint256 tableId = uint256(keccak256("MyTable"));
uint256 foo = 10;
uint256 bar = 24;
bytes32[] memory key = new bytes32[](1);
key[0] = keccak256("some.key");
bytes32[] memory keyTuple = new bytes32[](1);
keyTuple[0] = "some.key";
// Setting a record
StoreSwitch.setRecord(tableId, key, abi.encodePacked((foo, bar)));
StoreSwitch.setRecord(tableId, keyTuple, abi.encodePacked((foo, bar)));
```

**Setting a field**
Expand All @@ -132,23 +132,23 @@ StoreSwitch.setRecord(tableId, key, abi.encodePacked((foo, bar)));
uint256 tableId = uint256(keccak256("MyTable"));
uint256 foo = 45;
uint256 foo = 67;
bytes32[] memory key = new bytes32[](1);
key[0] = keccak256("some.key");
bytes32[] memory keyTuple = new bytes32[](1);
keyTuple[0] = "some.key";
// Setting foo
StoreSwitch.setField(tableId, key, 0, abi.encodePacked((foo)));
StoreSwitch.setField(tableId, keyTuple, 0, abi.encodePacked((foo)));
// Setting bar
StoreSwitch.setField(tableId, key, 1, abi.encodePacked((bar)));
StoreSwitch.setField(tableId, keyTuple, 1, abi.encodePacked((bar)));
```

**Retrieving a record**

```solidity
uint256 tableId = uint256(keccak256("MyTable"));
bytes32[] memory key = new bytes32[](1);
key[0] = keccak256("some.key");
bytes32[] memory keyTuple = new bytes32[](1);
keyTuple[0] = "some.key";
// Retrieve a record
Schema valueSchema = SchemaLib.encode(SchemaType.UINT256, SchemaType.UINT256);
bytes memory loadedData = StoreCore.getRecord(tableId, key, valueSchema);
bytes memory loadedData = StoreCore.getRecord(tableId, keyTuple, valueSchema);
uint256 foo = (uint256(Bytes.slice4(loadedData, 0)));
uint256 bar = (uint256(Bytes.slice4(loadedData, 32)));
```
Expand All @@ -157,22 +157,22 @@ uint256 bar = (uint256(Bytes.slice4(loadedData, 32)));

```solidity
uint256 tableId = uint256(keccak256("MyTable"));
bytes32[] memory key = new bytes32[](1);
key[0] = keccak256("some.key");
bytes32[] memory keyTuple = new bytes32[](1);
keyTuple[0] = "some.key";
// Retrieve foo
bytes memory loadedDatafoo = StoreCore.getField(tableId, key, 0);
bytes memory loadedDatafoo = StoreCore.getField(tableId, keyTuple, 0);
int32 foo = (uint32(Bytes.slice4(loadedDatafoo, 0)));
// Retrieve bar
bytes memory loadedDatabar = StoreCore.getField(tableId, key, 1);
bytes memory loadedDatabar = StoreCore.getField(tableId, keyTuple, 1);
int32 bar = (uint32(Bytes.slice4(loadedData, 0)));
```

**Deleting a record**

```solidity
uint256 tableId = uint256(keccak256("MyTable"));
bytes32[] memory key = new bytes32[](1);
key[0] = keccak256("some.key");
bytes32[] memory keyTuple = new bytes32[](1);
keyTuple[0] = "some.key";
// Deleting a record
StoreCore.deleteRecord(tableId, key);
StoreCore.deleteRecord(tableId, keyTuple);
```
6 changes: 3 additions & 3 deletions docs/pages/store/spec.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { Aside } from "../../components/Aside";
When a record or a single field is edited, or when a record is deleted, Store emits a standard event with enough information for off-chain actors to reconstruct the new version of the Store with event-sourcing.

```solidity
event StoreSetRecord(uint256 tableId, bytes32[] key, bytes data);
event StoreSetField(uint256 tableId, bytes32[] key, uint8 schemaIndex, bytes data);
event StoreDeleteRecord(uint256 tableId, bytes32[] key);
event StoreSetRecord(uint256 tableId, bytes32[] keyTuple, bytes data);
event StoreSetField(uint256 tableId, bytes32[] keyTuple, uint8 schemaIndex, bytes data);
event StoreDeleteRecord(uint256 tableId, bytes32[] keyTuple);
```

Each event includes the table ID and each key encoded as `bytes32`.
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/world/modules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ For example, it can be used to fetch all keys in the "Position" table (if the ta
It offers two methods:

- `getKeysInTable(bytes32 tableId)` returns all keys in a table
- `hasKey(bytes32 tableId, bytes32[] memory key)` returns whether a given key is in a table (with O(1) gas)
- `hasKey(bytes32 tableId, bytes32[] memory keyTuple)` returns whether a given keyTuple is in a table (with O(1) gas)

Using `getKeysInTable` to retrieve all keys in the Player table:

Expand All @@ -62,7 +62,7 @@ import { Player, PlayerTableId } from "../codegen/tables/Player.sol";
bytes32[][] memory players = getKeysInTable(world, PlayerTableId);
```

Using `hasKey` to check if a key is in the Player table:
Using `hasKey` to check if a keyTuple is in the Player table:

```solidity
// assumes a boolean flag indicates a player:
Expand All @@ -79,7 +79,7 @@ bool memory isPlayer = hasKey(world, PlayerTableId, keyTuple);
Internally, it works by installing a [hook](https://v2.mud.dev/store/advanced-features#storage-hooks) that maintains:

- an array of all keys in the table
- an index or "**reverse mapping**" of whether a given key is in the table
- an index or "**reverse mapping**" of whether a given keyTuple is in the table

#### **`KeysWithValueModule`**

Expand Down
8 changes: 4 additions & 4 deletions packages/block-logs-stream/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ latestBlockNumber$
publicClient,
address,
events: parseAbi([
"event StoreDeleteRecord(bytes32 tableId, bytes32[] key)",
"event StoreSetField(bytes32 tableId, bytes32[] key, uint8 schemaIndex, bytes data)",
"event StoreSetRecord(bytes32 tableId, bytes32[] key, bytes data)",
"event StoreEphemeralRecord(bytes32 tableId, bytes32[] key, bytes data)",
"event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple)",
"event StoreSetField(bytes32 tableId, bytes32[] keyTuple, uint8 schemaIndex, bytes data)",
"event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes data)",
"event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes data)",
]),
}),
mergeMap(({ logs }) => from(groupLogsByBlockNumber(logs)))
Expand Down
8 changes: 4 additions & 4 deletions packages/store-sync/src/blockLogsToStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe("blockLogsToStorage", () => {
removed: false,
args: {
tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000",
key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
data: "0x0004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000",
},
eventName: "StoreSetRecord",
Expand All @@ -77,7 +77,7 @@ describe("blockLogsToStorage", () => {
removed: false,
args: {
tableId: "0x00000000000000000000000000000000496e76656e746f727900000000000000",
key: [
keyTuple: [
"0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000001",
Expand Down Expand Up @@ -110,7 +110,7 @@ describe("blockLogsToStorage", () => {
"address": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
"args": {
"data": "0x00000008",
"key": [
"keyTuple": [
"0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000001",
Expand Down Expand Up @@ -164,7 +164,7 @@ describe("blockLogsToStorage", () => {
"address": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
"args": {
"data": "0x00000008",
"key": [
"keyTuple": [
"0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000001",
Expand Down
4 changes: 2 additions & 2 deletions packages/store-sync/src/blockLogsToStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function blockLogsToStorage<TConfig extends StoreConfig = StoreConfig>({
// TODO: refactor encode/decode to use Record<string, SchemaAbiType> schemas
// TODO: refactor to decode key with protocol-parser utils

const [tableId, ...otherKeys] = log.args.key;
const [tableId, ...otherKeys] = log.args.keyTuple;
if (otherKeys.length) {
console.warn("registerSchema event is expected to have only one key in key tuple, but got multiple", log);
}
Expand Down Expand Up @@ -115,7 +115,7 @@ export function blockLogsToStorage<TConfig extends StoreConfig = StoreConfig>({
const keyNames = Object.keys(table.keySchema);
const keyValues = decodeKeyTuple(
{ staticFields: Object.values(table.keySchema), dynamicFields: [] },
log.args.key
log.args.keyTuple
);
const key = Object.fromEntries(keyValues.map((value, i) => [keyNames[i], value])) as Key<
TConfig,
Expand Down
7 changes: 4 additions & 3 deletions packages/store-sync/src/postgres/postgresStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as transformSchemaNameExports from "./transformSchemaName";
import { getTables } from "./getTables";
import { PostgresStorageAdapter, postgresStorage } from "./postgresStorage";
import { buildTable } from "./buildTable";
import { StoreEventsLog } from "../common";

vi.spyOn(transformSchemaNameExports, "transformSchemaName").mockImplementation(
(schemaName) => `${process.pid}_${process.env.VITEST_POOL_ID}__${schemaName}`
Expand Down Expand Up @@ -47,7 +48,7 @@ describe("postgresStorage", async () => {
removed: false,
args: {
tableId: "0x000000000000000000000000000000005265736f757263655479706500000000",
key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
schemaIndex: 0,
data: "0x02",
},
Expand All @@ -65,12 +66,12 @@ describe("postgresStorage", async () => {
removed: false,
args: {
tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000",
key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
data: "0x0004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000",
},
eventName: "StoreSetRecord",
},
],
] satisfies StoreEventsLog[],
});

expect(await db.select().from(storageAdapter.internalTables.chain)).toMatchInlineSnapshot(`
Expand Down
7 changes: 4 additions & 3 deletions packages/store-sync/src/sqlite/sqliteStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { drizzle } from "drizzle-orm/sql-js";
import { createPublicClient, http } from "viem";
import { foundry } from "viem/chains";
import { blockLogsToStorage } from "../blockLogsToStorage";
import { StoreEventsLog } from "../common";

describe("sqliteStorage", async () => {
const SqlJs = await initSqlJs();
Expand Down Expand Up @@ -53,7 +54,7 @@ describe("sqliteStorage", async () => {
removed: false,
args: {
tableId: "0x000000000000000000000000000000005265736f757263655479706500000000",
key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
schemaIndex: 0,
data: "0x02",
},
Expand All @@ -71,12 +72,12 @@ describe("sqliteStorage", async () => {
removed: false,
args: {
tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000",
key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"],
data: "0x0004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000",
},
eventName: "StoreSetRecord",
},
],
] satisfies StoreEventsLog[],
});

expect(db.select().from(chainState).all()).toMatchInlineSnapshot(`
Expand Down
Loading

0 comments on commit 6e66c5b

Please sign in to comment.