1use std::f32::consts::E;
2
3use vstd::modes::tracked_swap;
4use vstd::pcm::Loc;
6use vstd::prelude::*;
7use vstd::storage_protocol::*;
8
9use crate::resource::storage_protocol::csum::*;
10use crate::sum::*;
11
12verus! {
13
14pub tracked struct SumResource<A, B, const TOTAL: u64 = 2> {
18 tracked r: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
19}
20
21pub tracked struct Left<A, B, const TOTAL: u64 = 2> {
23 tracked r: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
24}
25
26pub tracked struct Right<A, B, const TOTAL: u64 = 2> {
28 tracked r: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
29}
30
31pub tracked struct OneLeftOwner<A, B, const TOTAL: u64 = 2> {
33 tracked r: Left<A, B, TOTAL>,
34}
35
36pub tracked struct OneRightOwner<A, B, const TOTAL: u64 = 2> {
38 tracked r: Right<A, B, TOTAL>,
39}
40
41pub tracked struct OneLeftKnowledge<A, B, const TOTAL: u64 = 2> {
44 tracked r: Left<A, B, TOTAL>,
45}
46
47pub tracked struct OneRightKnowledge<A, B, const TOTAL: u64 = 2> {
50 tracked r: Right<A, B, TOTAL>,
51}
52
53impl<A, B, const TOTAL: u64> SumResource<A, B, TOTAL> {
54 pub closed spec fn id(self) -> Loc {
56 self.r.loc()
57 }
58
59 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
61 self.r.value()
62 }
63
64 pub open spec fn is_resource_owner(self) -> bool {
66 self.protocol_monoid().is_resource_owner()
67 }
68
69 pub open spec fn resource(self) -> Sum<A, B> {
71 self.protocol_monoid().resource()
72 }
73
74 pub open spec fn resource_left(self) -> A {
76 self.resource()->Left_0
77 }
78
79 pub open spec fn resource_right(self) -> B {
81 self.resource()->Right_0
82 }
83
84 pub open spec fn is_left(self) -> bool {
86 self.protocol_monoid().is_left()
87 }
88
89 pub open spec fn is_right(self) -> bool {
91 self.protocol_monoid().is_right()
92 }
93
94 pub open spec fn has_resource(self) -> bool {
96 let p = self.protocol_monoid();
97 p.is_resource_owner() && p.has_resource()
98 }
99
100 pub open spec fn has_no_resource(self) -> bool {
102 let p = self.protocol_monoid();
103 p.is_resource_owner() && p.has_no_resource()
104 }
105
106 pub open spec fn frac(self) -> int {
108 self.protocol_monoid().frac()
109 }
110
111 #[verifier::type_invariant]
112 closed spec fn type_inv(self) -> bool {
113 self.wf()
114 }
115
116 pub open spec fn wf(self) -> bool {
118 &&& 1 <= self.frac() <= TOTAL
119 &&& self.protocol_monoid().is_valid()
120 &&& self.is_resource_owner() ==> (self.has_resource() <==> !self.has_no_resource())
121 &&& (self.is_left() <==> !self.is_right())
122 }
123
124 closed spec fn type_inv_inner(r: CsumP<A, B, TOTAL>) -> bool {
125 &&& 1 <= r.frac() <= TOTAL
126 &&& r.is_valid()
127 &&& r.is_resource_owner() ==> (r.has_resource() <==> !r.has_no_resource())
128 &&& (r.is_left() <==> !r.is_right())
129 }
130
131 proof fn alloc_unit_storage() -> (tracked res: StorageResource<
132 (),
133 Sum<A, B>,
134 CsumP<A, B, TOTAL>,
135 >) {
136 StorageResource::alloc(CsumP::Unit, Map::tracked_empty())
137 }
138
139 pub proof fn alloc_left(tracked a: A) -> (tracked res: Self)
141 requires
142 TOTAL > 0,
143 ensures
144 res.is_left(),
145 res.is_resource_owner(),
146 res.has_resource(),
147 res.resource() == Sum::<A, B>::Left(a),
148 res.frac() == TOTAL,
149 res.wf(),
150 {
151 let tracked mut m = Map::tracked_empty();
152 m.tracked_insert((), Sum::<A, B>::Left(a));
153 let tracked r = StorageResource::alloc(CsumP::Cinl(Some(a), TOTAL as int, true), m);
154 Self { r }
155 }
156
157 pub proof fn alloc_right(tracked b: B) -> (tracked res: Self)
159 requires
160 TOTAL > 0,
161 ensures
162 res.is_right(),
163 res.is_resource_owner(),
164 res.has_resource(),
165 res.resource() == Sum::<A, B>::Right(b),
166 res.frac() == TOTAL,
167 res.wf(),
168 {
169 let tracked mut m = Map::tracked_empty();
170 m.tracked_insert((), Sum::<A, B>::Right(b));
171 let tracked r = StorageResource::alloc(CsumP::Cinr(Some(b), TOTAL as int, true), m);
172 Self { r }
173 }
174
175 pub proof fn validate(tracked &self)
177 ensures
178 self.wf(),
179 {
180 use_type_invariant(&*self);
181 }
182
183 pub proof fn validate_with_other(tracked &mut self, tracked other: &Self)
185 requires
186 old(self).is_left() && old(self).is_right() || other.is_left() && other.is_right()
187 || old(self).is_left() && other.is_left() && old(self).is_resource_owner()
188 && other.is_resource_owner() || old(self).is_right() && other.is_right() && old(
189 self,
190 ).is_resource_owner() && other.is_resource_owner(),
191 ensures
192 *old(self) == *final(self),
193 final(self).id() != other.id(),
194 final(self).wf(),
195 {
196 use_type_invariant(&*self);
197 use_type_invariant(other);
198 if self.id() == other.id() {
199 self.r.validate_with_shared(&other.r);
200 }
201 }
202
203 pub proof fn validate_with_left(tracked &mut self, tracked other: &Left<A, B, TOTAL>)
205 requires
206 old(self).id() == other.id(),
207 ensures
208 *old(self) == *final(self),
209 final(self).is_left(),
210 !(final(self).is_resource_owner() && other.is_resource_owner()),
211 final(self).frac() + other.frac() <= TOTAL,
212 final(self).wf(),
213 {
214 use_type_invariant(&*self);
215 use_type_invariant(other);
216 self.r.validate_with_shared(&other.r);
217 }
218
219 pub proof fn validate_with_right(tracked &mut self, tracked other: &Right<A, B, TOTAL>)
221 requires
222 old(self).id() == other.id(),
223 ensures
224 *old(self) == *final(self),
225 final(self).is_right(),
226 !(final(self).is_resource_owner() && other.is_resource_owner()),
227 final(self).frac() + other.frac() <= TOTAL,
228 final(self).wf(),
229 {
230 use_type_invariant(&*self);
231 use_type_invariant(other);
232 self.r.validate_with_shared(&other.r);
233 }
234
235 pub proof fn validate_with_one_left_owner(
237 tracked &mut self,
238 tracked other: &OneLeftOwner<A, B, TOTAL>,
239 )
240 requires
241 old(self).id() == other.id(),
242 ensures
243 *old(self) == *final(self),
244 final(self).is_left(),
245 !final(self).is_resource_owner(),
246 final(self).frac() + 1 <= TOTAL,
247 final(self).wf(),
248 {
249 use_type_invariant(&*self);
250 use_type_invariant(other);
251 self.r.validate_with_shared(&other.r.r);
252 }
253
254 pub proof fn validate_with_one_right_owner(
256 tracked &mut self,
257 tracked other: &OneRightOwner<A, B, TOTAL>,
258 )
259 requires
260 old(self).id() == other.id(),
261 ensures
262 *old(self) == *final(self),
263 final(self).is_right(),
264 !final(self).is_resource_owner(),
265 final(self).frac() + 1 <= TOTAL,
266 final(self).wf(),
267 {
268 use_type_invariant(&*self);
269 use_type_invariant(other);
270 self.r.validate_with_shared(&other.r.r);
271 }
272
273 pub proof fn validate_with_one_left_knowledge(
275 tracked &mut self,
276 tracked other: &OneLeftKnowledge<A, B, TOTAL>,
277 )
278 requires
279 old(self).id() == other.id(),
280 ensures
281 *old(self) == *final(self),
282 final(self).is_left(),
283 final(self).frac() + 1 <= TOTAL,
284 final(self).wf(),
285 {
286 use_type_invariant(&*self);
287 use_type_invariant(other);
288 self.r.validate_with_shared(&other.r.r);
289 }
290
291 pub proof fn validate_with_one_right_knowledge(
293 tracked &mut self,
294 tracked other: &OneRightKnowledge<A, B, TOTAL>,
295 )
296 requires
297 old(self).id() == other.id(),
298 ensures
299 *old(self) == *final(self),
300 final(self).is_right(),
301 final(self).frac() + 1 <= TOTAL,
302 final(self).wf(),
303 {
304 use_type_invariant(&*self);
305 use_type_invariant(other);
306 self.r.validate_with_shared(&other.r.r);
307 }
308
309 pub proof fn tracked_borrow_left(tracked &self) -> (tracked res: &A)
311 requires
312 self.is_left(),
313 self.is_resource_owner(),
314 self.has_resource(),
315 ensures
316 *res == self.resource_left(),
317 {
318 StorageResource::guard(&self.r, map![() => self.resource()]).tracked_borrow(
319 (),
320 ).tracked_borrow_left()
321 }
322
323 pub proof fn tracked_borrow_right(tracked &self) -> (tracked res: &B)
325 requires
326 self.is_right(),
327 self.is_resource_owner(),
328 self.has_resource(),
329 ensures
330 *res == self.resource()->Right_0,
331 {
332 StorageResource::guard(&self.r, map![() => self.resource()]).tracked_borrow(
333 (),
334 ).tracked_borrow_right()
335 }
336
337 pub proof fn split_left_with_resource(tracked &mut self, n: int) -> (tracked res: Left<
339 A,
340 B,
341 TOTAL,
342 >)
343 requires
344 old(self).is_left(),
345 0 < n < old(self).frac(),
346 ensures
347 final(self).id() == old(self).id(),
348 final(self).frac() == old(self).frac() - n,
349 res.id() == old(self).id(),
350 res.frac() == n,
351 !final(self).is_resource_owner(),
352 res.is_resource_owner() <==> old(self).is_resource_owner(),
353 res.is_resource_owner() ==> (res.has_resource() <==> old(self).has_resource()),
354 res.has_resource() ==> res.resource() == old(self).resource_left(),
355 final(self).wf(),
356 res.wf(),
357 {
358 use_type_invariant(&*self);
359 let tracked r = Self::split_left_with_resource_helper(&mut self.r, n);
360 Left { r }
361 }
362
363 proof fn split_left_with_resource_helper(
364 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
365 n: int,
366 ) -> (tracked res: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>)
367 requires
368 old(r).value().is_left(),
369 0 < n < old(r).value().frac(),
370 Self::type_inv_inner(old(r).value()),
371 ensures
372 Self::type_inv_inner(final(r).value()),
373 Self::type_inv_inner(res.value()),
374 final(r).loc() == old(r).loc(),
375 final(r).loc() == res.loc(),
376 final(r).value().is_left(),
377 final(r).value().frac() == old(r).value().frac() - n,
378 res.value().is_left(),
379 res.value().frac() == n,
380 !final(r).value().is_resource_owner(),
381 res.value().is_resource_owner() <==> old(r).value().is_resource_owner(),
382 res.value().is_resource_owner() ==> (res.value().has_resource() <==> old(
383 r,
384 ).value().has_resource()),
385 res.value().has_resource() ==> res.value().resource()->Left_0 == old(
386 r,
387 ).value().resource()->Left_0,
388 {
389 let tracked mut tmp = Self::alloc_unit_storage();
390 tracked_swap(r, &mut tmp);
391 let tracked (mut r1, r2) = tmp.split(
392 CsumP::Cinl(None, tmp.value().frac() - n, false),
393 CsumP::Cinl(tmp.value()->Cinl_0, n, tmp.value().is_resource_owner()),
394 );
395 tracked_swap(r, &mut r1);
396 r2
397 }
398
399 pub proof fn split_left_without_resource(tracked &mut self, n: int) -> (tracked res: Left<
401 A,
402 B,
403 TOTAL,
404 >)
405 requires
406 old(self).is_left(),
407 0 < n < old(self).frac(),
408 ensures
409 final(self).id() == old(self).id(),
410 final(self).frac() == old(self).frac() - n,
411 res.id() == old(self).id(),
412 res.frac() == n,
413 !res.is_resource_owner(),
414 final(self).is_resource_owner() <==> old(self).is_resource_owner(),
415 final(self).is_resource_owner() ==> (final(self).has_resource() <==> old(
416 self,
417 ).has_resource()),
418 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
419 final(self).wf(),
420 res.wf(),
421 {
422 use_type_invariant(&*self);
423 let tracked r = Self::split_left_without_resource_helper(&mut self.r, n);
424 Left { r }
425 }
426
427 proof fn split_left_without_resource_helper(
428 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
429 n: int,
430 ) -> (tracked res: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>)
431 requires
432 old(r).value().is_left(),
433 0 < n < old(r).value().frac(),
434 Self::type_inv_inner(old(r).value()),
435 ensures
436 Self::type_inv_inner(final(r).value()),
437 Self::type_inv_inner(res.value()),
438 final(r).loc() == old(r).loc(),
439 final(r).loc() == res.loc(),
440 final(r).value().is_left(),
441 final(r).value().frac() == old(r).value().frac() - n,
442 res.value().is_left(),
443 res.value().frac() == n,
444 !res.value().is_resource_owner(),
445 final(r).value().is_resource_owner() <==> old(r).value().is_resource_owner(),
446 final(r).value().is_resource_owner() ==> (final(r).value().has_resource() <==> old(
447 r,
448 ).value().has_resource()),
449 final(r).value().has_resource() ==> final(r).value().resource()->Left_0 == old(
450 r,
451 ).value().resource()->Left_0,
452 {
453 let tracked mut tmp = Self::alloc_unit_storage();
454 tracked_swap(r, &mut tmp);
455 let tracked (mut r1, r2) = tmp.split(
456 CsumP::Cinl(
457 tmp.value()->Cinl_0,
458 tmp.value().frac() - n,
459 tmp.value().is_resource_owner(),
460 ),
461 CsumP::Cinl(None, n, false),
462 );
463 tracked_swap(r, &mut r1);
464 r2
465 }
466
467 pub proof fn split_right_with_resource(tracked &mut self, n: int) -> (tracked res: Right<
469 A,
470 B,
471 TOTAL,
472 >)
473 requires
474 old(self).is_right(),
475 0 < n < old(self).frac(),
476 ensures
477 final(self).id() == old(self).id(),
478 final(self).frac() == old(self).frac() - n,
479 res.id() == old(self).id(),
480 res.frac() == n,
481 !final(self).is_resource_owner(),
482 res.is_resource_owner() <==> old(self).is_resource_owner(),
483 res.is_resource_owner() ==> (res.has_resource() <==> old(self).has_resource()),
484 res.has_resource() ==> res.resource() == old(self).resource_right(),
485 final(self).wf(),
486 res.wf(),
487 {
488 use_type_invariant(&*self);
489 let tracked r = Self::split_right_with_resource_helper(&mut self.r, n);
490 Right { r }
491 }
492
493 proof fn split_right_with_resource_helper(
494 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
495 n: int,
496 ) -> (tracked res: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>)
497 requires
498 old(r).value().is_right(),
499 0 < n < old(r).value().frac(),
500 Self::type_inv_inner(old(r).value()),
501 ensures
502 Self::type_inv_inner(final(r).value()),
503 Self::type_inv_inner(res.value()),
504 final(r).loc() == old(r).loc(),
505 final(r).loc() == res.loc(),
506 final(r).value().is_right(),
507 final(r).value().frac() == old(r).value().frac() - n,
508 res.value().is_right(),
509 res.value().frac() == n,
510 !final(r).value().is_resource_owner(),
511 res.value().is_resource_owner() <==> old(r).value().is_resource_owner(),
512 res.value().is_resource_owner() ==> (res.value().has_resource() <==> old(
513 r,
514 ).value().has_resource()),
515 res.value().has_resource() ==> res.value().resource()->Right_0 == old(
516 r,
517 ).value().resource()->Right_0,
518 {
519 let tracked mut tmp = Self::alloc_unit_storage();
520 tracked_swap(r, &mut tmp);
521 let tracked (mut r1, r2) = tmp.split(
522 CsumP::Cinr(None, tmp.value().frac() - n, false),
523 CsumP::Cinr(tmp.value()->Cinr_0, n, tmp.value().is_resource_owner()),
524 );
525 tracked_swap(r, &mut r1);
526 r2
527 }
528
529 pub proof fn split_right_without_resource(tracked &mut self, n: int) -> (tracked res: Right<
531 A,
532 B,
533 TOTAL,
534 >)
535 requires
536 old(self).is_right(),
537 0 < n < old(self).frac(),
538 ensures
539 final(self).id() == old(self).id(),
540 final(self).frac() == old(self).frac() - n,
541 res.id() == old(self).id(),
542 res.frac() == n,
543 !res.is_resource_owner(),
544 final(self).is_resource_owner() <==> old(self).is_resource_owner(),
545 final(self).is_resource_owner() ==> (final(self).has_resource() <==> old(
546 self,
547 ).has_resource()),
548 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
549 final(self).wf(),
550 res.wf(),
551 {
552 use_type_invariant(&*self);
553 let tracked r = Self::split_right_without_resource_helper(&mut self.r, n);
554 Right { r }
555 }
556
557 proof fn split_right_without_resource_helper(
558 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
559 n: int,
560 ) -> (tracked res: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>)
561 requires
562 old(r).value().is_right(),
563 0 < n < old(r).value().frac(),
564 Self::type_inv_inner(old(r).value()),
565 ensures
566 Self::type_inv_inner(final(r).value()),
567 Self::type_inv_inner(res.value()),
568 final(r).loc() == old(r).loc(),
569 final(r).loc() == res.loc(),
570 final(r).value().is_right(),
571 final(r).value().frac() == old(r).value().frac() - n,
572 res.value().is_right(),
573 res.value().frac() == n,
574 !res.value().is_resource_owner(),
575 final(r).value().is_resource_owner() <==> old(r).value().is_resource_owner(),
576 final(r).value().is_resource_owner() ==> (final(r).value().has_resource() <==> old(
577 r,
578 ).value().has_resource()),
579 final(r).value().has_resource() ==> final(r).value().resource()->Right_0 == old(
580 r,
581 ).value().resource()->Right_0,
582 {
583 let tracked mut tmp = Self::alloc_unit_storage();
584 tracked_swap(r, &mut tmp);
585 let tracked (mut r1, r2) = tmp.split(
586 CsumP::Cinr(
587 tmp.value()->Cinr_0,
588 tmp.value().frac() - n,
589 tmp.value().is_resource_owner(),
590 ),
591 CsumP::Cinr(None, n, false),
592 );
593 tracked_swap(r, &mut r1);
594 r2
595 }
596
597 pub proof fn split_one_left_owner(tracked &mut self) -> (tracked res: OneLeftOwner<A, B, TOTAL>)
599 requires
600 old(self).is_left(),
601 old(self).is_resource_owner(),
602 old(self).frac() > 1,
603 ensures
604 final(self).wf(),
605 final(self).id() == old(self).id(),
606 final(self).is_left(),
607 final(self).frac() + 1 == old(self).frac(),
608 !final(self).is_resource_owner(),
609 res.id() == old(self).id(),
610 res.wf(),
611 res.has_resource() == old(self).has_resource(),
612 res.has_resource() ==> res.resource() == old(self).resource_left(),
613 {
614 use_type_invariant(&*self);
615 let tracked r = Self::split_left_with_resource_helper(&mut self.r, 1);
616 OneLeftOwner { r: Left { r } }
617 }
618
619 pub proof fn split_one_right_owner(tracked &mut self) -> (tracked res: OneRightOwner<
621 A,
622 B,
623 TOTAL,
624 >)
625 requires
626 old(self).is_right(),
627 old(self).is_resource_owner(),
628 old(self).frac() > 1,
629 ensures
630 final(self).wf(),
631 final(self).id() == old(self).id(),
632 final(self).is_right(),
633 final(self).frac() + 1 == old(self).frac(),
634 !final(self).is_resource_owner(),
635 res.id() == old(self).id(),
636 res.wf(),
637 res.has_resource() == old(self).has_resource(),
638 res.has_resource() ==> res.resource() == old(self).resource_right(),
639 {
640 use_type_invariant(&*self);
641 let tracked r = Self::split_right_with_resource_helper(&mut self.r, 1);
642 OneRightOwner { r: Right { r } }
643 }
644
645 pub proof fn split_one_left_knowledge(tracked &mut self) -> (tracked res: OneLeftKnowledge<
647 A,
648 B,
649 TOTAL,
650 >)
651 requires
652 old(self).is_left(),
653 old(self).frac() > 1,
654 ensures
655 final(self).wf(),
656 final(self).id() == old(self).id(),
657 final(self).is_left(),
658 final(self).frac() + 1 == old(self).frac(),
659 final(self).is_resource_owner() == old(self).is_resource_owner(),
660 final(self).has_resource() == old(self).has_resource(),
661 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
662 res.id() == old(self).id(),
663 res.wf(),
664 {
665 use_type_invariant(&*self);
666 let tracked r = Self::split_left_without_resource_helper(&mut self.r, 1);
667 OneLeftKnowledge { r: Left { r } }
668 }
669
670 pub proof fn split_one_right_knowledge(tracked &mut self) -> (tracked res: OneRightKnowledge<
672 A,
673 B,
674 TOTAL,
675 >)
676 requires
677 old(self).is_right(),
678 old(self).frac() > 1,
679 ensures
680 final(self).wf(),
681 final(self).id() == old(self).id(),
682 final(self).is_right(),
683 final(self).frac() + 1 == old(self).frac(),
684 final(self).is_resource_owner() == old(self).is_resource_owner(),
685 final(self).has_resource() == old(self).has_resource(),
686 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
687 res.id() == old(self).id(),
688 res.wf(),
689 {
690 use_type_invariant(&*self);
691 let tracked r = Self::split_right_without_resource_helper(&mut self.r, 1);
692 OneRightKnowledge { r: Right { r } }
693 }
694
695 pub proof fn take_resource_left(tracked &mut self) -> (tracked res: A)
697 requires
698 old(self).is_left(),
699 old(self).is_resource_owner(),
700 old(self).has_resource(),
701 ensures
702 final(self).is_left(),
703 res == old(self).resource_left(),
704 final(self).id() == old(self).id(),
705 final(self).is_resource_owner(),
706 final(self).has_no_resource(),
707 final(self).frac() == old(self).frac(),
708 final(self).wf(),
709 {
710 use_type_invariant(&*self);
711 Self::take_resource_left_helper(&mut self.r)
712 }
713
714 proof fn take_resource_left_helper(
715 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
716 ) -> (tracked res: A)
717 requires
718 old(r).value().is_left(),
719 old(r).value().is_resource_owner(),
720 old(r).value().has_resource(),
721 Self::type_inv_inner(old(r).value()),
722 ensures
723 Self::type_inv_inner(final(r).value()),
724 res == old(r).value().resource()->Left_0,
725 final(r).loc() == old(r).loc(),
726 final(r).value().is_left(),
727 final(r).value().is_resource_owner(),
728 final(r).value().has_no_resource(),
729 final(r).value().frac() == old(r).value().frac(),
730 {
731 let tracked mut tmp = Self::alloc_unit_storage();
732 tracked_swap(r, &mut tmp);
733 tmp.value().lemma_withdraws_left();
734 let tracked (mut r1, mut s) = tmp.withdraw(
735 CsumP::Cinl(None, tmp.value().frac(), true),
736 map![() => tmp.value().resource()],
737 );
738 tracked_swap(r, &mut r1);
739 s.tracked_remove(()).tracked_take_left()
740 }
741
742 pub proof fn take_resource_right(tracked &mut self) -> (tracked res: B)
744 requires
745 old(self).is_right(),
746 old(self).is_resource_owner(),
747 old(self).has_resource(),
748 ensures
749 final(self).is_right(),
750 res == old(self).resource_right(),
751 final(self).id() == old(self).id(),
752 final(self).is_resource_owner(),
753 final(self).has_no_resource(),
754 final(self).frac() == old(self).frac(),
755 final(self).wf(),
756 {
757 use_type_invariant(&*self);
758 Self::take_resource_right_helper(&mut self.r)
759 }
760
761 proof fn take_resource_right_helper(
762 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
763 ) -> (tracked res: B)
764 requires
765 old(r).value().is_right(),
766 old(r).value().is_resource_owner(),
767 old(r).value().has_resource(),
768 Self::type_inv_inner(old(r).value()),
769 ensures
770 Self::type_inv_inner(final(r).value()),
771 res == old(r).value().resource()->Right_0,
772 final(r).loc() == old(r).loc(),
773 final(r).value().is_right(),
774 final(r).value().is_resource_owner(),
775 final(r).value().has_no_resource(),
776 final(r).value().frac() == old(r).value().frac(),
777 {
778 let tracked mut tmp = Self::alloc_unit_storage();
779 tracked_swap(r, &mut tmp);
780 tmp.value().lemma_withdraws_right();
781 let tracked (mut r1, mut s) = tmp.withdraw(
782 CsumP::Cinr(None, tmp.value().frac(), true),
783 map![() => tmp.value().resource()],
784 );
785 tracked_swap(r, &mut r1);
786 s.tracked_remove(()).tracked_take_right()
787 }
788
789 pub proof fn put_resource_left(tracked &mut self, tracked a: A)
791 requires
792 old(self).is_left(),
793 old(self).is_resource_owner(),
794 old(self).has_no_resource(),
795 ensures
796 final(self).is_left(),
797 final(self).has_resource(),
798 final(self).is_resource_owner(),
799 final(self).resource_left() == a,
800 final(self).id() == old(self).id(),
801 final(self).frac() == old(self).frac(),
802 final(self).wf(),
803 {
804 use_type_invariant(&*self);
805 Self::put_resource_left_helper(&mut self.r, a);
806 }
807
808 proof fn put_resource_left_helper(
809 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
810 tracked a: A,
811 )
812 requires
813 old(r).value().is_left(),
814 old(r).value().is_resource_owner(),
815 old(r).value().has_no_resource(),
816 Self::type_inv_inner(old(r).value()),
817 ensures
818 Self::type_inv_inner(final(r).value()),
819 final(r).loc() == old(r).loc(),
820 final(r).value().is_left(),
821 final(r).value().is_resource_owner(),
822 final(r).value().has_resource(),
823 final(r).value().resource()->Left_0 == a,
824 final(r).value().frac() == old(r).value().frac(),
825 {
826 let ghost a_ghost = a;
827 let tracked mut m = Map::tracked_empty();
828 m.tracked_insert((), Sum::<A, B>::Left(a));
829 let tracked mut tmp = Self::alloc_unit_storage();
830 tracked_swap(r, &mut tmp);
831 tmp.value().lemma_deposit_left(a);
832 let tracked mut r1 = tmp.deposit(m, CsumP::Cinl(Some(a), tmp.value().frac(), true));
833 tracked_swap(r, &mut r1);
834 }
835
836 pub proof fn put_resource_right(tracked &mut self, tracked b: B)
838 requires
839 old(self).is_right(),
840 old(self).is_resource_owner(),
841 old(self).has_no_resource(),
842 ensures
843 final(self).is_right(),
844 final(self).is_resource_owner(),
845 final(self).has_resource(),
846 final(self).resource_right() == b,
847 final(self).id() == old(self).id(),
848 final(self).frac() == old(self).frac(),
849 final(self).wf(),
850 {
851 use_type_invariant(&*self);
852 Self::put_resource_right_helper(&mut self.r, b);
853 }
854
855 proof fn put_resource_right_helper(
856 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
857 tracked b: B,
858 )
859 requires
860 old(r).value().is_right(),
861 old(r).value().is_resource_owner(),
862 old(r).value().has_no_resource(),
863 Self::type_inv_inner(old(r).value()),
864 ensures
865 Self::type_inv_inner(final(r).value()),
866 final(r).loc() == old(r).loc(),
867 final(r).value().is_right(),
868 final(r).value().is_resource_owner(),
869 final(r).value().has_resource(),
870 final(r).value().resource()->Right_0 == b,
871 final(r).value().frac() == old(r).value().frac(),
872 {
873 let ghost b_ghost = b;
874 let tracked mut m = Map::tracked_empty();
875 m.tracked_insert((), Sum::<A, B>::Right(b));
876 let tracked mut tmp = Self::alloc_unit_storage();
877 tracked_swap(r, &mut tmp);
878 tmp.value().lemma_deposit_right(b);
879 let tracked mut r1 = tmp.deposit(m, CsumP::Cinr(Some(b), tmp.value().frac(), true));
880 tracked_swap(r, &mut r1);
881 }
882
883 pub proof fn update_left(tracked &mut self, tracked a: A) -> (tracked res: Option<A>)
886 requires
887 old(self).is_left(),
888 old(self).is_resource_owner(),
889 old(self).has_resource(),
890 ensures
891 final(self).is_left(),
892 final(self).is_resource_owner(),
893 final(self).has_resource(),
894 final(self).resource_left() == a,
895 final(self).id() == old(self).id(),
896 final(self).frac() == old(self).frac(),
897 res == Some(old(self).resource_left()),
898 final(self).wf(),
899 {
900 use_type_invariant(&*self);
901 let tracked mut res = None;
902 if self.has_resource() {
903 let tracked r = Self::take_resource_left_helper(&mut self.r);
904 res = Some(r);
905 }
906 Self::put_resource_left_helper(&mut self.r, a);
907 res
908 }
909
910 pub proof fn update_right(tracked &mut self, tracked b: B) -> (tracked res: Option<B>)
913 requires
914 old(self).is_right(),
915 old(self).is_resource_owner(),
916 old(self).has_resource(),
917 ensures
918 final(self).is_right(),
919 final(self).is_resource_owner(),
920 final(self).has_resource(),
921 final(self).resource_right() == b,
922 final(self).id() == old(self).id(),
923 final(self).frac() == old(self).frac(),
924 res == Some(old(self).resource_right()),
925 final(self).wf(),
926 {
927 use_type_invariant(&*self);
928 let tracked mut res = None;
929 if self.has_resource() {
930 let tracked r = Self::take_resource_right_helper(&mut self.r);
931 res = Some(r);
932 }
933 Self::put_resource_right_helper(&mut self.r, b);
934 res
935 }
936
937 pub proof fn change_to_left(tracked &mut self, tracked a: A) -> (tracked res: Option<Sum<A, B>>)
942 requires
943 old(self).is_resource_owner(),
944 old(self).frac() == TOTAL,
945 ensures
946 final(self).id() == old(self).id(),
947 final(self).protocol_monoid() == CsumP::<A, B, TOTAL>::Cinl(
948 Some(a),
949 old(self).frac(),
950 true,
951 ),
952 final(self).frac() == old(self).frac(),
953 final(self).is_left(),
954 final(self).is_resource_owner(),
955 final(self).has_resource(),
956 final(self).resource_left() == a,
957 old(self).has_resource() ==> res == Some(old(self).resource()),
958 old(self).has_no_resource() ==> res == None::<Sum<A, B>>,
959 final(self).wf(),
960 {
961 use_type_invariant(&*self);
962 let tracked res = Self::change_to_left_helper(&mut self.r, a);
963 res
964 }
965
966 proof fn change_to_left_helper(
967 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
968 tracked a: A,
969 ) -> (tracked res: Option<Sum<A, B>>)
970 requires
971 old(r).value().is_resource_owner(),
972 old(r).value().frac() == TOTAL,
973 Self::type_inv_inner(old(r).value()),
974 ensures
975 Self::type_inv_inner(final(r).value()),
976 final(r).loc() == old(r).loc(),
977 final(r).value() == CsumP::<A, B, TOTAL>::Cinl(Some(a), old(r).value().frac(), true),
978 final(r).value().frac() == old(r).value().frac(),
979 final(r).value().is_left(),
980 final(r).value().is_resource_owner(),
981 final(r).value().has_resource(),
982 final(r).value().resource()->Left_0 == a,
983 old(r).value().has_resource() ==> res == Some(old(r).value().resource()),
984 old(r).value().has_no_resource() ==> res == None::<Sum<A, B>>,
985 {
986 let tracked mut res = None;
987 let tracked mut tmp = Self::alloc_unit_storage();
988 tracked_swap(r, &mut tmp);
989 if tmp.value().has_resource() {
990 if tmp.value().is_left() {
991 let tracked ret = Self::take_resource_left_helper(&mut tmp);
992 res = Some(Sum::Left(ret));
993 } else {
994 let tracked ret = Self::take_resource_right_helper(&mut tmp);
995 res = Some(Sum::Right(ret));
996 }
997 }
998 let tracked mut resource = tmp.update(
999 CsumP::<A, B, TOTAL>::Cinl(None, tmp.value().frac(), true),
1000 );
1001 Self::put_resource_left_helper(&mut resource, a);
1002 tracked_swap(r, &mut resource);
1003 res
1004 }
1005
1006 pub proof fn change_to_right(tracked &mut self, tracked b: B) -> (tracked res: Option<
1011 Sum<A, B>,
1012 >)
1013 requires
1014 old(self).is_resource_owner(),
1015 old(self).frac() == TOTAL,
1016 ensures
1017 final(self).id() == old(self).id(),
1018 final(self).protocol_monoid() == CsumP::<A, B, TOTAL>::Cinr(
1019 Some(b),
1020 old(self).frac(),
1021 true,
1022 ),
1023 final(self).frac() == old(self).frac(),
1024 final(self).is_right(),
1025 final(self).is_resource_owner(),
1026 final(self).has_resource(),
1027 final(self).resource_right() == b,
1028 old(self).has_resource() ==> res == Some(old(self).resource()),
1029 old(self).has_no_resource() ==> res == None::<Sum<A, B>>,
1030 final(self).wf(),
1031 {
1032 use_type_invariant(&*self);
1033 let tracked res = Self::change_to_right_helper(&mut self.r, b);
1034 res
1035 }
1036
1037 proof fn change_to_right_helper(
1038 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
1039 tracked b: B,
1040 ) -> (tracked res: Option<Sum<A, B>>)
1041 requires
1042 old(r).value().is_resource_owner(),
1043 old(r).value().frac() == TOTAL,
1044 Self::type_inv_inner(old(r).value()),
1045 ensures
1046 Self::type_inv_inner(final(r).value()),
1047 final(r).loc() == old(r).loc(),
1048 final(r).value() == CsumP::<A, B, TOTAL>::Cinr(Some(b), old(r).value().frac(), true),
1049 final(r).value().frac() == old(r).value().frac(),
1050 final(r).value().is_right(),
1051 final(r).value().is_resource_owner(),
1052 final(r).value().has_resource(),
1053 final(r).value().resource()->Right_0 == b,
1054 old(r).value().has_resource() ==> res == Some(old(r).value().resource()),
1055 old(r).value().has_no_resource() ==> res == None::<Sum<A, B>>,
1056 {
1057 let tracked mut res = None;
1058 let tracked mut tmp = Self::alloc_unit_storage();
1059 tracked_swap(r, &mut tmp);
1060 if tmp.value().has_resource() {
1061 if tmp.value().is_left() {
1062 let tracked ret = Self::take_resource_left_helper(&mut tmp);
1063 res = Some(Sum::Left(ret));
1064 } else {
1065 let tracked ret = Self::take_resource_right_helper(&mut tmp);
1066 res = Some(Sum::Right(ret));
1067 }
1068 }
1069 let tracked mut resource = tmp.update(
1070 CsumP::<A, B, TOTAL>::Cinr(None, tmp.value().frac(), true),
1071 );
1072 Self::put_resource_right_helper(&mut resource, b);
1073 tracked_swap(r, &mut resource);
1074 res
1075 }
1076
1077 pub proof fn join_left(tracked &mut self, tracked other: Left<A, B, TOTAL>)
1079 requires
1080 old(self).id() == other.id(),
1081 ensures
1082 final(self).id() == old(self).id(),
1083 final(self).is_left(),
1084 final(self).is_resource_owner() == (old(self).is_resource_owner()
1085 || other.is_resource_owner()),
1086 final(self).has_resource() == (old(self).has_resource() || other.has_resource()),
1087 final(self).has_resource() ==> final(self).resource() == if old(
1088 self,
1089 ).is_resource_owner() {
1090 old(self).resource()
1091 } else {
1092 Sum::Left(other.resource())
1093 },
1094 final(self).frac() == old(self).frac() + other.frac(),
1095 final(self).wf(),
1096 {
1097 use_type_invariant(&*self);
1098 use_type_invariant(&other);
1099 Self::join_left_helper(&mut self.r, other.r);
1100 }
1101
1102 proof fn join_left_helper(
1103 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
1104 tracked other: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
1105 )
1106 requires
1107 Self::type_inv_inner(old(r).value()),
1108 Self::type_inv_inner(other.value()),
1109 old(r).loc() == other.loc(),
1110 other.value().is_left(),
1111 ensures
1112 Self::type_inv_inner(final(r).value()),
1113 final(r).loc() == old(r).loc(),
1114 final(r).value().is_left(),
1115 final(r).value().frac() == old(r).value().frac() + other.value().frac(),
1116 final(r).value().is_resource_owner() == (old(r).value().is_resource_owner()
1117 || other.value().is_resource_owner()),
1118 final(r).value().has_resource() == (old(r).value().has_resource()
1119 || other.value().has_resource()),
1120 final(r).value().has_resource() ==> final(r).value().resource() == if old(
1121 r,
1122 ).value().is_resource_owner() {
1123 old(r).value().resource()
1124 } else {
1125 other.value().resource()
1126 },
1127 {
1128 r.validate_with_shared(&other);
1129 let tracked mut tmp = Self::alloc_unit_storage();
1130 tracked_swap(r, &mut tmp);
1131 let tracked mut joined = StorageResource::join(tmp, other);
1132 tracked_swap(r, &mut joined);
1133 }
1134
1135 pub proof fn join_right(tracked &mut self, tracked other: Right<A, B, TOTAL>)
1137 requires
1138 old(self).id() == other.id(),
1139 ensures
1140 final(self).id() == old(self).id(),
1141 final(self).is_right(),
1142 final(self).is_resource_owner() == (old(self).is_resource_owner()
1143 || other.is_resource_owner()),
1144 final(self).has_resource() == (old(self).has_resource() || other.has_resource()),
1145 final(self).has_resource() ==> final(self).resource() == if old(
1146 self,
1147 ).is_resource_owner() {
1148 old(self).resource()
1149 } else {
1150 Sum::Right(other.resource())
1151 },
1152 final(self).frac() == old(self).frac() + other.frac(),
1153 final(self).wf(),
1154 {
1155 use_type_invariant(&*self);
1156 use_type_invariant(&other);
1157 Self::join_right_helper(&mut self.r, other.r);
1158 }
1159
1160 proof fn join_right_helper(
1161 tracked r: &mut StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
1162 tracked other: StorageResource<(), Sum<A, B>, CsumP<A, B, TOTAL>>,
1163 )
1164 requires
1165 Self::type_inv_inner(old(r).value()),
1166 Self::type_inv_inner(other.value()),
1167 old(r).loc() == other.loc(),
1168 other.value().is_right(),
1169 ensures
1170 Self::type_inv_inner(final(r).value()),
1171 final(r).loc() == old(r).loc(),
1172 final(r).value().is_right(),
1173 final(r).value().frac() == old(r).value().frac() + other.value().frac(),
1174 final(r).value().is_resource_owner() == (old(r).value().is_resource_owner()
1175 || other.value().is_resource_owner()),
1176 final(r).value().has_resource() == (old(r).value().has_resource()
1177 || other.value().has_resource()),
1178 final(r).value().has_resource() ==> final(r).value().resource() == if old(
1179 r,
1180 ).value().is_resource_owner() {
1181 old(r).value().resource()
1182 } else {
1183 other.value().resource()
1184 },
1185 {
1186 r.validate_with_shared(&other);
1187 let tracked mut tmp = Self::alloc_unit_storage();
1188 tracked_swap(r, &mut tmp);
1189 let tracked mut joined = StorageResource::join(tmp, other);
1190 tracked_swap(r, &mut joined);
1191 }
1192
1193 pub proof fn join_one_left_owner(tracked &mut self, tracked other: OneLeftOwner<A, B, TOTAL>)
1195 requires
1196 old(self).id() == other.id(),
1197 ensures
1198 final(self).id() == old(self).id(),
1199 final(self).is_left(),
1200 final(self).is_resource_owner(),
1201 final(self).has_resource() == other.has_resource(),
1202 final(self).has_resource() ==> final(self).resource_left() == other.resource(),
1203 final(self).frac() == old(self).frac() + 1,
1204 final(self).wf(),
1205 {
1206 use_type_invariant(&*self);
1207 use_type_invariant(&other);
1208 StorageResource::validate_with_shared(&mut self.r, &other.r.r);
1209 Self::join_left_helper(&mut self.r, other.r.r);
1210 }
1211
1212 pub proof fn join_one_right_owner(tracked &mut self, tracked other: OneRightOwner<A, B, TOTAL>)
1214 requires
1215 old(self).id() == other.id(),
1216 ensures
1217 final(self).id() == old(self).id(),
1218 final(self).is_right(),
1219 final(self).is_resource_owner(),
1220 final(self).has_resource() == other.has_resource(),
1221 final(self).has_resource() ==> final(self).resource_right() == other.resource(),
1222 final(self).frac() == old(self).frac() + 1,
1223 final(self).wf(),
1224 {
1225 use_type_invariant(&*self);
1226 use_type_invariant(&other);
1227 StorageResource::validate_with_shared(&mut self.r, &other.r.r);
1228 Self::join_right_helper(&mut self.r, other.r.r);
1229 }
1230
1231 pub proof fn join_one_left_knowledge(
1233 tracked &mut self,
1234 tracked other: OneLeftKnowledge<A, B, TOTAL>,
1235 )
1236 requires
1237 old(self).id() == other.id(),
1238 ensures
1239 final(self).id() == old(self).id(),
1240 final(self).is_left(),
1241 final(self).is_resource_owner() == old(self).is_resource_owner(),
1242 final(self).has_resource() == old(self).has_resource(),
1243 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
1244 final(self).frac() == old(self).frac() + 1,
1245 final(self).wf(),
1246 {
1247 use_type_invariant(&*self);
1248 use_type_invariant(&other);
1249 StorageResource::validate_with_shared(&mut self.r, &other.r.r);
1250 Self::join_left_helper(&mut self.r, other.r.r);
1251 }
1252
1253 pub proof fn join_one_right_knowledge(
1255 tracked &mut self,
1256 tracked other: OneRightKnowledge<A, B, TOTAL>,
1257 )
1258 requires
1259 old(self).id() == other.id(),
1260 ensures
1261 final(self).id() == old(self).id(),
1262 final(self).is_right(),
1263 final(self).is_resource_owner() == old(self).is_resource_owner(),
1264 final(self).has_resource() == old(self).has_resource(),
1265 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
1266 final(self).frac() == old(self).frac() + 1,
1267 final(self).wf(),
1268 {
1269 use_type_invariant(&*self);
1270 use_type_invariant(&other);
1271 StorageResource::validate_with_shared(&mut self.r, &other.r.r);
1272 Self::join_right_helper(&mut self.r, other.r.r);
1273 }
1274}
1275
1276impl<A, B, const TOTAL: u64> Left<A, B, TOTAL> {
1277 pub closed spec fn id(self) -> Loc {
1279 self.r.loc()
1280 }
1281
1282 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
1284 self.r.value()
1285 }
1286
1287 pub open spec fn is_resource_owner(self) -> bool {
1289 self.protocol_monoid().is_resource_owner()
1290 }
1291
1292 pub open spec fn resource(self) -> A {
1294 self.protocol_monoid().resource()->Left_0
1295 }
1296
1297 #[verifier::type_invariant]
1298 closed spec fn type_inv(self) -> bool {
1299 self.wf()
1300 }
1301
1302 pub open spec fn wf(self) -> bool {
1304 &&& self.protocol_monoid().is_left()
1305 &&& self.protocol_monoid().is_valid()
1306 &&& 1 <= self.frac() <= TOTAL
1307 &&& self.is_resource_owner() ==> (self.has_resource() <==> !self.has_no_resource())
1308 }
1309
1310 pub open spec fn has_resource(self) -> bool {
1312 self.protocol_monoid().has_resource()
1313 }
1314
1315 pub open spec fn has_no_resource(self) -> bool {
1317 self.protocol_monoid().has_no_resource()
1318 }
1319
1320 pub open spec fn frac(self) -> int {
1322 self.protocol_monoid().frac()
1323 }
1324
1325 pub proof fn validate(tracked &self)
1327 ensures
1328 self.wf(),
1329 {
1330 use_type_invariant(&*self);
1331 }
1332
1333 pub proof fn validate_with_left(tracked &mut self, tracked other: &Self)
1335 requires
1336 old(self).id() == other.id(),
1337 ensures
1338 *old(self) == *final(self),
1339 !(final(self).is_resource_owner() && other.is_resource_owner()),
1340 final(self).frac() + other.frac() <= TOTAL,
1341 final(self).wf(),
1342 {
1343 use_type_invariant(&*self);
1344 use_type_invariant(other);
1345 self.r.validate_with_shared(&other.r);
1346 }
1347
1348 pub proof fn validate_with_right(tracked &self, tracked other: &Right<A, B, TOTAL>)
1350 ensures
1351 self.id() != other.id(),
1352 self.wf(),
1353 {
1354 use_type_invariant(&*self);
1355 use_type_invariant(other);
1356 if self.id() == other.id() {
1357 self.r.join_shared(&other.r).validate();
1358 }
1359 }
1360
1361 pub proof fn tracked_borrow(tracked &self) -> (tracked res: &A)
1363 requires
1364 self.has_resource(),
1365 ensures
1366 *res == self.resource(),
1367 {
1368 use_type_invariant(&*self);
1369 StorageResource::guard(
1370 &self.r,
1371 map![() => Sum::<A, B>::Left(self.resource())],
1372 ).tracked_borrow(()).tracked_borrow_left()
1373 }
1374
1375 pub proof fn take_resource(tracked &mut self) -> (tracked res: A)
1377 requires
1378 old(self).is_resource_owner(),
1379 old(self).has_resource(),
1380 ensures
1381 final(self).id() == old(self).id(),
1382 res == old(self).resource(),
1383 final(self).is_resource_owner(),
1384 final(self).has_no_resource(),
1385 final(self).frac() == old(self).frac(),
1386 final(self).wf(),
1387 {
1388 use_type_invariant(&*self);
1389 let tracked r = SumResource::take_resource_left_helper(&mut self.r);
1390 r
1391 }
1392
1393 pub proof fn put_resource(tracked &mut self, tracked a: A)
1395 requires
1396 old(self).is_resource_owner(),
1397 old(self).has_no_resource(),
1398 ensures
1399 final(self).id() == old(self).id(),
1400 final(self).protocol_monoid() == CsumP::<A, B, TOTAL>::Cinl(
1401 Some(a),
1402 final(self).frac(),
1403 true,
1404 ),
1405 final(self).is_resource_owner(),
1406 final(self).has_resource(),
1407 final(self).resource() == a,
1408 final(self).frac() == old(self).frac(),
1409 final(self).wf(),
1410 {
1411 use_type_invariant(&*self);
1412 SumResource::put_resource_left_helper(&mut self.r, a);
1413 }
1414
1415 pub proof fn split_with_resource(tracked &mut self, n: int) -> (tracked res: Self)
1417 requires
1418 0 < n < old(self).frac(),
1419 ensures
1420 final(self).id() == old(self).id(),
1421 res.id() == final(self).id(),
1422 final(self).frac() == old(self).frac() - n,
1423 res.frac() == n,
1424 !final(self).is_resource_owner(),
1425 res.is_resource_owner() <==> old(self).is_resource_owner(),
1426 res.is_resource_owner() ==> (res.has_resource() <==> old(self).has_resource()),
1427 res.has_resource() ==> res.resource() == old(self).resource(),
1428 final(self).wf(),
1429 res.wf(),
1430 {
1431 use_type_invariant(&*self);
1432 let tracked r = SumResource::split_left_with_resource_helper(&mut self.r, n);
1433 Self { r }
1434 }
1435
1436 pub proof fn split_without_resource(tracked &mut self, n: int) -> (tracked res: Self)
1438 requires
1439 0 < n < old(self).frac(),
1440 ensures
1441 final(self).id() == old(self).id(),
1442 res.id() == final(self).id(),
1443 final(self).frac() == old(self).frac() - n,
1444 res.frac() == n,
1445 !res.is_resource_owner(),
1446 final(self).is_resource_owner() <==> old(self).is_resource_owner(),
1447 final(self).is_resource_owner() ==> (final(self).has_resource() <==> old(
1448 self,
1449 ).has_resource()),
1450 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
1451 final(self).wf(),
1452 res.wf(),
1453 {
1454 use_type_invariant(&*self);
1455 let tracked r = SumResource::split_left_without_resource_helper(&mut self.r, n);
1456 Self { r }
1457 }
1458
1459 pub proof fn update(tracked &mut self, tracked a: A) -> (tracked res: Option<A>)
1461 requires
1462 old(self).is_resource_owner(),
1463 ensures
1464 final(self).id() == old(self).id(),
1465 final(self).is_resource_owner(),
1466 final(self).has_resource(),
1467 final(self).resource() == a,
1468 final(self).frac() == old(self).frac(),
1469 res == if old(self).has_resource() {
1470 Some(old(self).resource())
1471 } else {
1472 None
1473 },
1474 final(self).wf(),
1475 {
1476 use_type_invariant(&*self);
1477 let tracked mut res = None;
1478 if self.has_resource() {
1479 res = Some(self.take_resource());
1480 }
1481 self.put_resource(a);
1482 res
1483 }
1484}
1485
1486impl<A, B, const TOTAL: u64> Right<A, B, TOTAL> {
1487 pub closed spec fn id(self) -> Loc {
1489 self.r.loc()
1490 }
1491
1492 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
1494 self.r.value()
1495 }
1496
1497 pub open spec fn is_resource_owner(self) -> bool {
1499 self.protocol_monoid().is_resource_owner()
1500 }
1501
1502 pub open spec fn resource(self) -> B {
1504 self.protocol_monoid().resource()->Right_0
1505 }
1506
1507 #[verifier::type_invariant]
1508 closed spec fn type_inv(self) -> bool {
1509 self.wf()
1510 }
1511
1512 pub open spec fn wf(self) -> bool {
1514 &&& self.protocol_monoid().is_right()
1515 &&& self.protocol_monoid().is_valid()
1516 &&& 1 <= self.frac() <= TOTAL
1517 &&& self.is_resource_owner() ==> (self.has_resource() <==> !self.has_no_resource())
1518 }
1519
1520 pub open spec fn has_resource(self) -> bool {
1522 self.protocol_monoid().has_resource()
1523 }
1524
1525 pub open spec fn has_no_resource(self) -> bool {
1527 self.protocol_monoid().has_no_resource()
1528 }
1529
1530 pub open spec fn frac(self) -> int {
1532 self.protocol_monoid().frac()
1533 }
1534
1535 pub proof fn validate(tracked &self)
1537 ensures
1538 self.wf(),
1539 {
1540 use_type_invariant(&*self);
1541 }
1542
1543 pub proof fn validate_with_left(tracked &self, tracked other: &Left<A, B, TOTAL>)
1545 ensures
1546 self.id() != other.id(),
1547 {
1548 use_type_invariant(&*self);
1549 use_type_invariant(other);
1550 if self.id() == other.id() {
1551 self.r.join_shared(&other.r).validate();
1552 }
1553 }
1554
1555 pub proof fn validate_with_right(tracked &mut self, tracked other: &Self)
1557 requires
1558 old(self).id() == other.id(),
1559 ensures
1560 *old(self) == *final(self),
1561 !(final(self).is_resource_owner() && other.is_resource_owner()),
1562 final(self).frac() + other.frac() <= TOTAL,
1563 final(self).wf(),
1564 {
1565 use_type_invariant(&*self);
1566 use_type_invariant(other);
1567 self.r.validate_with_shared(&other.r);
1568 }
1569
1570 pub proof fn tracked_borrow(tracked &self) -> (tracked res: &B)
1572 requires
1573 self.has_resource(),
1574 ensures
1575 *res == self.resource(),
1576 {
1577 use_type_invariant(&*self);
1578 StorageResource::guard(
1579 &self.r,
1580 map![() => Sum::<A, B>::Right(self.resource())],
1581 ).tracked_borrow(()).tracked_borrow_right()
1582 }
1583
1584 pub proof fn take_resource(tracked &mut self) -> (tracked res: B)
1586 requires
1587 old(self).is_resource_owner(),
1588 old(self).has_resource(),
1589 ensures
1590 final(self).id() == old(self).id(),
1591 res == old(self).resource(),
1592 final(self).is_resource_owner(),
1593 final(self).has_no_resource(),
1594 final(self).frac() == old(self).frac(),
1595 final(self).wf(),
1596 {
1597 use_type_invariant(&*self);
1598 let tracked r = SumResource::take_resource_right_helper(&mut self.r);
1599 r
1600 }
1601
1602 pub proof fn put_resource(tracked &mut self, tracked b: B)
1604 requires
1605 old(self).is_resource_owner(),
1606 old(self).has_no_resource(),
1607 ensures
1608 final(self).id() == old(self).id(),
1609 final(self).protocol_monoid() == CsumP::<A, B, TOTAL>::Cinr(
1610 Some(b),
1611 final(self).frac(),
1612 true,
1613 ),
1614 final(self).is_resource_owner(),
1615 final(self).has_resource(),
1616 final(self).resource() == b,
1617 final(self).frac() == old(self).frac(),
1618 final(self).wf(),
1619 {
1620 use_type_invariant(&*self);
1621 SumResource::put_resource_right_helper(&mut self.r, b);
1622 }
1623
1624 pub proof fn split_with_resource(tracked &mut self, n: int) -> (tracked res: Self)
1626 requires
1627 0 < n < old(self).frac(),
1628 ensures
1629 final(self).id() == old(self).id(),
1630 res.id() == final(self).id(),
1631 final(self).frac() == old(self).frac() - n,
1632 res.frac() == n,
1633 !final(self).is_resource_owner(),
1634 res.is_resource_owner() <==> old(self).is_resource_owner(),
1635 res.is_resource_owner() ==> (res.has_resource() <==> old(self).has_resource()),
1636 res.has_resource() ==> res.resource() == old(self).resource(),
1637 final(self).wf(),
1638 res.wf(),
1639 {
1640 use_type_invariant(&*self);
1641 let tracked r = SumResource::split_right_with_resource_helper(&mut self.r, n);
1642 Self { r }
1643 }
1644
1645 pub proof fn split_without_resource(tracked &mut self, n: int) -> (tracked res: Self)
1647 requires
1648 0 < n < old(self).frac(),
1649 ensures
1650 final(self).id() == old(self).id(),
1651 res.id() == final(self).id(),
1652 final(self).frac() == old(self).frac() - n,
1653 res.frac() == n,
1654 !res.is_resource_owner(),
1655 final(self).is_resource_owner() <==> old(self).is_resource_owner(),
1656 final(self).is_resource_owner() ==> (final(self).has_resource() <==> old(
1657 self,
1658 ).has_resource()),
1659 final(self).has_resource() ==> final(self).resource() == old(self).resource(),
1660 final(self).wf(),
1661 res.wf(),
1662 {
1663 use_type_invariant(&*self);
1664 let tracked r = SumResource::split_right_without_resource_helper(&mut self.r, n);
1665 Self { r }
1666 }
1667
1668 pub proof fn update(tracked &mut self, tracked b: B) -> (tracked res: Option<B>)
1670 requires
1671 old(self).is_resource_owner(),
1672 ensures
1673 final(self).id() == old(self).id(),
1674 final(self).is_resource_owner(),
1675 final(self).has_resource(),
1676 final(self).resource() == b,
1677 final(self).frac() == old(self).frac(),
1678 res == if old(self).has_resource() {
1679 Some(old(self).resource())
1680 } else {
1681 None
1682 },
1683 final(self).wf(),
1684 {
1685 use_type_invariant(&*self);
1686 let tracked mut res = None;
1687 if self.has_resource() {
1688 res = Some(self.take_resource());
1689 }
1690 self.put_resource(b);
1691 res
1692 }
1693}
1694
1695impl<A, B, const TOTAL: u64> OneLeftOwner<A, B, TOTAL> {
1696 pub closed spec fn id(self) -> Loc {
1698 self.r.id()
1699 }
1700
1701 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
1703 self.r.protocol_monoid()
1704 }
1705
1706 pub closed spec fn resource(self) -> A {
1708 self.r.resource()
1709 }
1710
1711 pub closed spec fn frac(self) -> int {
1713 self.r.frac()
1714 }
1715
1716 pub closed spec fn has_resource(self) -> bool {
1718 self.r.has_resource()
1719 }
1720
1721 pub closed spec fn has_no_resource(self) -> bool {
1723 self.r.has_no_resource()
1724 }
1725
1726 #[verifier::type_invariant]
1727 closed spec fn type_inv(self) -> bool {
1728 self.wf()
1729 }
1730
1731 pub open spec fn wf(self) -> bool {
1733 &&& self.protocol_monoid().is_left()
1734 &&& self.protocol_monoid().is_valid()
1735 &&& self.protocol_monoid().is_resource_owner()
1736 &&& self.frac() == 1
1737 &&& TOTAL >= 1
1738 &&& self.has_resource() <==> !self.has_no_resource()
1739 }
1740
1741 pub proof fn validate(tracked &self)
1743 ensures
1744 self.wf(),
1745 {
1746 use_type_invariant(&*self);
1747 }
1748
1749 pub proof fn validate_with_one_left_owner(tracked &mut self, tracked other: &Self)
1751 ensures
1752 *old(self) == *final(self),
1753 final(self).id() != other.id(),
1754 final(self).wf(),
1755 {
1756 use_type_invariant(&*self);
1757 use_type_invariant(other);
1758 if self.id() == other.id() {
1759 self.r.validate_with_left(&other.r);
1760 }
1761 }
1762
1763 pub proof fn tracked_borrow(tracked &self) -> (tracked res: &A)
1765 requires
1766 self.has_resource(),
1767 ensures
1768 *res == self.resource(),
1769 {
1770 use_type_invariant(&*self);
1771 self.r.tracked_borrow()
1772 }
1773
1774 pub proof fn take_resource(tracked &mut self) -> (tracked res: A)
1776 requires
1777 old(self).has_resource(),
1778 ensures
1779 res == old(self).resource(),
1780 final(self).has_no_resource(),
1781 final(self).wf(),
1782 {
1783 use_type_invariant(&*self);
1784 self.r.take_resource()
1785 }
1786
1787 pub proof fn put_resource(tracked &mut self, tracked a: A)
1789 requires
1790 old(self).has_no_resource(),
1791 ensures
1792 final(self).resource() == a,
1793 final(self).has_resource(),
1794 final(self).wf(),
1795 {
1796 use_type_invariant(&*self);
1797 self.r.put_resource(a);
1798 }
1799
1800 pub proof fn update(tracked &mut self, tracked a: A) -> (tracked res: Option<A>)
1802 ensures
1803 final(self).resource() == a,
1804 final(self).has_resource(),
1805 final(self).wf(),
1806 res == if old(self).has_resource() {
1807 Some(old(self).resource())
1808 } else {
1809 None
1810 },
1811 {
1812 use_type_invariant(&*self);
1813 self.r.update(a)
1814 }
1815}
1816
1817impl<A, B, const TOTAL: u64> OneRightOwner<A, B, TOTAL> {
1818 pub closed spec fn id(self) -> Loc {
1820 self.r.id()
1821 }
1822
1823 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
1825 self.r.protocol_monoid()
1826 }
1827
1828 pub closed spec fn resource(self) -> B {
1830 self.r.resource()
1831 }
1832
1833 pub closed spec fn frac(self) -> int {
1835 self.r.frac()
1836 }
1837
1838 pub closed spec fn has_resource(self) -> bool {
1840 self.r.has_resource()
1841 }
1842
1843 pub closed spec fn has_no_resource(self) -> bool {
1845 self.r.has_no_resource()
1846 }
1847
1848 #[verifier::type_invariant]
1849 closed spec fn type_inv(self) -> bool {
1850 self.wf()
1851 }
1852
1853 pub open spec fn wf(self) -> bool {
1855 &&& self.protocol_monoid().is_right()
1856 &&& self.protocol_monoid().is_valid()
1857 &&& self.protocol_monoid().is_resource_owner()
1858 &&& self.frac() == 1
1859 &&& TOTAL >= 1
1860 &&& self.has_resource() <==> !self.has_no_resource()
1861 }
1862
1863 pub proof fn validate(tracked &self)
1865 ensures
1866 self.wf(),
1867 {
1868 use_type_invariant(&*self);
1869 }
1870
1871 pub proof fn validate_with_one_right_owner(tracked &mut self, tracked other: &Self)
1873 ensures
1874 *old(self) == *final(self),
1875 final(self).id() != other.id(),
1876 final(self).wf(),
1877 {
1878 use_type_invariant(&*self);
1879 use_type_invariant(other);
1880 if self.id() == other.id() {
1881 self.r.validate_with_right(&other.r);
1882 }
1883 }
1884
1885 pub proof fn tracked_borrow(tracked &self) -> (tracked res: &B)
1887 requires
1888 self.has_resource(),
1889 ensures
1890 *res == self.resource(),
1891 {
1892 use_type_invariant(&*self);
1893 self.r.tracked_borrow()
1894 }
1895
1896 pub proof fn take_resource(tracked &mut self) -> (tracked res: B)
1898 requires
1899 old(self).has_resource(),
1900 ensures
1901 res == old(self).resource(),
1902 final(self).has_no_resource(),
1903 final(self).wf(),
1904 {
1905 use_type_invariant(&*self);
1906 self.r.take_resource()
1907 }
1908
1909 pub proof fn put_resource(tracked &mut self, tracked b: B)
1911 requires
1912 old(self).has_no_resource(),
1913 ensures
1914 final(self).resource() == b,
1915 final(self).has_resource(),
1916 final(self).wf(),
1917 {
1918 use_type_invariant(&*self);
1919 self.r.put_resource(b);
1920 }
1921
1922 pub proof fn update(tracked &mut self, tracked b: B) -> (tracked res: Option<B>)
1924 ensures
1925 final(self).resource() == b,
1926 final(self).has_resource(),
1927 final(self).wf(),
1928 res == if old(self).has_resource() {
1929 Some(old(self).resource())
1930 } else {
1931 None
1932 },
1933 {
1934 use_type_invariant(&*self);
1935 self.r.update(b)
1936 }
1937}
1938
1939impl<A, B, const TOTAL: u64> OneLeftKnowledge<A, B, TOTAL> {
1940 pub closed spec fn id(self) -> Loc {
1942 self.r.id()
1943 }
1944
1945 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
1947 self.r.protocol_monoid()
1948 }
1949
1950 pub closed spec fn frac(self) -> int {
1952 self.r.frac()
1953 }
1954
1955 #[verifier::type_invariant]
1956 closed spec fn type_inv(self) -> bool {
1957 self.wf()
1958 }
1959
1960 pub open spec fn wf(self) -> bool {
1962 &&& self.protocol_monoid().is_left()
1963 &&& self.protocol_monoid().is_valid()
1964 &&& !self.protocol_monoid().is_resource_owner()
1965 &&& self.frac() == 1
1966 &&& TOTAL >= 1
1967 }
1968
1969 pub proof fn validate(tracked &self)
1971 ensures
1972 self.wf(),
1973 {
1974 use_type_invariant(&*self);
1975 }
1976
1977 pub proof fn validate_with_one_right_knowledge(
1979 tracked &self,
1980 tracked other: &OneRightKnowledge<A, B, TOTAL>,
1981 )
1982 ensures
1983 self.id() != other.id(),
1984 {
1985 use_type_invariant(&*self);
1986 use_type_invariant(other);
1987 if self.id() == other.id() {
1988 self.r.validate_with_right(&other.r);
1989 }
1990 }
1991
1992 pub proof fn validate_with_one_right_owner(
1994 tracked &self,
1995 tracked other: &OneRightOwner<A, B, TOTAL>,
1996 )
1997 ensures
1998 self.id() != other.id(),
1999 {
2000 use_type_invariant(&*self);
2001 use_type_invariant(other);
2002 if self.id() == other.id() {
2003 self.r.validate_with_right(&other.r);
2004 }
2005 }
2006}
2007
2008impl<A, B, const TOTAL: u64> OneRightKnowledge<A, B, TOTAL> {
2009 pub closed spec fn id(self) -> Loc {
2011 self.r.id()
2012 }
2013
2014 pub closed spec fn protocol_monoid(self) -> CsumP<A, B, TOTAL> {
2016 self.r.protocol_monoid()
2017 }
2018
2019 pub closed spec fn frac(self) -> int {
2021 self.r.frac()
2022 }
2023
2024 #[verifier::type_invariant]
2025 closed spec fn type_inv(self) -> bool {
2026 self.wf()
2027 }
2028
2029 pub open spec fn wf(self) -> bool {
2031 &&& self.protocol_monoid().is_right()
2032 &&& self.protocol_monoid().is_valid()
2033 &&& !self.protocol_monoid().is_resource_owner()
2034 &&& self.frac() == 1
2035 &&& TOTAL >= 1
2036 }
2037
2038 pub proof fn validate(tracked &self)
2040 ensures
2041 self.wf(),
2042 {
2043 use_type_invariant(&*self);
2044 }
2045
2046 pub proof fn validate_with_one_left_knowledge(
2048 tracked &self,
2049 tracked other: &OneLeftKnowledge<A, B, TOTAL>,
2050 )
2051 ensures
2052 self.id() != other.id(),
2053 {
2054 use_type_invariant(&*self);
2055 use_type_invariant(other);
2056 if self.id() == other.id() {
2057 self.r.validate_with_left(&other.r);
2058 }
2059 }
2060
2061 pub proof fn validate_with_one_left_owner(
2063 tracked &self,
2064 tracked other: &OneLeftOwner<A, B, TOTAL>,
2065 )
2066 ensures
2067 self.id() != other.id(),
2068 {
2069 use_type_invariant(&*self);
2070 use_type_invariant(other);
2071 if self.id() == other.id() {
2072 self.r.validate_with_left(&other.r);
2073 }
2074 }
2075}
2076
2077}