-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.leo
105 lines (86 loc) · 3.2 KB
/
main.leo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
program izar_protocol_v1.aleo {
mapping izar_keeper: bool => [address; 20];
mapping izar_digest: bool => scalar;
// 0: current_epoch, 1: current_keeper_num;
mapping izar_config: u8 => u32;
mapping nonces: Nonce => bool;
struct Nonce {
chain_id: u32,
nonce: u128,
}
struct IzarRecvMsg {
protocol_addr: address, // avoid replay attack when updated this contract
nonce: u128,
to_addr: address,
from_chain_id: u32,
from_asset_addr: field, // (from_chain_id, from_asset_addr) construct a unique asset
token_id: field,
amount: u128,
}
struct IzarCrossMsg {
to_chain_id: u32,
to_addr: field,
to_asset_addr: field,
token_id: field,
amount: u128,
fee: u128,
}
inline protocol_owner() -> address {
return aleo1yu6ssnehj4plgznatenfut3hkrfus26kqd226k99wfx79jqmsuxqfernns;
}
inline invalid_validator() -> address {
return aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc;
}
inline protocol_contract() -> address {
return aleo1e5szs84jql2hn08ffxc7yn97wa8s9vk7jgshcddxmaekdxh85upsdt8p9g;
}
/* config setup */
transition update_keeper (keepers: [address; 20]) {
assert_eq(self.caller, protocol_owner());
let digest: scalar = Poseidon8::hash_to_scalar(keepers);
return then finalize (keepers, digest);
}
finalize update_keeper (keepers: [address; 20], digest: scalar) {
let accpeted: u32 = 0u32;
for i: u8 in 0u8..20u8 {
if keepers[i] != invalid_validator() {
accpeted += 1u32;
}
}
Mapping::set(izar_keeper, true, keepers);
Mapping::set(izar_config, 1u8, accpeted);
Mapping::set(izar_digest, true, digest);
}
function verify_sigs (keepers: [address; 20], signatures: [signature; 20], msg: IzarRecvMsg) -> (scalar, u32) {
let accepted: u32 = 0u32;
for i: u8 in 0u8..20u8 {
if keepers[i] != invalid_validator() {
let sig: signature = signatures[i];
if sig.verify(keepers[i], msg) {
accepted += 1u32;
}
}
}
let result: scalar = Poseidon8::hash_to_scalar(keepers);
return (result, accepted);
}
transition verify (signatures: [signature; 20], keepers: [address; 20], payload: IzarRecvMsg) {
assert_eq(payload.protocol_addr, protocol_contract());
let (result, accepted): (scalar, u32) = verify_sigs(keepers, signatures, payload);
let nonce: Nonce = Nonce {
chain_id: payload.from_chain_id,
nonce: payload.nonce,
};
return then finalize (nonce, result, accepted);
}
finalize verify (nonce: Nonce, keeper_digest: scalar, accepted: u32) {
// check nonce
assert(!Mapping::get_or_use(nonces, nonce, false));
// check keeper digest & accepted
assert(keeper_digest == Mapping::get(izar_digest, true));
let num: u32 = Mapping::get(izar_config, 1u8);
assert(accepted >= num - (num - 1u32) / 3u32);
// set nonce
Mapping::set(nonces, nonce, true);
}
}