Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
cc4fd04019 | |||
97cea33be8 | |||
1cdcb9150b | |||
![]() |
b47b2fe23c | ||
![]() |
5e38d6e829 | ||
![]() |
009e036192 | ||
![]() |
37808419a8 | ||
![]() |
f4c3782888 | ||
![]() |
1688f85f2b | ||
![]() |
b38349274f | ||
![]() |
b8d593e351 | ||
![]() |
0f7529b26a | ||
![]() |
2a0a397afa | ||
![]() |
093bcd6204 | ||
![]() |
6601ad2d38 | ||
![]() |
578ebe2a8a |
@ -1,37 +0,0 @@
|
||||
version: 2.1
|
||||
|
||||
executors:
|
||||
aebuilder:
|
||||
docker:
|
||||
- image: aeternity/builder
|
||||
user: builder
|
||||
working_directory: ~/aebytecode
|
||||
|
||||
jobs:
|
||||
build:
|
||||
executor: aebuilder
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- dialyzer-cache-v1-{{ .Branch }}-{{ .Revision }}
|
||||
- dialyzer-cache-v1-{{ .Branch }}-
|
||||
- dialyzer-cache-v1-
|
||||
- run:
|
||||
name: Build
|
||||
command: rebar3 compile
|
||||
- run:
|
||||
name: Static Analysis
|
||||
command: make dialyzer
|
||||
- run:
|
||||
name: Eunit
|
||||
command: make eunit
|
||||
- run:
|
||||
name: Common Tests
|
||||
command: make test
|
||||
- save_cache:
|
||||
key: dialyzer-cache-v1-{{ .Branch }}-{{ .Revision }}
|
||||
paths:
|
||||
- _build/default/rebar3_20.3.8_plt
|
||||
- store_artifacts:
|
||||
path: _build/test/logs
|
15
.gitea/workflows/test.yaml
Normal file
15
.gitea/workflows/test.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
name: Gajumaru Bytecode Tests
|
||||
run-name: ${{ gitea.actor }} testing Gajumaru Bytecode
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: linux_amd64
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: test
|
||||
run: |
|
||||
. /home/act_runner/.erts/27.2.1/activate
|
||||
make dialyzer
|
||||
make eunit
|
20
.gitignore
vendored
20
.gitignore
vendored
@ -8,21 +8,21 @@ ebin/*.beam
|
||||
rel/example_project
|
||||
.concrete/DEV_MODE
|
||||
.rebar
|
||||
aeb_asm_scan.erl
|
||||
aeb_fate_asm_scan.erl
|
||||
aeb_fate_asm_scan.xrl
|
||||
gmb_asm_scan.erl
|
||||
gmb_fate_asm_scan.erl
|
||||
gmb_fate_asm_scan.xrl
|
||||
_build/
|
||||
aefateasm
|
||||
include/aeb_fate_opcodes.hrl
|
||||
src/aeb_fate_opcodes.erl
|
||||
src/aeb_fate_ops.erl
|
||||
src/aeb_fate_pp.erl
|
||||
gmfateasm
|
||||
include/gmb_fate_opcodes.hrl
|
||||
src/gmb_fate_opcodes.erl
|
||||
src/gmb_fate_ops.erl
|
||||
src/gmb_fate_pp.erl
|
||||
*.erl~
|
||||
*.hrl~
|
||||
*.aes~
|
||||
doc
|
||||
cover
|
||||
aefate
|
||||
gmfate
|
||||
current_counterexample.eqc
|
||||
.rebar3
|
||||
ebin
|
||||
ebin/*.beam
|
||||
|
1
Emakefile
Normal file
1
Emakefile
Normal file
@ -0,0 +1 @@
|
||||
{"src/*", [debug_info, {i, "include/"}, {outdir, "ebin/"}]}.
|
1
LICENSE
1
LICENSE
@ -1,5 +1,6 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2025, QPQ AG
|
||||
Copyright (c) 2017, aeternity developers
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
|
9
Makefile
9
Makefile
@ -1,5 +1,5 @@
|
||||
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
|
||||
GENERATED_SRC = src/gmb_fate_opcodes.erl src/gmb_fate_ops.erl include/gmb_fate_opcodes.hrl src/gmb_fate_asm_scan.xrl src/gmb_fate_pp.erl
|
||||
GENERATOR_DEPS = ebin/gmb_fate_generate_ops.beam src/gmb_fate_asm_scan.template
|
||||
REBAR ?= ./rebar3
|
||||
|
||||
all: local
|
||||
@ -15,7 +15,8 @@ console: local
|
||||
clean:
|
||||
@$(REBAR) clean
|
||||
rm -f $(GENERATED_SRC)
|
||||
rm -f ebin/*
|
||||
rm -f ebin/*.beam
|
||||
rm -rf _build
|
||||
|
||||
dialyzer: local
|
||||
@$(REBAR) as local dialyzer
|
||||
@ -33,4 +34,4 @@ ebin/%.beam: src/%.erl
|
||||
erlc +debug_info -o $(dir $@) $<
|
||||
|
||||
$(GENERATED_SRC): $(GENERATOR_DEPS)
|
||||
erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/
|
||||
erl -pa ebin/ -noshell -s gmb_fate_generate_ops gen_and_halt src/ include/
|
||||
|
@ -1,5 +1,5 @@
|
||||
# aebytecode
|
||||
A library and stand alone assembler for aeternity bytecode.
|
||||
# gmbytecode
|
||||
A library and stand alone assembler for Gajumaru bytecode.
|
||||
|
||||
This version supports AEVM bytecode and FATE bytecode.
|
||||
|
||||
|
16
ebin/gmbytecode.app
Normal file
16
ebin/gmbytecode.app
Normal file
@ -0,0 +1,16 @@
|
||||
{application,gmbytecode,
|
||||
[{description,"Bytecode definitions, serialization and deserialization for the Gajumaru."},
|
||||
{vsn,"3.4.1"},
|
||||
{registered,[]},
|
||||
{applications,[kernel,stdlib,eblake2,gmserialization,getopt]},
|
||||
{env,[]},
|
||||
{modules,[gmb_aevm_abi,gmb_aevm_data,gmb_asm,gmb_asm_scan,
|
||||
gmb_disassemble,gmb_fate_abi,gmb_fate_asm,
|
||||
gmb_fate_asm_scan,gmb_fate_code,gmb_fate_data,
|
||||
gmb_fate_encoding,gmb_fate_generate_docs,
|
||||
gmb_fate_generate_ops,gmb_fate_maps,gmb_fate_opcodes,
|
||||
gmb_fate_ops,gmb_fate_pp,gmb_heap,gmb_memory,
|
||||
gmb_opcodes,gmb_primops,gmfateasm]},
|
||||
{maintainers,[]},
|
||||
{licenses,[]},
|
||||
{links,[]}]}.
|
@ -88,7 +88,7 @@
|
||||
-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">>).
|
||||
% Result of gmb_fate_code:symbol_identifier(<<"init">>).
|
||||
% Stored here to avoid repeated calls to eblake2
|
||||
-define(FATE_INIT_ID, <<68,214,68,31>>).
|
||||
|
@ -1,15 +1,15 @@
|
||||
|
||||
-record(pmap, {key_t :: aeb_aevm_data:type(),
|
||||
val_t :: aeb_aevm_data:type(),
|
||||
-record(pmap, {key_t :: gmb_aevm_data:type(),
|
||||
val_t :: gmb_aevm_data:type(),
|
||||
parent :: none | non_neg_integer(),
|
||||
size = 0 :: non_neg_integer(),
|
||||
data :: #{aeb_heap:binary_value() => aeb_heap:binary_value() | tombstone}
|
||||
data :: #{gmb_heap:binary_value() => gmb_heap:binary_value() | tombstone}
|
||||
| stored}).
|
||||
|
||||
-record(maps, { maps = #{} :: #{ non_neg_integer() => #pmap{} }
|
||||
, next_id = 0 :: non_neg_integer() }).
|
||||
|
||||
-record(heap, { maps :: #maps{},
|
||||
offset :: aeb_heap:offset(),
|
||||
offset :: gmb_heap:offset(),
|
||||
heap :: binary() | #{non_neg_integer() => non_neg_integer()} }).
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
-define(Type(), aeb_aevm_data:type()).
|
||||
-define(Type(), gmb_aevm_data:type()).
|
||||
|
||||
-define(TYPEREP_WORD_TAG, 0).
|
||||
-define(TYPEREP_STRING_TAG, 1).
|
@ -1,14 +1,14 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Allow to run QuickCheck tests as eunit tests
|
||||
%%% `rebar3 as eqc eunit --cover`
|
||||
%%% or `rebar3 as eqc eunit --module=aeb_fate_code`
|
||||
%%% or `rebar3 as eqc eunit --module=gmb_fate_code`
|
||||
%%% Note that for obtainign cover file, one needs `rebar3 as eqc cover
|
||||
%%%
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aeb_fate_code_tests).
|
||||
-module(gmb_fate_code_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
@ -20,8 +20,8 @@
|
||||
|
||||
quickcheck_test_() ->
|
||||
{setup, fun() -> eqc:start() end,
|
||||
[ ?EQC_EUNIT(aefate_code_eqc, prop_opcodes, 200),
|
||||
?EQC_EUNIT(aefate_code_eqc, prop_serializes, 3000),
|
||||
?EQC_EUNIT(aefate_code_eqc, prop_fail_serializes, 3000),
|
||||
?EQC_EUNIT(aefate_code_eqc, prop_fuzz, 3000)
|
||||
[ ?EQC_EUNIT(gmfate_code_eqc, prop_opcodes, 200),
|
||||
?EQC_EUNIT(gmfate_code_eqc, prop_serializes, 3000),
|
||||
?EQC_EUNIT(gmfate_code_eqc, prop_fail_serializes, 3000),
|
||||
?EQC_EUNIT(gmfate_code_eqc, prop_fuzz, 3000)
|
||||
]}.
|
@ -1,14 +1,14 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Allow to run QuickCheck tests as eunit tests
|
||||
%%% `rebar3 as eqc eunit --cover`
|
||||
%%% or `rebar3 as eqc eunit --module=aeb_fate_data`
|
||||
%%% or `rebar3 as eqc eunit --module=gmb_fate_data`
|
||||
%%% Note that for obtainign cover file, one needs `rebar3 as eqc cover
|
||||
%%%
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aeb_fate_data_tests).
|
||||
-module(gmb_fate_data_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
@ -20,8 +20,8 @@
|
||||
|
||||
quickcheck_test_() ->
|
||||
{setup, fun() -> eqc:start() end,
|
||||
[ ?EQC_EUNIT(aefate_eqc, prop_roundtrip, 500),
|
||||
?EQC_EUNIT(aefate_eqc, prop_format_scan, 2000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_order, 2000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_fuzz, 2000)
|
||||
[ ?EQC_EUNIT(gmfate_eqc, prop_roundtrip, 500),
|
||||
?EQC_EUNIT(gmfate_eqc, prop_format_scan, 2000),
|
||||
?EQC_EUNIT(gmfate_eqc, prop_order, 2000),
|
||||
?EQC_EUNIT(gmfate_eqc, prop_fuzz, 2000)
|
||||
]}.
|
@ -1,14 +1,14 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Allow to run QuickCheck tests as eunit tests
|
||||
%%% `rebar3 as eqc eunit --cover`
|
||||
%%% or `rebar3 as eqc eunit --module=aeb_fate_encoding`
|
||||
%%% or `rebar3 as eqc eunit --module=gmb_fate_encoding`
|
||||
%%% Note that for obtaining cover file, one needs `rebar3 as eqc cover
|
||||
%%%
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts
|
||||
|
||||
-module(aeb_fate_encoding_tests).
|
||||
-module(gmb_fate_encoding_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
@ -20,8 +20,8 @@
|
||||
|
||||
quickcheck_test_() ->
|
||||
{setup, fun() -> eqc:start() end,
|
||||
[ ?EQC_EUNIT(aefate_type_eqc, prop_roundtrip, 1000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_serializes, 1000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_no_maps_in_keys, 1000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_idempotent, 1000)
|
||||
[ ?EQC_EUNIT(gmfate_type_eqc, prop_roundtrip, 1000),
|
||||
?EQC_EUNIT(gmfate_eqc, prop_serializes, 1000),
|
||||
?EQC_EUNIT(gmfate_eqc, prop_no_maps_in_keys, 1000),
|
||||
?EQC_EUNIT(gmfate_eqc, prop_idempotent, 1000)
|
||||
]}.
|
@ -16,7 +16,7 @@
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aefate_code_eqc).
|
||||
-module(gmfate_code_eqc).
|
||||
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
|
||||
@ -28,10 +28,10 @@ prop_serializes() ->
|
||||
in_parallel(
|
||||
?FORALL(FateCode, fate_code(0),
|
||||
begin
|
||||
{T0, Binary} = timer:tc(fun() -> aeb_fate_code:serialize(FateCode) end),
|
||||
{T0, Binary} = timer:tc(fun() -> gmb_fate_code:serialize(FateCode) end),
|
||||
?WHENFAIL(eqc:format("serialized:\n ~120p~n", [Binary]),
|
||||
begin
|
||||
{T1, Decoded} = timer:tc(fun() -> aeb_fate_code:deserialize(Binary) end),
|
||||
{T1, Decoded} = timer:tc(fun() -> gmb_fate_code:deserialize(Binary) end),
|
||||
measure(binary_size, size(Binary),
|
||||
measure(serialize, T0 / 1000,
|
||||
measure(deserialize, T1 / 1000,
|
||||
@ -44,20 +44,20 @@ prop_serializes() ->
|
||||
prop_fail_serializes() ->
|
||||
conjunction([{Failure, eqc:counterexample(
|
||||
?FORALL(FateCode, fate_code(Failure),
|
||||
?FORALL(Binary, catch aeb_fate_code:serialize(FateCode),
|
||||
?FORALL(Binary, catch gmb_fate_code:serialize(FateCode),
|
||||
is_binary(Binary))))
|
||||
=/= true} || Failure <- [1, 2, 3, 4, 5] ]).
|
||||
|
||||
prop_fuzz() ->
|
||||
in_parallel(
|
||||
?FORALL(Binary, ?LET(FateCode, fate_code(0), aeb_fate_code:serialize(FateCode)),
|
||||
?FORALL(Binary, ?LET(FateCode, fate_code(0), gmb_fate_code:serialize(FateCode)),
|
||||
?FORALL(FuzzedBin, fuzz(Binary),
|
||||
try aeb_fate_code:deserialize(FuzzedBin) of
|
||||
try gmb_fate_code:deserialize(FuzzedBin) of
|
||||
Code ->
|
||||
?WHENFAIL(eqc:format("Code:\n ~p\n", [Code]),
|
||||
begin
|
||||
Bin1 = aeb_fate_code:serialize(Code),
|
||||
Code1 = aeb_fate_code:deserialize(Bin1),
|
||||
Bin1 = gmb_fate_code:serialize(Code),
|
||||
Code1 = gmb_fate_code:deserialize(Bin1),
|
||||
?WHENFAIL(eqc:format("Reserialized\n ~120p\n", [Bin1]),
|
||||
equals(Code, Code1))
|
||||
end)
|
||||
@ -66,10 +66,10 @@ prop_fuzz() ->
|
||||
|
||||
prop_opcodes() ->
|
||||
?FORALL(Opcode, choose(0, 16#ff),
|
||||
try M = aeb_fate_opcodes:mnemonic(Opcode),
|
||||
try M = gmb_fate_opcodes:mnemonic(Opcode),
|
||||
?WHENFAIL(eqc:format("opcode ~p -> ~p", [Opcode, M]),
|
||||
conjunction([{valid, lists:member(Opcode, valid_opcodes())},
|
||||
{eq, equals(aeb_fate_opcodes:m_to_op(M), Opcode)}]))
|
||||
{eq, equals(gmb_fate_opcodes:m_to_op(M), Opcode)}]))
|
||||
catch
|
||||
_:_ ->
|
||||
not lists:member(Opcode, valid_opcodes())
|
||||
@ -77,7 +77,7 @@ prop_opcodes() ->
|
||||
|
||||
|
||||
valid_opcodes() ->
|
||||
[ Op || #{opcode := Op} <- aeb_fate_generate_ops:get_ops() ].
|
||||
[ Op || #{opcode := Op} <- gmb_fate_generate_ops:get_ops() ].
|
||||
|
||||
|
||||
fate_code(Failure) ->
|
||||
@ -86,13 +86,13 @@ fate_code(Failure) ->
|
||||
{non_empty(map(if Failure == 1 -> binary(1);
|
||||
true -> binary(4) end,
|
||||
{sublist(lists:sort([private, payable])), %% deserialize sorts them
|
||||
{list(aefate_type_eqc:fate_type(Size div 3)), aefate_type_eqc:fate_type(Size div 3)}, bbs_code(Failure)})),
|
||||
{list(gmfate_type_eqc:fate_type(Size div 3)), gmfate_type_eqc:fate_type(Size div 3)}, bbs_code(Failure)})),
|
||||
small_map(small_fate_data_key(5), small_fate_data(4)),
|
||||
small_map(small_fate_data_key(5), small_fate_data(4))},
|
||||
aeb_fate_code:update_annotations(
|
||||
aeb_fate_code:update_symbols(
|
||||
aeb_fate_code:update_functions(
|
||||
aeb_fate_code:new(), FMap), SMap), AMap))).
|
||||
gmb_fate_code:update_annotations(
|
||||
gmb_fate_code:update_symbols(
|
||||
gmb_fate_code:update_functions(
|
||||
gmb_fate_code:new(), FMap), SMap), AMap))).
|
||||
|
||||
short_list(Max, Gen) ->
|
||||
?LET(N, choose(0, Max), eqc_gen:list(N, Gen)).
|
||||
@ -108,7 +108,7 @@ bbs_code(Failure) ->
|
||||
lists:zip(lists:seq(0, length(BBs)-1), BBs)))}]).
|
||||
|
||||
bb_code(Failure) ->
|
||||
EndBB = [ Op || Op <- valid_opcodes(), aeb_fate_opcodes:end_bb(Op) ],
|
||||
EndBB = [ Op || Op <- valid_opcodes(), gmb_fate_opcodes:end_bb(Op) ],
|
||||
NonEndBB = valid_opcodes() -- EndBB,
|
||||
frequency(
|
||||
[{if Failure == 3 -> 5; true -> 0 end, ?LET(Ops, non_empty(short_list(6, elements(NonEndBB))), bblock(Failure, Ops))},
|
||||
@ -118,8 +118,8 @@ bb_code(Failure) ->
|
||||
|
||||
bblock(Failure, Ops) ->
|
||||
[ begin
|
||||
Mnemonic = aeb_fate_opcodes:mnemonic(Op),
|
||||
Arity = aeb_fate_opcodes:args(Op),
|
||||
Mnemonic = gmb_fate_opcodes:mnemonic(Op),
|
||||
Arity = gmb_fate_opcodes:args(Op),
|
||||
case Arity of
|
||||
0 -> Mnemonic;
|
||||
_ -> list_to_tuple([Mnemonic |
|
||||
@ -143,7 +143,7 @@ fuzz(Binary) ->
|
||||
prop_small() ->
|
||||
?FORALL(Value, small_fate_data(4),
|
||||
begin
|
||||
Bin = aeb_fate_encoding:serialize(Value),
|
||||
Bin = gmb_fate_encoding:serialize(Value),
|
||||
Size = byte_size(Bin),
|
||||
measure(size, Size,
|
||||
?WHENFAIL(eqc:format("Size: ~p\n", [Size]),
|
||||
@ -151,9 +151,9 @@ prop_small() ->
|
||||
end).
|
||||
|
||||
prop_small_type() ->
|
||||
?FORALL(Type, ?SIZED(Size, aefate_type_eqc:fate_type(Size div 3)),
|
||||
?FORALL(Type, ?SIZED(Size, gmfate_type_eqc:fate_type(Size div 3)),
|
||||
begin
|
||||
Bin = iolist_to_binary(aeb_fate_encoding:serialize_type(Type)),
|
||||
Bin = iolist_to_binary(gmb_fate_encoding:serialize_type(Type)),
|
||||
Size = byte_size(Bin),
|
||||
measure(size, Size,
|
||||
?WHENFAIL(eqc:format("Size: ~p\n", [Size]),
|
||||
@ -161,7 +161,7 @@ prop_small_type() ->
|
||||
end).
|
||||
|
||||
small_fate_data(N) ->
|
||||
?SIZED(Size, resize(Size div N, aefate_eqc:fate_data())).
|
||||
?SIZED(Size, resize(Size div N, gmfate_eqc:fate_data())).
|
||||
|
||||
small_fate_data_key(N) ->
|
||||
?SIZED(Size, ?LET(Data, aefate_eqc:fate_data(Size div N, []), eqc_symbolic:eval(Data))).
|
||||
?SIZED(Size, ?LET(Data, gmfate_eqc:fate_data(Size div N, []), eqc_symbolic:eval(Data))).
|
@ -7,10 +7,10 @@
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aefate_eqc).
|
||||
-module(gmfate_eqc).
|
||||
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
-include("../include/aeb_fate_data.hrl").
|
||||
-include("../include/gmb_fate_data.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
@ -18,17 +18,17 @@ prop_roundtrip() ->
|
||||
?FORALL(FateData, fate_data(),
|
||||
measure(bytes, size(term_to_binary(FateData)),
|
||||
begin
|
||||
Serialized = aeb_fate_encoding:serialize(FateData),
|
||||
Serialized = gmb_fate_encoding:serialize(FateData),
|
||||
?WHENFAIL(eqc:format("Serialized ~p to ~p~n", [FateData, Serialized]),
|
||||
equals(aeb_fate_encoding:deserialize(Serialized), FateData))
|
||||
equals(gmb_fate_encoding:deserialize(Serialized), FateData))
|
||||
end)).
|
||||
|
||||
prop_format_scan() ->
|
||||
?FORALL(FateData, fate_data([variant, map]),
|
||||
?WHENFAIL(eqc:format("Trying to format ~p failed~n", [FateData]),
|
||||
begin
|
||||
String = aeb_fate_data:format(FateData),
|
||||
{ok, _Scanned, _} = aeb_fate_asm_scan:scan(unicode:characters_to_list(String)),
|
||||
String = gmb_fate_data:format(FateData),
|
||||
{ok, _Scanned, _} = gmb_fate_asm_scan:scan(unicode:characters_to_list(String)),
|
||||
true
|
||||
end)).
|
||||
|
||||
@ -36,8 +36,8 @@ prop_serializes() ->
|
||||
?FORALL({Data, Garbage}, {fate_data(), binary()},
|
||||
?WHENFAIL(eqc:format("Trying to serialize/deserialize ~p failed~n", [Data]),
|
||||
begin
|
||||
Binary = <<(aeb_fate_encoding:serialize(Data))/binary, Garbage/binary>>,
|
||||
{FateData, Rest} = aeb_fate_encoding:deserialize_one(Binary),
|
||||
Binary = <<(gmb_fate_encoding:serialize(Data))/binary, Garbage/binary>>,
|
||||
{FateData, Rest} = gmb_fate_encoding:deserialize_one(Binary),
|
||||
measure(binary_size, size(Binary),
|
||||
conjunction([{equal, equals(Data, FateData)},
|
||||
{rest, equals(Garbage, Rest)},
|
||||
@ -48,7 +48,7 @@ prop_no_maps_in_keys() ->
|
||||
?FORALL(FateData, fate_bad_map(), %% may contain a map in its keys
|
||||
begin
|
||||
HasMapInKeys = lists:any(fun(K) -> has_map(K) end, maps:keys(FateData)),
|
||||
try aeb_fate_encoding:serialize(FateData),
|
||||
try gmb_fate_encoding:serialize(FateData),
|
||||
?WHENFAIL(eqc:format("Should not serialize, contains a map in key\n", []),
|
||||
not HasMapInKeys)
|
||||
catch error:Reason ->
|
||||
@ -58,11 +58,11 @@ prop_no_maps_in_keys() ->
|
||||
|
||||
prop_fuzz() ->
|
||||
in_parallel(
|
||||
?FORALL(Binary, ?LET(FateData, ?SIZED(Size, resize(Size div 4, fate_data())), aeb_fate_encoding:serialize(FateData)),
|
||||
?FORALL(Binary, ?LET(FateData, ?SIZED(Size, resize(Size div 4, fate_data())), gmb_fate_encoding:serialize(FateData)),
|
||||
?FORALL(InjectedBin, injection(Binary),
|
||||
try Org = aeb_fate_encoding:deserialize(InjectedBin),
|
||||
NewBin = aeb_fate_encoding:serialize(Org),
|
||||
NewOrg = aeb_fate_encoding:deserialize(NewBin),
|
||||
try Org = gmb_fate_encoding:deserialize(InjectedBin),
|
||||
NewBin = gmb_fate_encoding:serialize(Org),
|
||||
NewOrg = gmb_fate_encoding:deserialize(NewBin),
|
||||
measure(success, 1,
|
||||
?WHENFAIL(eqc:format("Deserialize ~p gives\n~p\nSerializes to ~p\n", [InjectedBin, Org, NewOrg]),
|
||||
equals(NewBin, InjectedBin)))
|
||||
@ -77,20 +77,20 @@ prop_order() ->
|
||||
%% Use lt to take minimum
|
||||
Min = lt_min(Items),
|
||||
Max = lt_max(Items),
|
||||
conjunction([ {minimum, is_empty([ {Min, '>', I} || I<-Items, aeb_fate_data:lt(I, Min)])},
|
||||
{maximum, is_empty([ {Max, '<', I} || I<-Items, aeb_fate_data:lt(Max, I)])},
|
||||
{asym, aeb_fate_data:lt(Min, Max) orelse Min == Max}])
|
||||
conjunction([ {minimum, is_empty([ {Min, '>', I} || I<-Items, gmb_fate_data:lt(I, Min)])},
|
||||
{maximum, is_empty([ {Max, '<', I} || I<-Items, gmb_fate_data:lt(Max, I)])},
|
||||
{asym, gmb_fate_data:lt(Min, Max) orelse Min == Max}])
|
||||
end).
|
||||
|
||||
lt_min([X, Y | Rest]) ->
|
||||
case aeb_fate_data:lt(X, Y) of
|
||||
case gmb_fate_data:lt(X, Y) of
|
||||
true -> lt_min([X | Rest]);
|
||||
false -> lt_min([Y| Rest])
|
||||
end;
|
||||
lt_min([X]) -> X.
|
||||
|
||||
lt_max([X, Y | Rest]) ->
|
||||
case aeb_fate_data:lt(X, Y) of
|
||||
case gmb_fate_data:lt(X, Y) of
|
||||
true -> lt_max([Y | Rest]);
|
||||
false -> lt_max([X| Rest])
|
||||
end;
|
||||
@ -98,8 +98,8 @@ lt_max([X]) -> X.
|
||||
|
||||
prop_idempotent() ->
|
||||
?FORALL(Items, list({fate_data_key(), fate_data()}),
|
||||
equals(aeb_fate_encoding:sort(Items),
|
||||
aeb_fate_encoding:sort(aeb_fate_encoding:sort(Items)))).
|
||||
equals(gmb_fate_encoding:sort(Items),
|
||||
gmb_fate_encoding:sort(gmb_fate_encoding:sort(Items)))).
|
||||
|
||||
|
||||
|
||||
@ -131,20 +131,20 @@ fate_data(Size, Options) ->
|
||||
|| lists:member(map, Options)])).
|
||||
|
||||
|
||||
fate_integer() -> ?LET(X, oneof([int(), largeint()]), return(aeb_fate_data:make_integer(X))).
|
||||
fate_bits() -> ?LET(X, oneof([int(), largeint()]), return(aeb_fate_data:make_bits(X))).
|
||||
fate_boolean() -> ?LET(X, elements([true, false]), return(aeb_fate_data:make_boolean(X))).
|
||||
fate_nil() -> aeb_fate_data:make_list([]).
|
||||
fate_unit() -> aeb_fate_data:make_unit().
|
||||
fate_integer() -> ?LET(X, oneof([int(), largeint()]), return(gmb_fate_data:make_integer(X))).
|
||||
fate_bits() -> ?LET(X, oneof([int(), largeint()]), return(gmb_fate_data:make_bits(X))).
|
||||
fate_boolean() -> ?LET(X, elements([true, false]), return(gmb_fate_data:make_boolean(X))).
|
||||
fate_nil() -> gmb_fate_data:make_list([]).
|
||||
fate_unit() -> gmb_fate_data:make_unit().
|
||||
fate_string() -> ?LET(X, frequency([{10, non_quote_string()}, {2, list(non_quote_string())},
|
||||
{1, ?LET(N, choose(64-3, 64+3), vector(N, $a))}]),
|
||||
return(aeb_fate_data:make_string(X))).
|
||||
fate_address() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_address(X))).
|
||||
fate_bytes() -> ?LET(X, non_empty(binary()), return(aeb_fate_data:make_bytes(X))).
|
||||
fate_contract() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_contract(X))).
|
||||
fate_oracle() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_oracle(X))).
|
||||
fate_oracle_q() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_oracle_query(X))).
|
||||
fate_channel() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_channel(X))).
|
||||
return(gmb_fate_data:make_string(X))).
|
||||
fate_address() -> ?LET(X, binary(256 div 8), return(gmb_fate_data:make_address(X))).
|
||||
fate_bytes() -> ?LET(X, non_empty(binary()), return(gmb_fate_data:make_bytes(X))).
|
||||
fate_contract() -> ?LET(X, binary(256 div 8), return(gmb_fate_data:make_contract(X))).
|
||||
fate_oracle() -> ?LET(X, binary(256 div 8), return(gmb_fate_data:make_oracle(X))).
|
||||
fate_oracle_q() -> ?LET(X, binary(256 div 8), return(gmb_fate_data:make_oracle_query(X))).
|
||||
fate_channel() -> ?LET(X, binary(256 div 8), return(gmb_fate_data:make_channel(X))).
|
||||
|
||||
fate_values(Size, N, Options) ->
|
||||
eqc_gen:list(N, fate_data(Size div max(1, N), Options)).
|
||||
@ -153,34 +153,34 @@ fate_values(Size, N, Options) ->
|
||||
fate_tuple(Size, Options) ->
|
||||
?LET(N, choose(0, 6),
|
||||
?LETSHRINK(Elements, fate_values(Size, N, Options),
|
||||
return(aeb_fate_data:make_tuple(list_to_tuple(Elements))))).
|
||||
return(gmb_fate_data:make_tuple(list_to_tuple(Elements))))).
|
||||
|
||||
fate_variant(Size, Options) ->
|
||||
?LET({L1, L2, {tuple, Args}}, {list(choose(0, 255)), list(choose(0,255)), fate_tuple(Size, Options)},
|
||||
return(aeb_fate_data:make_variant(L1 ++ [tuple_size(Args)] ++ L2,
|
||||
return(gmb_fate_data:make_variant(L1 ++ [tuple_size(Args)] ++ L2,
|
||||
length(L1), Args))).
|
||||
|
||||
fate_list(Size, Options) ->
|
||||
?LET(N, frequency([{20, choose(0, 6)}, {1, choose(64 - 3, 64 + 3)}]),
|
||||
?LETSHRINK(Vs, fate_values(Size, N, Options),
|
||||
return(aeb_fate_data:make_list(Vs)))).
|
||||
return(gmb_fate_data:make_list(Vs)))).
|
||||
|
||||
fate_map(Size, Options) ->
|
||||
?LET(N, choose(0, 6),
|
||||
?LETSHRINK(Values, fate_values(Size, N, Options),
|
||||
?LET(Keys, vector(length(Values), fate_data(Size div max(1, N * 2), Options -- [map, store_map])),
|
||||
return(aeb_fate_data:make_map(maps:from_list(lists:zip(Keys, Values))))))).
|
||||
return(gmb_fate_data:make_map(maps:from_list(lists:zip(Keys, Values))))))).
|
||||
|
||||
fate_store_map() ->
|
||||
%% only #{} is allowed as cache in serialization
|
||||
?LET(X, oneof([int(), largeint()]),
|
||||
return(aeb_fate_data:make_store_map(abs(X)))).
|
||||
return(gmb_fate_data:make_store_map(abs(X)))).
|
||||
|
||||
fate_bad_map() ->
|
||||
?LET(N, choose(0, 6),
|
||||
?LET(Values, vector(N, ?SIZED(Size, resize(Size div 8, fate_data()))),
|
||||
?LET(Keys, vector(N, ?SIZED(Size, resize(Size div 4, fate_data()))),
|
||||
return(aeb_fate_data:make_map(maps:from_list(lists:zip(Keys, Values))))))).
|
||||
return(gmb_fate_data:make_map(maps:from_list(lists:zip(Keys, Values))))))).
|
||||
|
||||
non_quote_string() ->
|
||||
?SUCHTHAT(S, utf8(), [ quote || <<34>> <= S ] == []).
|
@ -5,7 +5,7 @@
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aefate_type_eqc).
|
||||
-module(gmfate_type_eqc).
|
||||
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
|
||||
@ -18,11 +18,11 @@ prop_roundtrip() ->
|
||||
?FORALL(FateType, fate_type(),
|
||||
collect(kind(FateType),
|
||||
begin
|
||||
Serialized = aeb_fate_encoding:serialize_type(FateType),
|
||||
Serialized = gmb_fate_encoding:serialize_type(FateType),
|
||||
BinSerialized = list_to_binary(Serialized),
|
||||
?WHENFAIL(eqc:format("Serialized ~p to ~p (~p)~n", [FateType, Serialized, BinSerialized]),
|
||||
begin
|
||||
{Type, <<>>} = aeb_fate_encoding:deserialize_type(BinSerialized),
|
||||
{Type, <<>>} = gmb_fate_encoding:deserialize_type(BinSerialized),
|
||||
equals(Type, FateType)
|
||||
end)
|
||||
end)).
|
22
rebar.config
22
rebar.config
@ -5,14 +5,14 @@
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [ {eblake2, "1.0.0"}
|
||||
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
||||
{ref, "eb68fe3"}}}
|
||||
, {gmserialization, {git, "https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||
{ref, "9d2ecc00d32ea295309563e54a81636ecb597e96"}}}
|
||||
, {getopt, "1.0.1"}
|
||||
]}.
|
||||
|
||||
{escript_incl_apps, [aebytecode, eblake2, aeserialization, getopt]}.
|
||||
{escript_main_app, aebytecode}.
|
||||
{escript_name, aefateasm}.
|
||||
{escript_incl_apps, [gmbytecode, eblake2, gmserialization, getopt]}.
|
||||
{escript_main_app, gmbytecode}.
|
||||
{escript_name, gmfateasm}.
|
||||
{escript_emu_args, "%%!"}.
|
||||
|
||||
{pre_hooks,
|
||||
@ -29,8 +29,8 @@
|
||||
]}.
|
||||
|
||||
|
||||
{relx, [{release, {aebytecode, "2.0.1"},
|
||||
[aebytecode, eblake2, getopt]},
|
||||
{relx, [{release, {gmbytecode, "3.4.1"},
|
||||
[gmbytecode, eblake2, getopt]},
|
||||
|
||||
{dev_mode, true},
|
||||
{include_erts, false},
|
||||
@ -39,17 +39,17 @@
|
||||
|
||||
{profiles, [{binary, [
|
||||
{deps, [ {eblake2, "1.0.0"}
|
||||
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
||||
{ref, "47aaa8f"}}}
|
||||
, {gmserialization, {git, "https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||
{ref, "9d2ecc00d32ea295309563e54a81636ecb597e96"}}}
|
||||
, {getopt, "1.0.1"}
|
||||
]},
|
||||
|
||||
{post_hooks, [{"(linux|darwin|solaris|freebsd|netbsd|openbsd)",
|
||||
escriptize,
|
||||
"cp \"$REBAR_BUILD_DIR/bin/aefateasm\" ./aefateasm"},
|
||||
"cp \"$REBAR_BUILD_DIR/bin/gmfateasm\" ./gmfateasm"},
|
||||
{"win32",
|
||||
escriptize,
|
||||
"robocopy \"%REBAR_BUILD_DIR%/bin/\" ./ aefateasm* "
|
||||
"robocopy \"%REBAR_BUILD_DIR%/bin/\" ./ gmfateasm* "
|
||||
"/njs /njh /nfl /ndl & exit /b 0"} % silence things
|
||||
]}
|
||||
]},
|
||||
|
14
rebar.lock
14
rebar.lock
@ -1,16 +1,16 @@
|
||||
{"1.2.0",
|
||||
[{<<"aeserialization">>,
|
||||
{git,"https://github.com/aeternity/aeserialization.git",
|
||||
{ref,"eb68fe331bd476910394966b7f5ede7a74d37e35"}},
|
||||
[{<<"gmserialization">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||
{ref,"9d2ecc00d32ea295309563e54a81636ecb597e96"}},
|
||||
0},
|
||||
{<<"base58">>,
|
||||
{git,"https://github.com/aeternity/erl-base58.git",
|
||||
{ref,"60a335668a60328a29f9731b67c4a0e9e3d50ab6"}},
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/erl-base58.git",
|
||||
{ref,"e6aa62eeae3d4388311401f06e4b939bf4e94b9c"}},
|
||||
1},
|
||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
||||
{<<"enacl">>,
|
||||
{git,"https://github.com/aeternity/enacl.git",
|
||||
{ref,"793ddb502f7fe081302e1c42227dca70b09f8e17"}},
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/enacl.git",
|
||||
{ref,"4eb7ec70084ba7c87b1af8797c4c4e90c84f95a2"}},
|
||||
1},
|
||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}]}.
|
||||
[
|
||||
|
@ -1,13 +1,16 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Encode and decode data and function calls according to
|
||||
%%% Sophia-AEVM-ABI
|
||||
%%% @end
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 25 Jan 2018
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeb_aevm_abi).
|
||||
-module(gmb_aevm_abi).
|
||||
-vsn("3.4.1").
|
||||
-define(HASH_SIZE, 32).
|
||||
|
||||
-export([ create_calldata/4
|
||||
@ -25,7 +28,7 @@
|
||||
|
||||
-type hash() :: <<_:256>>. %% 256 = ?HASH_SIZE * 8.
|
||||
-type function_name() :: binary(). %% String
|
||||
-type typerep() :: aeb_aevm_data:type().
|
||||
-type typerep() :: gmb_aevm_data:type().
|
||||
-type function_type_info() :: { FunctionHash :: hash()
|
||||
, FunctionName :: function_name()
|
||||
, Payable :: boolean()
|
||||
@ -50,7 +53,7 @@ create_calldata(FunName, Args, ArgTypes0, RetType) ->
|
||||
ArgTypes = {tuple, ArgTypes0},
|
||||
<<TypeHashInt:?HASH_SIZE/unit:8>> =
|
||||
function_type_hash(list_to_binary(FunName), ArgTypes, RetType),
|
||||
Data = aeb_heap:to_binary({TypeHashInt, list_to_tuple(Args)}),
|
||||
Data = gmb_heap:to_binary({TypeHashInt, list_to_tuple(Args)}),
|
||||
{ok, Data}.
|
||||
|
||||
-spec check_calldata(binary(), type_info(), boolean()) ->
|
||||
@ -73,7 +76,7 @@ check_calldata(Hash, CallData, TypeInfo, true) ->
|
||||
check_calldata(Hash, CallData, TypeInfo, false) ->
|
||||
case typereps_from_type_hash(Hash, TypeInfo) of
|
||||
{ok, ArgType, OutType} ->
|
||||
try aeb_heap:from_binary({tuple, [word, ArgType]}, CallData) of
|
||||
try gmb_heap:from_binary({tuple, [word, ArgType]}, CallData) of
|
||||
{ok, _Something} ->
|
||||
{ok, {tuple, [word, ArgType]}, OutType};
|
||||
{error, _} ->
|
||||
@ -90,7 +93,7 @@ check_calldata(Hash, CallData, TypeInfo, false) ->
|
||||
-spec get_function_hash_from_calldata(CallData::binary()) ->
|
||||
{ok, binary()} | {error, term()}.
|
||||
get_function_hash_from_calldata(CallData) ->
|
||||
case aeb_heap:from_binary({tuple, [word]}, CallData) of
|
||||
case gmb_heap:from_binary({tuple, [word]}, CallData) of
|
||||
{ok, {HashInt}} -> {ok, <<HashInt:?HASH_SIZE/unit:8>>};
|
||||
{error, _} = Error -> Error
|
||||
end.
|
||||
@ -105,15 +108,15 @@ function_type_info(Name, Payable, ArgTypes, OutType) ->
|
||||
{ function_type_hash(Name, ArgType, OutType)
|
||||
, Name
|
||||
, Payable
|
||||
, aeb_heap:to_binary(ArgType)
|
||||
, aeb_heap:to_binary(OutType)
|
||||
, gmb_heap:to_binary(ArgType)
|
||||
, gmb_heap:to_binary(OutType)
|
||||
}.
|
||||
|
||||
-spec function_type_hash(function_name(), typerep(), typerep()) -> hash().
|
||||
function_type_hash(Name, ArgType, OutType) when is_binary(Name) ->
|
||||
Bin = iolist_to_binary([ Name
|
||||
, aeb_heap:to_binary(ArgType)
|
||||
, aeb_heap:to_binary(OutType)
|
||||
, gmb_heap:to_binary(ArgType)
|
||||
, gmb_heap:to_binary(OutType)
|
||||
]),
|
||||
%% Calculate a 256 bit digest BLAKE2b hash value of a binary
|
||||
{ok, Hash} = eblake2:blake2b(?HASH_SIZE, Bin),
|
||||
@ -132,7 +135,7 @@ arg_typerep_from_function(Function, TypeInfo) ->
|
||||
end.
|
||||
|
||||
arg_typerep_from_type_binary(ArgTBin) ->
|
||||
case aeb_heap:from_binary(typerep, ArgTBin) of
|
||||
case gmb_heap:from_binary(typerep, ArgTBin) of
|
||||
{ok, ArgT} -> {ok, ArgT};
|
||||
{error,_} -> {error, bad_type_data}
|
||||
end.
|
||||
@ -150,7 +153,7 @@ typereps_from_type_hash(TypeHash, TypeInfo) ->
|
||||
end.
|
||||
|
||||
typereps_from_type_binaries(ArgTBin, OutTBin) ->
|
||||
case {aeb_heap:from_binary(typerep, ArgTBin), aeb_heap:from_binary(typerep, OutTBin)} of
|
||||
case {gmb_heap:from_binary(typerep, ArgTBin), gmb_heap:from_binary(typerep, OutTBin)} of
|
||||
{{ok, ArgT}, {ok, OutT}} -> {ok, ArgT, OutT};
|
||||
{_, _} -> {error, bad_type_data}
|
||||
end.
|
@ -1,4 +1,5 @@
|
||||
-module(aeb_aevm_data).
|
||||
-module(gmb_aevm_data).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export_type([data/0,
|
||||
type/0,
|
@ -1,4 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc Assembler for aevm machine code.
|
||||
%%%
|
||||
@ -25,17 +26,19 @@
|
||||
%%% 4. labels as descibed above.
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 21 Dec 2017
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_asm).
|
||||
-module(gmb_asm).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ file/2
|
||||
, pp/1
|
||||
, to_hexstring/1
|
||||
]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_opcodes.hrl").
|
||||
|
||||
|
||||
pp(Asm) ->
|
||||
@ -47,10 +50,10 @@ format(Asm) -> format(Asm, 0).
|
||||
format([{comment, Comment} | Rest], Address) ->
|
||||
";; " ++ Comment ++ "\n" ++ format(Rest, Address);
|
||||
format([Mnemonic | Rest], Address) ->
|
||||
Op = aeb_opcodes:m_to_op(Mnemonic),
|
||||
Op = gmb_opcodes:m_to_op(Mnemonic),
|
||||
case (Op >= ?PUSH1) andalso (Op =< ?PUSH32) of
|
||||
true ->
|
||||
Arity = aeb_opcodes:op_size(Op) - 1,
|
||||
Arity = gmb_opcodes:op_size(Op) - 1,
|
||||
{Args, Code} = get_args(Arity, Rest),
|
||||
" " ++ atom_to_list(Mnemonic)
|
||||
++ " " ++ Args ++ "\n"
|
||||
@ -72,7 +75,7 @@ get_args(N, [Arg|Code]) ->
|
||||
|
||||
file(Filename, Options) ->
|
||||
{ok, File} = file:read_file(Filename),
|
||||
{ok, Tokens, _} = aeb_asm_scan:scan(binary_to_list(File)),
|
||||
{ok, Tokens, _} = gmb_asm_scan:scan(binary_to_list(File)),
|
||||
|
||||
case proplists:lookup(pp_tokens, Options) of
|
||||
{pp_tokens, true} ->
|
||||
@ -100,8 +103,8 @@ to_hexstring(ByteList) ->
|
||||
|
||||
|
||||
to_bytecode([{mnemonic,_line, Op}|Rest], Address, Env, Code, Opts) ->
|
||||
OpCode = aeb_opcodes:m_to_op(Op),
|
||||
OpSize = aeb_opcodes:op_size(OpCode),
|
||||
OpCode = gmb_opcodes:m_to_op(Op),
|
||||
OpSize = gmb_opcodes:op_size(OpCode),
|
||||
to_bytecode(Rest, Address + OpSize, Env, [OpCode|Code], Opts);
|
||||
to_bytecode([{int,_line, Int}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env, [Int|Code], Opts);
|
||||
@ -138,7 +141,7 @@ resolve_refs([Op | Rest], Env, Code) ->
|
||||
resolve_refs([],_Env, Code) -> Code.
|
||||
|
||||
expand_args([OP, Arg | Rest]) when OP >= ?PUSH1 andalso OP =< ?PUSH32 ->
|
||||
BitSize = (aeb_opcodes:op_size(OP) - 1) * 8,
|
||||
BitSize = (gmb_opcodes:op_size(OP) - 1) * 8,
|
||||
Bin = << << X:BitSize>> || X <- [Arg] >>,
|
||||
ArgByteList = binary_to_list(Bin),
|
||||
[OP | ArgByteList] ++ expand_args(Rest);
|
@ -1,5 +1,6 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc Assembler lexer.
|
||||
%%%
|
||||
@ -195,7 +196,7 @@ Erlang code.
|
||||
|
||||
-ignore_xref([format_error/1, string/2, token/2, token/3, tokens/2, tokens/3]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_opcodes.hrl").
|
||||
|
||||
|
||||
parse_hex("0x" ++ Chars) -> list_to_integer(Chars, 16).
|
@ -1,19 +1,22 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Prettyprint aevm machine code
|
||||
%%% @end
|
||||
%%% Created : 2 Oct 2017
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 02 Oct 2017
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_disassemble).
|
||||
-module(gmb_disassemble).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ pp/1,
|
||||
format/2,
|
||||
format_address/1
|
||||
]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_opcodes.hrl").
|
||||
|
||||
|
||||
pp(Binary) ->
|
||||
@ -26,37 +29,37 @@ format(Binary, ErrFormatFun) ->
|
||||
pp(Address, [Op|Ops], Assembly, ErrFormatFun) ->
|
||||
case Op of
|
||||
X when (X >= ?STOP) andalso (X =< ?SIGNEXTEND) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?LT) andalso (X =< ?BYTE) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?SHA3) andalso (X =< ?SHA3) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?ADDRESS) andalso (X =< ?EXTCODECOPY) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?BLOCKHASH) andalso (X =< ?GASLIMIT) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?POP) andalso (X =< ?JUMPDEST) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?PUSH1) andalso (X =< ?PUSH32) ->
|
||||
Bytes = X-?PUSH1+1,
|
||||
{ArgList, NextOps} = lists:split(Bytes, Ops),
|
||||
Arg = arglist_to_arg(ArgList),
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), [{Arg,8*Bytes}]),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), [{Arg,8*Bytes}]),
|
||||
next(Address+Bytes, NextOps, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?DUP1) andalso (X =< ?LOG4) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?CREATE) andalso (X =< ?DELEGATECALL) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
X when (X >= ?INVALID) andalso (X =< ?SUICIDE) ->
|
||||
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||
Instr = pp_instruction(Address, gmb_opcodes:mnemonic(Op), []),
|
||||
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||
_ ->
|
||||
ErrFormatFun("unhandled op ~p at ~p",[Op, Address]),
|
@ -1,13 +1,16 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Encode and decode data and function calls according to
|
||||
%%% Sophia-FATE-ABI
|
||||
%%% @end
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 11 Jun 2019
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeb_fate_abi).
|
||||
-module(gmb_fate_abi).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ create_calldata/2
|
||||
, decode_calldata/2
|
||||
@ -16,7 +19,7 @@
|
||||
, get_function_type_from_function_hash/2
|
||||
, abi_version/0 ]).
|
||||
|
||||
-include("../include/aeb_fate_data.hrl").
|
||||
-include("../include/gmb_fate_data.hrl").
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
@ -29,27 +32,27 @@ abi_version() ->
|
||||
|
||||
-spec create_calldata(list(), [term()]) -> {ok, binary()}.
|
||||
create_calldata(FunName, Args) ->
|
||||
FunctionId = aeb_fate_code:symbol_identifier(list_to_binary(FunName)),
|
||||
{ok, aeb_fate_encoding:serialize(
|
||||
aeb_fate_data:make_tuple({FunctionId,
|
||||
aeb_fate_data:make_tuple(list_to_tuple(Args))}))}.
|
||||
FunctionId = gmb_fate_code:symbol_identifier(list_to_binary(FunName)),
|
||||
{ok, gmb_fate_encoding:serialize(
|
||||
gmb_fate_data:make_tuple({FunctionId,
|
||||
gmb_fate_data:make_tuple(list_to_tuple(Args))}))}.
|
||||
|
||||
-spec decode_calldata(list(), binary()) -> {ok, term()} | {error, term()}.
|
||||
decode_calldata(FunName, Calldata) ->
|
||||
FunctionId = aeb_fate_code:symbol_identifier(list_to_binary(FunName)),
|
||||
try ?FATE_TUPLE_ELEMENTS(aeb_fate_encoding:deserialize(Calldata)) of
|
||||
FunctionId = gmb_fate_code:symbol_identifier(list_to_binary(FunName)),
|
||||
try ?FATE_TUPLE_ELEMENTS(gmb_fate_encoding:deserialize(Calldata)) of
|
||||
[FunctionId, FateArgs] -> {ok, ?FATE_TUPLE_ELEMENTS(FateArgs)};
|
||||
_ -> {error, decode_error}
|
||||
catch _:_ ->
|
||||
{error, decode_error}
|
||||
end.
|
||||
|
||||
-spec get_function_name_from_function_hash(binary(), aeb_fate_code:fcode()) ->
|
||||
-spec get_function_name_from_function_hash(binary(), gmb_fate_code:fcode()) ->
|
||||
{ok, term()} | {error, term()}.
|
||||
get_function_name_from_function_hash(<<SymbolHash:4/binary, _:28/binary>>, FateCode) ->
|
||||
get_function_name_from_function_hash(SymbolHash, FateCode);
|
||||
get_function_name_from_function_hash(SymbolHash = <<_:4/binary>>, FateCode) ->
|
||||
Symbols = aeb_fate_code:symbols(FateCode),
|
||||
Symbols = gmb_fate_code:symbols(FateCode),
|
||||
case maps:get(SymbolHash, Symbols, undefined) of
|
||||
undefined -> {error, no_function_matching_function_hash};
|
||||
Function -> {ok, Function}
|
||||
@ -58,19 +61,19 @@ get_function_name_from_function_hash(SymbolHash = <<_:4/binary>>, FateCode) ->
|
||||
-spec get_function_hash_from_calldata(binary()) ->
|
||||
{ok, binary()} | {error, term()}.
|
||||
get_function_hash_from_calldata(CallData) ->
|
||||
try ?FATE_TUPLE_ELEMENTS(aeb_fate_encoding:deserialize(CallData)) of
|
||||
try ?FATE_TUPLE_ELEMENTS(gmb_fate_encoding:deserialize(CallData)) of
|
||||
[FunHash, _Args] -> {ok, FunHash};
|
||||
_ -> {error, bad_calldata}
|
||||
catch _:_ ->
|
||||
{error, bad_calldata}
|
||||
end.
|
||||
|
||||
-spec get_function_type_from_function_hash(binary(), aeb_fate_code:fcode()) ->
|
||||
-spec get_function_type_from_function_hash(binary(), gmb_fate_code:fcode()) ->
|
||||
{ok, term(), term()} | {error, term()}.
|
||||
get_function_type_from_function_hash(<<SymbolHash:4/binary, _:28/binary>>, FateCode) ->
|
||||
get_function_type_from_function_hash(SymbolHash, FateCode);
|
||||
get_function_type_from_function_hash(SymbolHash, FateCode) ->
|
||||
Functions = aeb_fate_code:functions(FateCode),
|
||||
Functions = gmb_fate_code:functions(FateCode),
|
||||
case maps:get(SymbolHash, Functions, undefined) of
|
||||
undefined ->
|
||||
{error, no_function_matching_function_hash};
|
@ -1,4 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc Assembler for Fate machine code.
|
||||
%%% @end
|
||||
@ -80,10 +81,12 @@
|
||||
%%% Size: Digits
|
||||
%%% Tag: Digits
|
||||
%%%
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 21 Dec 2017
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_fate_asm).
|
||||
-module(gmb_fate_asm).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ assemble_file/3
|
||||
, asm_to_bytecode/2
|
||||
@ -94,8 +97,8 @@
|
||||
, to_asm/1
|
||||
]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_fate_opcodes.hrl").
|
||||
-include_lib("aebytecode/include/aeb_fate_data.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_fate_opcodes.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_fate_data.hrl").
|
||||
-define(HASH_BYTES, 32).
|
||||
|
||||
assemble_file(InFile, OutFile, Options) ->
|
||||
@ -104,12 +107,12 @@ assemble_file(InFile, OutFile, Options) ->
|
||||
ok = file:write_file(OutFile, BC).
|
||||
|
||||
function_call(String) ->
|
||||
{ok, Tokens, _} = aeb_fate_asm_scan:scan(String),
|
||||
{ok, Tokens, _} = gmb_fate_asm_scan:scan(String),
|
||||
parse_function_call(Tokens).
|
||||
|
||||
parse_function_call([{id,_,Name}, {'(',_}| Rest]) ->
|
||||
{Args, []} = to_args(Rest),
|
||||
aeb_fate_encoding:serialize(
|
||||
gmb_fate_encoding:serialize(
|
||||
{tuple, {mk_hash(Name), {tuple, list_to_tuple(Args)}}}).
|
||||
|
||||
|
||||
@ -129,9 +132,9 @@ pp(FateCode) ->
|
||||
|
||||
|
||||
to_asm(FateCode) ->
|
||||
Functions = aeb_fate_code:functions(FateCode),
|
||||
Symbols = aeb_fate_code:symbols(FateCode),
|
||||
Annotations = aeb_fate_code:annotations(FateCode),
|
||||
Functions = gmb_fate_code:functions(FateCode),
|
||||
Symbols = gmb_fate_code:symbols(FateCode),
|
||||
Annotations = gmb_fate_code:annotations(FateCode),
|
||||
insert_comments(get_comments(Annotations), 1,
|
||||
lists:flatten(
|
||||
io_lib:format("~s",
|
||||
@ -191,7 +194,7 @@ format_code([], _) ->
|
||||
"";
|
||||
format_code([Op|Rest], Symbols) ->
|
||||
[" ",
|
||||
aeb_fate_pp:format_op(Op, Symbols),
|
||||
gmb_fate_pp:format_op(Op, Symbols),
|
||||
"\n",
|
||||
format_code(Rest, Symbols)].
|
||||
|
||||
@ -201,7 +204,7 @@ read_file(Filename) ->
|
||||
binary_to_list(File).
|
||||
|
||||
asm_to_bytecode(AssemblerCode, Options) ->
|
||||
{ok, Tokens, _} = aeb_fate_asm_scan:scan(AssemblerCode),
|
||||
{ok, Tokens, _} = gmb_fate_asm_scan:scan(AssemblerCode),
|
||||
|
||||
case proplists:lookup(pp_tokens, Options) of
|
||||
{pp_tokens, true} ->
|
||||
@ -209,7 +212,7 @@ asm_to_bytecode(AssemblerCode, Options) ->
|
||||
none ->
|
||||
ok
|
||||
end,
|
||||
Env = #{ fate_code => aeb_fate_code:new()
|
||||
Env = #{ fate_code => gmb_fate_code:new()
|
||||
, functions => #{}
|
||||
},
|
||||
|
||||
@ -218,11 +221,11 @@ asm_to_bytecode(AssemblerCode, Options) ->
|
||||
FunctionsMap = maps:get(functions, Env1),
|
||||
Functions = [X || {_, X} <- lists:sort(maps:to_list(FunctionsMap))],
|
||||
FunctionsBin = iolist_to_binary(Functions),
|
||||
ByteCode = aeb_fate_code:serialize(FateCode, FunctionsBin, Options),
|
||||
ByteCode = gmb_fate_code:serialize(FateCode, FunctionsBin, Options),
|
||||
{Env, ByteCode}.
|
||||
|
||||
strip(ByteCode) ->
|
||||
{Code, _Rest} = aeser_rlp:decode_one(ByteCode),
|
||||
{Code, _Rest} = gmser_rlp:decode_one(ByteCode),
|
||||
Code.
|
||||
|
||||
%% -------------------------------------------------------------------
|
||||
@ -235,7 +238,7 @@ to_bytecode([{function,_line, 'FUNCTION'}|Rest], Address, Env, Code, Opts) ->
|
||||
{Fun, Rest2} = to_fun_def(Rest),
|
||||
to_bytecode(Rest2, Fun, Env2, [], Opts);
|
||||
to_bytecode([{mnemonic,_line, Op}|Rest], Address, Env, Code, Opts) ->
|
||||
OpCode = aeb_fate_opcodes:m_to_op(Op),
|
||||
OpCode = gmb_fate_opcodes:m_to_op(Op),
|
||||
to_bytecode(Rest, Address, Env, [OpCode|Code], Opts);
|
||||
to_bytecode([{arg,_line, N}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env, [{arg, N}|Code], Opts);
|
||||
@ -249,41 +252,41 @@ to_bytecode([{boolean,_line, Bool}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env, [{immediate, Bool}|Code], Opts);
|
||||
to_bytecode([{string,_line, String}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_string(String)}|Code],
|
||||
[{immediate, gmb_fate_data:make_string(String)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{object,_line, {address, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_address(Value)}|Code],
|
||||
[{immediate, gmb_fate_data:make_address(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{object,_line, {contract, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_contract(Value)}|Code],
|
||||
[{immediate, gmb_fate_data:make_contract(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{object,_line, {oracle, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_oracle(Value)}|Code],
|
||||
[{immediate, gmb_fate_data:make_oracle(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{object,_line, {oracle_query, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_oracle_query(Value)}|Code],
|
||||
[{immediate, gmb_fate_data:make_oracle_query(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{object,_line, {channel, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_contract(Value)}|Code],
|
||||
[{immediate, gmb_fate_data:make_contract(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{bytes,_line, Value}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_bytes(Value)}|Code],
|
||||
[{immediate, gmb_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],
|
||||
[{immediate, gmb_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),
|
||||
@ -296,19 +299,19 @@ to_bytecode([{'[',_line}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest2, Address, Env, [{immediate, List}|Code], Opts);
|
||||
to_bytecode([{'(',_line}|Rest], Address, Env, Code, Opts) ->
|
||||
{Elements, Rest2} = parse_tuple(Rest),
|
||||
Tuple = aeb_fate_data:make_tuple(list_to_tuple(Elements)),
|
||||
Tuple = gmb_fate_data:make_tuple(list_to_tuple(Elements)),
|
||||
to_bytecode(Rest2, Address, Env, [{immediate, Tuple}|Code], Opts);
|
||||
to_bytecode([{start_variant,_line}|_] = Tokens, Address, Env, Code, Opts) ->
|
||||
{Arities, Tag, Values, Rest} = parse_variant(Tokens),
|
||||
Variant = aeb_fate_data:make_variant(Arities, Tag, Values),
|
||||
Variant = gmb_fate_data:make_variant(Arities, Tag, Values),
|
||||
to_bytecode(Rest, Address, Env, [{immediate, Variant}|Code], Opts);
|
||||
to_bytecode([{typerep,_line}|Rest], Address, Env, Code, Opts) ->
|
||||
{Type, Rest1} = to_type(Rest),
|
||||
TypeRep = aeb_fate_data:make_typerep(Type),
|
||||
TypeRep = gmb_fate_data:make_typerep(Type),
|
||||
to_bytecode(Rest1, Address, Env, [{immediate, TypeRep}|Code], Opts);
|
||||
to_bytecode([{bits,_line, Bits}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_bits(Bits)}|Code], Opts);
|
||||
[{immediate, gmb_fate_data:make_bits(Bits)}|Code], Opts);
|
||||
|
||||
to_bytecode([{comment, Line, Comment}|Rest], Address, Env, Code, Opts) ->
|
||||
Env2 = insert_annotation(comment, Line, Comment, Env),
|
||||
@ -383,29 +386,29 @@ parse_value([{'{',_line} | Rest]) -> parse_map(Rest);
|
||||
parse_value([{'[',_line} | Rest]) -> parse_list(Rest);
|
||||
parse_value([{'(',_line} | Rest]) ->
|
||||
{T, Rest2} = parse_tuple(Rest),
|
||||
{aeb_fate_data:make_tuple(list_to_tuple(T)), Rest2};
|
||||
{gmb_fate_data:make_tuple(list_to_tuple(T)), Rest2};
|
||||
parse_value([{bits,_line, Bits} | Rest]) ->
|
||||
{aeb_fate_data:make_bits(Bits), Rest};
|
||||
{gmb_fate_data:make_bits(Bits), Rest};
|
||||
parse_value([{start_variant,_line}|_] = Tokens) ->
|
||||
{Arities, Tag, Values, Rest} = parse_variant(Tokens),
|
||||
Variant = aeb_fate_data:make_variant(Arities, Tag, Values),
|
||||
Variant = gmb_fate_data:make_variant(Arities, Tag, Values),
|
||||
{Variant, Rest};
|
||||
parse_value([{string,_line, String} | Rest]) ->
|
||||
{aeb_fate_data:make_string(String), Rest};
|
||||
{gmb_fate_data:make_string(String), Rest};
|
||||
parse_value([{object,_line, {address, Address}} | Rest]) ->
|
||||
{aeb_fate_data:make_address(Address), Rest};
|
||||
{gmb_fate_data:make_address(Address), Rest};
|
||||
parse_value([{object,_line, {contract, Address}} | Rest]) ->
|
||||
{aeb_fate_data:make_contract(Address), Rest};
|
||||
{gmb_fate_data:make_contract(Address), Rest};
|
||||
parse_value([{object,_line, {oracle, Address}} | Rest]) ->
|
||||
{aeb_fate_data:make_oracle(Address), Rest};
|
||||
{gmb_fate_data:make_oracle(Address), Rest};
|
||||
parse_value([{object,_line, {oracle_query, Address}} | Rest]) ->
|
||||
{aeb_fate_data:make_oracle_query(Address), Rest};
|
||||
{gmb_fate_data:make_oracle_query(Address), Rest};
|
||||
parse_value([{object,_line, {channel, Address}} | Rest]) ->
|
||||
{aeb_fate_data:make_channel(Address), Rest};
|
||||
{gmb_fate_data:make_channel(Address), Rest};
|
||||
parse_value([{hash,_line, Hash} | Rest]) ->
|
||||
{aeb_fate_data:make_hash(Hash), Rest};
|
||||
{gmb_fate_data:make_hash(Hash), Rest};
|
||||
parse_value([{signature,_line, Hash} | Rest]) ->
|
||||
{aeb_fate_data:make_signature(Hash), Rest};
|
||||
{gmb_fate_data:make_signature(Hash), Rest};
|
||||
parse_value([{typerep,_line} | Rest]) ->
|
||||
to_type(Rest).
|
||||
|
||||
@ -485,20 +488,20 @@ insert_fun(none, [], Env) -> Env;
|
||||
insert_fun({NameString, ArgType, RetType}, Code, #{ fate_code := FateCode
|
||||
, functions := Funs} = Env) ->
|
||||
Name = list_to_binary(NameString),
|
||||
{FateCode1, Id} = aeb_fate_code:insert_symbol(Name, FateCode),
|
||||
BodyByteCode = aeb_fate_code:serialize_code(lists:reverse(Code)),
|
||||
SigByteCode = aeb_fate_code:serialize_signature({ArgType, RetType}),
|
||||
FunByteCode = [?FUNCTION, Id, aeb_fate_encoding:serialize(0), SigByteCode, BodyByteCode],
|
||||
{FateCode1, Id} = gmb_fate_code:insert_symbol(Name, FateCode),
|
||||
BodyByteCode = gmb_fate_code:serialize_code(lists:reverse(Code)),
|
||||
SigByteCode = gmb_fate_code:serialize_signature({ArgType, RetType}),
|
||||
FunByteCode = [?FUNCTION, Id, gmb_fate_encoding:serialize(0), SigByteCode, BodyByteCode],
|
||||
Env#{ functions => Funs#{ Id => FunByteCode }
|
||||
, fate_code => FateCode1}.
|
||||
|
||||
insert_symbol(Name, #{ fate_code := FateCode } = Env) ->
|
||||
{FateCode1, Id} = aeb_fate_code:insert_symbol(Name, FateCode),
|
||||
{FateCode1, Id} = gmb_fate_code:insert_symbol(Name, FateCode),
|
||||
{ Env#{ fate_code => FateCode1 }
|
||||
, Id}.
|
||||
|
||||
insert_annotation(comment, Line, Comment, #{ fate_code := FateCode } = Env) ->
|
||||
FateCode1 = aeb_fate_code:insert_annotation(comment, Line, Comment, FateCode),
|
||||
FateCode1 = gmb_fate_code:insert_annotation(comment, Line, Comment, FateCode),
|
||||
Env#{ fate_code => FateCode1}.
|
||||
|
||||
mk_hash(Id) ->
|
@ -1,6 +1,7 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2019, aeternity Anstalt
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Handling FATE code.
|
||||
%%% @end
|
||||
@ -100,7 +101,7 @@ Erlang code.
|
||||
|
||||
-ignore_xref([format_error/1, string/2, token/2, token/3, tokens/2, tokens/3]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_fate_opcodes.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_fate_opcodes.hrl").
|
||||
|
||||
|
||||
parse_hex("0x" ++ Chars) -> list_to_integer(Chars, 16).
|
||||
@ -115,12 +116,12 @@ parse_hash("#" ++ Chars) ->
|
||||
base64:decode(Chars).
|
||||
|
||||
parse_contract_bytearray("@" ++ Chars) ->
|
||||
case aeser_api_encoder:decode(unicode:characters_to_binary(Chars)) of
|
||||
case gmser_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
|
||||
case gmser_api_encoder:decode(unicode:characters_to_binary(Chars)) of
|
||||
{account_pubkey, Bin} -> {address, Bin};
|
||||
{contract_pubkey, Bin} -> {contract, Bin};
|
||||
{oracle_pubkey, Bin} -> {oracle, Bin};
|
@ -1,11 +1,13 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% ADT for fate byte code/fate code
|
||||
%%% @end
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeb_fate_code).
|
||||
-module(gmb_fate_code).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ annotations/1
|
||||
, deserialize/1
|
||||
@ -24,14 +26,12 @@
|
||||
, symbols/1
|
||||
]).
|
||||
|
||||
-include("../include/aeb_fate_opcodes.hrl").
|
||||
-include("../include/aeb_fate_data.hrl").
|
||||
-include("../include/gmb_fate_opcodes.hrl").
|
||||
-include("../include/gmb_fate_data.hrl").
|
||||
|
||||
-ifdef(EQC).
|
||||
-export([ update_annotations/2
|
||||
, update_functions/2
|
||||
, update_symbols/2]).
|
||||
-endif.
|
||||
|
||||
-record(fcode, { functions = #{} :: map()
|
||||
, symbols = #{} :: map()
|
||||
@ -89,8 +89,8 @@ insert_symbol(Name, #fcode{ symbols = Syms } = F) ->
|
||||
end.
|
||||
|
||||
insert_annotation(comment =_Type, Line, Comment, FCode) ->
|
||||
Key = aeb_fate_data:make_tuple({aeb_fate_data:make_string("comment"), Line}),
|
||||
Value = aeb_fate_data:make_string(Comment),
|
||||
Key = gmb_fate_data:make_tuple({gmb_fate_data:make_string("comment"), Line}),
|
||||
Value = gmb_fate_data:make_string(Comment),
|
||||
update_annotations(FCode, #{ Key => Value }).
|
||||
|
||||
strip_init_function(#fcode{ functions = Funs,
|
||||
@ -113,9 +113,9 @@ serialize(#fcode{} = F, Options) ->
|
||||
serialize(#fcode{} = F, Functions, Options) ->
|
||||
SymbolTable = serialize_symbol_table(F),
|
||||
Annotatations = serialize_annotations(F),
|
||||
ByteCode = << (aeser_rlp:encode(Functions))/binary,
|
||||
(aeser_rlp:encode(SymbolTable))/binary,
|
||||
(aeser_rlp:encode(Annotatations))/binary
|
||||
ByteCode = << (gmser_rlp:encode(Functions))/binary,
|
||||
(gmser_rlp:encode(SymbolTable))/binary,
|
||||
(gmser_rlp:encode(Annotatations))/binary
|
||||
>>,
|
||||
|
||||
case proplists:lookup(pp_hex_string, Options) of
|
||||
@ -141,20 +141,20 @@ serialize_functions(#fcode{ functions = Functions }) ->
|
||||
|
||||
serialize_attributes(Attrs) ->
|
||||
AttrVal = lists:sum([ attr_value(Attr) || Attr <- Attrs ]),
|
||||
aeb_fate_encoding:serialize(?MAKE_FATE_INTEGER(AttrVal)).
|
||||
gmb_fate_encoding:serialize(?MAKE_FATE_INTEGER(AttrVal)).
|
||||
|
||||
attr_value(private) -> 1;
|
||||
attr_value(payable) -> 2.
|
||||
|
||||
serialize_signature({Args, RetType}) ->
|
||||
[aeb_fate_encoding:serialize_type({tuple, Args}) |
|
||||
aeb_fate_encoding:serialize_type(RetType)].
|
||||
[gmb_fate_encoding:serialize_type({tuple, Args}) |
|
||||
gmb_fate_encoding:serialize_type(RetType)].
|
||||
|
||||
serialize_symbol_table(#fcode{ symbols = Symbols }) ->
|
||||
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)).
|
||||
gmb_fate_encoding:serialize(gmb_fate_data:make_map(Symbols)).
|
||||
|
||||
serialize_annotations(#fcode{ annotations = Annotations }) ->
|
||||
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)).
|
||||
gmb_fate_encoding:serialize(gmb_fate_data:make_map(Annotations)).
|
||||
|
||||
serialize_bbs(#{} = BBs) ->
|
||||
serialize_bbs(BBs, 0, []).
|
||||
@ -176,7 +176,7 @@ serialize_op(Op) ->
|
||||
true -> tuple_to_list(Op);
|
||||
false -> [Op]
|
||||
end,
|
||||
[aeb_fate_opcodes:m_to_op(Mnemonic) | serialize_code(Args)].
|
||||
[gmb_fate_opcodes:m_to_op(Mnemonic) | serialize_code(Args)].
|
||||
|
||||
sanity_check(#fcode{ functions = Funs }) ->
|
||||
_ = [ case Def of
|
||||
@ -215,12 +215,12 @@ sanity_check_op(IsLast, Op) ->
|
||||
true -> tuple_to_list(Op);
|
||||
false -> [Op]
|
||||
end,
|
||||
safe_sanity_check(IsLast, aeb_fate_opcodes:m_to_op(Mnemonic), Args).
|
||||
safe_sanity_check(IsLast, gmb_fate_opcodes:m_to_op(Mnemonic), Args).
|
||||
|
||||
safe_sanity_check(IsLast, Op, Args) ->
|
||||
case length(Args) == aeb_fate_opcodes:args(Op) of
|
||||
case length(Args) == gmb_fate_opcodes:args(Op) of
|
||||
true ->
|
||||
case IsLast == aeb_fate_opcodes:end_bb(Op) of
|
||||
case IsLast == gmb_fate_opcodes:end_bb(Op) of
|
||||
true -> ok;
|
||||
false -> error({wrong_opcode_in_bb, Op})
|
||||
end;
|
||||
@ -271,7 +271,7 @@ pad_args(List) ->
|
||||
end.
|
||||
|
||||
serialize_data(_, Data) ->
|
||||
aeb_fate_encoding:serialize(Data).
|
||||
gmb_fate_encoding:serialize(Data).
|
||||
|
||||
%% 00 : stack/unused (depending on instruction)
|
||||
%% 01 : argN
|
||||
@ -293,9 +293,9 @@ bits_to_modifier(2#00) -> stack.
|
||||
%%%===================================================================
|
||||
|
||||
deserialize(Bytes) ->
|
||||
{ByteCode, Rest1} = aeser_rlp:decode_one(Bytes),
|
||||
{SymbolTable, Rest2} = aeser_rlp:decode_one(Rest1),
|
||||
{Annotations, <<>>} = aeser_rlp:decode_one(Rest2),
|
||||
{ByteCode, Rest1} = gmser_rlp:decode_one(Bytes),
|
||||
{SymbolTable, Rest2} = gmser_rlp:decode_one(Rest1),
|
||||
{Annotations, <<>>} = gmser_rlp:decode_one(Rest2),
|
||||
|
||||
Env = #{ function => none
|
||||
, bb => 0
|
||||
@ -355,7 +355,7 @@ deserialize_functions(<<Op:8, Rest/binary>>,
|
||||
, current_bb_code := Code
|
||||
, code := Program} = Env) ->
|
||||
{Rest2, OpCode} = deserialize_op(Op, Rest, Code),
|
||||
case aeb_fate_opcodes:end_bb(Op) of
|
||||
case gmb_fate_opcodes:end_bb(Op) of
|
||||
true ->
|
||||
deserialize_functions(Rest2, Env#{ bb => BB+1
|
||||
, current_bb_code => []
|
||||
@ -380,8 +380,8 @@ deserialize_functions(<<>>, #{ function := {F, Attrs, Sig}
|
||||
Funs#{F => {Attrs, Sig, FunctionCode}}.
|
||||
|
||||
deserialize_op(Op, Rest, Code) ->
|
||||
OpName = aeb_fate_opcodes:mnemonic(Op),
|
||||
case aeb_fate_opcodes:args(Op) of
|
||||
OpName = gmb_fate_opcodes:mnemonic(Op),
|
||||
case gmb_fate_opcodes:args(Op) of
|
||||
0 ->
|
||||
{Rest, [OpName | Code]};
|
||||
N ->
|
||||
@ -397,7 +397,7 @@ deserialize_n_args(N, <<M3:2, M2:2, M1:2, M0:2, Rest/binary>>) when N =< 4 ->
|
||||
stack ->
|
||||
{{stack, 0}, Acc};
|
||||
Modifier ->
|
||||
{Arg, Acc2} = aeb_fate_encoding:deserialize_one(Acc),
|
||||
{Arg, Acc2} = gmb_fate_encoding:deserialize_one(Acc),
|
||||
{{Modifier, Arg}, Acc2}
|
||||
end
|
||||
end, Rest, ArgMods);
|
||||
@ -410,13 +410,13 @@ deserialize_n_args(N, <<M7:2, M6:2, M5:2, M4:2, M3:2, M2:2, M1:2, M0:2,
|
||||
stack ->
|
||||
{{stack, 0}, Acc};
|
||||
Modifier ->
|
||||
{Arg, Acc2} = aeb_fate_encoding:deserialize_one(Acc),
|
||||
{Arg, Acc2} = gmb_fate_encoding:deserialize_one(Acc),
|
||||
{{Modifier, Arg}, Acc2}
|
||||
end
|
||||
end, Rest, ArgMods).
|
||||
|
||||
deserialize_attributes(Binary) ->
|
||||
{AttrVal, Rest} = aeb_fate_encoding:deserialize_one(Binary),
|
||||
{AttrVal, Rest} = gmb_fate_encoding:deserialize_one(Binary),
|
||||
Attrs = [ attr(AVal) || AVal <- attr_vals(1, AttrVal) ],
|
||||
{lists:sort(Attrs), Rest}.
|
||||
|
||||
@ -428,16 +428,16 @@ attr(1) -> private;
|
||||
attr(2) -> payable.
|
||||
|
||||
deserialize_signature(Binary) ->
|
||||
{{tuple, Args}, Rest} = aeb_fate_encoding:deserialize_type(Binary),
|
||||
{RetType, Rest2} = aeb_fate_encoding:deserialize_type(Rest),
|
||||
{{tuple, Args}, Rest} = gmb_fate_encoding:deserialize_type(Binary),
|
||||
{RetType, Rest2} = gmb_fate_encoding:deserialize_type(Rest),
|
||||
{{Args, RetType}, Rest2}.
|
||||
|
||||
deserialize_symbols(Table) ->
|
||||
?FATE_MAP_VALUE(SymbolTable) = aeb_fate_encoding:deserialize(Table),
|
||||
?FATE_MAP_VALUE(SymbolTable) = gmb_fate_encoding:deserialize(Table),
|
||||
SymbolTable.
|
||||
|
||||
deserialize_annotations(AnnotationsBin) ->
|
||||
?FATE_MAP_VALUE(Annotations) = aeb_fate_encoding:deserialize(AnnotationsBin),
|
||||
?FATE_MAP_VALUE(Annotations) = gmb_fate_encoding:deserialize(AnnotationsBin),
|
||||
Annotations.
|
||||
|
||||
assert_zero([]) ->
|
@ -1,8 +1,9 @@
|
||||
%% FATE data representation.
|
||||
%%
|
||||
-include("aeb_fate_data.hrl").
|
||||
-include("gmb_fate_data.hrl").
|
||||
|
||||
-module(aeb_fate_data).
|
||||
-module(gmb_fate_data).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-type fate_integer() :: ?FATE_INTEGER_T.
|
||||
-type fate_boolean() :: ?FATE_BOOLEAN_T.
|
||||
@ -182,19 +183,19 @@ format(M) when ?IS_FATE_MAP(M) ->
|
||||
["{ ", format_kvs(maps:to_list(?FATE_MAP_VALUE(M))), " }"];
|
||||
format(?FATE_BYTES(X)) -> ["#", base64:encode(X)];
|
||||
format(?FATE_ADDRESS(X)) ->
|
||||
["@", aeser_api_encoder:encode(account_pubkey, X)];
|
||||
["@", gmser_api_encoder:encode(account_pubkey, X)];
|
||||
format(?FATE_CONTRACT(X)) ->
|
||||
["@", aeser_api_encoder:encode(contract_pubkey, X)];
|
||||
["@", gmser_api_encoder:encode(contract_pubkey, X)];
|
||||
format(?FATE_ORACLE(X)) ->
|
||||
["@", aeser_api_encoder:encode(oracle_pubkey, X)];
|
||||
["@", gmser_api_encoder:encode(oracle_pubkey, X)];
|
||||
format(?FATE_ORACLE_Q(X)) ->
|
||||
["@", aeser_api_encoder:encode(oracle_query_id, X)];
|
||||
["@", gmser_api_encoder:encode(oracle_query_id, X)];
|
||||
format(?FATE_CHANNEL(X)) ->
|
||||
["@", aeser_api_encoder:encode(channel, X)];
|
||||
["@", gmser_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)];
|
||||
["@", gmser_api_encoder:encode(contract_bytearray, B)];
|
||||
format(V) -> exit({not_a_fate_type, V}).
|
||||
|
||||
format_bits(0, Acc) -> Acc;
|
@ -29,7 +29,7 @@
|
||||
%% * First draft of FATE serialization encoding/decoding.
|
||||
%% Initial experiment with tags
|
||||
%% * Second draft
|
||||
%% * FATE data is now defined in aefa_data.erl
|
||||
%% * FATE data is now defined in gmfa_data.erl
|
||||
%% * Third draft
|
||||
%% * Added Bit strings
|
||||
%%
|
||||
@ -39,7 +39,8 @@
|
||||
%% * Handle instructions.
|
||||
%%
|
||||
%% ------------------------------------------------------------------------
|
||||
-module(aeb_fate_encoding).
|
||||
-module(gmb_fate_encoding).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ deserialize/1
|
||||
, deserialize_one/1
|
||||
@ -52,7 +53,7 @@
|
||||
-export([sort/1]).
|
||||
-endif.
|
||||
|
||||
-include("aeb_fate_data.hrl").
|
||||
-include("gmb_fate_data.hrl").
|
||||
|
||||
%% Definition of tag scheme.
|
||||
%% This has to follow the protocol specification.
|
||||
@ -135,7 +136,7 @@
|
||||
%% Serialized a Fate data value into a sequence of bytes
|
||||
%% according to the Fate serialization specification.
|
||||
%% TODO: The type Fate Data is not final yet.
|
||||
-spec serialize(aeb_fate_data:fate_type()) -> binary().
|
||||
-spec serialize(gmb_fate_data:fate_type()) -> binary().
|
||||
serialize(?FATE_TRUE) -> <<?TRUE>>;
|
||||
serialize(?FATE_FALSE) -> <<?FALSE>>;
|
||||
serialize(?FATE_UNIT) -> <<?EMPTY_TUPLE>>; %% ! Untyped
|
||||
@ -158,15 +159,15 @@ serialize(String) when ?IS_FATE_STRING(String),
|
||||
serialize(?FATE_BYTES(Bytes)) when is_binary(Bytes) ->
|
||||
<<?OBJECT, ?OTYPE_BYTES, (serialize(?FATE_STRING(Bytes)))/binary>>;
|
||||
serialize(?FATE_ADDRESS(Address)) when is_binary(Address) ->
|
||||
<<?OBJECT, ?OTYPE_ADDRESS, (aeser_rlp:encode(Address))/binary>>;
|
||||
<<?OBJECT, ?OTYPE_ADDRESS, (gmser_rlp:encode(Address))/binary>>;
|
||||
serialize(?FATE_CONTRACT(Address)) when is_binary(Address) ->
|
||||
<<?OBJECT, ?OTYPE_CONTRACT, (aeser_rlp:encode(Address))/binary>>;
|
||||
<<?OBJECT, ?OTYPE_CONTRACT, (gmser_rlp:encode(Address))/binary>>;
|
||||
serialize(?FATE_ORACLE(Address)) when is_binary(Address) ->
|
||||
<<?OBJECT, ?OTYPE_ORACLE, (aeser_rlp:encode(Address))/binary>>;
|
||||
<<?OBJECT, ?OTYPE_ORACLE, (gmser_rlp:encode(Address))/binary>>;
|
||||
serialize(?FATE_ORACLE_Q(Address)) when is_binary(Address) ->
|
||||
<<?OBJECT, ?OTYPE_ORACLE_Q, (aeser_rlp:encode(Address))/binary>>;
|
||||
<<?OBJECT, ?OTYPE_ORACLE_Q, (gmser_rlp:encode(Address))/binary>>;
|
||||
serialize(?FATE_CHANNEL(Address)) when is_binary(Address) ->
|
||||
<<?OBJECT, ?OTYPE_CHANNEL, (aeser_rlp:encode(Address))/binary>>;
|
||||
<<?OBJECT, ?OTYPE_CHANNEL, (gmser_rlp:encode(Address))/binary>>;
|
||||
serialize(?FATE_TUPLE(T)) when size(T) > 0 ->
|
||||
S = size(T),
|
||||
L = tuple_to_list(T),
|
||||
@ -209,7 +210,7 @@ serialize(?FATE_VARIANT(Arities, Tag, Values)) ->
|
||||
, is_tuple(Values) ->
|
||||
Arity = lists:nth(Tag+1, Arities),
|
||||
if size(Values) =:= Arity ->
|
||||
EncodedArities = aeser_rlp:encode(list_to_binary(Arities)),
|
||||
EncodedArities = gmser_rlp:encode(list_to_binary(Arities)),
|
||||
<<?VARIANT,
|
||||
EncodedArities/binary,
|
||||
Tag:8,
|
||||
@ -227,7 +228,7 @@ serialize(?FATE_CONTRACT_BYTEARRAY(B)) ->
|
||||
|
||||
%% -----------------------------------------------------
|
||||
|
||||
-spec serialize_type(aeb_fate_data:fate_type_type()) -> [byte()].
|
||||
-spec serialize_type(gmb_fate_data:fate_type_type()) -> [byte()].
|
||||
serialize_type(integer) -> [?TYPE_INTEGER];
|
||||
serialize_type(boolean) -> [?TYPE_BOOLEAN];
|
||||
serialize_type(any) -> [?TYPE_ANY];
|
||||
@ -238,6 +239,8 @@ serialize_type({tuple, Ts}) ->
|
||||
N when N =< 255 ->
|
||||
[?TYPE_TUPLE, N | [serialize_type(T) || T <- Ts]]
|
||||
end;
|
||||
serialize_type({bytes, any}) ->
|
||||
[?TYPE_BYTES | binary_to_list(serialize_integer(-1))];
|
||||
serialize_type({bytes, N}) when 0 =< N ->
|
||||
[?TYPE_BYTES | binary_to_list(serialize_integer(N))];
|
||||
serialize_type(address) -> [?TYPE_OBJECT, ?OTYPE_ADDRESS];
|
||||
@ -257,7 +260,7 @@ serialize_type({variant, ListOfVariants}) ->
|
||||
serialize_type(contract_bytearray) -> [?TYPE_CONTRACT_BYTEARRAY].
|
||||
|
||||
|
||||
-spec deserialize_type(binary()) -> {aeb_fate_data:fate_type_type(), binary()}.
|
||||
-spec deserialize_type(binary()) -> {gmb_fate_data:fate_type_type(), binary()}.
|
||||
deserialize_type(<<?TYPE_INTEGER, Rest/binary>>) -> {integer, Rest};
|
||||
deserialize_type(<<?TYPE_BOOLEAN, Rest/binary>>) -> {boolean, Rest};
|
||||
deserialize_type(<<?TYPE_ANY, Rest/binary>>) -> {any, Rest};
|
||||
@ -270,8 +273,12 @@ deserialize_type(<<?TYPE_TUPLE, N, Rest/binary>>) ->
|
||||
{{tuple, Ts}, Rest2};
|
||||
deserialize_type(<<?TYPE_BYTES, Rest/binary>>) ->
|
||||
{N, Rest2} = deserialize_one(Rest),
|
||||
true = is_integer(N) andalso N >= 0,
|
||||
{{bytes, N}, Rest2};
|
||||
true = is_integer(N),
|
||||
if N == -1 ->
|
||||
{{bytes, any}, Rest2};
|
||||
0 =< N ->
|
||||
{{bytes, N}, Rest2}
|
||||
end;
|
||||
deserialize_type(<<?TYPE_OBJECT, ObjectType, Rest/binary>>) ->
|
||||
case ObjectType of
|
||||
?OTYPE_ADDRESS -> {address, Rest};
|
||||
@ -310,13 +317,13 @@ deserialize_types(N, Binary, Acc) ->
|
||||
%% -----------------------------------------------------
|
||||
|
||||
rlp_encode_int(S) when S >= 0 ->
|
||||
aeser_rlp:encode(binary:encode_unsigned(S)).
|
||||
gmser_rlp:encode(binary:encode_unsigned(S)).
|
||||
|
||||
|
||||
%% first byte of the binary gives the number of bytes we need <<129>> is 1, <<130>> = 2,
|
||||
%% so <<129, 0>> is <<0>> and <<130, 0, 0>> is <<0, 0>>
|
||||
rlp_decode_int(Binary) ->
|
||||
{Bin1, Rest} = aeser_rlp:decode_one(Binary),
|
||||
{Bin1, Rest} = gmser_rlp:decode_one(Binary),
|
||||
Int = binary:decode_unsigned(Bin1),
|
||||
ReEncode = rlp_encode_int(Int),
|
||||
case <<ReEncode/binary, Rest/binary>> == Binary of
|
||||
@ -347,7 +354,7 @@ serialize_bits(B) when is_integer(B) ->
|
||||
B >= 0 -> <<?POS_BITS, (rlp_encode_int(Abs))/binary>>
|
||||
end.
|
||||
|
||||
-spec deserialize(binary()) -> aeb_fate_data:fate_type().
|
||||
-spec deserialize(binary()) -> gmb_fate_data:fate_type().
|
||||
deserialize(B) ->
|
||||
{T, <<>>} = deserialize2(B),
|
||||
T.
|
||||
@ -400,7 +407,7 @@ deserialize2(<<?OBJECT, ?OTYPE_BYTES, Rest/binary>>) ->
|
||||
true = ?IS_FATE_STRING(String),
|
||||
{?FATE_BYTES(?FATE_STRING_VALUE(String)), Rest2};
|
||||
deserialize2(<<?OBJECT, ObjectType, Rest/binary>>) ->
|
||||
{A, Rest2} = aeser_rlp:decode_one(Rest),
|
||||
{A, Rest2} = gmser_rlp:decode_one(Rest),
|
||||
Val =
|
||||
case ObjectType of
|
||||
?OTYPE_ADDRESS -> ?FATE_ADDRESS(A);
|
||||
@ -449,7 +456,7 @@ deserialize2(<<?MAP_ID, Rest/binary>>) ->
|
||||
{Id, Rest1} = rlp_decode_int(Rest),
|
||||
{?FATE_STORE_MAP(#{}, Id), Rest1};
|
||||
deserialize2(<<?VARIANT, Rest/binary>>) ->
|
||||
{AritiesBin, <<Tag:8, Rest2/binary>>} = aeser_rlp:decode_one(Rest),
|
||||
{AritiesBin, <<Tag:8, Rest2/binary>>} = gmser_rlp:decode_one(Rest),
|
||||
Arities = binary_to_list(AritiesBin),
|
||||
Size = length(Arities),
|
||||
if Tag > Size -> exit({too_large_tag_in_variant, Tag, Size});
|
||||
@ -496,7 +503,7 @@ sort_and_check(List) ->
|
||||
|
||||
sort(KVList) ->
|
||||
SortFun = fun({K1, _}, {K2, _}) ->
|
||||
aeb_fate_data:elt(K1, K2)
|
||||
gmb_fate_data:elt(K1, K2)
|
||||
end,
|
||||
lists:sort(SortFun, KVList).
|
||||
|
@ -1,4 +1,5 @@
|
||||
-module(aeb_fate_generate_docs).
|
||||
-module(gmb_fate_generate_docs).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([generate_documentation/2, generate_documentation/3]).
|
||||
|
||||
@ -26,7 +27,7 @@ generate_documentation(Filename, Fields, Filter) when is_function(Filter, 1) ->
|
||||
Instructions =
|
||||
lists:flatten(
|
||||
[gen_doc_for_op(Op, Fields)
|
||||
++ "\n" || Op <- aeb_fate_generate_ops:get_ops(), Filter(Op)]),
|
||||
++ "\n" || Op <- gmb_fate_generate_ops:get_ops(), Filter(Op)]),
|
||||
io:format(File, "~ts~ts~ts\n", [Header, Separator, Instructions]),
|
||||
file:close(File).
|
||||
|
@ -1,4 +1,5 @@
|
||||
-module(aeb_fate_generate_ops).
|
||||
-module(gmb_fate_generate_ops).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ gen_and_halt/1
|
||||
, generate/0
|
||||
@ -18,12 +19,12 @@ generate(Src, Include) ->
|
||||
check_defs(ops_defs()),
|
||||
Ops = get_ops(),
|
||||
%% io:format("ops: ~p\n", [Ops]),
|
||||
HrlFile = Include ++ "aeb_fate_opcodes.hrl",
|
||||
HrlFile = Include ++ "gmb_fate_opcodes.hrl",
|
||||
generate_header_file(HrlFile, Ops),
|
||||
generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops),
|
||||
generate_code_ops(aeb_fate_ops, Src, Ops),
|
||||
generate_scanner("aeb_fate_asm_scan.template", "aeb_fate_asm_scan.xrl", Src, Ops),
|
||||
gen_asm_pp(aeb_fate_pp, Src, Ops).
|
||||
generate_opcodes_ops(gmb_fate_opcodes, HrlFile, Src, Ops),
|
||||
generate_code_ops(gmb_fate_ops, Src, Ops),
|
||||
generate_scanner("gmb_fate_asm_scan.template", "gmb_fate_asm_scan.xrl", Src, Ops),
|
||||
gen_asm_pp(gmb_fate_pp, Src, Ops).
|
||||
|
||||
check_defs(List) ->
|
||||
true = check_numbering(0, lists:keysort(2, List)).
|
||||
@ -31,7 +32,11 @@ check_defs(List) ->
|
||||
check_numbering(N, [T|Rest]) ->
|
||||
OpCode = element(2, T),
|
||||
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);
|
||||
_ when OpCode < N -> {duplicate_opcode, OpCode};
|
||||
_ when OpCode > N -> {missing_opcode, N}
|
||||
@ -150,13 +155,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."}
|
||||
%% 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."}
|
||||
, { '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"}
|
||||
%% Intentional gap (was oracles)
|
||||
|
||||
, { '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."}
|
||||
@ -171,10 +171,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"}
|
||||
, { '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"}
|
||||
, { '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)"}
|
||||
%% Intentional gap (was oracles)
|
||||
|
||||
, { '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"}
|
||||
@ -213,7 +211,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"}
|
||||
|
||||
, { '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."}
|
||||
|
||||
, { 'STR_TO_LIST', 16#9c, false, true, true, ?GAS(100), [a,a], str_to_list, {string}, list, "Arg0 := string converted to list of characters"}
|
||||
@ -232,15 +232,26 @@ ops_defs() ->
|
||||
|
||||
, { '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"}
|
||||
, { '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."}
|
||||
, { 'ABORT', 16#fb, true, true, true, ?GAS(10), [a], abort, {string}, none, "Abort execution (dont use all gas) with error message in Arg0."}
|
||||
@ -323,7 +334,7 @@ generate_code_ops(Modulename, SrcDir, Ops) ->
|
||||
" and documentation for Fate "
|
||||
"instructions.\n")]),
|
||||
io:format(File, "-module(~w).\n\n", [Modulename]),
|
||||
io:format(File, "-include_lib(\"aebytecode/include/aeb_fate_data.hrl\").\n\n"
|
||||
io:format(File, "-include_lib(\"gmbytecode/include/gmb_fate_data.hrl\").\n\n"
|
||||
"-define(i(__X__), {immediate, __X__ }).\n\n"
|
||||
"-type fate_arg_immediate(T) :: {immediate, T}.\n"
|
||||
"-type fate_arg_var() :: {var, integer()}.\n"
|
||||
@ -333,7 +344,7 @@ generate_code_ops(Modulename, SrcDir, Ops) ->
|
||||
" | fate_arg_var()\n"
|
||||
" | fate_arg_arg()\n"
|
||||
" | fate_arg_stack().\n\n"
|
||||
"-type fate_arg_immediate() :: {immediate, aeb_fate_data:fate_type()}.\n"
|
||||
"-type fate_arg_immediate() :: {immediate, gmb_fate_data:fate_type()}.\n"
|
||||
, []),
|
||||
io:format(File, "~s", [Types]),
|
||||
io:format(File, "-type fate_code() :: ~s\n~s .\n\n",
|
||||
@ -378,15 +389,15 @@ gen_constructors(#{constructor := Function, format := ArgSpec,
|
||||
|
||||
gen_arg_type_specs([]) -> [];
|
||||
gen_arg_type_specs([a]) -> "fate_arg()";
|
||||
gen_arg_type_specs([is]) -> "aeb_fate_data:fate_string()";
|
||||
gen_arg_type_specs([ii]) -> "aeb_fate_data:fate_integer()";
|
||||
gen_arg_type_specs([li]) -> "[aeb_fate_data:fate_integer()]";
|
||||
gen_arg_type_specs([t]) -> "aeb_fate_data:fate_type_type()";
|
||||
gen_arg_type_specs([is]) -> "gmb_fate_data:fate_string()";
|
||||
gen_arg_type_specs([ii]) -> "gmb_fate_data:fate_integer()";
|
||||
gen_arg_type_specs([li]) -> "[gmb_fate_data:fate_integer()]";
|
||||
gen_arg_type_specs([t]) -> "gmb_fate_data:fate_type_type()";
|
||||
gen_arg_type_specs([a | Args]) -> "fate_arg(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([is | Args]) -> "aeb_fate_data:fate_string(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([ii | Args]) -> "aeb_fate_data:fate_integer(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([li | Args]) -> "[aeb_fate_data:fate_integer()], " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([t | Args]) -> "aeb_fate_data:fate_type_type(), " ++ gen_arg_type_specs(Args).
|
||||
gen_arg_type_specs([is | Args]) -> "gmb_fate_data:fate_string(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([ii | Args]) -> "gmb_fate_data:fate_integer(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([li | Args]) -> "[gmb_fate_data:fate_integer()], " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([t | Args]) -> "gmb_fate_data:fate_type_type(), " ++ gen_arg_type_specs(Args).
|
||||
|
||||
|
||||
gen_arg_names(_, []) ->
|
||||
@ -418,7 +429,7 @@ ops_exports(Module, HrlFile, Exports) ->
|
||||
lists:flatten(io_lib:format(
|
||||
"-module(~w).\n\n"
|
||||
"-export([ ~s ]).\n\n"
|
||||
"-include_lib(\"aebytecode/" ++ HrlFile ++"\").\n\n"
|
||||
"-include_lib(\"gmbytecode/" ++ HrlFile ++"\").\n\n"
|
||||
"%%====================================================================\n"
|
||||
"%% API\n"
|
||||
"%%====================================================================\n",
|
||||
@ -458,7 +469,7 @@ prelude(Doc) ->
|
||||
"%%%\n"
|
||||
"%%% === === N O T E : This file is generated do not edit. === ===\n"
|
||||
"%%%\n"
|
||||
"%%% Source is in aeb_fate_generate_ops.erl\n"
|
||||
"%%% Source is in gmb_fate_generate_ops.erl\n"
|
||||
"%%% @doc\n"
|
||||
"%%% "++Doc++
|
||||
"%%% @end\n"
|
||||
@ -507,10 +518,10 @@ expand_types([T]) -> expand_type(T);
|
||||
expand_types([T|Ts]) ->expand_type(T) ++ ", " ++ expand_types(Ts).
|
||||
|
||||
expand_type(a) -> "fate_arg()";
|
||||
expand_type(is) -> "fate_arg_immediate(aeb_fate_data:fate_string())";
|
||||
expand_type(ii) -> "fate_arg_immediate(aeb_fate_data:fate_integer())";
|
||||
expand_type(li) -> "fate_arg_immediate([aeb_fate_data:fate_integer()])";
|
||||
expand_type(t) -> "aeb_fate_data:fate_type_type()".
|
||||
expand_type(is) -> "fate_arg_immediate(gmb_fate_data:fate_string())";
|
||||
expand_type(ii) -> "fate_arg_immediate(gmb_fate_data:fate_integer())";
|
||||
expand_type(li) -> "fate_arg_immediate([gmb_fate_data:fate_integer()])";
|
||||
expand_type(t) -> "gmb_fate_data:fate_type_type()".
|
||||
|
||||
generate_scanner(TemplateFile, Outfile, Path, Ops) ->
|
||||
{ok, Template} = file:read_file(filename:join(Path,TemplateFile)),
|
||||
@ -530,8 +541,8 @@ insert_tokens_in_template(<<"%%% ###REPLACEWITHNOTE###", Rest/binary >>, Tokens)
|
||||
"%%%\n"
|
||||
"%%% === === N O T E : This file is generated do not edit. === ===\n"
|
||||
"%%%\n"
|
||||
"%%% Source is in aeb_fate_generate_ops.erl\n"
|
||||
"%%% and aeb_fate_asm_scan.template"
|
||||
"%%% Source is in gmb_fate_generate_ops.erl\n"
|
||||
"%%% and gmb_fate_asm_scan.template"
|
||||
| insert_tokens_in_template(Rest, Tokens)];
|
||||
insert_tokens_in_template(<<B,Rest/binary>>, Tokens) ->
|
||||
[B|insert_tokens_in_template(Rest, Tokens)].
|
||||
@ -547,9 +558,9 @@ gen_asm_pp(Module, Path, Ops) ->
|
||||
io:format(File,
|
||||
"-export([format_op/2]).\n\n"
|
||||
"format_arg(li, {immediate, LI}) ->\n"
|
||||
" aeb_fate_data:format(LI);\n"
|
||||
" gmb_fate_data:format(LI);\n"
|
||||
"format_arg(_, {immediate, I}) ->\n"
|
||||
" aeb_fate_data:format(I);\n"
|
||||
" gmb_fate_data:format(I);\n"
|
||||
"format_arg(a, {arg, N}) -> io_lib:format(\"arg~~p\", [N]);\n"
|
||||
"format_arg(a, {var, N}) when N < 0 -> io_lib:format(\"store~~p\", [-N]);\n"
|
||||
"format_arg(a, {var, N}) -> io_lib:format(\"var~~p\", [N]);\n"
|
@ -1,4 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Functions for manipulating FATE maps. In particular for mediating
|
||||
@ -6,9 +7,10 @@
|
||||
%%% fully or partially saved in the contract store.
|
||||
%%% @end
|
||||
%%% -------------------------------------------------------------------
|
||||
-module(aeb_fate_maps).
|
||||
-module(gmb_fate_maps).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-include("aeb_fate_data.hrl").
|
||||
-include("gmb_fate_data.hrl").
|
||||
|
||||
-export([ allocate_store_maps/2
|
||||
, has_store_maps/1
|
||||
@ -31,11 +33,11 @@
|
||||
-define(STORE_MAP_THRESHOLD, 100).
|
||||
-endif.
|
||||
|
||||
-type fate_value() :: aeb_fate_data:fate_type().
|
||||
-type fate_value() :: gmb_fate_data:fate_type().
|
||||
-type fate_value_or_tombstone() :: fate_value() | ?FATE_MAP_TOMBSTONE.
|
||||
-type id() :: integer().
|
||||
-type used_ids() :: list(id()).
|
||||
-type maps() :: #{ id() => aeb_fate_data:fate_map() | aeb_fate_data:fate_store_map() }.
|
||||
-type maps() :: #{ id() => gmb_fate_data:fate_map() | gmb_fate_data:fate_store_map() }.
|
||||
|
||||
%% -- Allocating store maps --------------------------------------------------
|
||||
|
||||
@ -70,7 +72,7 @@ allocate_store_maps(Used, ?FATE_VARIANT(Arities, Tag, Vals), Maps) ->
|
||||
allocate_store_maps(Used, Val, Maps) when ?IS_FATE_MAP(Val) ->
|
||||
{Used1, KVs, Maps1} = allocate_store_maps_m(Used, ?FATE_MAP_VALUE(Val), Maps),
|
||||
Val1 = ?MAKE_FATE_MAP(KVs),
|
||||
case byte_size(aeb_fate_encoding:serialize(Val1)) < ?STORE_MAP_THRESHOLD of
|
||||
case byte_size(gmb_fate_encoding:serialize(Val1)) < ?STORE_MAP_THRESHOLD of
|
||||
true -> {Used1, Val1, Maps1};
|
||||
false ->
|
||||
{Id, Used2} = next_id(Used1),
|
||||
@ -97,7 +99,7 @@ allocate_store_maps_m(Used, Val, Maps) ->
|
||||
|
||||
%% -- Unfolding store maps ---------------------------------------------------
|
||||
|
||||
-type unfold_fun() :: fun((id()) -> aeb_fate_data:fate_map()).
|
||||
-type unfold_fun() :: fun((id()) -> gmb_fate_data:fate_map()).
|
||||
|
||||
-spec unfold_store_maps(unfold_fun(), fate_value_or_tombstone()) -> fate_value_or_tombstone().
|
||||
unfold_store_maps(_Unfold, ?FATE_MAP_TOMBSTONE = Val) -> Val;
|
@ -1,4 +1,5 @@
|
||||
-module(aeb_heap).
|
||||
-module(gmb_heap).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ to_binary/1
|
||||
, to_binary/2
|
||||
@ -22,8 +23,8 @@
|
||||
|
||||
-export_type([binary_value/0, heap_value/0, offset/0, heap_fragment/0]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_typerep_def.hrl").
|
||||
-include_lib("aebytecode/include/aeb_heap.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_typerep_def.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_heap.hrl").
|
||||
|
||||
-type word() :: non_neg_integer().
|
||||
-type pointer() :: word().
|
||||
@ -112,7 +113,7 @@ pmap_size(#pmap{data = Data}) when is_map(Data) ->
|
||||
|
||||
%% -- Value to binary --------------------------------------------------------
|
||||
|
||||
-spec to_binary(aeb_aevm_data:data()) -> aeb_aevm_data:heap().
|
||||
-spec to_binary(gmb_aevm_data:data()) -> gmb_aevm_data:heap().
|
||||
%% Encode the data as a heap where the first word is the value (for unboxed
|
||||
%% types) or a pointer to the value (for boxed types).
|
||||
to_binary(Data) ->
|
||||
@ -131,10 +132,10 @@ to_binary1(Data,_Address) when is_integer(Data) ->
|
||||
{Data,<<>>};
|
||||
to_binary1(Data, Address) when is_binary(Data) ->
|
||||
%% a string
|
||||
Words = aeb_memory:binary_to_words(Data),
|
||||
Words = gmb_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),
|
||||
Words = gmb_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);
|
@ -1,12 +1,15 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Memory speifics that compiler and VM need to agree upon
|
||||
%%% @end
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 19 Dec 2018
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_memory).
|
||||
-module(gmb_memory).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([binary_to_words/1]).
|
||||
|
@ -1,12 +1,15 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Opcodes
|
||||
%%% @end
|
||||
%%% Created : 2 Oct 2017
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 02 Oct 2017
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_opcodes).
|
||||
-module(gmb_opcodes).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([ dup/1
|
||||
, mnemonic/1
|
||||
@ -17,7 +20,7 @@
|
||||
, swap/1
|
||||
]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_opcodes.hrl").
|
||||
|
||||
|
||||
%%====================================================================
|
@ -1,18 +1,21 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Handle interaction with the aeternity chain
|
||||
%%% Handle interaction with the gmternity chain
|
||||
%%% through calls to AEternity primitive operations at address 0.
|
||||
%%% @end
|
||||
%%% Updated : 22 Jan 2025
|
||||
%%% Created : 18 Dec 2018
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_primops).
|
||||
-module(gmb_primops).
|
||||
-vsn("3.4.1").
|
||||
-export([ is_local_primop_op/1
|
||||
, op_needs_type_check/1
|
||||
]).
|
||||
|
||||
-include("aeb_opcodes.hrl").
|
||||
-include("gmb_opcodes.hrl").
|
||||
|
||||
is_local_primop_op(Op) when ?PRIM_CALL_IN_MAP_RANGE(Op) -> true;
|
||||
is_local_primop_op(Op) when ?PRIM_CALL_IN_CRYPTO_RANGE(Op) -> true;
|
@ -1,12 +1,12 @@
|
||||
{application, aebytecode,
|
||||
[{description, "Bytecode definitions, serialization and deserialization for aeternity."},
|
||||
{vsn, "3.1.1"},
|
||||
{application, gmbytecode,
|
||||
[{description, "Bytecode definitions, serialization and deserialization for the Gajumaru."},
|
||||
{vsn, "3.4.1"},
|
||||
{registered, []},
|
||||
{applications,
|
||||
[kernel,
|
||||
stdlib,
|
||||
eblake2,
|
||||
aeserialization,
|
||||
gmserialization,
|
||||
getopt
|
||||
]},
|
||||
{env,[]},
|
@ -1,4 +1,5 @@
|
||||
-module(aefateasm).
|
||||
-module(gmfateasm).
|
||||
-vsn("3.4.1").
|
||||
|
||||
-export([main/1]).
|
||||
|
||||
@ -9,7 +10,7 @@
|
||||
, {outfile, $o, "out", string, "Output file (experimental)"} ]).
|
||||
|
||||
usage() ->
|
||||
getopt:usage(?OPT_SPEC, "aefateasm").
|
||||
getopt:usage(?OPT_SPEC, "gmfateasm").
|
||||
|
||||
main(Args) ->
|
||||
case getopt:parse(?OPT_SPEC, Args) of
|
||||
@ -43,8 +44,8 @@ assemble(File, Opts) ->
|
||||
Verbose = proplists:get_value(verbose, Opts, false),
|
||||
case proplists:get_value(outfile, Opts, undefined) of
|
||||
undefined ->
|
||||
Asm = aeb_fate_asm:read_file(File),
|
||||
{Env, BC} = aeb_fate_asm:asm_to_bytecode(Asm, Opts),
|
||||
Asm = gmb_fate_asm:read_file(File),
|
||||
{Env, BC} = gmb_fate_asm:asm_to_bytecode(Asm, Opts),
|
||||
case Verbose of
|
||||
true ->
|
||||
io:format("Env: ~0p~n", [Env]);
|
||||
@ -52,6 +53,6 @@ assemble(File, Opts) ->
|
||||
end,
|
||||
io:format("Code: ~0p~n", [BC]);
|
||||
OutFile ->
|
||||
aeb_fate_asm:assemble_file(File, OutFile, Opts)
|
||||
gmb_fate_asm:assemble_file(File, OutFile, Opts)
|
||||
end.
|
||||
|
@ -1,97 +0,0 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc Basic tests for Fate serialization
|
||||
%%%
|
||||
%%% To run:
|
||||
%%% TEST=aeb_serialize_test rebar3 eunit
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_serialize_test).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
serialize_integer_test() ->
|
||||
<<0>> = aeb_fate_encoding:serialize(aeb_fate_data:make_integer(0)),
|
||||
<<2>> = aeb_fate_encoding:serialize(aeb_fate_data:make_integer(1)),
|
||||
<<126>> = aeb_fate_encoding:serialize(aeb_fate_data:make_integer(63)),
|
||||
<<111, 0>> = aeb_fate_encoding:serialize(aeb_fate_data:make_integer(64)),
|
||||
<<111,130,255,255>> = aeb_fate_encoding:serialize(aeb_fate_data:make_integer(65535 + 64)),
|
||||
<<111,184,129,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>> =
|
||||
aeb_fate_encoding:serialize(aeb_fate_data:make_integer(1 bsl 1024 + 64)).
|
||||
|
||||
serialize_deserialize_test_() ->
|
||||
[{lists:flatten(io_lib:format("~p", [X])),
|
||||
fun() ->
|
||||
?assertEqual(X,
|
||||
aeb_fate_encoding:deserialize(aeb_fate_encoding:serialize(X)))
|
||||
end}
|
||||
|| X <- sources()].
|
||||
|
||||
make_int_list(N) -> [aeb_fate_data:make_integer(I) || I <- lists:seq(1, N)].
|
||||
|
||||
sources() ->
|
||||
FortyTwo = aeb_fate_data:make_integer(42),
|
||||
Unit = aeb_fate_data:make_unit(),
|
||||
True = aeb_fate_data:make_boolean(true),
|
||||
False = aeb_fate_data:make_boolean(false),
|
||||
Nil = aeb_fate_data:make_list([]),
|
||||
EmptyString = aeb_fate_data:make_string(""),
|
||||
EmptyMap = aeb_fate_data:make_map(#{}),
|
||||
[aeb_fate_data:make_integer(0),
|
||||
aeb_fate_data:make_integer(1),
|
||||
True, False, Unit, Nil, EmptyString, EmptyMap,
|
||||
aeb_fate_data:make_hash(<<1,2,3,4,5>>),
|
||||
aeb_fate_data:make_signature(<<1,2,3,4,5>>),
|
||||
aeb_fate_data:make_contract(<<1,2,3,4,5>>),
|
||||
aeb_fate_data:make_channel(<<1,2,3,4,5>>),
|
||||
aeb_fate_data:make_list([True]),
|
||||
aeb_fate_data:make_address(
|
||||
<<0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,
|
||||
1,2>>),
|
||||
aeb_fate_data:make_string(<<"Hello">>),
|
||||
aeb_fate_data:make_string(
|
||||
<<"0123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789">>), %% Magic concat 80 char string.
|
||||
aeb_fate_data:make_tuple({True, FortyTwo}),
|
||||
aeb_fate_data:make_tuple(list_to_tuple(make_int_list(65))),
|
||||
aeb_fate_data:make_tuple(list_to_tuple(make_int_list(16))),
|
||||
aeb_fate_data:make_map(#{ aeb_fate_data:make_integer(1) => True, aeb_fate_data:make_integer(2) => False}),
|
||||
aeb_fate_data:make_map(#{ aeb_fate_data:make_string(<<"foo">>) => aeb_fate_data:make_tuple({FortyTwo, True})}),
|
||||
aeb_fate_data:make_list(make_int_list(3)),
|
||||
aeb_fate_data:make_integer(-65),
|
||||
aeb_fate_data:make_integer(65),
|
||||
aeb_fate_data:make_integer(-32432847932847928374983),
|
||||
aeb_fate_data:make_bits(0),
|
||||
aeb_fate_data:make_bits(1),
|
||||
aeb_fate_data:make_bits(-1),
|
||||
aeb_fate_data:make_list(make_int_list(65)),
|
||||
aeb_fate_data:make_variant([1,2,3], 0, {FortyTwo}),
|
||||
aeb_fate_data:make_variant([2,0], 1, {}),
|
||||
aeb_fate_data:make_list([aeb_fate_data:make_variant([0,0,0], 0, {})]),
|
||||
aeb_fate_data:make_variant([0|| _<-lists:seq(1,255)], 254, {}),
|
||||
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">>)}),
|
||||
%% 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>>)
|
||||
].
|
@ -62,13 +62,13 @@ id_local: JUMPDEST
|
||||
JUMP
|
||||
|
||||
;; Test the code from the shell
|
||||
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => list_to_binary(aeb_asm:file("apps/aesophia/test/contracts/identity.aesm", [])), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0 }, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{})).
|
||||
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => list_to_binary(gmb_asm:file("apps/gmsophia/test/contracts/identity.aesm", [])), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0 }, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{})).
|
||||
|
||||
;; Test the code from the shell with tracing.
|
||||
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => aeb_asm:file("apps/aesophia/test/contracts/identity.aesm", []), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0 }, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{ trace => true})).
|
||||
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => gmb_asm:file("apps/gmsophia/test/contracts/identity.aesm", []), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0 }, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{ trace => true})).
|
||||
|
||||
|
||||
;; Test the code from the shell with tracing.
|
||||
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => aeb_asm:file("apps/aesophia/test/contracts/identity.aesm", [pp_tokens, pp_opcodes, pp_patched_code, pp_hex_string]), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0}, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{ trace => true})).
|
||||
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => gmb_asm:file("apps/gmsophia/test/contracts/identity.aesm", [pp_tokens, pp_opcodes, pp_patched_code, pp_hex_string]), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0}, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{ trace => true})).
|
||||
|
||||
;; aec_conductor:stop_mining().
|
||||
|
@ -5,4 +5,4 @@ FUNCTION id(integer) -> integer
|
||||
;; Test the code from the shell
|
||||
;; _build/default/rel/aessembler/bin/aessembler console
|
||||
|
||||
;; aeb_aefa:file("../../../../test/asm_code/identity.fate", []).
|
||||
;; gmb_gmfa:file("../../../../test/asm_code/identity.fate", []).
|
||||
|
@ -68,9 +68,6 @@ FUNCTION tuple() : {tuple, [integer, boolean, string, {tuple, [integer, integer]
|
||||
FUNCTION address() : address
|
||||
RETURNR @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
|
||||
FUNCTION oracle() : oracle
|
||||
RETURNR @ok_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
|
||||
FUNCTION contract() : contract
|
||||
RETURNR @ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
;; CONTRACT oracles
|
||||
|
||||
FUNCTION register (address, integer, {variant, [{tuple, [integer]}, {tuple, [integer]}]}) : oracle
|
||||
ORACLE_REGISTER a #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== arg0 arg1 arg2 'string '{variant, [{tuple, []}, {tuple, [integer]}]}
|
||||
RETURN
|
||||
|
||||
FUNCTION query (oracle, integer, string) : oracle_query
|
||||
ORACLE_QUERY a arg0 arg1 arg2 (| [1,1] | 0 | (100) |) (| [1,1] | 0 | (100) |) 'string '{variant, [{tuple, []}, {tuple, [integer]}]}
|
||||
RETURN
|
||||
|
||||
FUNCTION bogus_query () : oracle_query
|
||||
RETURNR @oq_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
|
||||
FUNCTION respond (oracle, integer, string) : {tuple, []}
|
||||
ORACLE_RESPOND #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== arg0 arg1 arg2 'string '{variant, [{tuple, []}, {tuple, [integer]}]}
|
||||
RETURNR {}
|
||||
|
||||
FUNCTION extend (oracle, {variant, [{tuple, [integer]}, {tuple, [integer]}]}) : {tuple, []}
|
||||
ORACLE_EXTEND #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== arg0 arg1
|
||||
RETURNR {}
|
||||
|
||||
FUNCTION get_question (oracle, oracle_query) : string
|
||||
ORACLE_GET_QUESTION a arg0 arg1 'string '{variant, [{tuple, []}, {tuple, [integer]}]}
|
||||
RETURN
|
||||
|
||||
FUNCTION get_answer (oracle, oracle_query) : {variant, [{tuple, []}, {tuple, [string]}]}
|
||||
ORACLE_GET_ANSWER a arg1 arg2 'string '{variant, [{tuple, []}, {tuple, [integer]}]}
|
||||
RETURN
|
||||
|
||||
FUNCTION query_fee (oracle) : integer
|
||||
ORACLE_QUERY_FEE a arg0
|
||||
RETURN
|
@ -37,5 +37,5 @@ FUNCTION tailcall(integer) -> integer
|
||||
;; Test the code from the shell
|
||||
;; _build/default/rel/aessembler/bin/aessembler console
|
||||
|
||||
;; aeb_aefa:file("../../../../test/asm_code/test.fate", []).
|
||||
;; f(Asm), f(Env), f(BC), Asm = aefa_asm:read_file("../../../../test/asm_code/test.fate"), {Env, BC} = aefa_asm:asm_to_bytecode(Asm, []), aefa_asm:bytecode_to_fate_code(BC, []).
|
||||
;; gmb_gmfa:file("../../../../test/asm_code/test.fate", []).
|
||||
;; f(Asm), f(Env), f(BC), Asm = gmfa_asm:read_file("../../../../test/asm_code/test.fate"), {Env, BC} = gmfa_asm:asm_to_bytecode(Asm, []), gmfa_asm:bytecode_to_fate_code(BC, []).
|
||||
|
@ -1,12 +1,13 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc Basic tests for Fate data
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_data_test).
|
||||
-module(gmb_data_test).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
format_integer_test() ->
|
||||
"0" = aeb_fate_data:format(0).
|
||||
"0" = gmb_fate_data:format(0).
|
@ -1,19 +1,20 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc Basic tests for Fate serialization
|
||||
%%%
|
||||
%%% To run:
|
||||
%%% TEST=aeb_fate_asm_test rebar3 eunit
|
||||
%%% TEST=gmb_fate_asm_test rebar3 eunit
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeb_fate_asm_test).
|
||||
-module(gmb_fate_asm_test).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
asm_path() ->
|
||||
filename:join(code:lib_dir(aebytecode, test), "asm_code").
|
||||
filename:join(code:lib_dir(gmbytecode, test), "asm_code").
|
||||
|
||||
|
||||
file_path(File) ->
|
||||
@ -21,11 +22,11 @@ file_path(File) ->
|
||||
|
||||
read_file(File) ->
|
||||
FilePath = file_path(File),
|
||||
Asm = aeb_fate_asm:read_file(FilePath),
|
||||
Asm = gmb_fate_asm:read_file(FilePath),
|
||||
Asm.
|
||||
|
||||
assemble(Asm) ->
|
||||
aeb_fate_asm:asm_to_bytecode(Asm, []).
|
||||
gmb_fate_asm:asm_to_bytecode(Asm, []).
|
||||
|
||||
asm_disasm_idenity_test() ->
|
||||
check_roundtrip(identity).
|
||||
@ -48,19 +49,18 @@ sources() ->
|
||||
, "mapofmap"
|
||||
, "immediates"
|
||||
, "names"
|
||||
, "oracles"
|
||||
, "meta"
|
||||
].
|
||||
|
||||
check_roundtrip(File) ->
|
||||
AssemblerCode = read_file(File),
|
||||
{_Env, ByteCode} = assemble(AssemblerCode),
|
||||
FateCode = aeb_fate_code:deserialize(ByteCode),
|
||||
DissasmCode = aeb_fate_asm:to_asm(FateCode),
|
||||
FateCode = gmb_fate_code:deserialize(ByteCode),
|
||||
DissasmCode = gmb_fate_asm:to_asm(FateCode),
|
||||
{_Env2, ByteCode2} = assemble(DissasmCode),
|
||||
ByteCode3 = aeb_fate_code:serialize(FateCode),
|
||||
Code1 = aeb_fate_asm:strip(ByteCode),
|
||||
Code2 = aeb_fate_asm:strip(ByteCode2),
|
||||
Code3 = aeb_fate_asm:strip(ByteCode3),
|
||||
ByteCode3 = gmb_fate_code:serialize(FateCode),
|
||||
Code1 = gmb_fate_asm:strip(ByteCode),
|
||||
Code2 = gmb_fate_asm:strip(ByteCode2),
|
||||
Code3 = gmb_fate_asm:strip(ByteCode3),
|
||||
?assertEqual(Code1, Code2),
|
||||
?assertEqual(Code1, Code3).
|
98
test/gmb_serialize_test.erl
Normal file
98
test/gmb_serialize_test.erl
Normal file
@ -0,0 +1,98 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc Basic tests for Fate serialization
|
||||
%%%
|
||||
%%% To run:
|
||||
%%% TEST=gmb_serialize_test rebar3 eunit
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(gmb_serialize_test).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
serialize_integer_test() ->
|
||||
<<0>> = gmb_fate_encoding:serialize(gmb_fate_data:make_integer(0)),
|
||||
<<2>> = gmb_fate_encoding:serialize(gmb_fate_data:make_integer(1)),
|
||||
<<126>> = gmb_fate_encoding:serialize(gmb_fate_data:make_integer(63)),
|
||||
<<111, 0>> = gmb_fate_encoding:serialize(gmb_fate_data:make_integer(64)),
|
||||
<<111,130,255,255>> = gmb_fate_encoding:serialize(gmb_fate_data:make_integer(65535 + 64)),
|
||||
<<111,184,129,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>> =
|
||||
gmb_fate_encoding:serialize(gmb_fate_data:make_integer(1 bsl 1024 + 64)).
|
||||
|
||||
serialize_deserialize_test_() ->
|
||||
[{lists:flatten(io_lib:format("~p", [X])),
|
||||
fun() ->
|
||||
?assertEqual(X,
|
||||
gmb_fate_encoding:deserialize(gmb_fate_encoding:serialize(X)))
|
||||
end}
|
||||
|| X <- sources()].
|
||||
|
||||
make_int_list(N) -> [gmb_fate_data:make_integer(I) || I <- lists:seq(1, N)].
|
||||
|
||||
sources() ->
|
||||
FortyTwo = gmb_fate_data:make_integer(42),
|
||||
Unit = gmb_fate_data:make_unit(),
|
||||
True = gmb_fate_data:make_boolean(true),
|
||||
False = gmb_fate_data:make_boolean(false),
|
||||
Nil = gmb_fate_data:make_list([]),
|
||||
EmptyString = gmb_fate_data:make_string(""),
|
||||
EmptyMap = gmb_fate_data:make_map(#{}),
|
||||
[gmb_fate_data:make_integer(0),
|
||||
gmb_fate_data:make_integer(1),
|
||||
True, False, Unit, Nil, EmptyString, EmptyMap,
|
||||
gmb_fate_data:make_hash(<<1,2,3,4,5>>),
|
||||
gmb_fate_data:make_signature(<<1,2,3,4,5>>),
|
||||
gmb_fate_data:make_contract(<<1,2,3,4,5>>),
|
||||
gmb_fate_data:make_channel(<<1,2,3,4,5>>),
|
||||
gmb_fate_data:make_list([True]),
|
||||
gmb_fate_data:make_address(
|
||||
<<0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,
|
||||
1,2>>),
|
||||
gmb_fate_data:make_string(<<"Hello">>),
|
||||
gmb_fate_data:make_string(
|
||||
<<"0123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789">>), %% Magic concat 80 char string.
|
||||
gmb_fate_data:make_tuple({True, FortyTwo}),
|
||||
gmb_fate_data:make_tuple(list_to_tuple(make_int_list(65))),
|
||||
gmb_fate_data:make_tuple(list_to_tuple(make_int_list(16))),
|
||||
gmb_fate_data:make_map(#{ gmb_fate_data:make_integer(1) => True, gmb_fate_data:make_integer(2) => False}),
|
||||
gmb_fate_data:make_map(#{ gmb_fate_data:make_string(<<"foo">>) => gmb_fate_data:make_tuple({FortyTwo, True})}),
|
||||
gmb_fate_data:make_list(make_int_list(3)),
|
||||
gmb_fate_data:make_integer(-65),
|
||||
gmb_fate_data:make_integer(65),
|
||||
gmb_fate_data:make_integer(-32432847932847928374983),
|
||||
gmb_fate_data:make_bits(0),
|
||||
gmb_fate_data:make_bits(1),
|
||||
gmb_fate_data:make_bits(-1),
|
||||
gmb_fate_data:make_list(make_int_list(65)),
|
||||
gmb_fate_data:make_variant([1,2,3], 0, {FortyTwo}),
|
||||
gmb_fate_data:make_variant([2,0], 1, {}),
|
||||
gmb_fate_data:make_list([gmb_fate_data:make_variant([0,0,0], 0, {})]),
|
||||
gmb_fate_data:make_variant([0|| _<-lists:seq(1,255)], 254, {}),
|
||||
gmb_fate_data:make_variant([0,1,2,3,4,5],
|
||||
3, {gmb_fate_data:make_boolean(true),
|
||||
gmb_fate_data:make_list(make_int_list(3)),
|
||||
gmb_fate_data:make_string(<<"foo">>)}),
|
||||
%% contract C =
|
||||
%% type state = int
|
||||
%% entrypoint init() = 2137
|
||||
|
||||
%% cb_+FFGA6Af6sHTrctrcNGwEa8MPei7iEHIjnxcsBzlA5IK0Yn11sCllP5E1kQfADcANwAaDoJvgggZAQM/jC8BEUTWRB8RaW5pdIIvAIU0LjMuMAD7u
|
||||
gmb_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>>)
|
||||
].
|
@ -1,4 +1,4 @@
|
||||
-module(aebytecode_SUITE).
|
||||
-module(gmbytecode_SUITE).
|
||||
|
||||
%% common_test exports
|
||||
-export([ all/0 ]).
|
||||
@ -12,8 +12,8 @@ all() ->
|
||||
[ roundtrip_identy ].
|
||||
|
||||
roundtrip_identy(_Cfg) ->
|
||||
CodeDir = code:lib_dir(aebytecode, test),
|
||||
FileName = filename:join(CodeDir, "asm_code/identity.aesm"),
|
||||
Code = aeb_asm:file(FileName, []),
|
||||
ct:log("Code ~p:~n~s~n", [FileName, aeb_disassemble:format(Code, fun io:format/2)]),
|
||||
CodeDir = code:lib_dir(gmbytecode, test),
|
||||
FileName = filename:join(CodeDir, "asm_code/identity.gmsm"),
|
||||
Code = gmb_asm:file(FileName, []),
|
||||
ct:log("Code ~p:~n~s~n", [FileName, gmb_disassemble:format(Code, fun io:format/2)]),
|
||||
ok.
|
19
zomp.meta
Normal file
19
zomp.meta
Normal file
@ -0,0 +1,19 @@
|
||||
{name,"Gajumaru Bytecode"}.
|
||||
{type,lib}.
|
||||
{modules,[]}.
|
||||
{prefix,none}.
|
||||
{desc,"A library and stand alone assembler for Gajumaru bytecode. This version supports AEVM bytecode and FATE bytecode."}.
|
||||
{author,[]}.
|
||||
{package_id,{"otpr","gmbytecode",{3,4,1}}}.
|
||||
{deps,[{"otpr","gmserialization",{0,1,2}},
|
||||
{"otpr","eblake2",{1,0,0}},
|
||||
{"otpr","getopt",{1,0,2}}]}.
|
||||
{key_name,none}.
|
||||
{a_email,[]}.
|
||||
{c_email,[]}.
|
||||
{copyright,[]}.
|
||||
{file_exts,[]}.
|
||||
{license,skip}.
|
||||
{repo_url,"https://git.qpq.swiss/QPQ-AG/gmbytecode"}.
|
||||
{tags,["gajumaru","blockchain","fate","bytecode","crypto","gm"]}.
|
||||
{ws_url,[]}.
|
20
zomp_prep
Executable file
20
zomp_prep
Executable file
@ -0,0 +1,20 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This is a small pre-packaging source generation and include correction script that should be
|
||||
# run before packaging this project for use with ZX/Zomp.
|
||||
|
||||
rm -rf _build
|
||||
rm -f src/gmb_fate_opcodes.erl src/gmb_fate_ops.erl include/gmb_fate_opcodes.hrl src/gmb_fate_asm_scan.xrl src/gmb_fate_pp.erl
|
||||
make sources
|
||||
cd src
|
||||
for f in $(ls --ignore=gmb_fate_generate_ops.erl | grep erl)
|
||||
do
|
||||
echo "Updating includes in: $f"
|
||||
sed -i 's/gmbytecode\/include\///g' "$f"
|
||||
sed -i 's/\.\.\/include\///g' "$f"
|
||||
sed -i 's/include_lib/include/g' "$f"
|
||||
done
|
||||
cd ..
|
||||
rm -f ebin/*.beam
|
||||
rm -f rebar*
|
||||
rm -rf quickcheck
|
Loading…
x
Reference in New Issue
Block a user