Compare commits
26 Commits
v3.0.0
..
b47b2fe23c
| Author | SHA1 | Date | |
|---|---|---|---|
| b47b2fe23c | |||
| 5e38d6e829 | |||
| 009e036192 | |||
| 37808419a8 | |||
| f4c3782888 | |||
| 1688f85f2b | |||
| b38349274f | |||
| b8d593e351 | |||
| 0f7529b26a | |||
| 2a0a397afa | |||
| 093bcd6204 | |||
| 6601ad2d38 | |||
| 578ebe2a8a | |||
| 8269dbd71e | |||
| 08cc0a9fcd | |||
| 84f20ab683 | |||
| 7497345928 | |||
| 822a269f75 | |||
| 0699f35b03 | |||
| 3829e29a63 | |||
| 52e9d30f76 | |||
| da7f00ae5d | |||
| 326fca709f | |||
| e860e217a0 | |||
| bc48b5d62f | |||
| 7b9c1b856b |
@@ -3,7 +3,7 @@ version: 2.1
|
|||||||
executors:
|
executors:
|
||||||
aebuilder:
|
aebuilder:
|
||||||
docker:
|
docker:
|
||||||
- image: aeternity/builder
|
- image: aeternity/builder:bionic-otp23
|
||||||
user: builder
|
user: builder
|
||||||
working_directory: ~/aebytecode
|
working_directory: ~/aebytecode
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ test: local
|
|||||||
@$(REBAR) as local eunit
|
@$(REBAR) as local eunit
|
||||||
|
|
||||||
ebin/%.beam: src/%.erl
|
ebin/%.beam: src/%.erl
|
||||||
erlc -o $(dir $@) $<
|
erlc +debug_info -o $(dir $@) $<
|
||||||
|
|
||||||
$(GENERATED_SRC): $(GENERATOR_DEPS)
|
$(GENERATED_SRC): $(GENERATOR_DEPS)
|
||||||
erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/
|
erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/
|
||||||
|
|||||||
+3
-3
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{deps, [ {eblake2, "1.0.0"}
|
{deps, [ {eblake2, "1.0.0"}
|
||||||
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
||||||
{ref, "47aaa8f"}}}
|
{tag, "v1.0.0"}}}
|
||||||
, {getopt, "1.0.1"}
|
, {getopt, "1.0.1"}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
]}.
|
]}.
|
||||||
|
|
||||||
|
|
||||||
{relx, [{release, {aebytecode, "2.0.1"},
|
{relx, [{release, {aebytecode, "3.4.0"},
|
||||||
[aebytecode, eblake2, getopt]},
|
[aebytecode, eblake2, getopt]},
|
||||||
|
|
||||||
{dev_mode, true},
|
{dev_mode, true},
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
{profiles, [{binary, [
|
{profiles, [{binary, [
|
||||||
{deps, [ {eblake2, "1.0.0"}
|
{deps, [ {eblake2, "1.0.0"}
|
||||||
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
||||||
{ref, "47aaa8f"}}}
|
{tag, "v1.0.0"}}}
|
||||||
, {getopt, "1.0.1"}
|
, {getopt, "1.0.1"}
|
||||||
]},
|
]},
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -1,7 +1,7 @@
|
|||||||
{"1.1.0",
|
{"1.2.0",
|
||||||
[{<<"aeserialization">>,
|
[{<<"aeserialization">>,
|
||||||
{git,"https://github.com/aeternity/aeserialization.git",
|
{git,"https://github.com/aeternity/aeserialization.git",
|
||||||
{ref,"47aaa8f5434b365c50a35bfd1490340b19241991"}},
|
{ref,"177bf604b2a05e940f92cf00e96e6e269e708245"}},
|
||||||
0},
|
0},
|
||||||
{<<"base58">>,
|
{<<"base58">>,
|
||||||
{git,"https://github.com/aeternity/erl-base58.git",
|
{git,"https://github.com/aeternity/erl-base58.git",
|
||||||
@@ -10,11 +10,14 @@
|
|||||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
||||||
{<<"enacl">>,
|
{<<"enacl">>,
|
||||||
{git,"https://github.com/aeternity/enacl.git",
|
{git,"https://github.com/aeternity/enacl.git",
|
||||||
{ref,"26180f42c0b3a450905d2efd8bc7fd5fd9cece75"}},
|
{ref,"793ddb502f7fe081302e1c42227dca70b09f8e17"}},
|
||||||
1},
|
1},
|
||||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}]}.
|
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}]}.
|
||||||
[
|
[
|
||||||
{pkg_hash,[
|
{pkg_hash,[
|
||||||
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>},
|
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>},
|
||||||
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]}
|
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]},
|
||||||
|
{pkg_hash_ext,[
|
||||||
|
{<<"eblake2">>, <<"3C4D300A91845B25D501929A26AC2E6F7157480846FAB2347A4C11AE52E08A99">>},
|
||||||
|
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]}
|
||||||
].
|
].
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ parse_tuple(Tokens) ->
|
|||||||
|
|
||||||
|
|
||||||
parse_variant([{start_variant,_line}
|
parse_variant([{start_variant,_line}
|
||||||
, {'[', _line}
|
, {'[', _}
|
||||||
| Rest]) ->
|
| Rest]) ->
|
||||||
{Arities, Rest2} = parse_list(Rest),
|
{Arities, Rest2} = parse_list(Rest),
|
||||||
%% Make sure Arities is a list of bytes.
|
%% Make sure Arities is a list of bytes.
|
||||||
@@ -364,7 +364,7 @@ parse_variant([{start_variant,_line}
|
|||||||
is_integer(A), A < 256],
|
is_integer(A), A < 256],
|
||||||
|
|
||||||
[{'|',_}
|
[{'|',_}
|
||||||
, {int,_line, Tag}
|
, {int,_, Tag}
|
||||||
, {'|',_}
|
, {'|',_}
|
||||||
, {'(',_} | Rest3] = Rest2,
|
, {'(',_} | Rest3] = Rest2,
|
||||||
{Elements , [{end_variant, _} | Rest4]} = parse_tuple(Rest3),
|
{Elements , [{end_variant, _} | Rest4]} = parse_tuple(Rest3),
|
||||||
|
|||||||
@@ -27,11 +27,9 @@
|
|||||||
-include("../include/aeb_fate_opcodes.hrl").
|
-include("../include/aeb_fate_opcodes.hrl").
|
||||||
-include("../include/aeb_fate_data.hrl").
|
-include("../include/aeb_fate_data.hrl").
|
||||||
|
|
||||||
-ifdef(EQC).
|
|
||||||
-export([ update_annotations/2
|
-export([ update_annotations/2
|
||||||
, update_functions/2
|
, update_functions/2
|
||||||
, update_symbols/2]).
|
, update_symbols/2]).
|
||||||
-endif.
|
|
||||||
|
|
||||||
-record(fcode, { functions = #{} :: map()
|
-record(fcode, { functions = #{} :: map()
|
||||||
, symbols = #{} :: map()
|
, symbols = #{} :: map()
|
||||||
|
|||||||
@@ -238,6 +238,8 @@ serialize_type({tuple, Ts}) ->
|
|||||||
N when N =< 255 ->
|
N when N =< 255 ->
|
||||||
[?TYPE_TUPLE, N | [serialize_type(T) || T <- Ts]]
|
[?TYPE_TUPLE, N | [serialize_type(T) || T <- Ts]]
|
||||||
end;
|
end;
|
||||||
|
serialize_type({bytes, any}) ->
|
||||||
|
[?TYPE_BYTES | binary_to_list(serialize_integer(-1))];
|
||||||
serialize_type({bytes, N}) when 0 =< N ->
|
serialize_type({bytes, N}) when 0 =< N ->
|
||||||
[?TYPE_BYTES | binary_to_list(serialize_integer(N))];
|
[?TYPE_BYTES | binary_to_list(serialize_integer(N))];
|
||||||
serialize_type(address) -> [?TYPE_OBJECT, ?OTYPE_ADDRESS];
|
serialize_type(address) -> [?TYPE_OBJECT, ?OTYPE_ADDRESS];
|
||||||
@@ -270,8 +272,12 @@ deserialize_type(<<?TYPE_TUPLE, N, Rest/binary>>) ->
|
|||||||
{{tuple, Ts}, Rest2};
|
{{tuple, Ts}, Rest2};
|
||||||
deserialize_type(<<?TYPE_BYTES, Rest/binary>>) ->
|
deserialize_type(<<?TYPE_BYTES, Rest/binary>>) ->
|
||||||
{N, Rest2} = deserialize_one(Rest),
|
{N, Rest2} = deserialize_one(Rest),
|
||||||
true = is_integer(N) andalso N >= 0,
|
true = is_integer(N),
|
||||||
{{bytes, N}, Rest2};
|
if N == -1 ->
|
||||||
|
{{bytes, any}, Rest2};
|
||||||
|
0 =< N ->
|
||||||
|
{{bytes, N}, Rest2}
|
||||||
|
end;
|
||||||
deserialize_type(<<?TYPE_OBJECT, ObjectType, Rest/binary>>) ->
|
deserialize_type(<<?TYPE_OBJECT, ObjectType, Rest/binary>>) ->
|
||||||
case ObjectType of
|
case ObjectType of
|
||||||
?OTYPE_ADDRESS -> {address, Rest};
|
?OTYPE_ADDRESS -> {address, Rest};
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
-module(aeb_fate_generate_docs).
|
||||||
|
|
||||||
|
-export([generate_documentation/2, generate_documentation/3]).
|
||||||
|
|
||||||
|
-export(
|
||||||
|
[ gen_protocol_opcodes_flags_and_gas/1
|
||||||
|
, gen_protocol_description_of_operations/1
|
||||||
|
, gen_protocol_opcodes/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-define(LIMA_PROTOCOL_VSN, 4).
|
||||||
|
-define(IRIS_PROTOCOL_VSN, 5).
|
||||||
|
|
||||||
|
generate_documentation(Filename, Fields) ->
|
||||||
|
generate_documentation(Filename, Fields, fun(_) -> true end).
|
||||||
|
generate_documentation(Filename, Fields, Filter) when is_function(Filter, 1) ->
|
||||||
|
{ok, File} = file:open(Filename, [write, {encoding, utf8}]),
|
||||||
|
Header =
|
||||||
|
lists:flatten(
|
||||||
|
"|" ++ [" " ++ header_name(F) ++ " |" || F <- Fields] ++ "\n"
|
||||||
|
),
|
||||||
|
Separator =
|
||||||
|
lists:flatten(
|
||||||
|
"|" ++ [" " ++ ["-" || _ <- header_name(F)] ++ " |" || F <- Fields] ++ "\n"
|
||||||
|
),
|
||||||
|
Instructions =
|
||||||
|
lists:flatten(
|
||||||
|
[gen_doc_for_op(Op, Fields)
|
||||||
|
++ "\n" || Op <- aeb_fate_generate_ops:get_ops(), Filter(Op)]),
|
||||||
|
io:format(File, "~ts~ts~ts\n", [Header, Separator, Instructions]),
|
||||||
|
file:close(File).
|
||||||
|
|
||||||
|
header_name(opname) ->
|
||||||
|
"Name";
|
||||||
|
header_name(opcode) ->
|
||||||
|
"Opcode";
|
||||||
|
header_name(arity) ->
|
||||||
|
"Arity";
|
||||||
|
header_name(end_bb) ->
|
||||||
|
"Ends basic block";
|
||||||
|
header_name(in_auth) ->
|
||||||
|
"Allowed in auth";
|
||||||
|
header_name(offchain) ->
|
||||||
|
"Allowed offchain";
|
||||||
|
header_name(format) ->
|
||||||
|
"Args";
|
||||||
|
header_name(doc) ->
|
||||||
|
"Description";
|
||||||
|
header_name(gas) ->
|
||||||
|
"Gas cost";
|
||||||
|
header_name(arg_types) ->
|
||||||
|
"Arg types";
|
||||||
|
header_name(res_type) ->
|
||||||
|
"Res type".
|
||||||
|
|
||||||
|
gen_doc_for_op(#{ opname := OpName
|
||||||
|
, opcode := OpCode
|
||||||
|
, arity := Arity
|
||||||
|
, end_bb := EndBB
|
||||||
|
, in_auth := InAuth
|
||||||
|
, offchain := AllowedOffchain
|
||||||
|
, format := FateFormat
|
||||||
|
, doc := Doc
|
||||||
|
, gas := Gas
|
||||||
|
, arg_types := ArgTypes
|
||||||
|
, res_type := ResType
|
||||||
|
}, Fields) ->
|
||||||
|
"| " ++
|
||||||
|
string:join(
|
||||||
|
[ case Field of
|
||||||
|
opname -> io_lib:format("`~s`", [OpName]);
|
||||||
|
opcode -> io_lib:format("0x~.16b", [OpCode]);
|
||||||
|
arity -> io_lib:format("~p", [Arity]);
|
||||||
|
end_bb -> io_lib:format("~p", [EndBB]);
|
||||||
|
in_auth -> io_lib:format("~p", [InAuth]);
|
||||||
|
offchain -> io_lib:format("~p", [AllowedOffchain]);
|
||||||
|
format ->
|
||||||
|
case FateFormat of
|
||||||
|
[] -> "";
|
||||||
|
_ -> lists:join(
|
||||||
|
" ",
|
||||||
|
[format_arg_doc(A) ||
|
||||||
|
A <-
|
||||||
|
lists:zip(FateFormat,
|
||||||
|
lists:seq(0,length(FateFormat)-1))])
|
||||||
|
end;
|
||||||
|
doc -> Doc;
|
||||||
|
gas when is_integer(Gas) -> io_lib:format("~p", [Gas]);
|
||||||
|
gas when is_list(Gas) ->
|
||||||
|
lists:flatten(
|
||||||
|
string:join(
|
||||||
|
[ io_lib:format(
|
||||||
|
"~p (~s)",
|
||||||
|
[GasVal, protocol_name(Prot)]
|
||||||
|
)
|
||||||
|
|| {Prot, GasVal} <- Gas
|
||||||
|
], ", "));
|
||||||
|
arg_types -> io_lib:format("~p", [ArgTypes]);
|
||||||
|
res_type -> io_lib:format("~p", [ResType])
|
||||||
|
end
|
||||||
|
|| Field <- Fields
|
||||||
|
],
|
||||||
|
" | ") ++ " |".
|
||||||
|
|
||||||
|
protocol_name(?LIMA_PROTOCOL_VSN) ->
|
||||||
|
"lima";
|
||||||
|
protocol_name(?IRIS_PROTOCOL_VSN) ->
|
||||||
|
"iris".
|
||||||
|
|
||||||
|
format_arg_doc({a, N}) -> io_lib:format("Arg~w", [N]);
|
||||||
|
format_arg_doc({is,_N}) -> "Identifier";
|
||||||
|
format_arg_doc({ii,_N}) -> "Integer";
|
||||||
|
format_arg_doc({li,_N}) -> "[Integers]";
|
||||||
|
format_arg_doc({t,_N}) -> "Type".
|
||||||
|
|
||||||
|
|
||||||
|
%% --- protocol documentation ---
|
||||||
|
|
||||||
|
gen_protocol_description_of_operations(Filename) ->
|
||||||
|
generate_documentation(
|
||||||
|
Filename, [opname, format, doc, arg_types, res_type]
|
||||||
|
).
|
||||||
|
|
||||||
|
gen_protocol_opcodes_flags_and_gas(Filename) ->
|
||||||
|
generate_documentation(
|
||||||
|
Filename, [opcode, opname, end_bb, in_auth, offchain, gas]
|
||||||
|
).
|
||||||
|
|
||||||
|
gen_protocol_opcodes(Filename) ->
|
||||||
|
generate_documentation(
|
||||||
|
Filename, [opcode, opname]
|
||||||
|
).
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
-export([ gen_and_halt/1
|
-export([ gen_and_halt/1
|
||||||
, generate/0
|
, generate/0
|
||||||
, generate_documentation/1
|
|
||||||
, get_ops/0
|
, get_ops/0
|
||||||
, test_asm_generator/1 ]).
|
, test_asm_generator/1 ]).
|
||||||
|
|
||||||
@@ -32,7 +31,11 @@ check_defs(List) ->
|
|||||||
check_numbering(N, [T|Rest]) ->
|
check_numbering(N, [T|Rest]) ->
|
||||||
OpCode = element(2, T),
|
OpCode = element(2, T),
|
||||||
case OpCode of
|
case OpCode of
|
||||||
N -> check_numbering(N+1, Rest);
|
N -> check_numbering(N+1, Rest);
|
||||||
|
16#6d -> check_numbering(16#6d+1, Rest); %% Oracles
|
||||||
|
16#7b -> check_numbering(16#7b+1, Rest); %% Oracles
|
||||||
|
16#9b -> check_numbering(16#9b+1, Rest); %% Oracles
|
||||||
|
16#f0 -> check_numbering(16#f0+1, Rest);
|
||||||
16#fa -> check_numbering(16#fa+1, Rest);
|
16#fa -> check_numbering(16#fa+1, Rest);
|
||||||
_ when OpCode < N -> {duplicate_opcode, OpCode};
|
_ when OpCode < N -> {duplicate_opcode, OpCode};
|
||||||
_ when OpCode > N -> {missing_opcode, N}
|
_ when OpCode > N -> {missing_opcode, N}
|
||||||
@@ -46,7 +49,7 @@ check_numbering(_, []) -> true.
|
|||||||
-define(GAS_IRIS(A, B), [{?IRIS_PROTOCOL_VSN, B}, {?LIMA_PROTOCOL_VSN, A}]).
|
-define(GAS_IRIS(A, B), [{?IRIS_PROTOCOL_VSN, B}, {?LIMA_PROTOCOL_VSN, A}]).
|
||||||
|
|
||||||
ops_defs() ->
|
ops_defs() ->
|
||||||
%% Opname, Opcode, end_bb, in_auth offchain, gas, format, Constructor, ArgType, ResType, Documentation
|
%% Opname, Opcode, end_bb, in_auth,offchain, gas, format, Constructor, ArgType, ResType, Documentation
|
||||||
[ { 'RETURN', 16#00, true, true, true, ?GAS(10), [], return, {}, any, "Return from function call, top of stack is return value . The type of the retun value has to match the return type of the function."}
|
[ { 'RETURN', 16#00, true, true, true, ?GAS(10), [], return, {}, any, "Return from function call, top of stack is return value . The type of the retun value has to match the return type of the function."}
|
||||||
, { 'RETURNR', 16#01, true, true, true, ?GAS(10), [a], returnr, {any}, any, "Push Arg0 and return from function. The type of the retun value has to match the return type of the function."}
|
, { 'RETURNR', 16#01, true, true, true, ?GAS(10), [a], returnr, {any}, any, "Push Arg0 and return from function. The type of the retun value has to match the return type of the function."}
|
||||||
, { 'CALL', 16#02, true, true, true, ?GAS(10), [a], call, {string}, any, "Call the function Arg0 with args on stack. The types of the arguments has to match the argument typs of the function."}
|
, { 'CALL', 16#02, true, true, true, ?GAS(10), [a], call, {string}, any, "Call the function Arg0 with args on stack. The types of the arguments has to match the argument typs of the function."}
|
||||||
@@ -151,13 +154,8 @@ ops_defs() ->
|
|||||||
, { 'LOG4', 16#64, false, true, true, ?GAS(1400), [a,a,a,a,a], log, {integer, integer, integer, integer, string}, none, "Create a log message with four topics in the call object."}
|
, { 'LOG4', 16#64, false, true, true, ?GAS(1400), [a,a,a,a,a], log, {integer, integer, integer, integer, string}, none, "Create a log message with four topics in the call object."}
|
||||||
%% Transaction ops
|
%% Transaction ops
|
||||||
, { 'SPEND', 16#65, false, false, true, ?GAS_IRIS(100, 5000), [a,a], spend, {address, integer}, none, "Transfer Arg1 tokens to account Arg0. (If the contract account has at least that many tokens."}
|
, { 'SPEND', 16#65, false, false, true, ?GAS_IRIS(100, 5000), [a,a], spend, {address, integer}, none, "Transfer Arg1 tokens to account Arg0. (If the contract account has at least that many tokens."}
|
||||||
, { 'ORACLE_REGISTER', 16#66, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a,a,a,a], oracle_register, {signature, address, integer, variant, typerep, typerep}, oracle, "Arg0 := New oracle with address Arg2, query fee Arg3, TTL Arg4, query type Arg5 and response type Arg6. Arg0 contains delegation signature."}
|
%% Intentional gap (was oracles)
|
||||||
, { 'ORACLE_QUERY', 16#67, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a,a,a,a,a], oracle_query, {oracle, any, integer, variant, variant, typerep, typerep}, oracle_query, "Arg0 := New oracle query for oracle Arg1, question in Arg2, query fee in Arg3, query TTL in Arg4, response TTL in Arg5. Typereps for checking oracle type is in Arg6 and Arg7."}
|
|
||||||
, { 'ORACLE_RESPOND', 16#68, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a,a,a], oracle_respond, {signature, oracle, oracle_query,any, typerep, typerep}, none, "Respond as oracle Arg1 to query in Arg2 with response Arg3. Arg0 contains delegation signature. Typereps for checking oracle type is in Arg4 and Arg5."}
|
|
||||||
, { 'ORACLE_EXTEND', 16#69, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a], oracle_extend, {signature, oracle, variant}, none, "Extend oracle in Arg1 with TTL in Arg2. Arg0 contains delegation signature."}
|
|
||||||
, { 'ORACLE_GET_ANSWER', 16#6a, false, false, true, ?GAS_IRIS(100, 2000), [a,a,a,a,a], oracle_get_answer, {oracle, oracle_query, typerep, typerep}, any, "Arg0 := option variant with answer (if any) from oracle query in Arg1 given by oracle Arg0. Typereps for checking oracle type is in Arg3 and Arg4."}
|
|
||||||
, { 'ORACLE_GET_QUESTION', 16#6b, false, false, true, ?GAS_IRIS(100, 2000), [a,a,a,a,a], oracle_get_question, {oracle, oracle_query, typerep, typerep}, any, "Arg0 := question in oracle query Arg2 given to oracle Arg1. Typereps for checking oracle type is in Arg3 and Arg4."}
|
|
||||||
, { 'ORACLE_QUERY_FEE', 16#6c, false, false, true, ?GAS_IRIS(100, 2000), [a,a], oracle_query_fee, {oracle}, integer, "Arg0 := query fee for oracle Arg1"}
|
|
||||||
, { 'AENS_RESOLVE', 16#6d, false, false, true, ?GAS_IRIS(100, 2000), [a,a,a,a], aens_resolve, {string, string, typerep}, variant, "Resolve name in Arg0 with tag Arg1. Arg2 describes the type parameter of the resolved name."}
|
, { 'AENS_RESOLVE', 16#6d, false, false, true, ?GAS_IRIS(100, 2000), [a,a,a,a], aens_resolve, {string, string, typerep}, variant, "Resolve name in Arg0 with tag Arg1. Arg2 describes the type parameter of the resolved name."}
|
||||||
, { 'AENS_PRECLAIM', 16#6e, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a], aens_preclaim, {signature, address, hash}, none, "Preclaim the hash in Arg2 for address in Arg1. Arg0 contains delegation signature."}
|
, { 'AENS_PRECLAIM', 16#6e, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a], aens_preclaim, {signature, address, hash}, none, "Preclaim the hash in Arg2 for address in Arg1. Arg0 contains delegation signature."}
|
||||||
, { 'AENS_CLAIM', 16#6f, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a,a], aens_claim, {signature, address, string, integer, integer}, none, "Attempt to claim the name in Arg2 for address in Arg1 at a price in Arg4. Arg3 contains the salt used to hash the preclaim. Arg0 contains delegation signature."}
|
, { 'AENS_CLAIM', 16#6f, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a,a], aens_claim, {signature, address, string, integer, integer}, none, "Attempt to claim the name in Arg2 for address in Arg1 at a price in Arg4. Arg3 contains the salt used to hash the preclaim. Arg0 contains delegation signature."}
|
||||||
@@ -172,10 +170,8 @@ ops_defs() ->
|
|||||||
, { 'CONTRACT_TO_ADDRESS', 16#76, false, true, true, ?GAS(10), [a,a], contract_to_address, {contract}, address, "Arg0 := Arg1 - A no-op type conversion"}
|
, { 'CONTRACT_TO_ADDRESS', 16#76, false, true, true, ?GAS(10), [a,a], contract_to_address, {contract}, address, "Arg0 := Arg1 - A no-op type conversion"}
|
||||||
, { 'AUTH_TX_HASH', 16#77, false, true, true, ?GAS(10), [a], auth_tx_hash, {}, variant, "If in GA authentication context return Some(TxHash) otherwise None."}
|
, { 'AUTH_TX_HASH', 16#77, false, true, true, ?GAS(10), [a], auth_tx_hash, {}, variant, "If in GA authentication context return Some(TxHash) otherwise None."}
|
||||||
|
|
||||||
, { 'ORACLE_CHECK', 16#78, false, false, true, ?GAS(100), [a,a,a,a], oracle_check, {oracle, typerep, typerep}, bool, "Arg0 := is Arg1 an oracle with the given query (Arg2) and response (Arg3) types"}
|
%% Intentional gap (was oracles)
|
||||||
, { 'ORACLE_CHECK_QUERY', 16#79, false, false, true, ?GAS(100), [a,a,a,a,a], oracle_check_query, {oracle, oracle_query, typerep, typerep}, bool, "Arg0 := is Arg2 a query for the oracle Arg1 with the given types (Arg3, Arg4)"}
|
|
||||||
|
|
||||||
, { 'IS_ORACLE', 16#7a, false, false, true, ?GAS(100), [a,a], is_oracle, {address}, bool, "Arg0 := is Arg1 an oracle"}
|
|
||||||
, { 'IS_CONTRACT', 16#7b, false, false, true, ?GAS(100), [a,a], is_contract, {address}, bool, "Arg0 := is Arg1 a contract"}
|
, { 'IS_CONTRACT', 16#7b, false, false, true, ?GAS(100), [a,a], is_contract, {address}, bool, "Arg0 := is Arg1 a contract"}
|
||||||
, { 'IS_PAYABLE', 16#7c, false, false, true, ?GAS(100), [a,a], is_payable, {address}, bool, "Arg0 := is Arg1 a payable address"}
|
, { 'IS_PAYABLE', 16#7c, false, false, true, ?GAS(100), [a,a], is_payable, {address}, bool, "Arg0 := is Arg1 a payable address"}
|
||||||
, { 'CREATOR', 16#7d, false, true, true, ?GAS(10), [a], contract_creator, {}, address, "Arg0 := contract creator"}
|
, { 'CREATOR', 16#7d, false, true, true, ?GAS(10), [a], contract_creator, {}, address, "Arg0 := contract creator"}
|
||||||
@@ -214,7 +210,9 @@ ops_defs() ->
|
|||||||
, { 'BLS12_381_FP_TO_INT', 16#98, false, true, true, ?GAS(30), [a,a], bls12_381_fp_to_int, {tuple}, tuple, "Arg0 := from_montgomery(Arg1) - Convert montgomery representation (48 bytes) to integer"}
|
, { 'BLS12_381_FP_TO_INT', 16#98, false, true, true, ?GAS(30), [a,a], bls12_381_fp_to_int, {tuple}, tuple, "Arg0 := from_montgomery(Arg1) - Convert montgomery representation (48 bytes) to integer"}
|
||||||
|
|
||||||
, { 'AENS_LOOKUP', 16#99, false, false, true, ?GAS(2000), [a,a], aens_lookup, {string}, variant, "Lookup the name of Arg0. Returns option(AENS.name)"}
|
, { 'AENS_LOOKUP', 16#99, false, false, true, ?GAS(2000), [a,a], aens_lookup, {string}, variant, "Lookup the name of Arg0. Returns option(AENS.name)"}
|
||||||
, { 'ORACLE_EXPIRY', 16#9a, false, false, true, ?GAS(2000), [a,a], oracle_expiry, {oracle}, int, "Arg0 := expiry block for oracle Arg1"}
|
|
||||||
|
%% Intentional gap (was oracles)
|
||||||
|
|
||||||
, { 'AUTH_TX', 16#9b, false, true, true, ?GAS(100 ), [a], auth_tx, {}, variant, "If in GA authentication context return Some(Tx) otherwise None."}
|
, { 'AUTH_TX', 16#9b, false, true, true, ?GAS(100 ), [a], auth_tx, {}, variant, "If in GA authentication context return Some(Tx) otherwise None."}
|
||||||
|
|
||||||
, { 'STR_TO_LIST', 16#9c, false, true, true, ?GAS(100), [a,a], str_to_list, {string}, list, "Arg0 := string converted to list of characters"}
|
, { 'STR_TO_LIST', 16#9c, false, true, true, ?GAS(100), [a,a], str_to_list, {string}, list, "Arg0 := string converted to list of characters"}
|
||||||
@@ -226,13 +224,34 @@ ops_defs() ->
|
|||||||
|
|
||||||
, { 'CALL_PGR', 16#a2, true, false, true, ?GAS(100), [a,is,a,a,a,a,a], call_pgr, {contract, string, typerep, typerep, integer, integer, bool}, variant, "Potentially protected remote call. Arg5 is protected flag, otherwise as CALL_GR."}
|
, { 'CALL_PGR', 16#a2, true, false, true, ?GAS(100), [a,is,a,a,a,a,a], call_pgr, {contract, string, typerep, typerep, integer, integer, bool}, variant, "Potentially protected remote call. Arg5 is protected flag, otherwise as CALL_GR."}
|
||||||
|
|
||||||
, { 'CREATE', 16#a3, true, false, true, ?GAS(10000), [a,a,a], create, {contract_bytearray, typerep, integer}, contract, "Deploys a contract with a bytecode Arg1 and value Arg3. The `init` arguments should be placed on the stack and match the type in Arg2. Writes contract address to stack top."}
|
, { 'CREATE', 16#a3, true, false, true, ?GAS(10000), [a,a,a], create, {contract_bytearray, typerep, integer}, contract, "Deploys a contract with a bytecode Arg1 and value Arg3. The `init` arguments should be placed on the stack and match the type in Arg2. Writes contract address to the top of the accumulator stack. If an account on the resulting address did exist before the call, the `payable` flag will be updated."}
|
||||||
, { 'CLONE', 16#a4, true, false, true, ?GAS(5000), [a,a,a,a], clone, {contract, typerep, integer, bool}, any, "Clones the contract under Arg1 and deploys it with value of Arg3. The `init` arguments should be placed on the stack and match the type in Arg2. Writes contract (or `None` on fail when protected) to stack top."}
|
, { 'CLONE', 16#a4, true, false, true, ?GAS(5000), [a,a,a,a], clone, {contract, typerep, integer, bool}, any, "Clones the contract under Arg1 and deploys it with value of Arg3. The `init` arguments should be placed on the stack and match the type in Arg2. Writes contract (or `None` on fail when protected) to the top of the accumulator stack. Does not copy the existing contract's store – it will be initialized by a fresh call to the `init` function. If an account on the resulting address did exist before the call, the `payable` flag will be updated."}
|
||||||
, { 'CLONE_G', 16#a5, true, false, true, ?GAS(5000), [a,a,a,a,a], clone_g, {contract, typerep, integer, integer, bool}, any, "Like `CLONE` but additionally limits gas of `init` call to Arg3"}
|
, { 'CLONE_G', 16#a5, true, false, true, ?GAS(5000), [a,a,a,a,a], clone_g, {contract, typerep, integer, integer, bool}, any, "Like `CLONE` but additionally limits the gas of the `init` call by Arg3"}
|
||||||
, { 'BYTECODE_HASH', 16#a6, false, true, true, ?GAS(100), [a,a], bytecode_hash, {contract}, variant, "Arg0 := hash of the deserialized contract's bytecode under address given in Arg1 (or `None` on fail)."}
|
, { 'BYTECODE_HASH', 16#a6, false, true, true, ?GAS(100), [a,a], bytecode_hash, {contract}, variant, "Arg0 := hash of the deserialized contract's bytecode under address given in Arg1 (or `None` on fail). Fails on AEVM contracts and contracts deployed before Iris."}
|
||||||
|
|
||||||
, { 'FEE', 16#a7, false, true, true, ?GAS(10), [a], fee, {}, integer, "Arg0 := The fee for the current call tx."}
|
, { 'FEE', 16#a7, false, true, true, ?GAS(10), [a], fee, {}, integer, "Arg0 := The fee for the current call tx."}
|
||||||
|
|
||||||
|
, { 'ADDRESS_TO_BYTES', 16#a8, false, true, true, ?GAS(10), [a, a], addr_to_bytes, {address}, bytes, "Arg0 := the byte representation of the address"}
|
||||||
|
, { 'POSEIDON', 16#a9, false, true, true, ?GAS(6000), [a, a, a], poseidon, {integer, integer}, integer, "Arg0 := the Poseidon hash of Arg1 and Arg2 - all integers in the BLS12-381 scalar field"}
|
||||||
|
, { 'MULMOD', 16#aa, false, true, true, ?GAS(10), [a, a, a, a], mulmod, {integer, integer, integer}, integer, "Arg0 := (Arg1 * Arg2) mod Arg3"}
|
||||||
|
, { 'BAND', 16#ab, false, true, true, ?GAS(10), [a, a, a], bin_and, {integer, integer}, integer, "Arg0 := Arg1 & Arg2"}
|
||||||
|
, { 'BOR', 16#ac, false, true, true, ?GAS(10), [a, a, a], bin_or, {integer, integer}, integer, "Arg0 := Arg1 | Arg2"}
|
||||||
|
, { 'BXOR', 16#ad, false, true, true, ?GAS(10), [a, a, a], bin_xor, {integer, integer}, integer, "Arg0 := Arg1 ^ Arg2"}
|
||||||
|
, { 'BNOT', 16#ae, false, true, true, ?GAS(10), [a, a], bin_not, {integer}, integer, "Arg0 := ~Arg1"}
|
||||||
|
, { 'BSL', 16#af, false, true, true, ?GAS(10), [a, a, a], bin_sl, {integer, integer}, integer, "Arg0 := Arg1 << Arg2"}
|
||||||
|
, { 'BSR', 16#b0, false, true, true, ?GAS(10), [a, a, a], bin_sr, {integer, integer}, integer, "Arg0 := Arg1 >> Arg2"}
|
||||||
|
, { 'BYTES_SPLIT_ANY', 16#b1, false, true, true, ?GAS(10), [a, a, a], bytes_split_any, {bytes, integer}, variant, "Arg0 := bytes_split_any(Arg1, Arg2), where a positive Arg2 is the length of the first chunk, and a negative Arg2 is the length of the second chunk. Returns None if byte array is not long enough."}
|
||||||
|
, { 'BYTES_SIZE', 16#b2, false, true, true, ?GAS(10), [a, a], bytes_size, {bytes}, integer, "Arg0 := bytes_size(Arg1), returns the number of bytes in the byte array."}
|
||||||
|
, { 'BYTES_TO_FIXED_SIZE', 16#b3, false, true, true, ?GAS(10), [a, a, a], bytes_to_fixed_size, {bytes, integer}, variant, "Arg0 := bytes_to_fixed_size(Arg1, Arg2), returns Some(Arg1') if byte_size(Arg1) == Arg2, None otherwise. The type of Arg1' is bytes(Arg2) but the value is unchanged"}
|
||||||
|
, { 'INT_TO_BYTES', 16#b4, false, true, true, ?GAS(10), [a, a, a], int_to_bytes, {integer, integer}, bytes, "Arg0 := turn integer Arg1 into a byte array (big endian) length Arg2 (truncating if not fit)."}
|
||||||
|
, { 'STR_TO_BYTES', 16#b5, false, true, true, ?GAS(10), [a, a], str_to_bytes, {integer}, bytes, "Arg0 := turn string Arg1 into the corresponding byte array."}
|
||||||
|
, { 'NETWORK_ID', 16#b6, false, true, true, ?GAS(10), [a], network_id, {}, string, "Arg0 := The network_id of the chain."}
|
||||||
|
|
||||||
|
, { 'DBG_LOC', 16#f0, false, true, true, ?GAS(0), [a, a], dbg_loc, {string, integer}, none, "Debug Op: Execution location. Args = {file_name, line_num}" }
|
||||||
|
, { 'DBG_DEF', 16#f1, false, true, true, ?GAS(0), [a, a], dbg_def, {string, any}, none, "Debug Op: Define a variable. Args = {var_name, register}" }
|
||||||
|
, { 'DBG_UNDEF', 16#f2, false, true, true, ?GAS(0), [a, a], dbg_undef, {string, any}, none, "Debug Op: Undefine a variable. Args = {var_name, register}" }
|
||||||
|
, { 'DBG_CONTRACT', 16#f3, false, true, true, ?GAS(0), [a], dbg_contract, {string}, none, "Debug Op: Name the current contract. Args: {contract_name}"}
|
||||||
|
|
||||||
, { 'DEACTIVATE', 16#fa, false, true, true, ?GAS(10), [], deactivate, {}, none, "Mark the current contract for deactivation."}
|
, { 'DEACTIVATE', 16#fa, false, true, true, ?GAS(10), [], deactivate, {}, none, "Mark the current contract for deactivation."}
|
||||||
, { 'ABORT', 16#fb, true, true, true, ?GAS(10), [a], abort, {string}, none, "Abort execution (dont use all gas) with error message in Arg0."}
|
, { 'ABORT', 16#fb, true, true, true, ?GAS(10), [a], abort, {string}, none, "Abort execution (dont use all gas) with error message in Arg0."}
|
||||||
, { 'EXIT', 16#fc, true, true, true, ?GAS(10), [a], exit, {string}, none, "Abort execution (use upp all gas) with error message in Arg0."}
|
, { 'EXIT', 16#fc, true, true, true, ?GAS(10), [a], exit, {string}, none, "Abort execution (use upp all gas) with error message in Arg0."}
|
||||||
@@ -778,50 +797,3 @@ gen_variant() ->
|
|||||||
3 -> "(| 2 | 0 | ( " ++ imm_arg() ++ ", " ++ imm_arg() ++ " ) |)"
|
3 -> "(| 2 | 0 | ( " ++ imm_arg() ++ ", " ++ imm_arg() ++ " ) |)"
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
%% TODO: add gas cost and end_bb/in_auth?
|
|
||||||
generate_documentation(Filename) ->
|
|
||||||
{ok, File} = file:open(Filename, [write]),
|
|
||||||
Instructions = lists:flatten([gen_doc(Op)++"\n" || Op <- get_ops()]),
|
|
||||||
io:format(File,
|
|
||||||
"### Operations\n\n"
|
|
||||||
"| OpCode | Name | Args | Description |\n"
|
|
||||||
"| --- | --- | --- | --- |\n"
|
|
||||||
"~s"
|
|
||||||
, [Instructions]),
|
|
||||||
io:format(File, "\n", []),
|
|
||||||
file:close(File).
|
|
||||||
|
|
||||||
gen_doc(#{ opname := Name
|
|
||||||
, opcode := OpCode
|
|
||||||
, arity := _Arity
|
|
||||||
, end_bb := _EndBB
|
|
||||||
, format := FateFormat
|
|
||||||
, macro := _Macro
|
|
||||||
, type_name := _TypeName
|
|
||||||
, doc := Doc
|
|
||||||
, gas := _Gas
|
|
||||||
, type := _Type
|
|
||||||
, constructor := _Constructor
|
|
||||||
, constructor_type := _ConstructorType
|
|
||||||
}) ->
|
|
||||||
Arguments =
|
|
||||||
case FateFormat of
|
|
||||||
[] -> "";
|
|
||||||
_ -> lists:join(" ",
|
|
||||||
[format_arg_doc(A) ||
|
|
||||||
A <-
|
|
||||||
lists:zip(FateFormat,
|
|
||||||
lists:seq(0,length(FateFormat)-1))])
|
|
||||||
end,
|
|
||||||
io_lib:format("| 0x~.16b | ~w | ~s | ~s |\n",
|
|
||||||
[ OpCode
|
|
||||||
, Name
|
|
||||||
, Arguments
|
|
||||||
, Doc]).
|
|
||||||
|
|
||||||
format_arg_doc({a, N}) -> io_lib:format("Arg~w", [N]);
|
|
||||||
format_arg_doc({is,_N}) -> "Identifier";
|
|
||||||
format_arg_doc({ii,_N}) -> "Integer";
|
|
||||||
format_arg_doc({li,_N}) -> "[Integers]";
|
|
||||||
format_arg_doc({t,_N}) -> "Type".
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{application, aebytecode,
|
{application, aebytecode,
|
||||||
[{description, "Bytecode definitions, serialization and deserialization for aeternity."},
|
[{description, "Bytecode definitions, serialization and deserialization for aeternity."},
|
||||||
{vsn, "2.1.0"},
|
{vsn, "3.4.0"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications,
|
{applications,
|
||||||
[kernel,
|
[kernel,
|
||||||
|
|||||||
Reference in New Issue
Block a user