Skip to content

Commit

Permalink
[parser] - Normalize primitive objects of michelson JSON before parsi…
Browse files Browse the repository at this point in the history
…ng it
  • Loading branch information
RomarQ committed Feb 2, 2021
1 parent f40b152 commit 0813014
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
23 changes: 23 additions & 0 deletions src/chain/tezos/TezosLanguageUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import * as nearley from 'nearley';

import { TezosMessageUtils } from './TezosMessageUtil';

const primitiveRecordOrder = ["prim", "args", "annots"];

/**
* A collection of functions to encode and decode Michelson and Micheline code
*/
Expand Down Expand Up @@ -430,6 +432,27 @@ export namespace TezosLanguageUtil {
return parts.map(p => p.trim().split('\n').map(l => l.replace(/\#[\s\S]+$/, '').trim()).filter(v => v.length > 0).join(' '));
}

/**
* This util function is used to ensure the correct order in primitive records before parsing it.
*
* Micheline parser expects the following JSON order { prim: ..., args: ..., annots: ... }
*/
export function normalizePrimitiveRecordOrder(obj: object) {
if (Array.isArray(obj)) {
return obj.map(normalizePrimitiveRecordOrder);
}

if (typeof obj === "object") {
return Object.keys(obj)
.sort((k1, k2) => primitiveRecordOrder.indexOf(k1) - primitiveRecordOrder.indexOf(k2))
.reduce((newObj, key) => ({
...newObj,
[key]: normalizePrimitiveRecordOrder(obj[key])
}), {});
}
return obj;
}

/**
* Micheline parser expects certain whitespace arrangement, this function will correct the input string accordingly.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/chain/tezos/TezosMessageCodec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,12 @@ export namespace TezosMessageCodec {
}

if (!!origination.script) {
let parts: string[] = [];
let parts: object[] = [];
parts.push(origination.script['code']); // full contract definition containing code, storage and parameters properties
parts.push(origination.script['storage']); // initial storage

hex += parts
.map(TezosLanguageUtil.normalizePrimitiveRecordOrder)
.map(p => TezosLanguageUtil.normalizeMichelineWhiteSpace(JSON.stringify(p)))
.map(p => TezosLanguageUtil.translateMichelineToHex(p))
.reduce((m, p) => { return m + ('0000000' + (p.length / 2).toString(16)).slice(-8) + p; }, '');
Expand Down
74 changes: 74 additions & 0 deletions test/chain/tezos/TezosLanguageUtil.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,80 @@ describe("Tezos Michelson/Micheline fragment codec", () => {
let result = TezosLanguageUtil.translateMichelineToHex(params);
expect(result).to.equal('010000000568656c6c6f');
});

it('Normalize Michelson JSON primitive record', () => {
let input = {
"prim": "parameter",
"args": [
{
"prim": "list",
"args": [
{
"prim": "pair",
"args": [
{
"prim": "sapling_transaction",
"annots": ["%transaction"],
"args": [
{
"int":"8"
}
],
},
{
"prim": "option",
"annots": ["%key"],
"args": [
{
"prim":"key_hash"
}
],
}
]
}
]
}
]
};
let expectedOutput = {
"prim": "parameter",
"args": [
{
"prim": "list",
"args": [
{
"prim": "pair",
"args": [
{
"prim": "sapling_transaction",
"args": [
{
"int":"8"
}
],
"annots": ["%transaction"],
},
{
"prim": "option",
"args": [
{
"prim":"key_hash"
}
],
"annots": ["%key"],
}
]
}
]
}
]
};

/**
* Ensure that { prim: ..., annots: ..., args: ... } is ordered to => { prim: ..., args: ..., annots: ... }
*/
expect(JSON.stringify(TezosLanguageUtil.normalizePrimitiveRecordOrder(input))).equal(JSON.stringify(expectedOutput));
});
});

function preProcessMicheline(code: string): string[] {
Expand Down

0 comments on commit 0813014

Please sign in to comment.