Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix serialization errors #29

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
950cf06
fix: deserialization of ByteStrings with lengths of 1 to 8 bytes
rmgaray Nov 11, 2024
f01e3eb
improved CBOR mismastch visualization
rmgaray Nov 11, 2024
c8c9cd3
fix: missing path info in ByronAddress
rmgaray Nov 11, 2024
088945e
bump CSL to 'Set Theory' version
rmgaray Nov 16, 2024
312f5e4
fix: Vkey not being identical to PublicKey serialization-wise
rmgaray Nov 19, 2024
5822a63
fix: [de]serialization of CBOR strings
rmgaray Nov 19, 2024
95caf82
fix (de)serialization of auxiliary data
rmgaray Nov 21, 2024
9807d53
add PreBabbage TxOuts & add codegen support for optional fields in re…
rmgaray Nov 21, 2024
7072d9e
fix: code for recognizing address types
rmgaray Nov 24, 2024
742a09b
fix: readOptional not returning undefined when buffer is empty
rmgaray Nov 24, 2024
6e9ad5e
fix: implementation of variable length records
rmgaray Nov 24, 2024
c6666d5
fix: bug in tagged_record deserialization & PostAlonzo output definition
rmgaray Nov 25, 2024
b4309f3
fix: PlutusList not being a list
rmgaray Dec 3, 2024
138bed9
fix: roundtrip property for constr_plutus_data
rmgaray Dec 3, 2024
0af3ba2
fix: roundtrip property for redeemers
rmgaray Dec 3, 2024
2664e8c
fix: readLength not consuming byte header when array is null-terminated
rmgaray Dec 3, 2024
af2e280
fix: roundtrip property for arrays and Uint32Arrays
rmgaray Dec 4, 2024
e59894b
fix: zero being interpreted as indefinite length
rmgaray Dec 4, 2024
d1808ae
fix: use correct method for pushing bytes
rmgaray Dec 4, 2024
48089d3
fix: use sets instead of lists for fields of witness set & fix: round…
rmgaray Dec 4, 2024
ffa6c28
add script_pubkey to blacklist
rmgaray Dec 4, 2024
892e809
fix: off by two error when reading negative integers
rmgaray Dec 4, 2024
46f5950
switch to boolean flag for definite/indefinite encoding
rmgaray Dec 9, 2024
feca0a1
fix: re-add Redeemers class for API compatibility
rmgaray Dec 9, 2024
295592f
fix: return type for (set_)invalid_transactions methods
rmgaray Dec 9, 2024
fb0262a
fix: return typep for Redeemer.new
rmgaray Dec 9, 2024
03f2385
fix: types for TransactionWitnessSet.(set_)plutus_data
rmgaray Dec 9, 2024
090ab7a
update CDL declaration file
rmgaray Dec 9, 2024
ab3b996
remove debug method in Reader class
rmgaray Dec 9, 2024
bdc7ac7
fix: byron address deserialization
rmgaray Dec 11, 2024
3809ad0
fix: component extraction failing with inner_plutus_data
rmgaray Dec 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 56 additions & 27 deletions conway-cddl/codegen/generators/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { CodeGeneratorBase, CodeGeneratorBaseOptions } from ".";
import { SchemaTable } from "..";

export type GenArrayOptions = {
item: string;
item: string | undefined;
} & CodeGeneratorBaseOptions;

