Giter VIP home page Giter VIP logo

aesophia_http's Introduction

aesophia_http

An HTTP interface to the Sophia compiler. It handles compiling contracts and generating ACI data for contract. The examples show

HTTP interface uses port 3080, settable with application variable aesophia_http.port.

Interface paths (see the config/swagger.yaml for details):

/aci - generate ACI format for contract in both JSON encoded and textual decoded forms. Tags 'code' and 'options'.

/compile - compile contract and return code in a JSON structure encoded to contract_bytearray.

/decode-call-result - Tags 'source', 'function', 'call-result', 'call-value'.

/decode-call-result/bytecode - Tags 'bytecode', 'function', 'call-result', 'call-value'.

/encode-calldata - Tags 'source', 'function' and 'arguments'.

/decode-calldata/bytecode - Input calldata and contract bytecode, get function name and VM type arguments.

/decode-calldata/source - Input calldata and (possibly partial) conctract source code, get function name and Sophia type arguments.

/validate-byte-code - Check that some bytecode was produced from the given source code.

/fate-assembler - Get the FATE assembler (as a string) from FATE bytecode.

/compiler-version - Extract the compiler version from bytecode.

/version - return the version of the Sophia compiler

/api-version - return the version of the API

/api - return the API in a JSON-term (intended to be consumed by tools)

Usage

We publish a docker image as aeternity/aesophia_http - so if docker is in place all that is needed to have an HTTP server serving the Sophia compiler API is:

docker run -p <PORT>:3080 aeternity/aesophia_http

Where PORT is the local port where you'd like the API to be served.

Building

The most convenient way to start the an HTTP server serving the Sophia compiler API is using docker. make docker will create a docker image aeternity/aesophia_http:local and it is started by docker run -p <PORT>:3080 aeternity/aesophia_http:local where PORT is the local port where you'd like the API to be served.

Examples

In all the following examples we use the contract SimpleStorage defined as:

Preparation

contract SimpleStorage =
  record state = { data : int }
  function init(value : int) : state = { data = value }
  function get() : int = state.data
  stateful function set(value : int) = put(state{data = value})

To make the example calls easier to read we have bound the shell variable $contract to the contract definition:

contract="contract SimpleStorage =
  record state = { data : int }
  entrypoint init(value : int) : state = { data = value }
  entrypoint get() : int = state.data
  stateful entrypoint set(value : int) = put(state{data = value})"

Generating ACI

To get the ACI of the contract we use the /aci interface:

curl -H "Content-Type: application/json" -d "{\"code\":\"$contract\",\"options\":{}}" -X POST http://localhost:3080/aci

Returns:

{"encoded_aci":{"contract":{"functions":[{"arguments":[{"name":"value","type":"int"}],"name":"init","returns":"SimpleStorage.state","stateful":false},{"arguments":[],"name":"get","returns":"int","stateful":false},{"arguments":[{"name":"value","type":"int"}],"name":"set","returns":{"tuple":[]},"stateful":true}],"name":"SimpleStorage","state":{"record":[{"name":"data","type":"int"}]},"type_defs":[]}},"interface":"contract SimpleStorage =\n  record state = {data : int}\n  function init : (int) => SimpleStorage.state\n  function get : () => int\n  function set : (int) => ()\n"}

Important: If your contract code contains quotes, you need to escape every quote with a backslash:

    switch(expression)
      true => \"true\"    // also \"in comments
      false => \"false\"

This returns a structure with two fields: encoded_aci is a description of the contract containing the types and functions; interface is a definition of the contract suitable to be included in other contracts.

Compiling contract to bytecode

We can now compile the contract and get the bytecode:

curl -H "Content-Type: application/json" -d "{\"code\":\"$contract\", \"options\":{}}" -X POST http://localhost:3080/compile

Returns:

{"bytecode":"cb_+IBGA6AJQqlX6tyRsl4BPLit17O1UczvqlaptU2Kp4bI3PatZcC4U7D+L4Zb2QA3AAcBAoL+RNZEHwA3AQc3ABoGggABAz/+6MRetgA3AQc3ABoGggABAz+eLwMRL4Zb2Q1nZXQRRNZEHxFpbml0EejEXrYNc2V0gi8AhTYuMS4wAEhXFsk="}

Validating bytecode

You can check that some particular bytecode, for instance obtained from the chain, was compiled from given source code, using the validate-byte-code endpoint:

curl -H "Content-Type: application/json" -d '{"source":"contract Id = entrypoint id(x : int) = x","options":{},"bytecode":"cb_+GNGA6CBDP58NrY5L7PzZrlGZ0C8aqcXIYwqv2WMpyTg8IuBTsC3nv5E1kQfADcANwAaDoI/AQM//tjzDDgANwEHBwEBAJQvAhFE1kQfEWluaXQR2PMMOAlpZIIvAIU0LjAuMABqFanJ"}' -X POST http://localhost:3080/validate-byte-code

Returns:

{}

