Skip to content

Commit

Permalink
feat(store): add field index to Store_SpliceDynamicData event (#2279)
Browse files Browse the repository at this point in the history
Co-authored-by: Kevin Ingersoll <kingersoll@gmail.com>
  • Loading branch information
yonadaaa and holic committed Feb 21, 2024
1 parent a02da55 commit 8193136
Show file tree
Hide file tree
Showing 15 changed files with 840 additions and 730 deletions.
6 changes: 6 additions & 0 deletions .changeset/rich-deers-doubt.md
@@ -0,0 +1,6 @@
---
"@latticexyz/store": major
"@latticexyz/store-sync": major
---

Added `dynamicFieldIndex` to the `Store_SpliceDynamicData` event. This enables indexers to store dynamic data as a blob per dynamic field without a schema lookup.
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.6",
},
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,7 @@ describe("createStorageAdapter", async () => {
expect(tables).toMatchInlineSnapshot(`
[
{
"address": "0x2964aF56c8aACdE425978a28b018956D21cF50f0",
"address": "0xd843FB6A5fD209344E5A1b3d5c121330c2B4a36f",
"keySchema": {},
"name": "NumberList",
"namespace": "",
Expand All @@ -106,7 +106,7 @@ describe("createStorageAdapter", async () => {
[
{
"__keyBytes": "0x",
"__lastUpdatedBlockNumber": 20n,
"__lastUpdatedBlockNumber": 28n,
"value": [
420,
69,
Expand Down
6 changes: 3 additions & 3 deletions packages/store-sync/src/postgres/createStorageAdapter.test.ts
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.6",
},
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
16 changes: 8 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,11 @@ 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 +93,11 @@ 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 +117,7 @@ describe("sqliteStorage", async () => {
"__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008",
"__isDeleted": false,
"__key": "0x",
"__lastUpdatedBlockNumber": 20n,
"__lastUpdatedBlockNumber": 28n,
"__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": 56118
},
{
"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": 32402
},
{
"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": 18107
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromSecondField",
"name": "pop from field (warm, 1 slot, 1 uint32 item)",
"gasUsed": 11825
"gasUsed": 12114
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromThirdField",
"name": "pop from field (cold, 2 slots, 10 uint32 items)",
"gasUsed": 15588
"gasUsed": 15876
},
{
"file": "test/StoreCoreDynamic.t.sol",
"test": "testPopFromThirdField",
"name": "pop from field (warm, 2 slots, 10 uint32 items)",
"gasUsed": 11594
"gasUsed": 11883
},
{
"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": 56589
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -729,7 +729,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testHooksDynamicData",
"name": "register subscriber",
"gasUsed": 56304
"gasUsed": 56589
},
{
"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": 24430
},
{
"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": 9539
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testPushToDynamicField",
"name": "push to field (2 slots, 10 uint32 items)",
"gasUsed": 31922
"gasUsed": 32211
},
{
"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": 54022
},
{
"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": 32246
},
{
"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": 8899
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testUpdateInDynamicField",
"name": "push to field (2 slots, 6 uint64 items)",
"gasUsed": 9053
"gasUsed": 9342
},
{
"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": 58112
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: set field (cold)",
"gasUsed": 57824
"gasUsed": 58112
},
{
"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": 12491
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: pop 1 element (warm)",
"gasUsed": 9506
"gasUsed": 9795
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: push 1 element (warm)",
"gasUsed": 10218
"gasUsed": 10507
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTable",
"name": "StoreHooks: update 1 element (warm)",
"gasUsed": 29452
"gasUsed": 29741
},
{
"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": 30255
},
{
"file": "test/StoreHooks.t.sol",
"test": "testThreeSlots",
"name": "StoreHooks: set field with three elements (cold)",
"gasUsed": 80515
"gasUsed": 80803
},
{
"file": "test/StoreHooks.t.sol",
"test": "testTwoSlots",
"name": "StoreHooks: set field with two elements (cold)",
"gasUsed": 80427
"gasUsed": 80715
},
{
"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": 18231
},
{
"file": "test/StoreHooksColdLoad.t.sol",
"test": "testUpdate",
"name": "StoreHooks: update 1 element (cold)",
"gasUsed": 19906
"gasUsed": 20194
},
{
"file": "test/StoreSwitch.t.sol",
Expand Down

0 comments on commit 8193136

Please sign in to comment.