Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
Actris
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Iris
Actris
Commits
c914ef04
Commit
c914ef04
authored
1 year ago
by
Jonas Kastberg
Browse files
Options
Downloads
Patches
Plain Diff
WIP: Computable consistency
parent
4e7fc218
No related branches found
Branches containing commit
No related tags found
Tags containing commit
2 merge requests
!39
Multiparty synchronous
,
!35
Multiparty synchronous list
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
multi_actris/channel/proto_alt.v
+1408
-0
1408 additions, 0 deletions
multi_actris/channel/proto_alt.v
with
1408 additions
and
0 deletions
multi_actris/channel/proto_alt.v
0 → 100644
+
1408
−
0
View file @
c914ef04
(** This file defines the core of the Actris logic: It defines dependent
separation protocols and the various operations on it like dual, append, and
branching.
Dependent separation protocols [iProto] are defined by instantiating the
parameterized version in [proto_model] with the type of propositions [iProp] of Iris.
We define ways of constructing instances of the instantiated type via two
constructors:
- [iProto_end], which is identical to [proto_end].
- [iProto_message], which takes an [action] and an [iMsg]. The type [iMsg] is a
sequence of binders [iMsg_exist], terminated by the payload constructed with
[iMsg_base] based on arguments [v], [P] and [prot], which are the value, the
carried proposition and the [iProto] tail, respectively.
For convenience sake, we provide the following notations:
- [END], which is simply [iProto_end].
- [∃ x, m], which is [iMsg_exist] with argument [m].
- [MSG v {{ P }}; prot], which is [iMsg_Base] with arguments [v], [P] and [prot].
- [<a> m], which is [iProto_message] with arguments [a] and [m].
We also include custom notation to more easily construct complete constructions:
- [<a x1 .. xn> m], which is [<a> ∃ x1, .. ∃ xn, m].
- [<a x1 .. xn> MSG v; {{ P }}; prot], which constructs a full protocol.
Futhermore, we define the following operations:
- [iProto_dual], which turns all [Send] of a protocol into [Recv] and vice-versa.
- [iProto_app], which appends two protocols.
In addition we define the subprotocol relation [iProto_le] [⊑], which generalises
the following inductive definition for asynchronous subtyping on session types:
p1 <: p2 p1 <: p2 p1 <: !B.p3 ?A.p3 <: p2
---------- ---------------- ---------------- ----------------------------
end <: end !A.p1 <: !A.p2 ?A.p1 <: ?A.p2 ?A.p1 <: !B.p2
Example:
!R <: !R ?Q <: ?Q ?Q <: ?Q
------------------- --------------
?Q.!R <: !R.?Q ?P.?Q <: ?P.?Q
------------------------------------
?P.?Q.!R <: !R.?P.?Q
Lastly, relevant type classes instances are defined for each of the above
notions, such as contractiveness and non-expansiveness, after which the
specifications of the message-passing primitives are defined in terms of the
protocol connectives. *)
From
iris
.
algebra
Require
Import
gmap
excl_auth
gmap_view
.
From
iris
.
proofmode
Require
Import
proofmode
.
From
iris
.
base_logic
Require
Export
lib
.
iprop
.
From
iris
.
base_logic
Require
Import
lib
.
own
.
From
iris
.
program_logic
Require
Import
language
.
From
multi_actris
.
channel
Require
Import
proto_model
.
Set
Default
Proof
Using
"Type"
.
Export
action
.
(** * Setup of Iris's cameras *)
Class
protoG
Σ
V
:=
protoG_authG
::
inG
Σ
(
gmap_viewR
natO
(
optionUR
(
exclR
(
laterO
(
proto
(
leibnizO
V
)
(
iPropO
Σ
)
(
iPropO
Σ
))))))
.
Definition
protoΣ
V
:=
#
[
GFunctor
((
gmap_viewRF
natO
(
optionRF
(
exclRF
(
laterOF
(
protoOF
(
leibnizO
V
)
idOF
idOF
))))))
]
.
Global
Instance
subG_chanΣ
{
Σ
V
}
:
subG
(
protoΣ
V
)
Σ
→
protoG
Σ
V
.
Proof
.
solve_inG
.
Qed
.
(** * Types *)
Definition
iProto
Σ
V
:=
proto
V
(
iPropO
Σ
)
(
iPropO
Σ
)
.
Declare
Scope
proto_scope
.
Delimit
Scope
proto_scope
with
proto
.
Bind
Scope
proto_scope
with
iProto
.
Local
Open
Scope
proto
.
(** * Messages *)
Section
iMsg
.
Set
Primitive
Projections
.
Record
iMsg
Σ
V
:=
IMsg
{
iMsg_car
:
V
→
laterO
(
iProto
Σ
V
)
-
n
>
iPropO
Σ
}
.
End
iMsg
.
Arguments
IMsg
{_
_}
_
.
Arguments
iMsg_car
{_
_}
_
.
Declare
Scope
msg_scope
.
Delimit
Scope
msg_scope
with
msg
.
Bind
Scope
msg_scope
with
iMsg
.
Global
Instance
iMsg_inhabited
{
Σ
V
}
:
Inhabited
(
iMsg
Σ
V
)
:=
populate
(
IMsg
inhabitant
)
.
Section
imsg_ofe
.
Context
{
Σ
:
gFunctors
}
{
V
:
Type
}
.
Instance
iMsg_equiv
:
Equiv
(
iMsg
Σ
V
)
:=
λ
m1
m2
,
∀
w
p
,
iMsg_car
m1
w
p
≡
iMsg_car
m2
w
p
.
Instance
iMsg_dist
:
Dist
(
iMsg
Σ
V
)
:=
λ
n
m1
m2
,
∀
w
p
,
iMsg_car
m1
w
p
≡
{
n
}
≡
iMsg_car
m2
w
p
.
Lemma
iMsg_ofe_mixin
:
OfeMixin
(
iMsg
Σ
V
)
.
Proof
.
by
apply
(
iso_ofe_mixin
(
iMsg_car
:
_
→
V
-
d
>
_
-
n
>
_))
.
Qed
.
Canonical
Structure
iMsgO
:=
Ofe
(
iMsg
Σ
V
)
iMsg_ofe_mixin
.
Global
Instance
iMsg_cofe
:
Cofe
iMsgO
.
Proof
.
by
apply
(
iso_cofe
(
IMsg
:
(
V
-
d
>
_
-
n
>
_)
→
_)
iMsg_car
)
.
Qed
.
End
imsg_ofe
.
Program
Definition
iMsg_base_def
{
Σ
V
}
(
v
:
V
)
(
P
:
iProp
Σ
)
(
p
:
iProto
Σ
V
)
:
iMsg
Σ
V
:=
IMsg
(
λ
v'
,
λ
ne
p'
,
⌜
v
=
v'
⌝
∗
Next
p
≡
p'
∗
P
)
%
I
.
Next
Obligation
.
solve_proper
.
Qed
.
Definition
iMsg_base_aux
:
seal
(
@
iMsg_base_def
)
.
by
eexists
.
Qed
.
Definition
iMsg_base
:=
iMsg_base_aux
.(
unseal
)
.
Definition
iMsg_base_eq
:
@
iMsg_base
=
@
iMsg_base_def
:=
iMsg_base_aux
.(
seal_eq
)
.
Arguments
iMsg_base
{_
_}
_
%
V
_
%
I
_
%
proto
.
Global
Instance
:
Params
(
@
iMsg_base
)
3
:=
{}
.
Program
Definition
iMsg_exist_def
{
Σ
V
A
}
(
m
:
A
→
iMsg
Σ
V
)
:
iMsg
Σ
V
:=
IMsg
(
λ
v'
,
λ
ne
p'
,
∃
x
,
iMsg_car
(
m
x
)
v'
p'
)
%
I
.
Next
Obligation
.
solve_proper
.
Qed
.
Definition
iMsg_exist_aux
:
seal
(
@
iMsg_exist_def
)
.
by
eexists
.
Qed
.
Definition
iMsg_exist
:=
iMsg_exist_aux
.(
unseal
)
.
Definition
iMsg_exist_eq
:
@
iMsg_exist
=
@
iMsg_exist_def
:=
iMsg_exist_aux
.(
seal_eq
)
.
Arguments
iMsg_exist
{_
_
_}
_
%
msg
.
Global
Instance
:
Params
(
@
iMsg_exist
)
3
:=
{}
.
Definition
iMsg_texist
{
Σ
V
}
{
TT
:
tele
}
(
m
:
TT
→
iMsg
Σ
V
)
:
iMsg
Σ
V
:=
tele_fold
(
@
iMsg_exist
Σ
V
)
(
λ
x
,
x
)
(
tele_bind
m
)
.
Arguments
iMsg_texist
{_
_
!
_}
_
%
msg
/.
Notation
"'MSG' v {{ P } } ; p"
:=
(
iMsg_base
v
P
p
)
(
at
level
200
,
v
at
level
20
,
right
associativity
,
format
"MSG v {{ P } } ; p"
)
:
msg_scope
.
Notation
"'MSG' v ; p"
:=
(
iMsg_base
v
True
p
)
(
at
level
200
,
v
at
level
20
,
right
associativity
,
format
"MSG v ; p"
)
:
msg_scope
.
Notation
"∃ x .. y , m"
:=
(
iMsg_exist
(
λ
x
,
.
.
(
iMsg_exist
(
λ
y
,
m
))
..)
%
msg
)
:
msg_scope
.
Notation
"'∃..' x .. y , m"
:=
(
iMsg_texist
(
λ
x
,
.
.
(
iMsg_texist
(
λ
y
,
m
))
.
.
)%
msg
)
(
at
level
200
,
x
binder
,
y
binder
,
right
associativity
,
format
"∃.. x .. y , m"
)
:
msg_scope
.
Lemma
iMsg_texist_exist
{
Σ
V
}
{
TT
:
tele
}
w
lp
(
m
:
TT
→
iMsg
Σ
V
)
:
iMsg_car
(
∃
.
.
x
,
m
x
)
%
msg
w
lp
⊣⊢
(
∃
.
.
x
,
iMsg_car
(
m
x
)
w
lp
)
.
Proof
.
rewrite
/
iMsg_texist
iMsg_exist_eq
.
induction
TT
as
[|
T
TT
IH
];
simpl
;
[
done
|]
.
f_equiv
=>
x
.
apply
IH
.
Qed
.
(** * Operators *)
Definition
iProto_end_def
{
Σ
V
}
:
iProto
Σ
V
:=
proto_end
.
Definition
iProto_end_aux
:
seal
(
@
iProto_end_def
)
.
by
eexists
.
Qed
.
Definition
iProto_end
:=
iProto_end_aux
.(
unseal
)
.
Definition
iProto_end_eq
:
@
iProto_end
=
@
iProto_end_def
:=
iProto_end_aux
.(
seal_eq
)
.
Arguments
iProto_end
{_
_}
.
Definition
iProto_message_def
{
Σ
V
}
(
a
:
action
)
(
m
:
iMsg
Σ
V
)
:
iProto
Σ
V
:=
proto_message
a
(
iMsg_car
m
)
.
Definition
iProto_message_aux
:
seal
(
@
iProto_message_def
)
.
by
eexists
.
Qed
.
Definition
iProto_message
:=
iProto_message_aux
.(
unseal
)
.
Definition
iProto_message_eq
:
@
iProto_message
=
@
iProto_message_def
:=
iProto_message_aux
.(
seal_eq
)
.
Arguments
iProto_message
{_
_}
_
_
%
msg
.
Global
Instance
:
Params
(
@
iProto_message
)
3
:=
{}
.
Notation
"'END'"
:=
iProto_end
:
proto_scope
.
Notation
"< a > m"
:=
(
iProto_message
a
m
)
(
at
level
200
,
a
at
level
10
,
m
at
level
200
,
format
"< a > m"
)
:
proto_scope
.
Notation
"< a @ x1 .. xn > m"
:=
(
iProto_message
a
(
∃
x1
,
.
.
(∃
xn
,
m
)
..))
(
at
level
200
,
a
at
level
10
,
x1
closed
binder
,
xn
closed
binder
,
m
at
level
200
,
format
"< a @ x1 .. xn > m"
)
:
proto_scope
.
Notation
"< a @.. x1 .. xn > m"
:=
(
iProto_message
a
(
∃
.
.
x1
,
.
.
(∃..
xn
,
m
)
..))
(
at
level
200
,
a
at
level
10
,
x1
closed
binder
,
xn
closed
binder
,
m
at
level
200
,
format
"< a @.. x1 .. xn > m"
)
:
proto_scope
.
Class
MsgTele
{
Σ
V
}
{
TT
:
tele
}
(
m
:
iMsg
Σ
V
)
(
tv
:
TT
-
t
>
V
)
(
tP
:
TT
-
t
>
iProp
Σ
)
(
tp
:
TT
-
t
>
iProto
Σ
V
)
:=
msg_tele
:
m
≡
(
∃
.
.
x
,
MSG
tele_app
tv
x
{{
tele_app
tP
x
}};
tele_app
tp
x
)
%
msg
.
Global
Hint
Mode
MsgTele
!
!
-
!
-
-
-
:
typeclass_instances
.
(** * Operations *)
Program
Definition
iMsg_map
{
Σ
V
}
(
rec
:
iProto
Σ
V
→
iProto
Σ
V
)
(
m
:
iMsg
Σ
V
)
:
iMsg
Σ
V
:=
IMsg
(
λ
v
,
λ
ne
p1'
,
∃
p1
,
iMsg_car
m
v
(
Next
p1
)
∗
p1'
≡
Next
(
rec
p1
))
%
I
.
Next
Obligation
.
solve_proper
.
Qed
.
Program
Definition
iProto_map_app_aux
{
Σ
V
}
(
f
:
action
→
action
)
(
p2
:
iProto
Σ
V
)
(
rec
:
iProto
Σ
V
-
n
>
iProto
Σ
V
)
:
iProto
Σ
V
-
n
>
iProto
Σ
V
:=
λ
ne
p
,
proto_elim
p2
(
λ
a
m
,
proto_message
(
f
a
)
(
iMsg_car
(
iMsg_map
rec
(
IMsg
m
))))
p
.
Next
Obligation
.
intros
Σ
V
f
p2
rec
n
p1
p1'
Hp
.
apply
proto_elim_ne
=>
//
a
m1
m2
Hm
.
apply
proto_message_ne
=>
v
p'
/=.
by
repeat
f_equiv
.
Qed
.
Global
Instance
iProto_map_app_aux_contractive
{
Σ
V
}
f
(
p2
:
iProto
Σ
V
)
:
Contractive
(
iProto_map_app_aux
f
p2
)
.
Proof
.
intros
n
rec1
rec2
Hrec
p1
;
simpl
.
apply
proto_elim_ne
=>
//
a
m1
m2
Hm
.
apply
proto_message_ne
=>
v
p'
/=.
by
repeat
(
f_contractive
||
f_equiv
)
.
Qed
.
Definition
iProto_map_app
{
Σ
V
}
(
f
:
action
→
action
)
(
p2
:
iProto
Σ
V
)
:
iProto
Σ
V
-
n
>
iProto
Σ
V
:=
fixpoint
(
iProto_map_app_aux
f
p2
)
.
Definition
iProto_app_def
{
Σ
V
}
(
p1
p2
:
iProto
Σ
V
)
:
iProto
Σ
V
:=
iProto_map_app
id
p2
p1
.
Definition
iProto_app_aux
:
seal
(
@
iProto_app_def
)
.
Proof
.
by
eexists
.
Qed
.
Definition
iProto_app
:=
iProto_app_aux
.(
unseal
)
.
Definition
iProto_app_eq
:
@
iProto_app
=
@
iProto_app_def
:=
iProto_app_aux
.(
seal_eq
)
.
Arguments
iProto_app
{_
_}
_
%
proto
_
%
proto
.
Global
Instance
:
Params
(
@
iProto_app
)
2
:=
{}
.
Infix
"<++>"
:=
iProto_app
(
at
level
60
)
:
proto_scope
.
Notation
"m <++> p"
:=
(
iMsg_map
(
flip
iProto_app
p
)
m
)
:
msg_scope
.
Definition
iProto_dual_def
{
Σ
V
}
(
p
:
iProto
Σ
V
)
:
iProto
Σ
V
:=
iProto_map_app
action_dual
proto_end
p
.
Definition
iProto_dual_aux
:
seal
(
@
iProto_dual_def
)
.
Proof
.
by
eexists
.
Qed
.
Definition
iProto_dual
:=
iProto_dual_aux
.(
unseal
)
.
Definition
iProto_dual_eq
:
@
iProto_dual
=
@
iProto_dual_def
:=
iProto_dual_aux
.(
seal_eq
)
.
Arguments
iProto_dual
{_
_}
_
%
proto
.
Global
Instance
:
Params
(
@
iProto_dual
)
2
:=
{}
.
Notation
iMsg_dual
:=
(
iMsg_map
iProto_dual
)
.
Definition
iProto_dual_if
{
Σ
V
}
(
d
:
bool
)
(
p
:
iProto
Σ
V
)
:
iProto
Σ
V
:=
if
d
then
iProto_dual
p
else
p
.
Arguments
iProto_dual_if
{_
_}
_
_
%
proto
.
Global
Instance
:
Params
(
@
iProto_dual_if
)
3
:=
{}
.
(** * Proofs *)
Section
proto
.
Context
`{
!
protoG
Σ
V
}
.
Implicit
Types
v
:
V
.
Implicit
Types
p
pl
pr
:
iProto
Σ
V
.
Implicit
Types
m
:
iMsg
Σ
V
.
(** ** Equality *)
Lemma
iProto_case
p
:
p
≡
END
∨
∃
t
n
m
,
p
≡
<
(
t
,
n
)
>
m
.
Proof
.
rewrite
iProto_message_eq
iProto_end_eq
.
destruct
(
proto_case
p
)
as
[|([
a
n
]
&
m
&
?)];
[
by
left
|
right
]
.
by
exists
a
,
n
,
(
IMsg
m
)
.
Qed
.
Lemma
iProto_message_equivI
`{
!
BiInternalEq
SPROP
}
a1
a2
m1
m2
:
(
<
a1
>
m1
)
≡
(
<
a2
>
m2
)
⊣⊢@
{
SPROP
}
⌜
a1
=
a2
⌝
∧
(
∀
v
lp
,
iMsg_car
m1
v
lp
≡
iMsg_car
m2
v
lp
)
.
Proof
.
rewrite
iProto_message_eq
.
apply
proto_message_equivI
.
Qed
.
Lemma
iProto_message_end_equivI
`{
!
BiInternalEq
SPROP
}
a
m
:
(
<
a
>
m
)
≡
END
⊢@
{
SPROP
}
False
.
Proof
.
rewrite
iProto_message_eq
iProto_end_eq
.
apply
proto_message_end_equivI
.
Qed
.
Lemma
iProto_end_message_equivI
`{
!
BiInternalEq
SPROP
}
a
m
:
END
≡
(
<
a
>
m
)
⊢@
{
SPROP
}
False
.
Proof
.
by
rewrite
internal_eq_sym
iProto_message_end_equivI
.
Qed
.
(** ** Non-expansiveness of operators *)
Global
Instance
iMsg_car_proper
:
Proper
(
iMsg_equiv
==>
(
=
)
==>
(
≡
)
==>
(
≡
))
(
iMsg_car
(
Σ
:=
Σ
)
(
V
:=
V
))
.
Proof
.
intros
m1
m2
meq
v1
v2
veq
p1
p2
peq
.
rewrite
meq
.
f_equiv
;
[
by
f_equiv
|
done
]
.
Qed
.
Global
Instance
iMsg_car_ne
n
:
Proper
(
iMsg_dist
n
==>
(
=
)
==>
(
dist
n
)
==>
(
dist
n
))
(
iMsg_car
(
Σ
:=
Σ
)
(
V
:=
V
))
.
Proof
.
intros
m1
m2
meq
v1
v2
veq
p1
p2
peq
.
rewrite
meq
.
f_equiv
;
[
by
f_equiv
|
done
]
.
Qed
.
Global
Instance
iMsg_contractive
v
n
:
Proper
(
dist
n
==>
dist_later
n
==>
dist
n
)
(
iMsg_base
(
Σ
:=
Σ
)
(
V
:=
V
)
v
)
.
Proof
.
rewrite
iMsg_base_eq
=>
P1
P2
HP
p1
p2
Hp
w
q
/=.
solve_contractive
.
Qed
.
Global
Instance
iMsg_ne
v
:
NonExpansive2
(
iMsg_base
(
Σ
:=
Σ
)
(
V
:=
V
)
v
)
.
Proof
.
rewrite
iMsg_base_eq
=>
P1
P2
HP
p1
p2
Hp
w
q
/=.
solve_proper
.
Qed
.
Global
Instance
iMsg_proper
v
:
Proper
((
≡
)
==>
(
≡
)
==>
(
≡
))
(
iMsg_base
(
Σ
:=
Σ
)
(
V
:=
V
)
v
)
.
Proof
.
apply
(
ne_proper_2
_)
.
Qed
.
Global
Instance
iMsg_exist_ne
A
n
:
Proper
(
pointwise_relation
_
(
dist
n
)
==>
(
dist
n
))
(
@
iMsg_exist
Σ
V
A
)
.
Proof
.
rewrite
iMsg_exist_eq
=>
m1
m2
Hm
v
p
/=.
f_equiv
=>
x
.
apply
Hm
.
Qed
.
Global
Instance
iMsg_exist_proper
A
:
Proper
(
pointwise_relation
_
(
≡
)
==>
(
≡
))
(
@
iMsg_exist
Σ
V
A
)
.
Proof
.
rewrite
iMsg_exist_eq
=>
m1
m2
Hm
v
p
/=.
f_equiv
=>
x
.
apply
Hm
.
Qed
.
Global
Instance
msg_tele_base
(
v
:
V
)
(
P
:
iProp
Σ
)
(
p
:
iProto
Σ
V
)
:
MsgTele
(
TT
:=
TeleO
)
(
MSG
v
{{
P
}};
p
)
v
P
p
.
Proof
.
done
.
Qed
.
Global
Instance
msg_tele_exist
{
A
}
{
TT
:
A
→
tele
}
(
m
:
A
→
iMsg
Σ
V
)
tv
tP
tp
:
(
∀
x
,
MsgTele
(
TT
:=
TT
x
)
(
m
x
)
(
tv
x
)
(
tP
x
)
(
tp
x
))
→
MsgTele
(
TT
:=
TeleS
TT
)
(
∃
x
,
m
x
)
tv
tP
tp
.
Proof
.
intros
Hm
.
rewrite
/
MsgTele
/=.
f_equiv
=>
x
.
apply
Hm
.
Qed
.
Global
Instance
iProto_message_ne
a
:
NonExpansive
(
iProto_message
(
Σ
:=
Σ
)
(
V
:=
V
)
a
)
.
Proof
.
rewrite
iProto_message_eq
.
solve_proper
.
Qed
.
Global
Instance
iProto_message_proper
a
:
Proper
((
≡
)
==>
(
≡
))
(
iProto_message
(
Σ
:=
Σ
)
(
V
:=
V
)
a
)
.
Proof
.
apply
(
ne_proper
_)
.
Qed
.
Lemma
iProto_message_equiv
{
TT1
TT2
:
tele
}
a1
a2
(
m1
m2
:
iMsg
Σ
V
)
(
v1
:
TT1
-
t
>
V
)
(
v2
:
TT2
-
t
>
V
)
(
P1
:
TT1
-
t
>
iProp
Σ
)
(
P2
:
TT2
-
t
>
iProp
Σ
)
(
prot1
:
TT1
-
t
>
iProto
Σ
V
)
(
prot2
:
TT2
-
t
>
iProto
Σ
V
)
:
MsgTele
m1
v1
P1
prot1
→
MsgTele
m2
v2
P2
prot2
→
⌜
a1
=
a2
⌝
-∗
(
■
∀
.
.
(
xs1
:
TT1
),
tele_app
P1
xs1
-∗
∃
.
.
(
xs2
:
TT2
),
⌜
tele_app
v1
xs1
=
tele_app
v2
xs2
⌝
∗
▷
(
tele_app
prot1
xs1
≡
tele_app
prot2
xs2
)
∗
tele_app
P2
xs2
)
-∗
(
■
∀
.
.
(
xs2
:
TT2
),
tele_app
P2
xs2
-∗
∃
.
.
(
xs1
:
TT1
),
⌜
tele_app
v1
xs1
=
tele_app
v2
xs2
⌝
∗
▷
(
tele_app
prot1
xs1
≡
tele_app
prot2
xs2
)
∗
tele_app
P1
xs1
)
-∗
(
<
a1
>
m1
)
≡
(
<
a2
>
m2
)
.
Proof
.
iIntros
(
Hm1
Hm2
Heq
)
"#Heq1 #Heq2"
.
unfold
MsgTele
in
Hm1
.
rewrite
Hm1
.
clear
Hm1
.
unfold
MsgTele
in
Hm2
.
rewrite
Hm2
.
clear
Hm2
.
rewrite
iProto_message_eq
proto_message_equivI
.
iSplit
;
[
done
|
]
.
iIntros
(
v
p'
)
.
do
2
rewrite
iMsg_texist_exist
.
rewrite
iMsg_base_eq
/=.
iApply
prop_ext
.
iIntros
"!>"
.
iSplit
.
-
iDestruct
1
as
(
xs1
Hveq1
)
"[Hrec1 HP1]"
.
iDestruct
(
"Heq1"
with
"HP1"
)
as
(
xs2
Hveq2
)
"[Hrec2 HP2]"
.
iExists
xs2
.
rewrite
-
Hveq1
Hveq2
.
iSplitR
;
[
done
|
]
.
iSplitR
"HP2"
;
[
|
done
]
.
iRewrite
-
"Hrec1"
.
iApply
later_equivI
.
iIntros
"!>"
.
by
iRewrite
"Hrec2"
.
-
iDestruct
1
as
(
xs2
Hveq2
)
"[Hrec2 HP2]"
.
iDestruct
(
"Heq2"
with
"HP2"
)
as
(
xs1
Hveq1
)
"[Hrec1 HP1]"
.
iExists
xs1
.
rewrite
-
Hveq2
Hveq1
.
iSplitR
;
[
done
|
]
.
iSplitR
"HP1"
;
[
|
done
]
.
iRewrite
-
"Hrec2"
.
iApply
later_equivI
.
iIntros
"!>"
.
by
iRewrite
"Hrec1"
.
Qed
.
(** Helpers *)
Lemma
iMsg_map_base
f
v
P
p
:
NonExpansive
f
→
iMsg_map
f
(
MSG
v
{{
P
}};
p
)
≡
(
MSG
v
{{
P
}};
f
p
)
%
msg
.
Proof
.
rewrite
iMsg_base_eq
.
intros
?
v'
p'
;
simpl
.
iSplit
.
-
iDestruct
1
as
(
p''
)
"[(->&Hp&$) Hp']"
.
iSplit
;
[
done
|]
.
iRewrite
"Hp'"
.
iIntros
"!>"
.
by
iRewrite
"Hp"
.
-
iIntros
"(->&Hp'&$)"
.
iExists
p
.
iRewrite
-
"Hp'"
.
auto
.
Qed
.
Lemma
iMsg_map_exist
{
A
}
f
(
m
:
A
→
iMsg
Σ
V
)
:
iMsg_map
f
(
∃
x
,
m
x
)
≡
(
∃
x
,
iMsg_map
f
(
m
x
))
%
msg
.
Proof
.
rewrite
iMsg_exist_eq
.
intros
v'
p'
;
simpl
.
iSplit
.
-
iDestruct
1
as
(
p''
)
"[H Hp']"
.
iDestruct
"H"
as
(
x
)
"H"
;
auto
.
-
iDestruct
1
as
(
x
p''
)
"[Hm Hp']"
.
auto
.
Qed
.
(** ** Dual *)
Global
Instance
iProto_dual_ne
:
NonExpansive
(
@
iProto_dual
Σ
V
)
.
Proof
.
rewrite
iProto_dual_eq
.
solve_proper
.
Qed
.
Global
Instance
iProto_dual_proper
:
Proper
((
≡
)
==>
(
≡
))
(
@
iProto_dual
Σ
V
)
.
Proof
.
apply
(
ne_proper
_)
.
Qed
.
Global
Instance
iProto_dual_if_ne
d
:
NonExpansive
(
@
iProto_dual_if
Σ
V
d
)
.
Proof
.
solve_proper
.
Qed
.
Global
Instance
iProto_dual_if_proper
d
:
Proper
((
≡
)
==>
(
≡
))
(
@
iProto_dual_if
Σ
V
d
)
.
Proof
.
apply
(
ne_proper
_)
.
Qed
.
Lemma
iProto_dual_end
:
iProto_dual
(
Σ
:=
Σ
)
(
V
:=
V
)
END
≡
END
.
Proof
.
rewrite
iProto_end_eq
iProto_dual_eq
/
iProto_dual_def
/
iProto_map_app
.
etrans
;
[
apply
(
fixpoint_unfold
(
iProto_map_app_aux
_
_))|];
simpl
.
by
rewrite
proto_elim_end
.
Qed
.
Lemma
iProto_dual_message
a
m
:
iProto_dual
(
<
a
>
m
)
≡
<
action_dual
a
>
iMsg_dual
m
.
Proof
.
rewrite
iProto_message_eq
iProto_dual_eq
/
iProto_dual_def
/
iProto_map_app
.
etrans
;
[
apply
(
fixpoint_unfold
(
iProto_map_app_aux
_
_))|];
simpl
.
rewrite
/
iProto_message_def
.
rewrite
->
proto_elim_message
;
[
done
|]
.
intros
a'
m1
m2
Hm
;
f_equiv
;
solve_proper
.
Qed
.
Lemma
iMsg_dual_base
v
P
p
:
iMsg_dual
(
MSG
v
{{
P
}};
p
)
≡
(
MSG
v
{{
P
}};
iProto_dual
p
)
%
msg
.
Proof
.
apply
iMsg_map_base
,
_
.
Qed
.
Lemma
iMsg_dual_exist
{
A
}
(
m
:
A
→
iMsg
Σ
V
)
:
iMsg_dual
(
∃
x
,
m
x
)
≡
(
∃
x
,
iMsg_dual
(
m
x
))
%
msg
.
Proof
.
apply
iMsg_map_exist
.
Qed
.
Global
Instance
iProto_dual_involutive
:
Involutive
(
≡
)
(
@
iProto_dual
Σ
V
)
.
Proof
.
intros
p
.
apply
(
uPred
.
internal_eq_soundness
(
M
:=
iResUR
Σ
))
.
iLöb
as
"IH"
forall
(
p
)
.
destruct
(
iProto_case
p
)
as
[
->
|(
a
&
n
&
m
&
->
)]
.
{
by
rewrite
!
iProto_dual_end
.
}
rewrite
!
iProto_dual_message
involutive
.
iApply
iProto_message_equivI
;
iSplit
;
[
done
|];
iIntros
(
v
p'
)
"/="
.
iApply
prop_ext
;
iIntros
"!>"
;
iSplit
.
-
iDestruct
1
as
(
pd
)
"[H Hp']"
.
iRewrite
"Hp'"
.
iDestruct
"H"
as
(
pdd
)
"[H #Hpd]"
.
iApply
(
internal_eq_rewrite
);
[|
done
];
iIntros
"!>"
.
iRewrite
"Hpd"
.
by
iRewrite
(
"IH"
$!
pdd
)
.
-
iIntros
"H"
.
destruct
(
Next_uninj
p'
)
as
[
p''
Hp'
]
.
iExists
_
.
rewrite
Hp'
.
iSplitL
;
[
by
auto
|]
.
iIntros
"!>"
.
by
iRewrite
(
"IH"
$!
p''
)
.
Qed
.
(** ** Append *)
Global
Instance
iProto_app_end_l
:
LeftId
(
≡
)
END
(
@
iProto_app
Σ
V
)
.
Proof
.
intros
p
.
rewrite
iProto_end_eq
iProto_app_eq
/
iProto_app_def
/
iProto_map_app
.
etrans
;
[
apply
(
fixpoint_unfold
(
iProto_map_app_aux
_
_))|];
simpl
.
by
rewrite
proto_elim_end
.
Qed
.
Lemma
iProto_app_message
a
m
p2
:
(
<
a
>
m
)
<++>
p2
≡
<
a
>
m
<++>
p2
.
Proof
.
rewrite
iProto_message_eq
iProto_app_eq
/
iProto_app_def
/
iProto_map_app
.
etrans
;
[
apply
(
fixpoint_unfold
(
iProto_map_app_aux
_
_))|];
simpl
.
rewrite
/
iProto_message_def
.
rewrite
->
proto_elim_message
;
[
done
|]
.
intros
a'
m1
m2
Hm
.
f_equiv
;
solve_proper
.
Qed
.
Global
Instance
iProto_app_ne
:
NonExpansive2
(
@
iProto_app
Σ
V
)
.
Proof
.
assert
(
∀
n
,
Proper
(
dist
n
==>
(
=
)
==>
dist
n
)
(
@
iProto_app
Σ
V
))
.
{
intros
n
p1
p1'
Hp1
p2
p2'
<-.
by
rewrite
iProto_app_eq
/
iProto_app_def
Hp1
.
}
assert
(
Proper
((
≡
)
==>
(
=
)
==>
(
≡
))
(
@
iProto_app
Σ
V
))
.
{
intros
p1
p1'
Hp1
p2
p2'
<-.
by
rewrite
iProto_app_eq
/
iProto_app_def
Hp1
.
}
intros
n
p1
p1'
Hp1
p2
p2'
Hp2
.
rewrite
Hp1
.
clear
p1
Hp1
.
revert
p1'
.
induction
(
lt_wf
n
)
as
[
n
_
IH
];
intros
p1
.
destruct
(
iProto_case
p1
)
as
[
->
|(
a
&
i
&
m
&
->
)]
.
{
by
rewrite
!
left_id
.
}
rewrite
!
iProto_app_message
.
f_equiv
=>
v
p'
/=.
do
4
f_equiv
.
f_contractive
.
apply
IH
;
eauto
using
dist_le
with
lia
.
Qed
.
Global
Instance
iProto_app_proper
:
Proper
((
≡
)
==>
(
≡
)
==>
(
≡
))
(
@
iProto_app
Σ
V
)
.
Proof
.
apply
(
ne_proper_2
_)
.
Qed
.
Lemma
iMsg_app_base
v
P
p1
p2
:
((
MSG
v
{{
P
}};
p1
)
<++>
p2
)
%
msg
≡
(
MSG
v
{{
P
}};
p1
<++>
p2
)
%
msg
.
Proof
.
apply
:
iMsg_map_base
.
Qed
.
Lemma
iMsg_app_exist
{
A
}
(
m
:
A
→
iMsg
Σ
V
)
p2
:
((
∃
x
,
m
x
)
<++>
p2
)
%
msg
≡
(
∃
x
,
m
x
<++>
p2
)
%
msg
.
Proof
.
apply
iMsg_map_exist
.
Qed
.
Global
Instance
iProto_app_end_r
:
RightId
(
≡
)
END
(
@
iProto_app
Σ
V
)
.
Proof
.
intros
p
.
apply
(
uPred
.
internal_eq_soundness
(
M
:=
iResUR
Σ
))
.
iLöb
as
"IH"
forall
(
p
)
.
destruct
(
iProto_case
p
)
as
[
->
|(
a
&
i
&
m
&
->
)]
.
{
by
rewrite
left_id
.
}
rewrite
iProto_app_message
.
iApply
iProto_message_equivI
;
iSplit
;
[
done
|];
iIntros
(
v
p'
)
"/="
.
iApply
prop_ext
;
iIntros
"!>"
.
iSplit
.
-
iDestruct
1
as
(
p1'
)
"[H Hp']"
.
iRewrite
"Hp'"
.
iApply
(
internal_eq_rewrite
);
[|
done
];
iIntros
"!>"
.
by
iRewrite
(
"IH"
$!
p1'
)
.
-
iIntros
"H"
.
destruct
(
Next_uninj
p'
)
as
[
p''
Hp'
]
.
iExists
p''
.
rewrite
Hp'
.
iSplitL
;
[
by
auto
|]
.
iIntros
"!>"
.
by
iRewrite
(
"IH"
$!
p''
)
.
Qed
.
Global
Instance
iProto_app_assoc
:
Assoc
(
≡
)
(
@
iProto_app
Σ
V
)
.
Proof
.
intros
p1
p2
p3
.
apply
(
uPred
.
internal_eq_soundness
(
M
:=
iResUR
Σ
))
.
iLöb
as
"IH"
forall
(
p1
)
.
destruct
(
iProto_case
p1
)
as
[
->
|(
a
&
i
&
m
&
->
)]
.
{
by
rewrite
!
left_id
.
}
rewrite
!
iProto_app_message
.
iApply
iProto_message_equivI
;
iSplit
;
[
done
|];
iIntros
(
v
p123
)
"/="
.
iApply
prop_ext
;
iIntros
"!>"
.
iSplit
.
-
iDestruct
1
as
(
p1'
)
"[H #Hp']"
.
iExists
(
p1'
<++>
p2
)
.
iSplitL
;
[
by
auto
|]
.
iRewrite
"Hp'"
.
iIntros
"!>"
.
iApply
"IH"
.
-
iDestruct
1
as
(
p12
)
"[H #Hp123]"
.
iDestruct
"H"
as
(
p1'
)
"[H #Hp12]"
.
iExists
p1'
.
iFrame
"H"
.
iRewrite
"Hp123"
.
iIntros
"!>"
.
iRewrite
"Hp12"
.
by
iRewrite
(
"IH"
$!
p1'
)
.
Qed
.
Lemma
iProto_dual_app
p1
p2
:
iProto_dual
(
p1
<++>
p2
)
≡
iProto_dual
p1
<++>
iProto_dual
p2
.
Proof
.
apply
(
uPred
.
internal_eq_soundness
(
M
:=
iResUR
Σ
))
.
iLöb
as
"IH"
forall
(
p1
p2
)
.
destruct
(
iProto_case
p1
)
as
[
->
|(
a
&
i
&
m
&
->
)]
.
{
by
rewrite
iProto_dual_end
!
left_id
.
}
rewrite
iProto_dual_message
!
iProto_app_message
iProto_dual_message
/=.
iApply
iProto_message_equivI
;
iSplit
;
[
done
|];
iIntros
(
v
p12
)
"/="
.
iApply
prop_ext
;
iIntros
"!>"
.
iSplit
.
-
iDestruct
1
as
(
p12d
)
"[H #Hp12]"
.
iDestruct
"H"
as
(
p1'
)
"[H #Hp12d]"
.
iExists
(
iProto_dual
p1'
)
.
iSplitL
;
[
by
auto
|]
.
iRewrite
"Hp12"
.
iIntros
"!>"
.
iRewrite
"Hp12d"
.
iApply
"IH"
.
-
iDestruct
1
as
(
p1'
)
"[H #Hp12]"
.
iDestruct
"H"
as
(
p1d
)
"[H #Hp1']"
.
iExists
(
p1d
<++>
p2
)
.
iSplitL
;
[
by
auto
|]
.
iRewrite
"Hp12"
.
iIntros
"!>"
.
iRewrite
"Hp1'"
.
by
iRewrite
(
"IH"
$!
p1d
p2
)
.
Qed
.
End
proto
.
Global
Instance
iProto_inhabited
{
Σ
V
}
:
Inhabited
(
iProto
Σ
V
)
:=
populate
END
.
Program
Definition
iProto_elim
{
Σ
V
A
}
(
x
:
A
)
(
f
:
action
→
iMsg
Σ
V
->
A
)
(
p
:
iProto
Σ
V
)
:
A
:=
proto_elim
x
(
λ
a
m
,
f
a
(
IMsg
(
λ
v
,
λ
ne
p
,
m
v
p
)))
%
I
p
.
Next
Obligation
.
solve_proper
.
Qed
.
Lemma
iProto_elim_message
{
Σ
V
}
{
A
:
ofe
}
(
x
:
A
)
(
f
:
action
→
iMsg
Σ
V
->
A
)
a
m
(* `{Hf : ∀ a, Proper ((≡) ==> (≡)) (f a)} : *)
:
iProto_elim
x
f
(
iProto_message
a
m
)
≡
f
a
m
.
Proof
.
rewrite
/
iProto_elim
.
rewrite
iProto_message_eq
/
iProto_message_def
.
simpl
.
setoid_rewrite
proto_elim_message
.
{
f_equiv
.
destruct
m
.
f_equiv
.
simpl
.
admit
.
}
intros
a'
.
intros
f1
f2
Hf'
.
f_equiv
.
f_equiv
.
Admitted
.
Definition
nat_beq
:=
Eval
compute
in
Nat
.
eqb
.
Definition
find_recv
{
Σ
V
}
(
i
:
nat
)
(
j
:
nat
)
(
ps
:
list
(
iProto
Σ
V
))
:
option
$
iMsg
Σ
V
:=
iProto_elim
None
(
λ
a
m
,
match
a
with
|
(
Recv
,
i'
)
=>
if
nat_beq
i
i'
then
Some
m
else
None
|
(
Send
,
_)
=>
None
end
)
(
ps
!!!
j
)
.
Fixpoint
sync_pairs_aux
{
Σ
V
}
(
i
:
nat
)
(
ps_full
ps
:
list
(
iProto
Σ
V
))
:
list
(
nat
*
nat
*
iMsg
Σ
V
*
iMsg
Σ
V
)
:=
match
ps
with
|
[]
=>
[]
|
p
::
ps
=>
iProto_elim
(
sync_pairs_aux
(
S
i
)
ps_full
ps
)
(
λ
a
mi
,
match
a
with
|
(
Recv
,_)
=>
sync_pairs_aux
(
S
i
)
ps_full
ps
|
(
Send
,
j
)
=>
match
find_recv
i
j
ps_full
with
|
None
=>
sync_pairs_aux
(
S
i
)
ps_full
ps
|
Some
mj
=>
(
i
,
j
,
mi
,
mj
)
::
sync_pairs_aux
(
S
i
)
ps_full
ps
end
end
)
p
end
.
Notation
sync_pairs
ps
:=
(
sync_pairs_aux
0
ps
ps
)
.
Definition
can_step
{
Σ
V
}
(
rec
:
list
(
iProto
Σ
V
)
→
iProp
Σ
)
(
ps
:
list
(
iProto
Σ
V
))
:
iProp
Σ
:=
[
∧
list
]
'
(
i
,
j
,
m1
,
m2
)
∈
sync_pairs
ps
,
∀
v
p1
,
iMsg_car
m1
v
(
Next
p1
)
-∗
∃
p2
,
iMsg_car
m2
v
(
Next
p2
)
∗
▷
(
rec
(
<
[
i
:=
p1
]
>
(
<
[
j
:=
p2
]
>
ps
)))
.
From
iris
.
heap_lang
Require
Import
notation
.
Definition
iProto_binary
`{
!
heapGS
Σ
}
:
list
(
iProto
Σ
val
)
:=
[(
<
(
Send
,
1
)
@
(
x
:
Z
)
>
MSG
#
x
;
END
)
%
proto
;
(
<
(
Recv
,
0
)
@
(
x
:
Z
)
>
MSG
#
x
;
END
)
%
proto
]
.
Lemma
iProto_binary_consistent
`{
!
heapGS
Σ
}
:
⊢
can_step
(
λ
_,
True
)
(
@
iProto_binary
_
Σ
heapGS
)
.
Proof
.
rewrite
/
iProto_binary
/
can_step
/
iProto_elim
.
simpl
.
rewrite
/
find_recv
.
simpl
.
Fail
rewrite
iProto_elim_message
.
(* OBS: Break here *)
Definition
valid_target
{
Σ
V
}
(
ps
:
list
(
iProto
Σ
V
))
(
i
j
:
nat
)
:
iProp
Σ
:=
∀
a
m
,
(
ps
!!!
i
≡
<
(
a
,
j
)
>
m
)
-∗
⌜
is_Some
(
ps
!!
j
)
⌝.
Definition
iProto_consistent_pre
{
Σ
V
}
(
rec
:
list
(
iProto
Σ
V
)
→
iProp
Σ
)
(
ps
:
list
(
iProto
Σ
V
))
:
iProp
Σ
:=
(
∀
i
j
,
valid_target
ps
i
j
)
∗
(
can_step
rec
ps
)
.
Global
Instance
iProto_consistent_pre_ne
{
Σ
V
}
(
rec
:
listO
(
iProto
Σ
V
)
-
n
>
iPropO
Σ
)
:
NonExpansive
(
iProto_consistent_pre
rec
)
.
Proof
.
rewrite
/
iProto_consistent_pre
/
can_step
/
valid_target
.
solve_proper
.
Qed
.
Program
Definition
iProto_consistent_pre'
{
Σ
V
}
(
rec
:
listO
(
iProto
Σ
V
)
-
n
>
iPropO
Σ
)
:
listO
(
iProto
Σ
V
)
-
n
>
iPropO
Σ
:=
λ
ne
ps
,
iProto_consistent_pre
(
λ
ps
,
rec
ps
)
ps
.
Local
Instance
iProto_consistent_pre_contractive
{
Σ
V
}
:
Contractive
(
@
iProto_consistent_pre'
Σ
V
)
.
Proof
.
rewrite
/
iProto_consistent_pre'
/
iProto_consistent_pre
/
can_step
.
solve_contractive
.
Qed
.
Definition
iProto_consistent
{
Σ
V
}
(
ps
:
list
(
iProto
Σ
V
))
:
iProp
Σ
:=
fixpoint
iProto_consistent_pre'
ps
.
Arguments
iProto_consistent
{_
_}
_
%
proto
.
Global
Instance
:
Params
(
@
iProto_consistent
)
1
:=
{}
.
Global
Instance
iProto_consistent_ne
{
Σ
V
}
:
NonExpansive
(
@
iProto_consistent
Σ
V
)
.
Proof
.
solve_proper
.
Qed
.
Global
Instance
iProto_consistent_proper
{
Σ
V
}
:
Proper
((
≡
)
==>
(
⊣⊢
))
(
@
iProto_consistent
Σ
V
)
.
Proof
.
solve_proper
.
Qed
.
Lemma
iProto_consistent_unfold
{
Σ
V
}
(
ps
:
list
(
iProto
Σ
V
))
:
iProto_consistent
ps
≡
(
iProto_consistent_pre
iProto_consistent
)
ps
.
Proof
.
apply
:
(
fixpoint_unfold
iProto_consistent_pre'
)
.
Qed
.
(** * Protocol entailment *)
Definition
iProto_le_pre
{
Σ
V
}
(
rec
:
iProto
Σ
V
→
iProto
Σ
V
→
iProp
Σ
)
(
p1
p2
:
iProto
Σ
V
)
:
iProp
Σ
:=
(
p1
≡
END
∗
p2
≡
END
)
∨
∃
a1
a2
m1
m2
,
(
p1
≡
<
a1
>
m1
)
∗
(
p2
≡
<
a2
>
m2
)
∗
match
a1
,
a2
with
|
(
Recv
,
i
),
(
Recv
,
j
)
=>
⌜
i
=
j
⌝
∗
∀
v
p1'
,
iMsg_car
m1
v
(
Next
p1'
)
-∗
∃
p2'
,
▷
rec
p1'
p2'
∗
iMsg_car
m2
v
(
Next
p2'
)
|
(
Send
,
i
),
(
Send
,
j
)
=>
⌜
i
=
j
⌝
∗
∀
v
p2'
,
iMsg_car
m2
v
(
Next
p2'
)
-∗
∃
p1'
,
▷
rec
p1'
p2'
∗
iMsg_car
m1
v
(
Next
p1'
)
|
_,
_
=>
False
end
.
Global
Instance
iProto_le_pre_ne
{
Σ
V
}
(
rec
:
iProto
Σ
V
→
iProto
Σ
V
→
iProp
Σ
)
:
NonExpansive2
(
iProto_le_pre
rec
)
.
Proof
.
solve_proper
.
Qed
.
Program
Definition
iProto_le_pre'
{
Σ
V
}
(
rec
:
iProto
Σ
V
-
n
>
iProto
Σ
V
-
n
>
iPropO
Σ
)
:
iProto
Σ
V
-
n
>
iProto
Σ
V
-
n
>
iPropO
Σ
:=
λ
ne
p1
p2
,
iProto_le_pre
(
λ
p1'
p2'
,
rec
p1'
p2'
)
p1
p2
.
Solve
Obligations
with
solve_proper
.
Local
Instance
iProto_le_pre_contractive
{
Σ
V
}
:
Contractive
(
@
iProto_le_pre'
Σ
V
)
.
Proof
.
intros
n
rec1
rec2
Hrec
p1
p2
.
rewrite
/
iProto_le_pre'
/
iProto_le_pre
/=.
by
repeat
(
f_contractive
||
f_equiv
)
.
Qed
.
Definition
iProto_le
{
Σ
V
}
(
p1
p2
:
iProto
Σ
V
)
:
iProp
Σ
:=
fixpoint
iProto_le_pre'
p1
p2
.
Arguments
iProto_le
{_
_}
_
%
proto
_
%
proto
.
Global
Instance
:
Params
(
@
iProto_le
)
2
:=
{}
.
Notation
"p ⊑ q"
:=
(
iProto_le
p
q
)
:
bi_scope
.
Global
Instance
iProto_le_ne
{
Σ
V
}
:
NonExpansive2
(
@
iProto_le
Σ
V
)
.
Proof
.
solve_proper
.
Qed
.
Global
Instance
iProto_le_proper
{
Σ
V
}
:
Proper
((
≡
)
==>
(
≡
)
==>
(
⊣⊢
))
(
@
iProto_le
Σ
V
)
.
Proof
.
solve_proper
.
Qed
.
Record
proto_name
:=
ProtName
{
proto_names
:
gmap
nat
gname
}
.
Global
Instance
proto_name_inhabited
:
Inhabited
proto_name
:=
populate
(
ProtName
inhabitant
)
.
Global
Instance
proto_name_eq_dec
:
EqDecision
proto_name
.
Proof
.
solve_decision
.
Qed
.
Global
Instance
proto_name_countable
:
Countable
proto_name
.
Proof
.
refine
(
inj_countable
(
λ
'
(
ProtName
γs
),
(
γs
))
(
λ
'
(
γs
),
Some
(
ProtName
γs
))
_);
by
intros
[]
.
Qed
.
Definition
iProto_own_frag
`{
!
protoG
Σ
V
}
(
γ
:
gname
)
(
i
:
nat
)
(
p
:
iProto
Σ
V
)
:
iProp
Σ
:=
own
γ
(
gmap_view_frag
i
(
DfracOwn
1
)
(
Excl'
(
Next
p
)))
.
Definition
iProto_own_auth
`{
!
protoG
Σ
V
}
(
γ
:
gname
)
(
ps
:
list
(
iProto
Σ
V
))
:
iProp
Σ
:=
own
γ
(
gmap_view_auth
(
DfracOwn
1
)
(((
λ
p
,
Excl'
(
Next
p
))
<$>
(
list_to_map
(
zip
(
seq
0
(
length
ps
))
ps
)))
:
gmap
_
_))
.
Definition
iProto_ctx
`{
protoG
Σ
V
}
(
γ
:
gname
)
(
ps_len
:
nat
)
:
iProp
Σ
:=
∃
ps
,
⌜
length
ps
=
ps_len
⌝
∗
iProto_own_auth
γ
ps
∗
▷
iProto_consistent
ps
.
(** * The connective for ownership of channel ends *)
Definition
iProto_own
`{
!
protoG
Σ
V
}
(
γ
:
gname
)
(
i
:
nat
)
(
p
:
iProto
Σ
V
)
:
iProp
Σ
:=
∃
p'
,
▷
(
p'
⊑
p
)
∗
iProto_own_frag
γ
i
p'
.
Arguments
iProto_own
{_
_
_}
_
_
_
%
proto
.
Global
Instance
:
Params
(
@
iProto_own
)
3
:=
{}
.
Global
Instance
iProto_own_frag_contractive
`{
protoG
Σ
V
}
γ
i
:
Contractive
(
iProto_own_frag
γ
i
)
.
Proof
.
solve_contractive
.
Qed
.
Global
Instance
iProto_own_contractive
`{
protoG
Σ
V
}
γ
i
:
Contractive
(
iProto_own
γ
i
)
.
Proof
.
solve_contractive
.
Qed
.
Global
Instance
iProto_own_ne
`{
protoG
Σ
V
}
γ
s
:
NonExpansive
(
iProto_own
γ
s
)
.
Proof
.
solve_proper
.
Qed
.
Global
Instance
iProto_own_proper
`{
protoG
Σ
V
}
γ
s
:
Proper
((
≡
)
==>
(
≡
))
(
iProto_own
γ
s
)
.
Proof
.
apply
(
ne_proper
_)
.
Qed
.
(** * Proofs *)
Section
proto
.
Context
`{
!
protoG
Σ
V
}
.
Implicit
Types
v
:
V
.
Implicit
Types
p
pl
pr
:
iProto
Σ
V
.
Implicit
Types
m
:
iMsg
Σ
V
.
Lemma
own_prot_idx
γ
i
j
(
p1
p2
:
iProto
Σ
V
)
:
own
γ
(
gmap_view_frag
i
(
DfracOwn
1
)
(
Excl'
(
Next
p1
)))
-∗
own
γ
(
gmap_view_frag
j
(
DfracOwn
1
)
(
Excl'
(
Next
p2
)))
-∗
⌜
i
≠
j
⌝.
Proof
.
iIntros
"Hown Hown'"
(
->
)
.
iDestruct
(
own_valid_2
with
"Hown Hown'"
)
as
"H"
.
rewrite
uPred
.
cmra_valid_elim
.
by
iDestruct
"H"
as
%
[]
%
gmap_view_frag_op_validN
.
Qed
.
Lemma
own_prot_excl
γ
i
(
p1
p2
:
iProto
Σ
V
)
:
own
γ
(
gmap_view_frag
i
(
DfracOwn
1
)
(
Excl'
(
Next
p1
)))
-∗
own
γ
(
gmap_view_frag
i
(
DfracOwn
1
)
(
Excl'
(
Next
p2
)))
-∗
False
.
Proof
.
iIntros
"Hi Hj"
.
by
iDestruct
(
own_prot_idx
with
"Hi Hj"
)
as
%
?
.
Qed
.
(** ** Protocol entailment **)
Lemma
iProto_le_unfold
p1
p2
:
iProto_le
p1
p2
≡
iProto_le_pre
iProto_le
p1
p2
.
Proof
.
apply
:
(
fixpoint_unfold
iProto_le_pre'
)
.
Qed
.
Lemma
iProto_le_end
:
⊢
END
⊑
(
END
:
iProto
Σ
V
)
.
Proof
.
rewrite
iProto_le_unfold
.
iLeft
.
auto
10
.
Qed
.
Lemma
iProto_le_end_inv_r
p
:
p
⊑
END
-∗
(
p
≡
END
)
.
Proof
.
rewrite
iProto_le_unfold
.
iIntros
"[[Hp _]|H] //"
.
iDestruct
"H"
as
(
a1
a2
m1
m2
)
"(_ & Heq & _)"
.
by
iDestruct
(
iProto_end_message_equivI
with
"Heq"
)
as
%
[]
.
Qed
.
Lemma
iProto_le_end_inv_l
p
:
END
⊑
p
-∗
(
p
≡
END
)
.
Proof
.
rewrite
iProto_le_unfold
.
iIntros
"[[_ Hp]|H] //"
.
iDestruct
"H"
as
(
a1
a2
m1
m2
)
"(Heq & _ & _)"
.
iDestruct
(
iProto_end_message_equivI
with
"Heq"
)
as
%
[]
.
Qed
.
Lemma
iProto_le_send_inv
i
p1
m2
:
p1
⊑
(
<
(
Send
,
i
)
>
m2
)
-∗
∃
m1
,
(
p1
≡
<
(
Send
,
i
)
>
m1
)
∗
∀
v
p2'
,
iMsg_car
m2
v
(
Next
p2'
)
-∗
∃
p1'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m1
v
(
Next
p1'
)
.
Proof
.
rewrite
iProto_le_unfold
.
iIntros
"[[_ Heq]|H]"
.
{
by
iDestruct
(
iProto_message_end_equivI
with
"Heq"
)
as
%
[]
.
}
iDestruct
"H"
as
(
a1
a2
m1
m2'
)
"(Hp1 & Hp2 & H)"
.
rewrite
iProto_message_equivI
.
iDestruct
"Hp2"
as
"[%Heq Hm2]"
.
simplify_eq
.
destruct
a1
as
[[]];
[|
done
]
.
iDestruct
"H"
as
(
->
)
"H"
.
iExists
m1
.
iFrame
"Hp1"
.
iIntros
(
v
p2
)
.
iSpecialize
(
"Hm2"
$!
v
(
Next
p2
))
.
by
iRewrite
"Hm2"
.
Qed
.
Lemma
iProto_le_send_send_inv
i
m1
m2
v
p2'
:
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
>
m2
)
-∗
iMsg_car
m2
v
(
Next
p2'
)
-∗
∃
p1'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m1
v
(
Next
p1'
)
.
Proof
.
iIntros
"H Hm2"
.
iDestruct
(
iProto_le_send_inv
with
"H"
)
as
(
m1'
)
"[Hm1 H]"
.
iDestruct
(
iProto_message_equivI
with
"Hm1"
)
as
(
Heq
)
"Hm1"
.
iDestruct
(
"H"
with
"Hm2"
)
as
(
p1'
)
"[Hle Hm]"
.
iRewrite
-
(
"Hm1"
$!
v
(
Next
p1'
))
in
"Hm"
.
auto
with
iFrame
.
Qed
.
Lemma
iProto_le_recv_inv_l
i
m1
p2
:
(
<
(
Recv
,
i
)
>
m1
)
⊑
p2
-∗
∃
m2
,
(
p2
≡
<
(
Recv
,
i
)
>
m2
)
∗
∀
v
p1'
,
iMsg_car
m1
v
(
Next
p1'
)
-∗
∃
p2'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m2
v
(
Next
p2'
)
.
Proof
.
rewrite
iProto_le_unfold
.
iIntros
"[[Heq _]|H]"
.
{
iDestruct
(
iProto_message_end_equivI
with
"Heq"
)
as
%
[]
.
}
iDestruct
"H"
as
(
a1
a2
m1'
m2
)
"(Hp1 & Hp2 & H)"
.
rewrite
iProto_message_equivI
.
iDestruct
"Hp1"
as
"[%Heq Hm1]"
.
simplify_eq
.
destruct
a2
as
[[]];
[
done
|]
.
iDestruct
"H"
as
(
->
)
"H"
.
iExists
m2
.
iFrame
"Hp2"
.
iIntros
(
v
p1
)
.
iSpecialize
(
"Hm1"
$!
v
(
Next
p1
))
.
by
iRewrite
"Hm1"
.
Qed
.
Lemma
iProto_le_recv_inv_r
i
p1
m2
:
(
p1
⊑
<
(
Recv
,
i
)
>
m2
)
-∗
∃
m1
,
(
p1
≡
<
(
Recv
,
i
)
>
m1
)
∗
∀
v
p1'
,
iMsg_car
m1
v
(
Next
p1'
)
-∗
∃
p2'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m2
v
(
Next
p2'
)
.
Proof
.
rewrite
iProto_le_unfold
.
iIntros
"[[_ Heq]|H]"
.
{
iDestruct
(
iProto_message_end_equivI
with
"Heq"
)
as
%
[]
.
}
iDestruct
"H"
as
(
a1
a2
m1
m2'
)
"(Hp1 & Hp2 & H)"
.
rewrite
iProto_message_equivI
.
iDestruct
"Hp2"
as
"[%Heq Hm2]"
.
simplify_eq
.
destruct
a1
as
[[]];
[
done
|]
.
iDestruct
"H"
as
(
->
)
"H"
.
iExists
m1
.
iFrame
.
iIntros
(
v
p2
)
.
iIntros
"Hm1"
.
iDestruct
(
"H"
with
"Hm1"
)
as
(
p2'
)
"[Hle H]"
.
iSpecialize
(
"Hm2"
$!
v
(
Next
p2'
))
.
iExists
p2'
.
iFrame
.
iRewrite
"Hm2"
.
iApply
"H"
.
Qed
.
Lemma
iProto_le_recv_recv_inv
i
m1
m2
v
p1'
:
(
<
(
Recv
,
i
)
>
m1
)
⊑
(
<
(
Recv
,
i
)
>
m2
)
-∗
iMsg_car
m1
v
(
Next
p1'
)
-∗
∃
p2'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m2
v
(
Next
p2'
)
.
Proof
.
iIntros
"H Hm2"
.
iDestruct
(
iProto_le_recv_inv_r
with
"H"
)
as
(
m1'
)
"[Hm1 H]"
.
iApply
"H"
.
iDestruct
(
iProto_message_equivI
with
"Hm1"
)
as
(_)
"Hm1"
.
by
iRewrite
-
(
"Hm1"
$!
v
(
Next
p1'
))
.
Qed
.
Lemma
iProto_le_msg_inv_l
i
a
m1
p2
:
(
<
(
a
,
i
)
>
m1
)
⊑
p2
-∗
∃
m2
,
p2
≡
<
(
a
,
i
)
>
m2
.
Proof
.
rewrite
iProto_le_unfold
/
iProto_le_pre
.
iIntros
"[[Heq _]|H]"
.
{
iDestruct
(
iProto_message_end_equivI
with
"Heq"
)
as
%
[]
.
}
iDestruct
"H"
as
(
a1
a2
m1'
m2
)
"(Hp1 & Hp2 & H)"
.
destruct
a1
as
[
t1
?],
a2
as
[
t2
?]
.
destruct
t1
,
t2
;
[|
done
|
done
|]
.
-
rewrite
iProto_message_equivI
.
iDestruct
"Hp1"
as
(
Heq
)
"Hp1"
.
simplify_eq
.
iDestruct
"H"
as
(
->
)
"H"
.
by
iExists
_
.
-
rewrite
iProto_message_equivI
.
iDestruct
"Hp1"
as
(
Heq
)
"Hp1"
.
simplify_eq
.
iDestruct
"H"
as
(
->
)
"H"
.
by
iExists
_
.
Qed
.
Lemma
iProto_le_msg_inv_r
j
a
p1
m2
:
(
p1
⊑
<
(
a
,
j
)
>
m2
)
-∗
∃
m1
,
p1
≡
<
(
a
,
j
)
>
m1
.
Proof
.
rewrite
iProto_le_unfold
/
iProto_le_pre
.
iIntros
"[[_ Heq]|H]"
.
{
iDestruct
(
iProto_message_end_equivI
with
"Heq"
)
as
%
[]
.
}
iDestruct
"H"
as
(
a1
a2
m1
m2'
)
"(Hp1 & Hp2 & H)"
.
destruct
a1
as
[
t1
?],
a2
as
[
t2
?]
.
destruct
t1
,
t2
;
[|
done
|
done
|]
.
-
rewrite
iProto_message_equivI
.
iDestruct
"Hp2"
as
(
Heq
)
"Hp2"
.
simplify_eq
.
iDestruct
"H"
as
(
->
)
"H"
.
by
iExists
_
.
-
rewrite
iProto_message_equivI
.
iDestruct
"Hp2"
as
(
Heq
)
"Hp2"
.
simplify_eq
.
iDestruct
"H"
as
(
->
)
"H"
.
by
iExists
_
.
Qed
.
Lemma
valid_target_le
ps
i
p1
p2
:
(
∀
i'
j'
,
valid_target
ps
i'
j'
)
-∗
ps
!!!
i
≡
p1
-∗
p1
⊑
p2
-∗
(
∀
i'
j'
,
valid_target
(
<
[
i
:=
p2
]
>
ps
)
i'
j'
)
∗
p1
⊑
p2
.
Proof
.
Admitted
.
(* iIntros "Hprot #HSome Hle". *)
(* pose proof (iProto_case p1) as [Hend|Hmsg]. *)
(* { rewrite Hend. iDestruct (iProto_le_end_inv_l with "Hle") as "#H". *)
(* iFrame "Hle". *)
(* iIntros (i' j' a m) "Hm". *)
(* destruct (decide (i = j')) as [->|Hneqj]. *)
(* { Search list_lookup_total insert. rewrite list_lookup_total_insert. ; [done|]. lia. done. } *)
(* rewrite lookup_insert_ne; [|done]. *)
(* destruct (decide (i = i')) as [->|Hneqi]. *)
(* { rewrite lookup_total_insert. iRewrite "H" in "Hm". *)
(* by iDestruct (iProto_end_message_equivI with "Hm") as "Hm". } *)
(* rewrite lookup_total_insert_ne; [|done]. *)
(* by iApply "Hprot". } *)
(* destruct Hmsg as (t & n & m & Hmsg). *)
(* setoid_rewrite Hmsg. *)
(* iDestruct (iProto_le_msg_inv_l with "Hle") as (m2) "#Heq". iFrame "Hle". *)
(* iIntros (i' j' a m') "Hm". *)
(* destruct (decide (i = j')) as [->|Hneqj]. *)
(* { rewrite lookup_insert. done. } *)
(* rewrite lookup_insert_ne; [|done]. *)
(* destruct (decide (i = i')) as [->|Hneqi]. *)
(* { rewrite lookup_total_insert. iRewrite "Heq" in "Hm". *)
(* iDestruct (iProto_message_equivI with "Hm") as (Heq) "Hm". *)
(* simplify_eq. by iApply "Hprot". } *)
(* rewrite lookup_total_insert_ne; [|done]. *)
(* by iApply "Hprot". *)
(* Qed. *)
Lemma
iProto_consistent_le
ps
i
p1
p2
:
iProto_consistent
ps
-∗
ps
!!!
i
≡
p1
-∗
p1
⊑
p2
-∗
iProto_consistent
(
<
[
i
:=
p2
]
>
ps
)
.
Proof
.
iIntros
"Hprot #HSome Hle"
.
iRevert
"HSome"
.
iLöb
as
"IH"
forall
(
p1
p2
ps
)
.
iIntros
"#HSome"
.
rewrite
!
iProto_consistent_unfold
.
iDestruct
"Hprot"
as
"(Htar & Hprot)"
.
iDestruct
(
valid_target_le
with
"Htar HSome Hle"
)
as
"[Htar Hle]"
.
iFrame
.
iIntros
(
i'
j'
m1
m2
)
"#Hm1 #Hm2"
.
destruct
(
decide
(
i
=
i'
))
as
[
<-|
Hneq
]
.
{
rewrite
list_lookup_total_insert
;
[|
admit
]
.
pose
proof
(
iProto_case
p2
)
as
[
Hend
|
Hmsg
]
.
{
setoid_rewrite
Hend
.
rewrite
iProto_end_message_equivI
.
done
.
}
destruct
Hmsg
as
(
a
&
?
&
m
&
Hmsg
)
.
setoid_rewrite
Hmsg
.
destruct
a
;
last
first
.
{
rewrite
iProto_message_equivI
.
iDestruct
"Hm1"
as
"[%Htag Hm1]"
.
done
.
}
rewrite
iProto_message_equivI
.
iDestruct
"Hm1"
as
"[%Htag Hm1]"
.
inversion
Htag
.
simplify_eq
.
iIntros
(
v
p
)
"Hm1'"
.
iSpecialize
(
"Hm1"
$!
v
(
Next
p
))
.
iDestruct
(
iProto_le_send_inv
with
"Hle"
)
as
"Hle"
.
iRewrite
-
"Hm1"
in
"Hm1'"
.
iDestruct
"Hle"
as
(
m'
)
"[#Heq H]"
.
iDestruct
(
"H"
with
"Hm1'"
)
as
(
p'
)
"[Hle H]"
.
destruct
(
decide
(
i
=
j'
))
as
[
<-|
Hneq
]
.
{
rewrite
list_lookup_total_insert
.
rewrite
iProto_message_equivI
.
iDestruct
"Hm2"
as
"[%Heq _]"
.
done
.
admit
.
}
iDestruct
(
"Hprot"
$!
i
j'
with
"[] [] H"
)
as
"Hprot"
.
{
iRewrite
-
"Heq"
.
rewrite
!
list_lookup_total_alt
.
iRewrite
"HSome"
.
done
.
}
{
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
done
.
}
iDestruct
"Hprot"
as
(
p''
)
"[Hm Hprot]"
.
iExists
p''
.
iFrame
.
iNext
.
iDestruct
(
"IH"
with
"Hprot Hle [HSome]"
)
as
"HI"
.
{
rewrite
list_lookup_total_insert
;
[
done
|]
.
admit
.
}
iClear
"IH Hm1 Hm2 Heq"
.
rewrite
list_insert_insert
.
rewrite
(
list_insert_commute
_
j'
i
);
[|
done
]
.
rewrite
list_insert_insert
.
done
.
}
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
destruct
(
decide
(
i
=
j'
))
as
[
<-|
Hneq'
]
.
{
rewrite
list_lookup_total_insert
.
pose
proof
(
iProto_case
p2
)
as
[
Hend
|
Hmsg
]
.
{
setoid_rewrite
Hend
.
rewrite
iProto_end_message_equivI
.
done
.
}
destruct
Hmsg
as
(
a
&
?
&
m
&
Hmsg
)
.
setoid_rewrite
Hmsg
.
destruct
a
.
{
rewrite
iProto_message_equivI
.
iDestruct
"Hm2"
as
"[%Htag Hm2]"
.
done
.
}
rewrite
iProto_message_equivI
.
iDestruct
"Hm2"
as
"[%Htag Hm2]"
.
inversion
Htag
.
simplify_eq
.
iIntros
(
v
p
)
"Hm1'"
.
iDestruct
(
iProto_le_recv_inv_r
with
"Hle"
)
as
"Hle"
.
iDestruct
"Hle"
as
(
m'
)
"[#Heq Hle]"
.
iDestruct
(
"Hprot"
$!
i'
with
"[] [] Hm1'"
)
as
"Hprot"
.
{
done
.
}
{
rewrite
!
list_lookup_total_alt
.
iRewrite
"HSome"
.
done
.
}
iDestruct
(
"Hprot"
)
as
(
p'
)
"[Hm1' Hprot]"
.
iDestruct
(
"Hle"
with
"Hm1'"
)
as
(
p2'
)
"[Hle Hm']"
.
iSpecialize
(
"Hm2"
$!
v
(
Next
p2'
))
.
iExists
p2'
.
iRewrite
-
"Hm2"
.
iFrame
.
iDestruct
(
"IH"
with
"Hprot Hle []"
)
as
"HI"
.
{
iPureIntro
.
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
rewrite
list_lookup_total_insert
.
done
.
admit
.
}
rewrite
list_insert_commute
;
[|
done
]
.
rewrite
!
list_insert_insert
.
done
.
admit
.
}
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
iIntros
(
v
p
)
"Hm1'"
.
iDestruct
(
"Hprot"
$!
i'
j'
with
"[//] [//] Hm1'"
)
as
"Hprot"
.
iDestruct
"Hprot"
as
(
p'
)
"[Hm2' Hprot]"
.
iExists
p'
.
iFrame
.
iNext
.
rewrite
(
list_insert_commute
_
j'
i
);
[|
done
]
.
rewrite
(
list_insert_commute
_
i'
i
);
[|
done
]
.
iApply
(
"IH"
with
"Hprot Hle []"
)
.
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
done
.
Admitted
.
Lemma
iProto_le_send
i
m1
m2
:
(
∀
v
p2'
,
iMsg_car
m2
v
(
Next
p2'
)
-∗
∃
p1'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m1
v
(
Next
p1'
))
-∗
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
>
m2
)
.
Proof
.
iIntros
"Hle"
.
rewrite
iProto_le_unfold
.
iRight
.
iExists
(
Send
,
i
),
(
Send
,
i
),
m1
,
m2
.
by
eauto
.
Qed
.
Lemma
iProto_le_recv
i
m1
m2
:
(
∀
v
p1'
,
iMsg_car
m1
v
(
Next
p1'
)
-∗
∃
p2'
,
▷
(
p1'
⊑
p2'
)
∗
iMsg_car
m2
v
(
Next
p2'
))
-∗
(
<
(
Recv
,
i
)
>
m1
)
⊑
(
<
(
Recv
,
i
)
>
m2
)
.
Proof
.
iIntros
"Hle"
.
rewrite
iProto_le_unfold
.
iRight
.
iExists
(
Recv
,
i
),
(
Recv
,
i
),
m1
,
m2
.
by
eauto
.
Qed
.
Lemma
iProto_le_base
a
v
P
p1
p2
:
▷
(
p1
⊑
p2
)
-∗
(
<
a
>
MSG
v
{{
P
}};
p1
)
⊑
(
<
a
>
MSG
v
{{
P
}};
p2
)
.
Proof
.
rewrite
iMsg_base_eq
.
iIntros
"H"
.
destruct
a
as
[[]]
.
-
iApply
iProto_le_send
.
iIntros
(
v'
p'
)
"(->&Hp&$)"
.
iExists
p1
.
iSplit
;
[|
by
auto
]
.
iIntros
"!>"
.
by
iRewrite
-
"Hp"
.
-
iApply
iProto_le_recv
.
iIntros
(
v'
p'
)
"(->&Hp&$)"
.
iExists
p2
.
iSplit
;
[|
by
auto
]
.
iIntros
"!>"
.
by
iRewrite
-
"Hp"
.
Qed
.
Lemma
iProto_le_trans
p1
p2
p3
:
p1
⊑
p2
-∗
p2
⊑
p3
-∗
p1
⊑
p3
.
Proof
.
iIntros
"H1 H2"
.
iLöb
as
"IH"
forall
(
p1
p2
p3
)
.
destruct
(
iProto_case
p3
)
as
[
->
|([]
&
i
&
m3
&
->
)]
.
-
iDestruct
(
iProto_le_end_inv_r
with
"H2"
)
as
"H2"
.
by
iRewrite
"H2"
in
"H1"
.
-
iDestruct
(
iProto_le_send_inv
with
"H2"
)
as
(
m2
)
"[Hp2 H2]"
.
iRewrite
"Hp2"
in
"H1"
;
clear
p2
.
iDestruct
(
iProto_le_send_inv
with
"H1"
)
as
(
m1
)
"[Hp1 H1]"
.
iRewrite
"Hp1"
;
clear
p1
.
iApply
iProto_le_send
.
iIntros
(
v
p3'
)
"Hm3"
.
iDestruct
(
"H2"
with
"Hm3"
)
as
(
p2'
)
"[Hle Hm2]"
.
iDestruct
(
"H1"
with
"Hm2"
)
as
(
p1'
)
"[Hle' Hm1]"
.
iExists
p1'
.
iIntros
"{$Hm1} !>"
.
by
iApply
(
"IH"
with
"Hle'"
)
.
-
iDestruct
(
iProto_le_recv_inv_r
with
"H2"
)
as
(
m2
)
"[Hp2 H3]"
.
iRewrite
"Hp2"
in
"H1"
.
iDestruct
(
iProto_le_recv_inv_r
with
"H1"
)
as
(
m1
)
"[Hp1 H2]"
.
iRewrite
"Hp1"
.
iApply
iProto_le_recv
.
iIntros
(
v
p1'
)
"Hm1"
.
iDestruct
(
"H2"
with
"Hm1"
)
as
(
p2'
)
"[Hle Hm2]"
.
iDestruct
(
"H3"
with
"Hm2"
)
as
(
p3'
)
"[Hle' Hm3]"
.
iExists
p3'
.
iIntros
"{$Hm3} !>"
.
by
iApply
(
"IH"
with
"Hle"
)
.
Qed
.
Lemma
iProto_le_refl
p
:
⊢
p
⊑
p
.
Proof
.
iLöb
as
"IH"
forall
(
p
)
.
destruct
(
iProto_case
p
)
as
[
->
|([]
&
i
&
m
&
->
)]
.
-
iApply
iProto_le_end
.
-
iApply
iProto_le_send
.
auto
10
with
iFrame
.
-
iApply
iProto_le_recv
.
auto
10
with
iFrame
.
Qed
.
Lemma
iProto_le_dual
p1
p2
:
p2
⊑
p1
-∗
iProto_dual
p1
⊑
iProto_dual
p2
.
Proof
.
iIntros
"H"
.
iLöb
as
"IH"
forall
(
p1
p2
)
.
destruct
(
iProto_case
p1
)
as
[
->
|([]
&
i
&
m1
&
->
)]
.
-
iDestruct
(
iProto_le_end_inv_r
with
"H"
)
as
"H"
.
iRewrite
"H"
.
iApply
iProto_le_refl
.
-
iDestruct
(
iProto_le_send_inv
with
"H"
)
as
(
m2
)
"[Hp2 H]"
.
iRewrite
"Hp2"
;
clear
p2
.
iEval
(
rewrite
!
iProto_dual_message
)
.
iApply
iProto_le_recv
.
iIntros
(
v
p1d
)
.
iDestruct
1
as
(
p1'
)
"[Hm1 #Hp1d]"
.
iDestruct
(
"H"
with
"Hm1"
)
as
(
p2'
)
"[H Hm2]"
.
iDestruct
(
"IH"
with
"H"
)
as
"H"
.
iExists
(
iProto_dual
p2'
)
.
iSplitL
"H"
;
[
iIntros
"!>"
;
by
iRewrite
"Hp1d"
|]
.
simpl
;
auto
.
-
iDestruct
(
iProto_le_recv_inv_r
with
"H"
)
as
(
m2
)
"[Hp2 H]"
.
iRewrite
"Hp2"
;
clear
p2
.
iEval
(
rewrite
!
iProto_dual_message
/=
)
.
iApply
iProto_le_send
.
iIntros
(
v
p2d
)
.
iDestruct
1
as
(
p2'
)
"[Hm2 #Hp2d]"
.
iDestruct
(
"H"
with
"Hm2"
)
as
(
p1'
)
"[H Hm1]"
.
iDestruct
(
"IH"
with
"H"
)
as
"H"
.
iExists
(
iProto_dual
p1'
)
.
iSplitL
"H"
;
[
iIntros
"!>"
;
by
iRewrite
"Hp2d"
|]
.
simpl
;
auto
.
Qed
.
Lemma
iProto_le_dual_l
p1
p2
:
iProto_dual
p2
⊑
p1
⊢
iProto_dual
p1
⊑
p2
.
Proof
.
iIntros
"H"
.
iEval
(
rewrite
-
(
involutive
iProto_dual
p2
))
.
by
iApply
iProto_le_dual
.
Qed
.
Lemma
iProto_le_dual_r
p1
p2
:
p2
⊑
iProto_dual
p1
⊢
p1
⊑
iProto_dual
p2
.
Proof
.
iIntros
"H"
.
iEval
(
rewrite
-
(
involutive
iProto_dual
p1
))
.
by
iApply
iProto_le_dual
.
Qed
.
Lemma
iProto_le_app
p1
p2
p3
p4
:
p1
⊑
p2
-∗
p3
⊑
p4
-∗
p1
<++>
p3
⊑
p2
<++>
p4
.
Proof
.
iIntros
"H1 H2"
.
iLöb
as
"IH"
forall
(
p1
p2
p3
p4
)
.
destruct
(
iProto_case
p2
)
as
[
->
|([]
&
i
&
m2
&
->
)]
.
-
iDestruct
(
iProto_le_end_inv_r
with
"H1"
)
as
"H1"
.
iRewrite
"H1"
.
by
rewrite
!
left_id
.
-
iDestruct
(
iProto_le_send_inv
with
"H1"
)
as
(
m1
)
"[Hp1 H1]"
.
iRewrite
"Hp1"
;
clear
p1
.
rewrite
!
iProto_app_message
.
iApply
iProto_le_send
.
iIntros
(
v
p24
)
.
iDestruct
1
as
(
p2'
)
"[Hm2 #Hp24]"
.
iDestruct
(
"H1"
with
"Hm2"
)
as
(
p1'
)
"[H1 Hm1]"
.
iExists
(
p1'
<++>
p3
)
.
iSplitR
"Hm1"
;
[|
by
simpl
;
eauto
]
.
iIntros
"!>"
.
iRewrite
"Hp24"
.
by
iApply
(
"IH"
with
"H1"
)
.
-
iDestruct
(
iProto_le_recv_inv_r
with
"H1"
)
as
(
m1
)
"[Hp1 H1]"
.
iRewrite
"Hp1"
;
clear
p1
.
rewrite
!
iProto_app_message
.
iApply
iProto_le_recv
.
iIntros
(
v
p13
)
.
iDestruct
1
as
(
p1'
)
"[Hm1 #Hp13]"
.
iDestruct
(
"H1"
with
"Hm1"
)
as
(
p2''
)
"[H1 Hm2]"
.
iExists
(
p2''
<++>
p4
)
.
iSplitR
"Hm2"
;
[|
by
simpl
;
eauto
]
.
iIntros
"!>"
.
iRewrite
"Hp13"
.
by
iApply
(
"IH"
with
"H1"
)
.
Qed
.
Lemma
iProto_le_payload_elim_l
i
m
v
P
p
:
(
P
-∗
(
<
(
Recv
,
i
)
>
MSG
v
;
p
)
⊑
(
<
(
Recv
,
i
)
>
m
))
⊢
(
<
(
Recv
,
i
)
>
MSG
v
{{
P
}};
p
)
⊑
<
(
Recv
,
i
)
>
m
.
Proof
.
rewrite
iMsg_base_eq
.
iIntros
"H"
.
iApply
iProto_le_recv
.
iIntros
(
v'
p'
)
"(->&Hp&HP)"
.
iApply
(
iProto_le_recv_recv_inv
with
"(H HP)"
);
simpl
;
auto
.
Qed
.
Lemma
iProto_le_payload_elim_r
i
m
v
P
p
:
(
P
-∗
(
<
(
Send
,
i
)
>
m
)
⊑
(
<
(
Send
,
i
)
>
MSG
v
;
p
))
⊢
(
<
(
Send
,
i
)
>
m
)
⊑
(
<
(
Send
,
i
)
>
MSG
v
{{
P
}};
p
)
.
Proof
.
rewrite
iMsg_base_eq
.
iIntros
"H"
.
iApply
iProto_le_send
.
iIntros
(
v'
p'
)
"(->&Hp&HP)"
.
iApply
(
iProto_le_send_send_inv
with
"(H HP)"
);
simpl
;
auto
.
Qed
.
Lemma
iProto_le_payload_intro_l
i
v
P
p
:
P
-∗
(
<
(
Send
,
i
)
>
MSG
v
{{
P
}};
p
)
⊑
(
<
(
Send
,
i
)
>
MSG
v
;
p
)
.
Proof
.
rewrite
iMsg_base_eq
.
iIntros
"HP"
.
iApply
iProto_le_send
.
iIntros
(
v'
p'
)
"(->&Hp&_) /="
.
iExists
p'
.
iSplitR
;
[
iApply
iProto_le_refl
|]
.
auto
.
Qed
.
Lemma
iProto_le_payload_intro_r
i
v
P
p
:
P
-∗
(
<
(
Recv
,
i
)
>
MSG
v
;
p
)
⊑
(
<
(
Recv
,
i
)
>
MSG
v
{{
P
}};
p
)
.
Proof
.
rewrite
iMsg_base_eq
.
iIntros
"HP"
.
iApply
iProto_le_recv
.
iIntros
(
v'
p'
)
"(->&Hp&_) /="
.
iExists
p'
.
iSplitR
;
[
iApply
iProto_le_refl
|]
.
auto
.
Qed
.
Lemma
iProto_le_exist_elim_l
{
A
}
i
(
m1
:
A
→
iMsg
Σ
V
)
m2
:
(
∀
x
,
(
<
(
Recv
,
i
)
>
m1
x
)
⊑
(
<
(
Recv
,
i
)
>
m2
))
⊢
(
<
(
Recv
,
i
)
@
x
>
m1
x
)
⊑
(
<
(
Recv
,
i
)
>
m2
)
.
Proof
.
rewrite
iMsg_exist_eq
.
iIntros
"H"
.
iApply
iProto_le_recv
.
iIntros
(
v
p1'
)
"/="
.
iDestruct
1
as
(
x
)
"Hm"
.
by
iApply
(
iProto_le_recv_recv_inv
with
"H"
)
.
Qed
.
Lemma
iProto_le_exist_elim_r
{
A
}
i
m1
(
m2
:
A
→
iMsg
Σ
V
)
:
(
∀
x
,
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
>
m2
x
))
⊢
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
@
x
>
m2
x
)
.
Proof
.
rewrite
iMsg_exist_eq
.
iIntros
"H"
.
iApply
iProto_le_send
.
iIntros
(
v
p2'
)
.
iDestruct
1
as
(
x
)
"Hm"
.
by
iApply
(
iProto_le_send_send_inv
with
"H"
)
.
Qed
.
Lemma
iProto_le_exist_intro_l
{
A
}
i
(
m
:
A
→
iMsg
Σ
V
)
a
:
⊢
(
<
(
Send
,
i
)
@
x
>
m
x
)
⊑
(
<
(
Send
,
i
)
>
m
a
)
.
Proof
.
rewrite
iMsg_exist_eq
.
iApply
iProto_le_send
.
iIntros
(
v
p'
)
"Hm /="
.
iExists
p'
.
iSplitR
;
last
by
auto
.
iApply
iProto_le_refl
.
Qed
.
Lemma
iProto_le_exist_intro_r
{
A
}
i
(
m
:
A
→
iMsg
Σ
V
)
a
:
⊢
(
<
(
Recv
,
i
)
>
m
a
)
⊑
(
<
(
Recv
,
i
)
@
x
>
m
x
)
.
Proof
.
rewrite
iMsg_exist_eq
.
iApply
iProto_le_recv
.
iIntros
(
v
p'
)
"Hm /="
.
iExists
p'
.
iSplitR
;
last
by
auto
.
iApply
iProto_le_refl
.
Qed
.
Lemma
iProto_le_texist_elim_l
{
TT
:
tele
}
i
(
m1
:
TT
→
iMsg
Σ
V
)
m2
:
(
∀
x
,
(
<
(
Recv
,
i
)
>
m1
x
)
⊑
(
<
(
Recv
,
i
)
>
m2
))
⊢
(
<
(
Recv
,
i
)
@..
x
>
m1
x
)
⊑
(
<
(
Recv
,
i
)
>
m2
)
.
Proof
.
iIntros
"H"
.
iInduction
TT
as
[|
T
TT
]
"IH"
;
simpl
;
[
done
|]
.
iApply
iProto_le_exist_elim_l
;
iIntros
(
x
)
.
iApply
"IH"
.
iIntros
(
xs
)
.
iApply
"H"
.
Qed
.
Lemma
iProto_le_texist_elim_r
{
TT
:
tele
}
i
m1
(
m2
:
TT
→
iMsg
Σ
V
)
:
(
∀
x
,
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
>
m2
x
))
-∗
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
@..
x
>
m2
x
)
.
Proof
.
iIntros
"H"
.
iInduction
TT
as
[|
T
TT
]
"IH"
;
simpl
;
[
done
|]
.
iApply
iProto_le_exist_elim_r
;
iIntros
(
x
)
.
iApply
"IH"
.
iIntros
(
xs
)
.
iApply
"H"
.
Qed
.
Lemma
iProto_le_texist_intro_l
{
TT
:
tele
}
i
(
m
:
TT
→
iMsg
Σ
V
)
x
:
⊢
(
<
(
Send
,
i
)
@..
x
>
m
x
)
⊑
(
<
(
Send
,
i
)
>
m
x
)
.
Proof
.
induction
x
as
[|
T
TT
x
xs
IH
]
using
tele_arg_ind
;
simpl
.
{
iApply
iProto_le_refl
.
}
iApply
iProto_le_trans
;
[
by
iApply
iProto_le_exist_intro_l
|]
.
iApply
IH
.
Qed
.
Lemma
iProto_le_texist_intro_r
{
TT
:
tele
}
i
(
m
:
TT
→
iMsg
Σ
V
)
x
:
⊢
(
<
(
Recv
,
i
)
>
m
x
)
⊑
(
<
(
Recv
,
i
)
@..
x
>
m
x
)
.
Proof
.
induction
x
as
[|
T
TT
x
xs
IH
]
using
tele_arg_ind
;
simpl
.
{
iApply
iProto_le_refl
.
}
iApply
iProto_le_trans
;
[|
by
iApply
iProto_le_exist_intro_r
]
.
iApply
IH
.
Qed
.
Lemma
iProto_consistent_target
ps
m
a
i
j
:
iProto_consistent
ps
-∗
ps
!!!
i
≡
(
<
(
a
,
j
)
>
m
)
-∗
⌜
is_Some
(
ps
!!
j
)
⌝.
Proof
.
rewrite
iProto_consistent_unfold
.
iDestruct
1
as
"[Htar _]"
.
iApply
"Htar"
.
Qed
.
Lemma
iProto_consistent_step
ps
m1
m2
i
j
v
p1
:
iProto_consistent
ps
-∗
ps
!!!
i
≡
(
<
(
Send
,
j
)
>
m1
)
-∗
ps
!!!
j
≡
(
<
(
Recv
,
i
)
>
m2
)
-∗
iMsg_car
m1
v
(
Next
p1
)
-∗
∃
p2
,
iMsg_car
m2
v
(
Next
p2
)
∗
▷
iProto_consistent
(
<
[
i
:=
p1
]
>
(
<
[
j
:=
p2
]
>
ps
))
.
Proof
.
iIntros
"Hprot #Hi #Hj Hm1"
.
rewrite
iProto_consistent_unfold
/
iProto_consistent_pre
.
iDestruct
"Hprot"
as
"[_ Hprot]"
.
iDestruct
(
"Hprot"
with
"Hi Hj Hm1"
)
as
(
p2
)
"[Hm2 Hprot]"
.
iExists
p2
.
iFrame
.
Qed
.
Global
Instance
iProto_own_frag_ne
γ
s
:
NonExpansive
(
iProto_own_frag
γ
s
)
.
Proof
.
solve_proper
.
Qed
.
Lemma
iProto_own_auth_agree
γ
ps
i
p
:
iProto_own_auth
γ
ps
-∗
iProto_own_frag
γ
i
p
-∗
▷
(
ps
!!!
i
≡
p
)
.
Proof
.
Admitted
.
(* iIntros "H● H◯". *)
(* iDestruct (own_valid_2 with "H● H◯") as "H✓". *)
(* rewrite gmap_view_both_validI. *)
(* iDestruct "H✓" as "[_ [H1 H2]]". *)
(* rewrite list_lookup_total_alt lookup_fmap. *)
(* destruct (ps !! i); last first. *)
(* { rewrite !option_equivI. } *)
(* simpl. rewrite !option_equivI excl_equivI. by iNext. *)
(* Qed. *)
Lemma
iProto_own_auth_update
γ
ps
i
p
p'
:
iProto_own_auth
γ
ps
-∗
iProto_own_frag
γ
i
p
==∗
iProto_own_auth
γ
(
<
[
i
:=
p'
]
>
ps
)
∗
iProto_own_frag
γ
i
p'
.
Proof
.
iIntros
"H● H◯"
.
iMod
(
own_update_2
with
"H● H◯"
)
as
"[H1 H2]"
;
[|
iModIntro
]
.
{
eapply
(
gmap_view_replace
_
_
_
(
Excl'
(
Next
p'
)))
.
done
.
}
iFrame
.
rewrite
-
fmap_insert
.
Admitted
.
Lemma
iProto_own_auth_alloc
ps
:
⊢
|
==>
∃
γ
,
iProto_own_auth
γ
ps
∗
[
∗
list
]
i
↦
p
∈
ps
,
iProto_own
γ
i
p
.
Proof
.
Admitted
.
(* iMod (own_alloc (gmap_view_auth (DfracOwn 1) ∅)) as (γ) "Hauth". *)
(* { apply gmap_view_auth_valid. } *)
(* iExists γ. *)
(* iInduction ps as [|i p ps Hin] "IH" using map_ind. *)
(* { iModIntro. iFrame. by iApply big_sepM_empty. } *)
(* iMod ("IH" with "Hauth") as "[Hauth Hfrags]". *)
(* rewrite big_sepM_insert; [|done]. iFrame "Hfrags". *)
(* iMod (own_update with "Hauth") as "[Hauth Hfrag]". *)
(* { apply (gmap_view_alloc _ i (DfracOwn 1) (Excl' (Next p))); [|done|done]. *)
(* by rewrite lookup_fmap Hin. } *)
(* iModIntro. rewrite -fmap_insert. iFrame. *)
(* iExists _. iFrame. iApply iProto_le_refl. *)
(* Qed. *)
Lemma
iProto_own_le
γ
s
p1
p2
:
iProto_own
γ
s
p1
-∗
▷
(
p1
⊑
p2
)
-∗
iProto_own
γ
s
p2
.
Proof
.
iDestruct
1
as
(
p1'
)
"[Hle H]"
.
iIntros
"Hle'"
.
iExists
p1'
.
iFrame
"H"
.
by
iApply
(
iProto_le_trans
with
"Hle"
)
.
Qed
.
Lemma
iProto_init
ps
:
▷
iProto_consistent
ps
-∗
|
==>
∃
γ
,
iProto_ctx
γ
(
length
ps
)
∗
[
∗
list
]
i
↦
p
∈
ps
,
iProto_own
γ
i
p
.
Proof
.
iIntros
"Hconsistent"
.
iMod
iProto_own_auth_alloc
as
(
γ
)
"[Hauth Hfrags]"
.
iExists
γ
.
iFrame
.
iExists
_
.
by
iFrame
.
Qed
.
Lemma
iProto_step
γ
ps_dom
i
j
m1
m2
p1
v
:
iProto_ctx
γ
ps_dom
-∗
iProto_own
γ
i
(
<
(
Send
,
j
)
>
m1
)
-∗
iProto_own
γ
j
(
<
(
Recv
,
i
)
>
m2
)
-∗
iMsg_car
m1
v
(
Next
p1
)
==∗
▷
∃
p2
,
iMsg_car
m2
v
(
Next
p2
)
∗
iProto_ctx
γ
ps_dom
∗
iProto_own
γ
i
p1
∗
iProto_own
γ
j
p2
.
Proof
.
iIntros
"Hctx Hi Hj Hm"
.
iDestruct
"Hi"
as
(
pi
)
"[Hile Hi]"
.
iDestruct
"Hj"
as
(
pj
)
"[Hjle Hj]"
.
iDestruct
"Hctx"
as
(
ps
Hdom
)
"[Hauth Hconsistent]"
.
iDestruct
(
iProto_own_auth_agree
with
"Hauth Hi"
)
as
"#Hpi"
.
iDestruct
(
iProto_own_auth_agree
with
"Hauth Hj"
)
as
"#Hpj"
.
iDestruct
(
own_prot_idx
with
"Hi Hj"
)
as
%
Hneq
.
iAssert
(
▷
(
<
[
i
:=
<
(
Send
,
j
)
>
m1
]
>
ps
!!!
j
≡
pj
))
%
I
as
"Hpj'"
.
{
by
rewrite
list_lookup_total_insert_ne
.
}
iAssert
(
▷
(
⌜
is_Some
(
ps
!!
i
)
⌝
∗
(
pi
⊑
(
<
(
Send
,
j
)
>
m1
))))
%
I
with
"[Hile]"
as
"[Hi' Hile]"
.
{
iNext
.
iDestruct
(
iProto_le_msg_inv_r
with
"Hile"
)
as
(
m
)
"#Heq"
.
iFrame
.
iRewrite
"Heq"
in
"Hpi"
.
rewrite
list_lookup_total_alt
.
destruct
(
ps
!!
i
);
[
done
|]
.
iDestruct
(
iProto_end_message_equivI
with
"Hpi"
)
as
"[]"
.
}
iAssert
(
▷
(
⌜
is_Some
(
ps
!!
j
)
⌝
∗
(
pj
⊑
(
<
(
Recv
,
i
)
>
m2
))))
%
I
with
"[Hjle]"
as
"[Hj' Hjle]"
.
{
iNext
.
iDestruct
(
iProto_le_msg_inv_r
with
"Hjle"
)
as
(
m
)
"#Heq"
.
iFrame
.
iRewrite
"Heq"
in
"Hpj"
.
rewrite
!
list_lookup_total_alt
.
destruct
(
ps
!!
j
);
[
done
|]
.
iDestruct
(
iProto_end_message_equivI
with
"Hpj"
)
as
"[]"
.
}
iDestruct
(
iProto_consistent_le
with
"Hconsistent Hpi Hile"
)
as
"Hconsistent"
.
iDestruct
(
iProto_consistent_le
with
"Hconsistent Hpj' Hjle"
)
as
"Hconsistent"
.
iDestruct
(
iProto_consistent_step
_
_
_
i
j
with
"Hconsistent [] [] [Hm //]"
)
as
(
p2
)
"[Hm2 Hconsistent]"
.
{
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
rewrite
list_lookup_total_insert
;
[
done
|]
.
admit
.
}
{
rewrite
list_lookup_total_insert_ne
;
[|
done
]
.
rewrite
list_lookup_total_insert
;
[
done
|]
.
admit
.
}
iMod
(
iProto_own_auth_update
_
_
_
_
p2
with
"Hauth Hj"
)
as
"[Hauth Hj]"
.
iMod
(
iProto_own_auth_update
_
_
_
_
p1
with
"Hauth Hi"
)
as
"[Hauth Hi]"
.
iIntros
"!>!>"
.
iExists
p2
.
iFrame
"Hm2"
.
iDestruct
"Hi'"
as
%
Hi
.
iDestruct
"Hj'"
as
%
Hj
.
iSplitL
"Hconsistent Hauth"
.
{
iExists
(
<
[
i
:=
p1
]
>
(
<
[
j
:=
p2
]
>
ps
))
.
iSplit
.
{
admit
.
(* rewrite !dom_insert_lookup_L; [done..|by rewrite lookup_insert_ne]. *)
}
iFrame
.
rewrite
list_insert_insert
.
rewrite
list_insert_commute
;
[|
done
]
.
rewrite
list_insert_insert
.
by
rewrite
list_insert_commute
;
[|
done
]
.
}
iSplitL
"Hi"
;
iExists
_;
iFrame
;
iApply
iProto_le_refl
.
Admitted
.
Lemma
iProto_target
γ
ps_dom
i
a
j
m
:
iProto_ctx
γ
ps_dom
-∗
iProto_own
γ
i
(
<
(
a
,
j
)
>
m
)
-∗
▷
(
⌜
j
<
ps_dom
⌝
)
∗
iProto_ctx
γ
ps_dom
∗
iProto_own
γ
i
(
<
(
a
,
j
)
>
m
)
.
Proof
.
iIntros
"Hctx Hown"
.
rewrite
/
iProto_ctx
/
iProto_own
.
iDestruct
"Hctx"
as
(
ps
Hdom
)
"[Hauth Hps]"
.
iDestruct
"Hown"
as
(
p'
)
"[Hle Hown]"
.
iDestruct
(
iProto_own_auth_agree
with
"Hauth Hown"
)
as
"#Hi"
.
iDestruct
(
iProto_le_msg_inv_r
with
"Hle"
)
as
(
m'
)
"#Heq"
.
iAssert
(
▷
(
⌜
is_Some
(
ps
!!
j
)
⌝
∗
iProto_consistent
ps
))
%
I
with
"[Hps]"
as
"[HSome Hps]"
.
{
iNext
.
iRewrite
"Heq"
in
"Hi"
.
iDestruct
(
iProto_consistent_target
with
"Hps Hi"
)
as
"#$"
.
by
iFrame
.
}
iSplitL
"HSome"
.
{
iNext
.
iDestruct
"HSome"
as
%
Heq
.
iPureIntro
.
simplify_eq
.
admit
.
}
iSplitL
"Hauth Hps"
;
iExists
_;
by
iFrame
.
Admitted
.
(* (** The instances below make it possible to use the tactics [iIntros], *)
(* [iExist], [iSplitL]/[iSplitR], [iFrame] and [iModIntro] on [iProto_le] goals. *) *)
Global
Instance
iProto_le_from_forall_l
{
A
}
i
(
m1
:
A
→
iMsg
Σ
V
)
m2
name
:
AsIdentName
m1
name
→
FromForall
(
iProto_message
(
Recv
,
i
)
(
iMsg_exist
m1
)
⊑
(
<
(
Recv
,
i
)
>
m2
))
(
λ
x
,
(
<
(
Recv
,
i
)
>
m1
x
)
⊑
(
<
(
Recv
,
i
)
>
m2
))
%
I
name
|
10
.
Proof
.
intros
_
.
apply
iProto_le_exist_elim_l
.
Qed
.
Global
Instance
iProto_le_from_forall_r
{
A
}
i
m1
(
m2
:
A
→
iMsg
Σ
V
)
name
:
AsIdentName
m2
name
→
FromForall
((
<
(
Send
,
i
)
>
m1
)
⊑
iProto_message
(
Send
,
i
)
(
iMsg_exist
m2
))
(
λ
x
,
(
<
(
Send
,
i
)
>
m1
)
⊑
(
<
(
Send
,
i
)
>
m2
x
))
%
I
name
|
11
.
Proof
.
intros
_
.
apply
iProto_le_exist_elim_r
.
Qed
.
Global
Instance
iProto_le_from_wand_l
i
m
v
P
p
:
TCIf
(
TCEq
P
True
%
I
)
False
TCTrue
→
FromWand
((
<
(
Recv
,
i
)
>
MSG
v
{{
P
}};
p
)
⊑
(
<
(
Recv
,
i
)
>
m
))
P
((
<
(
Recv
,
i
)
>
MSG
v
;
p
)
⊑
(
<
(
Recv
,
i
)
>
m
))
|
10
.
Proof
.
intros
_
.
apply
iProto_le_payload_elim_l
.
Qed
.
Global
Instance
iProto_le_from_wand_r
i
m
v
P
p
:
FromWand
((
<
(
Send
,
i
)
>
m
)
⊑
(
<
(
Send
,
i
)
>
MSG
v
{{
P
}};
p
))
P
((
<
(
Send
,
i
)
>
m
)
⊑
(
<
(
Send
,
i
)
>
MSG
v
;
p
))
|
11
.
Proof
.
apply
iProto_le_payload_elim_r
.
Qed
.
Global
Instance
iProto_le_from_exist_l
{
A
}
i
(
m
:
A
→
iMsg
Σ
V
)
p
:
FromExist
((
<
(
Send
,
i
)
@
x
>
m
x
)
⊑
p
)
(
λ
a
,
(
<
(
Send
,
i
)
>
m
a
)
⊑
p
)
%
I
|
10
.
Proof
.
rewrite
/
FromExist
.
iDestruct
1
as
(
x
)
"H"
.
iApply
(
iProto_le_trans
with
"[] H"
)
.
iApply
iProto_le_exist_intro_l
.
Qed
.
Global
Instance
iProto_le_from_exist_r
{
A
}
i
(
m
:
A
→
iMsg
Σ
V
)
p
:
FromExist
(
p
⊑
<
(
Recv
,
i
)
@
x
>
m
x
)
(
λ
a
,
p
⊑
(
<
(
Recv
,
i
)
>
m
a
))
%
I
|
11
.
Proof
.
rewrite
/
FromExist
.
iDestruct
1
as
(
x
)
"H"
.
iApply
(
iProto_le_trans
with
"H"
)
.
iApply
iProto_le_exist_intro_r
.
Qed
.
Global
Instance
iProto_le_from_sep_l
i
m
v
P
p
:
FromSep
((
<
(
Send
,
i
)
>
MSG
v
{{
P
}};
p
)
⊑
(
<
(
Send
,
i
)
>
m
))
P
((
<
(
Send
,
i
)
>
MSG
v
;
p
)
⊑
(
<
(
Send
,
i
)
>
m
))
|
10
.
Proof
.
rewrite
/
FromSep
.
iIntros
"[HP H]"
.
iApply
(
iProto_le_trans
with
"[HP] H"
)
.
by
iApply
iProto_le_payload_intro_l
.
Qed
.
Global
Instance
iProto_le_from_sep_r
i
m
v
P
p
:
FromSep
((
<
(
Recv
,
i
)
>
m
)
⊑
(
<
(
Recv
,
i
)
>
MSG
v
{{
P
}};
p
))
P
((
<
(
Recv
,
i
)
>
m
)
⊑
(
<
(
Recv
,
i
)
>
MSG
v
;
p
))
|
11
.
Proof
.
rewrite
/
FromSep
.
iIntros
"[HP H]"
.
iApply
(
iProto_le_trans
with
"H"
)
.
by
iApply
iProto_le_payload_intro_r
.
Qed
.
Global
Instance
iProto_le_frame_l
i
q
m
v
R
P
Q
p
:
Frame
q
R
P
Q
→
Frame
q
R
((
<
(
Send
,
i
)
>
MSG
v
{{
P
}};
p
)
⊑
(
<
(
Send
,
i
)
>
m
))
((
<
(
Send
,
i
)
>
MSG
v
{{
Q
}};
p
)
⊑
(
<
(
Send
,
i
)
>
m
))
|
10
.
Proof
.
rewrite
/
Frame
/=.
iIntros
(
HP
)
"[HR H]"
.
iApply
(
iProto_le_trans
with
"[HR] H"
)
.
iApply
iProto_le_payload_elim_r
.
iIntros
"HQ"
.
iApply
iProto_le_payload_intro_l
.
iApply
HP
;
iFrame
.
Qed
.
Global
Instance
iProto_le_frame_r
i
q
m
v
R
P
Q
p
:
Frame
q
R
P
Q
→
Frame
q
R
((
<
(
Recv
,
i
)
>
m
)
⊑
(
<
(
Recv
,
i
)
>
MSG
v
{{
P
}};
p
))
((
<
(
Recv
,
i
)
>
m
)
⊑
(
<
(
Recv
,
i
)
>
MSG
v
{{
Q
}};
p
))
|
11
.
Proof
.
rewrite
/
Frame
/=.
iIntros
(
HP
)
"[HR H]"
.
iApply
(
iProto_le_trans
with
"H"
)
.
iApply
iProto_le_payload_elim_l
.
iIntros
"HQ"
.
iApply
iProto_le_payload_intro_r
.
iApply
HP
;
iFrame
.
Qed
.
Global
Instance
iProto_le_from_modal
a
v
p1
p2
:
FromModal
True
(
modality_instances
.
modality_laterN
1
)
(
p1
⊑
p2
)
((
<
a
>
MSG
v
;
p1
)
⊑
(
<
a
>
MSG
v
;
p2
))
(
p1
⊑
p2
)
.
Proof
.
intros
_
.
iApply
iProto_le_base
.
Qed
.
End
proto
.
Typeclasses
Opaque
iProto_ctx
iProto_own
.
Global
Hint
Extern
0
(
environments
.
envs_entails
_
(
?x
⊑
?y
))
=>
first
[
is_evar
x
;
fail
1
|
is_evar
y
;
fail
1
|
iApply
iProto_le_refl
]
:
core
.
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment