Ton

Форк
0
/
pow-testgiver-code.fc 
158 строк · 5.6 Кб
1
;; Advanced TestGiver smart contract with Proof-of-Work verification
2

3
int ufits(int x, int bits) impure asm "UFITSX";
4

5
() recv_internal(slice in_msg) impure {
6
  ;; do nothing for internal messages
7
}
8

9
() check_proof_of_work(slice cs) impure inline_ref {
10
  var hash = slice_hash(cs);
11
  var ds = get_data().begin_parse();
12
  var (stored_seqno_sw, public_key, seed, pow_complexity) = (ds~load_uint(64), ds~load_uint(256), ds~load_uint(128), ds~load_uint(256));
13
  throw_unless(24, hash < pow_complexity);  ;; hash problem NOT solved
14
  var (op, flags, expire, whom, rdata1, rseed, rdata2) = (cs~load_uint(32), cs~load_int(8), cs~load_uint(32), cs~load_uint(256), cs~load_uint(256), cs~load_uint(128), cs~load_uint(256));
15
  cs.end_parse();
16
  ufits(expire - now(), 10);
17
  throw_unless(25, (rseed == seed) & (rdata1 == rdata2));
18
  ;; Proof of Work correct
19
  accept_message();
20
  randomize_lt();
21
  randomize(rdata1);
22
  var (last_success, xdata) = (ds~load_uint(32), ds~load_ref());
23
  ds.end_parse();
24
  ds = xdata.begin_parse();
25
  var (amount, target_delta, min_cpl, max_cpl) = (ds~load_grams(), ds~load_uint(32), ds~load_uint(8), ds~load_uint(8));
26
  ds.end_parse();
27
  ;; recompute complexity
28
  int delta = now() - last_success;
29
  if (delta > 0) {
30
    int factor = muldivr(delta, 1 << 128, target_delta);
31
    factor = min(max(factor, 7 << 125), 9 << 125);  ;; factor must be in range 7/8 .. 9/8
32
    pow_complexity = muldivr(pow_complexity, factor, 1 << 128);  ;; rescale complexity
33
    pow_complexity = min(max(pow_complexity, 1 << min_cpl), 1 << max_cpl);
34
  }
35
  ;; update data
36
  set_data(begin_cell()
37
    .store_uint(stored_seqno_sw, 64)
38
    .store_uint(public_key, 256)
39
    .store_uint(random() >> 128, 128)  ;; new seed
40
    .store_uint(pow_complexity, 256)
41
    .store_uint(now(), 32)   ;; new last_success
42
    .store_ref(xdata)
43
    .end_cell());
44
  commit();
45
  ;; create outbound message
46
  send_raw_message(begin_cell()
47
    .store_uint(((flags & 1) << 6) | 0x84, 9)
48
    .store_int(flags >> 2, 8)
49
    .store_uint(whom, 256)
50
    .store_grams(amount)
51
    .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
52
  .end_cell(), 3);
53
}
54

55
() rescale_complexity(slice cs) impure inline_ref {
56
  var (op, expire) = (cs~load_uint(32), cs~load_uint(32));
57
  cs.end_parse();
58
  int time = now();
59
  throw_unless(28, time > expire);
60
  var ds = get_data().begin_parse();
61
  var (skipped_data, pow_complexity, last_success, xdata) = (ds~load_bits(64 + 256 + 128), ds~load_uint(256), ds~load_uint(32), ds~load_ref());
62
  ds.end_parse();
63
  throw_unless(29, expire > last_success);
64
  ds = xdata.begin_parse();
65
  var (amount, target_delta) = (ds~load_grams(), ds~load_uint(32));
66
  int delta = time - last_success;
67
  throw_unless(30, delta >= target_delta * 16);
68
  accept_message();
69
  var (min_cpl, max_cpl) = (ds~load_uint(8), ds~load_uint(8));
70
  ds.end_parse();
71
  int factor = muldivr(delta, 1 << 128, target_delta);
72
  int max_complexity = (1 << max_cpl);
73
  int max_factor = muldiv(max_complexity, 1 << 128, pow_complexity);
74
  pow_complexity = (max_factor < factor ? max_complexity : muldivr(pow_complexity, factor, 1 << 128));
75
  last_success = time - target_delta;
76
  set_data(begin_cell()
77
    .store_slice(skipped_data)
78
    .store_uint(pow_complexity, 256)
79
    .store_uint(last_success, 32)   ;; new last_success
80
    .store_ref(xdata)
81
    .end_cell());
82
}
83

84
(slice, ()) ~update_params(slice ds, cell pref) inline_ref {
85
  var cs = pref.begin_parse();
86
  var reset_cpl = cs~load_uint(8);
87
  var (seed, pow_complexity, last_success) = (ds~load_uint(128), ds~load_uint(256), ds~load_uint(32));
88
  if (reset_cpl) {
89
    randomize(seed);
90
    pow_complexity = (1 << reset_cpl);
91
    seed = (random() >> 128);
92
  }
93
  var c = begin_cell()
94
    .store_uint(seed, 128)
95
    .store_uint(pow_complexity, 256)
96
    .store_uint(now(), 32)
97
    .store_ref(begin_cell().store_slice(cs).end_cell())
98
    .end_cell();
99
  return (begin_parse(c), ());
100
}
101

102
() recv_external(slice in_msg) impure {
103
  var op = in_msg.preload_uint(32);
104
  if (op == 0x4d696e65) {
105
    ;; Mine = Obtain test grams by presenting valid proof of work
106
    return check_proof_of_work(in_msg);
107
  }
108
  if (op == 0x5253636c) {
109
    ;; RScl = Rescale complexity if no success for long time
110
    return rescale_complexity(in_msg);
111
  }
112
  var signature = in_msg~load_bits(512);
113
  var cs = in_msg;
114
  var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
115
  throw_if(35, valid_until <= now());
116
  var ds = get_data().begin_parse();
117
  var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256));
118
  throw_unless(33, msg_seqno == stored_seqno);
119
  throw_unless(34, (subwallet_id == stored_subwallet) | (subwallet_id == 0));
120
  throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));
121
  accept_message();
122
  cs~touch();
123
  while (cs.slice_refs()) {
124
    var ref = cs~load_ref();
125
    var mode = cs~load_uint(8);
126
    if (mode < 0xff) {
127
      send_raw_message(ref, mode);
128
    } else {
129
      ds~update_params(ref);
130
    }
131
  }
132
  set_data(begin_cell()
133
    .store_uint(stored_seqno + 1, 32)
134
    .store_uint(stored_subwallet, 32)
135
    .store_uint(public_key, 256)
136
    .store_slice(ds)
137
    .end_cell());
138
}
139

140
;; Get methods
141

142
int seqno() method_id {
143
  return get_data().begin_parse().preload_uint(32);
144
}
145

146
;; gets (seed, pow_complexity, amount, interval)
147
(int, int, int, int) get_pow_params() method_id {
148
  var ds = get_data().begin_parse().skip_bits(32 + 32 + 256);
149
  var (seed, pow_complexity, xdata) = (ds~load_uint(128), ds~load_uint(256), ds.preload_ref());
150
  ds = xdata.begin_parse();
151
  return (seed, pow_complexity, ds~load_grams(), ds.preload_uint(32));
152
}
153

154
int get_public_key() method_id {
155
  var ds = get_data().begin_parse();
156
  ds~load_uint(32 + 32);
157
  return ds.preload_uint(256);
158
}
159

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.