Skip to content

Commit 2c56ae1

Browse files
authored
Merge pull request #179 from fleet-sdk/arobsn/i176
Add `SBox` constant serialization
2 parents ddc1c71 + 82bd952 commit 2c56ae1

File tree

11 files changed

+83
-22
lines changed

11 files changed

+83
-22
lines changed

.changeset/smooth-planets-yawn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@fleet-sdk/serializer": patch
3+
---
4+
5+
Add `SBox` constant serialization and deserialization.

packages/serializer/src/_test-vectors/constantVectors.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
SShort
1313
} from "../types";
1414
import { type SConstructor, STuple } from "../types/constructors";
15+
import { validBoxes } from "_test-vectors";
1516

1617
const u8a = (input: number[]) => Uint8Array.from(input);
1718

@@ -585,3 +586,18 @@ export const tupleTestVectors: GenericTypeTestVector[] = [
585586
hex: "3c0c3c0e0e3c0c3c0e580c3c0e58060a6261636b67726f756e6404626c75650570756e6b730361706505626561726409626967206265617264056d6f757468066d6f6465737407676c617373657302767203746f700a7065616b207370696b650000"
586587
}
587588
];
589+
590+
export const sBoxVectors = [
591+
{
592+
value: validBoxes[0],
593+
hex: "63c0843d0008cd038d39af8c37583609ff51c6a577efe60684119da2fbd0d75f9c72372886a58a63cdee330150fdc80e168c153e472bd7e3dd18a4a0b9e90c550206fdbdb789ee8afdd3b1a90100ae11d207f0989945f63909d2f703b2640acf4f654a8fdadd23570a640f9d12ee00"
594+
},
595+
{
596+
value: validBoxes[1],
597+
hex: "63caf0ca330008cd038d39af8c37583609ff51c6a577efe60684119da2fbd0d75f9c72372886a58a639fbf3318de5ee573c6a492c129d51119649bfeaedfc9afa6f54af576e62e1f7f3bbd42078e87f9f1051fd6e032e8476c4aa54c18c1a308dce83940e8f4a28f576440513ed7326ad4898a993d03faf2cb329f2e90d6d23b58d91bbb6c046aa143261cc21f52fbe2824bfcbf043274251ce2cb4eb2024a1a155e19ad1d1f58ff8b9e6eb034a3bb1fd58802757d2380a0b787e905003bd19d0187117f130b62e1bcab0939929ff5c7709f843c5c4dd158949285d00136aba4b4a97b65be491cf9f5ca57b5408b0da8d0194f30ec8330d1e8946161c103c5d6629329285b14ed3eac1dba0e07dbd1e61ee332c2039a7a9c04e8be0cb74eb6f6b1c7ae03a3b3fa62124ef52209a46121e3f93ca98d7fc24198009e90fde8205ef9d3fc330100bd762484086cf560d3127eb53f0769d76244d9737636b2699d55c56cd470bfa589015a34d53ca483924b9a6aa0c771f11888881b516a8d1a9cdc535d063fe26d065e21d601123e8838b95cdaebe24e594276b2a89cd38e98add98405bb5327520ecf6cacf2cb07bf59773def7e08375a553be4cbd862de85f66e6dd3dccb8f87f53158f9255bf59582a6efc79e84911102f31739e2e4937bb9afb552943753d1e3e9cdd1a5e5661949cb0cef93f907eade9e0d30974274078845f263b4f21787e33cc99e9ec19a17ad85a5bc6da2cca91c5a2ec7c98b8c850b0cd8c9f416e5b1ca9f986a7f10a84191dfb85941619e49e53c0dc30ebf83324bfc1c1c51c3a53abfe87e6db9a03c649e8360f255ffc4bd34303d30fc7db23ae551db9c04fbbaac7337d051c10fc3da0ccb864f4d32d40027551e1c3ea3ce361f39b91e40c10fef802b475c06189fdbf844153cdc1d449a5ba87cce13d11bb47b5a539f27f12bfdecfad1f82a472c3d4ecaa08fb7392ff041ee2e6af75f4a558810a74b28600549d5392810e880ade204bf2afb01fde7e373e22f24032434a7b883913bd87a23b62ee8b43eba53c9f6c201bf337a2ce726259ad31e043c5b3d432e31b403fc6686691171e0e0a319b9ae7a0100b1e236b60b95c2c6f8007a9d89bc460fc9e78f98b09faec9449007b40bccf3888124d71693c49a84fbbecd4908c94813b46514b18b67a99952dc1e6e4791556de413db0eee105e8290b090a773b7c56756507d45a76743d73bce54e8a915e95d9eb97360b681e596010089b758cfed2b9eac6721fb4576d8ba016202fdd939f32425aa7e2aefcbdde32e01"
598+
},
599+
{
600+
value: validBoxes[2],
601+
hex: "63c0843d0008cd02200a1c1b8fa17ec82de54bcaef96f23d7b34196c0410f6f578abdbf163b14b258abd33010cd8c9f416e5b1ca9f986a7f10a84191dfb85941619e49e53c0dc30ebf83324b0100b66aab1e43874ad8c5583f685a7d6d947238c373f615aee1d04ee604ba2c934000"
602+
}
603+
];

