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]},
|
G1 = {tuple_t, Ann, [Fp, Fp, Fp]},
|
||||||
G2 = {tuple_t, Ann, [Fp2, Fp2, Fp2]},
|
G2 = {tuple_t, Ann, [Fp2, Fp2, Fp2]},
|
||||||
GT = {tuple_t, Ann, lists:duplicate(12, Fp)},
|
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,
|
Fee = Int,
|
||||||
[A, Q, R, K, V] = lists:map(TVar, ["a", "q", "r", "k", "v"]),
|
[A, Q, R, K, V] = lists:map(TVar, ["a", "q", "r", "k", "v"]),
|
||||||
@ -435,8 +444,36 @@ global_env() ->
|
|||||||
{"timestamp", Int},
|
{"timestamp", Int},
|
||||||
{"block_height", Int},
|
{"block_height", Int},
|
||||||
{"difficulty", Int},
|
{"difficulty", Int},
|
||||||
{"gas_limit", Int}])
|
{"gas_limit", Int},
|
||||||
, types = MkDefs([{"ttl", 0}]) },
|
%% 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
|
ContractScope = #scope
|
||||||
{ funs = MkDefs(
|
{ funs = MkDefs(
|
||||||
@ -543,7 +580,8 @@ global_env() ->
|
|||||||
%% Authentication
|
%% Authentication
|
||||||
AuthScope = #scope
|
AuthScope = #scope
|
||||||
{ funs = MkDefs(
|
{ funs = MkDefs(
|
||||||
[{"tx_hash", Option(Hash)}]) },
|
[{"tx_hash", Option(Hash)},
|
||||||
|
{"tx", Option(Tx)} ]) },
|
||||||
|
|
||||||
%% Strings
|
%% Strings
|
||||||
StringScope = #scope
|
StringScope = #scope
|
||||||
@ -584,6 +622,7 @@ global_env() ->
|
|||||||
{"is_contract", Fun1(Address, Bool)},
|
{"is_contract", Fun1(Address, Bool)},
|
||||||
{"is_payable", Fun1(Address, Bool)}]) },
|
{"is_payable", Fun1(Address, Bool)}]) },
|
||||||
|
|
||||||
|
|
||||||
#env{ scopes =
|
#env{ scopes =
|
||||||
#{ [] => TopScope
|
#{ [] => TopScope
|
||||||
, ["Chain"] => ChainScope
|
, ["Chain"] => ChainScope
|
||||||
@ -601,6 +640,9 @@ global_env() ->
|
|||||||
, ["Int"] => IntScope
|
, ["Int"] => IntScope
|
||||||
, ["Address"] => AddressScope
|
, ["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().
|
-spec init_env([option()]) -> env().
|
||||||
init_env(Options) ->
|
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(),
|
#{ type_env => init_type_env(),
|
||||||
fun_env => #{},
|
fun_env => #{},
|
||||||
builtins => builtins(),
|
builtins => builtins(),
|
||||||
@ -189,7 +190,31 @@ init_env(Options) ->
|
|||||||
["AENS", "OraclePt"] => #con_tag{ tag = 1, arities = [1, 1, 1, 1] },
|
["AENS", "OraclePt"] => #con_tag{ tag = 1, arities = [1, 1, 1, 1] },
|
||||||
["AENS", "ContractPt"] => #con_tag{ tag = 2, 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", "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,
|
options => Options,
|
||||||
functions => #{} }.
|
functions => #{} }.
|
||||||
@ -221,7 +246,7 @@ builtins() ->
|
|||||||
{"gt_inv", 1}, {"gt_add", 2}, {"gt_mul", 2}, {"gt_pow", 2}, {"gt_is_one", 1},
|
{"gt_inv", 1}, {"gt_add", 2}, {"gt_mul", 2}, {"gt_pow", 2}, {"gt_is_one", 1},
|
||||||
{"pairing", 2}, {"miller_loop", 2}, {"final_exp", 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}]},
|
{"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}]},
|
{["String"], [{"length", 1}, {"concat", 2}, {"sha3", 1}, {"sha256", 1}, {"blake2b", 1}]},
|
||||||
{["Bits"], [{"set", 2}, {"clear", 2}, {"test", 2}, {"sum", 1}, {"intersection", 2},
|
{["Bits"], [{"set", 2}, {"clear", 2}, {"test", 2}, {"sum", 1}, {"intersection", 2},
|
||||||
{"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]},
|
{"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().
|
-spec init_type_env() -> type_env().
|
||||||
init_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),
|
#{ ["int"] => ?type(integer),
|
||||||
["bool"] => ?type(boolean),
|
["bool"] => ?type(boolean),
|
||||||
["bits"] => ?type(bits),
|
["bits"] => ?type(bits),
|
||||||
@ -257,6 +287,9 @@ init_type_env() ->
|
|||||||
["Chain", "ttl"] => ?type({variant, [[integer], [integer]]}),
|
["Chain", "ttl"] => ?type({variant, [[integer], [integer]]}),
|
||||||
["AENS", "pointee"] => ?type({variant, [[address], [address], [address], [address]]}),
|
["AENS", "pointee"] => ?type({variant, [[address], [address], [address], [address]]}),
|
||||||
["AENS", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {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", "fr"] => ?type({bytes, 32}),
|
||||||
["MCL_BLS12_381", "fp"] => ?type({bytes, 48})
|
["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) ->
|
builtin_to_scode(Env, aens_lookup, [_Name] = Args) ->
|
||||||
call_to_scode(Env, aeb_fate_ops:aens_lookup(?a, ?a), Args);
|
call_to_scode(Env, aeb_fate_ops:aens_lookup(?a, ?a), Args);
|
||||||
builtin_to_scode(_Env, auth_tx_hash, []) ->
|
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 --
|
%% -- Operators --
|
||||||
|
|
||||||
@ -846,6 +848,7 @@ attributes(I) ->
|
|||||||
{'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]);
|
{'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]);
|
||||||
{'ADDRESS_TO_CONTRACT', A, B} -> Pure(A, [B]);
|
{'ADDRESS_TO_CONTRACT', A, B} -> Pure(A, [B]);
|
||||||
{'AUTH_TX_HASH', A} -> Pure(A, []);
|
{'AUTH_TX_HASH', A} -> Pure(A, []);
|
||||||
|
{'AUTH_TX', A} -> Pure(A, []);
|
||||||
{'BYTES_TO_INT', A, B} -> Pure(A, [B]);
|
{'BYTES_TO_INT', A, B} -> Pure(A, [B]);
|
||||||
{'BYTES_TO_STR', A, B} -> Pure(A, [B]);
|
{'BYTES_TO_STR', A, B} -> Pure(A, [B]);
|
||||||
{'BYTES_CONCAT', A, B, C} -> Pure(A, [B, C]);
|
{'BYTES_CONCAT', A, B, C} -> Pure(A, [B, C]);
|
||||||
|
@ -146,6 +146,7 @@ compilable_contracts() ->
|
|||||||
"events",
|
"events",
|
||||||
"include",
|
"include",
|
||||||
"basic_auth",
|
"basic_auth",
|
||||||
|
"basic_auth_tx",
|
||||||
"bitcoin_auth",
|
"bitcoin_auth",
|
||||||
"address_literals",
|
"address_literals",
|
||||||
"bytes_equality",
|
"bytes_equality",
|
||||||
@ -171,7 +172,7 @@ compilable_contracts() ->
|
|||||||
].
|
].
|
||||||
|
|
||||||
not_yet_compilable(fate) -> [];
|
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
|
%% 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