Compare commits

..

46 Commits

Author SHA1 Message Date
Hans Svensson 05dfd7ffc7 Merge pull request #104 from aeternity/iris_gas_prices_adjustment
BYTECODE_HASH should be cheaper
2021-04-30 12:16:57 +02:00
Hans Svensson 7d4f3fed10 BYTECODE_HASH should be cheaper 2021-04-30 12:05:17 +02:00
Hans Svensson 4c0906398e Merge pull request #103 from aeternity/iris_gas_prices_adjustment
Revert CALL_R/GR/PGR gas changes
2021-04-30 09:45:18 +02:00
Hans Svensson 1bb24a485b Revert CALL_R/GR/PGR gas changes 2021-04-30 09:14:03 +02:00
Hans Svensson abd12b599f Merge pull request #102 from aeternity/iris_gas_prices_adjustment
Adjust FATE OPs gas price for Iris
2021-04-29 20:31:58 +02:00
Hans Svensson e4d46bd17a Adjust FATE OPs gas price for Iris 2021-04-29 15:16:48 +02:00
Hans Svensson 142502179c Merge pull request #101 from aeternity/protocol_bound_gas_price
Add mechanism for pricing FATE ops differently in IRIS
2021-04-28 15:10:43 +02:00
Hans Svensson 0318c60caf Add mechanism for pricing FATE ops differently in IRIS 2021-04-28 13:18:56 +02:00
Radosław Rowicki eb8810a783 Merge pull request #100 from aeternity/call-fee
Call fee
2021-04-27 09:50:31 +02:00
radrow 69110b2ee8 Rename TX_FEE to just FEE 2021-04-26 15:19:59 +02:00
radrow b0263319e3 Add TX_FEE 2021-04-26 14:23:20 +02:00
Artur Puzio 951db9f384 Merge pull request #99 from aeternity/revert-string-compare
Restore old binary and string comparison
2021-04-14 11:25:35 +00:00
Artur Puzio fe11ee31ab Restore old binary and string comparison
Binary and string comparison is under consensus

This partially reverts commit d16f9a9579.
2021-04-14 13:07:24 +02:00
Artur Puzio 0c010cfd0d Merge pull request #98 from aeternity/bring-sanity-to-compare
Bring sanity to compare
2021-04-07 13:27:01 +00:00
Artur Puzio d16f9a9579 Compare binaries and strings in standard manner
By first different byte, if one is prefix of another than prefix is
smaller
2021-04-07 11:31:02 +02:00
Artur Puzio f53f61e554 Comparison cleanup
- more verbose comparison function
- adjusted bytes and bytecode comparison for consistency
- fixed oracle query type
2021-04-07 11:30:53 +02:00
Radosław Rowicki 84e246d9da Merge pull request #94 from aeternity/factories
Add CREATE, CLONE and BYTECODE_HASH opcodes. Add bytecode typerep and datatype
2021-03-31 09:45:57 +02:00
radrow 1498e1cdc2 Remove CREATE_G 2021-03-24 14:41:44 +01:00
radrow 41b80b5d44 Gas versions 2021-03-24 14:22:09 +01:00
radrow fd9f15789c Fix test 2021-03-24 13:13:05 +01:00
radrow 8d447e803b CREATE and CLONE now push to the stack 2021-03-23 20:37:36 +01:00
radrow 83616392e1 Add CREATE, CLONE and BYTECODE_HASH opcodes. Add bytecode typerep and datatype.
Format fixes. Changed type of BLOCKHASH to variant.

Fixed number of parameters to include target

Changed op args

Protected create

Make new type store a SERIALIZED CODE (instead of RAW BYTECODE)

Fix test

Format

Make create not protected

format

Fix serialization of fate_code type

Align

Add rebar3

Use shipped rebar3

Fix serialization, test

Fix tests

Rename fate_code to contract_bytearray

Update README
2021-03-23 12:27:35 +01:00
Artur Puzio 135a27c992 Merge pull request #95 from aeternity/precalculate-init-id
Avoid unnecessery calls to eblake2
2021-03-23 08:57:11 +00:00
Artur Puzio b30f8a2bfd Avoid unnecessery calls to eblake2
We frequently need identifier of init function. Store it precalculated
in headers.
2021-03-23 09:27:25 +01:00
Artur Puzio 9d81358daf Merge pull request #96 from aeternity/rebar
Use aeternity rebar
2021-03-23 08:24:40 +00:00
radrow 5493bece71 Include rebar 2021-03-22 17:28:21 +01:00
radrow c90bb0c6db Use aeternity rebar 2021-03-22 17:27:42 +01:00
Hans Svensson 7f0d3090d4 Merge pull request #93 from aeternity/GH-203-protected-calls
Add protected call FATE instruction
2020-03-02 12:07:50 +01:00
Ulf Norell e5164330b0 Get valid opcodes from instruction list 2020-03-02 08:48:29 +01:00
Ulf Norell e5bdf583f9 Add protected remote call instruction 2020-03-02 08:40:04 +01:00
Ulf Norell 719bf26a38 Set store map size theshold to 0 ifdef TEST 2020-03-02 08:37:30 +01:00
Hans Svensson 5ef5d455b4 Merge pull request #92 from aeternity/aesophia/GH-176-more_string_functions
Char.to_upper/lower isn't feasible do String.to_upper/lower
2020-02-26 18:22:03 +01:00
Hans Svensson 36559842ae Char.to_upper/lower isn't feasible do String.to_upper/lower 2020-02-26 14:06:50 +01:00
Hans Svensson 94d0b984e9 Merge pull request #91 from aeternity/aesophia/GH-176-more_string_functions
Aesophia/gh 176 more string functions
2020-02-25 09:01:17 +01:00
Hans Svensson 167bfcc0e6 Add String.to/from_list Char.to/from_int and Char.to_upper/lower as operations 2020-02-24 10:09:23 +01:00
Hans Svensson 2f11143e5a Align operators (missing spaces) 2020-02-24 10:08:48 +01:00
Hans Svensson ff5a4c7dd5 Merge pull request #90 from aeternity/GH-202-Auth_tx_introspection
Add AUTH_TX to FATE operations
2020-02-11 14:18:39 +01:00
Hans Svensson 370c7387a9 Add AUTH_TX to FATE operations 2020-02-11 09:34:48 +01:00
Hans Svensson 8a9c9dec95 Merge pull request #89 from aeternity/GH-188-AENS_lookup
Add AENS_LOOKUP and ORACLE_EXPIRY as FATE operations
2020-02-03 14:24:44 +01:00
Hans Svensson 4565188c6a Add AENS_LOOKUP and ORACLE_EXPIRY as FATE operations 2020-02-03 13:19:08 +01:00
Hans Svensson 059d114a06 Merge pull request #88 from aeternity/GH-2850-add_fancy_crypto_bls12_381
Add FATE-ops for BLS12-381
2019-11-29 15:27:13 +01:00
Hans Svensson e4b09d7c5c Add FATE-ops for BLS12-381 2019-11-27 09:06:20 +01:00
skkw b040dccdef Merge pull request #87 from aeternity/PT-158904718-aens-update-sophia
fixed documenting of AENS_UPDATE type
2019-11-18 16:20:16 +01:00
skkw 211ee74df2 fixed documenting of AENS_UPDATE type 2019-11-18 16:00:36 +01:00
skkw 38f4f0ecd7 Merge pull request #81 from aeternity/PT-158904718-aens-update-sophia
add support for AENS.update call
2019-11-12 14:17:11 +01:00
skkw f184abeb87 add support for AENS.update call 2019-09-10 15:46:04 +02:00
18 changed files with 331 additions and 440 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
GENERATED_SRC = src/aeb_fate_opcodes.erl src/aeb_fate_ops.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl src/aeb_fate_pp.erl
GENERATOR_DEPS = ebin/aeb_fate_generate_ops.beam src/aeb_fate_asm_scan.template
REBAR ?= rebar3
REBAR ?= ./rebar3
all: local
+6 -3
View File
@@ -1,7 +1,7 @@
# aebytecode
An library and stand alone assembler for aeternity bytecode.
A library and stand alone assembler for aeternity bytecode.
This version supports Aevm bytecode and Fate bytecode.
This version supports AEVM bytecode and FATE bytecode.
## Build
@@ -19,7 +19,7 @@ Fate code exists in 3 formats:
3. Internal. This is an Erlang representation of fate code
Used by this particular engin implementation.
This library handles all tree representations.
This library handles all three representations.
The byte code format is described in a separate document.
The internal format is described in a separate document.
The text representation is described below.
@@ -107,6 +107,9 @@ Immediate values can be of 10 types:
10. Bytes: #{base64char}+
`#AQIDCioLFQ==`
11. Contract bytearray (code of another smart contract)
`@cb_+PJGA6A4Fz4T2LHV5knITCldR3rqO7HrXO2zhOAR9JWNbhf8Q8C4xbhx/gx8JckANwAXfQBVACAAAP4vhlvZADcABwECgv5E1kQfADcBBzcACwAWMBReAHMAFjBvJFMAFjBvggOoFAAUABQSggABAz/+tIwWhAA3AAdTAAD+1jB5kAQ3AAcLAAD+6MRetgA3AQc3ABoGggABAz+4TS8GEQx8JclFY2FsbGVyX2lzX2NyZWF0b3IRL4Zb2Q1nZXQRRNZEHxFpbml0EbSMFoQdYmFsYW5jZRHWMHmQFXZhbHVlEejEXrYNc2V0gi8AhTQuMy4wAUqQ8s4=`
Where
+10
View File
@@ -18,6 +18,7 @@
-define(FATE_TUPLE_T, {tuple, tuple()}).
-define(FATE_BITS_T, {bits, integer()}).
-define(FATE_TYPEREP_T, {typerep, fate_type_type()}).
-define(FATE_CONTRACT_BYTEARRAY_T, {contract_bytearray, binary()}).
-define(IS_FATE_INTEGER(X), (is_integer(X))).
-define(IS_FATE_LIST(X), (is_list(X))).
@@ -45,6 +46,8 @@
))).
-define(IS_FATE_BOOLEAN(X), is_boolean(X)).
-define(IS_FATE_TYPEREP(X), (is_tuple(X) andalso tuple_size(X) =:= 2 andalso element(1, X) =:= typerep)).
-define(IS_FATE_CONTRACT_BYTEARRAY(X), (is_tuple(X) andalso tuple_size(X) =:= 2 andalso element(1, X) =:= contract_bytearray
andalso is_binary(element(2, X)))).
-define(FATE_UNIT, {tuple, {}}).
-define(FATE_TUPLE(T), {tuple, T}).
@@ -75,6 +78,7 @@
-define(FATE_STORE_MAP_ID(X), (element(3, X))).
-define(FATE_MAP_SIZE(X), (map_size(X))).
-define(FATE_STRING_SIZE(X), (byte_size(X))).
-define(FATE_CONTRACT_BYTEARRAY_SIZE(X), (byte_size(X))).
-define(FATE_TRUE, true).
-define(FATE_FALSE, false).
-define(FATE_NIL, []).
@@ -82,8 +86,14 @@
-define(FATE_EMPTY_STRING, <<>>).
-define(FATE_STRING(S), S).
-define(FATE_VARIANT(Arity, Tag,T), {variant, Arity, Tag, T}).
-define(FATE_CONTRACT_BYTEARRAY(B), {contract_bytearray, B}).
% Result of aeb_fate_code:symbol_identifier(<<"init">>).
% Stored here to avoid repeated calls to eblake2
-define(FATE_INIT_ID, <<68,214,68,31>>).
-define(MAKE_FATE_INTEGER(X), X).
-define(MAKE_FATE_LIST(X), X).
-define(MAKE_FATE_MAP(X), X).
-define(MAKE_FATE_STRING(X), X).
-define(MAKE_FATE_CONTRACT_BYTEARRAY(X), {contract_bytearray, X}).
+1
View File
@@ -9,3 +9,4 @@
-define(TYPEREP_TYPEREP_TAG, 5).
-define(TYPEREP_MAP_TAG, 6).
-define(TYPEREP_FUN_TAG, 7).
-define(TYPEREP_CONTRACT_BYTEARRAY_TAG,8).
+1 -1
View File
@@ -77,7 +77,7 @@ prop_opcodes() ->
valid_opcodes() ->
lists:seq(0, 16#80) ++ lists:seq(16#fa, 16#fd).
[ Op || #{opcode := Op} <- aeb_fate_generate_ops:get_ops() ].
fate_code(Failure) ->
Executable
BIN
View File
Binary file not shown.
+4
View File
@@ -281,6 +281,10 @@ to_bytecode([{bytes,_line, Value}|Rest],
to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_bytes(Value)}|Code],
Opts);
to_bytecode([{contract_bytearray,_line, FateCode}|Rest], Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_contract_bytearray(FateCode)}|Code],
Opts);
to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) ->
{Env2, Id} = insert_symbol(list_to_binary(ID), Env),
to_bytecode(Rest, Address, Env2, [{immediate, Id}|Code], Opts);
+10 -2
View File
@@ -16,7 +16,9 @@ BASE58 = [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]
BASE64 = [A-Za-z0-9+/=]
INT = {DIGIT}+
HEX = 0x{HEXDIGIT}+
OBJECT = @[a-z][a-z]_{BASE58}+
OBJ_PFX = (ak|ct|ok|oq|ch|sg)
OBJECT = @{OBJ_PFX}_{BASE58}+
CODE = @cb_{BASE64}+
BYTES = #{BASE64}+
WS = [\000-\s]
ID = {LOWER}[a-zA-Z0-9_]*
@@ -37,6 +39,8 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
{BYTES} :
{token, {bytes, TokenLine, parse_hash(TokenChars)}}.
{CODE} :
{token, {contract_bytearray, TokenLine, parse_contract_bytearray(TokenChars)}}.
{OBJECT} :
{token, {object, TokenLine, parse_object(TokenChars)}}.
{ID} :
@@ -107,10 +111,14 @@ parse_arg("arg" ++ N) -> list_to_integer(N).
parse_var("var" ++ N) -> list_to_integer(N).
parse_hash("#" ++ Chars) ->
base64:decode(Chars).
parse_contract_bytearray("@" ++ Chars) ->
case aeser_api_encoder:decode(unicode:characters_to_binary(Chars)) of
{contract_bytearray, Bin} -> Bin
end.
parse_object([_|Chars]) ->
case aeser_api_encoder:decode(unicode:characters_to_binary(Chars)) of
{account_pubkey, Bin} -> {address, Bin};
+2 -3
View File
@@ -95,9 +95,8 @@ insert_annotation(comment =_Type, Line, Comment, FCode) ->
strip_init_function(#fcode{ functions = Funs,
symbols = Syms } = FCode) ->
Id = symbol_identifier(<<"init">>),
Funs1 = maps:remove(Id, Funs),
Syms1 = maps:remove(Id, Syms),
Funs1 = maps:remove(?FATE_INIT_ID, Funs),
Syms1 = maps:remove(?FATE_INIT_ID, Syms),
FCode#fcode{ functions = Funs1, symbols = Syms1 }.
%%%===================================================================
+49 -23
View File
@@ -17,11 +17,13 @@
-type fate_signature() :: ?FATE_BYTES_T(64).
-type fate_contract() :: ?FATE_CONTRACT_T.
-type fate_oracle() :: ?FATE_ORACLE_T.
-type fate_oracle_q() :: ?FATE_ORACLE_Q_T.
-type fate_channel() :: ?FATE_CHANNEL_T.
-type fate_variant() :: ?FATE_VARIANT_T.
-type fate_tuple() :: ?FATE_TUPLE_T.
-type fate_bits() :: ?FATE_BITS_T.
-type fate_typerep() :: ?FATE_TYPEREP_T.
-type fate_contract_bytearray() :: ?FATE_CONTRACT_BYTEARRAY_T.
-type fate_type_type() :: integer
| boolean
@@ -33,10 +35,12 @@
| signature
| contract
| oracle
| oracle_query
| channel
| bits
| string
| {variant, [fate_type_type()]}.
| {variant, [fate_type_type()]}
| contract_bytearray.
-type fate_type() ::
@@ -52,11 +56,13 @@
| fate_signature()
| fate_contract()
| fate_oracle()
| fate_oracle_q()
| fate_channel()
| fate_variant()
| fate_map()
| fate_bits()
| fate_typerep().
| fate_typerep()
| fate_contract_bytearray().
-export_type([fate_type/0
, fate_boolean/0
@@ -99,6 +105,7 @@
, make_bits/1
, make_unit/0
, make_typerep/1
, make_contract_bytearray/1
]).
-export([
elt/2
@@ -130,6 +137,7 @@ make_string(S) when is_list(S) ->
?FATE_STRING(iolist_to_binary(S));
make_string(S) when is_binary(S) -> ?FATE_STRING(S).
make_typerep(T) -> ?FATE_TYPEREP(T).
make_contract_bytearray(B) -> ?FATE_CONTRACT_BYTEARRAY(B).
%% Tag points to the selected variant (zero based)
%% The arity of this variant is read from the list of provided arities
@@ -179,12 +187,14 @@ format(?FATE_CONTRACT(X)) ->
["@", aeser_api_encoder:encode(contract_pubkey, X)];
format(?FATE_ORACLE(X)) ->
["@", aeser_api_encoder:encode(oracle_pubkey, X)];
format(?FATE_ORACLE_Q(X)) ->
format(?FATE_ORACLE_Q(X)) ->
["@", aeser_api_encoder:encode(oracle_query_id, X)];
format(?FATE_CHANNEL(X)) ->
["@", aeser_api_encoder:encode(channel, X)];
format(?FATE_TYPEREP(X)) ->
["'", io_lib:format("~p", [X])];
format(?FATE_CONTRACT_BYTEARRAY(B)) ->
["@", aeser_api_encoder:encode(contract_bytearray, B)];
format(V) -> exit({not_a_fate_type, V}).
format_bits(0, Acc) -> Acc;
@@ -210,6 +220,7 @@ format_kvs(List) ->
%% Total order of FATE terms.
%% Integers < Booleans < Address < Channel < Contract < Oracle
%% < Hash < Signature < Bits < String < Tuple < Map < List < Variant
%% < Oracle query < FATE code
-define(ORD_INTEGER , 0).
-define(ORD_BOOLEAN , 1).
-define(ORD_ADDRESS , 2).
@@ -224,6 +235,7 @@ format_kvs(List) ->
-define(ORD_LIST , 11).
-define(ORD_VARIANT , 12).
-define(ORD_ORACLE_Q , 13).
-define(ORD_CONTRACT_BYTEARRAY , 14).
-spec ordinal(fate_type()) -> integer().
ordinal(T) when ?IS_FATE_INTEGER(T) -> ?ORD_INTEGER;
@@ -239,7 +251,8 @@ ordinal(T) when ?IS_FATE_TUPLE(T) -> ?ORD_TUPLE;
ordinal(T) when ?IS_FATE_MAP(T) -> ?ORD_MAP;
ordinal(T) when ?IS_FATE_LIST(T) -> ?ORD_LIST;
ordinal(T) when ?IS_FATE_VARIANT(T) -> ?ORD_VARIANT;
ordinal(T) when ?IS_FATE_ORACLE_Q(T) -> ?ORD_ORACLE_Q.
ordinal(T) when ?IS_FATE_ORACLE_Q(T) -> ?ORD_ORACLE_Q;
ordinal(T) when ?IS_FATE_CONTRACT_BYTEARRAY(T) -> ?ORD_CONTRACT_BYTEARRAY.
-spec lt(fate_type(), fate_type()) -> boolean().
@@ -267,17 +280,9 @@ lt(?ORD_BITS, A, B) when ?IS_FATE_BITS(A), ?IS_FATE_BITS(B) ->
true;
true -> BitsA < BitsB
end;
lt(?ORD_STRING,?FATE_STRING(A), ?FATE_STRING(B)) ->
SizeA = size(A),
SizeB = size(B),
case SizeA - SizeB of
0 -> A < B;
N -> N < 0
end;
lt(?ORD_TUPLE,?FATE_TUPLE(A), ?FATE_TUPLE(B)) ->
SizeA = size(A),
SizeB = size(B),
lt(?ORD_TUPLE, ?FATE_TUPLE(A), ?FATE_TUPLE(B)) ->
SizeA = tuple_size(A),
SizeB = tuple_size(B),
case SizeA - SizeB of
0 -> tuple_elements_lt(0, A, B, SizeA);
N -> N < 0
@@ -292,19 +297,15 @@ lt(?ORD_MAP, ?FATE_MAP_VALUE(A), ?FATE_MAP_VALUE(B)) ->
lt(?ORD_LIST, ?FATE_LIST_VALUE(_), ?FATE_LIST_VALUE([])) -> false;
lt(?ORD_LIST, ?FATE_LIST_VALUE([]), ?FATE_LIST_VALUE(_)) -> true;
lt(?ORD_LIST, ?FATE_LIST_VALUE([A|RA]), ?FATE_LIST_VALUE([B|RB])) ->
O1 = ordinal(A),
O2 = ordinal(B),
if O1 == O2 ->
if A == B -> lt(RA, RB);
true -> A < B
end;
true -> O1 < O2
if A == B -> lt(RA, RB);
true -> lt(A, B)
end;
lt(?ORD_VARIANT, ?FATE_VARIANT(AritiesA, TagA, TA),
?FATE_VARIANT(AritiesB, TagB, TB)) ->
if length(AritiesA) < length(AritiesB) -> true;
length(AritiesA) > length(AritiesB) -> false;
true ->
% Compare element by element consistent with Erlang compare
if AritiesA < AritiesB -> true;
AritiesA > AritiesB -> false;
true ->
@@ -314,7 +315,32 @@ lt(?ORD_VARIANT, ?FATE_VARIANT(AritiesA, TagA, TA),
end
end
end;
lt(_, A, B) -> A < B.
lt(?ORD_ADDRESS, ?FATE_ADDRESS(A), ?FATE_ADDRESS(B)) ->
A < B;
lt(?ORD_CHANNEL, ?FATE_CHANNEL(A), ?FATE_CHANNEL(B)) ->
A < B;
lt(?ORD_CONTRACT, ?FATE_CONTRACT(A), ?FATE_CONTRACT(B)) ->
A < B;
lt(?ORD_ORACLE, ?FATE_ORACLE(A), ?FATE_ORACLE(B)) ->
A < B;
lt(?ORD_ORACLE_Q, ?FATE_ORACLE_Q(A), ?FATE_ORACLE_Q(B)) ->
A < B;
lt(?ORD_STRING, ?FATE_STRING(A), ?FATE_STRING(B)) ->
compare_bytes(A, B);
lt(?ORD_BYTES, ?FATE_BYTES(A), ?FATE_BYTES(B)) ->
compare_bytes(A, B);
lt(?ORD_CONTRACT_BYTEARRAY, ?FATE_CONTRACT_BYTEARRAY(A), ?FATE_CONTRACT_BYTEARRAY(B)) ->
compare_bytes(A, B).
% Shorter comes first
% On same length compare by first different bit
compare_bytes(A, B) ->
SizeA = byte_size(A),
SizeB = byte_size(B),
case SizeA - SizeB of
0 -> A < B;
N -> N < 0
end.
tuple_elements_lt(N,_A,_B, N) ->
false;
+21 -7
View File
@@ -63,7 +63,7 @@
-define(SHORT_STRING , 2#01). %% xxxxxx 01 | [bytes] - when 0 < xxxxxx:size < 64
%% 11 Set below
-define(SHORT_LIST , 2#0011). %% xxxx 0011 | [encoded elements] when 0 < length < 16
%% xxxx 0111
%% 0111 Set below
-define(TYPE_INTEGER , 2#00000111). %% 0000 0111 - Integer typedef
-define(TYPE_BOOLEAN , 2#00010111). %% 0001 0111 - Boolean typedef
-define(TYPE_LIST , 2#00100111). %% 0010 0111 | Type
@@ -74,7 +74,7 @@
-define(TYPE_STRING , 2#01110111). %% 0111 0111 - string typedef
-define(TYPE_VARIANT , 2#10000111). %% 1000 0111 | [Arities] | [Type]
-define(TYPE_BYTES , 2#10010111). %% 1001 0111 - Bytes typedef
%% 1010 0111
-define(TYPE_CONTRACT_BYTEARRAY,2#10100111). %% 1010 0111 - Fate code typedef
%% 1011 0111
%% 1100 0111
%% 1101 0111
@@ -90,7 +90,8 @@
-define(EMPTY_STRING , 2#01011111). %% 0101 1111
-define(POS_BIG_INT , 2#01101111). %% 0110 1111 | RLP encoded (integer - 64)
-define(FALSE , 2#01111111). %% 0111 1111
%% %% 1000 1111 - FREE (Possibly for bytecode in the future.)
-define(
CONTRACT_BYTEARRAY, 2#10001111). %% 1000 1111
-define(OBJECT , 2#10011111). %% 1001 1111 | ObjectType | RLP encoded Array
-define(VARIANT , 2#10101111). %% 1010 1111 | [encoded arities] | encoded tag | [encoded values]
-define(MAP_ID , 2#10111111). %% 1011 1111 | RLP encoded integer (store map id)
@@ -126,7 +127,8 @@
X =:= ?TYPE_BYTES orelse
X =:= ?TYPE_MAP orelse
X =:= ?TYPE_STRING orelse
X =:= ?TYPE_VARIANT)).
X =:= ?TYPE_VARIANT orelse
X =:= ?TYPE_CONTRACT_BYTEARRAY)).
%% --------------------------------------------------
%% Serialize
@@ -216,7 +218,11 @@ serialize(?FATE_VARIANT(Arities, Tag, Values)) ->
end
end;
serialize(?FATE_TYPEREP(T)) ->
iolist_to_binary(serialize_type(T)).
iolist_to_binary(serialize_type(T));
serialize(?FATE_CONTRACT_BYTEARRAY(B)) ->
<<?CONTRACT_BYTEARRAY,
(serialize_integer(?FATE_CONTRACT_BYTEARRAY_SIZE(B)))/binary
, B/binary>>.
%% -----------------------------------------------------
@@ -247,7 +253,8 @@ serialize_type({variant, ListOfVariants}) ->
Size = length(ListOfVariants),
if Size < 256 ->
[?TYPE_VARIANT, Size | [serialize_type(T) || T <- ListOfVariants]]
end.
end;
serialize_type(contract_bytearray) -> [?TYPE_CONTRACT_BYTEARRAY].
-spec deserialize_type(binary()) -> {aeb_fate_data:fate_type_type(), binary()}.
@@ -282,7 +289,8 @@ deserialize_type(<<?TYPE_STRING, Rest/binary>>) ->
{string, Rest};
deserialize_type(<<?TYPE_VARIANT, Size, Rest/binary>>) ->
{Variants, Rest2} = deserialize_variants(Size, Rest, []),
{{variant, Variants}, Rest2}.
{{variant, Variants}, Rest2};
deserialize_type(<<?TYPE_CONTRACT_BYTEARRAY, Rest/binary>>) -> {contract_bytearray, Rest}.
deserialize_variants(0, Rest, Variants) ->
{lists:reverse(Variants), Rest};
@@ -377,6 +385,12 @@ deserialize2(<<?LONG_STRING, Rest/binary>>) ->
String = binary:part(Rest2, 0, Size),
Rest3 = binary:part(Rest2, byte_size(Rest2), - (byte_size(Rest2) - Size)),
{?MAKE_FATE_STRING(String), Rest3};
deserialize2(<<?CONTRACT_BYTEARRAY, Rest/binary>>) ->
{Size, Rest2} = deserialize_one(Rest),
true = is_integer(Size) andalso Size >= 0,
FateCode = binary:part(Rest2, 0, Size),
Rest3 = binary:part(Rest2, byte_size(Rest2), - (byte_size(Rest2) - Size)),
{?MAKE_FATE_CONTRACT_BYTEARRAY(FateCode), Rest3};
deserialize2(<<S:6, ?SHORT_STRING:2, Rest/binary>>) ->
String = binary:part(Rest, 0, S),
Rest2 = binary:part(Rest, byte_size(Rest), - (byte_size(Rest) - S)),
+186 -134
View File
@@ -39,152 +39,204 @@ check_numbering(N, [T|Rest]) ->
end;
check_numbering(_, []) -> true.
-define(LIMA_PROTOCOL_VSN, 4).
-define(IRIS_PROTOCOL_VSN, 5).
-define(GAS(A), A).
-define(GAS_IRIS(A, B), [{?IRIS_PROTOCOL_VSN, B}, {?LIMA_PROTOCOL_VSN, A}]).
%% TODO: Some real gas numbers...
ops_defs() ->
%% Opname, Opcode, end_bb, in_auth offchain, gas, format, Constructor, ArgType, ResType, Documentation
[ { 'RETURN', 16#00, true, true, true, 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, 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, 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_R', 16#03, true, false, true, 100, [a,is,a,a,a], call_r, {contract, string, typerep, typerep, integer}, any, "Remote call to contract Arg0 and function Arg1 of type Arg2 => Arg3 with value Arg4. The types of the arguments has to match the argument types of the function."}
, { 'CALL_T', 16#04, true, true, true, 10, [a], call_t, {string}, any, "Tail call to function Arg0. The types of the arguments has to match the argument typs of the function. And the return type of the called function has to match the type of the current function."}
, { 'CALL_GR', 16#05, true, false, true, 100, [a,is,a,a,a,a], call_gr, {contract, string, typerep, typerep, integer, integer}, any, "Remote call with gas cap in Arg4. Otherwise as CALL_R."}
, { 'JUMP', 16#06, true, true, true, 10, [ii], jump, {integer}, none, "Jump to a basic block. The basic block has to exist in the current function."}
, { 'JUMPIF', 16#07, true, true, true, 10, [a,ii], jumpif, {boolean, integer}, none, "Conditional jump to a basic block. If Arg0 then jump to Arg1."}
, { 'SWITCH_V2', 16#08, true, true, true, 10, [a,ii,ii], switch, {variant, integer, ingeger}, none, "Conditional jump to a basic block on variant tag."}
, { 'SWITCH_V3', 16#09, true, true, true, 10, [a,ii,ii,ii], switch, {variant, integer, integer, ingeger}, none, "Conditional jump to a basic block on variant tag."}
, { 'SWITCH_VN', 16#0a, true, true, true, 10, [a, li], switch, {variant, {list, integer}}, none, "Conditional jump to a basic block on variant tag."}
, { 'CALL_VALUE', 16#0b, false, true, true, 10, [a], call_value, {}, integer, "The value sent in the current remote call."}
, { 'PUSH', 16#0c, false, true, true, 10, [a], push, {any}, any, "Push argument to stack."}
, { 'DUPA', 16#0d, false, true, true, 10, [], dup, {any}, any, "Duplicate top of stack."}
, { 'DUP', 16#0e, false, true, true, 10, [a], dup, {any}, any, "push Arg0 stack pos on top of stack."}
, { 'POP', 16#0f, false, true, true, 10, [a], pop, {integer}, integer, "Arg0 := top of stack."}
, { 'INCA', 16#10, false, true, true, 10, [], inc, {integer}, integer, "Increment accumulator."}
, { 'INC', 16#11, false, true, true, 10, [a], inc, {integer}, integer, "Increment argument."}
, { 'DECA', 16#12, false, true, true, 10, [], dec, {integer}, integer, "Decrement accumulator."}
, { 'DEC', 16#13, false, true, true, 10, [a], dec, {integer}, integer, "Decrement argument."}
, { 'ADD', 16#14, false, true, true, 10, [a,a,a], add, {integer, integer}, integer, "Arg0 := Arg1 + Arg2."}
, { 'SUB', 16#15, false, true, true, 10, [a,a,a], sub, {integer, integer}, integer, "Arg0 := Arg1 - Arg2."}
, { 'MUL', 16#16, false, true, true, 10, [a,a,a], mul, {integer, integer}, integer, "Arg0 := Arg1 * Arg2."}
, { 'DIV', 16#17, false, true, true, 10, [a,a,a], divide, {integer, integer}, integer, "Arg0 := Arg1 / Arg2."}
, { 'MOD', 16#18, false, true, true, 10, [a,a,a], modulo, {integer, integer}, integer, "Arg0 := Arg1 mod Arg2."}
, { 'POW', 16#19, false, true, true, 10, [a,a,a], pow, {integer, integer}, integer, "Arg0 := Arg1 ^ Arg2."}
, { 'STORE', 16#1a, false, true, true, 10, [a,a], store, {any}, any, "Arg0 := Arg1."}
, { 'SHA3', 16#1b, false, true, true, 100, [a,a], sha3, {any}, hash, "Arg0 := sha3(Arg1)."}
, { 'SHA256', 16#1c, false, true, true, 100, [a,a], sha256, {any}, hash, "Arg0 := sha256(Arg1)."}
, { 'BLAKE2B', 16#1d, false, true, true, 100, [a,a], blake2b, {any}, hash, "Arg0 := blake2b(Arg1)."}
, { 'LT', 16#1e, false, true, true, 10, [a,a,a], lt, {integer, integer}, boolean, "Arg0 := Arg1 < Arg2."}
, { 'GT', 16#1f, false, true, true, 10, [a,a,a], gt, {integer, integer}, boolean, "Arg0 := Arg1 > Arg2."}
, { 'EQ', 16#20, false, true, true, 10, [a,a,a], eq, {integer, integer}, boolean, "Arg0 := Arg1 = Arg2."}
, { 'ELT', 16#21, false, true, true, 10, [a,a,a], elt, {integer, integer}, boolean, "Arg0 := Arg1 =< Arg2."}
, { 'EGT', 16#22, false, true, true, 10, [a,a,a], egt, {integer, integer}, boolean, "Arg0 := Arg1 >= Arg2."}
, { 'NEQ', 16#23, false, true, true, 10, [a,a,a], neq, {integer, integer}, boolean, "Arg0 := Arg1 /= Arg2."}
, { 'AND', 16#24, false, true, true, 10, [a,a,a], and_op, {boolean, boolean}, boolean, "Arg0 := Arg1 and Arg2."}
, { 'OR', 16#25, false, true, true, 10, [a,a,a], or_op, {boolean, boolean}, boolean, "Arg0 := Arg1 or Arg2."}
, { 'NOT', 16#26, false, true, true, 10, [a,a], not_op, {boolean}, boolean, "Arg0 := not Arg1."}
, { 'TUPLE', 16#27, false, true, true, 10, [a,ii], tuple, {integer}, tuple, "Arg0 := tuple of size = Arg1. Elements on stack."}
, { 'ELEMENT', 16#28, false, true, true, 10, [a,a,a], element_op, {integer, tuple}, any, "Arg1 := element(Arg2, Arg3)."}
, { 'SETELEMENT', 16#29, false, true, true, 10, [a,a,a,a], setelement, {integer, tuple, any}, tuple, "Arg0 := a new tuple similar to Arg2, but with element number Arg1 replaced by Arg3."}
, { 'MAP_EMPTY', 16#2a, false, true, true, 10, [a], map_empty, {}, map, "Arg0 := #{}."}
, { 'MAP_LOOKUP', 16#2b, false, true, true, 10, [a,a,a], map_lookup, {map, any}, any, "Arg0 := lookup key Arg2 in map Arg1."}
, { 'MAP_LOOKUPD', 16#2c, false, true, true, 10, [a,a,a,a], map_lookup, {map, any, any}, any, "Arg0 := lookup key Arg2 in map Arg1 if key exists in map otherwise Arg0 := Arg3."}
, { 'MAP_UPDATE', 16#2d, false, true, true, 10, [a,a,a,a], map_update, {map, any, any}, map, "Arg0 := update key Arg2 in map Arg1 with value Arg3."}
, { 'MAP_DELETE', 16#2e, false, true, true, 10, [a,a,a], map_delete, {map, any}, map, "Arg0 := delete key Arg2 from map Arg1."}
, { 'MAP_MEMBER', 16#2f, false, true, true, 10, [a,a,a], map_member, {map, any}, boolean, "Arg0 := true if key Arg2 is in map Arg1."}
, { 'MAP_FROM_LIST', 16#30, false, true, true, 10, [a,a], map_from_list, {{list, {tuple, [any, any]}}}, map, "Arg0 := make a map from (key, value) list in Arg1."}
, { 'MAP_SIZE', 16#31, false, true, true, 10, [a,a], map_size_, {map}, integer, "Arg0 := The size of the map Arg1."}
, { 'MAP_TO_LIST', 16#32, false, true, true, 10, [a,a], map_to_list, {map}, list, "Arg0 := The tuple list representation of the map Arg1."}
, { 'IS_NIL', 16#33, false, true, true, 10, [a,a], is_nil, {list}, boolean, "Arg0 := true if Arg1 == []."}
, { 'CONS', 16#34, false, true, true, 10, [a,a,a], cons, {any, list}, list, "Arg0 := [Arg1|Arg2]."}
, { 'HD', 16#35, false, true, true, 10, [a,a], hd, {list}, any, "Arg0 := head of list Arg1."}
, { 'TL', 16#36, false, true, true, 10, [a,a], tl, {list}, list, "Arg0 := tail of list Arg1."}
, { 'LENGTH', 16#37, false, true, true, 10, [a,a], length, {list}, integer, "Arg0 := length of list Arg1."}
, { 'NIL', 16#38, false, true, true, 10, [a], nil, {}, list, "Arg0 := []."}
, { 'APPEND', 16#39, false, true, true, 10, [a,a,a], append, {list, list}, list, "Arg0 := Arg1 ++ Arg2."}
, { 'STR_JOIN', 16#3a, false, true, true, 10, [a,a,a], str_join, {string, string}, string, "Arg0 := string Arg1 followed by string Arg2."}
, { 'INT_TO_STR', 16#3b, false, true, true, 100, [a,a], int_to_str, {integer}, string, "Arg0 := turn integer Arg1 into a string."}
, { 'ADDR_TO_STR', 16#3c, false, true, true, 100, [a,a], addr_to_str, {address}, string, "Arg0 := turn address Arg1 into a string."}
, { 'STR_REVERSE', 16#3d, false, true, true, 100, [a,a], str_reverse, {string}, string, "Arg0 := the reverse of string Arg1."}
, { 'STR_LENGTH', 16#3e, false, true, true, 10, [a,a], str_length, {string}, integer, "Arg0 := The length of the string Arg1."}
, { 'BYTES_TO_INT', 16#3f, false, true, true, 10, [a,a], bytes_to_int, {bytes}, integer, "Arg0 := bytes_to_int(Arg1)"}
, { 'BYTES_TO_STR', 16#40, false, true, true, 100, [a,a], bytes_to_str, {bytes}, string, "Arg0 := bytes_to_str(Arg1)"}
, { 'BYTES_CONCAT', 16#41, false, true, true, 10, [a,a,a], bytes_concat, {bytes, bytes}, bytes, "Arg0 := bytes_concat(Arg1, Arg2)"}
, { 'BYTES_SPLIT', 16#42, false, true, true, 10, [a,a,a], bytes_split, {bytes, integer}, bytes, "Arg0 := bytes_split(Arg2, Arg1), where Arg2 is the length of the first chunk."}
, { 'INT_TO_ADDR', 16#43, false, true, true, 10, [a,a], int_to_addr, {integer}, address, "Arg0 := turn integer Arg1 into an address."}
, { 'VARIANT', 16#44, false, true, true, 10, [a,a,a,a], variant, {integer, integer, integer}, variant, "Arg0 := create a variant of size Arg1 with the tag Arg2 (Arg2 < Arg1) and take Arg3 elements from the stack."}
, { 'VARIANT_TEST', 16#45, false, true, true, 10, [a,a,a], variant_test, {variant, integer}, boolean, "Arg0 := true if variant Arg1 has the tag Arg2."}
, { 'VARIANT_ELEMENT', 16#46, false, true, true, 10, [a,a,a], variant_element, {variant, integer}, any, "Arg0 := element number Arg2 from variant Arg1."}
, { 'BITS_NONEA', 16#47, false, true, true, 10, [], bits_none, {}, bits, "push an empty bitmap on the stack."}
, { 'BITS_NONE', 16#48, false, true, true, 10, [a], bits_none, {}, bits, "Arg0 := empty bitmap."}
, { 'BITS_ALLA', 16#49, false, true, true, 10, [], bits_all, {}, bits, "push a full bitmap on the stack."}
, { 'BITS_ALL', 16#4a, false, true, true, 10, [a], bits_all, {}, bits, "Arg0 := full bitmap."}
, { 'BITS_ALL_N', 16#4b, false, true, true, 10, [a,a], bits_all_n, {integer}, bits, "Arg0 := bitmap with Arg1 bits set."}
, { 'BITS_SET', 16#4c, false, true, true, 10, [a,a,a], bits_set, {bits, integer}, bits, "Arg0 := set bit Arg2 of bitmap Arg1."}
, { 'BITS_CLEAR', 16#4d, false, true, true, 10, [a,a,a], bits_clear, {bits, integer}, bits, "Arg0 := clear bit Arg2 of bitmap Arg1."}
, { 'BITS_TEST', 16#4e, false, true, true, 10, [a,a,a], bits_test, {bits, integer}, boolean, "Arg0 := true if bit Arg2 of bitmap Arg1 is set."}
, { 'BITS_SUM', 16#4f, false, true, true, 10, [a,a], bits_sum, {bits}, integer, "Arg0 := sum of set bits in bitmap Arg1. Exception if infinit bitmap."}
, { 'BITS_OR', 16#50, false, true, true, 10, [a,a,a], bits_or, {bits, bits}, bits, "Arg0 := Arg1 v Arg2."}
, { 'BITS_AND', 16#51, false, true, true, 10, [a,a,a], bits_and, {bits, bits}, bits, "Arg0 := Arg1 ^ Arg2."}
, { 'BITS_DIFF', 16#52, false, true, true, 10, [a,a,a], bits_diff, {bits, bits}, bits, "Arg0 := Arg1 - Arg2."}
, { 'BALANCE', 16#53, false, true, true, 10, [a], balance, {}, integer, "Arg0 := The current contract balance."}
, { 'ORIGIN', 16#54, false, true, true, 10, [a], origin, {}, address, "Arg0 := Address of contract called by the call transaction."}
, { 'CALLER', 16#55, false, true, true, 10, [a], caller, {}, address, "Arg0 := The address that signed the call transaction."}
, { 'BLOCKHASH', 16#56, false, true, true, 10, [a,a], blockhash, {integer}, hash, "Arg0 := The blockhash at height."}
, { 'BENEFICIARY', 16#57, false, true, true, 10, [a], beneficiary, {}, address, "Arg0 := The address of the current beneficiary."}
, { 'TIMESTAMP', 16#58, false, true, true, 10, [a], timestamp, {}, integer, "Arg0 := The current timestamp. Unrelaiable, don't use for anything."}
, { 'GENERATION', 16#59, false, true, true, 10, [a], generation, {}, integer, "Arg0 := The block height of the cureent generation."}
, { 'MICROBLOCK', 16#5a, false, true, true, 10, [a], microblock, {}, integer, "Arg0 := The current micro block number."}
, { 'DIFFICULTY', 16#5b, false, true, true, 10, [a], difficulty, {}, integer, "Arg0 := The current difficulty."}
, { 'GASLIMIT', 16#5c, false, true, true, 10, [a], gaslimit, {}, integer, "Arg0 := The current gaslimit."}
, { 'GAS', 16#5d, false, true, true, 10, [a], gas, {}, integer, "Arg0 := The amount of gas left."}
, { 'ADDRESS', 16#5e, false, true, true, 10, [a], address, {}, address, "Arg0 := The current contract address."}
, { 'GASPRICE', 16#5f, false, true, true, 10, [a], gasprice, {}, integer, "Arg0 := The current gas price."}
[ { '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."}
, { '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_R', 16#03, true, false, true, ?GAS(100), [a,is,a,a,a], call_r, {contract, string, typerep, typerep, integer}, any, "Remote call to contract Arg0 and function Arg1 of type Arg2 => Arg3 with value Arg4. The types of the arguments has to match the argument types of the function."}
, { 'CALL_T', 16#04, true, true, true, ?GAS(10), [a], call_t, {string}, any, "Tail call to function Arg0. The types of the arguments has to match the argument typs of the function. And the return type of the called function has to match the type of the current function."}
, { 'CALL_GR', 16#05, true, false, true, ?GAS(100), [a,is,a,a,a,a], call_gr, {contract, string, typerep, typerep, integer, integer}, any, "Remote call with gas cap in Arg4. Otherwise as CALL_R."}
, { 'JUMP', 16#06, true, true, true, ?GAS(10), [ii], jump, {integer}, none, "Jump to a basic block. The basic block has to exist in the current function."}
, { 'JUMPIF', 16#07, true, true, true, ?GAS(10), [a,ii], jumpif, {boolean, integer}, none, "Conditional jump to a basic block. If Arg0 then jump to Arg1."}
, { 'SWITCH_V2', 16#08, true, true, true, ?GAS(10), [a,ii,ii], switch, {variant, integer, ingeger}, none, "Conditional jump to a basic block on variant tag."}
, { 'SWITCH_V3', 16#09, true, true, true, ?GAS(10), [a,ii,ii,ii], switch, {variant, integer, integer, ingeger}, none, "Conditional jump to a basic block on variant tag."}
, { 'SWITCH_VN', 16#0a, true, true, true, ?GAS(10), [a, li], switch, {variant, {list, integer}}, none, "Conditional jump to a basic block on variant tag."}
, { 'CALL_VALUE', 16#0b, false, true, true, ?GAS(10), [a], call_value, {}, integer, "The value sent in the current remote call."}
, { 'PUSH', 16#0c, false, true, true, ?GAS(10), [a], push, {any}, any, "Push argument to stack."}
, { 'DUPA', 16#0d, false, true, true, ?GAS(10), [], dup, {any}, any, "Duplicate top of stack."}
, { 'DUP', 16#0e, false, true, true, ?GAS(10), [a], dup, {any}, any, "push Arg0 stack pos on top of stack."}
, { 'POP', 16#0f, false, true, true, ?GAS(10), [a], pop, {integer}, integer, "Arg0 := top of stack."}
, { 'INCA', 16#10, false, true, true, ?GAS(10), [], inc, {integer}, integer, "Increment accumulator."}
, { 'INC', 16#11, false, true, true, ?GAS(10), [a], inc, {integer}, integer, "Increment argument."}
, { 'DECA', 16#12, false, true, true, ?GAS(10), [], dec, {integer}, integer, "Decrement accumulator."}
, { 'DEC', 16#13, false, true, true, ?GAS(10), [a], dec, {integer}, integer, "Decrement argument."}
, { 'ADD', 16#14, false, true, true, ?GAS(10), [a,a,a], add, {integer, integer}, integer, "Arg0 := Arg1 + Arg2."}
, { 'SUB', 16#15, false, true, true, ?GAS(10), [a,a,a], sub, {integer, integer}, integer, "Arg0 := Arg1 - Arg2."}
, { 'MUL', 16#16, false, true, true, ?GAS(10), [a,a,a], mul, {integer, integer}, integer, "Arg0 := Arg1 * Arg2."}
, { 'DIV', 16#17, false, true, true, ?GAS(10), [a,a,a], divide, {integer, integer}, integer, "Arg0 := Arg1 / Arg2."}
, { 'MOD', 16#18, false, true, true, ?GAS(10), [a,a,a], modulo, {integer, integer}, integer, "Arg0 := Arg1 mod Arg2."}
, { 'POW', 16#19, false, true, true, ?GAS(10), [a,a,a], pow, {integer, integer}, integer, "Arg0 := Arg1 ^ Arg2."}
, { 'STORE', 16#1a, false, true, true, ?GAS(10), [a,a], store, {any}, any, "Arg0 := Arg1."}
, { 'SHA3', 16#1b, false, true, true, ?GAS(100), [a,a], sha3, {any}, hash, "Arg0 := sha3(Arg1)."}
, { 'SHA256', 16#1c, false, true, true, ?GAS(100), [a,a], sha256, {any}, hash, "Arg0 := sha256(Arg1)."}
, { 'BLAKE2B', 16#1d, false, true, true, ?GAS(100), [a,a], blake2b, {any}, hash, "Arg0 := blake2b(Arg1)."}
, { 'LT', 16#1e, false, true, true, ?GAS(10), [a,a,a], lt, {integer, integer}, boolean, "Arg0 := Arg1 < Arg2."}
, { 'GT', 16#1f, false, true, true, ?GAS(10), [a,a,a], gt, {integer, integer}, boolean, "Arg0 := Arg1 > Arg2."}
, { 'EQ', 16#20, false, true, true, ?GAS(10), [a,a,a], eq, {integer, integer}, boolean, "Arg0 := Arg1 = Arg2."}
, { 'ELT', 16#21, false, true, true, ?GAS(10), [a,a,a], elt, {integer, integer}, boolean, "Arg0 := Arg1 =< Arg2."}
, { 'EGT', 16#22, false, true, true, ?GAS(10), [a,a,a], egt, {integer, integer}, boolean, "Arg0 := Arg1 >= Arg2."}
, { 'NEQ', 16#23, false, true, true, ?GAS(10), [a,a,a], neq, {integer, integer}, boolean, "Arg0 := Arg1 /= Arg2."}
, { 'AND', 16#24, false, true, true, ?GAS(10), [a,a,a], and_op, {boolean, boolean}, boolean, "Arg0 := Arg1 and Arg2."}
, { 'OR', 16#25, false, true, true, ?GAS(10), [a,a,a], or_op, {boolean, boolean}, boolean, "Arg0 := Arg1 or Arg2."}
, { 'NOT', 16#26, false, true, true, ?GAS(10), [a,a], not_op, {boolean}, boolean, "Arg0 := not Arg1."}
, { 'TUPLE', 16#27, false, true, true, ?GAS(10), [a,ii], tuple, {integer}, tuple, "Arg0 := tuple of size = Arg1. Elements on stack."}
, { 'ELEMENT', 16#28, false, true, true, ?GAS(10), [a,a,a], element_op, {integer, tuple}, any, "Arg1 := element(Arg2, Arg3)."}
, { 'SETELEMENT', 16#29, false, true, true, ?GAS(10), [a,a,a,a], setelement, {integer, tuple, any}, tuple, "Arg0 := a new tuple similar to Arg2, but with element number Arg1 replaced by Arg3."}
, { 'MAP_EMPTY', 16#2a, false, true, true, ?GAS(10), [a], map_empty, {}, map, "Arg0 := #{}."}
, { 'MAP_LOOKUP', 16#2b, false, true, true, ?GAS(10), [a,a,a], map_lookup, {map, any}, any, "Arg0 := lookup key Arg2 in map Arg1."}
, { 'MAP_LOOKUPD', 16#2c, false, true, true, ?GAS(10), [a,a,a,a], map_lookup, {map, any, any}, any, "Arg0 := lookup key Arg2 in map Arg1 if key exists in map otherwise Arg0 := Arg3."}
, { 'MAP_UPDATE', 16#2d, false, true, true, ?GAS(10), [a,a,a,a], map_update, {map, any, any}, map, "Arg0 := update key Arg2 in map Arg1 with value Arg3."}
, { 'MAP_DELETE', 16#2e, false, true, true, ?GAS(10), [a,a,a], map_delete, {map, any}, map, "Arg0 := delete key Arg2 from map Arg1."}
, { 'MAP_MEMBER', 16#2f, false, true, true, ?GAS(10), [a,a,a], map_member, {map, any}, boolean, "Arg0 := true if key Arg2 is in map Arg1."}
, { 'MAP_FROM_LIST', 16#30, false, true, true, ?GAS(10), [a,a], map_from_list, {{list, {tuple, [any, any]}}}, map, "Arg0 := make a map from (key, value) list in Arg1."}
, { 'MAP_SIZE', 16#31, false, true, true, ?GAS(10), [a,a], map_size_, {map}, integer, "Arg0 := The size of the map Arg1."}
, { 'MAP_TO_LIST', 16#32, false, true, true, ?GAS(10), [a,a], map_to_list, {map}, list, "Arg0 := The tuple list representation of the map Arg1."}
, { 'IS_NIL', 16#33, false, true, true, ?GAS(10), [a,a], is_nil, {list}, boolean, "Arg0 := true if Arg1 == []."}
, { 'CONS', 16#34, false, true, true, ?GAS(10), [a,a,a], cons, {any, list}, list, "Arg0 := [Arg1|Arg2]."}
, { 'HD', 16#35, false, true, true, ?GAS(10), [a,a], hd, {list}, any, "Arg0 := head of list Arg1."}
, { 'TL', 16#36, false, true, true, ?GAS(10), [a,a], tl, {list}, list, "Arg0 := tail of list Arg1."}
, { 'LENGTH', 16#37, false, true, true, ?GAS(10), [a,a], length, {list}, integer, "Arg0 := length of list Arg1."}
, { 'NIL', 16#38, false, true, true, ?GAS(10), [a], nil, {}, list, "Arg0 := []."}
, { 'APPEND', 16#39, false, true, true, ?GAS(10), [a,a,a], append, {list, list}, list, "Arg0 := Arg1 ++ Arg2."}
, { 'STR_JOIN', 16#3a, false, true, true, ?GAS(10), [a,a,a], str_join, {string, string}, string, "Arg0 := string Arg1 followed by string Arg2."}
, { 'INT_TO_STR', 16#3b, false, true, true, ?GAS(100), [a,a], int_to_str, {integer}, string, "Arg0 := turn integer Arg1 into a string."}
, { 'ADDR_TO_STR', 16#3c, false, true, true, ?GAS(100), [a,a], addr_to_str, {address}, string, "Arg0 := turn address Arg1 into a string."}
, { 'STR_REVERSE', 16#3d, false, true, true, ?GAS(100), [a,a], str_reverse, {string}, string, "Arg0 := the reverse of string Arg1."}
, { 'STR_LENGTH', 16#3e, false, true, true, ?GAS(10), [a,a], str_length, {string}, integer, "Arg0 := The length of the string Arg1."}
, { 'BYTES_TO_INT', 16#3f, false, true, true, ?GAS(10), [a,a], bytes_to_int, {bytes}, integer, "Arg0 := bytes_to_int(Arg1)"}
, { 'BYTES_TO_STR', 16#40, false, true, true, ?GAS(100), [a,a], bytes_to_str, {bytes}, string, "Arg0 := bytes_to_str(Arg1)"}
, { 'BYTES_CONCAT', 16#41, false, true, true, ?GAS(10), [a,a,a], bytes_concat, {bytes, bytes}, bytes, "Arg0 := bytes_concat(Arg1, Arg2)"}
, { 'BYTES_SPLIT', 16#42, false, true, true, ?GAS(10), [a,a,a], bytes_split, {bytes, integer}, bytes, "Arg0 := bytes_split(Arg2, Arg1), where Arg2 is the length of the first chunk."}
, { 'INT_TO_ADDR', 16#43, false, true, true, ?GAS(10), [a,a], int_to_addr, {integer}, address, "Arg0 := turn integer Arg1 into an address."}
, { 'VARIANT', 16#44, false, true, true, ?GAS(10), [a,a,a,a], variant, {integer, integer, integer}, variant, "Arg0 := create a variant of size Arg1 with the tag Arg2 (Arg2 < Arg1) and take Arg3 elements from the stack."}
, { 'VARIANT_TEST', 16#45, false, true, true, ?GAS(10), [a,a,a], variant_test, {variant, integer}, boolean, "Arg0 := true if variant Arg1 has the tag Arg2."}
, { 'VARIANT_ELEMENT', 16#46, false, true, true, ?GAS(10), [a,a,a], variant_element, {variant, integer}, any, "Arg0 := element number Arg2 from variant Arg1."}
, { 'BITS_NONEA', 16#47, false, true, true, ?GAS(10), [], bits_none, {}, bits, "push an empty bitmap on the stack."}
, { 'BITS_NONE', 16#48, false, true, true, ?GAS(10), [a], bits_none, {}, bits, "Arg0 := empty bitmap."}
, { 'BITS_ALLA', 16#49, false, true, true, ?GAS(10), [], bits_all, {}, bits, "push a full bitmap on the stack."}
, { 'BITS_ALL', 16#4a, false, true, true, ?GAS(10), [a], bits_all, {}, bits, "Arg0 := full bitmap."}
, { 'BITS_ALL_N', 16#4b, false, true, true, ?GAS(10), [a,a], bits_all_n, {integer}, bits, "Arg0 := bitmap with Arg1 bits set."}
, { 'BITS_SET', 16#4c, false, true, true, ?GAS(10), [a,a,a], bits_set, {bits, integer}, bits, "Arg0 := set bit Arg2 of bitmap Arg1."}
, { 'BITS_CLEAR', 16#4d, false, true, true, ?GAS(10), [a,a,a], bits_clear, {bits, integer}, bits, "Arg0 := clear bit Arg2 of bitmap Arg1."}
, { 'BITS_TEST', 16#4e, false, true, true, ?GAS(10), [a,a,a], bits_test, {bits, integer}, boolean, "Arg0 := true if bit Arg2 of bitmap Arg1 is set."}
, { 'BITS_SUM', 16#4f, false, true, true, ?GAS(10), [a,a], bits_sum, {bits}, integer, "Arg0 := sum of set bits in bitmap Arg1. Exception if infinit bitmap."}
, { 'BITS_OR', 16#50, false, true, true, ?GAS(10), [a,a,a], bits_or, {bits, bits}, bits, "Arg0 := Arg1 v Arg2."}
, { 'BITS_AND', 16#51, false, true, true, ?GAS(10), [a,a,a], bits_and, {bits, bits}, bits, "Arg0 := Arg1 ^ Arg2."}
, { 'BITS_DIFF', 16#52, false, true, true, ?GAS(10), [a,a,a], bits_diff, {bits, bits}, bits, "Arg0 := Arg1 - Arg2."}
, { 'BALANCE', 16#53, false, true, true, ?GAS(10), [a], balance, {}, integer, "Arg0 := The current contract balance."}
, { 'ORIGIN', 16#54, false, true, true, ?GAS(10), [a], origin, {}, address, "Arg0 := Address of contract called by the call transaction."}
, { 'CALLER', 16#55, false, true, true, ?GAS(10), [a], caller, {}, address, "Arg0 := The address that signed the call transaction."}
, { 'BLOCKHASH', 16#56, false, true, true, ?GAS_IRIS(10, 1000), [a,a], blockhash, {integer}, variant, "Arg0 := The blockhash at height."}
, { 'BENEFICIARY', 16#57, false, true, true, ?GAS(10), [a], beneficiary, {}, address, "Arg0 := The address of the current beneficiary."}
, { 'TIMESTAMP', 16#58, false, true, true, ?GAS(10), [a], timestamp, {}, integer, "Arg0 := The current timestamp. Unrelaiable, don't use for anything."}
, { 'GENERATION', 16#59, false, true, true, ?GAS(10), [a], generation, {}, integer, "Arg0 := The block height of the cureent generation."}
, { 'MICROBLOCK', 16#5a, false, true, true, ?GAS(10), [a], microblock, {}, integer, "Arg0 := The current micro block number."}
, { 'DIFFICULTY', 16#5b, false, true, true, ?GAS(10), [a], difficulty, {}, integer, "Arg0 := The current difficulty."}
, { 'GASLIMIT', 16#5c, false, true, true, ?GAS(10), [a], gaslimit, {}, integer, "Arg0 := The current gaslimit."}
, { 'GAS', 16#5d, false, true, true, ?GAS(10), [a], gas, {}, integer, "Arg0 := The amount of gas left."}
, { 'ADDRESS', 16#5e, false, true, true, ?GAS(10), [a], address, {}, address, "Arg0 := The current contract address."}
, { 'GASPRICE', 16#5f, false, true, true, ?GAS(10), [a], gasprice, {}, integer, "Arg0 := The current gas price."}
, { 'LOG0', 16#60, false, true, true, 1000, [a], log, {string}, none, "Create a log message in the call object."}
, { 'LOG1', 16#61, false, true, true, 1100, [a,a], log, {integer, string}, none, "Create a log message with one topic in the call object."}
, { 'LOG2', 16#62, false, true, true, 1200, [a,a,a], log, {integer, integer, string}, none, "Create a log message with two topics in the call object."}
, { 'LOG3', 16#63, false, true, true, 1300, [a,a,a,a], log, {integer, integer, integer, string}, none, "Create a log message with three topics in the call object."}
, { 'LOG4', 16#64, false, true, true, 1400, [a,a,a,a,a], log, {integer, integer, integer, integer, string}, none, "Create a log message with four topics in the call object."}
, { 'LOG0', 16#60, false, true, true, ?GAS(1000), [a], log, {string}, none, "Create a log message in the call object."}
, { 'LOG1', 16#61, false, true, true, ?GAS(1100), [a,a], log, {integer, string}, none, "Create a log message with one topic in the call object."}
, { 'LOG2', 16#62, false, true, true, ?GAS(1200), [a,a,a], log, {integer, integer, string}, none, "Create a log message with two topics in the call object."}
, { 'LOG3', 16#63, false, true, true, ?GAS(1300), [a,a,a,a], log, {integer, integer, integer, string}, none, "Create a log message with three 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
, { 'SPEND', 16#65, false, false, true, 100, [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, 100, [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."}
, { 'ORACLE_QUERY', 16#67, false, false, false, 100, [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, 100, [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, 100, [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, 100, [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, 100, [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, 100, [a,a], oracle_query_fee, {oracle}, integer, "Arg0 := query fee for oracle Arg1"}
, { 'AENS_RESOLVE', 16#6d, false, false, true, 100, [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, 100, [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, 100, [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_UPDATE', 16#70, false, false, false, 100, [], aens_update, {}, none, "NYI"}
, { 'AENS_TRANSFER', 16#71, false, false, false, 100, [a,a,a,a], aens_transfer,{signature, address, address, string}, none, "Transfer ownership of name Arg3 from account Arg1 to Arg2. Arg0 contains delegation signature."}
, { 'AENS_REVOKE', 16#72, false, false, false, 100, [a,a,a], aens_revoke, {signature, address, string}, none, "Revoke the name in Arg2 from owner Arg1. Arg0 contains delegation signature."}
, { 'BALANCE_OTHER', 16#73, false, true, true, 50, [a,a], balance_other, {address}, integer, "Arg0 := The balance of address Arg1."}
, { '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."}
, { '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_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_UPDATE', 16#70, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a,a,a], aens_update, {signature, address, string, variant, variant, variant}, none, "Updates name in Arg2 for address in Arg1. Arg3 contains optional ttl (of type Chain.ttl), Arg4 contains optional client_ttl (of type int), Arg5 contains optional pointers (of type map(string, pointee))"}
, { 'AENS_TRANSFER', 16#71, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a,a], aens_transfer,{signature, address, address, string}, none, "Transfer ownership of name Arg3 from account Arg1 to Arg2. Arg0 contains delegation signature."}
, { 'AENS_REVOKE', 16#72, false, false, false, ?GAS_IRIS(100, 10000), [a,a,a], aens_revoke, {signature, address, string}, none, "Revoke the name in Arg2 from owner Arg1. Arg0 contains delegation signature."}
, { 'BALANCE_OTHER', 16#73, false, true, true, ?GAS_IRIS( 50, 2000), [a,a], balance_other, {address}, integer, "Arg0 := The balance of address Arg1."}
, { 'VERIFY_SIG', 16#74, false, true, true, 1300, [a,a,a,a], verify_sig, {bytes, address, bytes}, boolean, "Arg0 := verify_sig(Hash, PubKey, Signature)"}
, { 'VERIFY_SIG_SECP256K1',16#75, false, true, true, 1300, [a,a,a,a], verify_sig_secp256k1, {bytes, bytes, bytes}, boolean, "Arg0 := verify_sig_secp256k1(Hash, PubKey, Signature)"}
, { 'VERIFY_SIG', 16#74, false, true, true, ?GAS(1300), [a,a,a,a], verify_sig, {bytes, address, bytes}, boolean, "Arg0 := verify_sig(Hash, PubKey, Signature)"}
, { 'VERIFY_SIG_SECP256K1',16#75, false, true, true, ?GAS(1300), [a,a,a,a], verify_sig_secp256k1, {bytes, bytes, bytes}, boolean, "Arg0 := verify_sig_secp256k1(Hash, PubKey, Signature)"}
, { 'CONTRACT_TO_ADDRESS', 16#76, false, true, true, 10, [a,a], contract_to_address, {contract}, address, "Arg0 := Arg1 - A no-op type conversion"}
, { 'AUTH_TX_HASH', 16#77, false, true, true, 10, [a], auth_tx_hash, {}, variant, "If in GA authentication context return Some(TxHash) otherwise None."}
, { '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."}
, { 'ORACLE_CHECK', 16#78, false, false, true, 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"}
, { 'ORACLE_CHECK_QUERY', 16#79, false, false, true, 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)"}
, { '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"}
, { '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, 100, [a,a], is_oracle, {address}, bool, "Arg0 := is Arg1 an oracle"}
, { 'IS_CONTRACT', 16#7b, false, false, true, 100, [a,a], is_contract, {address}, bool, "Arg0 := is Arg1 a contract"}
, { 'IS_PAYABLE', 16#7c, false, false, true, 100, [a,a], is_payable, {address}, bool, "Arg0 := is Arg1 a payable address"}
, { 'CREATOR', 16#7d, false, true, true, 10, [a], contract_creator, {}, address, "Arg0 := contract creator"}
, { '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_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"}
, { 'ECVERIFY_SECP256K1', 16#7e, false, true, true, 1300, [a,a,a,a], ecverify_secp256k1, {bytes, bytes, bytes}, bytes, "Arg0 := ecverify_secp256k1(Hash, Addr, Signature)"}
, { 'ECRECOVER_SECP256K1', 16#7f, false, true, true, 1300, [a,a,a], ecrecover_secp256k1, {bytes, bytes}, bytes, "Arg0 := ecrecover_secp256k1(Hash, Signature)"}
, { 'ECVERIFY_SECP256K1', 16#7e, false, true, true, ?GAS(1300), [a,a,a,a], ecverify_secp256k1, {bytes, bytes, bytes}, bytes, "Arg0 := ecverify_secp256k1(Hash, Addr, Signature)"}
, { 'ECRECOVER_SECP256K1', 16#7f, false, true, true, ?GAS(1300), [a,a,a], ecrecover_secp256k1, {bytes, bytes}, bytes, "Arg0 := ecrecover_secp256k1(Hash, Signature)"}
, { 'ADDRESS_TO_CONTRACT', 16#80, false, true, true, 10, [a,a], address_to_contract, {address}, contract, "Arg0 := Arg1 - A no-op type conversion"}
, { 'ADDRESS_TO_CONTRACT', 16#80, false, true, true, ?GAS(10), [a,a], address_to_contract, {address}, contract, "Arg0 := Arg1 - A no-op type conversion"}
, { 'DEACTIVATE', 16#fa, false, true, true, 10, [], deactivate, {}, none, "Mark the current contract for deactivation."}
, { 'ABORT', 16#fb, true, true, true, 10, [a], abort, {string}, none, "Abort execution (dont use all gas) with error message in Arg0."}
, { 'EXIT', 16#fc, true, true, true, 10, [a], exit, {string}, none, "Abort execution (use upp all gas) with error message in Arg0."}
, { 'NOP', 16#fd, false, true, true, 1, [], nop, {}, none, "The no op. does nothing."}
, { 'BLS12_381_G1_NEG', 16#81, false, true, true, ?GAS(100), [a,a], bls12_381_g1_neg, {tuple}, tuple, "Arg0 := BLS12_381.g1_neg(Arg1) - Negate a G1-value"}
, { 'BLS12_381_G1_NORM', 16#82, false, true, true, ?GAS(100), [a,a], bls12_381_g1_norm, {tuple}, tuple, "Arg0 := BLS12_381.g1_normalize(Arg1) - Normalize a G1-value"}
, { 'BLS12_381_G1_VALID', 16#83, false, true, true, ?GAS(2000), [a,a], bls12_381_g1_valid, {tuple}, bool, "Arg0 := BLS12_381.g1_valid(Arg1) - Check if G1-value is a valid group member"}
, { 'BLS12_381_G1_IS_ZERO', 16#84, false, true, true, ?GAS(30), [a,a], bls12_381_g1_is_zero, {tuple}, bool, "Arg0 := BLS12_381.g1_is_zero(Arg1) - Check if G1-value is zero"}
, { 'BLS12_381_G1_ADD', 16#85, false, true, true, ?GAS(100), [a,a,a], bls12_381_g1_add, {tuple, tuple}, tuple, "Arg0 := BLS12_381.g1_add(Arg1, Arg2) - Add two G1-values"}
, { 'BLS12_381_G1_MUL', 16#86, false, true, true, ?GAS(1000), [a,a,a], bls12_381_g1_mul, {tuple, tuple}, tuple, "Arg0 := BLS12_381.g1_mul(Arg1, Arg2) - Scalar multiplication for a G1-value (Arg1), and an Fr-value"}
, { 'BLS12_381_G2_NEG', 16#87, false, true, true, ?GAS(100), [a,a], bls12_381_g2_neg, {tuple}, tuple, "Arg0 := BLS12_381.g2_neg(Arg1) - Negate a G2-value"}
, { 'BLS12_381_G2_NORM', 16#88, false, true, true, ?GAS(100), [a,a], bls12_381_g2_norm, {tuple}, tuple, "Arg0 := BLS12_381.g2_normalize(Arg1) - Normalize a G2-value"}
, { 'BLS12_381_G2_VALID', 16#89, false, true, true, ?GAS(2000), [a,a], bls12_381_g2_valid, {tuple}, bool, "Arg0 := BLS12_381.g2_valid(Arg1) - Check if G2-value is a valid group member"}
, { 'BLS12_381_G2_IS_ZERO', 16#8a, false, true, true, ?GAS(30), [a,a], bls12_381_g2_is_zero, {tuple}, bool, "Arg0 := BLS12_381.g2_is_zero(Arg1) - Check if G2-value is zero"}
, { 'BLS12_381_G2_ADD', 16#8b, false, true, true, ?GAS(100), [a,a,a], bls12_381_g2_add, {tuple, tuple}, tuple, "Arg0 := BLS12_381.g2_add(Arg1, Arg2) - Add two G2-values"}
, { 'BLS12_381_G2_MUL', 16#8c, false, true, true, ?GAS(1000), [a,a,a], bls12_381_g2_mul, {tuple, tuple}, tuple, "Arg0 := BLS12_381.g2_mul(Arg1, Arg2) - Scalar multiplication for a G2-value (Arg2), and an Fr-value"}
, { 'BLS12_381_GT_INV', 16#8d, false, true, true, ?GAS(100), [a,a], bls12_381_gt_inv, {tuple}, tuple, "Arg0 := BLS12_381.gt_inv(Arg1) - Invert a GT-value"}
, { 'BLS12_381_GT_ADD', 16#8e, false, true, true, ?GAS(100), [a,a,a], bls12_381_gt_add, {tuple, tuple}, tuple, "Arg0 := BLS12_381.gt_add(Arg1, Arg2) - Add two GT-values"}
, { 'BLS12_381_GT_MUL', 16#8f, false, true, true, ?GAS(100), [a,a,a], bls12_381_gt_mul, {tuple, tuple}, tuple, "Arg0 := BLS12_381.gt_mul(Arg1, Arg2) - Multiply two GT-values"}
, { 'BLS12_381_GT_POW', 16#90, false, true, true, ?GAS(2000), [a,a,a], bls12_381_gt_pow, {tuple, tuple}, tuple, "Arg0 := BLS12_381.gt_pow(Arg1, Arg2) - Scalar exponentiation for a GT-value (Arg2), and an Fr-value"}
, { 'BLS12_381_GT_IS_ONE', 16#91, false, true, true, ?GAS(30), [a,a], bls12_381_gt_is_one, {tuple}, bool, "Arg0 := BLS12_381.gt_is_one(Arg1) - Check if a GT value is \"one\""}
, { 'BLS12_381_PAIRING', 16#92, false, true, true, ?GAS(12000), [a,a,a], bls12_381_pairing, {tuple, tuple}, tuple, "Arg0 := BLS12_381.pairing(Arg1, Arg2) - Find the pairing of a G1-value (Arg1) and a G2-value (Arg2)"}
, { 'BLS12_381_MILLER_LOOP', 16#93, false, true, true, ?GAS(5000), [a,a,a], bls12_381_miller_loop, {tuple, tuple}, tuple, "Arg0 := BLS12_381.miller_loop(Arg1, Arg2) - Do the Miller-loop step of pairing for a G1-value (Arg1) and a G2-value (Arg2)"}
, { 'BLS12_381_FINAL_EXP', 16#94, false, true, true, ?GAS(7000), [a,a], bls12_381_final_exp, {tuple}, tuple, "Arg0 := BLS12_381.final_exp(Arg1) - Do the final exponentiation in pairing"}
, { 'BLS12_381_INT_TO_FR', 16#95, false, true, true, ?GAS(30), [a,a], bls12_381_int_to_fr, {tuple}, tuple, "Arg0 := to_montgomery(Arg1) - Convert (Big)integer to montgomery representation (32 bytes)"}
, { 'BLS12_381_INT_TO_FP', 16#96, false, true, true, ?GAS(30), [a,a], bls12_381_int_to_fp, {tuple}, tuple, "Arg0 := to_montgomery(Arg1) - Convert (Big)integer to montgomery representation (48 bytes)"}
, { 'BLS12_381_FR_TO_INT', 16#97, false, true, true, ?GAS(30), [a,a], bls12_381_fr_to_int, {tuple}, tuple, "Arg0 := from_montgomery(Arg1) - Convert montgomery representation (32 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)"}
, { 'ORACLE_EXPIRY', 16#9a, false, false, true, ?GAS(2000), [a,a], oracle_expiry, {oracle}, int, "Arg0 := expiry block for oracle Arg1"}
, { '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_FROM_LIST', 16#9d, false, true, true, ?GAS(100), [a,a], str_from_list, {list}, string, "Arg0 := string converted from list of characters"}
, { 'STR_TO_UPPER', 16#9e, false, true, true, ?GAS(100), [a,a], str_to_upper, {string}, string, "Arg0 := to_upper(string)"}
, { 'STR_TO_LOWER', 16#9f, false, true, true, ?GAS(100), [a,a], str_to_lower, {string}, string, "Arg0 := to_lower(string)"}
, { 'CHAR_TO_INT', 16#a0, false, true, true, ?GAS(10), [a,a], char_to_int, {char}, int, "Arg0 := integer representation of UTF-8 character"}
, { 'CHAR_FROM_INT', 16#a1, false, true, true, ?GAS(10), [a,a], char_from_int, {int}, variant, "Arg0 := Some(UTF-8 character) from integer if valid, None if not valid."}
, { '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."}
, { '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_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"}
, { '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)."}
, { 'FEE', 16#a7, false, true, true, ?GAS(10), [a], fee, {}, integer, "Arg0 := The fee for the current call tx."}
, { '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."}
, { 'EXIT', 16#fc, true, true, true, ?GAS(10), [a], exit, {string}, none, "Abort execution (use upp all gas) with error message in Arg0."}
, { 'NOP', 16#fd, false, true, true, ?GAS(1), [], nop, {}, none, "The no op. does nothing."}
%% FUNCTION 16#fe "Function declaration and entrypoint."
%% EXTEND 16#ff "Reserved for future extensions beyond one byte opcodes."
].
+4
View File
@@ -25,7 +25,11 @@
%% Size in bytes of serialization of a map for which we turn it into a store
%% map. It's not worth turning small maps into store maps.
%% Under consensus!
-ifdef(TEST).
-define(STORE_MAP_THRESHOLD, 0).
-else.
-define(STORE_MAP_THRESHOLD, 100).
-endif.
-type fate_value() :: aeb_fate_data:fate_type().
-type fate_value_or_tombstone() :: fate_value() | ?FATE_MAP_TOMBSTONE.
+12 -2
View File
@@ -133,11 +133,15 @@ to_binary1(Data, Address) when is_binary(Data) ->
%% a string
Words = aeb_memory:binary_to_words(Data),
{Address,<<(size(Data)):256, << <<W:256>> || W <- Words>>/binary>>};
to_binary1({contract_bytearray, FateCode}, Address) when is_binary(FateCode) ->
Words = aeb_memory:binary_to_words(FateCode),
{Address,<<(size(FateCode)):256, << <<W:256>> || W <- Words>>/binary>>};
to_binary1(none, Address) -> to_binary1({variant, 0, []}, Address);
to_binary1({some, Value}, Address) -> to_binary1({variant, 1, [Value]}, Address);
to_binary1(word, Address) -> to_binary1({?TYPEREP_WORD_TAG}, Address);
to_binary1(string, Address) -> to_binary1({?TYPEREP_STRING_TAG}, Address);
to_binary1(typerep, Address) -> to_binary1({?TYPEREP_TYPEREP_TAG}, Address);
to_binary1(contract_bytearray, Address) -> to_binary1({?TYPEREP_CONTRACT_BYTEARRAY_TAG}, Address);
to_binary1(function, Address) -> to_binary1({?TYPEREP_FUN_TAG}, Address);
to_binary1({list, T}, Address) -> to_binary1({?TYPEREP_LIST_TAG, T}, Address);
to_binary1({option, T}, Address) -> to_binary1({variant, [[], [T]]}, Address);
@@ -268,8 +272,14 @@ from_binary(Visited, typerep, Heap, V) ->
?TYPEREP_TUPLE_TAG -> {tuple, Arg({list, typerep})};
?TYPEREP_VARIANT_TAG -> {variant, Arg({list, {list, typerep}})};
?TYPEREP_MAP_TAG -> {map, Arg(typerep), Arg1(typerep, 2)};
?TYPEREP_FUN_TAG -> function
end.
?TYPEREP_FUN_TAG -> function;
?TYPEREP_CONTRACT_BYTEARRAY_TAG -> contract_bytearray
end;
from_binary(_, contract_bytearray, Heap, V) ->
FateCodeSize = heap_word(Heap, V),
BitAddr = 8*(V+32),
<<_:BitAddr,Bytes:FateCodeSize/binary,_/binary>> = Heap,
{contract_bytearray, Bytes}.
map_binary_to_value(KeyType, ValType, N, Bin, Ptr) ->
%% Avoid looping on bogus sizes
+1 -1
View File
@@ -49,7 +49,7 @@ sources() ->
, "immediates"
, "names"
, "oracles"
%% , "all_instructions"
, "meta"
].
check_roundtrip(File) ->
+11 -2
View File
@@ -83,6 +83,15 @@ sources() ->
aeb_fate_data:make_variant([0,1,2,3,4,5],
3, {aeb_fate_data:make_boolean(true),
aeb_fate_data:make_list(make_int_list(3)),
aeb_fate_data:make_string(<<"foo">>)})
aeb_fate_data:make_string(<<"foo">>)}),
%% contract C =
%% type state = int
%% entrypoint init() = 2137
].
%% cb_+FFGA6Af6sHTrctrcNGwEa8MPei7iEHIjnxcsBzlA5IK0Yn11sCllP5E1kQfADcANwAaDoJvgggZAQM/jC8BEUTWRB8RaW5pdIIvAIU0LjMuMAD7u
aeb_fate_data:make_contract_bytearray(
<<248,81,70,3,160,31,234,193,211,173,203,107,112,209,176,17,175,12,61,232,187,
136,65,200,142,124,92,176,28,229,3,146,10,209,137,245,214,192,165,148,254,68,
214,68,31,0,55,0,55,0,26,14,130,111,130,8,25,1,3,63,140,47,1,17,68,214,68,31,
17,105,110,105,116,130,47,0,133,52,46,51,46,48,0>>)
].
-261
View File
@@ -1,261 +0,0 @@
;; CONTRACT all_instructions
;; Dont expect this contract to typecheck or run.
;; Just used to check assembler roundtrip of all instructions.
FUNCTION foo () : {tuple, []}
RETURN
RETURNR a
CALL "foo"
CALL_R arg125 foo 0
CALL_T "foo"
CALL_TR arg245 foo 4711
CALL_GTR arg245 foo 0 100
CALL_GR arg245 foo 0 4711
JUMP 5514251025295783441695716053282666408426
JUMPIF arg196 0x12c651665
SWITCH_V2 a 63 33
SWITCH_V3 var4 0x1d61723dd 79 7
SWITCH_VN arg0 [1, 2, 3]
PUSH var80
DUPA
DUP a
POP a
STORE arg183 var225
INCA
INC a
DECA
DEC a
ADD a a a
SUB arg35 arg165 var74
MUL 44 35 "foo"
DIV 263838340369912686645632650718169038811 a a
MOD var113 arg80 arg207
POW a a a
LT a 78 var81
GT arg19 4729414120208894485838100532547810615352 var175
EQ 85 a arg164
ELT a arg226 a
EGT a 1 var250
NEQ a a a
AND var255 0x294a24f6 var189
OR (| [2,0] | 0 | ( (), (42) ) |) arg168 var107
NOT arg124 a
TUPLE var999 5019186157739257888756115213149493826410
ELEMENT arg148 var25 a
MAP_EMPTY a
MAP_LOOKUP a a a
MAP_LOOKUPD var112 arg35 a var112
MAP_UPDATE false a a a
MAP_DELETE arg180 a var1
MAP_MEMBER a { true => 4} 94
MAP_FROM_LIST () a
MAP_TO_LIST a { true => 4 }
MAP_SIZE a { true => 42 }
NIL arg91
IS_NIL a var6
CONS arg185 "foo" a
HD a var124
TL arg223 a
LENGTH var216 a
APPEND { 203961992615221001243597889146034217896 => 0x1f53a1843} 281217554184165828643225535776787296845 a
STR_JOIN a a 7144184027126178769820155907121270843348
INT_TO_STR var238 a
ADDR_TO_STR a arg216
STR_REVERSE a @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
STR_LENGTH a "foo"
INT_TO_ADDR arg127 var207
VARIANT a a 0x1f7b72200 a
VARIANT_TEST a arg217 a
VARIANT_ELEMENT a arg103 arg108
BITS_NONEA
BITS_NONE a
BITS_ALLA
BITS_ALL a
BITS_ALL_N a arg135
BITS_SET arg150 a { 0x1a715e2a6 => 3}
BITS_CLEAR arg98 a arg164
BITS_TEST a a (| [0,0,3] | 2 | (1, "foo", ()) |)
BITS_SUM a a
BITS_OR var20 var186 a
BITS_AND a 4 arg203
BITS_DIFF var200 arg247 var20
ADDRESS a
BALANCE a
ORIGIN arg216
CALLER a
GASPRICE arg119
BLOCKHASH a arg110
CALL_VALUE a
BENEFICIARY var163
TIMESTAMP a
GENERATION 242795038229506961431398379342231049652
MICROBLOCK arg43
DIFFICULTY var24
GASLIMIT arg220
GAS var35
LOG0 a
LOG1 arg86 arg208
LOG2 a a (| [0,1,3] | 2 | (1, "foo", ()) |)
LOG3 arg15 arg211 var139 arg44
LOG4 a a 9 a a
DEACTIVATE
SPEND @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv var136
ORACLE_REGISTER arg29 48 ((| [0,1,3] | 2 | (1, "foo", ()) |)) arg65 { <> => false} <>
ORACLE_QUERY
ORACLE_RESPOND
ORACLE_EXTEND
ORACLE_GET_ANSWER
ORACLE_GET_QUESTION
ORACLE_QUERY_FEE
AENS_RESOLVE
AENS_PRECLAIM
AENS_CLAIM
AENS_UPDATE
AENS_TRANSFER
AENS_REVOKE
ECRECOVER_SECP256K1
VERIFY_SIG
VERIFY_SIG_SECP256K1
ECVERIFY_SECP256K1
SHA3 a
SHA256 a
BLAKE2B a
ABORT a
EXIT var120
NOP
RETURNR ()
BALANCE_OTHER a arg0
SETELEMENT a 2 (1, "two", 3) 2
AUTH_TX_HASH
CONTRACT_TO_ADDRESS @ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
IS_ORACLE @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
IS_CONTRACT @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
IS_PAYABLE @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
+12
View File
@@ -0,0 +1,12 @@
;; CONTRACT meta
FUNCTION meta() : boolean
CREATE @cb_+PJGA6A4Fz4T2LHV5knITCldR3rqO7HrXO2zhOAR9JWNbhf8Q8C4xbhx/gx8JckANwAXfQBVACAAAP4vhlvZADcABwECgv5E1kQfADcBBzcACwAWMBReAHMAFjBvJFMAFjBvggOoFAAUABQSggABAz/+tIwWhAA3AAdTAAD+1jB5kAQ3AAcLAAD+6MRetgA3AQc3ABoGggABAz+4TS8GEQx8JclFY2FsbGVyX2lzX2NyZWF0b3IRL4Zb2Q1nZXQRRNZEHxFpbml0EbSMFoQdYmFsYW5jZRHWMHmQFXZhbHVlEejEXrYNc2V0gi8AhTQuMy4wAUqQ8s4= a 2137
CLONE a arg0 2137 false
CLONE_G a arg0 2137 10000 false
BYTECODE_HASH a a
BYTECODE_HASH a a
EQ a a a
RETURNR a