Validating against source code with a different implementation of id returns:

[{"message":"Byte code does not match source code.\n- The implementation of the function id is different.\n","pos":{"col":0,"line":0},"type":"data_error"}]

Getting fate assembler

You can get the FATE assembler code for some particular bytecode:

curl -H "Content-Type: application/json" -d '{"bytecode":"cb_+GNGA6CBDP58NrY5L7PzZrlGZ0C8aqcXIYwqv2WMpyTg8IuBTsC3nv5E1kQfADcANwAaDoI/AQM//tjzDDgANwEHBwEBAJQvAhFE1kQfEWluaXQR2PMMOAlpZIIvAIU0LjAuMABqFanJ"}' -X POST http://localhost:3080/fate-assembler

Returns:

{"fate-assembler":"FUNCTION init( ) : {tuple,[]}\n  ;; BB : 0\n          STORE store1 ()\n          RETURNR ()\nFUNCTION id( integer) : integer\n  ;; BB : 0\n          RETURNR arg0\n\n"}

Encoding calldata

To encode the call data necessary to call the function set with the argument 42:

curl -H "Content-Type: application/json" -d "{\"function\":\"set\",\"arguments\":[\"42\"],\"source\":\"$contract\", \"options\":{}}" -X POST http://localhost:3080/encode-calldata

Returns:

{"calldata":"cb_KxHoxF62G1Sy3bqn"}

Decoding call data

Call data from transactions can be decoded in two ways, either using the contract bytecode (this is a long one) which returns the VM types and values, or the Sophia contract source.

With Contract Bytecode

Example:

curl -H "Content-Type: application/json" -d "{\"calldata\":\"cb_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA6hZQte0c6B/XQTuHZwWpc6rFreRzqkolhGkTD+eW6BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoA4Uun\",\"bytecode\":\"cb_+QYYRgKgCTTJlUBVAUHWm6tXQKIwDZi3yvR+jeNv8JCPQzLT6xT5BKX5AUmgOoWULXtHOgf10E7h2cFqXOqxa3kc6pKJYRpEw/nlugeDc2V0uMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////////////////////////////////////jJoEnsSQdsAgNxJqQzA+rc5DsuLDKUV7ETxQp+ItyJgJS3g2dldLhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////////////////////////////////////////uEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+QKLoOIjHWzfyTkW3kyzqYV79lz0D8JW9KFJiz9+fJgMGZNEhGluaXS4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg//////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALkBoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA//////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYD//////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuQFEYgAAj2IAAMKRgICAUX9J7EkHbAIDcSakMwPq3OQ7LiwylFexE8UKfiLciYCUtxRiAAE5V1CAgFF/4iMdbN/JORbeTLOphXv2XPQPwlb0oUmLP358mAwZk0QUYgAA0VdQgFF/OoWULXtHOgf10E7h2cFqXOqxa3kc6pKJYRpEw/nlugcUYgABG1dQYAEZUQBbYAAZWWAgAZCBUmAgkANgAFmQgVKBUllgIAGQgVJgIJADYAOBUpBZYABRWVJgAFJgAPNbYACAUmAA81tgAFFRkFZbYCABUVGQUIOSUICRUFCAWZCBUllgIAGQgVJgIJADYAAZWWAgAZCBUmAgkANgAFmQgVKBUllgIAGQgVJgIJADYAOBUoFSkFCQVltgIAFRUVlQgJFQUGAAUYFZkIFSkFBgAFJZkFCQVltQUFlQUGIAAMpWhTIuMC4w4czHnw==\"}" -X POST http://localhost:3080/decode-calldata/bytecode

Returns: {"arguments":[{"type":"word","value":42}],"function":"set"}

With Sophia Source

And secondly, using the Sophia contract source which returns the Sophia types and values:

curl -H "Content-Type: application/json" -d "{\"calldata\":\"cb_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA6hZQte0c6B/XQTuHZwWpc6rFreRzqkolhGkTD+eW6BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoA4Uun\",\"function\":\"set\",\"source\":\"$contract\"}" -X POST http://localhost:3080/decode-calldata/source

Returns:

{"arguments":[{"type":"int","value":"42"}],"function":"set"}

Decoding return value

You can also decode the return value of a contract call:

curl -H "Content-Type: application/json" -d "{\"source\":\"$contract\",\"function\":\"get\", \"call-result\":\"ok\", \"call-value\":\"cb_VNLOFXc=\"}" -X POST http://localhost:3080/decode-call-result

Returns:

42

The contract call result can also be decoded using the bytecode as a starting point:

curl -H "Content-Type: application/json" -d "{\"bytecode\":\"cb_+JFGA6DcSHcAbyhLqfbIDJRe1S7ZJLCZQJBUuvMmCLK5OirpHsC4YLg8/i+GW9kANwAHKCwAggD+RNZEHwA3AQc3AAwBACcMAhoCggEDP/7oxF62ADcBBzcADAEAJwwCGgKCAQM/ni8DES+GW9kNZ2V0EUTWRB8RaW5pdBHoxF62DXNldIIvAIk0LjAuMC1yYzQAPwYsew==\",\"function\":\"get\", \"call-result\":\"ok\", \"call-value\":\"cb_VNLOFXc=\"}" -X POST http://localhost:3080/decode-call-result/bytecode

