Skip to content

Commit

Permalink
fix: the idx of a pair inside or inside pair is not calculated correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
ac10n committed Apr 23, 2024
1 parent 12996df commit 069c264
Show file tree
Hide file tree
Showing 5 changed files with 476 additions and 34 deletions.
15 changes: 11 additions & 4 deletions packages/taquito-michelson-encoder/src/tokens/createToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { TaquitoError } from '@taquito/core';
*/
export class InvalidTokenError extends TaquitoError {
name = 'Invalid token error';
constructor(public message: string, public data: any) {
constructor(
public message: string,
public data: any
) {
super(message);
}
}
Expand All @@ -19,9 +22,13 @@ export class InvalidTokenError extends TaquitoError {
* @description Create a token from a value
* @throws {@link InvalidTokenError} If the value passed is not supported by the Michelson Encoder
*/
export function createToken(val: any, idx: number): Token {
export function createToken(
val: any,
idx: number,
parentTokenType?: 'Or' | 'Pair' | 'Other' | undefined
): Token {
if (Array.isArray(val)) {
return new PairToken(val, idx, createToken);
return new PairToken(val, idx, createToken, parentTokenType);
}

const t = tokens.find((x) => x.prim === val.prim);
Expand All @@ -31,5 +38,5 @@ export function createToken(val: any, idx: number): Token {
val
);
}
return new t(val, idx, createToken);
return new t(val, idx, createToken, parentTokenType);
}
39 changes: 24 additions & 15 deletions packages/taquito-michelson-encoder/src/tokens/or.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import {
*/
export class OrValidationError extends TokenValidationError {
name = 'OrValidationError';
constructor(public value: any, public token: OrToken, message: string) {
constructor(
public value: any,
public token: OrToken,
message: string
) {
super(value, token, message);
}
}
Expand All @@ -25,21 +29,22 @@ export class OrToken extends ComparableToken {
constructor(
protected val: { prim: string; args: any[]; annots: any[] },
protected idx: number,
protected fac: TokenFactory
protected fac: TokenFactory,
protected parentTokenType?: 'Or' | 'Pair' | 'Other' | undefined
) {
super(val, idx, fac);
super(val, idx, fac, parentTokenType);
}

public Encode(args: any[]): any {
const label = args[args.length - 1];

const leftToken = this.createToken(this.val.args[0], this.idx);
const leftToken = this.createToken(this.val.args[0], this.getIdx(), 'Or');
let keyCount = 1;
if (leftToken instanceof OrToken) {
keyCount = Object.keys(leftToken.ExtractSchema()).length;
}

const rightToken = this.createToken(this.val.args[1], this.idx + keyCount);
const rightToken = this.createToken(this.val.args[1], this.getIdx() + keyCount, 'Or');

if (String(leftToken.annot()) === String(label) && !(leftToken instanceof OrToken)) {
args.pop();
Expand All @@ -66,13 +71,13 @@ export class OrToken extends ComparableToken {
}

public ExtractSignature(): any {
const leftToken = this.createToken(this.val.args[0], this.idx);
const leftToken = this.createToken(this.val.args[0], this.getIdx(), 'Or');
let keyCount = 1;
if (leftToken instanceof OrToken) {
keyCount = Object.keys(leftToken.ExtractSchema()).length;
}

const rightToken = this.createToken(this.val.args[1], this.idx + keyCount);
const rightToken = this.createToken(this.val.args[1], this.getIdx() + keyCount, 'Or');

const newSig = [];

Expand Down Expand Up @@ -102,13 +107,13 @@ export class OrToken extends ComparableToken {
this.validateJavascriptObject(args);
const label = Object.keys(args)[0];

const leftToken = this.createToken(this.val.args[0], this.idx);
const leftToken = this.createToken(this.val.args[0], this.getIdx(), 'Or');
let keyCount = 1;
if (leftToken instanceof OrToken) {
keyCount = Object.keys(leftToken.ExtractSchema()).length;
}

const rightToken = this.createToken(this.val.args[1], this.idx + keyCount);
const rightToken = this.createToken(this.val.args[1], this.getIdx() + keyCount, 'Or');

if (String(leftToken.annot()) === String(label) && !(leftToken instanceof OrToken)) {
return { prim: 'Left', args: [leftToken.EncodeObject(args[label], semantic)] };
Expand Down Expand Up @@ -154,12 +159,12 @@ export class OrToken extends ComparableToken {
* @throws {@link OrValidationError}
*/
public Execute(val: any, semantics?: Semantic): any {
const leftToken = this.createToken(this.val.args[0], this.idx);
const leftToken = this.createToken(this.val.args[0], this.getIdx(), 'Or');
let keyCount = 1;
if (leftToken instanceof OrToken) {
keyCount = Object.keys(leftToken.ExtractSchema()).length;
}
const rightToken = this.createToken(this.val.args[1], this.idx + keyCount);
const rightToken = this.createToken(this.val.args[1], this.getIdx() + keyCount, 'Or');

if (val.prim === 'Right') {
if (rightToken instanceof OrToken) {
Expand Down Expand Up @@ -190,7 +195,7 @@ export class OrToken extends ComparableToken {
getRightValue: (token: Token) => any,
concat: (left: any, right: any) => any
) {
const leftToken = this.createToken(this.val.args[0], this.idx);
const leftToken = this.createToken(this.val.args[0], this.getIdx(), 'Or');
let keyCount = 1;
let leftValue;
if (leftToken instanceof OrToken) {
Expand All @@ -200,7 +205,7 @@ export class OrToken extends ComparableToken {
leftValue = { [leftToken.annot()]: getLeftValue(leftToken) };
}

const rightToken = this.createToken(this.val.args[1], this.idx + keyCount);
const rightToken = this.createToken(this.val.args[1], this.getIdx() + keyCount, 'Or');
let rightValue;
if (rightToken instanceof OrToken) {
rightValue = getRightValue(rightToken);
Expand Down Expand Up @@ -255,13 +260,13 @@ export class OrToken extends ComparableToken {
}

private findToken(label: any): Token | null {
const leftToken = this.createToken(this.val.args[0], this.idx);
const leftToken = this.createToken(this.val.args[0], this.getIdx(), 'Or');
let keyCount = 1;
if (leftToken instanceof OrToken) {
keyCount = Object.keys(leftToken.ExtractSchema()).length;
}

const rightToken = this.createToken(this.val.args[1], this.idx + keyCount);
const rightToken = this.createToken(this.val.args[1], this.getIdx() + keyCount, 'Or');

if (
String(leftToken.annot()) === String(label) &&
Expand Down Expand Up @@ -334,4 +339,8 @@ export class OrToken extends ComparableToken {
);
return tokens;
}

protected getIdx(): number {
return this.parentTokenType === 'Or' ? this.idx : 0;
}
}
34 changes: 22 additions & 12 deletions packages/taquito-michelson-encoder/src/tokens/pair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,27 @@ function collapse(val: Token['val'] | any[], prim: string = PairToken.prim): [an
export class PairToken extends ComparableToken {
static prim: 'pair' = 'pair' as const;

constructor(val: MichelsonV1Expression, idx: number, fac: TokenFactory) {
constructor(
val: MichelsonV1Expression,
idx: number,
fac: TokenFactory,
parentTokenType?: 'Or' | 'Pair' | 'Other' | undefined
) {
super(
Array.isArray(val)
? {
prim: PairToken.prim,
args: val,
}
: (val as MichelsonV1ExpressionExtended).prim
? (val as MichelsonV1ExpressionExtended)
: ({
prim: PairToken.prim,
args: val,
} as MichelsonV1ExpressionExtended),
? (val as MichelsonV1ExpressionExtended)
: ({
prim: PairToken.prim,
args: val,
} as MichelsonV1ExpressionExtended),
idx,
fac
fac,
parentTokenType
);
}

Expand All @@ -91,7 +97,7 @@ export class PairToken extends ComparableToken {
private tokens(): [Token, Token] {
let cnt = 0;
return this.args().map((a) => {
const tok = this.createToken(a, this.idx + cnt);
const tok = this.createToken(a, this.getIdx() + cnt, 'Pair');
if (tok instanceof PairToken) {
cnt += Object.keys(tok.ExtractSchema()).length;
} else {
Expand All @@ -110,13 +116,13 @@ export class PairToken extends ComparableToken {

public ExtractSignature(): any {
const args = this.args();
const leftToken = this.createToken(args[0], this.idx);
const leftToken = this.createToken(args[0], this.getIdx(), 'Pair');
let keyCount = 1;
if (leftToken instanceof OrToken) {
keyCount = Object.keys(leftToken.ExtractSchema()).length;
}

const rightToken = this.createToken(args[1], this.idx + keyCount);
const rightToken = this.createToken(args[1], this.getIdx() + keyCount, 'Pair');

const newSig = [];

Expand Down Expand Up @@ -169,7 +175,7 @@ export class PairToken extends ComparableToken {
private traversal(getLeftValue: (token: Token) => any, getRightValue: (token: Token) => any) {
const args = this.args();

const leftToken = this.createToken(args[0], this.idx);
const leftToken = this.createToken(args[0], this.getIdx(), 'Pair');
let keyCount = 1;
let leftValue;
if (leftToken instanceof PairToken && !leftToken.hasAnnotations()) {
Expand All @@ -181,7 +187,7 @@ export class PairToken extends ComparableToken {
leftValue = { [leftToken.annot()]: getLeftValue(leftToken) };
}

const rightToken = this.createToken(args[1], this.idx + keyCount);
const rightToken = this.createToken(args[1], this.getIdx() + keyCount, 'Pair');
let rightValue;
if (rightToken instanceof PairToken && !rightToken.hasAnnotations()) {
rightValue = getRightValue(rightToken);
Expand Down Expand Up @@ -275,4 +281,8 @@ export class PairToken extends ComparableToken {
this.tokens().map((t) => t.findAndReturnTokens(tokenToFind, tokens));
return tokens;
}

protected getIdx(): number {
return this.parentTokenType === 'Pair' ? this.idx : 0;
}
}
15 changes: 12 additions & 3 deletions packages/taquito-michelson-encoder/src/tokens/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@ import { TaquitoError } from '@taquito/core';
export abstract class TokenValidationError extends TaquitoError {
name = 'TokenValidationError';

constructor(public readonly value: any, public readonly token: Token, baseMessage: string) {
constructor(
public readonly value: any,
public readonly token: Token,
baseMessage: string
) {
super();
const annot = this.token.annot();
const annotText = annot ? `[${annot}] ` : '';
this.message = `${annotText}${baseMessage}`;
}
}

export type TokenFactory = (val: any, idx: number) => Token;
export type TokenFactory = (
val: any,
idx: number,
parentTokenType?: 'Or' | 'Pair' | 'Other'
) => Token;

export interface Semantic {
[key: string]: (value: MichelsonV1Expression, schema: MichelsonV1Expression) => any;
Expand All @@ -31,7 +39,8 @@ export abstract class Token {
constructor(
protected val: MichelsonV1ExpressionExtended,
protected idx: number,
protected fac: TokenFactory
protected fac: TokenFactory,
protected parentTokenType?: 'Or' | 'Pair' | 'Other'
) {}

protected typeWithoutAnnotations() {
Expand Down
Loading

0 comments on commit 069c264

Please sign in to comment.