Auth.tx implementation and types
The arities field of the Chain.base_tx constructor is 22 integers long... This isn't very pretty but that is the design we've chosen.
This commit is contained in:
parent
34c10e1518
commit
bbc8555331
@ -397,6 +397,15 @@ global_env() ->
|
||||
G1 = {tuple_t, Ann, [Fp, Fp, Fp]},
|
||||
G2 = {tuple_t, Ann, [Fp2, Fp2, Fp2]},
|
||||
GT = {tuple_t, Ann, lists:duplicate(12, Fp)},
|
||||
Tx = {qid, Ann, ["Chain", "tx"]},
|
||||
GAMetaTx = {qid, Ann, ["Chain", "ga_meta_tx"]},
|
||||
BaseTx = {qid, Ann, ["Chain", "base_tx"]},
|
||||
PayForTx = {qid, Ann, ["Chain", "paying_for_tx"]},
|
||||
|
||||
FldT = fun(Id, T) -> {field_t, Ann, {id, Ann, Id}, T} end,
|
||||
TxFlds = [{"paying_for", Option(PayForTx)}, {"ga_metas", List(GAMetaTx)},
|
||||
{"actor", Address}, {"fee", Int}, {"ttl", Int}, {"tx", BaseTx}],
|
||||
TxType = {record_t, [FldT(N, T) || {N, T} <- TxFlds ]},
|
||||
|
||||
Fee = Int,
|
||||
[A, Q, R, K, V] = lists:map(TVar, ["a", "q", "r", "k", "v"]),
|
||||
@ -435,8 +444,36 @@ global_env() ->
|
||||
{"timestamp", Int},
|
||||
{"block_height", Int},
|
||||
{"difficulty", Int},
|
||||
{"gas_limit", Int}])
|
||||
, types = MkDefs([{"ttl", 0}]) },
|
||||
{"gas_limit", Int},
|
||||
%% Tx constructors
|
||||
{"GAMetaTx", Fun([Address, Int], GAMetaTx)},
|
||||
{"PayingForTx", Fun([Address, Int], PayForTx)},
|
||||
{"SpendTx", Fun([Address, Int, String], BaseTx)},
|
||||
{"OracleRegisterTx", BaseTx},
|
||||
{"OracleQueryTx", BaseTx},
|
||||
{"OracleResponseTx", BaseTx},
|
||||
{"OracleExtendTx", BaseTx},
|
||||
{"NamePreclaimTx", BaseTx},
|
||||
{"NameClaimTx", Fun([String], BaseTx)},
|
||||
{"NameUpdateTx", Fun([Hash], BaseTx)},
|
||||
{"NameRevokeTx", Fun([Hash], BaseTx)},
|
||||
{"NameTransferTx", Fun([Address, Hash], BaseTx)},
|
||||
{"ChannelCreateTx", Fun([Address], BaseTx)},
|
||||
{"ChannelDepositTx", Fun([Address, Int], BaseTx)},
|
||||
{"ChannelWithdrawTx", Fun([Address, Int], BaseTx)},
|
||||
{"ChannelForceProgressTx", Fun([Address], BaseTx)},
|
||||
{"ChannelCloseMutualTx", Fun([Address], BaseTx)},
|
||||
{"ChannelCloseSoloTx", Fun([Address], BaseTx)},
|
||||
{"ChannelSlashTx", Fun([Address], BaseTx)},
|
||||
{"ChannelSettleTx", Fun([Address], BaseTx)},
|
||||
{"ChannelSnapshotSoloTx", Fun([Address], BaseTx)},
|
||||
{"ContractCreateTx", Fun([Int], BaseTx)},
|
||||
{"ContractCallTx", Fun([Address, Int], BaseTx)},
|
||||
{"GAAttachTx", BaseTx}
|
||||
])
|
||||
, types = MkDefs([{"ttl", 0}, {"tx", {[], TxType}},
|
||||
{"base_tx", 0},
|
||||
{"paying_for_tx", 0}, {"ga_meta_tx", 0}]) },
|
||||
|
||||
ContractScope = #scope
|
||||
{ funs = MkDefs(
|
||||
@ -543,7 +580,8 @@ global_env() ->
|
||||
%% Authentication
|
||||
AuthScope = #scope
|
||||
{ funs = MkDefs(
|
||||
[{"tx_hash", Option(Hash)}]) },
|
||||
[{"tx_hash", Option(Hash)},
|
||||
{"tx", Option(Tx)} ]) },
|
||||
|
||||
%% Strings
|
||||
StringScope = #scope
|
||||
@ -584,6 +622,7 @@ global_env() ->
|
||||
{"is_contract", Fun1(Address, Bool)},
|
||||
{"is_payable", Fun1(Address, Bool)}]) },
|
||||
|
||||
|
||||
#env{ scopes =
|
||||
#{ [] => TopScope
|
||||
, ["Chain"] => ChainScope
|
||||
@ -601,6 +640,9 @@ global_env() ->
|
||||
, ["Int"] => IntScope
|
||||
, ["Address"] => AddressScope
|
||||
}
|
||||
, fields =
|
||||
maps:from_list([{N, [#field_info{ ann = [], field_t = T, record_t = Tx, kind = record }]}
|
||||
|| {N, T} <- TxFlds ])
|
||||
}.
|
||||
|
||||
|
||||
|
@ -178,6 +178,7 @@ ast_to_fcode(Code, Options) ->
|
||||
|
||||
-spec init_env([option()]) -> env().
|
||||
init_env(Options) ->
|
||||
ChainTxArities = [3, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0],
|
||||
#{ type_env => init_type_env(),
|
||||
fun_env => #{},
|
||||
builtins => builtins(),
|
||||
@ -189,7 +190,31 @@ init_env(Options) ->
|
||||
["AENS", "OraclePt"] => #con_tag{ tag = 1, arities = [1, 1, 1, 1] },
|
||||
["AENS", "ContractPt"] => #con_tag{ tag = 2, arities = [1, 1, 1, 1] },
|
||||
["AENS", "ChannelPt"] => #con_tag{ tag = 3, arities = [1, 1, 1, 1] },
|
||||
["AENS", "Name"] => #con_tag{ tag = 0, arities = [3] }
|
||||
["AENS", "Name"] => #con_tag{ tag = 0, arities = [3] },
|
||||
["Chain", "GAMetaTx"] => #con_tag{ tag = 0, arities = [2] },
|
||||
["Chain", "PayingForTx"] => #con_tag{ tag = 0, arities = [2] },
|
||||
["Chain", "SpendTx"] => #con_tag{ tag = 0, arities = ChainTxArities },
|
||||
["Chain", "OracleRegisterTx"] => #con_tag{ tag = 1, arities = ChainTxArities },
|
||||
["Chain", "OracleQueryTx"] => #con_tag{ tag = 2, arities = ChainTxArities },
|
||||
["Chain", "OracleResponseTx"] => #con_tag{ tag = 3, arities = ChainTxArities },
|
||||
["Chain", "OracleExtendTx"] => #con_tag{ tag = 4, arities = ChainTxArities },
|
||||
["Chain", "NamePreclaimTx"] => #con_tag{ tag = 5, arities = ChainTxArities },
|
||||
["Chain", "NameClaimTx"] => #con_tag{ tag = 6, arities = ChainTxArities },
|
||||
["Chain", "NameUpdateTx"] => #con_tag{ tag = 7, arities = ChainTxArities },
|
||||
["Chain", "NameRevokeTx"] => #con_tag{ tag = 8, arities = ChainTxArities },
|
||||
["Chain", "NameTransferTx"] => #con_tag{ tag = 9, arities = ChainTxArities },
|
||||
["Chain", "ChannelCreateTx"] => #con_tag{ tag = 10, arities = ChainTxArities },
|
||||
["Chain", "ChannelDepositTx"] => #con_tag{ tag = 11, arities = ChainTxArities },
|
||||
["Chain", "ChannelWithdrawTx"] => #con_tag{ tag = 12, arities = ChainTxArities },
|
||||
["Chain", "ChannelForceProgressTx"] => #con_tag{ tag = 13, arities = ChainTxArities },
|
||||
["Chain", "ChannelCloseMutualTx"] => #con_tag{ tag = 14, arities = ChainTxArities },
|
||||
["Chain", "ChannelCloseSoloTx"] => #con_tag{ tag = 15, arities = ChainTxArities },
|
||||
["Chain", "ChannelSlashTx"] => #con_tag{ tag = 16, arities = ChainTxArities },
|
||||
["Chain", "ChannelSettleTx"] => #con_tag{ tag = 17, arities = ChainTxArities },
|
||||
["Chain", "ChannelSnapshotSoloTx"] => #con_tag{ tag = 18, arities = ChainTxArities },
|
||||
["Chain", "ContractCreateTx"] => #con_tag{ tag = 19, arities = ChainTxArities },
|
||||
["Chain", "ContractCallTx"] => #con_tag{ tag = 20, arities = ChainTxArities },
|
||||
["Chain", "GAAttachTx"] => #con_tag{ tag = 21, arities = ChainTxArities }
|
||||
},
|
||||
options => Options,
|
||||
functions => #{} }.
|
||||
@ -221,7 +246,7 @@ builtins() ->
|
||||
{"gt_inv", 1}, {"gt_add", 2}, {"gt_mul", 2}, {"gt_pow", 2}, {"gt_is_one", 1},
|
||||
{"pairing", 2}, {"miller_loop", 2}, {"final_exp", 1},
|
||||
{"int_to_fr", 1}, {"int_to_fp", 1}, {"fr_to_int", 1}, {"fp_to_int", 1}]},
|
||||
{["Auth"], [{"tx_hash", none}]},
|
||||
{["Auth"], [{"tx_hash", none}, {"tx", none}]},
|
||||
{["String"], [{"length", 1}, {"concat", 2}, {"sha3", 1}, {"sha256", 1}, {"blake2b", 1}]},
|
||||
{["Bits"], [{"set", 2}, {"clear", 2}, {"test", 2}, {"sum", 1}, {"intersection", 2},
|
||||
{"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]},
|
||||
@ -241,6 +266,11 @@ state_layout(Env) -> maps:get(state_layout, Env, {reg, 1}).
|
||||
|
||||
-spec init_type_env() -> type_env().
|
||||
init_type_env() ->
|
||||
BaseTx = {variant, [[address, integer, string], [], [], [], [], [], [string],
|
||||
[hash], [hash], [address, hash], [address],
|
||||
[address, integer], [address, integer], [address],
|
||||
[address], [address], [address], [address], [address],
|
||||
[integer], [address, integer], []]},
|
||||
#{ ["int"] => ?type(integer),
|
||||
["bool"] => ?type(boolean),
|
||||
["bits"] => ?type(bits),
|
||||
@ -257,6 +287,9 @@ init_type_env() ->
|
||||
["Chain", "ttl"] => ?type({variant, [[integer], [integer]]}),
|
||||
["AENS", "pointee"] => ?type({variant, [[address], [address], [address], [address]]}),
|
||||
["AENS", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {variant, [[address], [address], [address], [address]]}}]]}),
|
||||
["Chain", "ga_meta_tx"] => ?type({variant, [[address, integer]]}),
|
||||
["Chain", "paying_for_tx"] => ?type({variant, [[address, integer]]}),
|
||||
["Chain", "base_tx"] => ?type(BaseTx),
|
||||
["MCL_BLS12_381", "fr"] => ?type({bytes, 32}),
|
||||
["MCL_BLS12_381", "fp"] => ?type({bytes, 48})
|
||||
}.
|
||||
|
@ -544,7 +544,9 @@ builtin_to_scode(Env, aens_update, [_Sign, _Account, _NameString, _TTL, _ClientT
|
||||
builtin_to_scode(Env, aens_lookup, [_Name] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:aens_lookup(?a, ?a), Args);
|
||||
builtin_to_scode(_Env, auth_tx_hash, []) ->
|
||||
[aeb_fate_ops:auth_tx_hash(?a)].
|
||||
[aeb_fate_ops:auth_tx_hash(?a)];
|
||||
builtin_to_scode(_Env, auth_tx, []) ->
|
||||
[aeb_fate_ops:auth_tx(?a)].
|
||||
|
||||
%% -- Operators --
|
||||
|
||||
@ -846,6 +848,7 @@ attributes(I) ->
|
||||
{'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]);
|
||||
{'ADDRESS_TO_CONTRACT', A, B} -> Pure(A, [B]);
|
||||
{'AUTH_TX_HASH', A} -> Pure(A, []);
|
||||
{'AUTH_TX', A} -> Pure(A, []);
|
||||
{'BYTES_TO_INT', A, B} -> Pure(A, [B]);
|
||||
{'BYTES_TO_STR', A, B} -> Pure(A, [B]);
|
||||
{'BYTES_CONCAT', A, B, C} -> Pure(A, [B, C]);
|
||||
|
@ -146,6 +146,7 @@ compilable_contracts() ->
|
||||
"events",
|
||||
"include",
|
||||
"basic_auth",
|
||||
"basic_auth_tx",
|
||||
"bitcoin_auth",
|
||||
"address_literals",
|
||||
"bytes_equality",
|
||||
@ -171,7 +172,7 @@ compilable_contracts() ->
|
||||
].
|
||||
|
||||
not_yet_compilable(fate) -> [];
|
||||
not_yet_compilable(aevm) -> ["pairing_crypto", "aens_update"].
|
||||
not_yet_compilable(aevm) -> ["pairing_crypto", "aens_update", "basic_auth_tx"].
|
||||
|
||||
%% Contracts that should produce type errors
|
||||
|
||||
|
74
test/contracts/basic_auth_tx.aes
Normal file
74
test/contracts/basic_auth_tx.aes
Normal file
@ -0,0 +1,74 @@
|
||||
// namespace Chain =
|
||||
// record tx = { paying_for : option(Chain.paying_for_tx)
|
||||
// , ga_metas : list(Chain.ga_meta_tx)
|
||||
// , actor : address
|
||||
// , fee : int
|
||||
// , ttl : int
|
||||
// , tx : Chain.base_tx }
|
||||
|
||||
// datatype ga_meta_tx = GAMetaTx(address, int)
|
||||
// datatype paying_for_tx = PayingForTx(address, int)
|
||||
// datatype base_tx = SpendTx(address, int, string)
|
||||
// | OracleRegisterTx | OracleQueryTx | OracleResponseTx | OracleExtendTx
|
||||
// | NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
||||
// | NameRevokeTx(hash) | NameTransferTx(address, string)
|
||||
// | ChannelCreateTx(address) | ChannelDepositTx(address, int) | ChannelWithdrawTx(address, int) |
|
||||
// | ChannelForceProgressTx(address) | ChannelCloseMutualTx(address) | ChannelCloseSoloTx(address)
|
||||
// | ChannelSlashTx(address) | ChannelSettleTx(address) | ChannelSnapshotSoloTx(address)
|
||||
// | ContractCreateTx(int) | ContractCallTx(address, int)
|
||||
// | GAAttachTx
|
||||
|
||||
|
||||
// Contract replicating "normal" Aeternity authentication
|
||||
contract BasicAuthTx =
|
||||
record state = { nonce : int, owner : address }
|
||||
datatype foo = Bar | Baz()
|
||||
|
||||
entrypoint init() = { nonce = 1, owner = Call.caller }
|
||||
|
||||
stateful entrypoint authorize(n : int, s : signature) : bool =
|
||||
require(n >= state.nonce, "Nonce too low")
|
||||
require(n =< state.nonce, "Nonce too high")
|
||||
put(state{ nonce = n + 1 })
|
||||
switch(Auth.tx_hash)
|
||||
None => abort("Not in Auth context")
|
||||
Some(tx_hash) =>
|
||||
let Some(tx0) = Auth.tx
|
||||
let x : option(Chain.paying_for_tx) = tx0.paying_for
|
||||
let x : list(Chain.ga_meta_tx) = tx0.ga_metas
|
||||
let x : int = tx0.fee + tx0.ttl
|
||||
let x : address = tx0.actor
|
||||
let x : Chain.tx = { tx = Chain.NamePreclaimTx, paying_for = None, ga_metas = [],
|
||||
fee = 123, ttl = 0, actor = Call.caller }
|
||||
switch(tx0.tx)
|
||||
Chain.SpendTx(receiver, amount, payload) => verify(tx_hash, n, s)
|
||||
Chain.OracleRegisterTx => false
|
||||
Chain.OracleQueryTx => false
|
||||
Chain.OracleResponseTx => false
|
||||
Chain.OracleExtendTx => false
|
||||
Chain.NamePreclaimTx => false
|
||||
Chain.NameClaimTx(name) => false
|
||||
Chain.NameUpdateTx(name) => false
|
||||
Chain.NameRevokeTx(name) => false
|
||||
Chain.NameTransferTx(to, name) => false
|
||||
Chain.ChannelCreateTx(other_party) => false
|
||||
Chain.ChannelDepositTx(channel, amount) => false
|
||||
Chain.ChannelWithdrawTx(channel, amount) => false
|
||||
Chain.ChannelForceProgressTx(channel) => false
|
||||
Chain.ChannelCloseMutualTx(channel) => false
|
||||
Chain.ChannelCloseSoloTx(channel) => false
|
||||
Chain.ChannelSlashTx(channel) => false
|
||||
Chain.ChannelSettleTx(channel) => false
|
||||
Chain.ChannelSnapshotSoloTx(channel) => false
|
||||
Chain.ContractCreateTx(amount) => false
|
||||
Chain.ContractCallTx(ct_address, amount) => false
|
||||
Chain.GAAttachTx => false
|
||||
|
||||
function verify(tx_hash, n, s) =
|
||||
Crypto.verify_sig(to_sign(tx_hash, n), state.owner, s)
|
||||
|
||||
entrypoint to_sign(h : hash, n : int) =
|
||||
Crypto.blake2b((h, n))
|
||||
|
||||
entrypoint weird_string() : string =
|
||||
"\x19Weird String\x42\nMore\n"
|
Loading…
x
Reference in New Issue
Block a user