Skip to content

Conversation

@skoszuta
Copy link
Contributor

@skoszuta skoszuta commented Jan 29, 2026

Resolves #48

Proposed YAML schema:

deployment:
  spawn: local
  services:
    jambrains:
      preimages:
        "0xf8d86b97d65319a078e5840f1614c296a5254217794dcc910e72ca174e3c2e86": "0x18000f4e554c4c20417574686f72697a65720131034343300000000000000000000000000a00000000000633073308320015"
      lookup_history:
        "0xf8d86b97d65319a078e5840f1614c296a5254217794dcc910e72ca174e3c2e86": [1, 2, 3]

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

This PR extends the service deployment infrastructure to support preimages and lookup_history. New optional fields are added to the deployment configuration, validated with schemas, passed through the generateServiceOutput function, and processed during genesis state generation to provision preimage data and update lookup histories.

Changes

Cohort / File(s) Summary
CLI Configuration & Validation
bin/cli/types/config.ts, bin/cli/utils/config-validator.ts
Added preimages (Record<string, string>) and lookup_history (Record<string, number[]>) fields to ServiceDeploymentConfig with validation schemas requiring 0x-prefixed hex for hashes/blobs and max 3 slots per lookup history entry.
CLI Configuration Tests
bin/cli/utils/config-validator.test.ts
Added 290+ lines of test coverage for preimages and lookup_history validation, including acceptance cases for various slot counts and rejection cases for invalid formats (missing 0x prefix, uneven hex lengths, oversized arrays).
CLI Deployment Command
bin/cli/src/commands/deploy-command.ts
Updated generateServiceOutput call to pass two additional optional parameters: preimages and lookup_history from deploymentConfig.
SDK Service Output
packages/jammin-sdk/util/generate-service-output.ts
Extended function signature to accept optional preimages and lookupHistory parameters; added corresponding public fields to ServiceBuildOutput (HashDictionary and Map types for preimage data).
SDK Genesis State Generation
packages/jammin-sdk/genesis-state-generator.ts, packages/jammin-sdk/genesis-state-generator.test.ts
Added logic to validate and process per-service preimages and lookup histories during state generation, including validation that preimage blobs exist for each lookup entry; expanded tests from 36 to 234 lines covering empty services, storage, custom service info, preimages with various slot configurations, and error cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • Generate genesis state #55: Extends service build output with preimages and lookup_history, directly modifying generateServiceOutput and genesis-state-generator consumed by this PR.
  • Core YAML Infrastructure + Build config #36: Extends deployment config types and schemas that are now receiving preimages and lookup_history fields.
  • Service deployment config #82: Modifies generateServiceOutput call in deploy-command to pass per-service deployment metadata, same integration point as this PR's updates.

Suggested reviewers

  • tomusdrw
  • mateuszsikora
  • DrEverr
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Declaring preimages and lookup history' clearly and concisely summarizes the main change—adding support for preimages and lookup history configuration to the deployment system.
Description check ✅ Passed The PR description is directly related to the changeset, providing issue reference, YAML schema example, and detailing the preimages and lookup_history feature being added.
Linked Issues check ✅ Passed The PR resolves issue #48 by implementing support for declaring preimages and lookup history in deployment configuration with validation, state generation, and CLI integration.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing preimages and lookup history support as specified in issue #48; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sk-preimages-and-lookup

Comment @coderabbitai help to get the list of available commands and usage tips.

