Skip to content

Commit

Permalink
- fixed hex->michelson annotation decoding issue
Browse files Browse the repository at this point in the history
- tests
- docs
- updated webdist: 55ElSck0OR93XvRRLY9kqwLv1ueRL2O04duNhZwdPRAO1qFCqYwqASM7NFphWOhv
  • Loading branch information
anonymoussprocket committed Aug 19, 2020
1 parent 0a7d250 commit 96b329c
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 215 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ TBD
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/cryptonomic/conseiljs/dist-web/conseiljs.min.js"
integrity="sha384-fEY0z9o3rje0DMNsk6cJ1znEOYXtTpSJX+QrwkIqrEvPGIYLHPDliaerr7tRJ0HL"
integrity="sha384-55ElSck0OR93XvRRLY9kqwLv1ueRL2O04duNhZwdPRAO1qFCqYwqASM7NFphWOhv"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/cryptonomic/conseiljs-softsigner/dist-web/conseiljs-softsigner.min.js"
integrity="sha384-V1iaajn0x/SMFcZ9Y/xNQmqQSKyll6Dzt27U6OWiv8NdbHTVaHOGHdQ8g0G68HPd"
Expand Down
2 changes: 1 addition & 1 deletion dist-web/conseiljs.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Unlike the nodejs sample, it's not possible to configure fetch or logger referen
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/cryptonomic/conseiljs/dist-web/conseiljs.min.js"
integrity="sha384-fEY0z9o3rje0DMNsk6cJ1znEOYXtTpSJX+QrwkIqrEvPGIYLHPDliaerr7tRJ0HL"
integrity="sha384-55ElSck0OR93XvRRLY9kqwLv1ueRL2O04duNhZwdPRAO1qFCqYwqASM7NFphWOhv"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/cryptonomic/conseiljs-softsigner/dist-web/conseiljs-softsigner.min.js"
crossorigin="anonymous"></script>
Expand Down
32 changes: 18 additions & 14 deletions src/chain/tezos/TezosLanguageUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export namespace TezosLanguageUtil {
code += `{ "prim": ${hexToMichelineKeyword(hex, offset)}, `;
offset += 2;

const annEnvelope = michelineHexToAnnotations(hex.substring(offset));
const annEnvelope = hexToAnnotations(hex.substring(offset));
code += `"annots": [ ${annEnvelope.code} ] }`;
offset += annEnvelope.consumed;
break;
Expand All @@ -82,7 +82,7 @@ export namespace TezosLanguageUtil {
code += `"args": [ ${args.code} ], `;
offset += args.consumed;

const anns = michelineHexToAnnotations(hex.substring(offset));
const anns = hexToAnnotations(hex.substring(offset));
code += `"annots": [ ${anns.code} ] }`;
offset += anns.consumed;
break;
Expand Down Expand Up @@ -112,7 +112,7 @@ export namespace TezosLanguageUtil {
offset += arg1.consumed;
code += `"args": [ ${arg0.code}, ${arg1.code} ], `;

const anns = michelineHexToAnnotations(hex.substring(offset));
const anns = hexToAnnotations(hex.substring(offset));
code += `"annots": [ ${anns.code} ] }`;
offset += anns.consumed;
break;
Expand All @@ -126,7 +126,7 @@ export namespace TezosLanguageUtil {
offset += envelope.consumed - 2; // account for the inserted '02' above

if (hex.substring(offset, offset + 8) !== '00000000') {
const annEnvelope = michelineHexToAnnotations(hex.substring(offset));
const annEnvelope = hexToAnnotations(hex.substring(offset));
if (annEnvelope.code.length > 2) { // more than empty quotes
code += `, "annots": [ ${annEnvelope.code} ] }`;
}
Expand Down Expand Up @@ -165,13 +165,13 @@ export namespace TezosLanguageUtil {
switch (fieldType) {
case '00': { // literal int or nat
const value = TezosMessageUtils.findInt(hex.substring(offset), 0, true);
code += ` ${value.value} `;
code += `${value.value}`;
offset += value.length;
break;
}
case '01': { // literal string
const stringEnvelope = michelineHexToString(hex.substring(offset));
code += ` "${stringEnvelope.code}" `;
code += `"${stringEnvelope.code}"`;
offset += stringEnvelope.consumed;
break;
}
Expand Down Expand Up @@ -202,7 +202,7 @@ export namespace TezosLanguageUtil {
code += `( ${hexToMichelsonKeyword(hex, offset)} `;
offset += 2;

const annEnvelope = michelineHexToAnnotations(hex.substring(offset));
const annEnvelope = hexToAnnotations(hex.substring(offset), false);
code += ` ${annEnvelope.code} )`;
offset += annEnvelope.consumed;
break;
Expand All @@ -223,7 +223,7 @@ export namespace TezosLanguageUtil {
code += ` ${args.code} `;
offset += args.consumed;

const anns = michelineHexToAnnotations(hex.substring(offset));
const anns = hexToAnnotations(hex.substring(offset), false);
code += ` ${anns.code} )`;
offset += anns.consumed;
break;
Expand Down Expand Up @@ -253,7 +253,7 @@ export namespace TezosLanguageUtil {
offset += arg1.consumed;
code += ` ${arg0.code} ${arg1.code} `;

const anns = michelineHexToAnnotations(hex.substring(offset));
const anns = hexToAnnotations(hex.substring(offset), false);
code += ` ${anns.code} )`;
offset += anns.consumed;
break;
Expand All @@ -267,7 +267,7 @@ export namespace TezosLanguageUtil {
offset += envelope.consumed - 2; // account for the inserted '02' above

if (hex.substring(offset, offset + 8) !== '00000000') {
const annEnvelope = michelineHexToAnnotations(hex.substring(offset));
const annEnvelope = hexToAnnotations(hex.substring(offset), false);
if (annEnvelope.code.length > 2) { // more than empty quotes
code += ` ${annEnvelope.code} )`;
}
Expand All @@ -281,7 +281,7 @@ export namespace TezosLanguageUtil {
case '0a': { // raw bytes
const length = parseInt(hex.substring(offset, offset + 8), 16);
offset += 8;
code += ` 0x${hex.substring(offset, offset + length * 2)} `;
code += `0x${hex.substring(offset, offset + length * 2)}`;
offset += length * 2;
break;
}
Expand Down Expand Up @@ -389,11 +389,15 @@ export namespace TezosLanguageUtil {
*
* @param {string} hex Hex-encoded contract fragment to process
* @returns {codeEnvelope} Parsed annotations and the number of consumed bytes.
* * @see [Michelson Annotations]{@link https://tezos.gitlab.io/whitedoc/michelson.html#annotations}
* @see [Michelson Annotations]{@link https://tezos.gitlab.io/whitedoc/michelson.html#annotations}
*/
function michelineHexToAnnotations(hex: string): codeEnvelope {
function hexToAnnotations(hex: string, quote: boolean = true): codeEnvelope {
const stringEnvelope = michelineHexToString(hex);
return { code: stringEnvelope.code.split(' ').map(s => `"${s}"`).join(', '), consumed: stringEnvelope.consumed };

return {
code: (quote ? stringEnvelope.code.split(' ').map(s => `"${s}"`).join(', ') : stringEnvelope.code),
consumed: stringEnvelope.consumed
};
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/chain/tezos/TezosMessageUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ export namespace TezosMessageUtils {
}

/**
* Writes a Base58-check key into hex.
* Serializes a Base58-check key into hex.
*
* @param key Key to encode, input is expected to be a base58-check encoded string.
* @param hint Key type, usually the curve it was generated from, eg: 'edsk'.
Expand All @@ -308,7 +308,7 @@ export namespace TezosMessageUtils {
}

/**
* Reads a signature value without a prefix from binary and decodes it into a Base58-check representation.
* Deserializes a signature value without a prefix from binary and decodes it into a Base58-check representation.
*
* @param {Buffer | Uint8Array} b Bytes containing signature.
* @param hint Support 'edsig'.
Expand All @@ -328,7 +328,7 @@ export namespace TezosMessageUtils {
}

/**
* Writes a Base58-check key into hex.
* Serializes a Base58-check key into hex.
*
* @param key Key to encode, input is expected to be a base58-check encoded string.
* @param hint Key type, usually the curve it was generated from, eg: 'edsig'.
Expand All @@ -346,7 +346,7 @@ export namespace TezosMessageUtils {
}

/**
* Reads a binary buffer and decodes it into a Base58-check string subject to a hint. Calling this method with a blank hint makes it a wraper for base58check.encode().
* Deserializes a binary buffer and decodes it into a Base58-check string subject to a hint. Calling this method with a blank hint makes it a wraper for base58check.encode().
*
* @param {Buffer | Uint8Array} b Bytes to encode
* @param hint One of: 'op' (operation encoding helper), 'p' (proposal), '' (blank)
Expand Down
98 changes: 82 additions & 16 deletions test/chain/tezos/TezosLanguageUtil.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil';
import * as fs from 'fs';
import * as path from 'path';

describe("Tezos Micheline fragment decoding", () => {
it('Small int', () => {
describe("Tezos Michelson/Micheline fragment codec", () => {
it('Small int: hex -> Micheline', () => {
let result = TezosLanguageUtil.hexToMicheline('0006');
expect(result.code).to.equal('{ "int": "6" }');

Expand All @@ -19,7 +19,21 @@ describe("Tezos Micheline fragment decoding", () => {
expect(result.code).to.equal('{ "int": "-63" }');
});

it('Medium int', () => {
it('Small int: hex -> Michelson', () => {
let result = TezosLanguageUtil.hexToMichelson('0006');
expect(result.code).to.equal('6');

result = TezosLanguageUtil.hexToMichelson('0046');
expect(result.code).to.equal('-6');

result = TezosLanguageUtil.hexToMichelson('003f');
expect(result.code).to.equal('63');

result = TezosLanguageUtil.hexToMichelson('007f');
expect(result.code).to.equal('-63');
});

it('Medium int: hex -> Micheline', () => {
let result = TezosLanguageUtil.hexToMicheline('00a101');
expect(result.code).to.equal('{ "int": "97" }');

Expand All @@ -33,7 +47,21 @@ describe("Tezos Micheline fragment decoding", () => {
expect(result.code).to.equal('{ "int": "-900" }');
});

it('Large int', () => {
it('Medium int: hex -> Michelson', () => {
let result = TezosLanguageUtil.hexToMichelson('00a101');
expect(result.code).to.equal('97');

result = TezosLanguageUtil.hexToMichelson('00ff01');
expect(result.code).to.equal('-127');

result = TezosLanguageUtil.hexToMichelson('00840e');
expect(result.code).to.equal('900');

result = TezosLanguageUtil.hexToMichelson('00c40e');
expect(result.code).to.equal('-900');
});

it('Large int: hex -> Micheline', () => {
let result = TezosLanguageUtil.hexToMicheline('00ba9af7ea06');
expect(result.code).to.equal('{ "int": "917431994" }');

Expand All @@ -53,34 +81,72 @@ describe("Tezos Micheline fragment decoding", () => {
expect(result.code).to.equal('{ "int": "-610913435200" }');
});

it('string', () => {
const result = TezosLanguageUtil.hexToMicheline('01000000096d696368656c696e65');
expect(result.code).to.equal('{ "string": "micheline" }');
it('Large int: hex -> Michelson', () => {
let result = TezosLanguageUtil.hexToMichelson('00ba9af7ea06');
expect(result.code).to.equal('917431994');

result = TezosLanguageUtil.hexToMichelson('00fa9af7ea06');
expect(result.code).to.equal('-917431994');

result = TezosLanguageUtil.hexToMichelson('00a1d22c');
expect(result.code).to.equal('365729');

result = TezosLanguageUtil.hexToMichelson('00e1d22c');
expect(result.code).to.equal('-365729');

result = TezosLanguageUtil.hexToMichelson('0080f9b9d4c723');
expect(result.code).to.equal('610913435200');

result = TezosLanguageUtil.hexToMichelson('00c0f9b9d4c723');
expect(result.code).to.equal('-610913435200');
});

it('empty string', () => {
const result = TezosLanguageUtil.hexToMicheline('0100000000');
it('string: hex -> Michelson', () => {
let result = TezosLanguageUtil.hexToMicheline('01000000096d696368656c696e65');
expect(result.code).to.equal('{ "string": "micheline" }');

result = TezosLanguageUtil.hexToMicheline('0100000000');
expect(result.code).to.equal('{ "string": "" }');
});

it('string: hex -> Michelson', () => {
let result = TezosLanguageUtil.hexToMichelson('01000000096d696368656c696e65');
expect(result.code).to.equal('"micheline"');

result = TezosLanguageUtil.hexToMichelson('0100000000');
expect(result.code).to.equal('""');
});

it('bytes', () => {
const result = TezosLanguageUtil.hexToMicheline('0a000000080123456789abcdef');
let result = TezosLanguageUtil.hexToMicheline('0a000000080123456789abcdef');
expect(result.code).to.equal('{ "bytes": "0123456789abcdef" }');

result = TezosLanguageUtil.hexToMichelson('0a000000080123456789abcdef');
expect(result.code).to.equal('0x0123456789abcdef');
});

it('Mixed literal value array', () => {
const result = TezosLanguageUtil.hexToMicheline('02000000210061010000000574657a6f730100000000010000000b63727970746f6e6f6d6963');
let result = TezosLanguageUtil.hexToMicheline('02000000210061010000000574657a6f730100000000010000000b63727970746f6e6f6d6963');
expect(result.code).to.equal('[ { "int": "-33" }, { "string": "tezos" }, { "string": "" }, { "string": "cryptonomic" } ]');

result = TezosLanguageUtil.hexToMichelson('02000000210061010000000574657a6f730100000000010000000b63727970746f6e6f6d6963');
expect(result.code).to.equal('[ -33 "tezos" "" "cryptonomic" ]');
});

it('Bare primitive', () => {
const result = TezosLanguageUtil.hexToMicheline('0343');
let result = TezosLanguageUtil.hexToMicheline('0343');
expect(result.code).to.equal('{ "prim": "PUSH" }');

result = TezosLanguageUtil.hexToMichelson('0343');
expect(result.code).to.equal('( PUSH )');
});

it('Single primitive with a single annotation', () => {
const result = TezosLanguageUtil.hexToMicheline('04430000000440636261');
let result = TezosLanguageUtil.hexToMicheline('04430000000440636261');
expect(result.code).to.equal('{ "prim": "PUSH", "annots": [ "@cba" ] }');

result = TezosLanguageUtil.hexToMichelson('04430000000440636261');
expect(result.code).to.equal('( PUSH @cba )');
});

it('Single primitive with a single argument', () => {
Expand Down Expand Up @@ -259,7 +325,7 @@ function indexOfKey(container: any, key: string): number {
for (let i = 0; i < container.script.length; i++) {
if (container.script[i]['prim'] === key) { return i; }
}

throw new Error(`${key} key was not found`);
}

Expand Down Expand Up @@ -299,5 +365,5 @@ describe('Hex to Micheline official contract tests', async () => {

expect(parsedMicheline).to.equal(expectedMicheline);
});
}
});
}
});
Loading

0 comments on commit 96b329c

Please sign in to comment.