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): add field index to Store_SpliceDynamicData event #2279

Merged
merged 16 commits into from Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rich-deers-doubt.md
@@ -0,0 +1,5 @@
---
"@latticexyz/store": minor
yonadaaa marked this conversation as resolved.
Show resolved Hide resolved
---

Added `dynamicFieldIndex` to the `Store_SpliceDynamicData` event. This enables indexers to store records as a blob per field without a schema lookup.
holic marked this conversation as resolved.
Show resolved Hide resolved
18 changes: 10 additions & 8 deletions docs/pages/store/reference/store-core.mdx
Expand Up @@ -812,6 +812,7 @@ Emitted when dynamic data in the store is spliced.
event Store_SpliceDynamicData(
ResourceId indexed tableId,
bytes32[] keyTuple,
uint8 dynamicFieldIndex,
uint48 start,
uint40 deleteCount,
PackedCounter encodedLengths,
Expand All @@ -821,14 +822,15 @@ event Store_SpliceDynamicData(

**Parameters**

| Name | Type | Description |
| ---------------- | --------------- | ------------------------------------------------------------------------- |
| `tableId` | `ResourceId` | The ID of the table where the data is spliced. |
| `keyTuple` | `bytes32[]` | An array representing the composite key for the record. |
| `start` | `uint48` | The start position in bytes for the splice operation. |
| `deleteCount` | `uint40` | The number of bytes to delete in the splice operation. |
| `encodedLengths` | `PackedCounter` | The encoded lengths of the dynamic data of the record. |
| `data` | `bytes` | The data to insert into the dynamic data of the record at the start byte. |
| Name | Type | Description |
| ------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tableId` | `ResourceId` | The ID of the table where the data is spliced. |
| `keyTuple` | `bytes32[]` | An array representing the composite key for the record. |
| `dynamicFieldIndex` | `uint8` | The index of the dynamic field to splice data, relative to the start of the dynamic fields. (Dynamic field index = field index - number of static fields) |
| `start` | `uint48` | The start position in bytes for the splice operation. |
| `deleteCount` | `uint40` | The number of bytes to delete in the splice operation. |
| `encodedLengths` | `PackedCounter` | The encoded lengths of the dynamic data of the record. |
| `data` | `bytes` | The data to insert into the dynamic data of the record at the start byte. |

### Store_DeleteRecord

Expand Down
18 changes: 10 additions & 8 deletions docs/pages/store/reference/store.mdx
Expand Up @@ -61,6 +61,7 @@ Emitted when dynamic data in the store is spliced.
event Store_SpliceDynamicData(
ResourceId indexed tableId,
bytes32[] keyTuple,
uint8 dynamicFieldIndex,
uint48 start,
uint40 deleteCount,
PackedCounter encodedLengths,
Expand All @@ -70,14 +71,15 @@ event Store_SpliceDynamicData(

**Parameters**

| Name | Type | Description |
| ---------------- | --------------- | ------------------------------------------------------------------------- |
| `tableId` | `ResourceId` | The ID of the table where the data is spliced. |
| `keyTuple` | `bytes32[]` | An array representing the composite key for the record. |
| `start` | `uint48` | The start position in bytes for the splice operation. |
| `deleteCount` | `uint40` | The number of bytes to delete in the splice operation. |
| `encodedLengths` | `PackedCounter` | The encoded lengths of the dynamic data of the record. |
| `data` | `bytes` | The data to insert into the dynamic data of the record at the start byte. |
| Name | Type | Description |
| ------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tableId` | `ResourceId` | The ID of the table where the data is spliced. |
| `keyTuple` | `bytes32[]` | An array representing the composite key for the record. |
| `dynamicFieldIndex` | `uint8` | The index of the dynamic field to splice data, relative to the start of the dynamic fields. (Dynamic field index = field index - number of static fields) |
| `start` | `uint48` | The start position in bytes for the splice operation. |
| `deleteCount` | `uint40` | The number of bytes to delete in the splice operation. |
| `encodedLengths` | `PackedCounter` | The encoded lengths of the dynamic data of the record. |
| `data` | `bytes` | The data to insert into the dynamic data of the record at the start byte. |

### Store_DeleteRecord

Expand Down
Expand Up @@ -50,7 +50,7 @@ describe("createStorageAdapter", async () => {
expect(await db.select().from(storageAdapter.tables.configTable)).toMatchInlineSnapshot(`
[
{
"blockNumber": 20n,
"blockNumber": 28n,
"chainId": 31337,
"version": "0.0.4",
},
Expand All @@ -70,8 +70,8 @@ describe("createStorageAdapter", async () => {
).toMatchInlineSnapshot(`
[
{
"address": "0x2964aF56c8aACdE425978a28b018956D21cF50f0",
"blockNumber": 20n,
"address": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f",
"blockNumber": 28n,
"dynamicData": "0x000001a400000045",
"encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008",
"isDeleted": false,
Expand All @@ -89,7 +89,8 @@ describe("createStorageAdapter", async () => {
expect(tables).toMatchInlineSnapshot(`
[
{
"address": "0x2964aF56c8aACdE425978a28b018956D21cF50f0",
"address": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f",

"keySchema": {},
"name": "NumberList",
"namespace": "",
Expand All @@ -106,7 +107,7 @@ describe("createStorageAdapter", async () => {
[
{
"__keyBytes": "0x",
"__lastUpdatedBlockNumber": 20n,
"__lastUpdatedBlockNumber": 23n,
"value": [
420,
69,
Expand Down
Expand Up @@ -48,7 +48,7 @@ describe("createStorageAdapter", async () => {
expect(await db.select().from(storageAdapter.tables.configTable)).toMatchInlineSnapshot(`
[
{
"blockNumber": 20n,
"blockNumber": 28n,
"chainId": 31337,
"version": "0.0.4",
},
Expand All @@ -68,8 +68,8 @@ describe("createStorageAdapter", async () => {
).toMatchInlineSnapshot(`
[
{
"address": "0x2964aF56c8aACdE425978a28b018956D21cF50f0",
"blockNumber": 20n,
"address": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f",
"blockNumber": 28n,
"dynamicData": "0x000001a400000045",
"encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008",
"isDeleted": false,
Expand Down
18 changes: 10 additions & 8 deletions packages/store-sync/src/sqlite/sqliteStorage.test.ts
Expand Up @@ -64,7 +64,7 @@ describe("sqliteStorage", async () => {
{
"chainId": 31337,
"lastError": null,
"lastUpdatedBlockNumber": 20n,
"lastUpdatedBlockNumber": 28n,
"schemaVersion": 1,
},
]
Expand All @@ -73,11 +73,12 @@ describe("sqliteStorage", async () => {
expect(db.select().from(mudStoreTables).where(eq(mudStoreTables.name, "NumberList")).all()).toMatchInlineSnapshot(`
[
{
"address": "0x2964aF56c8aACdE425978a28b018956D21cF50f0",
"id": "0x2964aF56c8aACdE425978a28b018956D21cF50f0____NumberList",
"address": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f",

"id": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f____NumberList",
"keySchema": {},
"lastError": null,
"lastUpdatedBlockNumber": 20n,
"lastUpdatedBlockNumber": 28n,
"name": "NumberList",
"namespace": "",
"schemaVersion": 1,
Expand All @@ -93,11 +94,12 @@ describe("sqliteStorage", async () => {
expect(tables).toMatchInlineSnapshot(`
[
{
"address": "0x2964aF56c8aACdE425978a28b018956D21cF50f0",
"id": "0x2964aF56c8aACdE425978a28b018956D21cF50f0____NumberList",
"address": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f",

"id": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f____NumberList",
"keySchema": {},
"lastError": null,
"lastUpdatedBlockNumber": 20n,
"lastUpdatedBlockNumber": 28n,
"name": "NumberList",
"namespace": "",
"schemaVersion": 1,
Expand All @@ -117,7 +119,7 @@ describe("sqliteStorage", async () => {
"__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008",
"__isDeleted": false,
"__key": "0x",
"__lastUpdatedBlockNumber": 20n,
"__lastUpdatedBlockNumber": 23n,
"__staticData": null,
"value": [
420,
Expand Down
52 changes: 26 additions & 26 deletions packages/store/gas-report.json
Expand Up @@ -15,7 +15,7 @@
"file": "test/Callbacks.t.sol",
"test": "testSetAndGet",
"name": "Callbacks: set field",
"gasUsed": 55829
"gasUsed": 56409
},
{
"file": "test/Callbacks.t.sol",
Expand All @@ -27,7 +27,7 @@
"file": "test/Callbacks.t.sol",
"test": "testSetAndGet",
"name": "Callbacks: push 1 element",
"gasUsed": 32114
"gasUsed": 32694
},
{
"file": "test/FieldLayout.t.sol",
Expand Down Expand Up @@ -621,25 +621,25 @@
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromSecondField",
"name": "pop from field (cold, 1 slot, 1 uint32 item)",
"gasUsed": 17819
"gasUsed": 18398
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromSecondField",
"name": "pop from field (warm, 1 slot, 1 uint32 item)",
"gasUsed": 11825
"gasUsed": 12406
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromThirdField",
"name": "pop from field (cold, 2 slots, 10 uint32 items)",
"gasUsed": 15588
"gasUsed": 16167
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromThirdField",
"name": "pop from field (warm, 2 slots, 10 uint32 items)",
"gasUsed": 11594
"gasUsed": 12174
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -705,7 +705,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testHooks",
"name": "register subscriber",
"gasUsed": 56304
"gasUsed": 56877
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -729,7 +729,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testHooksDynamicData",
"name": "register subscriber",
"gasUsed": 56304
"gasUsed": 56877
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -741,7 +741,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testHooksDynamicData",
"name": "set (dynamic) field on table with subscriber",
"gasUsed": 23856
"gasUsed": 25009
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -753,13 +753,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testPushToDynamicField",
"name": "push to field (1 slot, 1 uint32 item)",
"gasUsed": 9250
"gasUsed": 9831
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testPushToDynamicField",
"name": "push to field (2 slots, 10 uint32 items)",
"gasUsed": 31922
"gasUsed": 32503
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -855,7 +855,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set dynamic field (1 slot, first dynamic field)",
"gasUsed": 53732
"gasUsed": 54314
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -867,7 +867,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set dynamic field (1 slot, second dynamic field)",
"gasUsed": 31957
"gasUsed": 32539
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -909,13 +909,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testUpdateInDynamicField",
"name": "update in field (1 slot, 1 uint32 item)",
"gasUsed": 8610
"gasUsed": 9190
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testUpdateInDynamicField",
"name": "push to field (2 slots, 6 uint64 items)",
"gasUsed": 9053
"gasUsed": 9634
},
{
"file": "test/StoreHook.t.sol",
Expand Down Expand Up @@ -945,13 +945,13 @@
"file": "test/StoreHooks.t.sol",
"test": "testOneSlot",
"name": "StoreHooks: set field with one elements (cold)",
"gasUsed": 57824
"gasUsed": 58404
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: set field (cold)",
"gasUsed": 57824
"gasUsed": 58403
},
{
"file": "test/StoreHooks.t.sol",
Expand All @@ -963,25 +963,25 @@
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: push 1 element (cold)",
"gasUsed": 12202
"gasUsed": 12782
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: pop 1 element (warm)",
"gasUsed": 9506
"gasUsed": 10087
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: push 1 element (warm)",
"gasUsed": 10218
"gasUsed": 10799
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: update 1 element (warm)",
"gasUsed": 29452
"gasUsed": 30033
},
{
"file": "test/StoreHooks.t.sol",
Expand All @@ -993,19 +993,19 @@
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: set field (warm)",
"gasUsed": 29965
"gasUsed": 30548
},
{
"file": "test/StoreHooks.t.sol",
"test": "testThreeSlots",
"name": "StoreHooks: set field with three elements (cold)",
"gasUsed": 80515
"gasUsed": 81094
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTwoSlots",
"name": "StoreHooks: set field with two elements (cold)",
"gasUsed": 80427
"gasUsed": 81006
},
{
"file": "test/StoreHooksColdLoad.t.sol",
Expand Down Expand Up @@ -1035,13 +1035,13 @@
"file": "test/StoreHooksColdLoad.t.sol",
"test": "testPop",
"name": "StoreHooks: pop 1 element (cold)",
"gasUsed": 17942
"gasUsed": 18522
},
{
"file": "test/StoreHooksColdLoad.t.sol",
"test": "testUpdate",
"name": "StoreHooks: update 1 element (cold)",
"gasUsed": 19906
"gasUsed": 20485
},
{
"file": "test/StoreSwitch.t.sol",
Expand Down