packages/serializer/src/serializers/dataSerializer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { assert } from "@fleet-sdk/common";
1+
import { assert, type Box } from "@fleet-sdk/common";
22
import type { SigmaByteReader, SigmaByteWriter } from "../coders";
33
import type { SConstant } from "../sigmaConstant";
44
import { isColl, isTuple, type SCollType, type STupleType, type SType } from "../types";
55
import { descriptors } from "../types/descriptors";
6+
import { deserializeBox, serializeBox } from "./boxSerializer";
67

78
const GROUP_ELEMENT_LENGTH = 33;
89
const PROVE_DLOG_OP = 0xcd;
@@ -80,6 +81,7 @@ export const dataSerializer = {
8081
}
8182

8283
if (type.code === descriptors.unit.code) return writer;
84+
if (type.code === descriptors.box.code) return serializeBox(data as Box, writer);
8385

8486
throw Error(
8587
`Serialization error: '0x${type.code.toString(16)}' type not implemented.`
@@ -139,6 +141,8 @@ export const dataSerializer = {
139141
}
140142
case descriptors.unit.code:
141143
return undefined;
144+
case descriptors.box.code:
145+
return deserializeBox(reader);
142146
}
143147
}
144148

packages/serializer/src/serializers/typeSerializer.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export const typeSerializer = {
1414
writer.write(type.code);
1515
} else if (type.code === descriptors.unit.code) {
1616
writer.write(type.code);
17+
} else if (type.code === descriptors.box.code) {
18+
writer.write(type.code);
1719
} else if (isColl(type)) {
1820
if (type.elementsType.embeddable) {
1921
writer.write(descriptors.coll.simpleCollTypeCode + type.elementsType.code);
@@ -149,9 +151,10 @@ export const typeSerializer = {
149151

150152
return new STupleType(wrapped);
151153
}
152-
case descriptors.unit.code: {
154+
case descriptors.unit.code:
153155
return descriptors.unit;
154-
}
156+
case descriptors.box.code:
157+
return descriptors.box;
155158
}
156159

157160
throw new Error("Not implemented.");

packages/serializer/src/sigmaConstant.spec.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ensureBigInt } from "@fleet-sdk/common";
2-
import { hex, randomBytes } from "@fleet-sdk/crypto";
1+
import { type Box, ensureBigInt } from "@fleet-sdk/common";
2+
import { hex } from "@fleet-sdk/crypto";
33
import { describe, expect, it, test } from "vitest";
44
import {
55
bigintVectors,
@@ -9,14 +9,15 @@ import {
99
groupElementVectors,
1010
intVectors,
1111
longVectors,
12+
sBoxVectors,
1213
shortVectors,
1314
sigmaPropVectors,
1415
tupleTestVectors
1516
} from "./_test-vectors/constantVectors";
1617
import { SigmaByteWriter } from "./coders";
1718
import { dataSerializer } from "./serializers";
1819
import { decode, parse, SConstant, stypeof } from "./sigmaConstant";
19-
import type { SGroupElementType } from "./types";
20+
import type { SGroupElementType, SPrimitiveType } from "./types";
2021
import {
2122
SBigInt,
2223
SBool,
@@ -30,7 +31,7 @@ import {
3031
STupleType,
3132
SUnit
3233
} from "./types/";
33-
import { STuple } from "./types/constructors";
34+
import { SBox, STuple } from "./types/constructors";
3435
import { Value$ } from "sigmastate-js/main";
3536
import fc from "fast-check";
3637
import {
@@ -45,6 +46,7 @@ import {
4546
MIN_I64,
4647
MIN_I8
4748
} from "./coders/numRanges";
49+
import { SPair } from "../dist";
4850

4951
describe("Primitive types serialization and parsing", () => {
5052
it.each(boolVectors)("Should road-trip SBool($value)", (tv) => {
@@ -277,6 +279,25 @@ describe("Not implemented types", () => {
277279
});
278280
});
279281

282+
describe("SBox serialization", () => {
283+
test.each(sBoxVectors)("SBox serialization bytes", (tv) => {
284+
const sconst = SBox(tv.value);
285+
expect(sconst.toHex()).to.be.equal(tv.hex);
286+
expect(sconst.type.toString()).to.be.equal("SBox");
287+
});
288+
289+
test.each(sBoxVectors)("SBox roundtrip", (tv) => {
290+
expect(SBox(SConstant.from<Box>(tv.hex).data).toHex()).to.be.equal(tv.hex);
291+
});
292+
293+
it("Should not embed SBox", () => {
294+
// @ts-expect-error SBox is not compatible with SColl
295+
expect(() => SColl(SBox, [sBoxVectors[0].value])).toThrow();
296+
// @ts-expect-error SBox is not compatible with SPair
297+
expect(() => SPair(SBox(sBoxVectors[0].value), SBox(sBoxVectors[1]))).toThrow();
298+
});
299+
});
300+
280301
describe("Tuple serialization", () => {
281302
it.each(tupleTestVectors)("Should road-trip $name", (tv) => {
282303
expect(tv.sconst.toHex()).to.be.equal(tv.hex);

packages/serializer/src/sigmaConstant.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { assert, isUndefined } from "@fleet-sdk/common";
21
import { type ByteInput, hex } from "@fleet-sdk/crypto";
32
import { SigmaByteReader, SigmaByteWriter } from "./coders";
43
import { dataSerializer } from "./serializers/dataSerializer";

packages/serializer/src/types/constructors.spec.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,9 @@ describe("Constructor proxies", () => {
5151

5252
describe("SPair constructor", () => {
5353
it("Should throw if params contains different types", () => {
54-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
55-
expect(() => SPair(SBool(true) as any, SBool() as any)).to.throw(
56-
"Invalid tuple declaration."
57-
);
58-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
59-
expect(() => SPair(SBool() as any, SBool(true)) as any).to.throw(
60-
"Invalid tuple declaration."
61-
);
54+
// @ts-expect-error invalid pair construction
55+
expect(() => SPair(SBool(true), SBool())).to.throw("Invalid tuple declaration.");
56+
// @ts-expect-error invalid pair construction
57+
expect(() => SPair(SBool(), SBool(true))).to.throw("Invalid tuple declaration.");
6258
});
6359
});

packages/serializer/src/types/constructors.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { isEmpty } from "@fleet-sdk/common";
1+
import { type Box, isEmpty } from "@fleet-sdk/common";
22
import { SConstant } from "../sigmaConstant";
33
import type { SType } from "./base";
44
import { descriptors } from "./descriptors";
55
import { SCollType, STupleType } from "./generics";
6-
import { SUnitType } from "./monomorphics";
6+
import { SBoxType, SUnitType } from "./monomorphics";
77
import {
88
SBigIntType,
99
SBoolType,
@@ -108,8 +108,11 @@ export const SSigmaProp = monoProxy<SSigmaPropType, SConstant<Uint8Array>>(
108108
descriptors.sigmaProp
109109
);
110110

111-
type SUnit = (value?: undefined) => SConstant<undefined, SUnitType>;
112-
export const SUnit: SUnit = monoProxy(SUnitType, undefined, true);
111+
type SUnit = () => SConstant<undefined, SUnitType>;
112+
export const SUnit = monoProxy(SUnitType, undefined, true) as unknown as SUnit;
113+
114+
type SBox = (value?: Box) => SConstant<Box<bigint>, SBoxType>;
115+
export const SBox = monoProxy(SBoxType, undefined, true) as unknown as SBox;
113116

114117
type SColl = {
115118
<D, T extends SByteType>(

packages/serializer/src/types/descriptors.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { SType } from "./base";
22
import type { SCollType, STupleType } from "./generics";
3-
import { SUnitType } from "./monomorphics";
3+
import { SBoxType, SUnitType } from "./monomorphics";
44
import {
55
SBigIntType,
66
SBoolType,
@@ -61,6 +61,7 @@ export const descriptors = {
6161
groupElement: new SGroupElementType(),
6262
sigmaProp: new SSigmaPropType(),
6363
unit: new SUnitType(),
64+
box: new SBoxType(),
6465
coll: collDescriptor,
6566
tuple: tupleDescriptor
6667
} satisfies { [key: string]: Descriptor };

packages/serializer/src/types/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ export {
1414
SSigmaProp,
1515
SUnit,
1616
SColl,
17-
SPair
17+
SPair,
18+
SBox
1819
} from "./constructors";

0 commit comments

Comments
 (0)