@skoszuta skoszuta marked this pull request as ready for review January 29, 2026 10:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@bin/cli/utils/config-validator.test.ts`:
- Around line 785-810: Update the test so it expects validation to reject
negative slot values instead of accepting them: use validateBuildConfig (the
function under test) to assert it returns an error or throws for the provided
config containing negative lookup_history slots (i.e., ensure the validation
fails and surfaces an error mentioning lookup_history/Slot out-of-range),
referencing validateBuildConfig and the Slot validation rule so the test
confirms negative numbers are invalid.

In `@bin/cli/utils/config-validator.ts`:
- Around line 38-42: The lookup_history property in
ServiceDeploymentConfigSchema currently accepts any integers but must match
Slot() constraints (unsigned 32-bit) to avoid runtime crashes; update the
lookup_history record value schema (the z.array(...) for lookup_history) to only
allow integers that are integer, >= 0 and <= 0xffffffff and still enforce max(3)
per array so invalid negative or too-large slot values are rejected at
validation time (update the schema expression referenced by
ServiceDeploymentConfigSchema and the lookup_history key; no other behavioral
changes).
🧹 Nitpick comments (3)
packages/jammin-sdk/util/generate-service-output.ts (1)

25-41: Add JSDoc for the public API signature (new params).
This function is exported and now has new parameters; adding JSDoc keeps the public surface documented.

✍️ Suggested JSDoc
+/**
+ * Build service output from a JAM file and optional deployment overrides.
+ * `@param` jamFilePath Path to the JAM file.
+ * `@param` serviceId Numeric service identifier (u32).
+ * `@param` storage Optional storage key/value pairs.
+ * `@param` info Optional service account info overrides.
+ * `@param` preimages Optional map of preimage hashes to blobs.
+ * `@param` lookupHistory Optional map of preimage hashes to lookup history slots.
+ */
 export async function generateServiceOutput(

As per coding guidelines, Use JSDoc comments for public APIs (functions, classes, exported types).

packages/jammin-sdk/genesis-state-generator.test.ts (2)

151-167: Strengthen preimage and lookup history test assertions.

These tests verify that generateState doesn't crash and creates a service account, but they don't actually verify that the preimages are stored and retrievable from the service. Since preimages and lookup history are the main feature of this PR, consider adding assertions that verify the data is actually persisted.

For example, after generating state, retrieve the preimage from the service account and compare it to the expected value.

💡 Suggested enhancement for stronger assertions
       const state = generateState([serviceWithPreimages]);

       expect(state).toBeDefined();
       const serviceAccount = state.services.get(ServiceId(300));
       expect(serviceAccount).toBeDefined();
+
+      // Verify preimage is actually stored and retrievable
+      const storedPreimage = serviceAccount?.getPreimage(preimageHash, preimageBlob.length);
+      expect(storedPreimage?.toString()).toBe(preimageBlob.toString());
     });

Similarly for the multiple slots test - verify the lookup history entries are accessible.

Also applies to: 169-185


29-29: Remove unnecessary async keywords from test functions.

Multiple test functions are marked as async but don't contain any await expressions. While not harmful, this adds unnecessary overhead and could be misleading to readers.

♻️ Example fix for one test
-    test("should generate genesis with basic services", async () => {
+    test("should generate genesis with basic services", () => {

Apply similarly to other affected tests.

Also applies to: 49-49, 59-59, 91-91, 112-112, 129-129, 151-151, 169-169, 187-187

Copy link
Member

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

lgtm! I would just consider aligning the format with some existing json vectors from w3f, but afaik these has recently changed

@skoszuta
Copy link
Contributor Author

@tomusdrw do you think we should increment storage utilisation for these preimages?

@DrEverr
Copy link
Member

DrEverr commented Jan 29, 2026

what if our preimage hash is not a hash of a preimage, aka. our key to preimage is incorrect? Maybe we shoul provide preimages by simply giving preimageBlob and its availability, and it creates correct keys internally?

@tomusdrw
Copy link
Member

@tomusdrw do you think we should increment storage utilisation for these preimages?

if storage is not given by the user - yes, it should be calculated from these storage items. otherwise - it's up to the user (plus the warning that we've discussed in another pr).

@tomusdrw
Copy link
Member

what if our preimage hash is not a hash of a preimage, aka. our key to preimage is incorrect? Maybe we shoul provide preimages by simply giving preimageBlob and its availability, and it creates correct keys internally?

good point. just providing blobs would be more friendly, but the question then is - how do we know what the hashes are and what lookup items are needed? (btw, we should probably also suggest to the user that a preimage blob needs valid lookup history slots as well).

Providing "fake" blobs for some hashes is useful, but I think it might be better suited as some sort of "override" configuration where we know we explicitly want to break some consistency assumptions. Thinking about it now, having custom storage count/bytes falls into the same category. I'll leave the decision to you guys, I think it's fine either way, and we yet have to figure out what use cases are there and what kind of format brings the most value.

@DrEverr
Copy link
Member

DrEverr commented Jan 29, 2026

We are building state by using Updates
so we can easily calculate correct key

    const blob = BytesBlob.parseBlob("0x18000f4e554c4c20417574686f72697a65720131034343300000000000000000000000000a00000000000633073308320015");
    const hash = blake2b.hashBytes(blob).asOpaque();
    const preimage = PreimageItem.create({ hash, blob });
    const preimageLookupHistory = new LookupHistoryItem(
      hash,
      U32(blob.raw.length),
      tryAsLookupHistorySlots([Slot(1), Slot(2), Slot(3)]),
    );

    update.preimages?.set(serviceId, [
      UpdatePreimage.provide({
        preimage,
        slot: Slot(0),
        providedFor: serviceId,
      }),
      UpdatePreimage.updateOrAdd({ lookupHistory: preimageLookupHistory }),
    ]);

so IMO we could simply provide preimages like

deployment:
  spawn: local
  services:
    jambrains:
      preimages:
          "0x18000f4e554c4c20417574686f72697a65720131034343300000000000000000000000000a00000000000633073308320015" : [1, 2, 3]

and even the lookup history can simply default to [0], so in preimages we could also provide just a blob, without : [1, 2, 3]

@skoszuta
Copy link
Contributor Author

We are building state by using Updates so we can easily calculate correct key

    const blob = BytesBlob.parseBlob("0x18000f4e554c4c20417574686f72697a65720131034343300000000000000000000000000a00000000000633073308320015");
    const hash = blake2b.hashBytes(blob).asOpaque();
    const preimage = PreimageItem.create({ hash, blob });
    const preimageLookupHistory = new LookupHistoryItem(
      hash,
      U32(blob.raw.length),
      tryAsLookupHistorySlots([Slot(1), Slot(2), Slot(3)]),
    );

    update.preimages?.set(serviceId, [
      UpdatePreimage.provide({
        preimage,
        slot: Slot(0),
        providedFor: serviceId,
      }),
      UpdatePreimage.updateOrAdd({ lookupHistory: preimageLookupHistory }),
    ]);

so IMO we could simply provide preimages like

deployment:
  spawn: local
  services:
    jambrains:
      preimages:
          "0x18000f4e554c4c20417574686f72697a65720131034343300000000000000000000000000a00000000000633073308320015" : [1, 2, 3]

and even the lookup history can simply default to [0], so in preimages we could also provide just a blob, without : [1, 2, 3]

this won't work:

  • YAML has a 1024 character limit on non-explicit keys. if you want to provide a longer key you must precede it with a "?". i doubt anybody wants to do that
  • extremely long and variable-length keys with short values is the epitome of unreadable config

besides, dropping the hash limits debugging possibilites for the user. some that come to mind:

  • prevents the user from mocking blobs or injecting debug versions
  • makes it necessary to provide a blob (and a correct one at that) even if you only want to add a preimage request and provide the blob in a block later

given the nature of this project i think keeping extra debugging flexibility is a worthy goal.

for the time being i dont see any convincing arguments for change or even a format that would actually work so will keep the current format, plus new naming. future changes are very welcome if it turns out there are practical benefits to the user.

@coderabbitai coderabbitai bot requested a review from tomusdrw January 30, 2026 10:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/jammin-sdk/genesis-state-generator.test.ts`:
- Around line 2-10: The import for ServiceBuildOutput is using the wrong
relative directory; update the import in genesis-state-generator.test.ts to
import ServiceBuildOutput from "./utils/generate-service-output" (replace
"./util/generate-service-output" with "./utils/generate-service-output") so the
ServiceBuildOutput type resolves correctly when running tests that use
generateGenesis, generateState, and toJip4Schema.

In `@packages/jammin-sdk/genesis-state-generator.ts`:
- Around line 152-170: The storage counting currently adds
LOOKUP_HISTORY_ENTRY_BYTES and the preimageBlob length and increments
calculatedStorageCount by 2 unconditionally; change it so
LOOKUP_HISTORY_ENTRY_BYTES (the lookup-history entry overhead) is counted always
but only add BigInt(preimageBlob.length) via sumU64 and increment
calculatedStorageCount with sumU32 when a preimage is actually provided (i.e.,
when preimageBlob is non-null/defined and slots.length >= 1 and you push
UpdatePreimage.provide/PreimageItem.create); update the code around
calculatedStorageBytes, calculatedStorageCount, sumU64, sumU32, preimageBlob,
slots and the UpdatePreimage.provide block so blob bytes and the extra count are
only added inside the branch that creates the preimage.

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.

Declaring additional preimages & lookup data

5 participants