Returns:

{"function":"get","result":{"type":"int","value":42}}

Getting the compiler version used

You can extract the compiler version that was used to compile some particular bytecode:

curl -H "Content-Type: application/json" -d '{"bytecode":"cb_+GNGA6CBDP58NrY5L7PzZrlGZ0C8aqcXIYwqv2WMpyTg8IuBTsC3nv5E1kQfADcANwAaDoI/AQM//tjzDDgANwEHBwEBAJQvAhFE1kQfEWluaXQR2PMMOAlpZIIvAIU0LjAuMABqFanJ"}' -X POST http://localhost:3080/compiler-version

Returns:

{"version":"4.0.0"}

Complete API overview

To get information about the current version of the Sophia compiler, API version and the whole actual API (paste into any swagger file generator):

curl http://localhost:3080/version

{"version":"7.4.0"}
curl http://localhost:3080/api-version

{"api-version":"7.6.0"}
curl http://localhost:3080/api

{"basePath":"/","definitions":{  ... },"info":{ ... },"paths":{ ... },"schemes":["http"],"swagger":"2.0"}

aesophia_http's People

Contributors

davidyuk avatar dincho avatar ghallak avatar hanssv avatar mradkov avatar nikita-fuchs avatar radrow avatar rvirding avatar thepiwo avatar tolbrino avatar ulfnorell avatar valerifilipov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aesophia_http's Issues

Endpoint to parse contract imports and pragmas

I need to compile a contract created by user, it may contain some imports of files that I should pass to compiler in file_system option. I have access to file system, but I don't know what files imported. For privacy reasons I may not want to pass all local files in file_system option, also I don't want to implement an import parser as an error-prone approach. So I need an endpoint that accepts a single sophia file and return an array of its imports.

Additionally, would be nice to have a way to distinguish imports defined by language (a standard library?) and that ones that should be accessible in a local filesystem.

Pragmas parsing would help to identify a compatible compiler in case multiple available.

For example, for code:

@compiler >= 5

include "Option.aes"
include "String.aes"

contract FungibleTokenFull =
...

It should return something like this:

{
  "includes": ["Option.aes", "String.aes"],
  "pragmas": {
    "compiler": [["gte", 5]]
  }
}

Missing CORS headers on HTTP error

curl -I https://compiler.aepps.com/404 -H "Origin: http:/anyorigin.com"
HTTP/2 404 
date: Mon, 07 Nov 2022 08:42:30 GMT
server: Cowboy
content-length: 0

400 response for higher order functions

Hey, when doing

entrypoint a_function(test : (int) => int ) : (int) => int  =
        test 

I'm getting 400 from https://latest.compiler.aepps.com/aci instead of a proper response / error message, whereas the compiler itself properly complains.

No response on compiler error

currently a crashing compiler leads to a stalling/breaking connection with no response. It would be great to receive a proper 50x response with a corresponding error message, ideally maybe even containing the error for faster debugging.

EDIT: It seems like it's just chrome that's not showing the 500, curl is doing fine. Proper return data would still be very handy, though.

the /api path for the swagger specs is different from the node reply

Hello,
the node reply for the swagger specs from the compiler returns a root object

{
   "api": {
      "swagger": "2.0",
      ...
   }
} 

while for the node /api the root object is directly

{
    "swagger": "2.0",
    ...
} 

is it possible to change the compiler http behaviour to be consistent with the one used in the node?

Out of file descriptors

2022-07-18 12:41:11=WARNING REPORT==== 18-Jul-2022::09:41:11.736963 ===
2022-07-18 12:41:11Ranch acceptor reducing accept rate: out of file descriptors

What's the file descriptors requirements for HTTP compiler (per request?)? In general I wonder what it would not work with the default (1024).

pp_asm equivalent

aesophia_cli has the --pp_asm flag to pretty-print the byte code. There should be a similar entrypoint here.

Allow CORS

Hello,
please add CORS header to all response from compiler or this better to be done on server side?

Inline options object in requests

For example, /compile accepts a Contract that defined as:

    "Contract": {
      "properties": {
        "code": {
          "type": "string"
        },
        "options": {
          "$ref": "#/definitions/CompileOpts"
        }
      },
      "required": [
        "code",
        "options"
      ],
      "type": "object"
    },
    "CompileOpts": {
      "properties": {
        "backend": {
          "description": "Compiler backend; fate | aevm",
          "enum": [
            "fate",
            "aevm"
          ],
          "type": "string"
        },
        "file_system": {
          "description": "An explicit file system, mapping file names to file content",
          "properties": {
            
          },
          "type": "object"
        },
        "src_file": {
          "description": "Name of contract source file - only used in error messages",
          "type": "string"
        }
      },
      "type": "object"
    },

