Error when performing dryRun (Lima v5.0.0-rc.2)

Going from v3 to v4 :thinking: I think there are a few new options, check the changelog of aesophia_http and the swagger file for details.

I’ve got no problems producing the call-data using the latest aesophia_http docker image:

aeternity: cat /tmp/foo.aes 
contract Test =
  record state = { m : map(address, int) }
  entrypoint init(m_ : map(address, int)) = { m = m_ }
aeternity: csource=`cat /tmp/foo.aes`
aeternity: curl -H "Content-Type: application/json" -d "{\"function\":\"init\",\"arguments\":[\"{[ak_RPAwsPcdxzuBhEtwqdHQquKmdFFSY8M9myS4EaaTWbwEoUnS5] = 20, [ak_2feoWo2kTqv5Lb175vtPFFTQp6vGbme2GAbfM5EZqxVR549xWK] = 40, [ak_2JZC7Ynsr38XGxZqKHYCojPzTpb8dSZMTBsJZJoSGJuKD134Jy] = 40}\"],\"source\":\"$csource\",\"options\":{\"backend\":\"fate\"}}" -X POST http://localhost:3080/encode-calldata
{"calldata":"cb_KxFE1kQfGy8DnwCgN1zoUO0byvTdsEGbIVD9iEbIAIe7/ec2Np01s2IrHTAonwCgq46TKoipZr6WylwiPLkZ8vokHc5/fDP07GimDU15tvVQnwCg23Wq+Qk3svHNcS7oSB1V6JSgluUS1eKDRp7QsU/3D8hQiQ/W6A=="}

But, the same example produces an error in the CLI front-end of the compiler :disappointed:

aeternity: ./aesophia_cli --create_calldata /tmp/foo.aes --calldata_fun init --calldata_args "{[ak_RPAwsPcdxzuBhEtwqdHQquKmdFFSY8M9myS4EaaTWbwEoUnS5] = 60,  [ak_2feoWo2kTqv5Lb175vtPFFTQp6vGbme2GAbfM5EZqxVR549xWK] = 40}"

Parse error at line 7, col 2:
Unexpected indentation. Probable causes:
  - something is missing in the previous statement, or
  - this line should be indented more.

We will make sure that is fixed before the final 4.0.0 version is released.

I believe the only thing missing is the “backend” option, in the compiler v4.x series yo have to specify which backend you want to use: fate or aevm.If none is specified the compiler returns an error.

here is a sample request (from @hanssv example)

POST https://compiler.aepps.com/encode-calldata
Content-Type: application/json
Sophia-Compiler-Version: 4.0.0-rc5

{
    "function": "init",
    "arguments": [
        "{[ak_RPAwsPcdxzuBhEtwqdHQquKmdFFSY8M9myS4EaaTWbwEoUnS5] = 20, [ak_2feoWo2kTqv5Lb175vtPFFTQp6vGbme2GAbfM5EZqxVR549xWK] = 40, [ak_2JZC7Ynsr38XGxZqKHYCojPzTpb8dSZMTBsJZJoSGJuKD134Jy] = 40}"
    ],
    "source": "contract Test =\n    record state = { m : map(address, int) } \n    entrypoint init(m_ : map(address, int)) = { m = m_ }",
    "options": {
        "backend": "fate"
    }
}

and the result using fate:

HTTP/1.1 200 OK
Content-Length: 182
Content-Type: application/json
Date: Fri, 04 Oct 2019 07:22:23 GMT
Server: Cowboy
Vary: Accept-Encoding
Connection: close

{
  "calldata": "cb_KxFE1kQfGy8DnwCgN1zoUO0byvTdsEGbIVD9iEbIAIe7/ec2Np01s2IrHTAonwCgq46TKoipZr6WylwiPLkZ8vokHc5/fDP07GimDU15tvVQnwCg23Wq+Qk3svHNcS7oSB1V6JSgluUS1eKDRp7QsU/3D8hQiQ/W6A=="
}

and aevm:

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: application/json
Date: Fri, 04 Oct 2019 07:24:49 GMT
Server: Cowboy
Vary: Accept-Encoding
Content-Length: 254
Connection: close

{
  "calldata": "cb_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAwL/1cQIrYKi4PYb+8VX9C4UVfgoJVPy3WaoMHziQz3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgN1zoUO0byvTdsEGbIVD9iEbIAIe7/ec2Np01s2IrHTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCrjpMqiKlmvpbKXCI8uRny+iQdzn98M/TsaKYNTXm29QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINt1qvkJN7LxzXEu6EgdVeiUoJblEtXig0ae0LFP9w/IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKHMw6E0="
}
1 Like

