Skip to content

Commit d97be80

Browse files
authored
Declaring preimages and lookup history (#101)
* preimages and lookup history validation * passing data from deploy command to genesis generator * adding preimages to genesis state * calculating storage
1 parent b1c27fd commit d97be80

File tree

6 files changed

+658
-78
lines changed

6 files changed

+658
-78
lines changed

packages/jammin-sdk/config/config-validator.test.ts

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,295 @@ describe("Validate Build Config", () => {
520520
});
521521
});
522522

523+
describe("Preimage Blobs Config Validation", () => {
524+
test("Should parse valid preimage_blobs config", () => {
525+
const config = {
526+
services: [
527+
{
528+
path: "./services/auth.ts",
529+
name: "auth-service",
530+
sdk: "jam-sdk-0.1.26",
531+
},
532+
],
533+
deployment: {
534+
spawn: "local",
535+
services: {
536+
"auth-service": {
537+
preimage_blobs: {
538+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xdeadbeef",
539+
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": "0xadadadadad",
540+
},
541+
},
542+
},
543+
},
544+
};
545+
546+
const result = validateBuildConfig(config);
547+
expect(result.deployment?.services?.["auth-service"]?.preimageBlobs).toEqual({
548+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xdeadbeef",
549+
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": "0xadadadadad",
550+
});
551+
});
552+
553+
test("Should reject preimage_blobs with hash missing 0x prefix", () => {
554+
const config = {
555+
services: [
556+
{
557+
path: "./services/auth.ts",
558+
name: "auth-service",
559+
sdk: "jam-sdk-0.1.26",
560+
},
561+
],
562+
deployment: {
563+
spawn: "local",
564+
services: {
565+
"auth-service": {
566+
preimage_blobs: {
567+
"0000000000000000000000000000000000000000000000000000000000000001": "0x1234",
568+
},
569+
},
570+
},
571+
},
572+
};
573+
574+
expect(() => validateBuildConfig(config)).toThrow();
575+
});
576+
577+
test("Should reject preimage_blobs with blob missing 0x prefix", () => {
578+
const config = {
579+
services: [
580+
{
581+
path: "./services/auth.ts",
582+
name: "auth-service",
583+
sdk: "jam-sdk-0.1.26",
584+
},
585+
],
586+
deployment: {
587+
spawn: "local",
588+
services: {
589+
"auth-service": {
590+
preimage_blobs: {
591+
"0x0000000000000000000000000000000000000000000000000000000000000001": "deadbeef",
592+
},
593+
},
594+
},
595+
},
596+
};
597+
598+
expect(() => validateBuildConfig(config)).toThrow();
599+
});
600+
601+
test("Should reject preimage_blobs with blob consisting of an uneven number of characters", () => {
602+
const config = {
603+
services: [
604+
{
605+
path: "./services/auth.ts",
606+
name: "auth-service",
607+
sdk: "jam-sdk-0.1.26",
608+
},
609+
],
610+
deployment: {
611+
spawn: "local",
612+
services: {
613+
"auth-service": {
614+
preimage_blobs: {
615+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xabc",
616+
},
617+
},
618+
},
619+
},
620+
};
621+
622+
expect(() => validateBuildConfig(config)).toThrow();
623+
});
624+
625+
test("Should reject preimage_blobs where hash is not 32 bytes long", () => {
626+
const config = {
627+
services: [
628+
{
629+
path: "./services/auth.ts",
630+
name: "auth-service",
631+
sdk: "jam-sdk-0.1.26",
632+
},
633+
],
634+
deployment: {
635+
spawn: "local",
636+
services: {
637+
"auth-service": {
638+
preimage_blobs: {
639+
"0x00000000000000000000000000000001": "0xdeadbeef", // 16 bytes instead of 32
640+
},
641+
},
642+
},
643+
},
644+
};
645+
646+
expect(() => validateBuildConfig(config)).toThrow();
647+
});
648+
});
649+
650+
describe("Preimage Requests Config Validation", () => {
651+
test("Should parse valid preimage_requests config", () => {
652+
const config = {
653+
services: [
654+
{
655+
path: "./services/auth.ts",
656+
name: "auth-service",
657+
sdk: "jam-sdk-0.1.26",
658+
},
659+
],
660+
deployment: {
661+
spawn: "local",
662+
services: {
663+
"auth-service": {
664+
preimage_requests: {
665+
"0x0000000000000000000000000000000000000000000000000000000000000001": [100, 200, 300],
666+
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": [42],
667+
},
668+
},
669+
},
670+
},
671+
};
672+
673+
const result = validateBuildConfig(config);
674+
expect(result.deployment?.services?.["auth-service"]?.preimageRequests).toEqual({
675+
"0x0000000000000000000000000000000000000000000000000000000000000001": [100, 200, 300],
676+
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": [42],
677+
});
678+
});
679+
680+
test("Should accept preimage_requests with empty array", () => {
681+
const config = {
682+
services: [
683+
{
684+
path: "./services/auth.ts",
685+
name: "auth-service",
686+
sdk: "jam-sdk-0.1.26",
687+
},
688+
],
689+
deployment: {
690+
spawn: "local",
691+
services: {
692+
"auth-service": {
693+
preimage_requests: {
694+
"0x0000000000000000000000000000000000000000000000000000000000000001": [],
695+
},
696+
},
697+
},
698+
},
699+
};
700+
701+
const result = validateBuildConfig(config);
702+
expect(result.deployment?.services?.["auth-service"]?.preimageRequests).toEqual({
703+
"0x0000000000000000000000000000000000000000000000000000000000000001": [],
704+
});
705+
});
706+
707+
test("Should accept preimage_requests with 1, 2, and 3 time slots", () => {
708+
const config = {
709+
services: [
710+
{
711+
path: "./services/auth.ts",
712+
name: "auth-service",
713+
sdk: "jam-sdk-0.1.26",
714+
},
715+
],
716+
deployment: {
717+
spawn: "local",
718+
services: {
719+
"auth-service": {
720+
preimage_requests: {
721+
"0x0000000000000000000000000000000000000000000000000000000000000001": [1],
722+
"0x0000000000000000000000000000000000000000000000000000000000000002": [1, 2],
723+
"0x0000000000000000000000000000000000000000000000000000000000000003": [1, 2, 3],
724+
},
725+
},
726+
},
727+
},
728+
};
729+
730+
const result = validateBuildConfig(config);
731+
const preimageRequests = result.deployment?.services?.["auth-service"]?.preimageRequests;
732+
expect(preimageRequests?.["0x0000000000000000000000000000000000000000000000000000000000000001"]).toEqual([1]);
733+
expect(preimageRequests?.["0x0000000000000000000000000000000000000000000000000000000000000002"]).toEqual([1, 2]);
734+
expect(preimageRequests?.["0x0000000000000000000000000000000000000000000000000000000000000003"]).toEqual([
735+
1, 2, 3,
736+
]);
737+
});
738+
739+
test("Should reject preimage_requests with more than 3 time slots", () => {
740+
const config = {
741+
services: [
742+
{
743+
path: "./services/auth.ts",
744+
name: "auth-service",
745+
sdk: "jam-sdk-0.1.26",
746+
},
747+
],
748+
deployment: {
749+
spawn: "local",
750+
services: {
751+
"auth-service": {
752+
preimage_requests: {
753+
"0x0000000000000000000000000000000000000000000000000000000000000001": [1, 2, 3, 4],
754+
},
755+
},
756+
},
757+
},
758+
};
759+
760+
expect(() => validateBuildConfig(config)).toThrow();
761+
});
762+
763+
test("Should reject preimage_requests with non-integer time slot values", () => {
764+
const config = {
765+
services: [
766+
{
767+
path: "./services/auth.ts",
768+
name: "auth-service",
769+
sdk: "jam-sdk-0.1.26",
770+
},
771+
],
772+
deployment: {
773+
spawn: "local",
774+
services: {
775+
"auth-service": {
776+
preimage_requests: {
777+
"0x0000000000000000000000000000000000000000000000000000000000000001": [100.5, 200],
778+
},
779+
},
780+
},
781+
},
782+
};
783+
784+
expect(() => validateBuildConfig(config)).toThrow();
785+
});
786+
787+
test("Should reject preimage_requests with negative time slot values", () => {
788+
const config = {
789+
services: [
790+
{
791+
path: "./services/auth.ts",
792+
name: "auth-service",
793+
sdk: "jam-sdk-0.1.26",
794+
},
795+
],
796+
deployment: {
797+
spawn: "local",
798+
services: {
799+
"auth-service": {
800+
preimage_requests: {
801+
"0x0000000000000000000000000000000000000000000000000000000000000001": [-10, 0, 100],
802+
},
803+
},
804+
},
805+
},
806+
};
807+
808+
expect(() => validateBuildConfig(config)).toThrow();
809+
});
810+
});
811+
523812
describe("Service Info Config Validation", () => {
524813
test("Should parse valid info config with all fields", () => {
525814
const config = {

packages/jammin-sdk/config/config-validator.ts

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ const MAX_U64 = 18_446_744_073_709_551_615n;
99
const u64Schema = () =>
1010
z.union([z.bigint().min(0n).max(MAX_U64), z.number().int().min(0)]).transform((val) => BigInt(val));
1111
const u32Schema = () => z.number().int().min(0).max(MAX_U32);
12+
const preimageHashSchema = () =>
13+
z
14+
.string()
15+
.regex(/^0x[0-9a-fA-F]+$/)
16+
.length(66);
1217

1318
// jammin.build.yml schema
1419

@@ -30,41 +35,52 @@ const ServiceConfigSchema = z.object({
3035
),
3136
});
3237

33-
const ServiceDeploymentConfigSchema = z.object({
34-
id: u32Schema().optional(),
35-
storage: z.record(z.string(), z.string()).optional(),
36-
info: z
37-
.object({
38-
balance: u64Schema().optional(),
39-
accumulate_min_gas: u64Schema().optional(),
40-
on_transfer_min_gas: u64Schema().optional(),
41-
storage_utilisation_bytes: u64Schema().optional(),
42-
gratis_storage: u64Schema().optional(),
43-
storage_utilisation_count: u32Schema().optional(),
44-
created: u32Schema().optional(),
45-
last_accumulation: u32Schema().optional(),
46-
parent_service: u32Schema().optional(),
47-
})
48-
.transform((info) => {
49-
// snake to camel case
50-
if (!info) {
51-
return undefined;
52-
}
53-
const transformed = {
54-
balance: info.balance,
55-
accumulateMinGas: info.accumulate_min_gas,
56-
onTransferMinGas: info.on_transfer_min_gas,
57-
storageUtilisationBytes: info.storage_utilisation_bytes,
58-
gratisStorage: info.gratis_storage,
59-
storageUtilisationCount: info.storage_utilisation_count,
60-
created: info.created,
61-
lastAccumulation: info.last_accumulation,
62-
parentService: info.parent_service,
63-
};
64-
return transformed;
65-
})
66-
.optional(),
67-
});
38+
const ServiceDeploymentConfigSchema = z
39+
.object({
40+
id: u32Schema().optional(),
41+
storage: z.record(z.string(), z.string()).optional(),
42+
preimage_blobs: z.record(preimageHashSchema(), z.string().regex(/^0x([0-9a-fA-F]{2})+$/)).optional(),
43+
preimage_requests: z.record(preimageHashSchema(), z.array(u32Schema()).max(3)).optional(),
44+
info: z
45+
.object({
46+
balance: u64Schema().optional(),
47+
accumulate_min_gas: u64Schema().optional(),
48+
on_transfer_min_gas: u64Schema().optional(),
49+
storage_utilisation_bytes: u64Schema().optional(),
50+
gratis_storage: u64Schema().optional(),
51+
storage_utilisation_count: u32Schema().optional(),
52+
created: u32Schema().optional(),
53+
last_accumulation: u32Schema().optional(),
54+
parent_service: u32Schema().optional(),
55+
})
56+
.transform((info) => {
57+
// snake to camel case
58+
if (!info) {
59+
return undefined;
60+
}
61+
const transformed = {
62+
balance: info.balance,
63+
accumulateMinGas: info.accumulate_min_gas,
64+
onTransferMinGas: info.on_transfer_min_gas,
65+
storageUtilisationBytes: info.storage_utilisation_bytes,
66+
gratisStorage: info.gratis_storage,
67+
storageUtilisationCount: info.storage_utilisation_count,
68+
created: info.created,
69+
lastAccumulation: info.last_accumulation,
70+
parentService: info.parent_service,
71+
};
72+
return transformed;
73+
})
74+
.optional(),
75+
})
76+
.transform((config) => {
77+
const { preimage_blobs, preimage_requests, ...rest } = config;
78+
return {
79+
...rest,
80+
preimageBlobs: preimage_blobs,
81+
preimageRequests: preimage_requests,
82+
};
83+
});
6884

6985
const DeploymentConfigSchema = z.object({
7086
spawn: z.string().min(1),

0 commit comments

Comments
 (0)