Skip to content

Commit

Permalink
Merge pull request #352 from Cryptonomic/507-parser
Browse files Browse the repository at this point in the history
5.0.6-2
  • Loading branch information
anonymoussprocket committed Jan 21, 2021
2 parents a65f156 + fc7a3f9 commit f40b152
Show file tree
Hide file tree
Showing 14 changed files with 513 additions and 597 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
[![Build Status](https://travis-ci.org/Cryptonomic/ConseilJS.svg?branch=master)](https://travis-ci.org/Cryptonomic/ConseilJS)
[![Coverage Status](https://coveralls.io/repos/github/Cryptonomic/ConseilJS/badge.svg?branch=master)](https://coveralls.io/github/Cryptonomic/ConseilJS?branch=master)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Cryptonomic_ConseilJS&metric=alert_status)](https://sonarcloud.io/dashboard?id=Cryptonomic_ConseilJS)
[![dependencies](https://david-dm.org/Cryptonomic/ConseilJS/status.svg)](https://david-dm.org/Cryptonomic/ConseilJS)
[![conseiljs](https://snyk.io/advisor/npm-package/conseiljs/badge.svg)](https://snyk.io/advisor/npm-package/conseiljs)

A library for building decentralized applications in Typescript and Javascript, currently focused on the [Tezos](http://tezos.com/) platform.

ConseilJS connects to Tezos nodes for live chain data and operations and to [Conseil](https://github.com/Cryptonomic/Conseil) servers for high-performance analytics on blockchain data. Internally, Cryptonomic uses [Nautilus](https://github.com/Cryptonomic/Nautilus) for infrastructure deployments of these services. This is the library at the core of our products, [Periscope](https://periscope.arronax.io), [Harpoon](https://harpoon.arronax.io) and certainly [Galleon](https://cryptonomic.tech/galleon.html). There are [ReasonML bindings](https://github.com/Cryptonomic/ConseilJS-ReasonML-Bindings) as well.
ConseilJS connects to Tezos nodes for live chain data and operations and to [Conseil](https://github.com/Cryptonomic/Conseil) servers for high-performance analytics on blockchain data. Internally, Cryptonomic uses [Nautilus](https://github.com/Cryptonomic/Nautilus) for infrastructure deployments of these services. This is the library at the core of our products[Arronax](https://arronax.io), [Periscope](https://periscope.arronax.io), [Harpoon](https://harpoon.arronax.io) and certainly [Galleon](https://cryptonomic.tech/galleon.html). There are [ReasonML bindings](https://github.com/Cryptonomic/ConseilJS-ReasonML-Bindings) as well.

Cryptonomic offers an infrastructure service - [Nautilus Cloud](https://nautilus.cloud) which enables quick access to the Tezos platform along with products that make it easier build on it.

Expand Down
46 changes: 6 additions & 40 deletions grammar/tezos/Micheline.ne
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
@preprocessor typescript

@{%
const moo = require("moo");
const bigInt = require("big-integer");
import { TezosMessageUtils } from '../TezosMessageUtil';
import * as moo from 'moo';

// taken from https://gitlab.com/nomadic-labs/tezos, lib_protocol/michelson_v1_primitives.ml, prim_encoding enum
export const DefaultMichelsonKeywords = ['"parameter"', '"storage"', '"code"', '"False"', '"Elt"', '"Left"', '"None"', '"Pair"', '"Right"', '"Some"', '"True"', '"Unit"', '"PACK"', '"UNPACK"', '"BLAKE2B"', '"SHA256"', '"SHA512"', '"ABS"', '"ADD"', '"AMOUNT"', '"AND"', '"BALANCE"', '"CAR"', '"CDR"', '"CHECK_SIGNATURE"', '"COMPARE"', '"CONCAT"', '"CONS"', '"CREATE_ACCOUNT"', '"CREATE_CONTRACT"', '"IMPLICIT_ACCOUNT"', '"DIP"', '"DROP"', '"DUP"', '"EDIV"', '"EMPTY_MAP"', '"EMPTY_SET"', '"EQ"', '"EXEC"', '"FAILWITH"', '"GE"', '"GET"', '"GT"', '"HASH_KEY"', '"IF"', '"IF_CONS"', '"IF_LEFT"', '"IF_NONE"', '"INT"', '"LAMBDA"', '"LE"', '"LEFT"', '"LOOP"', '"LSL"', '"LSR"', '"LT"', '"MAP"', '"MEM"', '"MUL"', '"NEG"', '"NEQ"', '"NIL"', '"NONE"', '"NOT"', '"NOW"', '"OR"', '"PAIR"', '"PUSH"', '"RIGHT"', '"SIZE"', '"SOME"', '"SOURCE"', '"SENDER"', '"SELF"', '"STEPS_TO_QUOTA"', '"SUB"', '"SWAP"', '"TRANSFER_TOKENS"', '"SET_DELEGATE"', '"UNIT"', '"UPDATE"', '"XOR"', '"ITER"', '"LOOP_LEFT"', '"ADDRESS"', '"CONTRACT"', '"ISNAT"', '"CAST"', '"RENAME"', '"bool"', '"contract"', '"int"', '"key"', '"key_hash"', '"lambda"', '"list"', '"map"', '"big_map"', '"nat"', '"option"', '"or"', '"pair"', '"set"', '"signature"', '"string"', '"bytes"', '"mutez"', '"timestamp"', '"unit"', '"operation"', '"address"', '"SLICE"', '"DIG"', '"DUG"', '"EMPTY_BIG_MAP"', '"APPLY"', '"chain_id"', '"CHAIN_ID"'];
// https://gitlab.com/tezos/tezos/-/blob/master/src/proto_008_PtEdoTez/lib_protocol/michelson_v1_primitives.ml#L1088
export const DefaultMichelsonKeywords = ['"parameter"', '"storage"', '"code"', '"False"', '"Elt"', '"Left"', '"None"', '"Pair"', '"Right"', '"Some"', '"True"', '"Unit"', '"PACK"', '"UNPACK"', '"BLAKE2B"', '"SHA256"', '"SHA512"', '"ABS"', '"ADD"', '"AMOUNT"', '"AND"', '"BALANCE"', '"CAR"', '"CDR"', '"CHECK_SIGNATURE"', '"COMPARE"', '"CONCAT"', '"CONS"', '"CREATE_ACCOUNT"', '"CREATE_CONTRACT"', '"IMPLICIT_ACCOUNT"', '"DIP"', '"DROP"', '"DUP"', '"EDIV"', '"EMPTY_MAP"', '"EMPTY_SET"', '"EQ"', '"EXEC"', '"FAILWITH"', '"GE"', '"GET"', '"GT"', '"HASH_KEY"', '"IF"', '"IF_CONS"', '"IF_LEFT"', '"IF_NONE"', '"INT"', '"LAMBDA"', '"LE"', '"LEFT"', '"LOOP"', '"LSL"', '"LSR"', '"LT"', '"MAP"', '"MEM"', '"MUL"', '"NEG"', '"NEQ"', '"NIL"', '"NONE"', '"NOT"', '"NOW"', '"OR"', '"PAIR"', '"PUSH"', '"RIGHT"', '"SIZE"', '"SOME"', '"SOURCE"', '"SENDER"', '"SELF"', '"STEPS_TO_QUOTA"', '"SUB"', '"SWAP"', '"TRANSFER_TOKENS"', '"SET_DELEGATE"', '"UNIT"', '"UPDATE"', '"XOR"', '"ITER"', '"LOOP_LEFT"', '"ADDRESS"', '"CONTRACT"', '"ISNAT"', '"CAST"', '"RENAME"', '"bool"', '"contract"', '"int"', '"key"', '"key_hash"', '"lambda"', '"list"', '"map"', '"big_map"', '"nat"', '"option"', '"or"', '"pair"', '"set"', '"signature"', '"string"', '"bytes"', '"mutez"', '"timestamp"', '"unit"', '"operation"', '"address"', '"SLICE"', '"DIG"', '"DUG"', '"EMPTY_BIG_MAP"', '"APPLY"', '"chain_id"', '"CHAIN_ID"', '"LEVEL"', '"SELF_ADDRESS"', '"never"', '"NEVER"', '"UNPAIR"', '"VOTING_POWER"', '"TOTAL_VOTING_POWER"', '"KECCAK"', '"SHA3"', '"PAIRING_CHECK"', '"bls12_381_g1"', '"bls12_381_g2"', '"bls12_381_fr"', '"sapling_state"', '"sapling_transaction"', '"SAPLING_EMPTY_STATE"', '"SAPLING_VERIFY_UPDATE"', '"ticket"', '"TICKET"', '"READ_TICKET"', '"SPLIT_TICKET"', '"JOIN_TICKETS"', '"GET_AND_UPDATE"'];
let _languageKeywords = [...DefaultMichelsonKeywords];

export const setKeywordList = list => {
Expand Down Expand Up @@ -34,9 +34,7 @@ const lexer = moo.compile({

@lexer lexer

main -> staticObject {% id %}
| primBare {% id %} | primArg {% id %} | primAnn {% id %} | primArgAnn {% id %}
| anyArray {% id %}
main -> staticObject {% id %} | primAny {% id %} | anyArray {% id %}

staticInt -> %lbrace %_ "\"int\"" %_:* %colon %_ %quotedValue %_ %rbrace {% staticIntToHex %}
staticString -> %lbrace %_ "\"string\"" %_:* %colon %_ %quotedValue %_ %rbrace {% staticStringToHex %}
Expand All @@ -61,7 +59,7 @@ anyArray -> %lbracket %rbracket {% function(d) { return '0200000000'; } %}
const staticIntToHex = d => {
const prefix = '00';
const text = d[6].toString();
const value = writeSignedInt(parseInt(text.substring(1, text.length - 1))); // strip double quotes
const value = TezosMessageUtils.writeSignedInt(text.substring(1, text.length - 1)); // strip double quotes

return prefix + value;
};
Expand Down Expand Up @@ -196,36 +194,4 @@ const encodePrimitive = p => {
const encodeLength = l => {
return ('0000000' + l.toString(16)).slice(-8);
}

const writeSignedInt = value => {
if (value === 0) { return '00'; }

const n = bigInt(value).abs();
const l = n.bitLength().toJSNumber();
let arr: any = [];
let v = n;
for (let i = 0; i < l; i += 7) {
let byte = bigInt.zero;

if (i === 0) {
byte = v.and(0x3f); // first byte makes room for sign flag
v = v.shiftRight(6);
} else {
byte = v.and(0x7f); // NOT base128 encoded
v = v.shiftRight(7);
}

if (value < 0 && i === 0) { byte = byte.or(0x40); } // set sign flag

if (i + 7 < l) { byte = byte.or(0x80); } // set next byte flag
arr.push(byte.toJSNumber());
}

if (l % 7 === 0) {
arr[arr.length - 1] = arr[arr.length - 1] | 0x80;
arr.push(1);
}

return arr.map(v => ('0' + v.toString(16)).slice(-2)).join('');
}
%}
25 changes: 18 additions & 7 deletions grammar/tezos/Michelson.ne
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ typeData ->
data ->
%constantData {% keywordToJson %}
| %singleArgData _ data {% singleArgKeywordToJson %}
| %doubleArgData _ data _ %lbrace _ %rbrace {% doubleArgKeywordToJson %}
| %doubleArgData _ data _ data {% doubleArgKeywordToJson %}
| %doubleArgData _ data _ subInstruction {% doubleArgKeywordToJson %}
| subData {% id %}
| subElt {% id %}
| %string {% stringToJson %}
Expand Down Expand Up @@ -145,7 +147,7 @@ typeElt -> %elt _ typeData _ typeData {% doubleArgKeywordToJson %}

# Helper pattern for lists of michelson instructions
subInstruction ->
%lbrace _ %rbrace {% d => "" %}
%lbrace _ %rbrace {% d => "" %} # see TODO about double-wrapping
| %lbrace _ instruction _ %rbrace {% d => d[2] %}
| %lbrace _ (instruction _ %semicolon _):+ instruction _ %rbrace {% instructionSetToJsonNoSemi %} #If last instruction doesn't have semicolon
| %lbrace _ (instruction _ %semicolon _):+ %rbrace {% instructionSetToJsonSemi %} #If last instruction has semicolon
Expand Down Expand Up @@ -494,7 +496,7 @@ semicolons -> [;]:?
if (check_dip(word)) {
return expandDIP(word, d[2])
} else {
return `{ "prim": "${d[0]}", "args": [ [ ${d[2]} ] ] }`;
return `{ "prim": "${d[0]}", "args": [ [ ${d[2]} ] ] }`; /*TODO: [] double-wrapping here is Bad*/
}
}

Expand All @@ -517,17 +519,26 @@ semicolons -> [;]:?

/**
* Given a keyword with two arguments, convert it into JSON.
* Example: "Pair unit instruction" -> "{ prim: Pair, args: [{prim: unit}, {prim: instruction}] }"
* Example: "Pair Unit <instruction>" -> "{ prim: Pair, args: [{prim: Unit}, {prim: instruction}] }"
*/
const doubleArgKeywordToJson = d => `{ "prim": "${d[0]}", "args": [ ${d[2]}, ${d[4]} ] }`;
const doubleArgKeywordToJson = d => {
if (d.length === 7) {
/*
This handles the case where a blank {} for %subInstuction should be blank, but for %data they should be an empty array, see TODO about double-wrapping
*/
return `{ "prim": "${d[0]}", "args": [ ${d[2]}, [] ] }`;
} else {
return `{ "prim": "${d[0]}", "args": [ ${d[2]}, ${d[4]} ] }`;
}
};
const doubleArgParenKeywordToJson = d => `{ "prim": "${d[0]}", "args": [ ${d[4]}, ${d[8]} ] }`;

const doubleArgInstrKeywordToJson = d => {
const word = `${d[0].toString()}`
if (check_if(word)) {
return expandIF(word, d[2], d[4])
} else {
return `{ "prim": "${d[0]}", "args": [ [${d[2]}], [${d[4]}] ] }`;
return `{ "prim": "${d[0]}", "args": [ [${d[2]}], [${d[4]}] ] }`; /*TODO: [] double-wrapping here is Bad*/
}
}

Expand Down Expand Up @@ -585,7 +596,7 @@ semicolons -> [;]:?

const tripleArgTypeKeyWordToJson = d => {
const annot = d[1].map(x => `"${x[1]}"`)
return `{ "prim": "${d[0]}", "args": [ ${d[3]}, ${d[5]}, ${d[7]} ], "annots": [${annot}] }`;
return `{ "prim": "${d[0]}", "args": [ ${d[3]}, ${d[5]}, ${d[7]} ], "annots": [${annot}] }`;
}

const pushToJson = d => {
Expand Down Expand Up @@ -615,7 +626,7 @@ semicolons -> [;]:?

const dropnToJson = d => `{ "prim": "${d[0]}", "args": [ { "int": "${d[2]}" } ] }`;

const subContractToJson = d => `{ "prim":"CREATE_CONTRACT", "args": [ [ ${d[4]}, ${d[6]}, {"prim": "code" , "args":[ [ ${d[8]} ] ] } ] ] }`;
const subContractToJson = d => `{ "prim": "CREATE_CONTRACT", "args": [ [ ${d[4]}, ${d[6]}, { "prim": "code" , "args": [ [ ${d[8]} ] ] } ] ] }`;

const instructionListToJson = d => {
const instructionOne = [d[2]];
Expand Down

0 comments on commit f40b152

Please sign in to comment.