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(world, store): stop loading schema from storage, require schema as an argument #1174

Merged
merged 21 commits into from
Aug 16, 2023

Conversation

alvrs
Copy link
Member

@alvrs alvrs commented Jul 18, 2023

Fixes #1131
Breaking change: All of Store's read and write methods now require the table's value schema to be passed in instead of reading it from storage

@changeset-bot
Copy link

changeset-bot bot commented Jul 18, 2023

🦋 Changeset detected

Latest commit: b087930

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 26 packages
Name Type
@latticexyz/cli Major
@latticexyz/store Major
@latticexyz/world Major
create-mud Major
@latticexyz/std-client Major
@latticexyz/dev-tools Major
@latticexyz/react Major
@latticexyz/store-cache Major
@latticexyz/store-indexer Major
@latticexyz/store-sync Major
@latticexyz/ecs-browser Major
@latticexyz/block-logs-stream Major
@latticexyz/common Major
@latticexyz/config Major
@latticexyz/gas-report Major
@latticexyz/noise Major
@latticexyz/phaserx Major
@latticexyz/protocol-parser Major
@latticexyz/recs Major
@latticexyz/schema-type Major
@latticexyz/services Major
@latticexyz/solecs Major
solhint-config-mud Major
solhint-plugin-mud Major
@latticexyz/std-contracts Major
@latticexyz/utils Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@alvrs
Copy link
Member Author

alvrs commented Jul 18, 2023

We should probably wait for v2 networking to be merged and v1 networking to be removed to avoid double work in integrating this in the old stack.

@@ -261,13 +261,13 @@
"file": "test/Mixed.t.sol",
"test": "testSetAndGet",
"name": "set record in Mixed",
"gasUsed": 110021
"gasUsed": 111113
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very interesting that the gas cost increased for this one (while decreasing for the other tests). @dk1a do you have an intuition around why?

Copy link
Contributor

@dk1a dk1a Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty sure it's cause registerSchema is called in that test (before gas report), which warms the slot, so there's no gas reduction, but there is a new call to getSchema which is very suboptimal (should be better after #1252 and SchemaType->staticLength)

@alvrs alvrs marked this pull request as ready for review August 16, 2023 11:28
@alvrs alvrs requested a review from holic as a code owner August 16, 2023 11:28
Comment on lines +12 to +31
return mapObject(testData, (records, table) => {
if (!records) return undefined;
const keyConfig = config.tables[table].keySchema;
return records.map((record) => {
const encodedKey = Object.entries(record.key).map(([keyName, keyValue]) => {
const keyType = keyConfig[keyName as keyof typeof keyConfig] as StaticAbiType;
return encodeAbiParameters([{ type: keyType }], [keyValue]);
});

const encodedValue = encodePacked(Object.values(config.tables[table].schema), Object.values(record.value));

const encodedValueSchema = schemaToHex(abiTypesToSchema(Object.values(config.tables[table].schema)));

return {
key: encodedKey,
value: encodedValue,
valueSchema: encodedValueSchema,
};
});
}) as EncodedData<typeof testData>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change is fixing a type issue, adding the valueSchema to the encoded data and slightly refactoring because the nested functions became hard to read

Comment on lines 79 to 84
const address = await WorldContract.getField(
systemsTableId.toHex(),
[systemSelector.toHex()],
0,
systemTableSchema
);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getField now requires the value schema to be passed in

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another approach that might be a little less error prone if we change this schema later and forget to update this is to fetch the schema from the chain before we get field

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains the most significant changes (reading the schema from args instead of storage and renaming schema to valueSchema). The interface changes are then propagated through all the interfaces (IStore, World, etc)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passing the schema in all methods interacting with the store

@alvrs
Copy link
Member Author

alvrs commented Aug 16, 2023

This looks like a massive PR but it's mostly small refactors (passing the schema as arg to all methods interacting with the store). Added some PR comments to point out the relevant areas to make reviewing a bit easier.

holic
holic previously approved these changes Aug 16, 2023
Copy link
Member

@holic holic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Mostly just a question about where we want to put the schema arg.

bytes32 table,
bytes32[] calldata key,
bytes calldata data,
+ Schema valueSchema
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the argument ordering here make sense? I usually order args by specificity and would kind of expect valueSchema to be further ahead in the list of arguments (before or after table perhaps).

Unless it's an optional arg, then it being at the end makes a bit more sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree with ordering by specificity but would defer this refactor until after this current stack of PRs is merged since they touch lots of the same places in the code and changing it here would likely lead to massive merge conflicts in the upstream branches

@@ -1,5 +1,5 @@
{
"31337": {
"address": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
"address": "0xA7c59f010700930003b33aB25a7a0679C860f29c"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if this will muck with e2e tests or if this will get overwritten in CI after deploy

Comment on lines 3 to 6
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8.6.8

Comment on lines 79 to 84
const address = await WorldContract.getField(
systemsTableId.toHex(),
[systemSelector.toHex()],
0,
systemTableSchema
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another approach that might be a little less error prone if we change this schema later and forget to update this is to fetch the schema from the chain before we get field

@@ -90,7 +90,7 @@ library KeyEncoding {
_keyTuple[4] = _boolToBytes32(k5);
_keyTuple[5] = bytes32(uint256(uint8(k6)));

bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0);
bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getSchema());
Copy link
Member

@holic holic Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not blocking, just thinking aloud: I don't know the gas implications but I wonder if it would make sense to provide an alternative code path for these cases where we can generate a byte offset rather than a schema index + schema definition.

We could potentially do this for getters even if we don't commit to the bytes offset events changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this seems kinda related to #1222 and SchemaType removal, as we are moving away from validation in StoreCore and towards dealing with byte blobs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah could add this, but would defer the decision until after #1222

dk1a
dk1a previously approved these changes Aug 16, 2023
@@ -11,8 +11,10 @@ import { resolveWorldConfig, WorldConfig } from "@latticexyz/world";
import { IBaseWorld } from "@latticexyz/world/types/ethers-contracts/IBaseWorld";
import IBaseWorldData from "@latticexyz/world/abi/IBaseWorld.sol/IBaseWorld.json" assert { type: "json" };
import { getChainId, getExistingContracts } from "../utils";
import { schemaToHex } from "@latticexyz/protocol-parser";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be before the local import?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one day I'll add a linter/autofixer for this: #1277

@alvrs alvrs merged commit 952cd53 into main Aug 16, 2023
9 checks passed
@alvrs alvrs deleted the alvrs/schema-methods branch August 16, 2023 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove on-chain validation of schema from as many places as possible
3 participants