export class GenArray extends CodeGeneratorBase {
item: string;
item: string | undefined;

constructor(
name: string,
Expand All @@ -18,60 +18,89 @@ export class GenArray extends CodeGeneratorBase {
}

private itemJsType() {
return this.typeUtils.jsType(this.item);
return this.item ? `${this.typeUtils.jsType(this.item)}` : undefined;
}

generateMembers(): string {
return `private items: ${this.itemJsType()}[];`;
const jsType = this.itemJsType();
return `
private items: ${jsType ? `${jsType}[]` : `Uint32Array`};
private definiteEncoding: boolean;
`;
}

generateConstructor(): string {
const jsType = this.itemJsType();
return `
constructor(items: ${this.itemJsType()}[]) {
constructor(items: ${jsType ? `${jsType}[]` : `Uint32Array`}, definiteEncoding: boolean = true) {
this.items = items;
this.definiteEncoding = definiteEncoding;
}
`;
}

generateExtraMethods(): string {
let itemJsType = this.typeUtils.jsType(this.item);
let jsType = this.itemJsType();
return `
static new(): ${this.name} {
return new ${this.name}([]);
return new ${this.name}(${jsType ? "[]" : "new Uint32Array([])"});
}

len(): number {
return this.items.length;
}

get(index: number): ${itemJsType} {
if(index >= this.items.length) throw new Error("Array out of bounds");
return this.items[index];
}
${jsType ?
`
get(index: number): ${jsType} {
if(index >= this.items.length) throw new Error("Array out of bounds");
return this.items[index];
}

add(elem: ${itemJsType}): void {
this.items.push(elem);
add(elem: ${jsType}): void {
this.items.push(elem);
}
` : ''
}
`;
}

generateDeserialize(reader: string, path: string): string {
return `
return new ${this.name}(
${reader}.readArray(
(reader, idx) => ${this.typeUtils.readType("reader", this.item, `[...${path}, "Elem#" + idx]`)}
, ${path}
)
);
`;
if (this.item) {
return `
const { items, definiteEncoding } =
${reader}.readArray(
(reader, idx) => ${this.typeUtils.readType("reader", this.item, `[...${path}, "Elem#" + idx]`)}
, ${path}
)
return new ${this.name}(items, definiteEncoding);
`;
} else {
return `
const { items, definiteEncoding } =
${reader}.readArray(
(reader, idx) => Number(reader.readUint([...${path}, "Byte#" + idx]))
, ${path}
)

return new ${this.name}(new Uint32Array(items), definiteEncoding);
`;
}
}

generateSerialize(writer: string): string {
return `
${writer}.writeArray(
this.items,
(writer, x) => ${this.typeUtils.writeType("writer", "x", this.item)}
);
`;
if (this.item) {
return `
${writer}.writeArray(
this.items,
(writer, x) => ${this.typeUtils.writeType("writer", "x", this.item)},
this.definiteEncoding
);
`;
} else {
return `
${writer}.writeArray(this.items, (writer, x) => writer.writeInt(BigInt(x)), this.definiteEncoding)
`
}
}
}
8 changes: 0 additions & 8 deletions conway-cddl/codegen/generators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,6 @@ export class TypeUtils {
return yamlType;
case "bytes":
return "Uint8Array";
case "arrayToUint32Array":
return "Uint32Array";
default:
console.error("Unknown type: " + yamlType);
return "unknown";
Expand All @@ -292,8 +290,6 @@ export class TypeUtils {
return `${reader}.readBoolean(${path})`;
case "bytes":
return `${reader}.readBytes(${path})`;
case "arrayToUint32Array":
return `new Uint32Array(${reader}.readArray((reader) => Number(reader.readUint(${path})), ${path}));`;
default:
console.error("Can't decode: " + type);
return `$$CANT_READ("${type}")`;
Expand All @@ -317,8 +313,6 @@ export class TypeUtils {
return `${writer}.writeBoolean(${value})`;
case "bytes":
return `${writer}.writeBytes(${value})`;
case "arrayToUint32Array":
return `${writer}.writeArray(${value}, (writer, x) => writer.writeInt(BigInt(x)))`;
default:
console.error("Can't encode: " + type);
return `$$CANT_WRITE("${type}")`;
Expand All @@ -338,8 +332,6 @@ export class TypeUtils {
case "boolean":
return `${var1} === ${var2}`;
case "bytes":
case "arrayToUint32Array":
return `arrayEq(${var1}, ${var2})`;
default:
console.error("Can't compare: " + type);
return `$$CANT_EQ("${type}")`;
Expand Down
30 changes: 25 additions & 5 deletions conway-cddl/codegen/generators/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,21 @@ export class GenSet extends CodeGeneratorBase {
generateMembers(): string {
return `
private items: ${this.itemJsType()}[];
private definiteEncoding: boolean;
private nonEmptyTag: boolean;

private setItems(items: ${this.itemJsType()}[]) {
this.items = items;
}
`;
}

generateConstructor(): string {
return `
constructor() {
constructor(definiteEncoding: boolean = true, nonEmptyTag: boolean = true) {
this.items = [];
this.definiteEncoding = definiteEncoding;
this.nonEmptyTag = nonEmptyTag;
}
`;
}
Expand Down Expand Up @@ -66,19 +74,31 @@ export class GenSet extends CodeGeneratorBase {

generateDeserialize(reader: string, path: string): string {
return `
let ret = new ${this.name}();
let nonEmptyTag = false;
if(${reader}.peekType(${path}) == "tagged") {
let tag = ${reader}.readTaggedTag(${path});
if(tag != 258) throw new Error("Expected tag 258. Got " + tag);
if(tag != 258) {
throw new Error("Expected tag 258. Got " + tag);
} else {
nonEmptyTag = true;
}
}
${reader}.readArray((reader, idx) => ret.add(${this.typeUtils.readType(reader, this.item, `[...${path}, '${this.item}#' + idx]`)}), ${path});
const { items, definiteEncoding } = ${reader}.readArray(
(reader, idx) =>
${this.typeUtils.readType( reader, this.item, `[...${path}, '${this.item}#' + idx]`)},
${path}
);
let ret = new ${this.name}(definiteEncoding, nonEmptyTag);
ret.setItems(items);
return ret;
`;
}

generateSerialize(writer: string): string {
return `
${writer}.writeTaggedTag(258);
if (this.nonEmptyTag) {
${writer}.writeTaggedTag(258);
}
${writer}.writeArray(this.items, (writer, x) => ${this.typeUtils.writeType("writer", "x", this.item)});
`;
}
Expand Down
4 changes: 4 additions & 0 deletions conway-cddl/codegen/generators/structured/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export class GenStructuredBase<
return this.options.fields;
}

getMinFields(): number {
return this.options.fields.filter((v) => !v.optional).length
}

generateMembers(): string {
return this.options.fields
.map((x) => `private _${x.name}: ${this.fieldType(x)};`)
Expand Down
48 changes: 32 additions & 16 deletions conway-cddl/codegen/generators/structured/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type Field = {
name: string;
type: string;
nullable?: boolean;
optional?: boolean;
};

export type GenRecordOptions = {
Expand All @@ -24,21 +25,23 @@ export class GenRecord extends GenStructuredBase<Field> {
return `
let len = ${reader}.readArrayTag(${path});

if(len != null && len < ${this.getFields().length}) {
throw new Error("Insufficient number of fields in record. Expected ${this.getFields().length}. Received " + len + "(at " + path.join("/"));
if(len != null && len < ${this.getMinFields()}) {
throw new Error("Insufficient number of fields in record. Expected at least ${this.getMinFields()}. Received " + len + "(at " + path.join("/"));
}

${this.getFields()
.map(
(x) => `
const ${x.name}_path = [...${path}, '${x.type}(${x.name})'];
let ${x.name} = ${
x.nullable
? `${reader}.readNullable(r => ${this.typeUtils.readType("r", x.type, `${x.name}_path`)}, ${path})?? undefined`
: this.typeUtils.readType(reader, x.type, `${x.name}_path`)
};`,
)
.join("\n")}
${this.getFields().reduce((acc, x, idx) => {
acc.push(`
const ${x.name}_path = [...${path}, '${x.type}(${x.name})'];
let ${x.name} = ${
x.optional ?
`len != null && len > ${idx} ? ${this.typeUtils.readType(reader, x.type, `${x.name}_path`)} : undefined` :
x.nullable ?
`${reader}.readNullable(r => ${this.typeUtils.readType("r", x.type, `${x.name}_path`)}, ${path})?? undefined` :
this.typeUtils.readType(reader, x.type, `${x.name}_path`)
}
`);
return acc;
}, [] as string[]).join("\n")}

return new ${this.name}(${this.getFields()
.map((x) => x.name)
Expand All @@ -48,17 +51,30 @@ export class GenRecord extends GenStructuredBase<Field> {

generateSerialize(writer: string): string {
return `
${writer}.writeArrayTag(${this.getFields().length});
let arrayLen = ${this.getMinFields()};
${this.getFields().
map((x) => x.optional
? `if(this._${x.name}) {
arrayLen++;
}` :
"")
.join("\n")}

${writer}.writeArrayTag(arrayLen);

${this.getFields()
.map((x) =>
x.optional
? `if(this._${x.name}) {
${this.typeUtils.writeType(writer, `this._${x.name}`, x.type)};
}` :
x.nullable
? `if(this._${x.name} == null) {
${writer}.writeNull();
} else {
${this.typeUtils.writeType(writer, `this._${x.name}`, x.type)};
}`
: `${this.typeUtils.writeType(writer, `this._${x.name}`, x.type)};`,
}` :
`${this.typeUtils.writeType(writer, `this._${x.name}`, x.type)};`,
)
.join("\n")}
`;
Expand Down
8 changes: 6 additions & 2 deletions conway-cddl/codegen/generators/tagged_record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,18 @@ export class GenTaggedRecord extends CodeGeneratorBase {
break;
`,
)
.concat([`
default:
throw new Error("Unexpected tag for ${this.name}: " + tag + "(at " + ${path}.join("/") + ")");
`])
.join("\n")}
}

if(len == null) {
${reader}.readBreak();
}
throw new Error("Unexpected tag for ${this.name}: " + tag + "(at " + ${path}.join("/") + ")");

return new ${this.name}(variant);
`;
}

Expand Down
3 changes: 2 additions & 1 deletion conway-cddl/codegen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const Schema = Type.Intersect([
extra_methods: Type.Optional(Type.String()),
}),
Type.Union([
Type.Object({ type: Type.Literal("array"), item: Type.String() }),
Type.Object({ type: Type.Literal("array"), item: Type.Optional(Type.String()) }),
Type.Object({
type: Type.Literal("enum"),
values: Type.Array(
Expand Down Expand Up @@ -78,6 +78,7 @@ export const Schema = Type.Intersect([
name: Type.String(),
type: Type.String(),
nullable: Type.Optional(Type.Boolean()),
optional: Type.Optional(Type.Boolean())
}),
),
accessor_get_prefix: Type.Optional(Type.Boolean()),
Expand Down
Loading
Loading