can we inline options to have Contract looking like below?

    "Contract": {
      "properties": {
        "code": {
          "type": "string"
        },
        "backend": {
          "description": "Compiler backend; fate | aevm",
          "enum": [
            "fate",
            "aevm"
          ],
          "type": "string"
        },
        "file_system": {
          "description": "An explicit file system, mapping file names to file content",
          "properties": {},
          "type": "object"
        },
        "src_file": {
          "description": "Name of contract source file - only used in error messages",
          "type": "string"
        }
      },
      "required": [
        "code"
      ],
      "type": "object"
    },

/aci with invalid parameters returns JSON with undocumented fields

$ curl https://compiler.aepps.com/aci
{"info":"","parameter":"","reason":"validation_error"}
$ curl -d "p=1" -H "Content-Type: application/json" -X POST https://compiler.aepps.com/aci
{"info":{"data":"p=1","error":"invalid_body"},"parameter":"","reason":"validation_error"}

So, in one case info is a string in one case and an object in another.

The swagger file says that aci should return #/definitions/CompilerErrors in case of error, but CompilerErrors should be an array ๐Ÿค” The most similar thing to the response is #/definitions/Error, but it doesn't define info and parameter fields.

Exception error: {encode_expr_todo,'-'}

2020-03-18 13:29:05=CRASH REPORT==== 18-Mar-2020::11:29:05 ===
2020-03-18 13:29:05 crasher:
2020-03-18 13:29:05 initial call: cowboy_stream_h:request_process/3
2020-03-18 13:29:05 pid: <0.9457.0>
2020-03-18 13:29:05 registered_name: []
2020-03-18 13:29:05 exception error: {encode_expr_todo,'-'}
2020-03-18 13:29:05 in function aeso_aci:encode_expr/1 (/app/_build/default/lib/aesophia/src/aeso_aci.erl, line 204)
2020-03-18 13:29:05 in call from aeso_aci:encode_expr/1 (/app/_build/default/lib/aesophia/src/aeso_aci.erl, line 198)
2020-03-18 13:29:05 in call from aesophia_http_handler:decode_call_result/5 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 505)
2020-03-18 13:29:05 in call from aesophia_http_handler:handle_request_json/2 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 39)
2020-03-18 13:29:05 in call from cowboy_rest:call/3 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 1182)
2020-03-18 13:29:05=CRASH REPORT==== 18-Mar-2020::11:29:05 ===
2020-03-18 13:29:05 crasher:
2020-03-18 13:29:05 initial call: cowboy_stream_h:request_process/3
2020-03-18 13:29:05 pid: <0.9457.0>
2020-03-18 13:29:05 registered_name: []
2020-03-18 13:29:05 exception error: {encode_expr_todo,'-'}
2020-03-18 13:29:05 in function aeso_aci:encode_expr/1 (/app/_build/default/lib/aesophia/src/aeso_aci.erl, line 204)
2020-03-18 13:29:05 in call from aeso_aci:encode_expr/1 (/app/_build/default/lib/aesophia/src/aeso_aci.erl, line 198)
2020-03-18 13:29:05 in call from aesophia_http_handler:decode_call_result/5 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 505)
2020-03-18 13:29:05 in call from aesophia_http_handler:handle_request_json/2 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 39)
2020-03-18 13:29:05 in call from cowboy_rest:call/3 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 1182)
2020-03-18 13:29:05 in call from cowboy_rest:process_content_type/3 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 986)
2020-03-18 13:29:05 in call from cowboy_rest:upgrade/4 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 260)
2020-03-18 13:29:05 in call from cowboy_stream_h:execute/3 (/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl, line 249)
2020-03-18 13:29:05 ancestors: [<0.9454.0>,<0.566.0>,<0.565.0>,ranch_sup,<0.550.0>]
2020-03-18 13:29:05 message_queue_len: 0
2020-03-18 13:29:05 messages: []
2020-03-18 13:29:05 links: [<0.9454.0>]
2020-03-18 13:29:05 dictionary: [{'$current_file',no_file},{aeso_ast_infer_types,#{}}]
2020-03-18 13:29:05 trap_exit: false
2020-03-18 13:29:05 status: running
2020-03-18 13:29:05 heap_size: 46422
2020-03-18 13:29:05=CRASH REPORT==== 18-Mar-2020::11:29:05 ===
2020-03-18 13:29:05 crasher:
2020-03-18 13:29:05 initial call: cowboy_stream_h:request_process/3
2020-03-18 13:29:05 pid: <0.9457.0>
2020-03-18 13:29:05 registered_name: []
2020-03-18 13:29:05 exception error: {encode_expr_todo,'-'}
2020-03-18 13:29:05 in function aeso_aci:encode_expr/1 (/app/_build/default/lib/aesophia/src/aeso_aci.erl, line 204)
2020-03-18 13:29:05 in call from aeso_aci:encode_expr/1 (/app/_build/default/lib/aesophia/src/aeso_aci.erl, line 198)
2020-03-18 13:29:05 in call from aesophia_http_handler:decode_call_result/5 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 505)
2020-03-18 13:29:05 in call from aesophia_http_handler:handle_request_json/2 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 39)
2020-03-18 13:29:05 in call from cowboy_rest:call/3 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 1182)
2020-03-18 13:29:05 in call from cowboy_rest:process_content_type/3 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 986)
2020-03-18 13:29:05 in call from cowboy_rest:upgrade/4 (/app/_build/default/lib/cowboy/src/cowboy_rest.erl, line 260)
2020-03-18 13:29:05 in call from cowboy_stream_h:execute/3 (/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl, line 249)
2020-03-18 13:29:05 ancestors: [<0.9454.0>,<0.566.0>,<0.565.0>,ranch_sup,<0.550.0>]
2020-03-18 13:29:05 message_queue_len: 0
2020-03-18 13:29:05 messages: []
2020-03-18 13:29:05 links: [<0.9454.0>]
2020-03-18 13:29:05 dictionary: [{'$current_file',no_file},{aeso_ast_infer_types,#{}}]
2020-03-18 13:29:05 trap_exit: false
2020-03-18 13:29:05 status: running
2020-03-18 13:29:05 heap_size: 46422
2020-03-18 13:29:05 stack_size: 27
2020-03-18 13:29:05 reductions: 233711
2020-03-18 13:29:05 neighbours:
2020-03-18 13:29:05=ERROR REPORT==== 18-Mar-2020::11:29:05 ===

Remove trailing newline at the end of error messages

In case of error, /compile endpoint responses:

[{
  "message":"Unbound variable baz at line 3, column 32\\n",
  "pos":{ "col":32, "line":3 },
  "type":"type_error"
}, {
  "message":"Unbound variable baz at line 4, column 33\\n",
  "pos":{ "col":33, "line":4 },
  "type":"type_error"
}]

Trailing newline chars look extra, brings to broken output while doing something obvious like response.body.map(({ message })).join('; ')

Decode data: `sophia-type` format

Can we change sophia-type prop of /decode-data API endpoint
to take JSON return type from ACI object({ list: ['int'] }) instead of string ('list(int)')???

"code" argument of /compile is confusing

Without context, it can mean both source code and bytecode. Better to rename it to "source" or "sourceCode".

Renaming to "source" would be consistent with:

  • /decode-calldata/source
  • /encode-calldata
  • /decode-call-result
  • /validate-byte-code

Use bytecode instead of byteCode in all cases

$ curl https://compiler.aepps.com/api | jq . | grep bytecode -i
    "ByteCode": { <-- as two words
        "bytecode": {} <-- as a single word
        "bytecode": {
        "bytecode"
    "ByteCodeInput": {
        "bytecode": {}
        "bytecode": {
        "bytecode"
    "BytecodeCallResultInput": { <-- as a single word
        "bytecode": {},
        "bytecode": {
        "bytecode",
    "DecodeCalldataBytecode": { <-- as a single word
        "bytecode": null,
        "bytecode": {
        "bytecode",
    "ValidateByteCodeInput": { <-- as two words
        "bytecode": {},
        "bytecode": {
        "bytecode",
              "$ref": "#/definitions/ByteCode"
        "description": "Extract compiler version from bytecode",
              "$ref": "#/definitions/ByteCodeInput"
    "/decode-call-result/bytecode": {
        "description": "Decode the result of contract call from Bytecode",
        "operationId": "DecodeCallResultBytecode",
              "$ref": "#/definitions/BytecodeCallResultInput"
    "/decode-calldata/bytecode": {
        "operationId": "DecodeCalldataBytecode",
              "$ref": "#/definitions/DecodeCalldataBytecode"
        "description": "Get FATE assembler code from bytecode",
              "$ref": "#/definitions/ByteCodeInput"
        "operationId": "ValidateByteCode",
              "$ref": "#/definitions/ValidateByteCodeInput"

In comparison with "source code", seems correct to write "bytecode" as a single word, https://en.wikipedia.org/wiki/Bytecode ๐Ÿคทโ€โ™€๏ธ

Handle contract events in ACI generator

Events are currently not separately taken care of in the ACI, for a contract like

contract Events =
  type alias_int = int
  type alias_address = address
  type alias_string = string

  datatype event =
      Event1(indexed int, indexed int, string)
    | Event2(string, indexed address)

the events are put in the type definition:

{
    "encoded_aci": {
        "contract": {
            "name": "Events",
            "type_defs": [
                {...},
                {...},
                {...},
                {
                    "name": "event",
                    "vars": [],
                    "typedef": "Event1(int, int, string) | Event2(string, address)"
                }
            ],
            "functions": []
        }
    },
    "interface": "contract Events =\n"
}

Can't build a docker image

$ make docker
Using default tag: latest
latest: Pulling from aeternity/builder
68e7bb398b9f: Pull complete 
2118477f797b: Pull complete 
a788903329d3: Pull complete 
57b7b5d23a9e: Pull complete 
5852e99109fb: Pull complete 
bcc0fbad5542: Pull complete 
Digest: sha256:db4fb3766d05099d8ecf201efadde7bb4aec45da719f31a13d1e49600f7722c0
Status: Downloaded newer image for aeternity/builder:latest
docker.io/aeternity/builder:latest
[+] Building 68.5s (10/16)                                                                                                                    
 => [internal] load build definition from Dockerfile                                                                                     0.1s
 => => transferring dockerfile: 1.05kB                                                                                                   0.1s
 => [internal] load .dockerignore                                                                                                        0.1s
 => => transferring context: 221B                                                                                                        0.0s
 => [internal] load metadata for docker.io/library/ubuntu:18.04                                                                          2.3s
 => [internal] load metadata for docker.io/aeternity/builder:latest                                                                      0.0s
 => [auth] library/ubuntu:pull token for registry-1.docker.io                                                                            0.0s
 => [internal] load build context                                                                                                       13.5s
 => => transferring context: 117.94kB                                                                                                   11.9s
 => [stage-1 1/7] FROM docker.io/library/ubuntu:18.04@sha256:d8ac28b7bec51664c6b71a9dd1d8f788127ff310b8af30820560973bcfc605a0            8.0s
 => => resolve docker.io/library/ubuntu:18.04@sha256:d8ac28b7bec51664c6b71a9dd1d8f788127ff310b8af30820560973bcfc605a0                    0.1s
 => => sha256:b67d6ac264e4841abb64519b1e85d19873214864b6102939196c8c00ead895ee 1.46kB / 1.46kB                                           0.0s
 => => sha256:11323ed2c65349758e68a03a8e43825ec263dc9790daea93cf83b18ad0703109 26.71MB / 26.71MB                                         2.7s
 => => sha256:d8ac28b7bec51664c6b71a9dd1d8f788127ff310b8af30820560973bcfc605a0 1.41kB / 1.41kB                                           0.0s
 => => sha256:6b26a5e25e3b4d0337997ab73f28c67427d0aa9ff65c0efc1996c576b238502c 529B / 529B                                               0.0s
 => => extracting sha256:11323ed2c65349758e68a03a8e43825ec263dc9790daea93cf83b18ad0703109                                                4.4s
 => [builder 1/3] FROM docker.io/aeternity/builder                                                                                       0.4s
 => [builder 2/3] ADD . /app                                                                                                             0.3s
 => ERROR [builder 3/3] RUN cd /app && make prod-build                                                                                  52.3s
------                                                                                                                                        
 > [builder 3/3] RUN cd /app && make prod-build:                                                                                              
#10 0.488 curl -fsS --create-dirs -o swagger/swagger-codegen-cli-2.3.1.jar https://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.3.1/swagger-codegen-cli-2.3.1.jar                                                                                                                
#10 2.954 [main] INFO io.swagger.parser.Swagger20Parser - reading from config/swagger.yaml                                                    
#10 3.886 [main] INFO io.swagger.codegen.ignore.CodegenIgnoreProcessor - No .swagger-codegen-ignore file found.                               
#10 4.687 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_default_handler.erl
#10 4.763 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/rebar.config
#10 4.768 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger.app.src
#10 4.777 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_router.erl
#10 4.806 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_api.erl
#10 4.818 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_server.erl
#10 4.825 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_utils.erl
#10 4.834 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_auth.erl
#10 4.836 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/priv/swagger.json
#10 4.849 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_default_logic_handler.erl
#10 4.853 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/src/swagger_logic_handler.erl
#10 4.856 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/README.md
#10 4.865 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/.swagger-codegen-ignore
#10 4.867 [main] INFO io.swagger.codegen.AbstractGenerator - writing file /tmp/tmp.oBUQnz5iLT/.swagger-codegen/VERSION
#10 4.903 Swagger tempdir: /tmp/tmp.oBUQnz5iLT
#10 4.909 make[1]: Entering directory '/app'
#10 4.914 make[1]: Leaving directory '/app'
#10 4.917 rebar3 swagger_endpoints
#10 7.354 ===> Fetching swagger_endpoints (from {git,"https://github.com/aeternity/swagger_endpoints",
#10 7.354                              {ref,"ac38525ba55e8eefc00fb4fc0ec697ec3b2c26cf"}})
#10 11.20 ===> Fetching jsx v2.9.0
#10 11.55 ===> Fetching yamerl v0.6.0
#10 11.97 ===> Analyzing applications...
#10 14.09 ===> Compiling yamerl
#10 20.18 ===> Compiling jsx
#10 21.51 ===> Compiling swagger_endpoints
#10 21.92 ===> Generating code from "config/swagger.yaml" writing to "apps/aesophia_http/src/endpoints.erl"
#10 24.99 ===> Verifying dependencies...
#10 26.81 ===> Fetching aeserialization (from {git,"https://github.com/aeternity/aeserialization.git",
#10 26.81                            {ref,"58e34ae7b5abfcc54f505ea8d57183d04f67120e"}})
#10 28.53 ===> Fetching aesophia (from {git,"https://github.com/aeternity/aesophia.git",
#10 28.53                     {ref,"5ad5270e381f6e810d7b8b5cdc168d283e7a90bb"}})
#10 30.24 ===> Fetching cowboy (from {git,"https://github.com/ninenines/cowboy.git",
#10 30.24                   {ref,"8d49ae3dda5b4274e55d2f4e5a5b4da0515b5a10"}})
#10 33.42 ===> Fetching eblake2 v1.0.0
#10 33.77 ===> Fetching rebar3_hex v7.0.1
#10 34.03 ===> Fetching hex_core v0.8.4
#10 34.19 ===> Fetching verl v1.1.1
#10 34.29 ===> Analyzing applications...
#10 35.30 ===> Compiling verl
#10 37.57 ===> Compiling hex_core
#10 41.19 ===> Compiling rebar3_hex
#10 42.47 ===> Fetching jesse (from {git,"https://github.com/for-GET/jesse.git",
#10 42.47                  {ref,"9f9d050627093d6a43e02a102d78122f0c4989c8"}})
#10 44.03 ===> Fetching jsx (from {git,"https://github.com/talentdeficit/jsx.git",
#10 44.03                {ref,"3074d4865b3385a050badf7828ad31490d860df5"}})
#10 45.28 ===> Fetching aebytecode (from {git,"https://github.com/aeternity/aebytecode.git",
#10 45.28                       {ref,"05dfd7ffc7fb1e07ecc0b1e516da571f56d7dc8f"}})
#10 46.63 ===> Fetching base58 (from {git,"https://github.com/aeternity/erl-base58.git",
#10 46.63                   {ref,"60a335668a60328a29f9731b67c4a0e9e3d50ab6"}})
#10 47.60 ===> Fetching cowlib (from {git,"https://github.com/ninenines/cowlib",
#10 47.60                   {ref,"3ef5b48a028bb66f82b452c98ae515903096641c"}})
#10 48.80 ===> Fetching enacl (from {git,"https://github.com/aeternity/enacl.git",
#10 48.80                  {ref,"26180f42c0b3a450905d2efd8bc7fd5fd9cece75"}})
#10 49.81 ===> Fetching pc v1.14.0
#10 49.91 ===> Analyzing applications...
#10 50.01 ===> Compiling pc
#10 50.57 ===> Fetching getopt v1.0.1
#10 50.66 ===> Fetching ranch (from {git,"https://github.com/ninenines/ranch",
#10 50.66                  {ref,"55c2a9d623454f372a15e99721a37093d8773b48"}})
#10 51.82 ===> Fetching rfc3339 (from {git,"git://github.com/andreineculau/rfc3339.git",
#10 51.82                    {ref,"dcc77d66430490620677de8140a3415dfbd3fa61"}})
#10 52.12 ===> Failed to fetch and copy dep: {git,
#10 52.12                                   "git://github.com/andreineculau/rfc3339.git",
#10 52.12                                   {ref,
#10 52.12                                       "dcc77d66430490620677de8140a3415dfbd3fa61"}}
#10 52.14 Makefile:62: recipe for target 'prod-build' failed
#10 52.14 make: *** [prod-build] Error 1
------
executor failed running [/bin/sh -c cd /app && make prod-build]: exit code: 2
make: *** [Makefile:59: docker] Error 1

at 3f20f69
seems that replacing git:// with https:// in rebar.lock helps

Duplicate keys in swagger.yaml

responses:
'200':
description: 'ACI for contract'
schema:
$ref: '#/definitions/ACI'
'400':
description: Invalid input
schema:
$ref: '#/definitions/Error'
'400':
description: Compiler errors
schema:
$ref: '#/definitions/CompilerErrors'

Both responses are defined for 400 code, and as I get, only the last one appears in the resulting json file.

https://compiler.aeternity.io/api

        "responses": {
          "200": {
            "description": "ACI for contract",
            "schema": {
              "$ref": "#/definitions/ACI"
            }
          },
          "400": {
            "description": "Compiler errors",
            "schema": {
              "$ref": "#/definitions/CompilerErrors"
            }
          }
        }

swagger.yaml contains multiple duplications like this, them prevents using the swagger file in AutoRest

Dependency on dead maven URL

When the makefile is ran, swagger codegen cli is being fetched from a dead maven URL:

=> ERROR [builder 3/3] RUN cd /app && make prod-build                                                                                                                                                                                   0.4s
------
 > [builder 3/3] RUN cd /app && make prod-build:
#0 0.254 curl -fsS --create-dirs -o swagger/swagger-codegen-cli-2.3.1.jar http://central.maven.org/maven2/io/swagger/swagger-codegen-cli/2.3.1/swagger-codegen-cli-2.3.1.jar
#0 0.292 curl: (6) Could not resolve host: central.maven.org

from googling it 5 minutes, it seems like central.maven.org was sunset or so.

Don't duplicate line and col in error messages

In case of error, /compile endpoint responses:

[{
  "message":"Unbound variable baz at line 3, column 32\\n",
  "pos":{ "col":32, "line":3 },
  "type":"type_error"
}, {
  "message":"Unbound variable baz at line 4, column 33\\n",
  "pos":{ "col":33, "line":4 },
  "type":"type_error"
}]

The numbers of line and column are duplicated in the message and in separate fields. Looks reasonable to remove them from the message for better customization of how to present them to the user. For example, I would like to show just "type_error:33:4: Unbound variable baz".

Encoding call data with address type args

Hey, i have a strange behavior when try to encode call-data for this contract:

contract Identity =
  type state = ()
  function main(x : address) : address = x

This is the encode-call body: { source: 'SOURCE', function: 'main', arguments:['0x485edabd5526cea1a4bfb164b3de1c6ea67241723391efa1c9a287a1f34c1145' ] }
And the response is:

Type errors
Cannot unify address        
and int
when checking the application at line 5, column 23 of  main : (address) => address to arguments 
0x485EDABD5526CEA1A4BFB164B3DE1C6EA67241723391EFA1C9A287A1F34C1145 :  int

Crashing aesophia_http_api_validate:json_spec

2022-07-18 12:41:12=CRASH REPORT==== 18-Jul-2022::09:41:11.758997 ===
2022-07-18 12:41:12 crasher:
2022-07-18 12:41:12 initial call: cowboy_stream_h:request_process/3
2022-07-18 12:41:12 pid: <0.1482.4>
2022-07-18 12:41:12 registered_name: []
2022-07-18 12:41:12 exception error: no match of right hand side value {error,emfile}
2022-07-18 12:41:12 in function aesophia_http_api_validate:json_spec/0 (/app/apps/aesophia_http/src/aesophia_http_api_validate.erl, line 12)
2022-07-18 12:41:12 in call from aesophia_http_handler:init/2 (/app/apps/aesophia_http/src/aesophia_http_handler.erl, line 15)
2022-07-18 12:41:12 in call from cowboy_handler:execute/2 (/app/_build/default/lib/cowboy/src/cowboy_handler.erl, line 37)
2022-07-18 12:41:12 in call from cowboy_stream_h:execute/3 (/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl, line 249)
2022-07-18 12:41:12 in call from cowboy_stream_h:request_process/3 (/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl, line 227)
2022-07-18 12:41:12 ancestors: [<0.1472.4>,<0.610.0>,<0.609.0>,ranch_sup,<0.594.0>]
2022-07-18 12:41:12=ERROR REPORT==== 18-Jul-2022::09:41:11.821732 ===
Ranch listener http, connection process <0.1469.4>, stream 1 had its request process <0.1479.4> exit with reason {badmatch,{error,emfile}} and stacktrace [{aesophia_http_api_validate,json_spec,0,[{file,"/app/apps/aesophia_http/src/aesophia_http_api_validate.erl"},{line,12}]},{aesophia_http_handler,init,2,[{file,"/app/apps/aesophia_http/src/aesophia_http_handler.erl"},{line,15}]},{cowboy_handler,execute,2,[{file,"/app/_build/default/lib/cowboy/src/cowboy_handler.erl"},{line,37}]},{cowboy_stream_h,execute,3,[{file,"/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl"},{line,249}]},{cowboy_stream_h,request_process,3,[{file,"/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl"},{line,227}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]
Ranch listener http, connection process <0.1469.4>, stream 1 had its request process <0.1479.4> exit with reason {badmatch,{error,emfile}} and stacktrace [{aesophia_http_api_validate,json_spec,0,[{file,"/app/apps/aesophia_http/src/aesophia_http_api_validate.erl"},{line,12}]},{aesophia_http_handler,init,2,[{file,"/app/apps/aesophia_http/src/aesophia_http_handler.erl"},{line,15}]},{cowboy_handler,execute,2,[{file,"/app/_build/default/lib/cowboy/src/cowboy_handler.erl"},{line,37}]},{cowboy_stream_h,execute,3,[{file,"/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl"},{line,249}]},{cowboy_stream_h,request_process,3,[{file,"/app/_build/default/lib/cowboy/src/cowboy_stream_h.erl"},{line,227}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]

Version: 6.1.0, unknown request

Missed definition of SophiaCallResult

SophiaCallResult: {}

Can we use some kind of oneOf to define all possible variants? This would fix the autorest warning

WARNING (Modeler/MissingType): The schema 'SophiaCallResult' has no type or format information whatsoever. Location:
   https://compiler.aeternity.io/api#/components/schemas/SophiaCallResult

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.