Skip to content

Commit 1dfc0be

Browse files
AngelCastilloBmkazlauskas
authored andcommitted
feat(core): added custom PlutusData serialization classes
1 parent 996b9da commit 1dfc0be

File tree

10 files changed

+1101
-124
lines changed

10 files changed

+1101
-124
lines changed

packages/core/src/Serialization/PlutusData.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { CborReader, CborWriter } from '../CBOR';
2+
import { HexBlob } from '@cardano-sdk/util';
3+
import { PlutusList } from './PlutusList';
4+
import { hexToBytes } from '../../util/misc';
5+
6+
const GENERAL_FORM_TAG = 102n;
7+
const ALTERNATIVE_TAG_OFFSET = 7n;
8+
9+
/**
10+
* The main datatype `Constr` represents the nth constructor
11+
* along with its arguments.
12+
*
13+
* Remark: We don't directly serialize the alternative in the tag,
14+
* instead the scheme is:
15+
*
16+
* - Alternatives 0-6 -> tags 121-127, followed by the arguments in a list.
17+
* - Alternatives 7-127 -> tags 1280-1400, followed by the arguments in a list.
18+
* - Any alternatives, including those that don't fit in the above -> tag 102 followed by a list containing
19+
* an unsigned integer for the actual alternative, and then the arguments in a (nested!) list.
20+
*/
21+
export class ConstrPlutusData {
22+
private readonly _alternative: bigint = 0n;
23+
private readonly _data = new PlutusList();
24+
25+
/**
26+
* Initializes a new instance of the ConstrPlutusData class.
27+
*
28+
* @param alternative Get the Constr alternative. The alternative represents the nth
29+
* constructor of a 'Sum Type'.
30+
* @param data Gets the list of arguments of the 'Sum Type' as a 'PlutusList'.
31+
*/
32+
constructor(alternative: bigint, data: PlutusList) {
33+
this._alternative = alternative;
34+
this._data = data;
35+
}
36+
37+
/**
38+
* Serializes this ConstrPlutusData instance into its CBOR representation as a Uint8Array.
39+
*
40+
* @returns The CBOR representation of this instance as a Uint8Array.
41+
*/
42+
toCbor(): HexBlob {
43+
const writer = new CborWriter();
44+
const compactTag = ConstrPlutusData.alternativeToCompactCborTag(this._alternative);
45+
46+
writer.writeTag(Number(compactTag));
47+
48+
if (compactTag !== GENERAL_FORM_TAG) {
49+
writer.writeEncodedValue(hexToBytes(this._data.toCbor()));
50+
} else {
51+
writer.writeStartArray(2);
52+
writer.writeInt(this._alternative);
53+
writer.writeEncodedValue(hexToBytes(this._data.toCbor()));
54+
}
55+
56+
return HexBlob.fromBytes(writer.encode());
57+
}
58+
59+
/**
60+
* Deserializes a ConstrPlutusData instance from its CBOR representation.
61+
*
62+
* @param cbor The CBOR representation of this instance as a Uint8Array.
63+
* @returns A ConstrPlutusData instance.
64+
*/
65+
static fromCbor(cbor: HexBlob): ConstrPlutusData {
66+
const reader = new CborReader(cbor);
67+
68+
const tag = reader.readTag();
69+
70+
if (tag === Number(GENERAL_FORM_TAG)) {
71+
reader.readStartArray();
72+
73+
const alternative = reader.readInt();
74+
const data = reader.readEncodedValue();
75+
const plutusList = PlutusList.fromCbor(HexBlob.fromBytes(data));
76+
77+
reader.readEndArray();
78+
79+
return new ConstrPlutusData(alternative, plutusList);
80+
}
81+
82+
const alternative = ConstrPlutusData.compactCborTagToAlternative(BigInt(tag));
83+
const data = reader.readEncodedValue();
84+
const plutusList = PlutusList.fromCbor(HexBlob.fromBytes(data));
85+
86+
return new ConstrPlutusData(alternative, plutusList);
87+
}
88+
89+
/**
90+
* Gets the ConstrPlutusData alternative. The alternative represents the nth
91+
* constructor of a 'Sum Type'.
92+
*
93+
* @returns The alternative constructor of the 'Sum Type'.
94+
*/
95+
getAlternative(): bigint {
96+
return this._alternative;
97+
}
98+
99+
/**
100+
* The list of arguments of the 'Sum Type' as a 'PlutusList'.
101+
*
102+
* @returns The list of arguments.
103+
*/
104+
getData(): PlutusList {
105+
return this._data;
106+
}
107+
108+
// Mapping functions to and from alternative to and from CBOR tags.
109+
// See https://github.com/input-output-hk/plutus/blob/1f31e640e8a258185db01fa899da63f9018c0e85/plutus-core/plutus-core/src/PlutusCore/Data.hs#L69-L72
110+
111+
/**
112+
* Converts a CBOR compact tag to a Constr alternative.
113+
*
114+
* @param tag The tag to be converted.
115+
* @returns The Constr alternative.
116+
*/
117+
private static compactCborTagToAlternative(tag: bigint): bigint {
118+
if (tag >= 121n && tag <= 127) return tag - 121n;
119+
if (tag >= 1280n && tag <= 1400) return tag - 1280n + ALTERNATIVE_TAG_OFFSET;
120+
121+
return GENERAL_FORM_TAG;
122+
}
123+
124+
/**
125+
* Converts the constructor alternative to its CBOR compact tag.
126+
*
127+
* @param alternative The Constr alternative to be converted.
128+
* @returns The compact CBOR tag.
129+
*/
130+
private static alternativeToCompactCborTag(alternative: bigint): bigint {
131+
if (alternative <= 6n) return 121n + alternative;
132+
if (alternative >= 7n && alternative <= 127n) return 1280n - ALTERNATIVE_TAG_OFFSET + alternative;
133+
134+
return GENERAL_FORM_TAG;
135+
}
136+
}

0 commit comments

Comments
 (0)