Add Sophia AIC builtins and Auth.tx constructors #992
@@ -749,6 +749,35 @@ Spend `amount` tokens to `to`. Will fail (and abort the contract) if contract
|
||||
doesn't have `amount` tokens to transfer, or, if `to` is not `payable`.
|
||||
|
||||
|
||||
##### spend\_currency
|
||||
```
|
||||
Chain.spend_currency(to : address, issuer : address, amount : int) : unit
|
||||
```
|
||||
|
||||
Transfer `amount` of the account-issued currency identified by `issuer` from
|
||||
the contract to `to`. Aborts if the contract does not hold enough, or if the
|
||||
recipient requires inbound AIC authorization and is not a signer of the outer
|
||||
transaction.
|
||||
|
||||
|
||||
##### balance\_currency
|
||||
```
|
||||
Chain.balance_currency(holder : address, issuer : address) : int
|
||||
```
|
||||
|
||||
The `holder`'s balance of the account-issued currency identified by `issuer`
|
||||
(0 if none).
|
||||
|
||||
|
||||
##### currency\_supply
|
||||
```
|
||||
Chain.currency_supply(issuer : address) : int
|
||||
```
|
||||
|
||||
Total supply of the account-issued currency identified by `issuer` (0 if the
|
||||
account has not minted).
|
||||
|
||||
|
||||
##### timestamp
|
||||
```
|
||||
Chain.timestamp : int
|
||||
|
||||
+3
-2
@@ -1,10 +1,11 @@
|
||||
%% -*- mode: erlang; indent-tabs-mode: nil -*-
|
||||
|
||||
{minimum_otp_vsn, "28.1"}.
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [ {gmbytecode,
|
||||
{git, "https://git.qpq.swiss/QPQ-AG/gmbytecode.git",
|
||||
{ref, "97cea33be8f3a35d26055664da7aa59531ff5537"}}}
|
||||
{git, "https://git.qpq.swiss/QPQ-AG/gmbytecode.git", {ref, "c44313efb9"}}}
|
||||
, {eblake2, "1.0.0"}
|
||||
, {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}}
|
||||
]}.
|
||||
|
||||
+18
-17
@@ -1,30 +1,31 @@
|
||||
{"1.2.0",
|
||||
[{<<"gmbytecode">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmbytecode.git",
|
||||
{ref, "97cea33be8f3a35d26055664da7aa59531ff5537"}},
|
||||
0},
|
||||
{<<"gmserialization">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||
{ref,"ac64e01b0f675c1a34c70a827062f381920742db"}},
|
||||
1},
|
||||
{<<"base58">>,
|
||||
[{<<"base58">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/erl-base58.git",
|
||||
{ref,"e6aa62eeae3d4388311401f06e4b939bf4e94b9c"}},
|
||||
2},
|
||||
{<<"eblake2">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/eblake2.git",
|
||||
{ref,"b29d585b8760746142014884007eb8441a3b6a14"}},
|
||||
0},
|
||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
||||
{<<"enacl">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/enacl.git",
|
||||
{ref,"4eb7ec70084ba7c87b1af8797c4c4e90c84f95a2"}},
|
||||
2},
|
||||
{<<"getopt">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/getopt.git",
|
||||
{ref,"dbab6262a2430809430deda9d8650f58f9d80898"}},
|
||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},1},
|
||||
{<<"gmbytecode">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmbytecode.git",
|
||||
{ref,"c44313efb9c8fecace217e799d90e3d91d7e54d1"}},
|
||||
0},
|
||||
{<<"gmserialization">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||
{ref,"9d2ecc00d32ea295309563e54a81636ecb597e96"}},
|
||||
1},
|
||||
{<<"jsx">>,
|
||||
{git,"https://github.com/talentdeficit/jsx.git",
|
||||
{ref,"3074d4865b3385a050badf7828ad31490d860df5"}},
|
||||
0}]}.
|
||||
|
||||
[
|
||||
{pkg_hash,[
|
||||
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>},
|
||||
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]},
|
||||
{pkg_hash_ext,[
|
||||
{<<"eblake2">>, <<"3C4D300A91845B25D501929A26AC2E6F7157480846FAB2347A4C11AE52E08A99">>},
|
||||
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]}
|
||||
].
|
||||
|
||||
@@ -646,9 +646,12 @@ global_env() ->
|
||||
ChainScope = #scope
|
||||
{ funs = MkDefs(
|
||||
%% Spend transaction.
|
||||
[{"spend", StateFun([Address, Int], Unit)},
|
||||
[{"spend", StateFun([Address, Int], Unit)},
|
||||
{"spend_currency", StateFun([Address, Address, Int], Unit)},
|
||||
%% Chain environment
|
||||
{"balance", Fun1(Address, Int)},
|
||||
{"balance", Fun1(Address, Int)},
|
||||
{"balance_currency", Fun([Address, Address], Int)},
|
||||
{"currency_supply", Fun1(Address, Int)},
|
||||
{"block_hash", Fun1(Int, Option(Hash))},
|
||||
{"coinbase", Address},
|
||||
{"timestamp", Int},
|
||||
@@ -697,7 +700,15 @@ global_env() ->
|
||||
{"ChannelSnapshotSoloTx", Fun([Address], BaseTx)},
|
||||
{"ContractCreateTx", Fun([Int], BaseTx)},
|
||||
{"ContractCallTx", Fun([Address, Int], BaseTx)},
|
||||
{"GAAttachTx", BaseTx}
|
||||
{"GAAttachTx", BaseTx},
|
||||
{"AccountCreateTx", Fun([Address, Int], BaseTx)},
|
||||
{"MintTx", Fun([Int], BaseTx)},
|
||||
{"ExchangeTx", Fun([List({tuple_t, Ann,
|
||||
[Option(Address), Address,
|
||||
Address, Int]})], BaseTx)},
|
||||
{"SpendCurrenciesTx", Fun([Address, Int, String,
|
||||
List(Pair(Address, Int))], BaseTx)},
|
||||
{"BurnTx", Fun([Int], BaseTx)}
|
||||
])
|
||||
, types = MkDefs([{"ttl", 0}, {"tx", {[], TxType}},
|
||||
{"base_tx", 0},
|
||||
@@ -781,6 +792,9 @@ global_env() ->
|
||||
{"verify_sig_secp256k1", Fun([Hash, Bytes(64), SignId], Bool)},
|
||||
{"ecverify_secp256k1", Fun([Hash, Bytes(20), Bytes(65)], Bool)},
|
||||
{"ecrecover_secp256k1", Fun([Hash, Bytes(65)], Option(Bytes(20)))},
|
||||
{"verify_sig_mldsa44", Fun([Hash, Bytes(1312), Bytes(2420)], Bool)},
|
||||
{"verify_sig_mldsa65", Fun([Hash, Bytes(1952), Bytes(3309)], Bool)},
|
||||
{"verify_sig_mldsa87", Fun([Hash, Bytes(2592), Bytes(4627)], Bool)},
|
||||
{"sha3", Fun1(A, Hash)},
|
||||
{"sha256", Fun1(A, Hash)},
|
||||
{"blake2b", Fun1(A, Hash)},
|
||||
|
||||
+22
-4
@@ -40,6 +40,7 @@
|
||||
contract_to_address | address_to_contract | crypto_verify_sig | crypto_verify_sig_secp256k1 |
|
||||
crypto_sha3 | crypto_sha256 | crypto_blake2b | crypto_poseidon |
|
||||
crypto_ecverify_secp256k1 | crypto_ecrecover_secp256k1 |
|
||||
crypto_verify_sig_mldsa44 | crypto_verify_sig_mldsa65 | crypto_verify_sig_mldsa87 |
|
||||
mcl_bls12_381_g1_neg | mcl_bls12_381_g1_norm | mcl_bls12_381_g1_valid |
|
||||
mcl_bls12_381_g1_is_zero | mcl_bls12_381_g1_add | mcl_bls12_381_g1_mul |
|
||||
mcl_bls12_381_g2_neg | mcl_bls12_381_g2_norm | mcl_bls12_381_g2_valid |
|
||||
@@ -211,7 +212,8 @@ optimize(FCode1, 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],
|
||||
ChainTxArities = [3, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0,
|
||||
2, 1, 1, 4, 1],
|
||||
#{ type_env => init_type_env(),
|
||||
fun_env => #{},
|
||||
builtins => builtins(),
|
||||
@@ -254,7 +256,12 @@ init_env(Options) ->
|
||||
["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 }
|
||||
["Chain", "GAAttachTx"] => #con_tag{ tag = 21, arities = ChainTxArities },
|
||||
["Chain", "AccountCreateTx"] => #con_tag{ tag = 22, arities = ChainTxArities },
|
||||
["Chain", "MintTx"] => #con_tag{ tag = 23, arities = ChainTxArities },
|
||||
["Chain", "ExchangeTx"] => #con_tag{ tag = 24, arities = ChainTxArities },
|
||||
["Chain", "SpendCurrenciesTx"] => #con_tag{ tag = 25, arities = ChainTxArities },
|
||||
["Chain", "BurnTx"] => #con_tag{ tag = 26, arities = ChainTxArities }
|
||||
},
|
||||
options => Options,
|
||||
functions => #{},
|
||||
@@ -270,7 +277,9 @@ builtins() ->
|
||||
list_to_atom(string:to_lower(string:join(NS ++ [Fun], "_")))
|
||||
end,
|
||||
Scopes = [{[], [{"abort", 1}, {"require", 2}, {"exit", 1}]},
|
||||
{["Chain"], [{"spend", 2}, {"balance", 1}, {"block_hash", 1}, {"coinbase", none},
|
||||
{["Chain"], [{"spend", 2}, {"spend_currency", 3}, {"balance", 1},
|
||||
{"balance_currency", 2}, {"currency_supply", 1},
|
||||
{"block_hash", 1}, {"coinbase", none},
|
||||
{"timestamp", none}, {"block_height", none}, {"difficulty", none}, {"gas_limit", none},
|
||||
{"network_id", none}, {"bytecode_hash", 1}, {"create", variable}, {"clone", variable}]},
|
||||
{["Contract"], [{"address", none}, {"balance", none}, {"creator", none}]},
|
||||
@@ -285,6 +294,8 @@ builtins() ->
|
||||
{"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]},
|
||||
{["Crypto"], [{"verify_sig", 3}, {"verify_sig_secp256k1", 3},
|
||||
{"ecverify_secp256k1", 3}, {"ecrecover_secp256k1", 2},
|
||||
{"verify_sig_mldsa44", 3}, {"verify_sig_mldsa65", 3},
|
||||
{"verify_sig_mldsa87", 3},
|
||||
{"sha3", 1}, {"sha256", 1}, {"blake2b", 1}, {"poseidon", 2}]},
|
||||
{["MCL_BLS12_381"], [{"g1_neg", 1}, {"g1_norm", 1}, {"g1_valid", 1}, {"g1_is_zero", 1}, {"g1_add", 2}, {"g1_mul", 2},
|
||||
{"g2_neg", 1}, {"g2_norm", 1}, {"g2_valid", 1}, {"g2_is_zero", 1}, {"g2_add", 2}, {"g2_mul", 2},
|
||||
@@ -320,7 +331,13 @@ init_type_env() ->
|
||||
[{bytes, 32}], [{bytes, 32}], [address, {bytes, 32}], [address],
|
||||
[address, integer], [address, integer], [address],
|
||||
[address], [address], [address], [address], [address],
|
||||
[integer], [address, integer], []]},
|
||||
[integer], [address, integer], [],
|
||||
[address, integer],
|
||||
[integer],
|
||||
[{list, {tuple, [{variant, [[], [address]]}, address, address, integer]}}],
|
||||
[address, integer, string, {list, {tuple, [address, integer]}}],
|
||||
[integer]
|
||||
]},
|
||||
#{ ["int"] => ?type(integer),
|
||||
["bool"] => ?type(boolean),
|
||||
["bits"] => ?type(bits),
|
||||
@@ -1163,6 +1180,7 @@ op_builtins() ->
|
||||
int_to_str, int_to_bytes, int_mulmod,
|
||||
address_to_str, address_to_bytes, address_to_contract,
|
||||
crypto_verify_sig, crypto_verify_sig_secp256k1, crypto_sha3, crypto_sha256, crypto_blake2b,
|
||||
crypto_verify_sig_mldsa44, crypto_verify_sig_mldsa65, crypto_verify_sig_mldsa87,
|
||||
crypto_poseidon, crypto_ecverify_secp256k1, crypto_ecrecover_secp256k1,
|
||||
mcl_bls12_381_g1_neg, mcl_bls12_381_g1_norm, mcl_bls12_381_g1_valid,
|
||||
mcl_bls12_381_g1_is_zero, mcl_bls12_381_g1_add, mcl_bls12_381_g1_mul,
|
||||
|
||||
@@ -553,8 +553,15 @@ builtin_to_scode(Env, exit, [_] = Args) ->
|
||||
builtin_to_scode(Env, chain_spend, [_, _] = Args) ->
|
||||
call_to_scode(Env, [gmb_fate_ops:spend(?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, chain_spend_currency, [_, _, _] = Args) ->
|
||||
call_to_scode(Env, [gmb_fate_ops:spend_currency(?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, chain_balance, [_] = Args) ->
|
||||
call_to_scode(Env, gmb_fate_ops:balance_other(?a, ?a), Args);
|
||||
builtin_to_scode(Env, chain_balance_currency, [_, _] = Args) ->
|
||||
call_to_scode(Env, gmb_fate_ops:balance_currency(?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, chain_currency_supply, [_] = Args) ->
|
||||
call_to_scode(Env, gmb_fate_ops:currency_supply(?a, ?a), Args);
|
||||
builtin_to_scode(Env, chain_block_hash, [_] = Args) ->
|
||||
call_to_scode(Env, gmb_fate_ops:blockhash(?a, ?a), Args);
|
||||
builtin_to_scode(_Env, chain_coinbase, []) ->
|
||||
@@ -693,6 +700,9 @@ op_to_scode(crypto_verify_sig) -> gmb_fate_ops:verify_sig(?a, ?a, ?a,
|
||||
op_to_scode(crypto_verify_sig_secp256k1) -> gmb_fate_ops:verify_sig_secp256k1(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_ecverify_secp256k1) -> gmb_fate_ops:ecverify_secp256k1(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_ecrecover_secp256k1) -> gmb_fate_ops:ecrecover_secp256k1(?a, ?a, ?a);
|
||||
op_to_scode(crypto_verify_sig_mldsa44) -> gmb_fate_ops:verify_sig_mldsa44(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_verify_sig_mldsa65) -> gmb_fate_ops:verify_sig_mldsa65(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_verify_sig_mldsa87) -> gmb_fate_ops:verify_sig_mldsa87(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
||||
op_to_scode(crypto_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
||||
op_to_scode(crypto_blake2b) -> gmb_fate_ops:blake2b(?a, ?a);
|
||||
@@ -1033,6 +1043,9 @@ attributes(I) ->
|
||||
{'POSEIDON', A, B, C} -> Pure(A, [B, C]);
|
||||
{'VERIFY_SIG', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'VERIFY_SIG_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'VERIFY_SIG_MLDSA44', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'VERIFY_SIG_MLDSA65', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'VERIFY_SIG_MLDSA87', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'ECVERIFY_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'ECRECOVER_SECP256K1', A, B, C} -> Pure(A, [B, C]);
|
||||
{'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]);
|
||||
@@ -1056,6 +1069,8 @@ attributes(I) ->
|
||||
{'ADDRESS', A} -> Pure(A, []);
|
||||
{'BALANCE', A} -> Pure(A, []);
|
||||
{'BALANCE_OTHER', A, B} -> Pure(A, [B]);
|
||||
{'BALANCE_CURRENCY', A, B, C} -> Pure(A, [B, C]);
|
||||
{'CURRENCY_SUPPLY', A, B} -> Pure(A, [B]);
|
||||
{'ORIGIN', A} -> Pure(A, []);
|
||||
{'CALLER', A} -> Pure(A, []);
|
||||
{'GASPRICE', A} -> Pure(A, []);
|
||||
@@ -1076,6 +1091,7 @@ attributes(I) ->
|
||||
{'LOG4', A, B, C, D, E} -> Impure(none, [A, B, C, D, E]);
|
||||
'DEACTIVATE' -> Impure(none, []);
|
||||
{'SPEND', A, B} -> Impure(none, [A, B]);
|
||||
{'SPEND_CURRENCY', A, B, C} -> Impure(none, [A, B, C]);
|
||||
{'ORACLE_REGISTER', A, B, C, D, E, F, G} -> Impure(A, [B, C, D, E, F, G]);
|
||||
{'ORACLE_QUERY', A, B, C, D, E, F, G, H} -> Impure(A, [B, C, D, E, F, G, H]);
|
||||
{'ORACLE_RESPOND', A, B, C, D, E, F} -> Impure(none, [A, B, C, D, E, F]);
|
||||
|
||||
+15
-1
@@ -85,7 +85,8 @@ from_fate_builtin(QType, Val) ->
|
||||
Bts = {bytes_t, [], any},
|
||||
Qid = fun(Name) -> {qid, [], Name} end,
|
||||
Map = fun(KT, VT) -> {app_t, [], {id, [], "map"}, [KT, VT]} end,
|
||||
ChainTxArities = [3, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0],
|
||||
ChainTxArities = [3, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0,
|
||||
2, 1, 1, 4, 1],
|
||||
|
||||
case {QType, Val} of
|
||||
{["Chain", "ttl"], {variant, [1, 1], 0, {X}}} -> App("RelativeTTL", [Chk(Int, X)]);
|
||||
@@ -169,6 +170,19 @@ from_fate_builtin(QType, Val) ->
|
||||
App(["Chain","ContractCallTx"], [Chk(Adr, Addr), Chk(Int, Amount)]);
|
||||
{["Chain", "base_tx"], {variant, ChainTxArities, 21, {}}} ->
|
||||
App(["Chain","GAAttachTx"], []);
|
||||
{["Chain", "base_tx"], {variant, ChainTxArities, 22, {Addr, Amount}}} ->
|
||||
App(["Chain","AccountCreateTx"], [Chk(Adr, Addr), Chk(Int, Amount)]);
|
||||
{["Chain", "base_tx"], {variant, ChainTxArities, 23, {Amount}}} ->
|
||||
App(["Chain","MintTx"], [Chk(Int, Amount)]);
|
||||
{["Chain", "base_tx"], {variant, ChainTxArities, 24, {Legs}}} ->
|
||||
LegT = {tuple_t, [], [{app_t, [], {id, [], "option"}, [Adr]}, Adr, Adr, Int]},
|
||||
App(["Chain","ExchangeTx"], [Chk({app_t, [], {id, [], "list"}, [LegT]}, Legs)]);
|
||||
{["Chain", "base_tx"], {variant, ChainTxArities, 25, {Addr, Amount, Payload, Cs}}} ->
|
||||
CsT = {app_t, [], {id, [], "list"}, [{tuple_t, [], [Adr, Int]}]},
|
||||
App(["Chain","SpendCurrenciesTx"],
|
||||
[Chk(Adr, Addr), Chk(Int, Amount), Chk(Str, Payload), Chk(CsT, Cs)]);
|
||||
{["Chain", "base_tx"], {variant, ChainTxArities, 26, {Amount}}} ->
|
||||
App(["Chain","BurnTx"], [Chk(Int, Amount)]);
|
||||
|
||||
{["MCL_BLS12_381", "fp"], X} ->
|
||||
App(["MCL_BLS12_381", "fp"], [Chk(I32, X)]);
|
||||
|
||||
@@ -63,6 +63,11 @@ contract BasicAuthTx =
|
||||
Chain.ContractCreateTx(amount) => false
|
||||
Chain.ContractCallTx(ct_address, amount) => false
|
||||
Chain.GAAttachTx => false
|
||||
Chain.AccountCreateTx(_, _) => false
|
||||
Chain.MintTx(_) => false
|
||||
Chain.ExchangeTx(_) => false
|
||||
Chain.SpendCurrenciesTx(_, _, _, _) => false
|
||||
Chain.BurnTx(_) => false
|
||||
|
||||
function verify(tx_hash, n, s) =
|
||||
Crypto.verify_sig(to_sign(tx_hash, n), state.owner, s)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Contract using Quantum-Resistant signing (MLDSA65)
|
||||
contract QrAuth =
|
||||
record state = { nonce : int, owner : address, owner_pub : bytes }
|
||||
|
||||
entrypoint init(pub : bytes) = { nonce = 1
|
||||
, owner = Call.caller
|
||||
, owner_pub = pub }
|
||||
|
||||
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) => Crypto.verify_sig_mldsa65(to_sign(tx_hash, n), state.owner_pub, s)
|
||||
|
||||
entrypoint to_sign(h : hash, n : int) =
|
||||
Crypto.blake2b((h, n))
|
||||
|
||||
entrypoint weird_string() : string =
|
||||
"\x19Weird String\x42\nMore\n"
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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 implementing Quantum-resistant (MLDSA65) authentication
|
||||
contract QrAuthTx =
|
||||
record state = { nonce : int, owner : address, owner_pub : bytes }
|
||||
datatype foo = Bar | Baz()
|
||||
|
||||
entrypoint init(pub : bytes) = { nonce = 1
|
||||
, owner = Call.caller
|
||||
, owner_pub = pub }
|
||||
|
||||
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
|
||||
Chain.AccountCreateTx(_, _) => false
|
||||
Chain.MintTx(_) => false
|
||||
Chain.ExchangeTx(_) => false
|
||||
Chain.SpendCurrenciesTx(_, _, _, _) => false
|
||||
Chain.BurnTx(_) => false
|
||||
|
||||
function verify(tx_hash, n, s) =
|
||||
Crypto.verify_sig_mldsa65(to_sign(tx_hash, n), state.owner_pub, s)
|
||||
|
||||
entrypoint to_sign(h : hash, n : int) =
|
||||
Crypto.blake2b((h, n))
|
||||
|
||||
entrypoint weird_string() : string =
|
||||
"\x19Weird String\x42\nMore\n"
|
||||
@@ -29,6 +29,9 @@ contract UnappliedBuiltins =
|
||||
function crypto_verify_sig_secp256k1() = Crypto.verify_sig_secp256k1
|
||||
function crypto_ecverify_secp256k1() = Crypto.ecverify_secp256k1
|
||||
function crypto_ecrecover_secp256k1() = Crypto.ecrecover_secp256k1
|
||||
function crypto_verify_sig_mldsa44() = Crypto.verify_sig_mldsa44
|
||||
function crypto_verify_sig_mldsa65() = Crypto.verify_sig_mldsa65
|
||||
function crypto_verify_sig_mldsa87() = Crypto.verify_sig_mldsa87
|
||||
function crypto_sha3() = Crypto.sha3 : t => _
|
||||
function crypto_sha256() = Crypto.sha256 : t => _
|
||||
function crypto_blake2b() = Crypto.blake2b : t => _
|
||||
|
||||
@@ -115,6 +115,9 @@ compilable_contracts() ->
|
||||
{"funargs", "chain_base_tx", ["Chain.NameRevokeTx(#ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)"]},
|
||||
{"funargs", "chain_base_tx", ["Chain.NameTransferTx(ak_2dATVcZ9KJU5a8hdsVtTv21pYiGWiPbmVcU1Pz72FFqpk9pSRR, #ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)"]},
|
||||
{"funargs", "chain_base_tx", ["Chain.GAAttachTx"]},
|
||||
{"funargs", "chain_base_tx", ["Chain.MintTx(100)"]},
|
||||
{"funargs", "chain_base_tx", ["Chain.BurnTx(50)"]},
|
||||
{"funargs", "chain_base_tx", ["Chain.AccountCreateTx(ak_2dATVcZ9KJU5a8hdsVtTv21pYiGWiPbmVcU1Pz72FFqpk9pSRR, 50)"]},
|
||||
{"funargs", "sig", ["sg_MhibzTP1wWzGCTjtPFr1TiPqRJrrJqw7auvEuF5i3FdoALWqXLBDY6xxRRNUSPHK3EQTnTzF12EyspkxrSMxVHKsZeSMj"]},
|
||||
{"variant_types", "init", []},
|
||||
{"basic_auth", "init", []},
|
||||
|
||||
Reference in New Issue
Block a user