@fleet-sdk/serializer 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/index.cjs.js +5 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.esm.js +5 -4
- package/dist/index.esm.js.map +1 -1
- package/package.json +4 -4
- package/src/_test-vectors/boxVectors.ts +0 -207
- package/src/_test-vectors/constantVectors.ts +0 -457
- package/src/_test-vectors/transactionVectors.ts +0 -590
- package/src/coders/bigint.ts +0 -73
- package/src/coders/index.ts +0 -4
- package/src/coders/sigmaReader.ts +0 -81
- package/src/coders/sigmaWriter.ts +0 -106
- package/src/coders/vlq.ts +0 -141
- package/src/coders/zigZag.ts +0 -46
- package/src/index.ts +0 -4
- package/src/serializers/boxSerializer.ts +0 -139
- package/src/serializers/dataSerializer.ts +0 -141
- package/src/serializers/index.ts +0 -4
- package/src/serializers/transactionSerializer.ts +0 -76
- package/src/serializers/typeSerializer.ts +0 -148
- package/src/sigmaConstant.ts +0 -59
- package/src/types/base.ts +0 -46
- package/src/types/constructors.test-d.ts +0 -147
- package/src/types/constructors.ts +0 -144
- package/src/types/descriptors.ts +0 -105
- package/src/types/generics.ts +0 -42
- package/src/types/index.ts +0 -18
- package/src/types/monomorphics.ts +0 -11
- package/src/types/primitives.ts +0 -97
@@ -1,81 +0,0 @@
|
|
1
|
-
import { HexString, isEmpty } from "@fleet-sdk/common";
|
2
|
-
import { hex } from "@fleet-sdk/crypto";
|
3
|
-
import { hexToBigInt } from "./bigint";
|
4
|
-
import { readBigVLQ, readVLQ } from "./vlq";
|
5
|
-
import { zigZagDecode, zigZagDecodeBigInt } from "./zigZag";
|
6
|
-
|
7
|
-
export class SigmaReader {
|
8
|
-
readonly #bytes: Uint8Array;
|
9
|
-
#cursor: number;
|
10
|
-
|
11
|
-
public get isEmpty(): boolean {
|
12
|
-
return isEmpty(this.#bytes);
|
13
|
-
}
|
14
|
-
|
15
|
-
constructor(bytes: HexString | Uint8Array) {
|
16
|
-
if (typeof bytes === "string") {
|
17
|
-
this.#bytes = hex.decode(bytes);
|
18
|
-
} else {
|
19
|
-
this.#bytes = bytes;
|
20
|
-
}
|
21
|
-
|
22
|
-
this.#cursor = 0;
|
23
|
-
}
|
24
|
-
|
25
|
-
public readBoolean(): boolean {
|
26
|
-
return this.readByte() === 0x01;
|
27
|
-
}
|
28
|
-
|
29
|
-
public readBits(length: number): ArrayLike<boolean> {
|
30
|
-
const bits = new Array<boolean>(length);
|
31
|
-
let bitOffset = 0;
|
32
|
-
|
33
|
-
for (let i = 0; i < length; i++) {
|
34
|
-
const bit = (this.#bytes[this.#cursor] >> bitOffset++) & 1;
|
35
|
-
bits[i] = bit === 1;
|
36
|
-
|
37
|
-
if (bitOffset == 8) {
|
38
|
-
bitOffset = 0;
|
39
|
-
this.#cursor++;
|
40
|
-
}
|
41
|
-
}
|
42
|
-
|
43
|
-
if (bitOffset > 0) {
|
44
|
-
this.#cursor++;
|
45
|
-
}
|
46
|
-
|
47
|
-
return bits;
|
48
|
-
}
|
49
|
-
|
50
|
-
public readByte(): number {
|
51
|
-
return this.#bytes[this.#cursor++];
|
52
|
-
}
|
53
|
-
|
54
|
-
public readBytes(length: number): Uint8Array {
|
55
|
-
return this.#bytes.subarray(this.#cursor, (this.#cursor += length));
|
56
|
-
}
|
57
|
-
|
58
|
-
public readVlq(): number {
|
59
|
-
return readVLQ(this);
|
60
|
-
}
|
61
|
-
|
62
|
-
public readShort(): number {
|
63
|
-
return Number(zigZagDecode(readVLQ(this)));
|
64
|
-
}
|
65
|
-
|
66
|
-
public readInt(): number {
|
67
|
-
const int = this.readLong();
|
68
|
-
|
69
|
-
return Number(int);
|
70
|
-
}
|
71
|
-
|
72
|
-
public readLong(): bigint {
|
73
|
-
return zigZagDecodeBigInt(readBigVLQ(this));
|
74
|
-
}
|
75
|
-
|
76
|
-
public readBigInt(): bigint {
|
77
|
-
const len = readVLQ(this);
|
78
|
-
|
79
|
-
return hexToBigInt(hex.encode(this.readBytes(len)));
|
80
|
-
}
|
81
|
-
}
|
@@ -1,106 +0,0 @@
|
|
1
|
-
import { hex } from "@fleet-sdk/crypto";
|
2
|
-
import { bigIntToHex } from "./bigint";
|
3
|
-
import { writeBigVLQ, writeVLQ } from "./vlq";
|
4
|
-
import { zigZagEncode, zigZagEncodeBigInt } from "./zigZag";
|
5
|
-
|
6
|
-
export class SigmaWriter {
|
7
|
-
readonly #bytes: Uint8Array;
|
8
|
-
#cursor: number;
|
9
|
-
|
10
|
-
public get length() {
|
11
|
-
return this.#cursor;
|
12
|
-
}
|
13
|
-
|
14
|
-
constructor(maxLength: number) {
|
15
|
-
this.#bytes = new Uint8Array(maxLength);
|
16
|
-
this.#cursor = 0;
|
17
|
-
}
|
18
|
-
|
19
|
-
public writeBoolean(value: boolean): SigmaWriter {
|
20
|
-
this.write(value === true ? 0x01 : 0x00);
|
21
|
-
|
22
|
-
return this;
|
23
|
-
}
|
24
|
-
|
25
|
-
public writeVLQ(value: number): SigmaWriter {
|
26
|
-
return writeVLQ(this, value);
|
27
|
-
}
|
28
|
-
|
29
|
-
public writeBigVLQ(value: bigint): SigmaWriter {
|
30
|
-
return writeBigVLQ(this, value);
|
31
|
-
}
|
32
|
-
|
33
|
-
public writeShort(value: number): SigmaWriter {
|
34
|
-
this.writeVLQ(zigZagEncode(value));
|
35
|
-
|
36
|
-
return this;
|
37
|
-
}
|
38
|
-
|
39
|
-
public writeInt(value: number): SigmaWriter {
|
40
|
-
this.writeLong(BigInt(value));
|
41
|
-
|
42
|
-
return this;
|
43
|
-
}
|
44
|
-
|
45
|
-
public writeLong(value: bigint): SigmaWriter {
|
46
|
-
this.writeBigVLQ(zigZagEncodeBigInt(value));
|
47
|
-
|
48
|
-
return this;
|
49
|
-
}
|
50
|
-
|
51
|
-
public write(byte: number): SigmaWriter {
|
52
|
-
this.#bytes[this.#cursor++] = byte;
|
53
|
-
|
54
|
-
return this;
|
55
|
-
}
|
56
|
-
|
57
|
-
public writeBytes(bytes: Uint8Array): SigmaWriter {
|
58
|
-
this.#bytes.set(bytes, this.#cursor);
|
59
|
-
this.#cursor += bytes.length;
|
60
|
-
|
61
|
-
return this;
|
62
|
-
}
|
63
|
-
|
64
|
-
public writeHex(bytesHex: string): SigmaWriter {
|
65
|
-
return this.writeBytes(hex.decode(bytesHex));
|
66
|
-
}
|
67
|
-
|
68
|
-
public writeBits(bits: ArrayLike<boolean>): SigmaWriter {
|
69
|
-
let bitOffset = 0;
|
70
|
-
|
71
|
-
for (let i = 0; i < bits.length; i++) {
|
72
|
-
if (bits[i]) {
|
73
|
-
this.#bytes[this.#cursor] |= 1 << bitOffset++;
|
74
|
-
} else {
|
75
|
-
this.#bytes[this.#cursor] &= ~(1 << bitOffset++);
|
76
|
-
}
|
77
|
-
|
78
|
-
if (bitOffset == 8) {
|
79
|
-
bitOffset = 0;
|
80
|
-
this.#cursor++;
|
81
|
-
}
|
82
|
-
}
|
83
|
-
|
84
|
-
if (bitOffset > 0) {
|
85
|
-
this.#cursor++;
|
86
|
-
}
|
87
|
-
|
88
|
-
return this;
|
89
|
-
}
|
90
|
-
|
91
|
-
public writeBigInt(value: bigint): SigmaWriter {
|
92
|
-
const hex = bigIntToHex(value);
|
93
|
-
this.writeVLQ(hex.length / 2);
|
94
|
-
this.writeHex(hex);
|
95
|
-
|
96
|
-
return this;
|
97
|
-
}
|
98
|
-
|
99
|
-
public toHex(): string {
|
100
|
-
return hex.encode(this.toBytes());
|
101
|
-
}
|
102
|
-
|
103
|
-
public toBytes(): Uint8Array {
|
104
|
-
return this.#bytes.subarray(0, this.#cursor);
|
105
|
-
}
|
106
|
-
}
|
package/src/coders/vlq.ts
DELETED
@@ -1,141 +0,0 @@
|
|
1
|
-
import { _0n, _127n, _128n, _7n, ensureBigInt } from "@fleet-sdk/common";
|
2
|
-
import { SigmaReader } from "./sigmaReader";
|
3
|
-
import { SigmaWriter } from "./sigmaWriter";
|
4
|
-
|
5
|
-
/**
|
6
|
-
* A **variable-length quantity (VLQ)** is a universal code that uses an arbitrary number
|
7
|
-
* of binary octets (eight-bit bytes) to represent an arbitrarily large integer. A VLQ
|
8
|
-
* is essentially a base-128 representation of an unsigned integer with the addition of
|
9
|
-
* the eighth bit to mark continuation of bytes. VLQ is identical to LEB128 except in
|
10
|
-
* endianness. See the example below.
|
11
|
-
*/
|
12
|
-
|
13
|
-
/**
|
14
|
-
* Write an unsigned integer value as VLQ to a `SigmaWriter`.
|
15
|
-
* @param value: Integer value
|
16
|
-
* @param writer: Sigma writer
|
17
|
-
* @returns Sigma writer passed as function argument.
|
18
|
-
*/
|
19
|
-
export function writeVLQ(writer: SigmaWriter, value: number): SigmaWriter {
|
20
|
-
// source: https://stackoverflow.com/a/3564685
|
21
|
-
|
22
|
-
if (value === 0) {
|
23
|
-
return writer.write(0);
|
24
|
-
} else if (value < 0) {
|
25
|
-
throw new RangeError("Variable Length Quantity not supported for negative numbers.");
|
26
|
-
}
|
27
|
-
|
28
|
-
do {
|
29
|
-
let lower7bits = value & 0x7f;
|
30
|
-
value >>= 7;
|
31
|
-
|
32
|
-
if (value > 0) {
|
33
|
-
lower7bits |= 0x80;
|
34
|
-
}
|
35
|
-
|
36
|
-
writer.write(lower7bits);
|
37
|
-
} while (value > 0);
|
38
|
-
|
39
|
-
return writer;
|
40
|
-
}
|
41
|
-
|
42
|
-
/**
|
43
|
-
* Decode VLQ bytes to an unsigned integer value
|
44
|
-
* @param reader VLQ bytes
|
45
|
-
* @returns Unsigned integer value
|
46
|
-
*/
|
47
|
-
export function readVLQ(reader: SigmaReader): number {
|
48
|
-
if (reader.isEmpty) {
|
49
|
-
return 0;
|
50
|
-
}
|
51
|
-
|
52
|
-
let value = 0;
|
53
|
-
let shift = 0;
|
54
|
-
let lower7bits = 0;
|
55
|
-
|
56
|
-
do {
|
57
|
-
lower7bits = reader.readByte();
|
58
|
-
value |= (lower7bits & 0x7f) << shift;
|
59
|
-
shift += 7;
|
60
|
-
} while ((lower7bits & 0x80) != 0);
|
61
|
-
|
62
|
-
return value;
|
63
|
-
}
|
64
|
-
|
65
|
-
/**
|
66
|
-
* Write an unsigned integer value as VLQ to a `SigmaWriter`.
|
67
|
-
* @param value: Big integer value
|
68
|
-
* @param writer: Sigma writer
|
69
|
-
* @returns Sigma writer passed as function argument.
|
70
|
-
*/
|
71
|
-
export function writeBigVLQ(writer: SigmaWriter, value: bigint): SigmaWriter {
|
72
|
-
// source: https://stackoverflow.com/a/3564685
|
73
|
-
|
74
|
-
if (value === _0n) {
|
75
|
-
return writer.write(0);
|
76
|
-
} else if (value < _0n) {
|
77
|
-
throw new RangeError("Variable Length Quantity not supported for negative numbers");
|
78
|
-
}
|
79
|
-
|
80
|
-
do {
|
81
|
-
let lower7bits = Number(value & _127n);
|
82
|
-
value >>= _7n;
|
83
|
-
|
84
|
-
if (value > 0) {
|
85
|
-
lower7bits |= 0x80;
|
86
|
-
}
|
87
|
-
|
88
|
-
writer.write(lower7bits);
|
89
|
-
} while (value > 0);
|
90
|
-
|
91
|
-
return writer;
|
92
|
-
}
|
93
|
-
|
94
|
-
/**
|
95
|
-
* Decode VLQ bytes to an unsigned big integer value
|
96
|
-
* @param reader VLQ bytes
|
97
|
-
* @returns Unsigned integer value
|
98
|
-
*/
|
99
|
-
export function readBigVLQ(reader: SigmaReader): bigint {
|
100
|
-
if (reader.isEmpty) {
|
101
|
-
return _0n;
|
102
|
-
}
|
103
|
-
|
104
|
-
let value = _0n;
|
105
|
-
let shift = _0n;
|
106
|
-
let lower7bits = _0n;
|
107
|
-
|
108
|
-
do {
|
109
|
-
lower7bits = BigInt(reader.readByte());
|
110
|
-
value |= (lower7bits & _127n) << shift;
|
111
|
-
shift += _7n;
|
112
|
-
} while ((lower7bits & _128n) != _0n);
|
113
|
-
|
114
|
-
return value;
|
115
|
-
}
|
116
|
-
|
117
|
-
/**
|
118
|
-
* Estimates the byte size of a given unsigned integer.
|
119
|
-
* @param value: the value to be evaluated.
|
120
|
-
* @returns the byte size of the value.
|
121
|
-
*/
|
122
|
-
export function estimateVLQSize(value: number | bigint | string): number {
|
123
|
-
let size = 0;
|
124
|
-
|
125
|
-
if (typeof value === "number") {
|
126
|
-
do {
|
127
|
-
size++;
|
128
|
-
value = Math.floor(value / 128);
|
129
|
-
} while (value > 0);
|
130
|
-
|
131
|
-
return size;
|
132
|
-
}
|
133
|
-
|
134
|
-
value = ensureBigInt(value);
|
135
|
-
do {
|
136
|
-
size++;
|
137
|
-
value /= _128n;
|
138
|
-
} while (value > _0n);
|
139
|
-
|
140
|
-
return size;
|
141
|
-
}
|
package/src/coders/zigZag.ts
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
import { _1n, _63n } from "@fleet-sdk/common";
|
2
|
-
|
3
|
-
/**
|
4
|
-
* ZigZag encoding maps signed integers to unsigned integers so that numbers
|
5
|
-
* with a small absolute value (for instance, -1) have a small variant encoded
|
6
|
-
* value too. It does this in a way that "zig-zags" back and forth through the
|
7
|
-
* positive and negative integers, so that -1 is encoded as 1, 1 is encoded as 2,
|
8
|
-
* -2 is encoded as 3, and so on.
|
9
|
-
* @see https://developers.google.com/protocol-buffers/docs/encoding#types
|
10
|
-
*/
|
11
|
-
|
12
|
-
/**
|
13
|
-
* Encode a signed integer.
|
14
|
-
* @param input Signed integer
|
15
|
-
* @returns ZigZag-encoded value
|
16
|
-
*/
|
17
|
-
export function zigZagEncode(input: number): number {
|
18
|
-
return (input << 1) ^ (input >> 63);
|
19
|
-
}
|
20
|
-
|
21
|
-
/**
|
22
|
-
* Decode a ZigZag-encoded value.
|
23
|
-
* @param input ZigZag-encoded value
|
24
|
-
* @returns Signed integer
|
25
|
-
*/
|
26
|
-
export function zigZagDecode(input: number): number {
|
27
|
-
return (input >> 1) ^ -(input & 1);
|
28
|
-
}
|
29
|
-
|
30
|
-
/**
|
31
|
-
* Encode a signed big integer.
|
32
|
-
* @param input Signed big integer
|
33
|
-
* @returns ZigZag-encoded value
|
34
|
-
*/
|
35
|
-
export function zigZagEncodeBigInt(input: bigint): bigint {
|
36
|
-
return (input << _1n) ^ (input >> _63n);
|
37
|
-
}
|
38
|
-
|
39
|
-
/**
|
40
|
-
* Decode a ZigZag-encoded value.
|
41
|
-
* @param input ZigZag-encoded value
|
42
|
-
* @returns Signed big integer
|
43
|
-
*/
|
44
|
-
export function zigZagDecodeBigInt(input: bigint): bigint {
|
45
|
-
return (input >> _1n) ^ -(input & _1n);
|
46
|
-
}
|
package/src/index.ts
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
Amount,
|
3
|
-
Box,
|
4
|
-
BoxCandidate,
|
5
|
-
byteSizeOf,
|
6
|
-
ensureBigInt,
|
7
|
-
isDefined,
|
8
|
-
isEmpty,
|
9
|
-
isUndefined,
|
10
|
-
NonMandatoryRegisters,
|
11
|
-
some,
|
12
|
-
TokenAmount
|
13
|
-
} from "@fleet-sdk/common";
|
14
|
-
import { estimateVLQSize, SigmaWriter } from "../coders";
|
15
|
-
|
16
|
-
const MAX_UINT16_VALUE = 65535;
|
17
|
-
|
18
|
-
export function serializeBox(box: Box<Amount>): SigmaWriter;
|
19
|
-
export function serializeBox(box: Box<Amount>, writer: SigmaWriter): SigmaWriter;
|
20
|
-
export function serializeBox(
|
21
|
-
box: BoxCandidate<Amount>,
|
22
|
-
writer: SigmaWriter,
|
23
|
-
distinctTokenIds: string[]
|
24
|
-
): SigmaWriter;
|
25
|
-
export function serializeBox(
|
26
|
-
box: Box<Amount> | BoxCandidate<Amount>,
|
27
|
-
writer?: SigmaWriter,
|
28
|
-
distinctTokenIds?: string[]
|
29
|
-
): SigmaWriter {
|
30
|
-
if (!writer) {
|
31
|
-
writer = new SigmaWriter(5_0000);
|
32
|
-
}
|
33
|
-
|
34
|
-
writer.writeBigVLQ(ensureBigInt(box.value));
|
35
|
-
writer.writeHex(box.ergoTree);
|
36
|
-
writer.writeVLQ(box.creationHeight);
|
37
|
-
writeTokens(writer, box.assets, distinctTokenIds);
|
38
|
-
writeRegisters(writer, box.additionalRegisters);
|
39
|
-
|
40
|
-
if (isDefined(distinctTokenIds)) {
|
41
|
-
return writer;
|
42
|
-
} else {
|
43
|
-
if (!isBox(box)) {
|
44
|
-
throw new Error("Invalid box type.");
|
45
|
-
}
|
46
|
-
|
47
|
-
return writer.writeHex(box.transactionId).writeVLQ(box.index);
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
function isBox<T extends Amount>(box: Box<Amount> | BoxCandidate<Amount>): box is Box<T> {
|
52
|
-
const castedBox = box as Box<T>;
|
53
|
-
|
54
|
-
return isDefined(castedBox.transactionId) && isDefined(castedBox.index);
|
55
|
-
}
|
56
|
-
|
57
|
-
function writeTokens(
|
58
|
-
writer: SigmaWriter,
|
59
|
-
tokens: TokenAmount<Amount>[],
|
60
|
-
tokenIds?: string[]
|
61
|
-
): void {
|
62
|
-
if (isEmpty(tokens)) {
|
63
|
-
writer.write(0);
|
64
|
-
|
65
|
-
return;
|
66
|
-
}
|
67
|
-
|
68
|
-
writer.writeVLQ(tokens.length);
|
69
|
-
if (some(tokenIds)) {
|
70
|
-
tokens.map((token) =>
|
71
|
-
writer.writeVLQ(tokenIds.indexOf(token.tokenId)).writeBigVLQ(ensureBigInt(token.amount))
|
72
|
-
);
|
73
|
-
} else {
|
74
|
-
tokens.map((token) => writer.writeHex(token.tokenId).writeBigVLQ(ensureBigInt(token.amount)));
|
75
|
-
}
|
76
|
-
}
|
77
|
-
|
78
|
-
function writeRegisters(writer: SigmaWriter, registers: NonMandatoryRegisters): void {
|
79
|
-
const keys = Object.keys(registers).sort();
|
80
|
-
let length = 0;
|
81
|
-
|
82
|
-
for (const key of keys) {
|
83
|
-
if (registers[key as keyof NonMandatoryRegisters]) {
|
84
|
-
length++;
|
85
|
-
}
|
86
|
-
}
|
87
|
-
|
88
|
-
writer.writeVLQ(length);
|
89
|
-
if (length == 0) {
|
90
|
-
return;
|
91
|
-
}
|
92
|
-
|
93
|
-
for (const key of keys) {
|
94
|
-
const register = registers[key as keyof NonMandatoryRegisters];
|
95
|
-
if (isDefined(register)) {
|
96
|
-
writer.writeHex(register);
|
97
|
-
}
|
98
|
-
}
|
99
|
-
}
|
100
|
-
|
101
|
-
/**
|
102
|
-
* Estimates the byte size a box.
|
103
|
-
* @returns byte size of the box.
|
104
|
-
*/
|
105
|
-
export function estimateBoxSize(
|
106
|
-
box: Box<Amount> | BoxCandidate<Amount>,
|
107
|
-
withValue?: Amount
|
108
|
-
): number {
|
109
|
-
if (isUndefined(box.creationHeight)) {
|
110
|
-
throw new Error("Box size estimation error: creation height is undefined.");
|
111
|
-
}
|
112
|
-
|
113
|
-
let size = 0;
|
114
|
-
|
115
|
-
size += estimateVLQSize(isDefined(withValue) ? withValue : box.value);
|
116
|
-
size += byteSizeOf(box.ergoTree);
|
117
|
-
size += estimateVLQSize(box.creationHeight);
|
118
|
-
|
119
|
-
size += estimateVLQSize(box.assets.length);
|
120
|
-
size += box.assets.reduce(
|
121
|
-
(acc: number, curr) => (acc += byteSizeOf(curr.tokenId) + estimateVLQSize(curr.amount)),
|
122
|
-
0
|
123
|
-
);
|
124
|
-
|
125
|
-
let registersLength = 0;
|
126
|
-
for (const key in box.additionalRegisters) {
|
127
|
-
const register = box.additionalRegisters[key as keyof NonMandatoryRegisters];
|
128
|
-
if (register) {
|
129
|
-
size += byteSizeOf(register);
|
130
|
-
registersLength++;
|
131
|
-
}
|
132
|
-
}
|
133
|
-
size += estimateVLQSize(registersLength);
|
134
|
-
|
135
|
-
size += 32; // transaction id (BLAKE2b 256 hash)
|
136
|
-
size += estimateVLQSize(isBox(box) ? box.index : MAX_UINT16_VALUE);
|
137
|
-
|
138
|
-
return size;
|
139
|
-
}
|
@@ -1,141 +0,0 @@
|
|
1
|
-
import { assert } from "@fleet-sdk/common";
|
2
|
-
import { SigmaReader, SigmaWriter } from "../coders";
|
3
|
-
import { SConstant } from "../sigmaConstant";
|
4
|
-
import { isColl, isTuple, SCollType, STupleType, SType } from "../types";
|
5
|
-
import { descriptors } from "../types/descriptors";
|
6
|
-
|
7
|
-
const GROUP_ELEMENT_LENGTH = 33;
|
8
|
-
const PROVE_DLOG_OP = 0xcd;
|
9
|
-
|
10
|
-
export class DataSerializer {
|
11
|
-
public static serialize(data: unknown, type: SType, writer: SigmaWriter): SigmaWriter {
|
12
|
-
if (type.embeddable) {
|
13
|
-
switch (type.code) {
|
14
|
-
case descriptors.bool.code:
|
15
|
-
return writer.writeBoolean(data as boolean);
|
16
|
-
case descriptors.byte.code:
|
17
|
-
return writer.write(data as number);
|
18
|
-
case descriptors.short.code:
|
19
|
-
return writer.writeShort(data as number);
|
20
|
-
case descriptors.int.code:
|
21
|
-
return writer.writeInt(data as number);
|
22
|
-
case descriptors.long.code:
|
23
|
-
return writer.writeLong(data as bigint);
|
24
|
-
case descriptors.bigInt.code: {
|
25
|
-
return writer.writeBigInt(data as bigint);
|
26
|
-
}
|
27
|
-
case descriptors.groupElement.code:
|
28
|
-
return writer.writeBytes(data as Uint8Array);
|
29
|
-
case descriptors.sigmaProp.code: {
|
30
|
-
const node = data as SConstant<SConstant<Uint8Array>>;
|
31
|
-
|
32
|
-
if (node.type === descriptors.groupElement) {
|
33
|
-
writer.write(PROVE_DLOG_OP);
|
34
|
-
|
35
|
-
return DataSerializer.serialize(node.data, node.type, writer);
|
36
|
-
} else {
|
37
|
-
throw Error("Serialization error: SigmaProp operation not implemented.");
|
38
|
-
}
|
39
|
-
}
|
40
|
-
}
|
41
|
-
} else if (isColl(type)) {
|
42
|
-
if (type.elementsType.code === descriptors.byte.code) {
|
43
|
-
const isUint8Array = data instanceof Uint8Array;
|
44
|
-
assert(isUint8Array, `SColl[Byte] expected an UInt8Array, got ${typeof data}.`);
|
45
|
-
} else {
|
46
|
-
assert(Array.isArray(data), `SColl expected an array, got ${typeof data}.`);
|
47
|
-
}
|
48
|
-
|
49
|
-
writer.writeVLQ(data.length);
|
50
|
-
switch (type.elementsType.code) {
|
51
|
-
case descriptors.bool.code: {
|
52
|
-
return writer.writeBits(data as boolean[]);
|
53
|
-
}
|
54
|
-
case descriptors.byte.code: {
|
55
|
-
return writer.writeBytes(data as Uint8Array);
|
56
|
-
}
|
57
|
-
default: {
|
58
|
-
for (let i = 0; i < data.length; i++) {
|
59
|
-
DataSerializer.serialize(data[i], type.elementsType, writer);
|
60
|
-
}
|
61
|
-
|
62
|
-
return writer;
|
63
|
-
}
|
64
|
-
}
|
65
|
-
} else if (isTuple(type)) {
|
66
|
-
assert(
|
67
|
-
Array.isArray(data),
|
68
|
-
`STupleType serialization expected an array, got ${typeof data}.`
|
69
|
-
);
|
70
|
-
|
71
|
-
const len = type.elementsType.length;
|
72
|
-
for (let i = 0; i < len; i++) {
|
73
|
-
DataSerializer.serialize(data[i], type.elementsType[i], writer);
|
74
|
-
}
|
75
|
-
|
76
|
-
return writer;
|
77
|
-
} else if (type.code === descriptors.unit.code) {
|
78
|
-
return writer;
|
79
|
-
}
|
80
|
-
|
81
|
-
throw Error(`Serialization error: '0x${type.code.toString(16)}' type not implemented.`);
|
82
|
-
}
|
83
|
-
|
84
|
-
static deserialize(type: SType, reader: SigmaReader): unknown {
|
85
|
-
if (type.embeddable) {
|
86
|
-
switch (type.code) {
|
87
|
-
case descriptors.bool.code:
|
88
|
-
return reader.readBoolean();
|
89
|
-
case descriptors.byte.code:
|
90
|
-
return reader.readByte();
|
91
|
-
case descriptors.short.code:
|
92
|
-
return reader.readShort();
|
93
|
-
case descriptors.int.code:
|
94
|
-
return reader.readInt();
|
95
|
-
case descriptors.long.code:
|
96
|
-
return reader.readLong();
|
97
|
-
case descriptors.bigInt.code:
|
98
|
-
return reader.readBigInt();
|
99
|
-
case descriptors.groupElement.code:
|
100
|
-
return reader.readBytes(GROUP_ELEMENT_LENGTH);
|
101
|
-
case descriptors.sigmaProp.code: {
|
102
|
-
if (reader.readByte() === PROVE_DLOG_OP) {
|
103
|
-
return this.deserialize(descriptors.groupElement, reader);
|
104
|
-
}
|
105
|
-
|
106
|
-
break;
|
107
|
-
}
|
108
|
-
}
|
109
|
-
} else {
|
110
|
-
switch (type.code) {
|
111
|
-
case descriptors.coll.code: {
|
112
|
-
const length = reader.readVlq();
|
113
|
-
const embeddedType = (type as SCollType).elementsType;
|
114
|
-
|
115
|
-
switch (embeddedType.code) {
|
116
|
-
case descriptors.bool.code:
|
117
|
-
return reader.readBits(length);
|
118
|
-
case descriptors.byte.code:
|
119
|
-
return reader.readBytes(length);
|
120
|
-
default: {
|
121
|
-
const elements = new Array(length);
|
122
|
-
for (let i = 0; i < length; i++) {
|
123
|
-
elements[i] = this.deserialize(embeddedType, reader);
|
124
|
-
}
|
125
|
-
|
126
|
-
return elements;
|
127
|
-
}
|
128
|
-
}
|
129
|
-
}
|
130
|
-
case descriptors.tuple.code: {
|
131
|
-
return (type as STupleType).elementsType.map((t) => this.deserialize(t, reader));
|
132
|
-
}
|
133
|
-
case descriptors.unit.code: {
|
134
|
-
return undefined;
|
135
|
-
}
|
136
|
-
}
|
137
|
-
}
|
138
|
-
|
139
|
-
throw new Error(`Parsing error: '0x${type.code.toString(16)}' type not implemented.`);
|
140
|
-
}
|
141
|
-
}
|
package/src/serializers/index.ts
DELETED