thats a good hint. probably this is the problem. will check and inform you about it. thanks!

@hanssv @noandrea:

after adding the compiler-options I am able to deploy the contract and call the payAndSplit-function. but it seems like the functionality of the contract is broken. somehow the amount is not splitted across the given accounts in the init function. this is really strange! … the only thing I changed in the contract is the syntax regarding tuples.

How do you observe that it doesn’t work? Is the funds split in some other way, or not at all?

None of the functions is payable, and neither is the contract so I’m not sure how it is supposed to work?

1 Like

again didn’t catch that :sweat_smile: forgot about the introduction of payable. now it works as expected. thanks!

@hanssv I made all required changes and now we provide an easy selection between FATE and AEVM in our SDK.

with AEVM we have no problems. when using FATE then the dryRun is failing for the payAndSplit-function. (Internal Server Error)

the dryRun for the init-function works without any problems.

this seems to be a problem in the implementation of the core-protocol I think. will look into the debug-log and hopefully find more information about the problem.

edit
here the error-log of the node. I hope this is related to the dryRun for the payAndSplit-function:

2019-10-06 14:02:08.774 [error] <0.5465.1>@aec_trees:apply_txs_on_state_trees:607 Tx {aetx,contract_call_tx,aect_call_tx,109,{contract_call_tx,{id,account,<<117,238,152,37,173,99,9,99,72,43,177,147,154,33,42,14,83,88,131,198,180,215,128,78,64,40,126,31,85,109,162,114>>},2,{id,contract,<<62,44,231,91,214,95,57,42,226,167,63,31,25,1,27,108,118,168,104,112,152,92,209,4,53,78,77,169,17,129,176,177>>},3,452180000000000,0,1000000000000000000,1579000,1000000000,<<43,17,245,174,169,217,63>>,[],<<117,238,152,37,173,99,9,99,72,43,177,147,154,33,42,14,83,88,131,198,180,215,128,78,64,40,126,31,85,109,162,114>>}} cannot be applied due to an error {error,{badmatch,{es,void,[],#{0 => [{'PUSH',{immediate,0}},{'BALANCE',{stack,0}},{'GT',{stack,0},{stack,0},{stack,0}},{'JUMPIF',{stack,0},{immediate,4}}],1 => [{'PUSH',{immediate,<<"contract didn't receive any payment">>}},{'ABORT',{stack,0}}],2 => [{'STORE',{var,9999},{stack,0}},{'ELEMENT',{stack,0},{immediate,1},{var,-1}},{'MAP_TO_LIST',{var,1},{stack,0}},{'ELEMENT',{stack,0},{immediate,2},{var,-1}},{'BALANCE',{stack,0}},{'ADD',{stack,0},{stack,0},{stack,0}},{'PUSH',{var,-1}},{'SETELEMENT',{stack,0},{immediate,2},{stack,0},{stack,0}},{'STORE',{var,-1},{stack,0}},{'BALANCE',{stack,0}},{'PUSH',{var,1}},{'CALL',{immediate,<<48,129,120,71>>}}],3 => [{'STORE',{var,9999},{stack,0}},{'CALLER',{stack,0}},{'CALL_VALUE',{stack,0}},{'BALANCE',{stack,0}},{'VARIANT',{stack,0},{immediate,[0,2,2,0,3]},{immediate,4},{immediate,3}},{'CALL_T',{immediate,<<101,165,224,15>>}}],4 => [{'PUSH',{immediate,{tuple,{}}}},{'JUMP',{immediate,2}}]},[],{address,<<117,238,152,37,173,99,9,99,72,43,177,147,154,33,42,14,83,88,131,198,180,215,128,78,64,40,126,31,85,109,162,114>>},1000000000000000000,{state,{state,{trees,{mpt,<<171,228,5,15,89,141,152,193,101,156,117,113,162,178,91,110,54,52,159,46,19,34,192,133,31,198,187,103,190,49,4,48>>,{db,accounts,{gb_trees,{6,{<<117,136,145,167,177,0,60,195,178,67,231,39,105,236,45,30,70,137,18,208,152,213,107,232,95,253,233,255,72,9,210,169>>,[<<48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>,<<205,10,1,0,137,54,53,201,173,197,222,160,0,0>>],{<<76,143,150,212,192,14,37,167,216,214,98,59,47,140,151,175,190,28,43,95,35,188,196,210,230,109,18,87,182,79,154,198>>,[<<117,136,145,167,177,0,60,195,178,67,231,39,105,236,45,30,70,137,18,208,152,213,107,232,95,253,233,255,72,9,210,169>>,<<>>,<<>>,<<206,6,103,203,1,140,194,39,195,15,159,222,218,167,21,216,239,251,15,116,4,47,120,248,242,174,10,199,1,239,42,155>>,<<>>,<<>>,<<>>,<<194,185,119,83,16,122,56,160,194,30,34,5,112,247,64,40,84,60,24,86,25,12,136,207,154,162,176,127,14,119,222,166>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>],{<<42,145,88,134,154,134,84,70,138,13,167,218,43,216,79,207,241,241,224,38,204,66,67,162,14,228,244,111,33,172,202,181>>,[<<53,238,152,37,173,99,9,99,72,43,177,147,154,33,42,14,83,88,131,198,180,215,128,78,64,40,126,31,85,109,162,114>>,<<210,10,1,2,142,4,238,45,109,65,91,133,165,71,57,120,226,36,0>>],nil,nil},nil},{<<196,236,139,84,213,10,252,221,235,68,7,110,56,191,2,91,204,167,133,153,157,129,30,107,145,207,87,3,179,23,30,145>>,[<<117,136,145,167,177,0,60,195,178,67,231,39,105,236,45,30,70,137,18,208,152,213,107,232,95,253,233,255,72,9,210,169>>,<<>>,<<>>,<<206,6,103,203,1,140,194,39,195,15,159,222,218,167,21,216,239,251,15,116,4,47,120,248,242,174,10,199,1,239,42,155>>,<<>>,<<>>,<<>>,<<42,145,88,134,154,134,84,70,138,13,167,218,43,216,79,207,241,241,224,38,204,66,67,162,14,228,244,111,33,172,202,181>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>],{<<145,157,68,129,85,57,130,68,39,17,179,160,136,125,125,130,254,150,3,14,14,158,214,1,209,43,35,133,248,215,254,178>>,[<<62,44,231,91,214,95,57,42,226,167,63,31,25,1,27,108,118,168,104,112,152,92,209,4,53,78,77,169,17,129,176,177>>,<<204,10,1,0,136,13,224,182,179,167,100,0,0>>],nil,{<<171,228,5,15,89,141,152,193,101,156,117,113,162,178,91,110,54,52,159,46,19,34,192,133,31,198,187,103,190,49,4,48>>,[<<117,136,145,167,177,0,60,195,178,67,231,39,105,236,45,30,70,137,18,208,152,213,107,232,95,253,233,255,72,9,210,169>>,<<>>,<<>>,<<145,157,68,129,85,57,130,68,39,17,179,160,136,125,125,130,254,...>>,...],...}},...}}}},...}},...},...},...},...}}}
2019-10-06 14:02:08.775 [error] <0.5465.1>@lists:thing_to_list:603 CRASH REPORT Process <0.5465.1> with 0 neighbours crashed with reason: no function clause matching lists:thing_to_list({error,{badmatch,{es,void,[],#{0 => [{'PUSH',{immediate,0}},{'BALANCE',{stack,0}},{'GT',{stack,...},...},...],...},...}}}) line 603
2019-10-06 14:02:08.775 [error] <0.5465.1>@lists:thing_to_list:603 Cowboy stream 1 with ranch listener internal and connection process <0.5464.1> had its request process exit with reason: no function clause matching lists:thing_to_list({error,{badmatch,{es,void,[],#{0 => [{'PUSH',{immediate,0}},{'BALANCE',{stack,0}},{'GT',{stack,...},...},...],...},...}}}) line 603

we are using this version of the PaymentSplitter contract:

the node-version we are running against is v5.0.0-rc.3

1 Like

I can’t reproduce the problem. What is the failing dryRun transaction?

We experimented a bit more, and finally managed to reproduce the issue.

It looks to be a problem with Map.to_list in FATE - we’ll investigate further.

3 Likes

hopefully not a big deal. I guess it will be fixed in the next release candidate :slight_smile:

@erik93 isn’t this observation worth a bug bounty? :stuck_out_tongue:

1 Like

It is fixed already - 5.0.0-rc4 has been out for several hours :slight_smile:

2 Likes

the problem I mentioned has been fixed with 5.0.0-rc4. but I probably got another issue regarding the FATE-VM.

it seems like for the contract:

contract Identity =
  entrypoint main(z : int) = z

when calling the main-function with following calldata (value 42):

cb_KxG4F37sG1Q/+F7e

and afterwards waiting for the TxInfoObject we get for both (returnValue and returnType) the same content:

cb_VNLOFXc=

when trying to decode this with the compiler providing cb_VNLOFXc= as body and int as sophiaType we get a Bad Request with following responseBody:

[{"message":"bad type/data","pos":{"col":0,"line":0},"type":"data_error"}]

are we doing sth wrong? can you check that? doing the same using AEVM works without any problem.

edit:

  • assuming the node response is correct (although returnType of the TxInfoObject should be ‘ok’, ‘error’ or ‘revert’) then this is probably a problem in the compiler when trying to decode cb_VNLOFXc= as sophiaType int.

First, the returnValue looks correct, it is indeed 42

4> {_, X} = aeser_api_encoder:decode(<<"cb_VNLOFXc=">>).
{contract_bytearray,<<"T">>}
5> aeb_fate_encoding:deserialize(X).
42

The problem is that you are using the legacy decoding endpoint /decode-data it only works for AEVM results. To decode the result of a contract call it is better to use /decode-call-result - it takes slightly different parameters:

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

Finally, about getting a returnType that is Base64Check encoded (cb_...). It sounds weird, the returnType should be either ok, revert, or error as you mention. Which HTTP-endpoint did give you that? Could you post the full response?

1 Like

regarding the returnType -> we are mapping the response into our own objects. seems like we got an issue there. response looks good:

{"results":[{"call_obj":{"caller_id":"ak_twR4h7dEcUtc2iSEDv8kB7UFJJDGiEDQCXr85C3fYF8FdVdyo","caller_nonce":5,"contract_id":"ct_S1WcdNQf5dqVcnC6pc9kwMNVz84s91ZMeUZfYjzHgreBznzuA","gas_price":1000000000,"gas_used":11,"height":139,"log":[],"return_type":"ok","return_value":"cb_VNLOFXc="},"result":"ok","type":"contract_call"}]}

I am just adding the /decode-call-result endpoint to our compiler-service. I noticed, that in the swagger-definition of the compiler the SophiaCallResult-Definition has no property. I guess that needs to be added, right? currently it is empty

  SophiaCallResult: {}
  SophiaCallResultInput:
    example:
      call-result: call-result
      call-value: call-value
      function: function
      options:
        backend: fate
        file_system: '{}'
        src_file: src_file
      source: source
    properties:
      call-result:
        description: Call result type (ok | revert | error)
        type: string
      call-value:
        description: Call result value (ABI encoded data or error string)
        type: string
      function:
        description: Name of the called function
        type: string
      options:
        $ref: '#/definitions/CompileOpts'
      source:
        description: (Possibly partial) Sophia contract code/interface
        type: string
    required:
      - call-result
      - call-value
      - function
      - source

edit

  • @hanssv can you please change the response in the compiler regarding that endpoint? doesn’t seem to be a valid json. it is just returning the value 42

Hmm, last time I checked 42 is perfectly valid as a JSON value?

If I remember correctly, the reason for not specifying SophiaCallResult was that Swagger didn’t like what I tried to say… So in the end I went with {} which supposedly means “anything” in Swagger lingo. Improvement suggestions are welcome.

1 Like

again my mistake. haven’t used json with the context of a single value so fair.

still the SophiaCallResult should probably be defined in another way. currently when generating java classes from the swagger definition there is absolutely no chance to deserialize the response because the generated class has no attribute.

to fix the problem for us I changed to swagger-definition as follows:

  /decode-call-result:
    post:
      consumes:
        - application/json
      description: Decode the result of contract call
      operationId: DecodeCallResult
      parameters:
        - description: Binary data in Sophia ABI format
          in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/SophiaCallResultInput'
      produces:
        - application/json
      responses:
        '200':
          description: Json encoded data
          schema:
            oneOf:
              - type: string
              - type: integer
              - type: number
              - type: boolean
              - type: array
        '400':
          description: Invalid data
          schema:
            $ref: '#/definitions/CompilerErrors'

we now totally ignore the SophiaCallResult definition. I don’t know whether this would cover all response-values.

the response could also contain maps, right? for the moment I only tested the change for the sample function that returns an integer.

It is using the ACI generator, and its JSON encoder. It returns a JSON representation of the Sophia value. If I remember correctly Sophia-tuples are mapped to JSON-array, numbers are numbers, booleans are booleans, strings are strings, Sophia-records become JSON-objects, constructors also become JSON-objects, and Sophia-maps will become an array of pairs (arrays with length2) in JSON.

(42, true, "Hello", ())              => [42, true, "Hello", []]
(One(12, 18), Two)                   => [{"One": [12, 18]}, {"Two": []}]
{x = 43, y = "Foo", z = { [1] = 2 }} => {"x": 43, "y": "Foo", "z": [[1, 2]]}

we will test whether my “workaround” will be able to cover decoding these response-values. thanks :slight_smile:

As far as I can read the Swagger documentation what you’ve written more or less means {} so let’s see what happens.