1use rhdl::prelude::*;
34
35use crate::cert::{ROLE_HISTORY, share_context};
36use crate::cert::collector::popcount16;
37use crate::consensus::{Constraint, ConsMsg, Install, SlotView, empty_constraint, leader_of};
38use crate::ctb::bswap64;
39
40pub mod kind {
42 pub const COMMIT: u128 = 2;
43 pub const SEALVIEW: u128 = 5;
44 pub const NEWVIEW: u128 = 6;
45}
46
47pub const HIS_DOMAIN: u128 = 0x5349_482D_3242_5552;
49
50#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
52pub struct VcConfig {
53 pub init: bool,
54 pub n: b5,
55 pub me: b5,
56 pub session: b64,
57 pub nv_deadline: b32,
60}
61
62#[derive(Clone, Copy, Debug, PartialEq, Digital)]
64pub struct Record<const P: usize> {
65 pub valid: bool,
66 pub certified: bool,
67 pub view: b32,
68 pub instance: b32,
69 pub digest: [b64; 4],
70 pub len: b5,
71 pub value: [b32; P],
72}
73
74#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
76pub struct VcDigestReq {
77 pub valid: bool,
78 pub epoch: b32,
79 pub subject: b5,
80 pub j: b4,
81 pub block: [b64; 16],
84}
85
86#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
88pub struct VcDigest {
89 pub valid: bool,
90 pub epoch: b32,
91 pub subject: b5,
92 pub j: b4,
93 pub digest: [b64; 4],
94}
95
96#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
98pub struct VcSignReq {
99 pub valid: bool,
100 pub epoch: b32,
101 pub subject: b5,
102 pub context: [b64; 6],
103}
104
105#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
107pub struct VcSigned {
108 pub valid: bool,
109 pub epoch: b32,
110 pub subject: b5,
111 pub sig: [b64; 8],
112}
113
114#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
116pub struct VcKey {
117 pub valid: bool,
118 pub view: b32,
119 pub subject: b5,
120 pub digest: [b64; 4],
121 pub sig: [b64; 8],
122}
123
124#[derive(Clone, Copy, Debug, PartialEq, Digital)]
126pub struct VcIn<const G: usize, const P: usize> {
127 pub cfg: VcConfig,
128 pub ctb: ConsMsg<P>,
131 pub ctb_taken: bool,
132 pub gap_from: b16,
136 pub view: b32,
138 pub low: b32,
140 pub stalled: bool,
141 pub bridge_done: bool,
142 pub slots: [SlotView<P>; G],
143 pub certified: [bool; G],
145 pub hist_certified: [bool; 16],
147 pub digest: VcDigest,
148 pub signed: VcSigned,
149 pub ctb_ready: bool,
150 pub digest_ready: bool,
151 pub sign_ready: bool,
152 pub key_ready: bool,
153 pub share_ready: bool,
154}
155
156#[derive(Clone, Copy, Debug, PartialEq, Digital)]
158pub struct VcOut<const G: usize, const P: usize> {
159 pub ctb_ready: bool,
161 pub sealing: bool,
163 pub ctb_send: ConsMsg<P>,
164 pub digest_req: VcDigestReq,
165 pub sign_req: VcSignReq,
166 pub open: VcKey,
168 pub own: VcKey,
169 pub share_send: VcKey,
171 pub install: Install<G, P>,
172 pub refused: b32,
173}
174
175#[derive(Clone, Copy, Debug, PartialEq, Digital)]
177pub struct VcState<const N: usize, const G: usize, const P: usize> {
178 pub configured: bool,
179 pub epoch: b32,
180 pub n: b5,
181 pub me: b5,
182 pub q: b5,
183 pub session: b64,
184 pub view: b32,
185 pub rec: [[Record<P>; G]; N],
186 pub sealed_from: b16,
189 pub seal_hi: [b32; N],
192 pub p_view: b32,
197 pub p_open: b16,
198 pub p_busy: bool,
199 pub p_subject: b5,
200 pub p_rec: [Record<P>; G],
201 pub p_j: b4,
202 pub p_sent: bool,
203 pub p_acc: [b64; 4],
204 pub p_have: bool,
205 pub p_sign_out: bool,
206 pub p_signed: bool,
207 pub p_sig: [b64; 8],
208 pub p_key_out: bool,
211 pub p_keyed: bool,
212 pub p_own_given: bool,
213 pub p_shared: bool,
214 pub skip_pending: bool,
217 pub in_skipped: bool,
218 pub late_done: bool,
219 pub prev_open_done: b16,
220 pub dirty: b16,
224 pub tainted: b16,
226 pub sealing: bool,
227 pub seal_sent: bool,
228 pub chain_busy: bool,
230 pub chain_subject: b5,
231 pub chain_j: b4,
232 pub chain_sent: bool,
233 pub chain_acc: [b64; 4],
234 pub hdone: b16,
235 pub hdigest: [[b64; 4]; N],
236 pub opened: b16,
237 pub open_done: b16,
240 pub sign_sent: b16,
241 pub signed: b16,
242 pub hsig: [[b64; 8]; N],
243 pub own_given: b16,
244 pub shared: b16,
245 pub nv_sent: bool,
246 pub clock: b32,
247 pub seal_at: b32,
248 pub nv_deadline: b32,
249 pub installed_next: bool,
251 pub h_ctb: ConsMsg<P>,
252 pub h_dig: VcDigestReq,
253 pub h_sign: VcSignReq,
254 pub h_open: VcKey,
255 pub h_own: VcKey,
256 pub h_share: VcKey,
257 pub h_inst: Install<G, P>,
258 pub refused: b32,
259}
260
261#[kernel]
263pub fn empty_record<const P: usize>() -> Record<P> {
264 Record::<P> { valid: false, certified: false, view: b32(0), instance: b32(0), digest: [b64(0); 4], len: b5(0), value: [b32(0); P] }
265}
266
267#[kernel]
269pub fn vc_idle_msg<const P: usize>() -> ConsMsg<P> {
270 ConsMsg::<P> { valid: false, from: b5(0), kind: b4(0), view: b32(0), instance: b32(0), digest: [b64(0); 4], len: b5(0), value: [b32(0); P] }
271}
272
273#[kernel]
275pub fn idle_install<const G: usize, const P: usize>() -> Install<G, P> {
276 Install::<G, P> { valid: false, skip: false, late: false, view: b32(0), c: [empty_constraint::<P>(); G] }
277}
278
279#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
281pub struct Link {
282 pub view: b32,
283 pub subject: b5,
284 pub j: b4,
285}
286
287#[kernel]
292pub fn history_block<const P: usize>(session: b64, link: Link, acc: [b64; 4], rec: Record<P>) -> [b64; 16] {
293 let mut le = [b64(0); 16];
294 le[0] = b64(HIS_DOMAIN);
295 le[1] = session;
296 le[2] = link.view.resize::<64>() | (link.subject.resize::<64>() << b64(32));
297 let flags: b64 = if rec.valid { b64(1) } else { b64(0) };
298 le[3] = link.j.resize::<64>() | (flags << b64(32));
299 for k in 0..4 {
300 le[4 + k] = acc[k];
301 }
302 if rec.valid {
303 le[8] = rec.view.resize::<64>() | (rec.instance.resize::<64>() << b64(32));
304 for k in 0..4 {
305 le[9 + k] = rec.digest[k];
306 }
307 le[13] = rec.len.resize::<64>();
308 for k in 0..P {
309 let word = if b5(k as u128) < rec.len { rec.value[k] } else { b32(0) };
310 let w = (k >> 1) + 14;
311 let sh = (k & 1) * 32;
312 le[w] = le[w] | (word.resize::<64>() << b64(sh as u128));
313 }
314 }
315 let mut be = [b64(0); 16];
316 for k in 0..16 {
317 be[k] = bswap64(le[k]);
318 }
319 be
320}
321
322impl<const N: usize, const G: usize, const P: usize> VcState<N, G, P> {
323 pub fn idle() -> Self {
324 Self {
325 configured: false,
326 epoch: b32(0),
327 n: b5(0),
328 me: b5(0),
329 q: b5(0),
330 session: b64(0),
331 view: b32(0),
332 rec: [[empty_record::<P>(); G]; N],
333 sealed_from: b16(0),
334 seal_hi: [b32(0); N],
335 p_view: b32(0),
336 p_open: b16(0),
337 p_busy: false,
338 p_subject: b5(0),
339 p_rec: [empty_record::<P>(); G],
340 p_j: b4(0),
341 p_sent: false,
342 p_acc: [b64(0); 4],
343 p_have: false,
344 p_sign_out: false,
345 p_signed: false,
346 p_sig: [b64(0); 8],
347 p_key_out: false,
348 p_keyed: false,
349 p_own_given: false,
350 p_shared: false,
351 skip_pending: false,
352 in_skipped: false,
353 late_done: false,
354 prev_open_done: b16(0),
355 dirty: b16(0),
356 tainted: b16(0),
357 sealing: false,
358 seal_sent: false,
359 chain_busy: false,
360 chain_subject: b5(0),
361 chain_j: b4(0),
362 chain_sent: false,
363 chain_acc: [b64(0); 4],
364 hdone: b16(0),
365 hdigest: [[b64(0); 4]; N],
366 opened: b16(0),
367 open_done: b16(0),
368 sign_sent: b16(0),
369 signed: b16(0),
370 hsig: [[b64(0); 8]; N],
371 own_given: b16(0),
372 shared: b16(0),
373 nv_sent: false,
374 clock: b32(0),
375 seal_at: b32(0),
376 nv_deadline: b32(0),
377 installed_next: false,
378 h_ctb: vc_idle_msg::<P>(),
379 h_dig: VcDigestReq::default(),
380 h_sign: VcSignReq::default(),
381 h_open: VcKey::default(),
382 h_own: VcKey::default(),
383 h_share: VcKey::default(),
384 h_inst: idle_install::<G, P>(),
385 refused: b32(0),
386 }
387 }
388}
389
390impl<const N: usize, const G: usize, const P: usize> Default for VcState<N, G, P> {
391 fn default() -> Self {
392 Self::idle()
393 }
394}
395
396impl<const G: usize, const P: usize> Default for VcIn<G, P> {
397 fn default() -> Self {
398 Self {
399 cfg: VcConfig::default(),
400 ctb: vc_idle_msg::<P>(),
401 ctb_taken: false,
402 gap_from: b16(0),
403 view: b32(0),
404 low: b32(0),
405 stalled: false,
406 bridge_done: false,
407 slots: [SlotView::<P> { active: false, instance: b32(0), dig_have: false, digest: [b64(0); 4], len: b5(0), value: [b32(0); P], kview: b32(0) }; G],
408 certified: [false; G],
409 hist_certified: [false; 16],
410 digest: VcDigest::default(),
411 signed: VcSigned::default(),
412 ctb_ready: false,
413 digest_ready: false,
414 sign_ready: false,
415 key_ready: false,
416 share_ready: false,
417 }
418 }
419}
420
421#[kernel]
423pub fn vc_step<const N: usize, const G: usize, const P: usize>(i: VcIn<G, P>, r: VcState<N, G, P>) -> (VcOut<G, P>, VcState<N, G, P>) {
424 let mut s = r;
425 let gmask = b32(G as u128) - b32(1);
426 if i.cfg.init {
427 s = VcState::<N, G, P> {
428 configured: i.cfg.n >= b5(3) && i.cfg.n <= b5(N as u128) && i.cfg.me < i.cfg.n && i.cfg.session != b64(0),
429 epoch: r.epoch + b32(1),
430 n: i.cfg.n,
431 me: i.cfg.me,
432 q: (i.cfg.n >> b5(1)) + b5(1),
433 session: i.cfg.session,
434 view: b32(0),
435 rec: [[empty_record::<P>(); G]; N],
436 sealed_from: b16(0),
437 seal_hi: [b32(0); N],
438 p_view: b32(0),
439 p_open: b16(0),
440 p_busy: false,
441 p_subject: b5(0),
442 p_rec: [empty_record::<P>(); G],
443 p_j: b4(0),
444 p_sent: false,
445 p_acc: [b64(0); 4],
446 p_have: false,
447 p_sign_out: false,
448 p_signed: false,
449 p_sig: [b64(0); 8],
450 p_key_out: false,
451 p_keyed: false,
452 p_own_given: false,
453 p_shared: false,
454 skip_pending: false,
455 in_skipped: false,
456 late_done: false,
457 prev_open_done: b16(0),
458 dirty: b16(0),
459 tainted: b16(0),
460 sealing: false,
461 seal_sent: false,
462 chain_busy: false,
463 chain_subject: b5(0),
464 chain_j: b4(0),
465 chain_sent: false,
466 chain_acc: [b64(0); 4],
467 hdone: b16(0),
468 hdigest: [[b64(0); 4]; N],
469 opened: b16(0),
470 open_done: b16(0),
471 sign_sent: b16(0),
472 signed: b16(0),
473 hsig: [[b64(0); 8]; N],
474 own_given: b16(0),
475 shared: b16(0),
476 nv_sent: false,
477 clock: b32(0),
478 seal_at: b32(0),
479 nv_deadline: b32(0),
480 installed_next: false,
481 h_ctb: vc_idle_msg::<P>(),
482 h_dig: VcDigestReq::default(),
483 h_sign: VcSignReq::default(),
484 h_open: VcKey::default(),
485 h_own: VcKey::default(),
486 h_share: VcKey::default(),
487 h_inst: idle_install::<G, P>(),
488 refused: b32(0),
489 };
490 }
491 if i.cfg.init {
492 s.nv_deadline = i.cfg.nv_deadline;
493 s.configured = s.configured && i.cfg.nv_deadline != b32(0);
494 }
495 let run = r.configured && !i.cfg.init;
496 s.clock = r.clock + b32(1);
497 let next = r.view + b32(1);
498 let next_leader = leader_of(next, r.n);
499
500 let m = i.ctb;
503 let is_nv = m.valid && m.kind == b4(kind::NEWVIEW);
504 let subjects: b16 = m.value[0].resize();
505 let mut all_cert = true;
506 for k in 0..16 {
507 if ((subjects >> b16(k as u128)) & b16(1)) != b16(0) {
508 if !(i.hist_certified[k] && ((r.open_done >> b16(k as u128)) & b16(1)) != b16(0)) {
510 all_cert = false;
511 }
512 }
513 }
514 let nv_ahead = is_nv && m.view == next + b32(1);
517 let nv_late = is_nv && m.view == r.view && r.in_skipped && !r.late_done && !r.seal_sent && (r.opened & subjects) == b16(0);
522 let mut late_cert = true;
523 for k in 0..16 {
524 if ((subjects >> b16(k as u128)) & b16(1)) != b16(0) {
525 if !(i.hist_certified[k] && ((r.prev_open_done >> b16(k as u128)) & b16(1)) != b16(0)) {
526 late_cert = false;
527 }
528 }
529 }
530 let nv_stale = is_nv && !nv_ahead && !nv_late && (m.view != next || r.installed_next);
531 let nv_shape = is_nv && m.from == leader_of(m.view, r.n) && popcount16(subjects) == r.q && (subjects & !(r_all(r.n))) == b16(0);
534 let nv_wait = nv_ahead || (is_nv && !nv_late && !nv_stale && nv_shape && (!r.seal_sent || !all_cert)) || (nv_late && nv_shape && !late_cert);
536 let late_seal = m.valid && m.kind == b4(kind::SEALVIEW) && m.from < r.n && m.view == r.p_view && ((r.p_open >> m.from.resize::<16>()) & b16(1)) != b16(0);
539 let late_hold = late_seal && r.p_busy;
540
541 let mut o = VcOut::<G, P> {
542 ctb_ready: run && !nv_wait && !late_hold,
543 sealing: r.sealing,
544 ctb_send: r.h_ctb,
545 digest_req: r.h_dig,
546 sign_req: r.h_sign,
547 open: r.h_open,
548 own: r.h_own,
549 share_send: r.h_share,
550 install: r.h_inst,
551 refused: r.refused,
552 };
553 if i.cfg.init {
554 o.ctb_send.valid = false;
555 o.digest_req.valid = false;
556 o.sign_req.valid = false;
557 o.open.valid = false;
558 o.own.valid = false;
559 o.share_send.valid = false;
560 o.install.valid = false;
561 }
562 if !i.cfg.init {
563 if r.h_ctb.valid && i.ctb_ready {
564 s.h_ctb.valid = false;
565 }
566 if r.h_dig.valid && i.digest_ready {
567 s.h_dig.valid = false;
568 }
569 if r.h_sign.valid && i.sign_ready {
570 s.h_sign.valid = false;
571 }
572 if r.h_open.valid && i.key_ready {
573 s.h_open.valid = false;
574 if r.p_key_out {
575 s.prev_open_done = r.prev_open_done | (b16(1) << r.h_open.subject.resize::<16>());
577 s.p_key_out = false;
578 s.p_keyed = true;
579 } else {
580 s.open_done = r.open_done | (b16(1) << r.h_open.subject.resize::<16>());
581 }
582 }
583 if r.h_own.valid && i.key_ready && !r.h_open.valid {
584 s.h_own.valid = false;
585 }
586 if r.h_share.valid && i.share_ready {
587 s.h_share.valid = false;
588 }
589 s.h_inst.valid = false;
591 }
592 if r.h_open.valid {
593 o.own.valid = false;
594 }
595
596 if run && m.valid && i.ctb_taken && m.from < r.n {
598 let fk: b4 = m.from.resize();
599 let mut from_hi = b32(0);
602 for x in 0..N {
603 if m.from == b5(x as u128) {
604 from_hi = r.seal_hi[x];
605 if m.kind == b4(kind::SEALVIEW) && m.view + b32(1) > r.seal_hi[x] {
606 s.seal_hi[x] = m.view + b32(1);
607 }
608 }
609 }
610 if m.kind == b4(kind::COMMIT) && m.view <= r.view && from_hi <= m.view {
613 let k: b3 = (m.instance & gmask).resize();
616 let e = r.rec[fk][k];
617 let newer = !e.valid || m.instance > e.instance || (m.instance == e.instance && m.view > e.view);
618 let replaceable = !e.valid || m.instance == e.instance || e.instance < i.low;
623 if newer && replaceable {
624 s.rec[fk][k] = Record::<P> { valid: true, certified: false, view: m.view, instance: m.instance, digest: m.digest, len: m.len, value: m.value };
625 s.dirty = s.dirty | (b16(1) << m.from.resize::<16>());
626 }
627 } else if m.kind == b4(kind::SEALVIEW) && m.view >= r.view {
628 s.sealed_from = r.sealed_from | (b16(1) << m.from.resize::<16>());
631 } else if late_seal && !r.p_busy {
632 s.p_open = r.p_open & !(b16(1) << m.from.resize::<16>());
634 s.p_busy = true;
635 s.p_subject = m.from;
636 for x in 0..N {
638 if m.from == b5(x as u128) {
639 for k in 0..G {
640 s.p_rec[k] = r.rec[x][k];
641 }
642 }
643 }
644 s.p_j = b4(0);
645 s.p_sent = false;
646 s.p_acc = [b64(0); 4];
647 s.p_have = false;
648 s.p_sign_out = false;
649 s.p_signed = false;
650 s.p_key_out = false;
651 s.p_keyed = false;
652 s.p_own_given = false;
653 s.p_shared = false;
654 let cb = b16(1) << m.from.resize::<16>();
657 s.dirty = (s.dirty & !cb) | (s.dirty & !r.dirty & cb);
658 } else if is_nv && !nv_stale && !nv_wait {
659 if !nv_shape {
660 s.refused = r.refused + b32(1);
661 } else {
662 let mut inst = idle_install::<G, P>();
665 inst.valid = true;
666 inst.view = if nv_late { r.view } else { next };
667 inst.late = nv_late;
668 let mut conflict = false;
669 for k in 0..G {
670 let mut best = empty_record::<P>();
671 for x in 0..N {
672 let bit = ((subjects >> b16(x as u128)) & b16(1)) != b16(0);
673 let e = r.rec[x][k];
674 if bit && e.valid {
675 if !best.valid || e.instance > best.instance || (e.instance == best.instance && e.view > best.view) {
676 best = e;
677 } else if e.instance == best.instance && e.view == best.view && e.digest != best.digest {
678 conflict = true;
679 }
680 }
681 }
682 if best.valid {
683 inst.c[k] = Constraint::<P> { set: true, instance: best.instance, digest: best.digest, len: best.len, value: best.value };
684 }
685 for x in 0..N {
693 let bit = ((subjects >> b16(x as u128)) & b16(1)) != b16(0);
694 let e = r.rec[x][k];
695 if nv_late && bit && e.valid && (!e.certified || e.view >= r.view) {
696 conflict = true;
697 }
698 }
699 for x in 0..N {
708 let own = r.rec[x][k];
709 if nv_late && r.me == b5(x as u128) && own.valid && own.instance >= i.low {
710 let kept = best.valid && (best.instance > own.instance || (best.instance == own.instance && (best.digest == own.digest || best.view > own.view)));
711 if !kept {
712 conflict = true;
713 }
714 }
715 }
716 }
717 if nv_late && (r.dirty & subjects) != b16(0) {
720 conflict = true;
721 }
722 if conflict {
723 s.refused = r.refused + b32(1);
724 } else if nv_late {
725 s.h_inst = inst;
726 s.late_done = true;
727 } else {
728 s.h_inst = inst;
729 s.installed_next = true;
730 s.skip_pending = false;
731 }
732 }
733 }
734 }
735
736 if run {
741 s.tainted = r.tainted | i.gap_from;
742 }
743
744 for x in 0..N {
747 for k in 0..G {
748 let e = s.rec[x][k];
749 let sv = i.slots[k];
750 if e.valid && !e.certified && sv.kview == e.view && sv.active && sv.dig_have && sv.instance == e.instance && sv.digest == e.digest && i.certified[k] {
753 s.rec[x][k].certified = true;
754 }
755 }
756 }
757 for k in 0..G {
758 let e = s.p_rec[k];
759 let sv = i.slots[k];
760 if e.valid && !e.certified && sv.kview == e.view && sv.active && sv.dig_have && sv.instance == e.instance && sv.digest == e.digest && i.certified[k] {
761 s.p_rec[k].certified = true;
762 }
763 }
764
765 let others_sealed = popcount16(r.sealed_from & !(b16(1) << r.me.resize::<16>()));
767 let nv_seen = is_nv && !nv_stale && !nv_ahead && m.view == next && nv_shape;
771 if run && !r.sealing && (i.stalled || others_sealed >= r.q || nv_seen) {
772 s.sealing = true;
773 }
774 if run && r.sealing && i.bridge_done && !r.seal_sent && !r.h_ctb.valid {
775 s.h_ctb = ConsMsg::<P> { valid: true, from: r.me, kind: b4(kind::SEALVIEW), view: r.view, instance: b32(0), digest: [b64(0); 4], len: b5(0), value: [b32(0); P] };
776 s.seal_sent = true;
777 s.seal_at = r.clock;
778 }
779 let quorum_sealed = popcount16(r.sealed_from) >= r.q;
787 if run && r.seal_sent && quorum_sealed && !r.installed_next && !r.h_inst.valid && r.clock - r.seal_at >= r.nv_deadline {
788 let mut skip = idle_install::<G, P>();
789 skip.valid = true;
790 skip.skip = true;
791 skip.view = next;
792 s.h_inst = skip;
793 s.installed_next = true;
794 s.skip_pending = true;
795 }
796
797 if run && i.digest.valid && i.digest.epoch == r.epoch && r.chain_busy && r.chain_sent && i.digest.subject == r.chain_subject && i.digest.j == r.chain_j {
799 s.chain_acc = i.digest.digest;
800 s.chain_sent = false;
801 if r.chain_j == b4((G - 1) as u128) {
802 s.chain_busy = false;
803 let sb = r.chain_subject;
804 let sk: b4 = sb.resize();
805 s.hdone = r.hdone | (b16(1) << sb.resize::<16>());
806 s.hdigest[sk] = i.digest.digest;
807 } else {
808 s.chain_j = r.chain_j + b4(1);
809 }
810 }
811 if run && i.digest.valid && i.digest.epoch == r.epoch && r.p_busy && r.p_sent && !r.chain_sent && i.digest.subject == r.p_subject && i.digest.j == r.p_j {
812 s.p_acc = i.digest.digest;
813 s.p_sent = false;
814 if r.p_j == b4((G - 1) as u128) {
815 s.p_have = true;
816 } else {
817 s.p_j = r.p_j + b4(1);
818 }
819 }
820 if run && r.p_busy && ((r.tainted >> r.p_subject.resize::<16>()) & b16(1)) != b16(0) {
822 s.p_busy = false;
823 }
824 if run && !r.chain_busy && !r.p_sent && !(r.p_busy && !r.p_have) {
828 let mut found = false;
830 for x in 0..N {
831 let bit = b16(1) << b16(x as u128);
832 let mut ready = (r.sealed_from & bit) != b16(0) && (r.hdone & bit) == b16(0) && (r.tainted & bit) == b16(0);
833 for k in 0..G {
834 if r.rec[x][k].valid && !r.rec[x][k].certified {
835 ready = false;
836 }
837 }
838 if !found && ready {
839 found = true;
840 s.chain_busy = true;
841 s.chain_subject = b5(x as u128);
842 s.chain_j = b4(0);
843 s.chain_sent = false;
844 s.chain_acc = [b64(0); 4];
845 s.dirty = (s.dirty & !bit) | (s.dirty & !r.dirty & bit);
848 }
849 }
850 }
851 if run && r.chain_busy && !r.chain_sent && !r.h_dig.valid {
852 let sk: b4 = r.chain_subject.resize();
853 let jk: b3 = r.chain_j.resize();
854 s.h_dig = VcDigestReq { valid: true, epoch: r.epoch, subject: r.chain_subject, j: r.chain_j, block: history_block::<P>(r.session, Link { view: r.view, subject: r.chain_subject, j: r.chain_j }, r.chain_acc, r.rec[sk][jk]) };
855 s.chain_sent = true;
856 }
857 let mut p_ready = r.p_busy && !r.p_have && !r.p_sent && !r.chain_busy && !s.chain_busy && !r.h_dig.valid;
860 for k in 0..G {
861 if r.p_rec[k].valid && !r.p_rec[k].certified {
862 p_ready = false;
863 }
864 }
865 if run && p_ready {
866 let jk: b3 = r.p_j.resize();
867 s.h_dig = VcDigestReq { valid: true, epoch: r.epoch, subject: r.p_subject, j: r.p_j, block: history_block::<P>(r.session, Link { view: r.p_view, subject: r.p_subject, j: r.p_j }, r.p_acc, r.p_rec[jk]) };
868 s.p_sent = true;
869 }
870
871 let mut k_done = r.h_open.valid;
873 let mut g_done = r.h_sign.valid || (r.p_sign_out && !r.p_signed);
874 let mut w_done = r.h_own.valid || r.h_open.valid;
875 let mut x_done = r.h_share.valid;
876 for x in 0..N {
877 let bit = b16(1) << b16(x as u128);
878 let xs = b5(x as u128);
879 if run && (r.hdone & bit) != b16(0) {
880 if !k_done && (r.opened & bit) == b16(0) {
881 k_done = true;
882 s.h_open = VcKey { valid: true, view: r.view, subject: xs, digest: r.hdigest[x], sig: [b64(0); 8] };
883 s.opened = s.opened | bit;
884 }
885 if !g_done && (r.sign_sent & bit) == b16(0) {
886 g_done = true;
887 s.h_sign = VcSignReq { valid: true, epoch: r.epoch, subject: xs, context: share_context(b8(ROLE_HISTORY), r.view, xs.resize(), r.hdigest[x]) };
888 s.sign_sent = s.sign_sent | bit;
889 }
890 if !w_done && (r.signed & bit) != b16(0) && (r.open_done & bit) != b16(0) && (r.own_given & bit) == b16(0) {
891 w_done = true;
892 s.h_own = VcKey { valid: true, view: r.view, subject: xs, digest: r.hdigest[x], sig: r.hsig[x] };
893 s.own_given = s.own_given | bit;
894 }
895 if !x_done && (r.signed & bit) != b16(0) && (r.shared & bit) == b16(0) {
896 x_done = true;
897 s.h_share = VcKey { valid: true, view: r.view, subject: xs, digest: r.hdigest[x], sig: r.hsig[x] };
898 s.shared = s.shared | bit;
899 }
900 }
901 }
902 let cur_out = (r.sign_sent & !r.signed) != b16(0);
905 if run && r.p_busy && r.p_have && !r.p_sign_out && !g_done && !cur_out {
906 g_done = true;
907 s.h_sign = VcSignReq { valid: true, epoch: r.epoch, subject: r.p_subject, context: share_context(b8(ROLE_HISTORY), r.p_view, r.p_subject.resize(), r.p_acc) };
908 s.p_sign_out = true;
909 }
910 let p_bit = b16(1) << r.p_subject.resize::<16>();
914 let p_slot_free = (r.opened & p_bit) == b16(0);
915 if run && r.p_busy && r.p_have && p_slot_free && !r.p_keyed && !r.p_key_out && !k_done {
916 k_done = true;
917 s.h_open = VcKey { valid: true, view: r.p_view, subject: r.p_subject, digest: r.p_acc, sig: [b64(0); 8] };
918 s.p_key_out = true;
919 }
920 if run && r.p_busy && r.p_signed && r.p_keyed && !r.p_own_given && !w_done {
921 w_done = true;
922 s.h_own = VcKey { valid: true, view: r.p_view, subject: r.p_subject, digest: r.p_acc, sig: r.p_sig };
923 s.p_own_given = true;
924 }
925 if run && r.p_busy && r.p_signed && !r.p_shared && !x_done {
926 x_done = true;
927 s.h_share = VcKey { valid: true, view: r.p_view, subject: r.p_subject, digest: r.p_acc, sig: r.p_sig };
928 s.p_shared = true;
929 }
930 if run && r.p_busy && r.p_shared && (r.p_own_given || !p_slot_free) && !r.p_key_out {
932 s.p_busy = false;
933 }
934 if run && i.signed.valid && i.signed.epoch == r.epoch {
935 if r.p_sign_out && !r.p_signed && i.signed.subject == r.p_subject {
936 s.p_signed = true;
937 s.p_sig = i.signed.sig;
938 } else {
939 let sk: b4 = i.signed.subject.resize();
940 s.signed = s.signed | (b16(1) << i.signed.subject.resize::<16>());
941 s.hsig[sk] = i.signed.sig;
942 }
943 }
944
945 if run && r.me == next_leader && r.seal_sent && !r.nv_sent && !r.h_ctb.valid {
947 let mut mask = b16(0);
948 let mut count = b5(0);
949 for x in 0..N {
950 let bit = b16(1) << b16(x as u128);
951 if count < r.q && i.hist_certified[x] && (r.open_done & bit) != b16(0) {
952 mask = mask | bit;
953 count = count + b5(1);
954 }
955 }
956 if count == r.q {
957 let mut v = [b32(0); P];
958 v[0] = mask.resize();
959 s.h_ctb = ConsMsg::<P> { valid: true, from: r.me, kind: b4(kind::NEWVIEW), view: next, instance: b32(0), digest: [b64(0); 4], len: b5(1), value: v };
960 s.nv_sent = true;
961 }
962 }
963
964 if run && i.view == next {
967 s.view = next;
968 let mut carried = b16(0);
970 for x in 0..N {
971 if s.seal_hi[x] > next {
972 carried = carried | (b16(1) << b16(x as u128));
973 }
974 }
975 s.sealed_from = carried;
976 let mut late = b16(0);
979 for x in 0..N {
980 if b5(x as u128) < r.n && b5(x as u128) != r.me && s.seal_hi[x] <= r.view {
981 late = late | (b16(1) << b16(x as u128));
982 }
983 }
984 s.p_view = r.view;
985 s.p_open = late;
986 s.in_skipped = r.skip_pending || s.skip_pending;
987 s.skip_pending = false;
988 s.late_done = false;
989 s.prev_open_done = r.open_done;
990 s.p_busy = false;
991 s.p_sent = false;
992 s.p_have = false;
993 s.p_sign_out = false;
994 s.p_signed = false;
995 if r.p_key_out || s.p_key_out {
998 s.h_open.valid = false;
999 }
1000 s.p_key_out = false;
1001 s.p_keyed = false;
1002 s.p_own_given = false;
1003 s.p_shared = false;
1004 s.sealing = false;
1005 s.seal_sent = false;
1006 s.chain_busy = false;
1007 s.hdone = b16(0);
1008 s.opened = b16(0);
1009 s.open_done = b16(0);
1010 s.sign_sent = b16(0);
1011 s.signed = b16(0);
1012 s.own_given = b16(0);
1013 s.shared = b16(0);
1014 s.nv_sent = false;
1015 s.installed_next = false;
1016 s.epoch = r.epoch + b32(1);
1017 }
1018 (o, s)
1019}
1020
1021#[kernel]
1023pub fn r_all(n: b5) -> b16 {
1024 let mut all = b16(0);
1025 for k in 0..16 {
1026 if b5(k as u128) < n {
1027 all = all | (b16(1) << b16(k as u128));
1028 }
1029 }
1030 all
1031}