diff --git a/pkg/addr/fmt.go b/pkg/addr/fmt.go index f534b82ea..fea603bcb 100644 --- a/pkg/addr/fmt.go +++ b/pkg/addr/fmt.go @@ -111,7 +111,7 @@ func FormatAS(as_ AS, opts ...FormatOption) string { return s } -// @ requires as_.inRange() +// @ requires as_.InRange() // @ decreases func fmtAS(as_ AS, sep string) string { if !as_.inRange() { diff --git a/pkg/addr/host.go b/pkg/addr/host.go index ce971e76c..ff10d9890 100644 --- a/pkg/addr/host.go +++ b/pkg/addr/host.go @@ -47,7 +47,7 @@ const ( HostTypeSVC ) -// @ requires isValidHostAddrType(t) +// @ requires IsValidHostAddrType(t) // @ decreases func (t HostAddrType) String() string { switch t { @@ -433,8 +433,8 @@ func (h HostSVC) Network() string { } // @ requires acc(b) -// @ requires isValidHostAddrType(htype) -// @ requires len(b) == sizeOfHostAddrType(htype) +// @ requires IsValidHostAddrType(htype) +// @ requires len(b) == SizeOfHostAddrType(htype) // @ ensures err == nil ==> res.Mem() // @ decreases func HostFromRaw(b []byte, htype HostAddrType) (res HostAddr, err error) { @@ -502,7 +502,7 @@ func HostFromIPStr(s string) (res HostAddr) { return HostFromIP(ip) } -// @ requires isValidHostAddrType(htype) +// @ requires IsValidHostAddrType(htype) // @ decreases func HostLen(htype HostAddrType) (uint8, error) { var length uint8 diff --git a/pkg/addr/host_spec.gobra b/pkg/addr/host_spec.gobra index 4108094ab..038a8db93 100644 --- a/pkg/addr/host_spec.gobra +++ b/pkg/addr/host_spec.gobra @@ -51,7 +51,7 @@ pred (h *HostSVC) Mem() { acc(h) } ghost decreases -pure func isValidHostAddrType(htype HostAddrType) bool { +pure func IsValidHostAddrType(htype HostAddrType) bool { return htype == HostTypeNone || htype == HostTypeIPv4 || htype == HostTypeIPv6 || @@ -59,13 +59,13 @@ pure func isValidHostAddrType(htype HostAddrType) bool { } ghost -requires isValidHostAddrType(htype) +requires IsValidHostAddrType(htype) ensures htype == HostTypeNone ==> res == HostLenNone ensures htype == HostTypeIPv4 ==> res == HostLenIPv4 ensures htype == HostTypeIPv6 ==> res == HostLenIPv6 ensures htype == HostTypeSVC ==> res == HostLenSVC decreases -pure func sizeOfHostAddrType(htype HostAddrType) (res int) { +pure func SizeOfHostAddrType(htype HostAddrType) (res int) { return htype == HostTypeNone ? HostLenNone : htype == HostTypeIPv4 ? HostLenIPv4 : htype == HostTypeIPv6 ? diff --git a/pkg/addr/isdas.go b/pkg/addr/isdas.go index ee5f5e296..3332b4e01 100644 --- a/pkg/addr/isdas.go +++ b/pkg/addr/isdas.go @@ -71,13 +71,13 @@ type AS uint64 // ParseAS parses an AS from a decimal (in the case of the 32bit BGP AS number // space) or ipv6-style hex (in the case of SCION-only AS numbers) string. -// @ ensures retErr == nil ==> retAs.inRange() +// @ ensures retErr == nil ==> retAs.InRange() // @ decreases func ParseAS(_as string) (retAs AS, retErr error) { return parseAS(_as, ":") } -// @ ensures retErr == nil ==> retAs.inRange() +// @ ensures retErr == nil ==> retAs.InRange() // @ decreases func parseAS(_as string, sep string) (retAs AS, retErr error) { parts := strings.Split(_as, sep) @@ -110,7 +110,7 @@ func parseAS(_as string, sep string) (retAs AS, retErr error) { return parsed, nil } -// @ ensures retErr == nil ==> retAs.inRange() +// @ ensures retErr == nil ==> retAs.InRange() // @ decreases func asParseBGP(s string) (retAs AS, retErr error) { _as, err := strconv.ParseUint(s, 10, BGPASBits) @@ -118,7 +118,7 @@ func asParseBGP(s string) (retAs AS, retErr error) { return 0, serrors.WrapStr("parsing BGP AS", err) } // (VerifiedSCION) - // The following assertions are needed to prove retAs.inRange(). + // The following assertions are needed to prove retAs.InRange(). // Gobra is not able to infer this automatically from the definition // of strconv.Exp, unless we put a postcondition saying that the // result is equal to the body. @@ -131,7 +131,7 @@ func asParseBGP(s string) (retAs AS, retErr error) { return AS(_as), nil } -// @ requires _as.inRange() +// @ requires _as.InRange() // @ decreases func (_as AS) String() string { return fmtAS(_as, ":") @@ -175,7 +175,7 @@ type IA uint64 // MustIAFrom creates an IA from the ISD and AS number. It panics if any error // is encountered. Callers must ensure that the values passed to this function // are valid. -// @ requires _as.inRange() +// @ requires _as.InRange() // @ decreases func MustIAFrom(isd ISD, _as AS) IA { ia, err := IAFrom(isd, _as) @@ -186,7 +186,7 @@ func MustIAFrom(isd ISD, _as AS) IA { } // IAFrom creates an IA from the ISD and AS number. -// @ requires _as.inRange() +// @ requires _as.InRange() // @ ensures err == nil // @ decreases func IAFrom(isd ISD, _as AS) (ia IA, err error) { diff --git a/pkg/addr/isdas_spec.gobra b/pkg/addr/isdas_spec.gobra index 3bd12dd19..701037f6e 100644 --- a/pkg/addr/isdas_spec.gobra +++ b/pkg/addr/isdas_spec.gobra @@ -67,3 +67,12 @@ pred (_as *AS) Mem() { acc(_as) } fold ia.Mem() } } + +// InRange is the ghost counterpart of the (non-exported) method AS.inRange. It is +// part of the contracts of exported members of this package, which may not +// mention non-exported members. +ghost +decreases +pure func (_as AS) InRange() bool { + return _as <= MaxAS +} diff --git a/pkg/experimental/epic/epic.go b/pkg/experimental/epic/epic.go index 77a131064..cc2597db1 100644 --- a/pkg/experimental/epic/epic.go +++ b/pkg/experimental/epic/epic.go @@ -14,7 +14,7 @@ // +gobra -// @ dup pkgInvariant acc(postInitInvariant(), _) +// @ dup pkgInvariant acc(PostInitInvariant(), _) package epic import ( @@ -51,7 +51,7 @@ var zeroInitVector /*@@@*/ [16]byte // ghost init // @ func init() { // @ fold acc(sl.Bytes(zeroInitVector[:], 0, len(zeroInitVector[:])), _) -// @ fold acc(postInitInvariant(), _) +// @ fold acc(PostInitInvariant(), _) // @ } // CreateTimestamp returns the epic timestamp, which encodes the current time (now) relative to the @@ -216,7 +216,7 @@ func initEpicMac(key []byte) (res cipher.BlockMode, reserr error) { } // @ establishPostInitInvariant() - // @ unfold acc(postInitInvariant(), _) + // @ unfold acc(PostInitInvariant(), _) // CBC-MAC = CBC-Encryption with zero initialization vector mode := cipher.NewCBCEncrypter(block, zeroInitVector[:]) return mode, nil @@ -302,7 +302,7 @@ func prepareMacInput(pktID epic.PktID, s *slayers.SCION, timestamp uint32, // @ assert forall i int :: { &inputBuffer[offset:inputLength][i] } 0 <= i && i < len(inputBuffer[offset:inputLength]) ==> // @ acc(&inputBuffer[offset:inputLength][i]) // @ establishPostInitInvariant() - // @ unfold acc(postInitInvariant(), _) + // @ unfold acc(PostInitInvariant(), _) // @ assert acc(sl.Bytes(zeroInitVector[:], 0, 16), _) // (VerifiedSCION) From the package invariant, we learn that we have a wildcard access to zeroInitVector. // Unfortunately, it is not possible to call `copy` with a wildcard amount, even though diff --git a/pkg/experimental/epic/epic_spec.gobra b/pkg/experimental/epic/epic_spec.gobra index 68bf2565c..171cd5cd3 100644 --- a/pkg/experimental/epic/epic_spec.gobra +++ b/pkg/experimental/epic/epic_spec.gobra @@ -18,7 +18,9 @@ package epic import sl "github.com/scionproto/scion/verification/utils/slices" -pred postInitInvariant() { +// The body describes the private global state of this package, so the predicate +// is closed: importing packages may hold it, but they cannot unfold it. +closed pred PostInitInvariant() { acc(&zeroInitVector) && len(zeroInitVector[:]) == 16 && acc(sl.Bytes(zeroInitVector[:], 0, len(zeroInitVector[:]))) @@ -26,7 +28,7 @@ pred postInitInvariant() { // learn the invariant established by init ghost -ensures acc(postInitInvariant(), _) +ensures acc(PostInitInvariant(), _) decreases func establishPostInitInvariant() { openDupPkgInv diff --git a/pkg/slayers/extn.go b/pkg/slayers/extn.go index 2bbffd883..2b21da187 100644 --- a/pkg/slayers/extn.go +++ b/pkg/slayers/extn.go @@ -303,7 +303,7 @@ func (h *HopByHopExtn) CanDecode() (res gopacket.LayerClass) { // @ preserves acc(h.Mem(ubuf), R20) // @ decreases func (h *HopByHopExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType { - return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in (unfolding acc(h.extnBase.Mem(ubuf), R20) in @*/ h.NextHdr /*@ ) @*/) + return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in @*/ h.NextHdr) } // @ preserves acc(h.Mem(ub), R20) @@ -313,14 +313,12 @@ func (h *HopByHopExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.Layer // @ decreases func (h *HopByHopExtn) LayerPayload( /*@ ghost ub []byte @*/ ) (res []byte /*@ , ghost start int, ghost end int @*/) { // @ unfold acc(h.Mem(ub), R20) - // @ unfold acc(h.extnBase.Mem(ub), R20) - // @ ghost base := &h.extnBase.BaseLayer + // @ ghost base := &h.BaseLayer // @ unfold acc(base.Mem(ub, h.ActualLen), R20) tmp := h.Payload // @ start = h.ActualLen // @ end = len(ub) // @ fold acc(base.Mem(ub, h.ActualLen), R20) - // @ fold acc(h.extnBase.Mem(ub), R20) // @ fold acc(h.Mem(ub), R20) return tmp /*@ , start, end @*/ } @@ -392,8 +390,7 @@ func (h *HopByHopExtn) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) // @ fold tmp.Mem(lenOptions) // @ lenOptions += 1 } - // @ fold h.extnBase.BaseLayer.Mem(data, h.extnBase.ActualLen) - // @ fold h.extnBase.Mem(data) + // @ fold h.BaseLayer.Mem(data, h.ActualLen) // @ fold h.Mem(data) return nil } @@ -411,7 +408,7 @@ func decodeHopByHopExtn(data []byte, p gopacket.PacketBuilder) (res error) { if err != nil { return err } - nextTmp := scionNextLayerTypeAfterHBH(( /*@ unfolding h.Mem(data) in (unfolding h.extnBase.Mem(data) in @*/ h.NextHdr /*@ ) @*/)) + nextTmp := scionNextLayerTypeAfterHBH(( /*@ unfolding h.Mem(data) in @*/ h.NextHdr)) // @ fold nextTmp.Mem() return p.NextDecoder(nextTmp) } @@ -452,7 +449,7 @@ func (e *EndToEndExtn) CanDecode() (res gopacket.LayerClass) { // @ preserves acc(e.Mem(ubuf), R20) // @ decreases func (e *EndToEndExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType { - return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in (unfolding acc(e.extnBase.Mem(ubuf), R20) in @*/ e.NextHdr /*@ ) @*/) + return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in @*/ e.NextHdr) } // @ preserves acc(e.Mem(ub), R20) @@ -462,14 +459,12 @@ func (e *EndToEndExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.Layer // @ decreases func (e *EndToEndExtn) LayerPayload( /*@ ghost ub []byte @*/ ) (res []byte /*@ , ghost start int, ghost end int @*/) { // @ unfold acc(e.Mem(ub), R20) - // @ unfold acc(e.extnBase.Mem(ub), R20) - // @ ghost base := &e.extnBase.BaseLayer + // @ ghost base := &e.BaseLayer // @ unfold acc(base.Mem(ub, e.ActualLen), R20) tmp := e.Payload // @ start = e.ActualLen // @ end = len(ub) // @ fold acc(base.Mem(ub, e.ActualLen), R20) - // @ fold acc(e.extnBase.Mem(ub), R20) // @ fold acc(e.Mem(ub), R20) return tmp /*@ , start, end @*/ } @@ -524,8 +519,7 @@ func (e *EndToEndExtn) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) // @ fold tmp.Mem(lenOptions) // @ lenOptions += 1 } - // @ fold e.extnBase.BaseLayer.Mem(data, e.ActualLen) - // @ fold e.extnBase.Mem(data) + // @ fold e.BaseLayer.Mem(data, e.ActualLen) // @ fold e.Mem(data) return nil } @@ -543,7 +537,7 @@ func decodeEndToEndExtn(data []byte, p gopacket.PacketBuilder) (res error) { if err != nil { return err } - nextTmp := scionNextLayerTypeAfterE2E( /*@ unfolding e.Mem(data) in (unfolding e.extnBase.Mem(data) in @*/ e.NextHdr /*@ ) @*/) + nextTmp := scionNextLayerTypeAfterE2E( /*@ unfolding e.Mem(data) in @*/ e.NextHdr) // @ fold nextTmp.Mem() return p.NextDecoder(nextTmp) } @@ -617,9 +611,8 @@ func (s *HopByHopExtnSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFee // @ fold s.NonInitMem() return err } - // @ ghost contentsLen := s.extnBase.ActualLen - // @ fold s.extnBase.BaseLayer.Mem(data, s.ActualLen) - // @ fold s.extnBase.Mem(data) + // @ ghost contentsLen := s.ActualLen + // @ fold s.BaseLayer.Mem(data, s.ActualLen) // @ fold s.Mem(data) return nil } @@ -641,7 +634,7 @@ func (s *HopByHopExtnSkipper) CanDecode() (res gopacket.LayerClass) { // @ preserves acc(h.Mem(ubuf), R20) // @ decreases func (h *HopByHopExtnSkipper) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType { - return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in (unfolding acc(h.extnBase.Mem(ubuf), R20) in @*/ h.NextHdr /*@ ) @*/) + return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in @*/ h.NextHdr) } // EndToEndExtnSkipper is a DecodingLayer which decodes an EndToEnd extension @@ -672,9 +665,8 @@ func (s *EndToEndExtnSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFee // @ fold s.NonInitMem() return err } - // @ ghost contentsLen := s.extnBase.ActualLen - // @ fold s.extnBase.BaseLayer.Mem(data, s.ActualLen) - // @ fold s.extnBase.Mem(data) + // @ ghost contentsLen := s.ActualLen + // @ fold s.BaseLayer.Mem(data, s.ActualLen) // @ fold s.Mem(data) return nil } @@ -696,5 +688,5 @@ func (s *EndToEndExtnSkipper) CanDecode() (res gopacket.LayerClass) { // @ preserves acc(e.Mem(ubuf), R20) // @ decreases func (e *EndToEndExtnSkipper) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType { - return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in (unfolding acc(e.extnBase.Mem(ubuf), R20) in @*/ e.NextHdr /*@ ) @*/) + return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in @*/ e.NextHdr) } diff --git a/pkg/slayers/extn_spec.gobra b/pkg/slayers/extn_spec.gobra index 844859f8d..1594b3aa5 100644 --- a/pkg/slayers/extn_spec.gobra +++ b/pkg/slayers/extn_spec.gobra @@ -23,20 +23,11 @@ import ( // sl "github.com/scionproto/scion/verification/utils/slices" ) -/** start of extnBase **/ - -pred (e *extnBase) NonInitMem() { - acc(e) -} - -pred (e *extnBase) Mem(ubuf []byte) { - acc(&e.NextHdr) && - acc(&e.ExtLen) && - acc(&e.ActualLen) && - e.BaseLayer.Mem(ubuf, e.ActualLen) -} - -/** end of extnBase **/ +// The memory of the (non-exported) extnBase embedded in every extension header. +// It is spelled out in the predicates below instead of being factored out into a +// predicate of extnBase: the bodies of the fully-public predicates of the +// exported extension headers may only mention exported members, and importing +// packages must be able to unfold them to reach the promoted fields. /** start of HopByHopExtn **/ pred (h *HopByHopExtn) NonInitMem() { @@ -44,7 +35,10 @@ pred (h *HopByHopExtn) NonInitMem() { } pred (h *HopByHopExtn) Mem(ubuf []byte) { - h.extnBase.Mem(ubuf) && + acc(&h.NextHdr) && + acc(&h.ExtLen) && + acc(&h.ActualLen) && + h.BaseLayer.Mem(ubuf, h.ActualLen) && acc(&h.Options) && forall i int :: { &h.Options[i] } 0 <= i && i < len(h.Options) ==> (acc(&h.Options[i]) && h.Options[i].Mem(i)) @@ -64,7 +58,6 @@ ensures s.NonInitMem() decreases func (s *HopByHopExtn) DowngradePerm(ghost ub []byte) { unfold s.Mem(ub) - unfold s.extnBase.Mem(ub) unfold s.BaseLayer.Mem(ub, s.ActualLen) fold s.NonInitMem() } @@ -80,7 +73,10 @@ pred (h *HopByHopExtnSkipper) NonInitMem() { } pred (h *HopByHopExtnSkipper) Mem(ubuf []byte) { - h.extnBase.Mem(ubuf) + acc(&h.NextHdr) && + acc(&h.ExtLen) && + acc(&h.ActualLen) && + h.BaseLayer.Mem(ubuf, h.ActualLen) } // Gobra is not able to infer that HopByHopExtnSkipper is "inheriting" @@ -100,12 +96,10 @@ ensures res === ub[start:end] decreases func (h *HopByHopExtnSkipper) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) { unfold acc(h.Mem(ub), R20) - unfold acc(h.extnBase.Mem(ub), R20) - ghost base := &h.extnBase.BaseLayer + ghost base := &h.BaseLayer res = base.LayerPayload(ub, h.ActualLen) start = h.ActualLen end = len(ub) - fold acc(h.extnBase.Mem(ub), R20) fold acc(h.Mem(ub), R20) return res, start, end } @@ -116,7 +110,6 @@ ensures s.NonInitMem() decreases func (s *HopByHopExtnSkipper) DowngradePerm(ghost ub []byte) { unfold s.Mem(ub) - unfold s.extnBase.Mem(ub) unfold s.BaseLayer.Mem(ub, s.ActualLen) fold s.NonInitMem() } @@ -132,7 +125,10 @@ pred (e *EndToEndExtn) NonInitMem() { } pred (e *EndToEndExtn) Mem(ubuf []byte) { - e.extnBase.Mem(ubuf) && + acc(&e.NextHdr) && + acc(&e.ExtLen) && + acc(&e.ActualLen) && + e.BaseLayer.Mem(ubuf, e.ActualLen) && acc(&e.Options) && forall i int :: { &e.Options[i] } 0 <= i && i < len(e.Options) ==> (acc(&e.Options[i]) && e.Options[i].Mem(i)) @@ -152,7 +148,6 @@ ensures s.NonInitMem() decreases func (s *EndToEndExtn) DowngradePerm(ghost ub []byte) { unfold s.Mem(ub) - unfold s.extnBase.Mem(ub) unfold s.BaseLayer.Mem(ub, s.ActualLen) fold s.NonInitMem() } @@ -170,7 +165,10 @@ pred (e *EndToEndExtnSkipper) NonInitMem() { } pred (e *EndToEndExtnSkipper) Mem(ubuf []byte) { - e.extnBase.Mem(ubuf) + acc(&e.NextHdr) && + acc(&e.ExtLen) && + acc(&e.ActualLen) && + e.BaseLayer.Mem(ubuf, e.ActualLen) } // Gobra is not able to infer that EndToEndExtnSkipper is "inheriting" @@ -190,12 +188,10 @@ ensures res === ub[start:end] decreases func (e *EndToEndExtnSkipper) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) { unfold acc(e.Mem(ub), R20) - unfold acc(e.extnBase.Mem(ub), R20) - ghost base := &e.extnBase.BaseLayer + ghost base := &e.BaseLayer res = base.LayerPayload(ub, e.ActualLen) start = e.ActualLen end = len(ub) - fold acc(e.extnBase.Mem(ub), R20) fold acc(e.Mem(ub), R20) return res, start, end } @@ -206,7 +202,6 @@ ensures s.NonInitMem() decreases func (s *EndToEndExtnSkipper) DowngradePerm(ghost ub []byte) { unfold s.Mem(ub) - unfold s.extnBase.Mem(ub) unfold s.BaseLayer.Mem(ub, s.ActualLen) fold s.NonInitMem() } diff --git a/pkg/slayers/path/epic/epic.go b/pkg/slayers/path/epic/epic.go index 8d33b9649..91c5de1e9 100644 --- a/pkg/slayers/path/epic/epic.go +++ b/pkg/slayers/path/epic/epic.go @@ -83,10 +83,10 @@ type Path struct { // @ preserves sl.Bytes(ubuf, 0, len(ubuf)) // @ preserves sl.Bytes(b, 0, len(b)) // @ ensures r != nil ==> r.ErrorMem() -// @ ensures !old(p.hasScionPath(ubuf)) ==> r != nil +// @ ensures !old(p.HasScionPath(ubuf)) ==> r != nil // @ ensures len(b) < old(p.LenSpec(ubuf)) ==> r != nil -// @ ensures old(p.getPHVFLen(ubuf)) != HVFLen ==> r != nil -// @ ensures old(p.getLHVFLen(ubuf)) != HVFLen ==> r != nil +// @ ensures old(p.GetPHVFLen(ubuf)) != HVFLen ==> r != nil +// @ ensures old(p.GetLHVFLen(ubuf)) != HVFLen ==> r != nil // @ decreases func (p *Path) SerializeTo(b []byte /*@, ghost ubuf []byte @*/) (r error) { if len(b) < p.Len( /*@ ubuf @*/ ) { diff --git a/pkg/slayers/path/epic/epic_spec.gobra b/pkg/slayers/path/epic/epic_spec.gobra index bdf63195f..5e8cd224f 100644 --- a/pkg/slayers/path/epic/epic_spec.gobra +++ b/pkg/slayers/path/epic/epic_spec.gobra @@ -69,7 +69,7 @@ pure func (r *Path) GetBase(ub []byte) scion.Base { ghost requires p.Mem(buf) decreases -pure func (p *Path) getPHVFLen(buf []byte) (l int) { +pure func (p *Path) GetPHVFLen(buf []byte) (l int) { return unfolding p.Mem(buf) in len(p.PHVF) } @@ -77,7 +77,7 @@ pure func (p *Path) getPHVFLen(buf []byte) (l int) { ghost requires p.Mem(buf) decreases -pure func (p *Path) getLHVFLen(buf []byte) (l int) { +pure func (p *Path) GetLHVFLen(buf []byte) (l int) { return unfolding p.Mem(buf) in len(p.LHVF) } @@ -85,7 +85,7 @@ pure func (p *Path) getLHVFLen(buf []byte) (l int) { ghost requires p.Mem(buf) decreases -pure func (p *Path) hasScionPath(buf []byte) (r bool) { +pure func (p *Path) HasScionPath(buf []byte) (r bool) { return unfolding p.Mem(buf) in p.ScionPath != nil } diff --git a/pkg/slayers/path/hopfield.go b/pkg/slayers/path/hopfield.go index 03299dbb4..735cc3d20 100644 --- a/pkg/slayers/path/hopfield.go +++ b/pkg/slayers/path/hopfield.go @@ -50,6 +50,7 @@ const expTimeUnit = MaxTTL / 256 // ~5m38s // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | MAC | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// @ comparable type HopField struct { // IngressRouterAlert flag. If the IngressRouterAlert is set, the ingress router (in // construction direction) will process the L4 payload in the packet. diff --git a/pkg/slayers/path/hopfield_spec.gobra b/pkg/slayers/path/hopfield_spec.gobra index 816768b22..ad4fbfa9c 100644 --- a/pkg/slayers/path/hopfield_spec.gobra +++ b/pkg/slayers/path/hopfield_spec.gobra @@ -30,7 +30,7 @@ pred (h *HopField) Mem() { ghost decreases -pure func ifsToIO_ifs(ifs uint16) option[io.Ifs] { +pure func IfsToIO_ifs(ifs uint16) option[io.Ifs] { return ifs == 0 ? none[io.Ifs] : some(io.Ifs{ifs}) } @@ -52,8 +52,8 @@ pure func BytesToIO_HF(raw [] byte, start int, middle int, end int) (io.HF) { unfolding sl.Bytes(raw, start, end) in let inif2 := binary.BigEndian.Uint16(raw[middle+2:middle+4]) in let egif2 := binary.BigEndian.Uint16(raw[middle+4:middle+6]) in - let op_inif2 := ifsToIO_ifs(inif2) in - let op_egif2 := ifsToIO_ifs(egif2) in + let op_inif2 := IfsToIO_ifs(inif2) in + let op_egif2 := IfsToIO_ifs(egif2) in io.HF { InIF2: op_inif2, EgIF2: op_egif2, @@ -110,8 +110,8 @@ ghost decreases pure func (h HopField) Abs() (io.HF) { return io.HF { - InIF2: ifsToIO_ifs(h.ConsIngress), - EgIF2: ifsToIO_ifs(h.ConsEgress), + InIF2: IfsToIO_ifs(h.ConsIngress), + EgIF2: IfsToIO_ifs(h.ConsEgress), HVF: AbsMac(h.Mac), } } diff --git a/pkg/slayers/path/infofield.go b/pkg/slayers/path/infofield.go index 6f9e616aa..4b99c71ff 100644 --- a/pkg/slayers/path/infofield.go +++ b/pkg/slayers/path/infofield.go @@ -42,6 +42,7 @@ const InfoLen = 8 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | Timestamp | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// @ comparable type InfoField struct { // Peer is the peering flag. If set to true, then the forwarding path is built as a peering // path, which requires special processing on the dataplane. @@ -140,12 +141,12 @@ func (inf *InfoField) SerializeTo(b []byte) (err error) { // @ requires hf.HVF == AbsMac(hfMac) // @ preserves acc(&inf.SegID) // @ ensures AbsUInfoFromUint16(inf.SegID) == -// @ old(io.upd_uinfo(AbsUInfoFromUint16(inf.SegID), hf)) +// @ old(io.Upd_uinfo(AbsUInfoFromUint16(inf.SegID), hf)) // @ decreases func (inf *InfoField) UpdateSegID(hfMac [MacLen]byte /* @, ghost hf io.HF @ */) { //@ share hfMac inf.SegID = inf.SegID ^ binary.BigEndian.Uint16(hfMac[:2]) - // @ AssumeForIO(AbsUInfoFromUint16(inf.SegID) == old(io.upd_uinfo(AbsUInfoFromUint16(inf.SegID), hf))) + // @ AssumeForIO(AbsUInfoFromUint16(inf.SegID) == old(io.Upd_uinfo(AbsUInfoFromUint16(inf.SegID), hf))) } // @ decreases diff --git a/pkg/slayers/path/path.go b/pkg/slayers/path/path.go index 2d0bdc5af..50fd787b1 100644 --- a/pkg/slayers/path/path.go +++ b/pkg/slayers/path/path.go @@ -52,7 +52,7 @@ func init() { // Type indicates the type of the path contained in the SCION header. type Type uint8 -// @ requires 0 <= t && t < maxPathType +// @ requires 0 <= t && t < MaxPathType // @ preserves acc(PkgMem(), R20) // @ decreases func (t Type) String() string { @@ -148,7 +148,7 @@ type Metadata struct { // RegisterPath registers a new SCION path type globally. // The PathType passed in must be unique, or a runtime panic will occur. -// @ requires 0 <= pathMeta.Type && pathMeta.Type < maxPathType +// @ requires 0 <= pathMeta.Type && pathMeta.Type < MaxPathType // @ requires PkgMem() // @ requires RegisteredTypes().DoesNotContain(int64(pathMeta.Type)) // @ requires pathMeta.New implements NewPathSpec @@ -186,7 +186,7 @@ func StrictDecoding(strict bool) { } // NewPath returns a new path object of pathType. -// @ requires 0 <= pathType && pathType < maxPathType +// @ requires 0 <= pathType && pathType < MaxPathType // @ requires acc(PkgMem(), _) // @ ensures e != nil ==> e.ErrorMem() // @ ensures e == nil ==> p != nil && p.NonInitMem() diff --git a/pkg/slayers/path/path_spec.gobra b/pkg/slayers/path/path_spec.gobra index b22031a19..9f41bb421 100644 --- a/pkg/slayers/path/path_spec.gobra +++ b/pkg/slayers/path/path_spec.gobra @@ -64,11 +64,16 @@ ghost const MaxPathType = maxPathType ghost decreases +// The body mentions the package's private state, so it is hidden from importers, +// which only rely on the abstract set returned here. +closed pure func RegisteredTypes() monoset.BoundedMonotonicSet { return registeredKeys } -pred PkgMem() { +// PkgMem describes the private global state of this package. Importing packages +// may hold (fractions of) this predicate, but they cannot unfold it. +closed pred PkgMem() { acc(®isteredPaths) && acc(&strictDecoding) && registeredKeys.Inv() && @@ -81,18 +86,20 @@ pred PkgMem() { } ghost -requires 0 <= t && t < maxPathType +requires 0 <= t && t < MaxPathType requires PkgMem() decreases +closed pure func Registered(t Type) (res bool) { return unfolding PkgMem() in registeredPaths[t].inUse } ghost -requires 0 <= t && t < maxPathType +requires 0 <= t && t < MaxPathType requires PkgMem() decreases +closed pure func GetType(t Type) (res Metadata) { return unfolding PkgMem() in registeredPaths[t].Metadata @@ -101,6 +108,7 @@ pure func GetType(t Type) (res Metadata) { ghost requires PkgMem() decreases +closed pure func IsStrictDecoding() (b bool) { return unfolding PkgMem() in strictDecoding } diff --git a/pkg/slayers/path/scion/base.go b/pkg/slayers/path/scion/base.go index 1e0b48d53..6e6f8907e 100644 --- a/pkg/slayers/path/scion/base.go +++ b/pkg/slayers/path/scion/base.go @@ -66,6 +66,7 @@ func RegisterPath() { } // Base holds the basic information that is used by both raw and fully decoded paths. +// @ comparable type Base struct { // PathMeta is the SCION path meta header. It is always instantiated when // decoding a path from bytes. @@ -241,6 +242,7 @@ func (s *Base) Type() (t path.Type) { } // MetaHdr is the PathMetaHdr of a SCION (data-plane) path type. +// @ comparable type MetaHdr struct { CurrINF uint8 CurrHF uint8 diff --git a/pkg/slayers/path/scion/info_hop_setter_lemmas.gobra b/pkg/slayers/path/scion/info_hop_setter_lemmas.gobra index 886d6c3d2..6de08f2b9 100644 --- a/pkg/slayers/path/scion/info_hop_setter_lemmas.gobra +++ b/pkg/slayers/path/scion/info_hop_setter_lemmas.gobra @@ -224,7 +224,7 @@ requires SegLen * path.HopLen == len(hopfields) requires sl.Bytes(hopfields, 0, len(hopfields)) decreases pure func CurrSegWithInfo(hopfields []byte, currHfIdx int, SegLen int, inf io.AbsInfoField) io.Seg { - return segment(hopfields, 0, currHfIdx, inf.AInfo, inf.UInfo, inf.ConsDir, inf.Peer, SegLen) + return AbsSegment(hopfields, 0, currHfIdx, inf.AInfo, inf.UInfo, inf.ConsDir, inf.Peer, SegLen) } @@ -580,9 +580,9 @@ pure func BytesStoreCurrSeg(hopfields []byte, currHfIdx int, segLen int, inf io. let currHfEnd := currHfStart + path.HopLen in len(currseg.Future) > 0 && currseg.Future[0] == path.BytesToIO_HF(hopfields[currHfStart:currHfEnd], 0, 0, path.HopLen) && - currseg.Future[1:] == hopFields(hopfields[currHfEnd:], 0, 0, (segLen - currHfIdx - 1)) && - currseg.Past == segPast(hopFields(hopfields[:currHfStart], 0, 0, currHfIdx)) && - currseg.History == segHistory(hopFields(hopfields[:currHfStart], 0, 0, currHfIdx)) && + currseg.Future[1:] == AbsHopFields(hopfields[currHfEnd:], 0, 0, (segLen - currHfIdx - 1)) && + currseg.Past == AbsSegPast(AbsHopFields(hopfields[:currHfStart], 0, 0, currHfIdx)) && + currseg.History == AbsSegHistory(AbsHopFields(hopfields[:currHfStart], 0, 0, currHfIdx)) && currseg.AInfo == inf.AInfo && currseg.UInfo == inf.UInfo && currseg.ConsDir == inf.ConsDir && diff --git a/pkg/slayers/path/scion/raw.go b/pkg/slayers/path/scion/raw.go index 9947c338e..5cc1562e6 100644 --- a/pkg/slayers/path/scion/raw.go +++ b/pkg/slayers/path/scion/raw.go @@ -223,10 +223,10 @@ func (s *Raw) ToDecoded( /*@ ghost ubuf []byte @*/ ) (d *Decoded, err error) { // @ requires sl.Bytes(ubuf, 0, len(ubuf)) // pres for IO: // @ requires s.GetBase(ubuf).EqAbsHeader(ubuf) -// @ requires validPktMetaHdr(ubuf) -// @ requires s.absPkt(ubuf).PathNotFullyTraversed() +// @ requires ValidPktMetaHdr(ubuf) +// @ requires s.AbsPkt(ubuf).PathNotFullyTraversed() // @ requires s.GetBase(ubuf).IsXoverSpec() ==> -// @ s.absPkt(ubuf).LeftSeg != none[io.Seg] +// @ s.AbsPkt(ubuf).LeftSeg != none[io.Seg] // @ ensures sl.Bytes(ubuf, 0, len(ubuf)) // @ ensures old(unfolding s.Mem(ubuf) in unfolding // @ s.Base.Mem() in (s.NumINF <= 0 || int(s.PathMeta.CurrHF) >= s.NumHops-1)) ==> r != nil @@ -235,11 +235,11 @@ func (s *Raw) ToDecoded( /*@ ghost ubuf []byte @*/ ) (d *Decoded, err error) { // @ ensures r != nil ==> r.ErrorMem() // post for IO: // @ ensures r == nil ==> -// @ s.GetBase(ubuf).EqAbsHeader(ubuf) && validPktMetaHdr(ubuf) +// @ s.GetBase(ubuf).EqAbsHeader(ubuf) && ValidPktMetaHdr(ubuf) // @ ensures r == nil && old(s.GetBase(ubuf).IsXoverSpec()) ==> -// @ s.absPkt(ubuf) == AbsXover(old(s.absPkt(ubuf))) +// @ s.AbsPkt(ubuf) == AbsXover(old(s.AbsPkt(ubuf))) // @ ensures r == nil && !old(s.GetBase(ubuf).IsXoverSpec()) ==> -// @ s.absPkt(ubuf) == AbsIncPath(old(s.absPkt(ubuf))) +// @ s.AbsPkt(ubuf) == AbsIncPath(old(s.AbsPkt(ubuf))) // (VerifiedSCION) the following post is technically redundant, // as it conveys information that could, in principle, be conveyed // with the previous posts. We should at some point revisit all @@ -249,7 +249,7 @@ func (s *Raw) ToDecoded( /*@ ghost ubuf []byte @*/ ) (d *Decoded, err error) { // @ decreases func (s *Raw) IncPath( /*@ ghost ubuf []byte @*/ ) (r error) { //@ unfold s.Mem(ubuf) - //@ reveal validPktMetaHdr(ubuf) + //@ reveal ValidPktMetaHdr(ubuf) //@ unfold acc(s.Base.Mem(), R56) //@ oldCurrInfIdx := int(s.PathMeta.CurrINF) //@ oldCurrHfIdx := int(s.PathMeta.CurrHF) @@ -277,7 +277,7 @@ func (s *Raw) IncPath( /*@ ghost ubuf []byte @*/ ) (r error) { //@ WidenMidSeg(ubuf, oldCurrInfIdx + 2, oldSegs, MetaLen, MetaLen, len(ubuf)) //@ WidenRightSeg(ubuf, oldCurrInfIdx - 1, oldSegs, MetaLen, MetaLen, len(ubuf)) //@ LenCurrSeg(tail, oldOffset, oldCurrInfIdx, oldHfIdxSeg, oldSegLen) - //@ oldAbsPkt := reveal s.absPkt(ubuf) + //@ oldAbsPkt := reveal s.AbsPkt(ubuf) //@ sl.SplitRange_Bytes(ubuf, 0, MetaLen, HalfPerm) //@ unfold acc(s.Base.Mem(), R2) err := s.PathMeta.SerializeTo(s.Raw[:MetaLen]) @@ -294,7 +294,7 @@ func (s *Raw) IncPath( /*@ ghost ubuf []byte @*/ ) (r error) { //@ sl.CombineRange_Bytes(ubuf, 0, MetaLen, HalfPerm) //@ ValidPktMetaHdrSublice(ubuf, MetaLen) //@ assert s.EqAbsHeader(ubuf) == s.PathMeta.EqAbsHeader(ubuf) - //@ assert reveal validPktMetaHdr(ubuf) + //@ assert reveal ValidPktMetaHdr(ubuf) //@ currInfIdx := int(s.PathMeta.CurrINF) //@ currHfIdx := int(s.PathMeta.CurrHF) //@ assert currHfIdx == oldCurrHfIdx + 1 @@ -306,7 +306,7 @@ func (s *Raw) IncPath( /*@ ghost ubuf []byte @*/ ) (r error) { //@ WidenLeftSeg(ubuf, oldCurrInfIdx + 1, oldSegs, MetaLen, MetaLen, len(ubuf)) //@ WidenMidSeg(ubuf, oldCurrInfIdx + 2, oldSegs, MetaLen, MetaLen, len(ubuf)) //@ WidenRightSeg(ubuf, oldCurrInfIdx - 1, oldSegs, MetaLen, MetaLen, len(ubuf)) - //@ assert reveal s.absPkt(ubuf) == AbsIncPath(oldAbsPkt) + //@ assert reveal s.AbsPkt(ubuf) == AbsIncPath(oldAbsPkt) //@ } else { //@ segLen := oldSegs.LengthOfCurrSeg(currHfIdx) //@ prevSegLen := oldSegs.LengthOfPrevSeg(currHfIdx) @@ -321,7 +321,7 @@ func (s *Raw) IncPath( /*@ ghost ubuf []byte @*/ ) (r error) { //@ WidenLeftSeg(ubuf, currInfIdx + 1, oldSegs, MetaLen, MetaLen, len(ubuf)) //@ WidenMidSeg(ubuf, currInfIdx + 2, oldSegs, MetaLen, MetaLen, len(ubuf)) //@ WidenRightSeg(ubuf, currInfIdx - 1, oldSegs, MetaLen, MetaLen, len(ubuf)) - //@ assert reveal s.absPkt(ubuf) == AbsXover(oldAbsPkt) + //@ assert reveal s.AbsPkt(ubuf) == AbsXover(oldAbsPkt) //@ } //@ fold acc(sl.Bytes(tail, 0, len(tail)), R50) @@ -392,23 +392,23 @@ func (s *Raw) GetCurrentInfoField( /*@ ghost ubuf []byte @*/ ) (res path.InfoFie // @ requires sl.Bytes(ubuf, 0, len(ubuf)) // @ requires acc(s.Mem(ubuf), R20) // pres for IO: -// @ requires validPktMetaHdr(ubuf) +// @ requires ValidPktMetaHdr(ubuf) // @ requires s.GetBase(ubuf).EqAbsHeader(ubuf) // @ ensures acc(s.Mem(ubuf), R20) // @ ensures sl.Bytes(ubuf, 0, len(ubuf)) // @ ensures r != nil ==> r.ErrorMem() // posts for IO: // @ ensures r == nil ==> -// @ validPktMetaHdr(ubuf) && s.GetBase(ubuf).EqAbsHeader(ubuf) +// @ ValidPktMetaHdr(ubuf) && s.GetBase(ubuf).EqAbsHeader(ubuf) // @ ensures r == nil && idx == int(old(s.GetCurrINF(ubuf))) ==> -// @ let oldPkt := old(s.absPkt(ubuf)) in +// @ let oldPkt := old(s.AbsPkt(ubuf)) in // @ let newPkt := oldPkt.UpdateInfoField(info.ToAbsInfoField()) in -// @ s.absPkt(ubuf) == newPkt +// @ s.AbsPkt(ubuf) == newPkt // @ decreases // @ #backend[exhaleMode(1)] func (s *Raw) SetInfoField(info path.InfoField, idx int /*@, ghost ubuf []byte @*/) (r error) { //@ share info - //@ reveal validPktMetaHdr(ubuf) + //@ reveal ValidPktMetaHdr(ubuf) //@ unfold acc(s.Mem(ubuf), R50) //@ unfold acc(s.Base.Mem(), R50) //@ currInfIdx := int(s.PathMeta.CurrINF) @@ -443,21 +443,21 @@ func (s *Raw) SetInfoField(info path.InfoField, idx int /*@, ghost ubuf []byte @ //@ MidSegEquality(ubuf, currInfIdx+2, segLens) //@ RightSegEquality(ubuf, currInfIdx-1, segLens) //@ } - //@ reveal s.absPkt(ubuf) + //@ reveal s.AbsPkt(ubuf) //@ sl.SplitRange_Bytes(ubuf[:hopfieldOffset], infOffset, infOffset+path.InfoLen, R40) //@ sl.SplitRange_Bytes(ubuf, infOffset, infOffset+path.InfoLen, HalfPerm-R40) ret := info.SerializeTo(s.Raw[infOffset : infOffset+path.InfoLen]) //@ sl.CombineRange_Bytes(ubuf[:hopfieldOffset], infOffset, infOffset+path.InfoLen, R40) //@ sl.CombineRange_Bytes(ubuf, infOffset, infOffset+path.InfoLen, HalfPerm-R40) //@ ValidPktMetaHdrSublice(ubuf, MetaLen) - //@ assert reveal validPktMetaHdr(ubuf) + //@ assert reveal ValidPktMetaHdr(ubuf) //@ ghost if idx == currInfIdx { //@ CurrSegEquality(ubuf, offset, currInfIdx, hfIdxSeg, segLen) //@ UpdateCurrSegInfo(hopfields, hfIdxSeg, segLen, oldInfo, newInfo) //@ LeftSegEquality(ubuf, currInfIdx+1, segLens) //@ MidSegEquality(ubuf, currInfIdx+2, segLens) //@ RightSegEquality(ubuf, currInfIdx-1, segLens) - //@ reveal s.absPkt(ubuf) + //@ reveal s.AbsPkt(ubuf) //@ } //@ CombineBytesFromSegments(ubuf, segLens, R40) //@ CombineBytesFromInfoFields(ubuf, s.NumINF, segLens, HalfPerm) @@ -527,20 +527,20 @@ func (s *Raw) GetCurrentHopField( /*@ ghost ubuf []byte @*/ ) (res path.HopField // @ requires acc(s.Mem(ubuf), R20) // @ requires sl.Bytes(ubuf, 0, len(ubuf)) // pres for IO: -// @ requires validPktMetaHdr(ubuf) +// @ requires ValidPktMetaHdr(ubuf) // @ requires s.GetBase(ubuf).EqAbsHeader(ubuf) -// @ requires s.absPkt(ubuf).PathNotFullyTraversed() +// @ requires s.AbsPkt(ubuf).PathNotFullyTraversed() // @ ensures acc(s.Mem(ubuf), R20) // @ ensures sl.Bytes(ubuf, 0, len(ubuf)) // @ ensures r != nil ==> r.ErrorMem() // posts for IO: // @ ensures r == nil ==> -// @ validPktMetaHdr(ubuf) && +// @ ValidPktMetaHdr(ubuf) && // @ s.GetBase(ubuf).EqAbsHeader(ubuf) // @ ensures r == nil && idx == int(old(s.GetCurrHF(ubuf))) ==> -// @ let oldPkt := old(s.absPkt(ubuf)) in +// @ let oldPkt := old(s.AbsPkt(ubuf)) in // @ let newPkt := oldPkt.UpdateHopField(hop.Abs()) in -// @ s.absPkt(ubuf) == newPkt +// @ s.AbsPkt(ubuf) == newPkt // @ decreases // @ #backend[exhaleMode(1)] func (s *Raw) SetHopField(hop path.HopField, idx int /*@, ghost ubuf []byte @*/) (r error) { @@ -552,7 +552,7 @@ func (s *Raw) SetHopField(hop path.HopField, idx int /*@, ghost ubuf []byte @*/) // https://github.com/viperproject/gobra/issues/192 //@ assume 0 <= tmpHopField.ConsIngress && 0 <= tmpHopField.ConsEgress //@ fold acc(tmpHopField.Mem(), R9) - //@ reveal validPktMetaHdr(ubuf) + //@ reveal ValidPktMetaHdr(ubuf) //@ unfold acc(s.Mem(ubuf), R50) //@ unfold acc(s.Base.Mem(), R50) //@ ghost currInfIdx := int(s.PathMeta.CurrINF) @@ -586,7 +586,7 @@ func (s *Raw) SetHopField(hop path.HopField, idx int /*@, ghost ubuf []byte @*/) //@ LeftSegEquality(ubuf, currInfIdx+1, segLens) //@ MidSegEquality(ubuf, currInfIdx+2, segLens) //@ RightSegEquality(ubuf, currInfIdx-1, segLens) - //@ reveal s.absPkt(ubuf) + //@ reveal s.AbsPkt(ubuf) //@ SplitHopfields(currHopfields, hfIdxSeg, segLen, R0) //@ EstablishBytesStoreCurrSeg(currHopfields, hfIdxSeg, segLen, inf) //@ SplitHopfields(currHopfields, hfIdxSeg, segLen, R0) @@ -598,7 +598,7 @@ func (s *Raw) SetHopField(hop path.HopField, idx int /*@, ghost ubuf []byte @*/) ret := tmpHopField.SerializeTo(s.Raw[hopOffset : hopOffset+path.HopLen]) //@ sl.CombineRange_Bytes(ubuf, hopOffset, hopOffset+path.HopLen, HalfPerm) //@ ValidPktMetaHdrSublice(ubuf, MetaLen) - //@ assert reveal validPktMetaHdr(ubuf) + //@ assert reveal ValidPktMetaHdr(ubuf) //@ ghost if idx == currHfIdx { //@ CombineHopfields(currHopfields, hfIdxSeg, segLen, R0) //@ EstablishBytesStoreCurrSeg(currHopfields, hfIdxSeg, segLen, inf) @@ -607,9 +607,9 @@ func (s *Raw) SetHopField(hop path.HopField, idx int /*@, ghost ubuf []byte @*/) //@ LeftSegEquality(ubuf, currInfIdx+1, segLens) //@ MidSegEquality(ubuf, currInfIdx+2, segLens) //@ RightSegEquality(ubuf, currInfIdx-1, segLens) - //@ reveal s.absPkt(ubuf) - //@ assert s.absPkt(ubuf).CurrSeg.Future == - //@ seq[io.HF]{tmpHopField.Abs()} ++ old(s.absPkt(ubuf).CurrSeg.Future[1:]) + //@ reveal s.AbsPkt(ubuf) + //@ assert s.AbsPkt(ubuf).CurrSeg.Future == + //@ seq[io.HF]{tmpHopField.Abs()} ++ old(s.AbsPkt(ubuf).CurrSeg.Future[1:]) //@ } else { //@ sl.CombineRange_Bytes(ubuf[offset:offset+segLen*path.HopLen], hfIdxSeg*path.HopLen, //@ (hfIdxSeg+1)*path.HopLen, HalfPerm) diff --git a/pkg/slayers/path/scion/raw_spec.gobra b/pkg/slayers/path/scion/raw_spec.gobra index 218a6a38e..a0f651de6 100644 --- a/pkg/slayers/path/scion/raw_spec.gobra +++ b/pkg/slayers/path/scion/raw_spec.gobra @@ -223,31 +223,31 @@ requires offset + path.HopLen * segLen <= len(raw) requires sl.Bytes(raw, 0, len(raw)) ensures len(res) == segLen - currHfIdx decreases segLen - currHfIdx -pure func hopFields( +pure func AbsHopFields( raw []byte, offset int, currHfIdx int, segLen int) (res seq[io.HF]) { return currHfIdx == segLen ? seq[io.HF]{} : let hf := path.BytesToIO_HF(raw, 0, offset + path.HopLen * currHfIdx, len(raw)) in - seq[io.HF]{hf} ++ hopFields(raw, offset, currHfIdx + 1, segLen) + seq[io.HF]{hf} ++ AbsHopFields(raw, offset, currHfIdx + 1, segLen) } ghost ensures len(res) == len(hopfields) decreases len(hopfields) -pure func segPast(hopfields seq[io.HF]) (res seq[io.HF]) { +pure func AbsSegPast(hopfields seq[io.HF]) (res seq[io.HF]) { return len(hopfields) == 0 ? seq[io.HF]{} : - seq[io.HF]{hopfields[len(hopfields) - 1]} ++ segPast( + seq[io.HF]{hopfields[len(hopfields) - 1]} ++ AbsSegPast( hopfields[:len(hopfields) - 1]) } ghost ensures len(res) == len(hopfields) decreases len(hopfields) -pure func segHistory(hopfields seq[io.HF]) (res seq[io.AHI]) { +pure func AbsSegHistory(hopfields seq[io.HF]) (res seq[io.AHI]) { return len(hopfields) == 0 ? seq[io.AHI]{} : - seq[io.AHI]{hopfields[len(hopfields) - 1].Toab()} ++ segHistory( + seq[io.AHI]{hopfields[len(hopfields) - 1].Toab()} ++ AbsSegHistory( hopfields[:len(hopfields) - 1]) } @@ -261,7 +261,7 @@ ensures len(res.Future) == segLen - currHfIdx ensures len(res.History) == currHfIdx ensures len(res.Past) == currHfIdx decreases -pure func segment(raw []byte, +pure func AbsSegment(raw []byte, offset int, currHfIdx int, ainfo io.Ainfo, @@ -269,15 +269,15 @@ pure func segment(raw []byte, consDir bool, peer bool, segLen int) (res io.Seg) { - return let hopfields := hopFields(raw, offset, 0, segLen) in + return let hopfields := AbsHopFields(raw, offset, 0, segLen) in io.Seg { AInfo: ainfo, UInfo: uinfo, ConsDir: consDir, Peer: peer, - Past: segPast(hopfields[:currHfIdx]), + Past: AbsSegPast(hopfields[:currHfIdx]), Future: hopfields[currHfIdx:], - History: segHistory(hopfields[:currHfIdx]), + History: AbsSegHistory(hopfields[:currHfIdx]), } } @@ -304,7 +304,7 @@ pure func CurrSeg(raw []byte, let consDir := path.ConsDir(raw, currInfIdx, headerOffset) in let peer := path.Peer(raw, currInfIdx, headerOffset) in let uinfo := path.AbsUinfo(raw, currInfIdx, headerOffset) in - segment(raw, offset, currHfIdx, ainfo, uinfo, consDir, peer, segLen) + AbsSegment(raw, offset, currHfIdx, ainfo, uinfo, consDir, peer, segLen) } ghost @@ -373,11 +373,11 @@ pure func MidSeg( ghost opaque requires sl.Bytes(raw, 0, len(raw)) -requires validPktMetaHdr(raw) +requires ValidPktMetaHdr(raw) decreases // TODO: rename this to View() -pure func (s *Raw) absPkt(raw []byte) (res io.Pkt) { - return let _ := reveal validPktMetaHdr(raw) in +pure func (s *Raw) AbsPkt(raw []byte) (res io.Pkt) { + return let _ := reveal ValidPktMetaHdr(raw) in let metaHdr := RawBytesToMetaHdr(raw) in let currInfIdx := int(metaHdr.CurrINF) in let currHfIdx := int(metaHdr.CurrHF) in @@ -424,7 +424,7 @@ ghost opaque requires sl.Bytes(raw, 0, len(raw)) decreases -pure func validPktMetaHdr(raw []byte) bool { +pure func ValidPktMetaHdr(raw []byte) bool { return MetaLen <= len(raw) && let metaHdr := RawBytesToMetaHdr(raw) in let seg1 := int(metaHdr.SegLen[0]) in @@ -445,8 +445,8 @@ ensures RawBytesToMetaHdr(raw) == RawBytesToMetaHdr(raw[:idx]) ensures RawBytesToBase(raw) == RawBytesToBase(raw[:idx]) decreases func ValidPktMetaHdrSublice(raw []byte, idx int) { - reveal validPktMetaHdr(raw) - reveal validPktMetaHdr(raw[:idx]) + reveal ValidPktMetaHdr(raw) + reveal ValidPktMetaHdr(raw[:idx]) unfold acc(sl.Bytes(raw, 0, len(raw)), R56) unfold acc(sl.Bytes(raw[:idx], 0, idx), R56) assert forall i int :: { &raw[:MetaLen][i] } 0 <= i && i < MetaLen ==> @@ -462,7 +462,7 @@ requires s.GetBase(ub).Valid() requires s.GetBase(ub).EqAbsHeader(ub) ensures acc(sl.Bytes(ub, 0, len(ub)), R55) ensures acc(s.Mem(ub), R54) -ensures validPktMetaHdr(ub) +ensures ValidPktMetaHdr(ub) ensures s.GetBase(ub).EqAbsHeader(ub) decreases func (s *Raw) EstablishValidPktMetaHdr(ghost ub []byte) { @@ -477,7 +477,7 @@ func (s *Raw) EstablishValidPktMetaHdr(ghost ub []byte) { assert 0 < seg1 assert s.GetBase(ub).NumsCompatibleWithSegLen() assert PktLen(segs, MetaLen) <= len(ub) - assert reveal validPktMetaHdr(ub) + assert reveal ValidPktMetaHdr(ub) fold acc(s.Base.Mem(), R56) fold acc(s.Mem(ub), R55) } @@ -491,7 +491,7 @@ pure func AbsXover(oldPkt io.Pkt) (newPkt io.Pkt) { get(oldPkt.LeftSeg), oldPkt.MidSeg, oldPkt.RightSeg, - some(absIncPathSeg(oldPkt.CurrSeg)), + some(AbsIncPathSeg(oldPkt.CurrSeg)), } } @@ -500,7 +500,7 @@ requires oldPkt.PathNotFullyTraversed() decreases pure func AbsIncPath(oldPkt io.Pkt) (newPkt io.Pkt) { return io.Pkt { - absIncPathSeg(oldPkt.CurrSeg), + AbsIncPathSeg(oldPkt.CurrSeg), oldPkt.LeftSeg, oldPkt.MidSeg, oldPkt.RightSeg, @@ -510,7 +510,7 @@ pure func AbsIncPath(oldPkt io.Pkt) (newPkt io.Pkt) { ghost requires len(currseg.Future) > 0 decreases -pure func absIncPathSeg(currseg io.Seg) io.Seg { +pure func AbsIncPathSeg(currseg io.Seg) io.Seg { return io.Seg { AInfo: currseg.AInfo, UInfo: currseg.UInfo, @@ -594,12 +594,12 @@ ghost preserves acc(s.Mem(ubuf), R55) preserves s.IsLastHopSpec(ubuf) preserves acc(sl.Bytes(ubuf, 0, len(ubuf)), R56) -preserves validPktMetaHdr(ubuf) +preserves ValidPktMetaHdr(ubuf) preserves s.GetBase(ubuf).EqAbsHeader(ubuf) -ensures len(s.absPkt(ubuf).CurrSeg.Future) == 1 +ensures len(s.AbsPkt(ubuf).CurrSeg.Future) == 1 decreases func (s *Raw) LastHopLemma(ubuf []byte) { - reveal validPktMetaHdr(ubuf) + reveal ValidPktMetaHdr(ubuf) metaHdr := RawBytesToMetaHdr(ubuf) currInfIdx := int(metaHdr.CurrINF) currHfIdx := int(metaHdr.CurrHF) @@ -611,7 +611,7 @@ func (s *Raw) LastHopLemma(ubuf []byte) { prevSegLen := segs.LengthOfPrevSeg(currHfIdx) numINF := segs.NumInfoFields() offset := HopFieldOffset(numINF, prevSegLen, MetaLen) - pkt := reveal s.absPkt(ubuf) + pkt := reveal s.AbsPkt(ubuf) assert pkt.CurrSeg == reveal CurrSeg(ubuf, offset, currInfIdx, currHfIdx - prevSegLen, segLen, MetaLen) assert len(pkt.CurrSeg.Future) == 1 } @@ -620,15 +620,15 @@ ghost preserves acc(s.Mem(ubuf), R55) preserves s.GetBase(ubuf).IsXoverSpec() preserves acc(sl.Bytes(ubuf, 0, len(ubuf)), R56) -preserves validPktMetaHdr(ubuf) +preserves ValidPktMetaHdr(ubuf) preserves s.GetBase(ubuf).EqAbsHeader(ubuf) -ensures s.absPkt(ubuf).LeftSeg != none[io.Seg] -ensures len(s.absPkt(ubuf).CurrSeg.Future) == 1 -ensures len(get(s.absPkt(ubuf).LeftSeg).Future) > 0 -ensures len(get(s.absPkt(ubuf).LeftSeg).History) == 0 +ensures s.AbsPkt(ubuf).LeftSeg != none[io.Seg] +ensures len(s.AbsPkt(ubuf).CurrSeg.Future) == 1 +ensures len(get(s.AbsPkt(ubuf).LeftSeg).Future) > 0 +ensures len(get(s.AbsPkt(ubuf).LeftSeg).History) == 0 decreases func (s *Raw) XoverLemma(ubuf []byte) { - reveal validPktMetaHdr(ubuf) + reveal ValidPktMetaHdr(ubuf) metaHdr := RawBytesToMetaHdr(ubuf) currInfIdx := int(metaHdr.CurrINF) currHfIdx := int(metaHdr.CurrHF) @@ -640,12 +640,12 @@ func (s *Raw) XoverLemma(ubuf []byte) { prevSegLen := segs.LengthOfPrevSeg(currHfIdx) numINF := segs.NumInfoFields() offset := HopFieldOffset(numINF, prevSegLen, MetaLen) - pkt := reveal s.absPkt(ubuf) + pkt := reveal s.AbsPkt(ubuf) assert pkt.CurrSeg == reveal CurrSeg(ubuf, offset, currInfIdx, currHfIdx - prevSegLen, segLen, MetaLen) assert pkt.LeftSeg == reveal LeftSeg(ubuf, currInfIdx + 1, segs, MetaLen) assert len(pkt.CurrSeg.Future) == 1 assert pkt.LeftSeg != none[io.Seg] - assert len(get(s.absPkt(ubuf).LeftSeg).History) == 0 + assert len(get(s.AbsPkt(ubuf).LeftSeg).History) == 0 assert len(get(pkt.LeftSeg).Future) > 0 } @@ -672,18 +672,18 @@ pure func (s *Raw) EqAbsInfoField(pkt io.Pkt, info io.AbsInfoField) bool { ghost preserves acc(s.Mem(ubuf), R53) preserves acc(sl.Bytes(ubuf, 0, len(ubuf)), R53) -preserves validPktMetaHdr(ubuf) +preserves ValidPktMetaHdr(ubuf) preserves s.GetBase(ubuf).EqAbsHeader(ubuf) -preserves s.absPkt(ubuf).PathNotFullyTraversed() +preserves s.AbsPkt(ubuf).PathNotFullyTraversed() preserves s.GetBase(ubuf).ValidCurrInfSpec() preserves s.GetBase(ubuf).ValidCurrHfSpec() preserves s.CorrectlyDecodedInf(ubuf, info) preserves s.CorrectlyDecodedHf(ubuf, hop) -ensures s.EqAbsInfoField(s.absPkt(ubuf), info.ToAbsInfoField()) -ensures s.EqAbsHopField(s.absPkt(ubuf), hop.Abs()) +ensures s.EqAbsInfoField(s.AbsPkt(ubuf), info.ToAbsInfoField()) +ensures s.EqAbsHopField(s.AbsPkt(ubuf), hop.Abs()) decreases func (s *Raw) DecodingLemma(ubuf []byte, info path.InfoField, hop path.HopField) { - assert reveal validPktMetaHdr(ubuf) + assert reveal ValidPktMetaHdr(ubuf) metaHdr := RawBytesToMetaHdr(ubuf) currInfIdx := int(metaHdr.CurrINF) currHfIdx := int(metaHdr.CurrHF) @@ -702,7 +702,7 @@ func (s *Raw) DecodingLemma(ubuf []byte, info path.InfoField, hop path.HopField) currSeg := reveal CurrSeg(ubuf, offset, currInfIdx, hfIdxSeg, segLen, MetaLen) HopsFromPrefixOfRawMatchPrefixOfHops(ubuf, offset, 0, segLen, hfIdxSeg) - pktView := reveal s.absPkt(ubuf) + pktView := reveal s.AbsPkt(ubuf) infoView := info.ToAbsInfoField() // assertions for proving s.EqAbsInfoField(pktView, infoView) @@ -760,12 +760,12 @@ requires 0 <= currInfIdx && currInfIdx < 3 preserves acc(sl.Bytes(raw, 0, len(raw)), R56) preserves len(CurrSeg(raw, offset, currInfIdx, currHfIdx, segLen, 0).Future) > 0 ensures CurrSeg(raw, offset, currInfIdx, currHfIdx + 1, segLen, 0) == - absIncPathSeg(CurrSeg(raw, offset, currInfIdx, currHfIdx, segLen, 0)) + AbsIncPathSeg(CurrSeg(raw, offset, currInfIdx, currHfIdx, segLen, 0)) decreases func IncCurrSeg(raw []byte, offset int, currInfIdx int, currHfIdx int, segLen int) { currseg := reveal CurrSeg(raw, offset, currInfIdx, currHfIdx, segLen, 0) incseg := reveal CurrSeg(raw, offset, currInfIdx, currHfIdx + 1, segLen, 0) - hf := hopFields(raw, offset, 0, segLen) + hf := AbsHopFields(raw, offset, 0, segLen) hfPast := hf[:currHfIdx + 1] assert hfPast[:len(hfPast) - 1] == hf[:currHfIdx] assert currseg.AInfo == incseg.AInfo @@ -775,7 +775,7 @@ func IncCurrSeg(raw []byte, offset int, currInfIdx int, currHfIdx int, segLen in assert seq[io.HF]{currseg.Future[0]} ++ currseg.Past == incseg.Past assert currseg.Future[1:] == incseg.Future assert seq[io.AHI]{currseg.Future[0].Toab()} ++ currseg.History == incseg.History - assert incseg == absIncPathSeg(currseg) + assert incseg == AbsIncPathSeg(currseg) } ghost @@ -853,7 +853,7 @@ ensures let offset := HopFieldOffset(numInf, prevSegLen, 0) in let currseg := CurrSeg(raw, offset, currInfIdx, currHfIdx - prevSegLen, segLen, 0) in len(currseg.Future) > 0 && - get(RightSeg(raw, currInfIdx, segs, 0)) == absIncPathSeg(currseg) + get(RightSeg(raw, currInfIdx, segs, 0)) == AbsIncPathSeg(currseg) decreases func XoverRightSeg(raw []byte, currInfIdx int, currHfIdx int, segs io.SegLens) { prevSegLen := segs.LengthOfPrevSeg(currHfIdx) @@ -865,9 +865,9 @@ func XoverRightSeg(raw []byte, currInfIdx int, currHfIdx int, segs io.SegLens) { currseg := CurrSeg(raw, offset, currInfIdx, segLen - 1, segLen, 0) nextseg := CurrSeg(raw, offset, currInfIdx, segLen, segLen, 0) rightseg := reveal RightSeg(raw, currInfIdx, segs, 0) - assert absIncPathSeg(currseg) == nextseg + assert AbsIncPathSeg(currseg) == nextseg assert nextseg == get(rightseg) - assert absIncPathSeg(currseg) == get(rightseg) + assert AbsIncPathSeg(currseg) == get(rightseg) } ghost @@ -876,8 +876,8 @@ requires 0 <= currHfIdx && currHfIdx <= end requires end <= segLen requires offset + path.HopLen * segLen <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), R54) -ensures hopFields(raw, offset, currHfIdx, segLen)[:end - currHfIdx] == - hopFields(raw, offset, currHfIdx, end) +ensures AbsHopFields(raw, offset, currHfIdx, segLen)[:end - currHfIdx] == + AbsHopFields(raw, offset, currHfIdx, end) decreases func HopsFromSuffixOfRawMatchSuffixOfHops(raw []byte, offset int, currHfIdx int, segLen int, end int) { hopsFromSuffixOfRawMatchSuffixOfHops(raw, offset, currHfIdx, segLen, end, R54) @@ -890,8 +890,8 @@ requires 0 <= currHfIdx && currHfIdx <= end requires end <= segLen requires offset + path.HopLen * segLen <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), p) -ensures hopFields(raw, offset, currHfIdx, segLen)[:end - currHfIdx] == - hopFields(raw, offset, currHfIdx, end) +ensures AbsHopFields(raw, offset, currHfIdx, segLen)[:end - currHfIdx] == + AbsHopFields(raw, offset, currHfIdx, end) decreases end - currHfIdx func hopsFromSuffixOfRawMatchSuffixOfHops(raw []byte, offset int, currHfIdx int, segLen int, end int, p perm) { if (currHfIdx != end) { @@ -906,8 +906,8 @@ requires 0 <= start requires 0 <= currHfIdx && currHfIdx <= segLen - start requires offset + path.HopLen * segLen <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), R54) -ensures hopFields(raw, offset, currHfIdx, segLen)[start:] == - hopFields(raw, offset, currHfIdx + start, segLen) +ensures AbsHopFields(raw, offset, currHfIdx, segLen)[start:] == + AbsHopFields(raw, offset, currHfIdx + start, segLen) decreases func HopsFromPrefixOfRawMatchPrefixOfHops(raw []byte, offset int, currHfIdx int, segLen int, start int) { hopsFromPrefixOfRawMatchPrefixOfHops(raw, offset, currHfIdx, segLen, start, R54) @@ -920,8 +920,8 @@ requires 0 <= start requires 0 <= currHfIdx && currHfIdx <= segLen - start requires offset + path.HopLen * segLen <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), p) -ensures hopFields(raw, offset, currHfIdx, segLen)[start:] == - hopFields(raw, offset, currHfIdx + start, segLen) +ensures AbsHopFields(raw, offset, currHfIdx, segLen)[start:] == + AbsHopFields(raw, offset, currHfIdx + start, segLen) decreases start func hopsFromPrefixOfRawMatchPrefixOfHops(raw []byte, offset int, currHfIdx int, segLen int, start int, p perm) { if (start != 0) { @@ -936,8 +936,8 @@ requires 0 <= start && start <= currHfIdx requires 0 <= currHfIdx && currHfIdx <= segLen requires offset + path.HopLen * segLen <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), R54) -ensures hopFields(raw, offset, currHfIdx, segLen) == - hopFields(raw, offset + start * path.HopLen, currHfIdx - start, segLen - start) +ensures AbsHopFields(raw, offset, currHfIdx, segLen) == + AbsHopFields(raw, offset + start * path.HopLen, currHfIdx - start, segLen - start) decreases func AlignHopsOfRawWithOffsetAndIndex(raw []byte, offset int, currHfIdx int, segLen int, start int) { alignHopsOfRawWithOffsetAndIndex(raw, offset, currHfIdx, segLen, start, R54) @@ -950,8 +950,8 @@ requires 0 <= start && start <= currHfIdx requires 0 <= currHfIdx && currHfIdx <= segLen requires offset + path.HopLen * segLen <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), p) -ensures hopFields(raw, offset, currHfIdx, segLen) == - hopFields(raw, offset + start * path.HopLen, currHfIdx - start, segLen - start) +ensures AbsHopFields(raw, offset, currHfIdx, segLen) == + AbsHopFields(raw, offset + start * path.HopLen, currHfIdx - start, segLen - start) decreases segLen - currHfIdx func alignHopsOfRawWithOffsetAndIndex(raw []byte, offset int, currHfIdx int, segLen int, start int, p perm) { if (currHfIdx != segLen) { diff --git a/pkg/slayers/path/scion/widen-lemma.gobra b/pkg/slayers/path/scion/widen-lemma.gobra index 9eb8eb06f..84a836fae 100644 --- a/pkg/slayers/path/scion/widen-lemma.gobra +++ b/pkg/slayers/path/scion/widen-lemma.gobra @@ -84,8 +84,8 @@ requires length <= len(raw) requires offset + path.HopLen * segLen <= length preserves acc(sl.Bytes(raw, 0, len(raw)), R52) preserves acc(sl.Bytes(raw[start:length], 0, len(raw[start:length])), R52) -ensures segment(raw, offset, currHfIdx, ainfo, uinfo, consDir, peer, segLen) == - segment(raw[start:length], offset-start, currHfIdx, ainfo, uinfo, consDir, peer, segLen) +ensures AbsSegment(raw, offset, currHfIdx, ainfo, uinfo, consDir, peer, segLen) == + AbsSegment(raw[start:length], offset-start, currHfIdx, ainfo, uinfo, consDir, peer, segLen) decreases func widenSegment(raw []byte, offset int, @@ -109,8 +109,8 @@ requires offset + path.HopLen * segLen <= length requires length <= len(raw) preserves acc(sl.Bytes(raw, 0, len(raw)), p) preserves acc(sl.Bytes(raw[start:length], 0, len(raw[start:length])), p) -ensures hopFields(raw, offset, currHfIdx, segLen) == - hopFields(raw[start:length], offset-start, currHfIdx, segLen) +ensures AbsHopFields(raw, offset, currHfIdx, segLen) == + AbsHopFields(raw[start:length], offset-start, currHfIdx, segLen) decreases segLen - currHfIdx func widenHopFields(raw []byte, offset int, currHfIdx int, segLen int, start int, length int, p perm) { if (currHfIdx != segLen) { diff --git a/pkg/slayers/scion.go b/pkg/slayers/scion.go index b74c6d61d..11adda8ec 100644 --- a/pkg/slayers/scion.go +++ b/pkg/slayers/scion.go @@ -414,13 +414,16 @@ func (s *SCION) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) (res er return serrors.New("provided buffer is too small", "expected", minLen, "actual", len(data)) } + // @ unfold s.HiddenPathPoolMem() // @ assert unfolding PathPoolMem(s.pathPool, s.pathPoolRaw) in (s.pathPool == nil) == (s.pathPoolRaw == nil) s.Path, err = s.getPath(s.PathType) if err != nil { + // @ fold s.HiddenPathPoolMem() // @ unfold s.HeaderMem(data[CmnHdrLen:]) // @ fold s.NonInitMem() return err } + // @ fold s.HiddenPathPoolMemExceptOne(s.PathType, s.Path) // @ sl.SplitRange_Bytes(data, offset, offset+pathLen, R41) err = s.Path.DecodeFromBytes(data[offset : offset+pathLen]) if err != nil { @@ -477,11 +480,11 @@ func (s *SCION) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) (res er // When this is enabled, the Path instance may be overwritten in // DecodeFromBytes. No references to Path should be kept in use between // invocations of DecodeFromBytes. -// @ preserves acc(&s.pathPool) && acc(&s.pathPoolRaw) -// @ preserves PathPoolMem(s.pathPool, s.pathPoolRaw) -// @ ensures s.pathPoolInitialized() +// @ preserves s.HiddenPathPoolMem() +// @ ensures s.PathPoolInitialized() // @ decreases func (s *SCION) RecyclePaths() { + // @ unfold s.HiddenPathPoolMem() // @ unfold PathPoolMem(s.pathPool, s.pathPoolRaw) if s.pathPool == nil { s.pathPool = []path.Path{ @@ -497,6 +500,7 @@ func (s *SCION) RecyclePaths() { // @ fold s.pathPool[empty.PathType].NonInitMem() } // @ fold PathPoolMem(s.pathPool, s.pathPoolRaw) + // @ fold s.HiddenPathPoolMem() } // getPath returns a new or recycled path for pathType @@ -544,6 +548,7 @@ func (s *SCION) getPath(pathType path.Type) (res path.Path, err error) { func decodeSCION(data []byte, pb gopacket.PacketBuilder) (res error) { scn := &SCION{} // @ fold PathPoolMem(scn.pathPool, scn.pathPoolRaw) + // @ fold scn.HiddenPathPoolMem() // @ fold scn.NonInitMem() err := scn.DecodeFromBytes(data, pb) if err != nil { @@ -665,30 +670,30 @@ func (s *SCION) SrcAddr() (res net.Addr, err error) { // @ requires acc(&s.DstAddrType) // @ requires wildcard ==> acc(dst.Mem(), _) // @ requires !wildcard ==> acc(dst.Mem(), R18) -// @ ensures isIP(dst) ==> res == nil -// @ ensures isHostSVC(dst) ==> res == nil +// @ ensures IsIP(dst) ==> res == nil +// @ ensures IsHostSVC(dst) ==> res == nil // @ ensures acc(&s.RawDstAddr) && acc(&s.DstAddrType) // @ ensures res != nil ==> res.ErrorMem() -// @ ensures res == nil ==> isIP(dst) || isHostSVC(dst) -// @ ensures res == nil && wildcard && isIP(dst) ==> acc(sl.Bytes(s.RawDstAddr, 0, len(s.RawDstAddr)), _) -// @ ensures res == nil && wildcard && isHostSVC(dst) ==> sl.Bytes(s.RawDstAddr, 0, len(s.RawDstAddr)) -// @ ensures res == nil && !wildcard && isHostSVC(dst) ==> sl.Bytes(s.RawDstAddr, 0, len(s.RawDstAddr)) +// @ ensures res == nil ==> IsIP(dst) || IsHostSVC(dst) +// @ ensures res == nil && wildcard && IsIP(dst) ==> acc(sl.Bytes(s.RawDstAddr, 0, len(s.RawDstAddr)), _) +// @ ensures res == nil && wildcard && IsHostSVC(dst) ==> sl.Bytes(s.RawDstAddr, 0, len(s.RawDstAddr)) +// @ ensures res == nil && !wildcard && IsHostSVC(dst) ==> sl.Bytes(s.RawDstAddr, 0, len(s.RawDstAddr)) // @ ensures res == nil && !wildcard ==> acc(dst.Mem(), R18) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (isIPv4(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[i])) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (isIPv6(dst) && isConvertibleToIPv4(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[12+i])) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (!isIPv4(dst) && !isIPv6(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[i])) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (isIPv6(dst) && !isConvertibleToIPv4(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[i])) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (isIPv4(dst) ==> len(s.RawDstAddr) == len(dst.(*net.IPAddr).IP))) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (isIPv6(dst) && isConvertibleToIPv4(dst) ==> len(dst.(*net.IPAddr).IP) == len(s.RawDstAddr) + 12)) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (!isIPv4(dst) && !isIPv6(dst) ==> len(dst.(*net.IPAddr).IP) == len(s.RawDstAddr))) -// @ ensures res == nil && !wildcard && isIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (isIPv6(dst) && !isConvertibleToIPv4(dst) ==> len(dst.(*net.IPAddr).IP) == len(s.RawDstAddr))) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (IsIPv4(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[i])) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (IsIPv6(dst) && IsConvertibleToIPv4(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[12+i])) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (!IsIPv4(dst) && !IsIPv6(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[i])) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (IsIPv6(dst) && !IsConvertibleToIPv4(dst) ==> forall i int :: { &s.RawDstAddr[i] } 0 <= i && i < len(s.RawDstAddr) ==> &s.RawDstAddr[i] == &dst.(*net.IPAddr).IP[i])) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (IsIPv4(dst) ==> len(s.RawDstAddr) == len(dst.(*net.IPAddr).IP))) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (IsIPv6(dst) && IsConvertibleToIPv4(dst) ==> len(dst.(*net.IPAddr).IP) == len(s.RawDstAddr) + 12)) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (!IsIPv4(dst) && !IsIPv6(dst) ==> len(dst.(*net.IPAddr).IP) == len(s.RawDstAddr))) +// @ ensures res == nil && !wildcard && IsIP(dst) ==> (unfolding acc(dst.Mem(), R20) in (IsIPv6(dst) && !IsConvertibleToIPv4(dst) ==> len(dst.(*net.IPAddr).IP) == len(s.RawDstAddr))) // @ ensures (res == nil) == (typeOf(dst) == type[*net.IPAddr] || typeOf(dst) == type[addr.HostSVC]) // @ decreases func (s *SCION) SetDstAddr(dst net.Addr /*@ , ghost wildcard bool @*/) (res error) { var err error var verScionTmp []byte s.DstAddrType, verScionTmp, err = packAddr(dst /*@ , wildcard @*/) - // @ ghost if !wildcard && err == nil && isIP(dst) { + // @ ghost if !wildcard && err == nil && IsIP(dst) { // @ apply acc(sl.Bytes(verScionTmp, 0, len(verScionTmp)), R20) --* acc(dst.Mem(), R20) // @ } s.RawDstAddr = verScionTmp @@ -702,30 +707,30 @@ func (s *SCION) SetDstAddr(dst net.Addr /*@ , ghost wildcard bool @*/) (res erro // @ requires acc(&s.SrcAddrType) // @ requires wildcard ==> acc(src.Mem(), _) // @ requires !wildcard ==> acc(src.Mem(), R18) -// @ ensures isIP(src) ==> res == nil -// @ ensures isHostSVC(src) ==> res == nil +// @ ensures IsIP(src) ==> res == nil +// @ ensures IsHostSVC(src) ==> res == nil // @ ensures acc(&s.RawSrcAddr) && acc(&s.SrcAddrType) // @ ensures res != nil ==> res.ErrorMem() -// @ ensures res == nil ==> isIP(src) || isHostSVC(src) -// @ ensures res == nil && wildcard && isIP(src) ==> acc(sl.Bytes(s.RawSrcAddr, 0, len(s.RawSrcAddr)), _) -// @ ensures res == nil && wildcard && isHostSVC(src) ==> sl.Bytes(s.RawSrcAddr, 0, len(s.RawSrcAddr)) -// @ ensures res == nil && !wildcard && isHostSVC(src) ==> sl.Bytes(s.RawSrcAddr, 0, len(s.RawSrcAddr)) +// @ ensures res == nil ==> IsIP(src) || IsHostSVC(src) +// @ ensures res == nil && wildcard && IsIP(src) ==> acc(sl.Bytes(s.RawSrcAddr, 0, len(s.RawSrcAddr)), _) +// @ ensures res == nil && wildcard && IsHostSVC(src) ==> sl.Bytes(s.RawSrcAddr, 0, len(s.RawSrcAddr)) +// @ ensures res == nil && !wildcard && IsHostSVC(src) ==> sl.Bytes(s.RawSrcAddr, 0, len(s.RawSrcAddr)) // @ ensures res == nil && !wildcard ==> acc(src.Mem(), R18) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (isIPv4(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[i])) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (isIPv6(src) && isConvertibleToIPv4(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[12+i])) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (!isIPv4(src) && !isIPv6(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[i])) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (isIPv6(src) && !isConvertibleToIPv4(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[i])) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (isIPv4(src) ==> len(s.RawSrcAddr) == len(src.(*net.IPAddr).IP))) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (isIPv6(src) && isConvertibleToIPv4(src) ==> len(src.(*net.IPAddr).IP) == len(s.RawSrcAddr) + 12)) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (!isIPv4(src) && !isIPv6(src) ==> len(src.(*net.IPAddr).IP) == len(s.RawSrcAddr))) -// @ ensures res == nil && !wildcard && isIP(src) ==> (unfolding acc(src.Mem(), R20) in (isIPv6(src) && !isConvertibleToIPv4(src) ==> len(src.(*net.IPAddr).IP) == len(s.RawSrcAddr))) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (IsIPv4(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[i])) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (IsIPv6(src) && IsConvertibleToIPv4(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[12+i])) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (!IsIPv4(src) && !IsIPv6(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[i])) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (IsIPv6(src) && !IsConvertibleToIPv4(src) ==> forall i int :: { &s.RawSrcAddr[i] } 0 <= i && i < len(s.RawSrcAddr) ==> &s.RawSrcAddr[i] == &src.(*net.IPAddr).IP[i])) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (IsIPv4(src) ==> len(s.RawSrcAddr) == len(src.(*net.IPAddr).IP))) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (IsIPv6(src) && IsConvertibleToIPv4(src) ==> len(src.(*net.IPAddr).IP) == len(s.RawSrcAddr) + 12)) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (!IsIPv4(src) && !IsIPv6(src) ==> len(src.(*net.IPAddr).IP) == len(s.RawSrcAddr))) +// @ ensures res == nil && !wildcard && IsIP(src) ==> (unfolding acc(src.Mem(), R20) in (IsIPv6(src) && !IsConvertibleToIPv4(src) ==> len(src.(*net.IPAddr).IP) == len(s.RawSrcAddr))) // @ ensures (res == nil) == (typeOf(src) == type[*net.IPAddr] || typeOf(src) == type[addr.HostSVC]) // @ decreases func (s *SCION) SetSrcAddr(src net.Addr /*@, ghost wildcard bool @*/) (res error) { var err error var verScionTmp []byte s.SrcAddrType, verScionTmp, err = packAddr(src /*@ , wildcard @*/) - // @ ghost if !wildcard && err == nil && isIP(src) { + // @ ghost if !wildcard && err == nil && IsIP(src) { // @ apply acc(sl.Bytes(verScionTmp, 0, len(verScionTmp)), R20) --* acc(src.Mem(), R20) // @ } s.RawSrcAddr = verScionTmp @@ -779,24 +784,24 @@ func parseAddr(addrType AddrType, raw []byte) (res net.Addr, err error) { // @ requires !wildcard ==> acc(hostAddr.Mem(), R19) // @ ensures !wildcard ==> acc(hostAddr.Mem(), R20) // @ ensures hostAddr === old(hostAddr) -// @ ensures isIP(hostAddr) ==> err == nil -// @ ensures isHostSVC(hostAddr) ==> err == nil -// @ ensures err == nil ==> isIP(hostAddr) || isHostSVC(hostAddr) +// @ ensures IsIP(hostAddr) ==> err == nil +// @ ensures IsHostSVC(hostAddr) ==> err == nil +// @ ensures err == nil ==> IsIP(hostAddr) || IsHostSVC(hostAddr) // @ ensures err != nil ==> err.ErrorMem() -// @ ensures err == nil && wildcard && isIP(hostAddr) ==> acc(sl.Bytes(b, 0, len(b)), _) -// @ ensures err == nil && wildcard && isHostSVC(hostAddr) ==> sl.Bytes(b, 0, len(b)) -// @ ensures err == nil && !wildcard && isHostSVC(hostAddr) ==> sl.Bytes(b, 0, len(b)) -// @ ensures err == nil && !wildcard && isHostSVC(hostAddr) ==> acc(hostAddr.Mem(), R20) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> acc(sl.Bytes(b, 0, len(b)), R20) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (acc(sl.Bytes(b, 0, len(b)), R20) --* acc(hostAddr.Mem(), R20)) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[i])) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv6(hostAddr) && isConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[12+i])) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (!isIPv4(hostAddr) && !isIPv6(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[i])) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv6(hostAddr) && !isConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[i])) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv4(hostAddr) ==> len(b) == len(hostAddr.(*net.IPAddr).IP))) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv6(hostAddr) && isConvertibleToIPv4(hostAddr) ==> len(hostAddr.(*net.IPAddr).IP) == len(b) + 12)) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (!isIPv4(hostAddr) && !isIPv6(hostAddr) ==> len(hostAddr.(*net.IPAddr).IP) == len(b))) -// @ ensures err == nil && !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv6(hostAddr) && !isConvertibleToIPv4(hostAddr) ==> len(hostAddr.(*net.IPAddr).IP) == len(b))) +// @ ensures err == nil && wildcard && IsIP(hostAddr) ==> acc(sl.Bytes(b, 0, len(b)), _) +// @ ensures err == nil && wildcard && IsHostSVC(hostAddr) ==> sl.Bytes(b, 0, len(b)) +// @ ensures err == nil && !wildcard && IsHostSVC(hostAddr) ==> sl.Bytes(b, 0, len(b)) +// @ ensures err == nil && !wildcard && IsHostSVC(hostAddr) ==> acc(hostAddr.Mem(), R20) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> acc(sl.Bytes(b, 0, len(b)), R20) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (acc(sl.Bytes(b, 0, len(b)), R20) --* acc(hostAddr.Mem(), R20)) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[i])) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv6(hostAddr) && IsConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[12+i])) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (!IsIPv4(hostAddr) && !IsIPv6(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[i])) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv6(hostAddr) && !IsConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[i])) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv4(hostAddr) ==> len(b) == len(hostAddr.(*net.IPAddr).IP))) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv6(hostAddr) && IsConvertibleToIPv4(hostAddr) ==> len(hostAddr.(*net.IPAddr).IP) == len(b) + 12)) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (!IsIPv4(hostAddr) && !IsIPv6(hostAddr) ==> len(hostAddr.(*net.IPAddr).IP) == len(b))) +// @ ensures err == nil && !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv6(hostAddr) && !IsConvertibleToIPv4(hostAddr) ==> len(hostAddr.(*net.IPAddr).IP) == len(b))) // @ ensures (err == nil) == (typeOf(hostAddr) == type[*net.IPAddr] || typeOf(hostAddr) == type[addr.HostSVC]) // @ decreases func packAddr(hostAddr net.Addr /*@ , ghost wildcard bool @*/) (addrtyp AddrType, b []byte, err error) { @@ -808,12 +813,12 @@ func packAddr(hostAddr net.Addr /*@ , ghost wildcard bool @*/) (addrtyp AddrType // @ unfold acc(hostAddr.Mem(), R20) // @ } if ip := a.IP.To4( /*@ wildcard @*/ ); ip != nil { - // @ ghost if !wildcard && isIPv6(a) { - // @ assert isConvertibleToIPv4(hostAddr) ==> + // @ ghost if !wildcard && IsIPv6(a) { + // @ assert IsConvertibleToIPv4(hostAddr) ==> // @ forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &a.IP[12+i] // @ } - // @ assert !wildcard && isIP(hostAddr) ==> - // @ (unfolding acc(hostAddr.Mem(), R20) in (isIPv6(hostAddr) && isConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[12+i])) + // @ assert !wildcard && IsIP(hostAddr) ==> + // @ (unfolding acc(hostAddr.Mem(), R20) in (IsIPv6(hostAddr) && IsConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[12+i])) // @ ghost if wildcard { // @ fold acc(sl.Bytes(ip, 0, len(ip)), _) // @ } else { @@ -825,7 +830,7 @@ func packAddr(hostAddr net.Addr /*@ , ghost wildcard bool @*/) (addrtyp AddrType // @ } return T4Ip, ip, nil } - // @ assert !wildcard && isIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (isIPv6(hostAddr) && isConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[12+i])) + // @ assert !wildcard && IsIP(hostAddr) ==> (unfolding acc(hostAddr.Mem(), R20) in (IsIPv6(hostAddr) && IsConvertibleToIPv4(hostAddr) ==> forall i int :: { &b[i] } 0 <= i && i < len(b) ==> &b[i] == &hostAddr.(*net.IPAddr).IP[12+i])) verScionTmp := a.IP // @ ghost if wildcard { // @ fold acc(sl.Bytes(verScionTmp, 0, len(verScionTmp)), _) diff --git a/pkg/slayers/scion_spec.gobra b/pkg/slayers/scion_spec.gobra index 3bcf6a96f..2a708f369 100644 --- a/pkg/slayers/scion_spec.gobra +++ b/pkg/slayers/scion_spec.gobra @@ -95,6 +95,56 @@ pred PathPoolMemExceptOne(pathPool []path.Path, pathPoolRaw path.Path, pathType (int(pathType) < len(pathPool) ==> pathPoolRaw.NonInitMem()) } +// HiddenPathPoolMem holds the resources of the (private) path pool of a SCION +// layer. The predicate is closed because its body mentions non-exported fields; +// importing packages may hold it, but they can neither fold nor unfold it. They +// obtain it from EstablishHiddenPathPoolMem. +closed pred (s *SCION) HiddenPathPoolMem() { + acc(&s.pathPool) && + acc(&s.pathPoolRaw) && + PathPoolMem(s.pathPool, s.pathPoolRaw) +} + +// HiddenPathPoolMemExceptOne is the counterpart of HiddenPathPoolMem for a layer +// whose path `p` of type `pathType` has been taken out of the pool. It is the +// part of Mem that describes the private state of the layer. +closed pred (s *SCION) HiddenPathPoolMemExceptOne(pathType path.Type, p path.Path) { + acc(&s.pathPool) && + acc(&s.pathPoolRaw) && + (!s.pathPoolInitialized() ==> PathPoolMem(s.pathPool, s.pathPoolRaw)) && + (s.pathPoolInitialized() ==> (s.pathPool != nil && s.pathPoolRaw != nil && + PathPoolMemExceptOne(s.pathPool, s.pathPoolRaw, pathType) && + p === s.getPathPure(pathType))) +} + +// PathPoolInitialized holds iff the path pool of the layer has been allocated. +ghost +requires s.HiddenPathPoolMem() +decreases +closed +pure func (s *SCION) PathPoolInitialized() bool { + return unfolding s.HiddenPathPoolMem() in s.pathPool != nil +} + +// EstablishHiddenPathPoolMem packages the permission to the private path pool of +// a freshly allocated SCION layer into the closed predicate HiddenPathPoolMem, +// which importing packages cannot fold themselves. +ghost +requires acc(s) +requires *s === SCION{} +ensures acc(&s.Version) && acc(&s.TrafficClass) && acc(&s.FlowID) && + acc(&s.NextHdr) && acc(&s.HdrLen) && acc(&s.PayloadLen) && + acc(&s.PathType) && acc(&s.DstAddrType) && acc(&s.SrcAddrType) && + acc(&s.DstIA) && acc(&s.SrcIA) && acc(&s.RawDstAddr) && acc(&s.RawSrcAddr) && + acc(&s.Path) && acc(&s.BaseLayer) +ensures s.HiddenPathPoolMem() +ensures !s.PathPoolInitialized() +decreases +func (s *SCION) EstablishHiddenPathPoolMem() { + fold PathPoolMem(s.pathPool, s.pathPoolRaw) + fold s.HiddenPathPoolMem() +} + ghost requires acc(&s.pathPool) decreases @@ -105,9 +155,10 @@ pure func (s *SCION) pathPoolInitialized() bool { ghost requires s.NonInitMem() decreases +closed pure func (s *SCION) PathPoolInitializedNonInitMem() bool { return unfolding s.NonInitMem() in - s.pathPool != nil + s.PathPoolInitialized() } ghost @@ -139,9 +190,7 @@ pred (s *SCION) NonInitMem() { acc(&s.Path) && acc(&s.BaseLayer) && // path pool properties - acc(&s.pathPool) && - acc(&s.pathPoolRaw) && - PathPoolMem(s.pathPool, s.pathPoolRaw) + s.HiddenPathPoolMem() } // TODO: simplify the body of the predicate when let expressions @@ -174,11 +223,7 @@ pred (s *SCION) Mem(ubuf []byte) { s.HeaderMem(ubuf[CmnHdrLen:]) && // path pool 0 <= s.PathType && s.PathType < path.MaxPathType && - acc(&s.pathPool) && - acc(&s.pathPoolRaw) && - (!s.pathPoolInitialized() ==> PathPoolMem(s.pathPool, s.pathPoolRaw)) && - (s.pathPoolInitialized() ==> (s.pathPool != nil && s.pathPoolRaw != nil && - PathPoolMemExceptOne(s.pathPool, s.pathPoolRaw, s.PathType) && s.Path === s.getPathPure(s.PathType))) && + s.HiddenPathPoolMemExceptOne(s.PathType, s.Path) && // end of path pool // helpful facts for other methods: // - for router::updateScionLayer: @@ -734,21 +779,18 @@ func (s *SCION) LayerContents() (res []byte) { } ghost -requires 0 <= pathType && pathType < path.MaxPathType -requires acc(&s.pathPool, R20) && acc(&s.pathPoolRaw, R20) -requires s.pathPoolInitialized() ==> ( - p.NonInitMem() && - PathPoolMemExceptOne(s.pathPool, s.pathPoolRaw, pathType) && - p === s.getPathPure(pathType)) -requires !s.pathPoolInitialized() ==> PathPoolMem(s.pathPool, s.pathPoolRaw) -ensures acc(&s.pathPool, R20) && acc(&s.pathPoolRaw, R20) -ensures PathPoolMem(s.pathPool, s.pathPoolRaw) +requires 0 <= pathType && pathType < path.MaxPathType +requires s.HiddenPathPoolMemExceptOne(pathType, p) +requires p != nil ==> p.NonInitMem() +ensures s.HiddenPathPoolMem() decreases func (s *SCION) PathPoolMemExchange(pathType path.Type, p path.Path) { + unfold s.HiddenPathPoolMemExceptOne(pathType, p) if s.pathPoolInitialized() { unfold PathPoolMemExceptOne(s.pathPool, s.pathPoolRaw, pathType) fold PathPoolMem(s.pathPool, s.pathPoolRaw) } + fold s.HiddenPathPoolMem() } // gopacket subtyping @@ -764,8 +806,8 @@ requires forall i int :: { &a.(*net.IPAddr).IP[i] } 0 <= i && i < len(a.(*net.IP acc(&a.(*net.IPAddr).IP[i]) requires len(a.(*net.IPAddr).IP) == net.IPv6len decreases -pure func isConvertibleToIPv4(a net.Addr) bool { - return net.isZeros(a.(*net.IPAddr).IP[0:10]) && +pure func IsConvertibleToIPv4(a net.Addr) bool { + return net.IsZeros(a.(*net.IPAddr).IP[0:10]) && a.(*net.IPAddr).IP[10] == 255 && a.(*net.IPAddr).IP[11] == 255 } @@ -774,7 +816,7 @@ ghost requires typeOf(a) == *net.IPAddr requires acc(&a.(*net.IPAddr).IP) decreases -pure func isIPv6(a net.Addr) bool { +pure func IsIPv6(a net.Addr) bool { return len(a.(*net.IPAddr).IP) == net.IPv6len } @@ -782,19 +824,19 @@ ghost requires typeOf(a) == *net.IPAddr requires acc(&a.(*net.IPAddr).IP) decreases -pure func isIPv4(a net.Addr) bool { +pure func IsIPv4(a net.Addr) bool { return len(a.(*net.IPAddr).IP) == net.IPv4len } ghost decreases -pure func isIP(a net.Addr) bool { +pure func IsIP(a net.Addr) bool { return typeOf(a) == *net.IPAddr } ghost decreases -pure func isHostSVC(a net.Addr) bool { +pure func IsHostSVC(a net.Addr) bool { return typeOf(a) == addr.HostSVC } diff --git a/pkg/slayers/scmp.go b/pkg/slayers/scmp.go index 6892c007d..b87d6b6b9 100644 --- a/pkg/slayers/scmp.go +++ b/pkg/slayers/scmp.go @@ -132,7 +132,9 @@ func (s *SCMP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOp // @ sl.CombineAtIndex_Bytes(underlyingBufRes, 0, len(underlyingBufRes), 2, writePerm) if opts.ComputeChecksums { + // @ unfold s.ChecksumNetworkLayerMem() if s.scn == nil { + // @ fold s.ChecksumNetworkLayerMem() // @ fold s.Mem(ubufMem) return serrors.New("can not calculate checksum without SCION header") } @@ -148,6 +150,7 @@ func (s *SCMP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOp // @ unfold s.scn.ChecksumMem() s.Checksum, err = s.scn.computeChecksum(verScionTmp, uint8(L4SCMP)) // @ fold s.scn.ChecksumMem() + // @ fold s.ChecksumNetworkLayerMem() if err != nil { // @ fold s.Mem(ubufMem) return err @@ -221,11 +224,17 @@ func (s *SCMP) String() string { // SetNetworkLayerForChecksum tells this layer which network layer is wrapping it. // This is needed for computing the checksum when serializing, -// @ preserves acc(&s.scn) -// @ ensures s.scn == scn +// (VerifiedSCION) the network layer is stored in a non-exported field, so the +// contract of this exported method describes it through the closed predicate +// ChecksumNetworkLayerMem instead of mentioning the field directly. +// @ requires s.ChecksumNetworkLayerMem() +// @ requires scn != nil ==> scn.ChecksumMem() +// @ ensures s.ChecksumNetworkLayerMem() // @ decreases func (s *SCMP) SetNetworkLayerForChecksum(scn *SCION) { + // @ unfold s.ChecksumNetworkLayerMem() s.scn = scn + // @ fold s.ChecksumNetworkLayerMem() } // @ requires pb != nil @@ -235,6 +244,7 @@ func (s *SCMP) SetNetworkLayerForChecksum(scn *SCION) { // @ decreases func decodeSCMP(data []byte, pb gopacket.PacketBuilder) (res error) { scmp := &SCMP{} + // @ fold scmp.ChecksumNetworkLayerMem() // @ fold scmp.NonInitMem() err := scmp.DecodeFromBytes(data, pb) if err != nil { diff --git a/pkg/slayers/scmp_msg_spec.gobra b/pkg/slayers/scmp_msg_spec.gobra index f4cd61b64..304103e57 100644 --- a/pkg/slayers/scmp_msg_spec.gobra +++ b/pkg/slayers/scmp_msg_spec.gobra @@ -23,12 +23,18 @@ import ( "github.com/scionproto/scion/verification/utils/slices" ) +// SCMPRawInterfaceLen is the exported, ghost counterpart of the non-exported +// constant scmpRawInterfaceLen. Contracts of exported members and bodies of +// fully-public predicates may only mention exported names, so they use this +// constant instead. +ghost const SCMPRawInterfaceLen = scmpRawInterfaceLen + pred (s *SCMPExternalInterfaceDown) NonInitMem() { acc(&s.IA) && acc(&s.IfID) && acc(&s.BaseLayer) } pred (s *SCMPExternalInterfaceDown) Mem(ub []byte) { - acc(&s.IA) && acc(&s.IfID) && s.BaseLayer.Mem(ub, addr.IABytes+scmpRawInterfaceLen) + acc(&s.IA) && acc(&s.IfID) && s.BaseLayer.Mem(ub, addr.IABytes+SCMPRawInterfaceLen) } requires false @@ -44,8 +50,8 @@ ensures res === ub[start:end] decreases func (b *SCMPExternalInterfaceDown) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) { unfold acc(b.Mem(ub), R20) - res = b.BaseLayer.LayerPayload(ub, addr.IABytes+scmpRawInterfaceLen) - start = addr.IABytes+scmpRawInterfaceLen + res = b.BaseLayer.LayerPayload(ub, addr.IABytes+SCMPRawInterfaceLen) + start = addr.IABytes+SCMPRawInterfaceLen end = len(ub) fold acc(b.Mem(ub), R20) return res, start, end @@ -60,7 +66,7 @@ pred (s *SCMPInternalConnectivityDown) NonInitMem() { } pred (s *SCMPInternalConnectivityDown) Mem(ub []byte) { - acc(&s.IA) && acc(&s.Ingress) && acc(&s.Egress) && s.BaseLayer.Mem(ub, addr.IABytes+2*scmpRawInterfaceLen) + acc(&s.IA) && acc(&s.Ingress) && acc(&s.Egress) && s.BaseLayer.Mem(ub, addr.IABytes+2*SCMPRawInterfaceLen) } requires false @@ -76,8 +82,8 @@ ensures res === ub[start:end] decreases func (b *SCMPInternalConnectivityDown) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) { unfold acc(b.Mem(ub), R20) - res = b.BaseLayer.LayerPayload(ub, addr.IABytes+2*scmpRawInterfaceLen) - start = addr.IABytes+2*scmpRawInterfaceLen + res = b.BaseLayer.LayerPayload(ub, addr.IABytes+2*SCMPRawInterfaceLen) + start = addr.IABytes+2*SCMPRawInterfaceLen end = len(ub) fold acc(b.Mem(ub), R20) return res, start, end @@ -157,7 +163,7 @@ pred (s *SCMPTraceroute) Mem(ub []byte) { acc(&s.Sequence) && acc(&s.IA) && acc(&s.Interface) && - s.BaseLayer.Mem(ub, 4+addr.IABytes+scmpRawInterfaceLen) + s.BaseLayer.Mem(ub, 4+addr.IABytes+SCMPRawInterfaceLen) } requires false @@ -174,8 +180,8 @@ ensures res === ub[start:end] decreases func (b *SCMPTraceroute) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) { unfold acc(b.Mem(ub), R20) - res = b.BaseLayer.LayerPayload(ub, 4+addr.IABytes+scmpRawInterfaceLen) - start = 4+addr.IABytes+scmpRawInterfaceLen + res = b.BaseLayer.LayerPayload(ub, 4+addr.IABytes+SCMPRawInterfaceLen) + start = 4+addr.IABytes+SCMPRawInterfaceLen end = len(ub) fold acc(b.Mem(ub), R20) return res, start, end diff --git a/pkg/slayers/scmp_spec.gobra b/pkg/slayers/scmp_spec.gobra index edc47876d..8f43f3545 100644 --- a/pkg/slayers/scmp_spec.gobra +++ b/pkg/slayers/scmp_spec.gobra @@ -23,20 +23,40 @@ import ( "github.com/scionproto/scion/verification/utils/slices" ) +// ChecksumNetworkLayerMem holds the resources of the private state of an SCMP +// layer, namely the SCION header that the layer uses to compute its checksum. +// The predicate is closed because its body mentions a non-exported field; +// importing packages may hold it, but they can neither fold nor unfold it. +closed pred (s *SCMP) ChecksumNetworkLayerMem() { + acc(&s.scn) && + (s.scn != nil ==> s.scn.ChecksumMem()) +} + pred (s *SCMP) NonInitMem() { acc(&s.TypeCode) && acc(&s.Checksum) && acc(&s.BaseLayer) && - acc(&s.scn) && - (s.scn != nil ==> s.scn.ChecksumMem()) + s.ChecksumNetworkLayerMem() } pred (s *SCMP) Mem(ub []byte) { acc(&s.TypeCode) && acc(&s.Checksum) && s.BaseLayer.Mem(ub, 4) && - acc(&s.scn) && - (s.scn != nil ==> s.scn.ChecksumMem()) + s.ChecksumNetworkLayerMem() +} + +// EstablishNonInitMem packages full permission to a zero-valued SCMP layer into +// its NonInitMem predicate. Importing packages cannot fold NonInitMem +// themselves, since it covers the private state of the layer. +ghost +requires acc(s) +requires *s === SCMP{} +ensures s.NonInitMem() +decreases +func (s *SCMP) EstablishNonInitMem() { + fold s.ChecksumNetworkLayerMem() + fold s.NonInitMem() } ghost diff --git a/pkg/slayers/scmp_typecode_spec.gobra b/pkg/slayers/scmp_typecode_spec.gobra index 3cbdc0d7d..33d58643a 100644 --- a/pkg/slayers/scmp_typecode_spec.gobra +++ b/pkg/slayers/scmp_typecode_spec.gobra @@ -16,7 +16,9 @@ package slayers -pred SCMPTypeCodeMem() { +// The body of this predicate describes private global state of the package, so +// importing packages may hold it, but they cannot unfold it. +closed pred SCMPTypeCodeMem() { // We don't use a trigger here since triggers of the form scmpTypeCodeInfo[i].codes would generate a ternary expression // The default trigger generated is: { (i_V0 elem domain((getMap(scmpTypeCodeInfo_e8d3837_G().underlyingMapField): Map[Int,Tuple2[Int, Ref]]))) } acc(scmpTypeCodeInfo) && diff --git a/router/dataplane.go b/router/dataplane.go index 7803ba3c7..8f5a0cc5c 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -168,11 +168,11 @@ type BatchConn interface { // @ ensures err != nil ==> err.ErrorMem() // contracts for IO-spec // @ requires Prophecy(prophecyM) - // @ requires io.token(place) && MultiReadBio(place, prophecyM) + // @ requires io.IOToken(place) && MultiReadBio(place, prophecyM) // @ ensures err != nil ==> prophecyM == 0 // @ ensures err == nil ==> prophecyM == n - // @ ensures io.token(old(MultiReadBioNext(place, prophecyM))) - // @ ensures old(MultiReadBioCorrectIfs(place, prophecyM, path.ifsToIO_ifs(ingressID))) + // @ ensures io.IOToken(old(MultiReadBioNext(place, prophecyM))) + // @ ensures old(MultiReadBioCorrectIfs(place, prophecyM, path.IfsToIO_ifs(ingressID))) // @ ensures err == nil ==> // @ forall i int :: { &msgs[i] } 0 <= i && i < n ==> // @ MsgToAbsVal(&msgs[i], ingressID) == old(MultiReadBioIO_val(place, n)[i]) @@ -191,7 +191,7 @@ type BatchConn interface { // @ requires acc(sl.Bytes(msgs[0].GetFstBuffer(), 0, len(msgs[0].GetFstBuffer())), R50) // preconditions for IO-spec: // @ requires MsgToAbsVal(&msgs[0], egressID) == ioAbsPkts - // @ requires io.token(place) && io.CBioIO_bio3s_send(place, ioAbsPkts) + // @ requires io.IOToken(place) && io.CBioIO_bio3s_send(place, ioAbsPkts) // @ ensures acc(msgs[0].Mem(), R50) && msgs[0].HasActiveAddr() // @ ensures acc(sl.Bytes(msgs[0].GetFstBuffer(), 0, len(msgs[0].GetFstBuffer())), R50) // @ ensures err == nil ==> 0 <= n && n <= len(msgs) @@ -199,7 +199,7 @@ type BatchConn interface { // postconditions for IO-spec: // (VerifiedSCION) the permission to the protocol must always be returned, // otherwise the router cannot continue after failing to send a packet. - // @ ensures io.token(old(io.dp3s_iospec_bio3s_send_T(place, ioAbsPkts))) + // @ ensures io.IOToken(old(io.Dp3s_iospec_bio3s_send_T(place, ioAbsPkts))) WriteBatch(msgs underlayconn.Messages, flags int /*@, ghost egressID uint16, ghost place io.Place, ghost ioAbsPkts io.Val @*/) (n int, err error) // @ requires Mem() // @ ensures err != nil ==> err.ErrorMem() @@ -274,13 +274,14 @@ func (e scmpError) Error() string { // @ requires !d.IsRunning() // @ requires d.LocalIA().IsZero() // @ requires !ia.IsZero() -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ ensures acc(d.Mem(), OutMutexPerm) // @ ensures !d.IsRunning() // @ ensures e == nil // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) SetIA(ia addr.IA) (e error) { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() // @ unfold MutexInvariant{d}() @@ -312,14 +313,15 @@ func (d *DataPlane) SetIA(ia addr.IA) (e error) { // @ requires !d.KeyIsSet() // @ requires len(key) > 0 // @ requires sl.Bytes(key, 0, len(key)) -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ ensures acc(d.Mem(), OutMutexPerm) // @ ensures !d.IsRunning() // @ ensures res == nil ==> d.KeyIsSet() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) SetKey(key []byte) (res error) { // @ share key + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() // @ unfold MutexInvariant{d}() @@ -376,12 +378,13 @@ func (d *DataPlane) SetKey(key []byte) (res error) { // @ requires !d.InternalConnIsSet() // @ requires conn != nil && conn.Mem() // @ requires ip.Mem() -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ ensures acc(d.Mem(), OutMutexPerm) // @ ensures !d.IsRunning() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) AddInternalInterface(conn BatchConn, ip net.IP) error { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() // @ unfold MutexInvariant{d}() @@ -419,10 +422,11 @@ func (d *DataPlane) AddInternalInterface(conn BatchConn, ip net.IP) error { // @ requires conn != nil && conn.Mem() // @ preserves acc(d.Mem(), OutMutexPerm) // @ preserves !d.IsRunning() -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) AddExternalInterface(ifID uint16, conn BatchConn) error { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() // @ unfold MutexInvariant{d}() @@ -467,10 +471,11 @@ func (d *DataPlane) AddExternalInterface(ifID uint16, conn BatchConn) error { // @ requires !remote.IsZero() // @ preserves acc(d.Mem(), OutMutexPerm) // @ preserves !d.IsRunning() -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) AddNeighborIA(ifID uint16, remote addr.IA) error { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() // @ unfold MutexInvariant{d}() @@ -633,10 +638,11 @@ func (d *DataPlane) addBFDController(ifID uint16, s *bfdSend, cfg control.BFD, // @ requires a != nil && acc(a.Mem(), R10) // @ preserves acc(d.Mem(), OutMutexPerm) // @ preserves !d.IsRunning() -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) AddSvc(svc addr.HostSVC, a *net.UDPAddr) error { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() // @ unfold MutexInvariant{d}() // @ d.isRunningEq() @@ -693,9 +699,11 @@ func (d *DataPlane) AddSvc(svc addr.HostSVC, a *net.UDPAddr) error { // the lock invariant to perform the operations in this function. // @ requires a != nil && acc(a.Mem(), R10) // @ preserves acc(d.Mem(), OutMutexPerm/2) -// @ preserves d.mtx.LockP() +// @ preserves d.MtxInv() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) DelSvc(svc addr.HostSVC, a *net.UDPAddr) error { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() if a == nil { @@ -727,10 +735,11 @@ func (d *DataPlane) DelSvc(svc addr.HostSVC, a *net.UDPAddr) error { // @ requires a != nil && a.Mem() // @ preserves acc(d.Mem(), OutMutexPerm) // @ preserves !d.IsRunning() -// @ preserves d.mtx.LockP() -// @ preserves d.mtx.LockInv() == MutexInvariant{d} +// @ preserves d.MtxInv() // @ decreases 0 if sync.IgnoreBlockingForTermination() func (d *DataPlane) AddNextHop(ifID uint16, a *net.UDPAddr) error { + // @ unfold d.MtxInv() + // @ ghost defer fold d.MtxInv() d.mtx.Lock() defer d.mtx.Unlock() // @ unfold MutexInvariant{d}() @@ -811,17 +820,16 @@ func (d *DataPlane) AddNextHopBFD(ifID uint16, src, dst *net.UDPAddr, cfg contro // @ requires d.SvcsAreSet() // @ requires d.MetricsAreSet() // @ requires d.PreWellConfigured() -// (VerifiedSCION) here, the spec still uses a private field. -// @ requires d.mtx.LockP() -// @ requires d.mtx.LockInv() == MutexInvariant{d} +// @ requires d.MtxInv() // @ requires ctx != nil && ctx.Mem() // contracts for IO-spec // @ requires dp.Valid() // @ requires d.DpAgreesWithSpec(dp) -// @ requires io.token(place) && dp.dp3s_iospec_ordered(state, place) +// @ requires io.IOToken(place) && dp.Dp3s_iospec_ordered(state, place) // @ #backend[moreJoins()] func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost state io.Dp3sStateLocal, ghost dp io.DataPlaneSpec @*/) error { // @ share d, ctx + // @ unfold d.MtxInv() d.mtx.Lock() // @ unfold MutexInvariant{d}() // @ assert !d.IsRunning() @@ -848,13 +856,13 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ decreases // @ outline ( // @ reveal d.PreWellConfigured() - // @ reveal d.getDomExternal() + // @ reveal d.GetDomExternal() // @ reveal d.DpAgreesWithSpec(dp) // @ unfold d.Mem() d.running = true // @ fold MutexInvariant{d}() // @ fold d.Mem() - // @ reveal d.getDomExternal() + // @ reveal d.GetDomExternal() // @ reveal d.PreWellConfigured() // @ reveal d.DpAgreesWithSpec(dp) // @ ) @@ -872,8 +880,8 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ d.WellConfigured() && // @ d.getValSvc() != nil && // @ d.getValForwardingMetrics() != nil && - // @ (0 elem d.getDomForwardingMetrics()) && - // @ (ingressID elem d.getDomForwardingMetrics()) && + // @ (0 elem d.GetDomForwardingMetrics()) && + // @ (ingressID elem d.GetDomForwardingMetrics()) && // @ d.getMacFactory() != nil // @ requires rd != nil && acc(rd.Mem(), _) // contracts for IO-spec @@ -952,8 +960,8 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ invariant acc(d.Mem(), _) && d.WellConfigured() // @ invariant d.getValSvc() != nil // @ invariant d.getValForwardingMetrics() != nil - // @ invariant 0 elem d.getDomForwardingMetrics() - // @ invariant ingressID elem d.getDomForwardingMetrics() + // @ invariant 0 elem d.GetDomForwardingMetrics() + // @ invariant ingressID elem d.GetDomForwardingMetrics() // @ invariant acc(rd.Mem(), _) // @ invariant processor.sInit() && processor.sInitD() === d // @ invariant let ubuf := processor.sInitBufferUBuf() in @@ -963,7 +971,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ invariant ioLock.LockInv() == SharedInv{dp, ioSharedArg} // @ invariant d.DpAgreesWithSpec(dp) && dp.Valid() for d.running { - // @ ghost ioIngressID := path.ifsToIO_ifs(ingressID) + // @ ghost ioIngressID := path.IfsToIO_ifs(ingressID) // Multi recv event // @ ghost ioLock.Lock() // @ unfold SharedInv{dp, ioSharedArg}() @@ -975,7 +983,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ ghost sN := MultiReadBioUpd(t, numberOfReceivedPacketsProphecy, s) // @ ghost tN := MultiReadBioNext(t, numberOfReceivedPacketsProphecy) - // @ assert dp.dp3s_iospec_ordered(sN, tN) + // @ assert dp.Dp3s_iospec_ordered(sN, tN) // @ BeforeReadBatch: pkts, err := rd.ReadBatch(msgs /*@, ingressID, numberOfReceivedPacketsProphecy, t @*/) // @ assert old[BeforeReadBatch](MultiReadBioIO_val(t, numberOfReceivedPacketsProphecy)) == ioValSeq @@ -1024,8 +1032,8 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ invariant acc(d.Mem(), _) && d.WellConfigured() // @ invariant d.getValSvc() != nil // @ invariant d.getValForwardingMetrics() != nil - // @ invariant 0 elem d.getDomForwardingMetrics() - // @ invariant ingressID elem d.getDomForwardingMetrics() + // @ invariant 0 elem d.GetDomForwardingMetrics() + // @ invariant ingressID elem d.GetDomForwardingMetrics() // @ invariant acc(rd.Mem(), _) // @ invariant pkts <= len(msgs) // @ invariant 0 <= i0 && i0 <= pkts @@ -1042,7 +1050,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // contracts for IO-spec // @ invariant pkts <= len(ioValSeq) // @ invariant d.DpAgreesWithSpec(dp) && dp.Valid() - // @ invariant ioIngressID == path.ifsToIO_ifs(ingressID) + // @ invariant ioIngressID == path.IfsToIO_ifs(ingressID) // @ invariant acc(ioLock.LockP(), _) // @ invariant ioLock.LockInv() == SharedInv{dp, ioSharedArg} // @ invariant forall i int :: { &msgs[i] } i0 <= i && i < pkts ==> @@ -1082,8 +1090,8 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ assert p.N <= len(p.Buffers[0]) // @ sl.SplitRange_Bytes(p.Buffers[0], 0, p.N, HalfPerm) tmpBuf := p.Buffers[0][:p.N] - // @ ghost absPktTmpBuf := absIO_val(tmpBuf, ingressID) - // @ ghost absPktBuf0 := absIO_val(msgs[i0].Buffers[0], ingressID) + // @ ghost absPktTmpBuf := AbsIO_val(tmpBuf, ingressID) + // @ ghost absPktBuf0 := AbsIO_val(msgs[i0].Buffers[0], ingressID) // @ assert msgs[i0] === p // @ absIO_valWidenLemma(p.Buffers[0], ingressID, p.N) // @ assert absPktTmpBuf.isValPkt ==> absPktTmpBuf === absPktBuf0 @@ -1091,7 +1099,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ assert ioValSeq[i0].isValPkt ==> // @ ElemWitness(ioSharedArg.IBufY, ioIngressID, ioValSeq[i0].ValPkt_2) // @ assert absPktTmpBuf.isValPkt ==> absPktTmpBuf == ioValSeq[i0] - // @ assert path.ifsToIO_ifs(processor.getIngressID()) == ioIngressID + // @ assert path.IfsToIO_ifs(processor.getIngressID()) == ioIngressID // @ sl.SplitRange_Bytes(p.Buffers[0], 0, p.N, HalfPerm) // @ assert sl.Bytes(tmpBuf, 0, p.N) // @ assert sl.Bytes(tmpBuf, 0, len(tmpBuf)) @@ -1170,23 +1178,23 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta writeMsgs[0].Addr = result.OutAddr } // @ sl.NilAcc_Bytes() - // @ assert absIO_val(result.OutPkt, result.EgressID) == - // @ absIO_val(writeMsgs[0].Buffers[0], result.EgressID) + // @ assert AbsIO_val(result.OutPkt, result.EgressID) == + // @ AbsIO_val(writeMsgs[0].Buffers[0], result.EgressID) // @ assert result.OutPkt != nil ==> newAbsPkt == - // @ absIO_val(writeMsgs[0].Buffers[0], result.EgressID) + // @ AbsIO_val(writeMsgs[0].Buffers[0], result.EgressID) // @ fold acc(writeMsgs[0].Mem(), R50) // @ ghost ioLock.Lock() // @ unfold SharedInv{dp, ioSharedArg}() // @ ghost t, s := *ioSharedArg.Place, *ioSharedArg.State // @ ghost if(newAbsPkt.isValPkt) { - // @ ApplyElemWitness(s.obuf, ioSharedArg.OBufY, newAbsPkt.ValPkt_1, newAbsPkt.ValPkt_2) - // @ assert newAbsPkt.ValPkt_2 elem AsSet(s.obuf[newAbsPkt.ValPkt_1]) - // @ assert dp.dp3s_iospec_bio3s_send_guard(s, t, newAbsPkt) + // @ ApplyElemWitness(s.Obuf, ioSharedArg.OBufY, newAbsPkt.ValPkt_1, newAbsPkt.ValPkt_2) + // @ assert newAbsPkt.ValPkt_2 elem AsSet(s.Obuf[newAbsPkt.ValPkt_1]) + // @ assert dp.Dp3s_iospec_bio3s_send_guard(s, t, newAbsPkt) // @ } else { assert newAbsPkt.isValUnsupported } - // @ unfold dp.dp3s_iospec_ordered(s, t) - // @ unfold dp.dp3s_iospec_bio3s_send(s, t) + // @ unfold dp.Dp3s_iospec_ordered(s, t) + // @ unfold dp.Dp3s_iospec_bio3s_send(s, t) // @ io.TriggerBodyIoSend(newAbsPkt) - // @ ghost tN := io.dp3s_iospec_bio3s_send_T(t, newAbsPkt) + // @ ghost tN := io.Dp3s_iospec_bio3s_send_T(t, newAbsPkt) _, err = result.OutConn.WriteBatch(writeMsgs, syscall.MSG_DONTWAIT /*@, result.EgressID, t, newAbsPkt @*/) // @ ghost *ioSharedArg.Place = tN // @ fold SharedInv{dp, ioSharedArg}() @@ -1221,7 +1229,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta } // @ requires acc(dPtr, _) && *dPtr === d // @ requires acc(d.Mem(), _) - // @ requires result.EgressID elem d.getDomForwardingMetrics() + // @ requires result.EgressID elem d.GetDomForwardingMetrics() // @ decreases // @ outline( // ok metric @@ -1242,7 +1250,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ unfold acc(d.Mem(), R1) // @ unfold acc(bfdSessionsInv(d.bfdSessions), R1) // @ assert d.WellConfigured() - // @ assert 0 elem d.getDomForwardingMetrics() + // @ assert 0 elem d.GetDomForwardingMetrics() // @ ghost if d.bfdSessions != nil { unfold acc(accBfdSession(d.bfdSessions), R2) } // (VerifiedSCION) we introduce this to avoid problems with the invariants that @@ -1292,7 +1300,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ invariant acc(d.Mem(), _) && d.WellConfigured() // @ invariant d.getValSvc() != nil // @ invariant d.getValForwardingMetrics() != nil - // @ invariant 0 elem d.getDomForwardingMetrics() + // @ invariant 0 elem d.GetDomForwardingMetrics() // @ invariant d.getMacFactory() != nil // @ invariant dp.Valid() // @ invariant d.DpAgreesWithSpec(dp) @@ -1306,8 +1314,8 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ requires acc(d.Mem(), _) && d.WellConfigured() // @ requires d.getValSvc() != nil // @ requires d.getValForwardingMetrics() != nil - // @ requires 0 elem d.getDomForwardingMetrics() - // @ requires i elem d.getDomForwardingMetrics() + // @ requires 0 elem d.GetDomForwardingMetrics() + // @ requires i elem d.GetDomForwardingMetrics() // @ requires d.getMacFactory() != nil // @ requires c != nil && acc(c.Mem(), _) // contracts for IO-spec @@ -1322,7 +1330,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ ghost if d.external != nil { unfold acc(accBatchConn(d.external), R50) } // @ assert v elem range(d.external) // @ assert acc(v.Mem(), _) - // @ d.InDomainExternalInForwardingMetrics3(ifID) + // @ d.inDomainExternalInForwardingMetrics3(ifID) // @ ghost if d.external != nil { fold acc(accBatchConn(d.external), R50) } go cl(ifID, v /*@, ioLockRun, ioSharedArgRun, dp @*/) //@ as closure2 } @@ -1332,7 +1340,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ requires acc(d.Mem(), _) && d.WellConfigured() // @ requires d.getValSvc() != nil // @ requires d.getValForwardingMetrics() != nil - // @ requires 0 elem d.getDomForwardingMetrics() + // @ requires 0 elem d.GetDomForwardingMetrics() // @ requires d.getMacFactory() != nil // @ requires c != nil && acc(c.Mem(), _) // contracts for IO-spec @@ -1378,7 +1386,7 @@ func (d *DataPlane) Run(ctx context.Context /*@, ghost place io.Place, ghost sta // @ decreases func (d *DataPlane) initMetrics( /*@ ghost dp io.DataPlaneSpec @*/ ) { // @ assert reveal d.PreWellConfigured() - // @ reveal d.getDomExternal() + // @ reveal d.GetDomExternal() // @ assert reveal d.DpAgreesWithSpec(dp) // @ assert unfolding acc(d.Mem(), _) in // @ unfolding acc(neighborIAsInv(d.neighborIAs), _) in @@ -1465,7 +1473,7 @@ func (d *DataPlane) initMetrics( /*@ ghost dp io.DataPlaneSpec @*/ ) { // @ fold neighborIAsInv(d.neighborIAs) // @ fold linkTypesInv(d.linkTypes) // @ fold d.Mem() - // @ reveal d.getDomExternal() + // @ reveal d.GetDomExternal() // @ reveal d.WellConfigured() // @ assert reveal d.DpAgreesWithSpec(dp) } @@ -1499,7 +1507,7 @@ func newPacketProcessor(d *DataPlane, ingressID uint16) (res *scionPacketProcess } // @ fold sl.Bytes(p.macBuffers.scionInput, 0, len(p.macBuffers.scionInput)) // @ fold sl.Bytes(p.macBuffers.epicInput, 0, len(p.macBuffers.epicInput)) - // @ fold slayers.PathPoolMem(p.scionLayer.pathPool, p.scionLayer.pathPoolRaw) + // @ p.scionLayer.EstablishHiddenPathPoolMem() p.scionLayer.RecyclePaths() // @ fold p.scionLayer.NonInitMem() // @ fold p.hbhLayer.NonInitMem() @@ -1568,10 +1576,10 @@ func (p *scionPacketProcessor) reset() (err error) { // @ requires dp.Valid() // @ requires acc(ioLock.LockP(), _) // @ requires ioLock.LockInv() == SharedInv{dp, ioSharedArg} -// @ requires let absPkt := absIO_val(rawPkt, p.getIngressID()) in -// @ absPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.ifsToIO_ifs(p.getIngressID()), absPkt.ValPkt_2) +// @ requires let AbsPkt := AbsIO_val(rawPkt, p.getIngressID()) in +// @ AbsPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.IfsToIO_ifs(p.getIngressID()), AbsPkt.ValPkt_2) // @ ensures respr.OutPkt != nil ==> -// @ newAbsPkt == absIO_val(respr.OutPkt, respr.EgressID) +// @ newAbsPkt == AbsIO_val(respr.OutPkt, respr.EgressID) // @ ensures (respr.OutPkt == nil) == (newAbsPkt == io.ValUnit{}) // @ ensures newAbsPkt.isValPkt ==> // @ ElemWitness(ioSharedArg.OBufY, newAbsPkt.ValPkt_1, newAbsPkt.ValPkt_2) @@ -1897,12 +1905,12 @@ func (p *scionPacketProcessor) processIntraBFD(data []byte) (res error) { // @ requires p.scionLayer.EqPathType(ub) // @ requires acc(ioLock.LockP(), _) // @ requires ioLock.LockInv() == SharedInv{dp, ioSharedArg} -// @ requires let absPkt := absIO_val(p.rawPkt, p.ingressID) in -// @ absPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.ifsToIO_ifs(p.ingressID), absPkt.ValPkt_2) +// @ requires let AbsPkt := AbsIO_val(p.rawPkt, p.ingressID) in +// @ AbsPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.IfsToIO_ifs(p.ingressID), AbsPkt.ValPkt_2) // @ ensures reserr == nil && newAbsPkt.isValPkt ==> // @ ElemWitness(ioSharedArg.OBufY, newAbsPkt.ValPkt_1, newAbsPkt.ValPkt_2) // @ ensures respr.OutPkt != nil ==> -// @ newAbsPkt == absIO_val(respr.OutPkt, respr.EgressID) +// @ newAbsPkt == AbsIO_val(respr.OutPkt, respr.EgressID) // @ ensures reserr != nil && respr.OutPkt != nil ==> // @ newAbsPkt.isValUnsupported // @ ensures (respr.OutPkt == nil) == (newAbsPkt == io.ValUnit{}) @@ -1981,12 +1989,12 @@ func (p *scionPacketProcessor) processSCION( /*@ ghost ub []byte, ghost llIsNil // @ p.scionLayer.EqAbsHeader(ub) && p.scionLayer.ValidScionInitSpec(ub) // @ requires acc(ioLock.LockP(), _) // @ requires ioLock.LockInv() == SharedInv{dp, ioSharedArg} -// @ requires let absPkt := absIO_val(p.rawPkt, p.ingressID) in -// @ absPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.ifsToIO_ifs(p.ingressID), absPkt.ValPkt_2) +// @ requires let AbsPkt := AbsIO_val(p.rawPkt, p.ingressID) in +// @ AbsPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.IfsToIO_ifs(p.ingressID), AbsPkt.ValPkt_2) // @ ensures reserr == nil && newAbsPkt.isValPkt ==> // @ ElemWitness(ioSharedArg.OBufY, newAbsPkt.ValPkt_1, newAbsPkt.ValPkt_2) // @ ensures respr.OutPkt != nil ==> -// @ newAbsPkt == absIO_val(respr.OutPkt, respr.EgressID) +// @ newAbsPkt == AbsIO_val(respr.OutPkt, respr.EgressID) // @ ensures reserr != nil && respr.OutPkt != nil ==> // @ newAbsPkt.isValUnsupported // @ ensures (respr.OutPkt == nil) == (newAbsPkt == io.ValUnit{}) @@ -2196,7 +2204,9 @@ func (p *scionPacketProcessor) packSCMP( if p.lastLayer.NextLayerType( /*@ ubLL @*/ ) == slayers.LayerTypeSCMP { // @ llIsScmp = true var scmpLayer /*@@@*/ slayers.SCMP - // @ fold scmpLayer.NonInitMem() + // (VerifiedSCION) NonInitMem covers the private state of the layer, so a + // client cannot fold it; it is established by the lemma below instead. + // @ scmpLayer.EstablishNonInitMem() pld /*@ , start, end @*/ := p.lastLayer.LayerPayload( /*@ ubLL @*/ ) // @ sl.SplitRange_Bytes(ub, startLL, endLL, writePerm) // @ maybeStartPld = start @@ -2269,9 +2279,9 @@ func (p *scionPacketProcessor) packSCMP( // @ slayers.ValidPktMetaHdr(ub) && // @ p.scionLayer.EqAbsHeader(ub) && // @ p.scionLayer.ValidPathMetaData(ub) -// @ ensures reserr == nil ==> absPkt(ub).PathNotFullyTraversed() -// @ ensures reserr == nil ==> p.EqAbsHopField(absPkt(ub)) -// @ ensures reserr == nil ==> p.EqAbsInfoField(absPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub).PathNotFullyTraversed() +// @ ensures reserr == nil ==> p.EqAbsHopField(AbsPkt(ub)) +// @ ensures reserr == nil ==> p.EqAbsInfoField(AbsPkt(ub)) // @ ensures old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) // @ ensures respr.OutPkt == nil // @ decreases @@ -2339,12 +2349,12 @@ func (p *scionPacketProcessor) parsePath( /*@ ghost ub []byte @*/ ) (respr proce // @ p.SubSliceAbsPktToAbsPkt(ub, startScionP, endScionP) // @ absPktFutureLemma(ub) // @ p.path.DecodingLemma(ubScionPath, p.infoField, p.hopField) - // @ assert reveal p.path.EqAbsInfoField(p.path.absPkt(ubScionPath), + // @ assert reveal p.path.EqAbsInfoField(p.path.AbsPkt(ubScionPath), // @ p.infoField.ToAbsInfoField()) - // @ assert reveal p.path.EqAbsHopField(p.path.absPkt(ubScionPath), + // @ assert reveal p.path.EqAbsHopField(p.path.AbsPkt(ubScionPath), // @ p.hopField.Abs()) - // @ assert reveal p.EqAbsHopField(absPkt(ub)) - // @ assert reveal p.EqAbsInfoField(absPkt(ub)) + // @ assert reveal p.EqAbsHopField(AbsPkt(ub)) + // @ assert reveal p.EqAbsInfoField(AbsPkt(ub)) // @ assert old(reveal slayers.IsSupportedPkt(ub)) == reveal slayers.IsSupportedPkt(ub) return processResult{}, nil } @@ -2360,7 +2370,7 @@ func (p *scionPacketProcessor) parsePath( /*@ ghost ub []byte @*/ ) (respr proce // @ requires sl.Bytes(p.buffer.UBuf(), 0, len(p.buffer.UBuf())) // pres for IO: // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() // @ preserves ubLL == nil || ubLL === ubScionL[startLL:endLL] // @ preserves acc(&p.lastLayer, R55) && p.lastLayer != nil // @ preserves &p.scionLayer !== p.lastLayer ==> @@ -2384,11 +2394,11 @@ func (p *scionPacketProcessor) parsePath( /*@ ghost ub []byte @*/ ) (respr proce // @ respr === processResult{} // posts for IO: // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL).PathNotFullyTraversed() -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL).PathNotFullyTraversed() +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) validateHopExpiry( /*@ ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { expiration := util.SecsToTime(p.infoField.Timestamp). @@ -2477,16 +2487,16 @@ func (p *scionPacketProcessor) validateHopExpiry( /*@ ghost ubScionL []byte, gho // @ respr === processResult{} // contracts for IO-spec // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ubScionL)) -// @ requires p.EqAbsInfoField(absPkt(ubScionL)) +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ubScionL)) +// @ requires p.EqAbsInfoField(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) // @ ensures reserr == nil ==> -// @ AbsValidateIngressIDConstraint(absPkt(ubScionL), path.ifsToIO_ifs(p.ingressID)) +// @ AbsValidateIngressIDConstraint(AbsPkt(ubScionL), path.IfsToIO_ifs(p.ingressID)) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) validateIngressID( /*@ ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int@*/ ) (respr processResult, reserr error) { pktIngressID := p.hopField.ConsIngress @@ -2509,10 +2519,10 @@ func (p *scionPacketProcessor) validateIngressID( /*@ ghost ubScionL []byte, gho // @ } return tmpRes, tmpErr } - // @ ghost oldPkt := absPkt(ubScionL) + // @ ghost oldPkt := AbsPkt(ubScionL) // @ reveal p.EqAbsHopField(oldPkt) // @ reveal p.EqAbsInfoField(oldPkt) - // @ assert reveal AbsValidateIngressIDConstraint(oldPkt, path.ifsToIO_ifs(p.ingressID)) + // @ assert reveal AbsValidateIngressIDConstraint(oldPkt, path.IfsToIO_ifs(p.ingressID)) // @ fold p.d.validResult(respr, false) return processResult{}, nil } @@ -2547,15 +2557,15 @@ func (p *scionPacketProcessor) validateIngressID( /*@ ghost ubScionL []byte, gho // @ respr === processResult{} // contracts for IO-spec // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) // @ ensures reserr == nil ==> p.DstIsLocalIngressID(ubScionL) // @ ensures reserr == nil ==> p.LastHopLen(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL).PathNotFullyTraversed() -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL).PathNotFullyTraversed() +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) validateSrcDstIA( /*@ ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { // @ assert unfolding acc(p.scionLayer.Mem(ubScionL), R56) in slayers.CmnHdrLen <= len(ubScionL) @@ -2655,7 +2665,7 @@ func (p *scionPacketProcessor) validateSrcDstIA( /*@ ghost ubScionL []byte, ghos // @ respr.OutPkt === p.buffer.UBuf() // @ ensures reserr != nil && reserr.ErrorMem() // @ ensures respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) invalidSrcIA( // @ ghost ub []byte, @@ -2705,7 +2715,7 @@ func (p *scionPacketProcessor) invalidSrcIA( // @ respr.OutPkt === p.buffer.UBuf() // @ ensures reserr != nil && reserr.ErrorMem() // @ ensures respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) invalidDstIA( // @ ghost ub []byte, @@ -2850,32 +2860,32 @@ func (p *scionPacketProcessor) validateTransitUnderlaySrc( /*@ ghost ub []byte @ // @ requires p.d.WellConfigured() // @ requires p.d.DpAgreesWithSpec(dp) // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ubScionL)) -// @ requires p.EqAbsInfoField(absPkt(ubScionL)) +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ubScionL)) +// @ requires p.EqAbsInfoField(AbsPkt(ubScionL)) // @ requires p.segmentChange ==> -// @ absPkt(ubScionL).RightSeg != none[io.Seg] && len(get(absPkt(ubScionL).RightSeg).Past) > 0 +// @ AbsPkt(ubScionL).RightSeg != none[io.Seg] && len(get(AbsPkt(ubScionL).RightSeg).Past) > 0 // @ requires !p.segmentChange ==> -// @ AbsValidateIngressIDConstraint(absPkt(ubScionL), path.ifsToIO_ifs(p.ingressID)) +// @ AbsValidateIngressIDConstraint(AbsPkt(ubScionL), path.IfsToIO_ifs(p.ingressID)) // @ requires p.segmentChange ==> -// @ AbsValidateIngressIDConstraintXover(absPkt(ubScionL), path.ifsToIO_ifs(p.ingressID)) +// @ AbsValidateIngressIDConstraintXover(AbsPkt(ubScionL), path.IfsToIO_ifs(p.ingressID)) // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) -// @ ensures reserr == nil ==> p.NoBouncingPkt(absPkt(ubScionL)) +// @ ensures reserr == nil ==> p.NoBouncingPkt(AbsPkt(ubScionL)) // @ ensures reserr == nil && !p.segmentChange ==> -// @ AbsValidateEgressIDConstraint(absPkt(ubScionL), (p.ingressID != 0), dp) +// @ AbsValidateEgressIDConstraint(AbsPkt(ubScionL), (p.ingressID != 0), dp) // @ ensures reserr == nil && p.segmentChange ==> -// @ absPkt(ubScionL).RightSeg != none[io.Seg] && len(get(absPkt(ubScionL).RightSeg).Past) > 0 +// @ AbsPkt(ubScionL).RightSeg != none[io.Seg] && len(get(AbsPkt(ubScionL).RightSeg).Past) > 0 // @ ensures reserr == nil && p.segmentChange ==> -// @ p.ingressID != 0 && AbsValidateEgressIDConstraintXover(absPkt(ubScionL), dp) +// @ p.ingressID != 0 && AbsValidateEgressIDConstraintXover(AbsPkt(ubScionL), dp) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) validateEgressID( /*@ ghost dp io.DataPlaneSpec, ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { - // @ ghost oldPkt := absPkt(ubScionL) + // @ ghost oldPkt := AbsPkt(ubScionL) pktEgressID := p.egressInterface( /*@ oldPkt @*/ ) - // @ reveal AbsEgressInterfaceConstraint(oldPkt, path.ifsToIO_ifs(pktEgressID)) + // @ reveal AbsEgressInterfaceConstraint(oldPkt, path.IfsToIO_ifs(pktEgressID)) // @ p.d.getInternalNextHops() // @ if p.d.internalNextHops != nil { unfold acc(accAddr(p.d.internalNextHops), _) } _, ih := p.d.internalNextHops[pktEgressID] @@ -2907,11 +2917,11 @@ func (p *scionPacketProcessor) validateEgressID( /*@ ghost dp io.DataPlaneSpec, // @ p.EstablishNoBouncingPkt(oldPkt, pktEgressID) // @ p.d.getLinkTypesMem() ingress, egress := p.d.linkTypes[p.ingressID], p.d.linkTypes[pktEgressID] - // @ p.d.LinkTypesLemma(dp) + // @ p.d.linkTypesLemma(dp) if !p.segmentChange { // Check that the interface pair is valid within a single segment. // No check required if the packet is received from an internal interface. - // @ assert reveal AbsValidateIngressIDConstraint(oldPkt, path.ifsToIO_ifs(p.ingressID)) + // @ assert reveal AbsValidateIngressIDConstraint(oldPkt, path.IfsToIO_ifs(p.ingressID)) switch { case p.ingressID == 0: // @ assert reveal AbsValidateEgressIDConstraint(oldPkt, (p.ingressID != 0), dp) @@ -2944,7 +2954,7 @@ func (p *scionPacketProcessor) validateEgressID( /*@ ghost dp io.DataPlaneSpec, return tmpRes, tmpErr } } - // @ assert reveal AbsValidateIngressIDConstraintXover(oldPkt, path.ifsToIO_ifs(p.ingressID)) + // @ assert reveal AbsValidateIngressIDConstraintXover(oldPkt, path.IfsToIO_ifs(p.ingressID)) // Check that the interface pair is valid on a segment switch. // Having a segment change received from the internal interface is never valid. switch { @@ -2985,11 +2995,11 @@ func (p *scionPacketProcessor) validateEgressID( /*@ ghost dp io.DataPlaneSpec, // @ requires acc(&p.ingressID, R21) // preconditions for IO: // @ requires slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ requires absPkt(ub).PathNotFullyTraversed() +// @ requires AbsPkt(ub).PathNotFullyTraversed() // @ requires acc(&p.d, R55) && acc(p.d.Mem(), _) && acc(&p.ingressID, R55) // @ requires p.LastHopLen(ub) -// @ requires p.EqAbsHopField(absPkt(ub)) -// @ requires p.EqAbsInfoField(absPkt(ub)) +// @ requires p.EqAbsHopField(AbsPkt(ub)) +// @ requires p.EqAbsInfoField(AbsPkt(ub)) // @ ensures acc(&p.ingressID, R21) // @ ensures acc(&p.hopField, R20) // @ ensures sl.Bytes(ub, 0, len(ub)) @@ -3000,12 +3010,12 @@ func (p *scionPacketProcessor) validateEgressID( /*@ ghost dp io.DataPlaneSpec, // posconditions for IO: // @ ensures acc(&p.d, R55) && acc(p.d.Mem(), _) && acc(&p.ingressID, R55) // @ ensures err == nil ==> slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ ensures err == nil ==> absPkt(ub).PathNotFullyTraversed() +// @ ensures err == nil ==> AbsPkt(ub).PathNotFullyTraversed() // @ ensures err == nil ==> -// @ absPkt(ub) == AbsUpdateNonConsDirIngressSegID(old(absPkt(ub)), path.ifsToIO_ifs(p.ingressID)) +// @ AbsPkt(ub) == AbsUpdateNonConsDirIngressSegID(old(AbsPkt(ub)), path.IfsToIO_ifs(p.ingressID)) // @ ensures err == nil ==> p.LastHopLen(ub) -// @ ensures err == nil ==> p.EqAbsHopField(absPkt(ub)) -// @ ensures err == nil ==> p.EqAbsInfoField(absPkt(ub)) +// @ ensures err == nil ==> p.EqAbsHopField(AbsPkt(ub)) +// @ ensures err == nil ==> p.EqAbsInfoField(AbsPkt(ub)) // @ ensures err == nil ==> old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) // @ decreases func (p *scionPacketProcessor) updateNonConsDirIngressSegID( /*@ ghost ub []byte @*/ ) (err error) { @@ -3033,13 +3043,13 @@ func (p *scionPacketProcessor) updateNonConsDirIngressSegID( /*@ ghost ub []byte // means this comes from this AS itself, so nothing has to be done. // TODO(lukedirtwalker): For packets destined to peer links this shouldn't // be updated. - // @ reveal p.EqAbsInfoField(absPkt(ub)) - // @ reveal p.EqAbsHopField(absPkt(ub)) + // @ reveal p.EqAbsInfoField(AbsPkt(ub)) + // @ reveal p.EqAbsHopField(AbsPkt(ub)) if !p.infoField.ConsDir && p.ingressID != 0 { p.infoField.UpdateSegID(p.hopField.Mac /*@, p.hopField.Abs() @*/) // @ reveal p.LastHopLen(ub) // @ assert path.AbsUInfoFromUint16(p.infoField.SegID) == - // @ old(io.upd_uinfo(path.AbsUInfoFromUint16(p.infoField.SegID), p.hopField.Abs())) + // @ old(io.Upd_uinfo(path.AbsUInfoFromUint16(p.infoField.SegID), p.hopField.Abs())) // (VerifiedSCION) the following property is guaranteed by the type system, but Gobra cannot infer it yet // @ assume 0 <= p.path.GetCurrINF(ubScionPath) // @ sl.SplitRange_Bytes(ub, startScionP, endScionP, HalfPerm) @@ -3065,13 +3075,13 @@ func (p *scionPacketProcessor) updateNonConsDirIngressSegID( /*@ ghost ub []byte // @ p.SubSliceAbsPktToAbsPkt(ub, startScionP, endScionP) // @ ghost sl.CombineRange_Bytes(ub, startScionP, endScionP, HalfPerm) // @ absPktFutureLemma(ub) - // @ assert absPkt(ub).CurrSeg.UInfo == - // @ old(io.upd_uinfo(path.AbsUInfoFromUint16(p.infoField.SegID), p.hopField.Abs())) - // @ assert reveal p.EqAbsInfoField(absPkt(ub)) - // @ assert reveal p.EqAbsHopField(absPkt(ub)) + // @ assert AbsPkt(ub).CurrSeg.UInfo == + // @ old(io.Upd_uinfo(path.AbsUInfoFromUint16(p.infoField.SegID), p.hopField.Abs())) + // @ assert reveal p.EqAbsInfoField(AbsPkt(ub)) + // @ assert reveal p.EqAbsHopField(AbsPkt(ub)) // @ assert reveal p.LastHopLen(ub) } - // @ assert absPkt(ub) == reveal AbsUpdateNonConsDirIngressSegID(old(absPkt(ub)), path.ifsToIO_ifs(p.ingressID)) + // @ assert AbsPkt(ub) == reveal AbsUpdateNonConsDirIngressSegID(old(AbsPkt(ub)), path.IfsToIO_ifs(p.ingressID)) return nil } @@ -3162,21 +3172,21 @@ func (p *scionPacketProcessor) currentHopPointer( /*@ ghost ubScionL []byte @*/ // @ ensures reserr == nil ==> sl.Bytes(p.cachedMac, 0, len(p.cachedMac)) // contracts for IO-spec // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ubScionL)) -// @ requires p.EqAbsInfoField(absPkt(ubScionL)) +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ubScionL)) +// @ requires p.EqAbsInfoField(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL).PathNotFullyTraversed() -// @ ensures reserr == nil ==> AbsVerifyCurrentMACConstraint(absPkt(ubScionL), dp) +// @ ensures reserr == nil ==> AbsPkt(ubScionL).PathNotFullyTraversed() +// @ ensures reserr == nil ==> AbsVerifyCurrentMACConstraint(AbsPkt(ubScionL), dp) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> p.DstIsLocalIngressID(ubScionL) == old(p.DstIsLocalIngressID(ubScionL)) // @ ensures reserr == nil ==> p.LastHopLen(ubScionL) == old(p.LastHopLen(ubScionL)) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) verifyCurrentMAC( /*@ ghost dp io.DataPlaneSpec, ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { - // @ ghost oldPkt := absPkt(ubScionL) + // @ ghost oldPkt := AbsPkt(ubScionL) fullMac := path.FullMAC(p.mac, p.infoField, p.hopField, p.macBuffers.scionInput) // @ fold acc(sl.Bytes(p.hopField.Mac[:path.MacLen], 0, path.MacLen), R21) // @ defer unfold acc(sl.Bytes(p.hopField.Mac[:path.MacLen], 0, path.MacLen), R21) @@ -3225,7 +3235,7 @@ func (p *scionPacketProcessor) verifyCurrentMAC( /*@ ghost dp io.DataPlaneSpec, // (VerifiedSCION) Assumptions for Cryptography: // @ absInf := p.infoField.ToAbsInfoField() // @ absHF := p.hopField.Abs() - // @ AssumeForIO(dp.hf_valid(absInf.ConsDir, absInf.AInfo.V, absInf.UInfo, absHF)) + // @ AssumeForIO(dp.Hf_valid(absInf.ConsDir, absInf.AInfo.V, absInf.UInfo, absHF)) // @ reveal AbsVerifyCurrentMACConstraint(oldPkt, dp) // @ fold p.d.validResult(processResult{}, false) return processResult{}, nil @@ -3242,7 +3252,7 @@ func (p *scionPacketProcessor) verifyCurrentMAC( /*@ ghost dp io.DataPlaneSpec, // @ requires acc(&p.d, R15) && acc(p.d.Mem(), _) // pres for IO: // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() // @ preserves acc(&p.ingressID, R40) // @ preserves ubLL == nil || ubLL === ubScionL[startLL:endLL] // @ preserves acc(&p.lastLayer, R55) && p.lastLayer != nil @@ -3271,11 +3281,11 @@ func (p *scionPacketProcessor) verifyCurrentMAC( /*@ ghost dp io.DataPlaneSpec, // @ respr === processResult{} // posts for IO: // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL).PathNotFullyTraversed() -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL).PathNotFullyTraversed() +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases 0 if sync.IgnoreBlockingForTermination() func (p *scionPacketProcessor) resolveInbound( /*@ ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (resaddr *net.UDPAddr, respr processResult, reserr error /*@ , ghost addrAliasesUb bool @*/) { // (VerifiedSCION) the parameter used to be p.scionLayer, @@ -3312,9 +3322,9 @@ func (p *scionPacketProcessor) resolveInbound( /*@ ghost ubScionL []byte, ghost // @ requires !p.GetIsXoverSpec(ub) // Preconditions for IO: // @ requires slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ requires absPkt(ub).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ub)) -// @ requires p.EqAbsInfoField(absPkt(ub)) +// @ requires AbsPkt(ub).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ub)) +// @ requires p.EqAbsInfoField(AbsPkt(ub)) // @ ensures acc(&p.infoField) // @ ensures acc(&p.hopField, R20) // @ ensures sl.Bytes(ub, 0, len(ub)) @@ -3327,8 +3337,8 @@ func (p *scionPacketProcessor) resolveInbound( /*@ ghost ubScionL []byte, ghost // @ ensures reserr != nil ==> reserr.ErrorMem() // Postconditions for IO: // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ ensures reserr == nil ==> len(absPkt(ub).CurrSeg.Future) >= 0 -// @ ensures reserr == nil ==> absPkt(ub) == AbsProcessEgress(old(absPkt(ub))) +// @ ensures reserr == nil ==> len(AbsPkt(ub).CurrSeg.Future) >= 0 +// @ ensures reserr == nil ==> AbsPkt(ub) == AbsProcessEgress(old(AbsPkt(ub))) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) // @ decreases func (p *scionPacketProcessor) processEgress( /*@ ghost ub []byte @*/ ) (reserr error) { @@ -3357,8 +3367,8 @@ func (p *scionPacketProcessor) processEgress( /*@ ghost ub []byte @*/ ) (reserr // @ slayers.GetPathTypeSubslice(ub, slayers.CmnHdrLen) // @ p.AbsPktToSubSliceAbsPkt(ub, startScionP, endScionP) // @ p.scionLayer.ValidHeaderOffsetToSubSliceLemma(ub, startScionP) - // @ reveal p.EqAbsInfoField(absPkt(ub)) - // @ reveal p.EqAbsHopField(absPkt(ub)) + // @ reveal p.EqAbsInfoField(AbsPkt(ub)) + // @ reveal p.EqAbsHopField(AbsPkt(ub)) // @ sl.SplitRange_Bytes(ub, startScionP, endScionP, HalfPerm) // @ reveal p.scionLayer.ValidHeaderOffset(ub, startScionP) // @ unfold acc(p.scionLayer.Mem(ub), R55) @@ -3370,7 +3380,7 @@ func (p *scionPacketProcessor) processEgress( /*@ ghost ub []byte @*/ ) (reserr if p.infoField.ConsDir { p.infoField.UpdateSegID(p.hopField.Mac /*@, p.hopField.Abs() @*/) // @ assert path.AbsUInfoFromUint16(p.infoField.SegID) == - // @ old(io.upd_uinfo(path.AbsUInfoFromUint16(p.infoField.SegID), p.hopField.Abs())) + // @ old(io.Upd_uinfo(path.AbsUInfoFromUint16(p.infoField.SegID), p.hopField.Abs())) // @ assume 0 <= p.path.GetCurrINF(ubScionPath) if err := p.path.SetInfoField(p.infoField, int( /*@ unfolding acc(p.path.Mem(ubScionPath), R45) in (unfolding acc(p.path.Base.Mem(), R50) in @*/ p.path.PathMeta.CurrINF /*@ ) @*/) /*@ , ubScionPath @*/); err != nil { // TODO parameter problem invalid path @@ -3410,7 +3420,7 @@ func (p *scionPacketProcessor) processEgress( /*@ ghost ub []byte @*/ ) (reserr // @ p.SubSliceAbsPktToAbsPkt(ub, startScionP, endScionP) // @ ghost sl.CombineRange_Bytes(ub, startScionP, endScionP, HalfPerm) // @ absPktFutureLemma(ub) - // @ assert absPkt(ub) == reveal AbsProcessEgress(old(absPkt(ub))) + // @ assert AbsPkt(ub) == reveal AbsProcessEgress(old(AbsPkt(ub))) // @ ghost if typeOf(p.scionLayer.Path) == *epic.Path { // @ fold acc(p.scionLayer.Path.Mem(ubPath), 1-R55) // @ } @@ -3449,15 +3459,15 @@ func (p *scionPacketProcessor) processEgress( /*@ ghost ub []byte @*/ ) (reserr // @ ensures respr === processResult{} // @ ensures reserr != nil ==> reserr.ErrorMem() // Postconditions for IO: -// @ ensures reserr == nil ==> len(old(absPkt(ub)).CurrSeg.Future) == 1 -// @ ensures reserr == nil ==> old(absPkt(ub)).LeftSeg != none[io.Seg] -// @ ensures reserr == nil ==> len(get(old(absPkt(ub)).LeftSeg).Future) > 0 -// @ ensures reserr == nil ==> len(get(old(absPkt(ub)).LeftSeg).History) == 0 +// @ ensures reserr == nil ==> len(old(AbsPkt(ub)).CurrSeg.Future) == 1 +// @ ensures reserr == nil ==> old(AbsPkt(ub)).LeftSeg != none[io.Seg] +// @ ensures reserr == nil ==> len(get(old(AbsPkt(ub)).LeftSeg).Future) > 0 +// @ ensures reserr == nil ==> len(get(old(AbsPkt(ub)).LeftSeg).History) == 0 // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ ensures reserr == nil ==> absPkt(ub).PathNotFullyTraversed() -// @ ensures reserr == nil ==> p.EqAbsHopField(absPkt(ub)) -// @ ensures reserr == nil ==> p.EqAbsInfoField(absPkt(ub)) -// @ ensures reserr == nil ==> absPkt(ub) == AbsDoXover(old(absPkt(ub))) +// @ ensures reserr == nil ==> AbsPkt(ub).PathNotFullyTraversed() +// @ ensures reserr == nil ==> p.EqAbsHopField(AbsPkt(ub)) +// @ ensures reserr == nil ==> p.EqAbsInfoField(AbsPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub) == AbsDoXover(old(AbsPkt(ub))) // @ ensures reserr == nil ==> // @ old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) // @ ensures reserr == nil ==> p.path === p.scionLayer.GetScionPath(ub) @@ -3501,10 +3511,10 @@ func (p *scionPacketProcessor) doXover( /*@ ghost ub []byte, ghost currBase scio // @ p.AbsPktToSubSliceAbsPkt(ub, startScionP, endScionP) // @ assert p.path === p.scionLayer.GetScionPath(ub) // @ p.scionLayer.ValidHeaderOffsetToSubSliceLemma(ub, startScionP) - // @ ghost preAbsPkt := p.path.absPkt(ubScionPath) + // @ ghost preAbsPkt := p.path.AbsPkt(ubScionPath) // @ p.path.XoverLemma(ubScionPath) - // @ reveal p.EqAbsInfoField(absPkt(ub)) - // @ reveal p.EqAbsHopField(absPkt(ub)) + // @ reveal p.EqAbsInfoField(AbsPkt(ub)) + // @ reveal p.EqAbsHopField(AbsPkt(ub)) // @ sl.SplitRange_Bytes(ub, startScionP, endScionP, HalfPerm) // @ reveal p.scionLayer.ValidHeaderOffset(ub, startScionP) // @ unfold acc(p.scionLayer.Mem(ub), R55) @@ -3526,7 +3536,7 @@ func (p *scionPacketProcessor) doXover( /*@ ghost ub []byte, ghost currBase scio return processResult{}, serrors.WrapStr("incrementing path", err) } // @ assert p.path.GetBase(ubScionPath) == nextBase - // @ assert p.path.absPkt(ubScionPath) == scion.AbsXover(preAbsPkt) + // @ assert p.path.AbsPkt(ubScionPath) == scion.AbsXover(preAbsPkt) // @ ghost if typeOf(p.scionLayer.Path) == *epic.Path { // @ fold acc(p.scionLayer.Path.Mem(ubPath), R55) // @ } @@ -3545,10 +3555,10 @@ func (p *scionPacketProcessor) doXover( /*@ ghost ub []byte, ghost currBase scio // @ assert p.scionLayer.ValidHeaderOffset(ub, len(ub)) // @ assert p.path === p.scionLayer.GetScionPath(ub) // @ assert p.path.GetBase(ubScionPath) == nextBase - // @ assert len(get(old(absPkt(ub)).LeftSeg).Future) > 0 - // @ assert len(get(old(absPkt(ub)).LeftSeg).History) == 0 + // @ assert len(get(old(AbsPkt(ub)).LeftSeg).Future) > 0 + // @ assert len(get(old(AbsPkt(ub)).LeftSeg).History) == 0 // @ assert slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) - // @ assert absPkt(ub) == reveal AbsDoXover(old(absPkt(ub))) + // @ assert AbsPkt(ub) == reveal AbsDoXover(old(AbsPkt(ub))) // @ assert p.path === p.scionLayer.GetScionPath(ub) // @ assert p.path.GetBase(ubScionPath) == nextBase var err error @@ -3586,10 +3596,10 @@ func (p *scionPacketProcessor) doXover( /*@ ghost ub []byte, ghost currBase scio // @ ghost sl.CombineRange_Bytes(ub, startScionP, endScionP, HalfPerm/2) // @ absPktFutureLemma(ub) // @ p.path.DecodingLemma(ubScionPath, p.infoField, p.hopField) - // @ assert reveal p.path.EqAbsInfoField(p.path.absPkt(ubScionPath), p.infoField.ToAbsInfoField()) - // @ assert reveal p.path.EqAbsHopField(p.path.absPkt(ubScionPath), p.hopField.Abs()) - // @ assert reveal p.EqAbsHopField(absPkt(ub)) - // @ assert reveal p.EqAbsInfoField(absPkt(ub)) + // @ assert reveal p.path.EqAbsInfoField(p.path.AbsPkt(ubScionPath), p.infoField.ToAbsInfoField()) + // @ assert reveal p.path.EqAbsHopField(p.path.AbsPkt(ubScionPath), p.hopField.Abs()) + // @ assert reveal p.EqAbsHopField(AbsPkt(ub)) + // @ assert reveal p.EqAbsInfoField(AbsPkt(ub)) // @ ghost sl.CombineRange_Bytes(ub, startScionP, endScionP, HalfPerm/2) // @ ghost if typeOf(p.scionLayer.Path) == *epic.Path { // @ fold acc(p.scionLayer.Path.Mem(ubPath), 1-R55) @@ -3640,16 +3650,16 @@ func (p *scionPacketProcessor) ingressInterface( /*@ ghost ubPath []byte @*/ ) u // posts for IO: // @ ensures p.EqAbsInfoField(oldPkt) // @ ensures p.EqAbsHopField(oldPkt) -// @ ensures AbsEgressInterfaceConstraint(oldPkt, path.ifsToIO_ifs(egress)) +// @ ensures AbsEgressInterfaceConstraint(oldPkt, path.IfsToIO_ifs(egress)) // @ decreases func (p *scionPacketProcessor) egressInterface( /*@ ghost oldPkt io.Pkt @*/ ) (egress uint16) { // @ reveal p.EqAbsInfoField(oldPkt) // @ reveal p.EqAbsHopField(oldPkt) if p.infoField.ConsDir { - // @ assert reveal AbsEgressInterfaceConstraint(oldPkt, path.ifsToIO_ifs(p.hopField.ConsEgress)) + // @ assert reveal AbsEgressInterfaceConstraint(oldPkt, path.IfsToIO_ifs(p.hopField.ConsEgress)) return p.hopField.ConsEgress } - // @ assert reveal AbsEgressInterfaceConstraint(oldPkt, path.ifsToIO_ifs(p.hopField.ConsIngress)) + // @ assert reveal AbsEgressInterfaceConstraint(oldPkt, path.IfsToIO_ifs(p.hopField.ConsIngress)) return p.hopField.ConsIngress } @@ -3667,9 +3677,9 @@ func (p *scionPacketProcessor) egressInterface( /*@ ghost oldPkt io.Pkt @*/ ) (e // @ requires acc(&p.ingressID, R21) // pres for IO: // @ requires slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ requires absPkt(ub).PathNotFullyTraversed() -// @ requires p.EqAbsInfoField(absPkt(ub)) -// @ requires p.EqAbsHopField(absPkt(ub)) +// @ requires AbsPkt(ub).PathNotFullyTraversed() +// @ requires p.EqAbsInfoField(AbsPkt(ub)) +// @ requires p.EqAbsHopField(AbsPkt(ub)) // @ preserves ubLL == nil || ubLL === ub[startLL:endLL] // @ preserves acc(&p.lastLayer, R55) && p.lastLayer != nil // @ preserves &p.scionLayer !== p.lastLayer ==> @@ -3694,9 +3704,9 @@ func (p *scionPacketProcessor) egressInterface( /*@ ghost oldPkt io.Pkt @*/ ) (e // posts for IO: // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) -// @ ensures reserr == nil ==> absPkt(ub) == old(absPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub) == old(AbsPkt(ub)) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases 0 if sync.IgnoreBlockingForTermination() func (p *scionPacketProcessor) validateEgressUp( // @ ghost ub []byte, @@ -3704,7 +3714,7 @@ func (p *scionPacketProcessor) validateEgressUp( // @ ghost startLL int, // @ ghost endLL int, ) (respr processResult, reserr error) { - // @ ghost oldPkt := absPkt(ub) + // @ ghost oldPkt := AbsPkt(ub) egressID := p.egressInterface( /*@ oldPkt @ */ ) // @ p.d.getBfdSessionsMem() // @ ghost if p.d.bfdSessions != nil { unfold acc(accBfdSession(p.d.bfdSessions), _) } @@ -3779,21 +3789,21 @@ func (p *scionPacketProcessor) validateEgressUp( // @ requires slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) // @ requires p.DstIsLocalIngressID(ub) // @ requires p.LastHopLen(ub) -// @ requires absPkt(ub).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ub)) +// @ requires AbsPkt(ub).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ub)) // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) // @ ensures reserr == nil ==> p.DstIsLocalIngressID(ub) // @ ensures reserr == nil ==> p.LastHopLen(ub) -// @ ensures reserr == nil ==> absPkt(ub).PathNotFullyTraversed() -// @ ensures reserr == nil ==> p.EqAbsHopField(absPkt(ub)) -// @ ensures reserr == nil ==> absPkt(ub) == old(absPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub).PathNotFullyTraversed() +// @ ensures reserr == nil ==> p.EqAbsHopField(AbsPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub) == old(AbsPkt(ub)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) handleIngressRouterAlert( /*@ ghost ub []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { - // @ reveal p.EqAbsHopField(absPkt(ub)) - // @ assert let fut := absPkt(ub).CurrSeg.Future in + // @ reveal p.EqAbsHopField(AbsPkt(ub)) + // @ assert let fut := AbsPkt(ub).CurrSeg.Future in // @ fut == seq[io.HF]{p.hopField.Abs()} ++ fut[1:] // @ ghost ubPath := p.scionLayer.UBPath(ub) // @ ghost startP := p.scionLayer.PathStartIdx(ub) @@ -3850,7 +3860,7 @@ func (p *scionPacketProcessor) handleIngressRouterAlert( /*@ ghost ub []byte, gh // @ p.scionLayer.ValidHeaderOffsetFromSubSliceLemma(ub, startScionP) // @ p.SubSliceAbsPktToAbsPkt(ub, startScionP, endScionP) // @ absPktFutureLemma(ub) - // @ assert reveal p.EqAbsHopField(absPkt(ub)) + // @ assert reveal p.EqAbsHopField(AbsPkt(ub)) // @ assert reveal p.LastHopLen(ub) // @ assert p.scionLayer.EqAbsHeader(ub) // @ sl.CombineRange_Bytes(ub, startScionP, endScionP, HalfPerm) @@ -3909,21 +3919,21 @@ func (p *scionPacketProcessor) ingressRouterAlertFlag() (res *bool) { // @ respr === processResult{} // constracts for IO-spec // @ requires slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ requires absPkt(ub).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ub)) -// @ requires p.EqAbsInfoField(absPkt(ub)) +// @ requires AbsPkt(ub).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ub)) +// @ requires p.EqAbsInfoField(AbsPkt(ub)) // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ub) && p.scionLayer.EqAbsHeader(ub) -// @ ensures reserr == nil ==> absPkt(ub).PathNotFullyTraversed() -// @ ensures reserr == nil ==> p.EqAbsHopField(absPkt(ub)) -// @ ensures reserr == nil ==> p.EqAbsInfoField(absPkt(ub)) -// @ ensures reserr == nil ==> absPkt(ub) == old(absPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub).PathNotFullyTraversed() +// @ ensures reserr == nil ==> p.EqAbsHopField(AbsPkt(ub)) +// @ ensures reserr == nil ==> p.EqAbsInfoField(AbsPkt(ub)) +// @ ensures reserr == nil ==> AbsPkt(ub) == old(AbsPkt(ub)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ub)) == slayers.IsSupportedPkt(ub) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) handleEgressRouterAlert( /*@ ghost ub []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { - // @ reveal p.EqAbsHopField(absPkt(ub)) - // @ assert let fut := absPkt(ub).CurrSeg.Future in + // @ reveal p.EqAbsHopField(AbsPkt(ub)) + // @ assert let fut := AbsPkt(ub).CurrSeg.Future in // @ fut == seq[io.HF]{p.hopField.Abs()} ++ fut[1:] // @ ghost ubPath := p.scionLayer.UBPath(ub) // @ ghost startP := p.scionLayer.PathStartIdx(ub) @@ -3942,7 +3952,7 @@ func (p *scionPacketProcessor) handleEgressRouterAlert( /*@ ghost ub []byte, gho // @ fold p.d.validResult(processResult{}, false) return processResult{}, nil } - egressID := p.egressInterface( /*@ absPkt(ub) @*/ ) + egressID := p.egressInterface( /*@ AbsPkt(ub) @*/ ) // @ p.d.getExternalMem() // @ if p.d.external != nil { unfold acc(accBatchConn(p.d.external), _) } if _, ok := p.d.external[egressID]; !ok { @@ -3984,8 +3994,8 @@ func (p *scionPacketProcessor) handleEgressRouterAlert( /*@ ghost ub []byte, gho // @ p.scionLayer.ValidHeaderOffsetFromSubSliceLemma(ub, startScionP) // @ p.SubSliceAbsPktToAbsPkt(ub, startScionP, endScionP) // @ absPktFutureLemma(ub) - // @ assert reveal p.EqAbsHopField(absPkt(ub)) - // @ assert reveal p.EqAbsInfoField(absPkt(ub)) + // @ assert reveal p.EqAbsHopField(AbsPkt(ub)) + // @ assert reveal p.EqAbsInfoField(AbsPkt(ub)) // @ sl.CombineRange_Bytes(ub, startScionP, endScionP, HalfPerm) // @ ghost if typeOf(p.scionLayer.Path) == *epic.Path { fold acc(p.scionLayer.Path.Mem(ubPath), R20) } // @ fold acc(p.scionLayer.Mem(ub), R20) @@ -4015,8 +4025,8 @@ func (p *scionPacketProcessor) egressRouterAlertFlag() (res *bool) { // @ requires acc(&p.hopField, R20) // pres for IO: // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() -// @ requires p.EqAbsHopField(absPkt(ubScionL)) +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() +// @ requires p.EqAbsHopField(AbsPkt(ubScionL)) // @ preserves acc(&p.ingressID, R22) // @ preserves acc(&p.mac, R20) && p.mac != nil && p.mac.Mem() // @ preserves acc(&p.macBuffers.scionInput, R20) @@ -4046,15 +4056,15 @@ func (p *scionPacketProcessor) egressRouterAlertFlag() (res *bool) { // posts for IO: // @ ensures reserr == nil ==> old(p.DstIsLocalIngressID(ubScionL)) == p.DstIsLocalIngressID(ubScionL) // @ ensures reserr == nil ==> slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL).PathNotFullyTraversed() +// @ ensures reserr == nil ==> AbsPkt(ubScionL).PathNotFullyTraversed() // @ ensures reserr == nil ==> old(p.LastHopLen(ubScionL)) == p.LastHopLen(ubScionL) // @ ensures reserr == nil ==> -// @ old(p.EqAbsInfoField(absPkt(ubScionL))) == p.EqAbsInfoField(absPkt(ubScionL)) -// @ ensures reserr == nil ==> p.EqAbsHopField(absPkt(ubScionL)) -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ old(p.EqAbsInfoField(AbsPkt(ubScionL))) == p.EqAbsInfoField(AbsPkt(ubScionL)) +// @ ensures reserr == nil ==> p.EqAbsHopField(AbsPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) handleSCMPTraceRouteRequest( interfaceID uint16 /*@, ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/) (respr processResult, reserr error) { @@ -4109,7 +4119,7 @@ func (p *scionPacketProcessor) handleSCMPTraceRouteRequest( return processResult{}, nil } // @ unfold scmpP.Mem(scmpH.Payload) - // @ unfold scmpP.BaseLayer.Mem(scmpH.Payload, 4+addr.IABytes+slayers.scmpRawInterfaceLen) + // @ unfold scmpP.BaseLayer.Mem(scmpH.Payload, 4+addr.IABytes+slayers.SCMPRawInterfaceLen) // @ p.d.getLocalIA() scmpP = slayers.SCMPTraceroute{ Identifier: scmpP.Identifier, @@ -4161,14 +4171,14 @@ func (p *scionPacketProcessor) handleSCMPTraceRouteRequest( // @ respr === processResult{} // contracts for IO-spec // @ requires slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ requires absPkt(ubScionL).PathNotFullyTraversed() +// @ requires AbsPkt(ubScionL).PathNotFullyTraversed() // @ ensures reserr == nil ==> // @ slayers.ValidPktMetaHdr(ubScionL) && p.scionLayer.EqAbsHeader(ubScionL) -// @ ensures reserr == nil ==> absPkt(ubScionL).PathNotFullyTraversed() -// @ ensures reserr == nil ==> absPkt(ubScionL) == old(absPkt(ubScionL)) +// @ ensures reserr == nil ==> AbsPkt(ubScionL).PathNotFullyTraversed() +// @ ensures reserr == nil ==> AbsPkt(ubScionL) == old(AbsPkt(ubScionL)) // @ ensures reserr == nil ==> old(slayers.IsSupportedPkt(ubScionL)) == slayers.IsSupportedPkt(ubScionL) // @ ensures reserr != nil && respr.OutPkt != nil ==> -// @ absIO_val(respr.OutPkt, respr.EgressID).isValUnsupported +// @ AbsIO_val(respr.OutPkt, respr.EgressID).isValUnsupported // @ decreases func (p *scionPacketProcessor) validatePktLen( /*@ ghost ubScionL []byte, ghost ubLL []byte, ghost startLL int, ghost endLL int @*/ ) (respr processResult, reserr error) { // @ unfold acc(p.scionLayer.Mem(ubScionL), R20) @@ -4245,12 +4255,12 @@ func (p *scionPacketProcessor) validatePktLen( /*@ ghost ubScionL []byte, ghost // @ requires p.scionLayer.EqAbsHeader(ub) && p.scionLayer.EqPathType(ub) && p.scionLayer.ValidScionInitSpec(ub) // @ requires acc(ioLock.LockP(), _) // @ requires ioLock.LockInv() == SharedInv{dp, ioSharedArg} -// @ requires let absPkt := absIO_val(ub, p.ingressID) in -// @ absPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.ifsToIO_ifs(p.ingressID), absPkt.ValPkt_2) +// @ requires let AbsPkt := AbsIO_val(ub, p.ingressID) in +// @ AbsPkt.isValPkt ==> ElemWitness(ioSharedArg.IBufY, path.IfsToIO_ifs(p.ingressID), AbsPkt.ValPkt_2) // @ ensures reserr == nil && newAbsPkt.isValPkt ==> // @ ElemWitness(ioSharedArg.OBufY, newAbsPkt.ValPkt_1, newAbsPkt.ValPkt_2) // @ ensures respr.OutPkt != nil ==> -// @ newAbsPkt == absIO_val(respr.OutPkt, respr.EgressID) +// @ newAbsPkt == AbsIO_val(respr.OutPkt, respr.EgressID) // @ ensures reserr != nil && respr.OutPkt != nil ==> // @ newAbsPkt.isValUnsupported // @ ensures (respr.OutPkt == nil) == (newAbsPkt == io.ValUnit{}) @@ -4275,10 +4285,10 @@ func (p *scionPacketProcessor) process( // @ ghost var oldPkt io.Pkt // @ ghost if(slayers.IsSupportedPkt(ub)) { // @ absIO_valLemma(ub, p.ingressID) - // @ oldPkt = absIO_val(ub, p.ingressID).ValPkt_2 + // @ oldPkt = AbsIO_val(ub, p.ingressID).ValPkt_2 // @ } else { // @ absPktFutureLemma(ub) - // @ oldPkt = absPkt(ub) + // @ oldPkt = AbsPkt(ub) // @ } // @ nextPkt := oldPkt if r, err := p.validateHopExpiry( /*@ ub, ubLL, startLL, endLL @*/ ); err != nil { @@ -4289,7 +4299,7 @@ func (p *scionPacketProcessor) process( // @ p.scionLayer.DowngradePerm(ub) return r, err /*@, false, absReturnErr(r) @*/ } - // @ assert AbsValidateIngressIDConstraint(nextPkt, path.ifsToIO_ifs(p.ingressID)) + // @ assert AbsValidateIngressIDConstraint(nextPkt, path.IfsToIO_ifs(p.ingressID)) if r, err := p.validatePktLen( /*@ ub, ubLL, startLL, endLL @*/ ); err != nil { // @ p.scionLayer.DowngradePerm(ub) return r, err /*@, false, absReturnErr(r) @*/ @@ -4308,9 +4318,9 @@ func (p *scionPacketProcessor) process( // @ p.scionLayer.DowngradePerm(ub) return processResult{}, err /*@, false, absReturnErr(processResult{}) @*/ } - // @ assert absPkt(ub) == AbsUpdateNonConsDirIngressSegID(oldPkt, path.ifsToIO_ifs(p.ingressID)) - // @ nextPkt = absPkt(ub) - // @ AbsValidateIngressIDLemma(oldPkt, nextPkt, path.ifsToIO_ifs(p.ingressID)) + // @ assert AbsPkt(ub) == AbsUpdateNonConsDirIngressSegID(oldPkt, path.IfsToIO_ifs(p.ingressID)) + // @ nextPkt = AbsPkt(ub) + // @ AbsValidateIngressIDLemma(oldPkt, nextPkt, path.IfsToIO_ifs(p.ingressID)) if r, err := p.verifyCurrentMAC( /*@ dp, ub, ubLL, startLL, endLL @*/ ); err != nil { // @ p.scionLayer.DowngradePerm(ub) return r, err /*@, false, absReturnErr(r) @*/ @@ -4320,7 +4330,7 @@ func (p *scionPacketProcessor) process( // @ p.scionLayer.DowngradePerm(ub) return r, err /*@, false, absReturnErr(r) @*/ } - // @ assert nextPkt == absPkt(ub) + // @ assert nextPkt == AbsPkt(ub) // Inbound: pkts destined to the local IA. // @ p.d.getLocalIA() if /*@ unfolding acc(p.scionLayer.Mem(ub), R50) in (unfolding acc(p.scionLayer.HeaderMem(ub[slayers.CmnHdrLen:]), R55) in @*/ p.scionLayer.DstIA /*@ ) @*/ == p.d.localIA { @@ -4341,9 +4351,9 @@ func (p *scionPacketProcessor) process( // @ fold p.d.validResult(processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, aliasesUb) // @ assert ub === p.rawPkt // @ ghost if(slayers.IsSupportedPkt(ub)) { - // @ InternalEnterEvent(oldPkt, path.ifsToIO_ifs(p.ingressID), nextPkt, none[io.Ifs], ioLock, ioSharedArg, dp) + // @ InternalEnterEvent(oldPkt, path.IfsToIO_ifs(p.ingressID), nextPkt, none[io.Ifs], ioLock, ioSharedArg, dp) // @ } - // @ newAbsPkt = reveal absIO_val(p.rawPkt, 0) + // @ newAbsPkt = reveal AbsIO_val(p.rawPkt, 0) return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil /*@, aliasesUb, newAbsPkt @*/ } // Outbound: pkts leaving the local IA. @@ -4370,9 +4380,9 @@ func (p *scionPacketProcessor) process( } // @ assert p.path === p.scionLayer.GetScionPath(ub) // @ assert p.scionLayer.UBScionPath(ub) === ubScionPath - // @ assert absPkt(ub) == AbsDoXover(nextPkt) - // @ AbsValidateIngressIDXoverLemma(nextPkt, AbsDoXover(nextPkt), path.ifsToIO_ifs(p.ingressID)) - // @ nextPkt = absPkt(ub) + // @ assert AbsPkt(ub) == AbsDoXover(nextPkt) + // @ AbsValidateIngressIDXoverLemma(nextPkt, AbsDoXover(nextPkt), path.IfsToIO_ifs(p.ingressID)) + // @ nextPkt = AbsPkt(ub) if r, err := p.validateHopExpiry( /*@ ub, ubLL, startLL, endLL @*/ ); err != nil { // @ p.scionLayer.DowngradePerm(ub) return r, serrors.WithCtx(err, "info", "after xover") /*@, false, absReturnErr(r) @*/ @@ -4408,14 +4418,14 @@ func (p *scionPacketProcessor) process( // @ p.scionLayer.DowngradePerm(ub) return r, err /*@, false, absReturnErr(r) @*/ } - // @ assert nextPkt == absPkt(ub) + // @ assert nextPkt == AbsPkt(ub) if r, err := p.validateEgressUp( /*@ ub, ubLL, startLL, endLL @*/ ); err != nil { // @ p.scionLayer.DowngradePerm(ub) return r, err /*@, false, absReturnErr(r) @*/ } - // @ assert nextPkt == absPkt(ub) + // @ assert nextPkt == AbsPkt(ub) egressID := p.egressInterface( /*@ nextPkt @*/ ) - // @ assert AbsEgressInterfaceConstraint(nextPkt, path.ifsToIO_ifs(egressID)) + // @ assert AbsEgressInterfaceConstraint(nextPkt, path.IfsToIO_ifs(egressID)) // @ p.d.getExternalMem() // @ if p.d.external != nil { unfold acc(accBatchConn(p.d.external), _) } if c, ok := p.d.external[egressID]; ok { @@ -4426,16 +4436,16 @@ func (p *scionPacketProcessor) process( return processResult{}, err /*@, false, absReturnErr(processResult{}) @*/ } // @ p.d.InDomainExternalInForwardingMetrics(egressID) - // @ assert absPkt(ub) == AbsProcessEgress(nextPkt) - // @ nextPkt = absPkt(ub) + // @ assert AbsPkt(ub) == AbsProcessEgress(nextPkt) + // @ nextPkt = AbsPkt(ub) // @ ghost if(slayers.IsSupportedPkt(ub)) { // @ ghost if(!p.segmentChange) { - // @ ExternalEnterOrExitEvent(oldPkt, path.ifsToIO_ifs(p.ingressID), nextPkt, path.ifsToIO_ifs(egressID), ioLock, ioSharedArg, dp) + // @ ExternalEnterOrExitEvent(oldPkt, path.IfsToIO_ifs(p.ingressID), nextPkt, path.IfsToIO_ifs(egressID), ioLock, ioSharedArg, dp) // @ } else { - // @ XoverEvent(oldPkt, path.ifsToIO_ifs(p.ingressID), nextPkt, path.ifsToIO_ifs(egressID), ioLock, ioSharedArg, dp) + // @ XoverEvent(oldPkt, path.IfsToIO_ifs(p.ingressID), nextPkt, path.IfsToIO_ifs(egressID), ioLock, ioSharedArg, dp) // @ } // @ } - // @ newAbsPkt = reveal absIO_val(p.rawPkt, egressID) + // @ newAbsPkt = reveal AbsIO_val(p.rawPkt, egressID) // @ fold p.d.validResult(processResult{EgressID: egressID, OutConn: c, OutPkt: p.rawPkt}, false) return processResult{EgressID: egressID, OutConn: c, OutPkt: p.rawPkt}, nil /*@, false, newAbsPkt @*/ } @@ -4448,12 +4458,12 @@ func (p *scionPacketProcessor) process( // @ p.d.getInternal() // @ ghost if(slayers.IsSupportedPkt(ub)) { // @ if(!p.segmentChange) { - // @ InternalEnterEvent(oldPkt, path.ifsToIO_ifs(p.ingressID), nextPkt, none[io.Ifs], ioLock, ioSharedArg, dp) + // @ InternalEnterEvent(oldPkt, path.IfsToIO_ifs(p.ingressID), nextPkt, none[io.Ifs], ioLock, ioSharedArg, dp) // @ } else { - // @ XoverEvent(oldPkt, path.ifsToIO_ifs(p.ingressID), nextPkt, none[io.Ifs], ioLock, ioSharedArg, dp) + // @ XoverEvent(oldPkt, path.IfsToIO_ifs(p.ingressID), nextPkt, none[io.Ifs], ioLock, ioSharedArg, dp) // @ } // @ } - // @ newAbsPkt = reveal absIO_val(p.rawPkt, 0) + // @ newAbsPkt = reveal AbsIO_val(p.rawPkt, 0) // @ fold p.d.validResult(processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, false) return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil /*@, false, newAbsPkt @*/ } @@ -4506,7 +4516,7 @@ func (p *scionPacketProcessor) process( // @ requires !slayers.IsSupportedPkt(p.rawPkt) // @ ensures (respr.OutPkt == nil) == (newAbsPkt == io.ValUnit{}) // @ ensures respr.OutPkt != nil ==> -// @ newAbsPkt == absIO_val(respr.OutPkt, respr.EgressID) && +// @ newAbsPkt == AbsIO_val(respr.OutPkt, respr.EgressID) && // @ newAbsPkt.isValUnsupported // @ decreases 0 if sync.IgnoreBlockingForTermination() func (p *scionPacketProcessor) processOHP() (respr processResult, reserr error /*@ , ghost addrAliasesPkt bool, ghost newAbsPkt io.Val @*/) { @@ -4604,11 +4614,11 @@ func (p *scionPacketProcessor) processOHP() (respr processResult, reserr error / // @ ghost if p.d.external != nil { unfold acc(accBatchConn(p.d.external), _) } if c, ok := p.d.external[ohp.FirstHop.ConsEgress]; ok { // @ p.d.getDomExternalLemma() - // @ assert ohp.FirstHop.ConsEgress elem p.d.getDomExternal() + // @ assert ohp.FirstHop.ConsEgress elem p.d.GetDomExternal() // @ p.d.InDomainExternalInForwardingMetrics(ohp.FirstHop.ConsEgress) // @ fold p.d.validResult(processResult{EgressID: ohp.FirstHop.ConsEgress, OutConn: c, OutPkt: p.rawPkt}, false) return processResult{EgressID: ohp.FirstHop.ConsEgress, OutConn: c, OutPkt: p.rawPkt}, - nil /*@ , false, reveal absIO_val(respr.OutPkt, respr.EgressID) @*/ + nil /*@ , false, reveal AbsIO_val(respr.OutPkt, respr.EgressID) @*/ } // TODO parameter problem invalid interface // @ establishCannotRoute() @@ -4673,7 +4683,7 @@ func (p *scionPacketProcessor) processOHP() (respr processResult, reserr error / // @ p.d.getInternal() // @ assert p.d.internal != nil ==> acc(p.d.internal.Mem(), _) // @ fold p.d.validResult(processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, addrAliases) - return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil /*@ , addrAliases, reveal absIO_val(respr.OutPkt, 0) @*/ + return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil /*@ , addrAliases, reveal AbsIO_val(respr.OutPkt, 0) @*/ } // @ requires acc(d.Mem(), _) @@ -5085,7 +5095,13 @@ func (p *scionPacketProcessor) prepareSCMP( scionL.NextHdr = slayers.L4SCMP typeCode := slayers.CreateSCMPTypeCode(typ, code) - scmpH /*@@@*/ := slayers.SCMP{TypeCode: typeCode} + // (VerifiedSCION) the layer is built from its zero value, because the lemma + // that establishes NonInitMem (which covers the private state of the layer, + // and can thus not be folded by a client) requires it. + scmpH /*@@@*/ := slayers.SCMP{} + // @ scmpH.EstablishNonInitMem() + // @ unfold scmpH.NonInitMem() + scmpH.TypeCode = typeCode scmpH.SetNetworkLayerForChecksum(&scionL) if err := p.buffer.Clear(); err != nil { @@ -5295,9 +5311,9 @@ func nextHdr(layer gopacket.DecodingLayer /*@ , ghost ubuf []byte @*/) slayers.L case *slayers.SCION: return /*@ unfolding acc(v.Mem(ubuf), R20) in @*/ v.NextHdr case *slayers.EndToEndExtnSkipper: - return /*@ unfolding acc(v.Mem(ubuf), R20) in (unfolding acc(v.extnBase.Mem(ubuf), R20) in @*/ v.NextHdr /*@ ) @*/ + return /*@ unfolding acc(v.Mem(ubuf), R20) in @*/ v.NextHdr case *slayers.HopByHopExtnSkipper: - return /*@ unfolding acc(v.Mem(ubuf), R20) in (unfolding acc(v.extnBase.Mem(ubuf), R20) in @*/ v.NextHdr /*@ ) @*/ + return /*@ unfolding acc(v.Mem(ubuf), R20) in @*/ v.NextHdr default: return slayers.L4None } diff --git a/router/dataplane_concurrency_model.gobra b/router/dataplane_concurrency_model.gobra index 19648041f..651e29c37 100644 --- a/router/dataplane_concurrency_model.gobra +++ b/router/dataplane_concurrency_model.gobra @@ -31,13 +31,13 @@ ghost type SharedArg ghost struct { pred SharedInv(ghost dp io.DataPlaneSpec, ghost y SharedArg) { acc(y.Place) && acc(y.State) && // existentials are expressed using ghost pointers - io.token(*y.Place) && dp.dp3s_iospec_ordered(*y.State, *y.Place) && - ElemAuth((*y.State).ibuf, y.IBufY) && ElemAuth((*y.State).obuf, y.OBufY) + io.IOToken(*y.Place) && dp.Dp3s_iospec_ordered(*y.State, *y.Place) && + ElemAuth((*y.State).Ibuf, y.IBufY) && ElemAuth((*y.State).Obuf, y.OBufY) } // initialize the shared invariant: ghost -requires io.token(p) && dp.dp3s_iospec_ordered(s, p) +requires io.IOToken(p) && dp.Dp3s_iospec_ordered(s, p) ensures m.LockP() && m.LockInv() == SharedInv{dp, y} decreases func InitSharedInv( @@ -48,8 +48,8 @@ func InitSharedInv( m = &mV pE@ := p sE@ := s - yI := InitElemAuth(s.ibuf) - yO := InitElemAuth(s.obuf) + yI := InitElemAuth(s.Ibuf) + yO := InitElemAuth(s.Obuf) y := SharedArg{&pE, &sE, yI, yO} fold SharedInv{dp, y}() m.SetInv(SharedInv{dp, y}) @@ -70,7 +70,7 @@ func AllocProphecy() (expectedPkts int) pred MultiReadBio(ghost t io.Place, ghost expectedPkts int) { (expectedPkts > 0 ==> io.CBioIO_bio3s_recv(t) && - MultiReadBio(io.dp3s_iospec_bio3s_recv_T(t), expectedPkts-1)) + MultiReadBio(io.Dp3s_iospec_bio3s_recv_T(t), expectedPkts-1)) } ghost @@ -78,7 +78,7 @@ requires MultiReadBio(t, expectedPkts) decreases expectedPkts pure func MultiReadBioNext(t io.Place, expectedPkts int) (tn io.Place) { return expectedPkts <= 0 ? t : unfolding MultiReadBio(t, expectedPkts) in - MultiReadBioNext(io.dp3s_iospec_bio3s_recv_T(t), expectedPkts-1) + MultiReadBioNext(io.Dp3s_iospec_bio3s_recv_T(t), expectedPkts-1) } // Checks that all packets are received from the same interface (key). @@ -90,14 +90,14 @@ pure func MultiReadBioCorrectIfs( expectedPkts int, k Key) bool { return expectedPkts <= 0 || unfolding MultiReadBio(t, expectedPkts) in - match io.dp3s_iospec_bio3s_recv_R(t) { + match io.Dp3s_iospec_bio3s_recv_R(t) { case io.ValUnsupported{?ifs, _}: k == ifs case io.ValPkt{?ifs, _ }: k == ifs default: false - } && MultiReadBioCorrectIfs(io.dp3s_iospec_bio3s_recv_T(t), expectedPkts-1, k) + } && MultiReadBioCorrectIfs(io.Dp3s_iospec_bio3s_recv_T(t), expectedPkts-1, k) } ghost @@ -108,8 +108,8 @@ decreases expectedPkts pure func MultiReadBioIO_val(t io.Place, expectedPkts int) (res seq[io.Val]) { return expectedPkts <= 0 ? seq[io.Val]{} : unfolding MultiReadBio(t, expectedPkts) in - seq[io.Val]{io.dp3s_iospec_bio3s_recv_R(t)} ++ MultiReadBioIO_val( - io.dp3s_iospec_bio3s_recv_T(t), expectedPkts-1) + seq[io.Val]{io.Dp3s_iospec_bio3s_recv_R(t)} ++ MultiReadBioIO_val( + io.Dp3s_iospec_bio3s_recv_T(t), expectedPkts-1) } ghost @@ -120,50 +120,50 @@ pure func MultiReadBioUpd( expectedPkts int, s io.Dp3sStateLocal) io.Dp3sStateLocal { return expectedPkts <= 0 ? s : unfolding MultiReadBio(t, expectedPkts) in - MultiReadBioUpd(io.dp3s_iospec_bio3s_recv_T(t), expectedPkts-1, - addIbuf(s, io.dp3s_iospec_bio3s_recv_R(t))) + MultiReadBioUpd(io.Dp3s_iospec_bio3s_recv_T(t), expectedPkts-1, + AddIbuf(s, io.Dp3s_iospec_bio3s_recv_R(t))) } ghost requires val.isValPkt || val.isValUnsupported decreases -pure func addIbuf(s io.Dp3sStateLocal, val io.Val) io.Dp3sStateLocal { +pure func AddIbuf(s io.Dp3sStateLocal, val io.Val) io.Dp3sStateLocal { return match val { case io.ValPkt{?ifs, ?pkt}: - io.dp3s_add_ibuf(s, ifs, pkt) + io.Dp3s_add_ibuf(s, ifs, pkt) case io.ValUnsupported{_, _}: s default: - io.undefined() + io.Undefined() } } ghost decreases n -requires dp.dp3s_iospec_ordered(s, t) +requires dp.Dp3s_iospec_ordered(s, t) ensures MultiReadBio(t, n) -ensures dp.dp3s_iospec_ordered(MultiReadBioUpd(t, n, s), MultiReadBioNext(t, n)) +ensures dp.Dp3s_iospec_ordered(MultiReadBioUpd(t, n, s), MultiReadBioNext(t, n)) func ExtractMultiReadBio( dp io.DataPlaneSpec, t io.Place, n int, s io.Dp3sStateLocal) { if n > 0 { - unfold dp.dp3s_iospec_ordered(s,t) - unfold dp.dp3s_iospec_bio3s_recv(s,t) - ExtractMultiReadBio(dp, io.dp3s_iospec_bio3s_recv_T(t), n-1, addIbuf(s, io.dp3s_iospec_bio3s_recv_R(t))) + unfold dp.Dp3s_iospec_ordered(s,t) + unfold dp.Dp3s_iospec_bio3s_recv(s,t) + ExtractMultiReadBio(dp, io.Dp3s_iospec_bio3s_recv_T(t), n-1, AddIbuf(s, io.Dp3s_iospec_bio3s_recv_R(t))) } fold MultiReadBio(t,n) } ghost requires MultiReadBio(t, n) -requires ElemAuth(s.ibuf, y.IBufY) && ElemAuth(s.obuf, y.OBufY) +requires ElemAuth(s.Ibuf, y.IBufY) && ElemAuth(s.Obuf, y.OBufY) ensures MultiReadBio(t, n) ensures MultiReadBioUpd(t, n, s) == old(MultiReadBioUpd(t, n, s)) ensures MultiReadBioNext(t, n) == old(MultiReadBioNext(t, n)) -ensures ElemAuth(MultiReadBioUpd(t, n, s).ibuf, y.IBufY) -ensures ElemAuth(MultiReadBioUpd(t, n, s).obuf, y.OBufY) +ensures ElemAuth(MultiReadBioUpd(t, n, s).Ibuf, y.IBufY) +ensures ElemAuth(MultiReadBioUpd(t, n, s).Obuf, y.OBufY) ensures 0 <= n && MultiReadBioCorrectIfs(t, n, k) ==> MultiElemWitness(y.IBufY, k, MultiReadBioIO_val(t, n)) decreases n @@ -175,12 +175,12 @@ func MultiUpdateElemWitness( y SharedArg) { if n > 0 { unfold MultiReadBio(t, n) - val := io.dp3s_iospec_bio3s_recv_R(t) - next := io.dp3s_iospec_bio3s_recv_T(t) + val := io.Dp3s_iospec_bio3s_recv_R(t) + next := io.Dp3s_iospec_bio3s_recv_T(t) if val.isValPkt{ - UpdateElemWitness(s.ibuf, y.IBufY, val.ValPkt_1, val.ValPkt_2) + UpdateElemWitness(s.Ibuf, y.IBufY, val.ValPkt_1, val.ValPkt_2) } - MultiUpdateElemWitness(next, n-1, k, addIbuf(s, val), y) + MultiUpdateElemWitness(next, n-1, k, AddIbuf(s, val), y) fold MultiReadBio(t, n) } @@ -262,9 +262,9 @@ Dict implements DictWithTopBot ghost type TypeAuthRA ghost struct{} -ghost type AuthCarrier ghost struct { - fst DictWithTopBot - snd Dict +ghost comparable type AuthCarrier ghost struct { + Fst DictWithTopBot + Snd Dict } ghost @@ -286,9 +286,9 @@ decreases pure func (ra TypeAuthRA) IsElem(e resalgebra.Elem) (res bool) { return typeOf(e) == type[AuthCarrier] && let c := e.(AuthCarrier) in - c.fst === Bottom{} || - c.fst === Top{} || - typeOf(c.fst) == type[Dict] + c.Fst === Bottom{} || + c.Fst === Top{} || + typeOf(c.Fst) == type[Dict] } ghost @@ -296,26 +296,26 @@ requires ra.IsElem(e) decreases pure func (ra TypeAuthRA) IsValid(e resalgebra.Elem) bool { return let x := e.(AuthCarrier) in - x.fst === Bottom{} || - (typeOf(x.fst) == type[Dict] && dictLessThan(x.snd.V, x.fst.(Dict).V)) + x.Fst === Bottom{} || + (typeOf(x.Fst) == type[Dict] && DictLessThan(x.Snd.V, x.Fst.(Dict).V)) } ghost decreases -pure func dictLessThan(d1 dict[Key]Val, d2 dict[Key]Val) bool { +pure func DictLessThan(d1 dict[Key]Val, d2 dict[Key]Val) bool { return (forall k Key :: k elem domain(d1) ==> k elem domain(d2) && AsSet(d1[k]) union AsSet(d2[k]) == AsSet(d2[k])) } ghost -ensures forall d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val :: {dictLessThan(d1, d2), dictLessThan(d2, d3)} dictLessThan(d1, d2) && dictLessThan(d2, d3) ==> - dictLessThan(d1, d3) +ensures forall d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val :: {DictLessThan(d1, d2), DictLessThan(d2, d3)} DictLessThan(d1, d2) && DictLessThan(d2, d3) ==> + DictLessThan(d1, d3) decreases func dictLessThanTransitiveQ() { // proven } ghost -ensures dictLessThan(d1, d3) && dictLessThan(d2, d3) ==> dictLessThan(dictMax(d1, d2), d3) +ensures DictLessThan(d1, d3) && DictLessThan(d2, d3) ==> DictLessThan(DictMax(d1, d2), d3) decreases pure func dictMaxIsLessThan(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) U { return dictUnionIsLessThan(d1, d2, d3) @@ -323,14 +323,15 @@ pure func dictMaxIsLessThan(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) U ghost decreases -pure func dictMax(d1 dict[Key]Val, d2 dict[Key]Val) dict[Key]Val { +closed +pure func DictMax(d1 dict[Key]Val, d2 dict[Key]Val) dict[Key]Val { // logically redundant but it simplifies automated reasoning when - // either dictLessThan(d1, d2) or dictLessThan(d2, d1) is known. - return dictLessThan(d1, d2) ? d2 : dictLessThan(d2, d1) ? d1 : dictUnion(d1, d2) + // either DictLessThan(d1, d2) or DictLessThan(d2, d1) is known. + return DictLessThan(d1, d2) ? d2 : DictLessThan(d2, d1) ? d1 : dictUnion(d1, d2) } ghost -requires dictLessThan(d1, d2) && dictLessThan(d2, d1) +requires DictLessThan(d1, d2) && DictLessThan(d2, d1) ensures d1 === d2 decreases func dictLessEq(d1 dict[Key]Val, d2 dict[Key]Val) { @@ -346,8 +347,8 @@ pure func keyInDict(d dict[Key]Val, k Key, v io.Pkt) bool { } ghost -ensures domain(dictMax(d1, d2)) == domain(d1) union domain(d2) -ensures let d := dictMax(d1, d2) in +ensures domain(DictMax(d1, d2)) == domain(d1) union domain(d2) +ensures let d := DictMax(d1, d2) in forall k Key, v io.Pkt :: !keyInDict(d, k, v) == !(keyInDict(d1, k, v) || keyInDict(d2, k, v)) decreases func dictMaxAssocLemma0(d1 dict[Key]Val, d2 dict[Key]Val) { @@ -355,28 +356,28 @@ func dictMaxAssocLemma0(d1 dict[Key]Val, d2 dict[Key]Val) { } ghost -ensures domain(dictMax(d1, dictMax(d2, d3))) == domain(d1) union domain(d2) union domain(d3) -ensures let d := dictMax(d1, dictMax(d2, d3)) in +ensures domain(DictMax(d1, DictMax(d2, d3))) == domain(d1) union domain(d2) union domain(d3) +ensures let d := DictMax(d1, DictMax(d2, d3)) in forall k Key, v io.Pkt :: keyInDict(d, k, v) == (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) decreases func dictMaxAssocLemma1(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) { - d := dictMax(d1, dictMax(d2, d3)) + d := DictMax(d1, DictMax(d2, d3)) assert forall k Key, v io.Pkt :: (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) ==> keyInDict(d, k, v) dictMaxAssocLemma0(d2, d3) - dictMaxAssocLemma0(d1, dictMax(d2, d3)) + dictMaxAssocLemma0(d1, DictMax(d2, d3)) assert forall k Key, v io.Pkt :: keyInDict(d, k, v) ==> (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) } ghost -ensures domain(dictMax(dictMax(d1, d2), d3)) == domain(d1) union domain(d2) union domain(d3) -ensures let d := dictMax(dictMax(d1, d2), d3) in +ensures domain(DictMax(DictMax(d1, d2), d3)) == domain(d1) union domain(d2) union domain(d3) +ensures let d := DictMax(DictMax(d1, d2), d3) in forall k Key, v io.Pkt :: keyInDict(d, k, v) == (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) decreases func dictMaxAssocLemma2(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) { - d := dictMax(dictMax(d1, d2), d3) + d := DictMax(DictMax(d1, d2), d3) assert forall k Key, v io.Pkt :: (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) ==> keyInDict(d, k, v) dictMaxAssocLemma0(d1, d2) - dictMaxAssocLemma0(dictMax(d1, d2), d3) + dictMaxAssocLemma0(DictMax(d1, d2), d3) assert forall k Key, v io.Pkt :: keyInDict(d, k, v) ==> (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) } @@ -393,8 +394,8 @@ func dictExtensionality(d1 dict[Key]Val, d2 dict[Key]Val) { lemmaSubSet() assert forall k Key :: k elem domain(d1) ==> AsSet(d1[k]) union AsSet(d2[k]) == AsSet(d2[k]) assert forall k Key :: k elem domain(d2) ==> AsSet(d2[k]) union AsSet(d1[k]) == AsSet(d1[k]) - assert dictLessThan(d1, d2) - assert dictLessThan(d2, d1) + assert DictLessThan(d1, d2) + assert DictLessThan(d2, d1) dictLessEq(d1, d2) } @@ -406,26 +407,26 @@ func lemmaSubSet() { } ghost -ensures dictMax(d1, dictMax(d2, d3)) === dictMax(dictMax(d1, d2), d3) +ensures DictMax(d1, DictMax(d2, d3)) === DictMax(DictMax(d1, d2), d3) decreases func dictMaxAssoc(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) { dictMaxAssocLemma1(d1, d2, d3) dictMaxAssocLemma2(d1, d2, d3) - dictExtensionality(dictMax(d1, dictMax(d2, d3)), dictMax(dictMax(d1, d2), d3)) + dictExtensionality(DictMax(d1, DictMax(d2, d3)), DictMax(DictMax(d1, d2), d3)) } ghost -ensures dictMax(d1, d2) == dictMax(d2, d1) +ensures DictMax(d1, d2) == DictMax(d2, d1) decreases func dictMaxIsComm(d1 dict[Key]Val, d2 dict[Key]Val) { - if dictLessThan(d1, d2) && dictLessThan(d2, d1) { + if DictLessThan(d1, d2) && DictLessThan(d2, d1) { dictLessEq(d1, d2) } - assert d1 != d2 && dictLessThan(d1, d2) ==> !dictLessThan(d2, d1) - assert dictLessThan(d1, d2) ==> dictMax(d1, d2) == d2 - assert dictLessThan(d1, d2) ==> dictMax(d2, d1) == d2 - assert dictLessThan(d2, d1) ==> dictMax(d1, d2) == d1 - assert dictLessThan(d2, d1) ==> dictMax(d2, d1) == d1 + assert d1 != d2 && DictLessThan(d1, d2) ==> !DictLessThan(d2, d1) + assert DictLessThan(d1, d2) ==> DictMax(d1, d2) == d2 + assert DictLessThan(d1, d2) ==> DictMax(d2, d1) == d2 + assert DictLessThan(d2, d1) ==> DictMax(d1, d2) == d1 + assert DictLessThan(d2, d1) ==> DictMax(d2, d1) == d1 dictUnionIsComm(d1, d2) } @@ -435,7 +436,7 @@ ensures res !== none[resalgebra.Elem] ==> ra.IsElem(get(res)) decreases pure func (ra TypeAuthRA) Core(e resalgebra.Elem) (ghost res option[resalgebra.Elem]) { return let x := e.(AuthCarrier) in - some(resalgebra.Elem(AuthCarrier{Bottom{}, x.snd})) + some(resalgebra.Elem(AuthCarrier{Bottom{}, x.Snd})) } ghost @@ -445,11 +446,11 @@ decreases pure func (ra TypeAuthRA) Compose(e1 resalgebra.Elem, e2 resalgebra.Elem) (res resalgebra.Elem) { return let c1 := e1.(AuthCarrier) in let c2 := e2.(AuthCarrier) in - (c1.fst === Bottom{} ? - AuthCarrier{c2.fst, Dict{dictMax(c1.snd.V, c2.snd.V)}} : - (c2.fst === Bottom{} ? - AuthCarrier{c1.fst, Dict{dictMax(c1.snd.V, c2.snd.V)}} : - AuthCarrier{Top{}, Dict{dictMax(c1.snd.V, c2.snd.V)}})) + (c1.Fst === Bottom{} ? + AuthCarrier{c2.Fst, Dict{DictMax(c1.Snd.V, c2.Snd.V)}} : + (c2.Fst === Bottom{} ? + AuthCarrier{c1.Fst, Dict{DictMax(c1.Snd.V, c2.Snd.V)}} : + AuthCarrier{Top{}, Dict{DictMax(c1.Snd.V, c2.Snd.V)}})) } ghost @@ -464,8 +465,8 @@ func (ra TypeAuthRA) ComposeAssoc(e1 resalgebra.Elem, e2 resalgebra.Elem, e3 res comp1 := ra.Compose(ra.Compose(e1, e2), e3).(AuthCarrier) comp2 := ra.Compose(e1, ra.Compose(e2, e3)).(AuthCarrier) - assert comp1.fst === comp2.fst - dictMaxAssoc(c1.snd.V, c2.snd.V, c3.snd.V) + assert comp1.Fst === comp2.Fst + dictMaxAssoc(c1.Snd.V, c2.Snd.V, c3.Snd.V) } ghost @@ -475,7 +476,7 @@ decreases func (ra TypeAuthRA) ComposeComm(e1 resalgebra.Elem, e2 resalgebra.Elem) { c1 := e1.(AuthCarrier) c2 := e2.(AuthCarrier) - dictMaxIsComm(c1.snd.V, c2.snd.V) + dictMaxIsComm(c1.Snd.V, c2.Snd.V) } ghost @@ -520,11 +521,11 @@ func (ra TypeAuthRA) ValidOp(e1 resalgebra.Elem, e2 resalgebra.Elem) { c := ra.Compose(e1, e2).(AuthCarrier) c1 := e1.(AuthCarrier) c2 := e2.(AuthCarrier) - if (c1.fst !== Bottom{}) { - fst := c.fst.(Dict).V - snd := c.snd.V - assert dictLessThan(snd, fst) - assert snd === dictMax(c1.snd.V, c2.snd.V) + if (c1.Fst !== Bottom{}) { + fst := c.Fst.(Dict).V + snd := c.Snd.V + assert DictLessThan(snd, fst) + assert snd === DictMax(c1.Snd.V, c2.Snd.V) } } @@ -558,54 +559,54 @@ func ApplyElemWitness(m dict[Key]Val, y ElemRA, k Key, e Elem) { ghost requires ElemAuth(m, y) -ensures ElemAuth(io.insert(m, k, e), y) +ensures ElemAuth(io.Insert(m, k, e), y) ensures ElemWitness(y, k, e) decreases func UpdateElemWitness(m dict[Key]Val, y ElemRA, k Key, e Elem) { unfold ElemAuth(m, y) d := Dict{dict[Key]Val{k: set[io.Pkt]{e}}} - c := (TypeAuthRA{}).Compose(AuthView(Dict{io.insert(m, k, e)}), FragView(d)) + c := (TypeAuthRA{}).Compose(AuthView(Dict{io.Insert(m, k, e)}), FragView(d)) updateElemWitnessAuxLemma(m, k, e) assert resalgebra.IsFramePreservingUpdate(TypeAuthRA{}, AuthView(Dict{m}), c) resalgebra.GhostUpdate(y, TypeAuthRA{}, AuthView(Dict{m}), c) assert resalgebra.GhostLocation(y, TypeAuthRA{}, c) - resalgebra.GhostOp1(y, TypeAuthRA{}, AuthView(Dict{io.insert(m, k, e)}), FragView(d)) - fold ElemAuth(io.insert(m, k, e), y) + resalgebra.GhostOp1(y, TypeAuthRA{}, AuthView(Dict{io.Insert(m, k, e)}), FragView(d)) + fold ElemAuth(io.Insert(m, k, e), y) fold ElemWitness(y, k, e) } // by far, the slowest lemma to prove atm ghost ensures let d := Dict{dict[Key]Val{k: set[io.Pkt]{e}}} in - let c := (TypeAuthRA{}).Compose(AuthView(Dict{io.insert(m, k, e)}), FragView(d)) in + let c := (TypeAuthRA{}).Compose(AuthView(Dict{io.Insert(m, k, e)}), FragView(d)) in resalgebra.IsFramePreservingUpdate(TypeAuthRA{}, AuthView(Dict{m}), c) decreases func updateElemWitnessAuxLemma(m dict[Key]Val, k Key, e Elem) { ra := TypeAuthRA{} a := AuthView(Dict{m}) d := Dict{dict[Key]Val{k: set[io.Pkt]{e}}} - c := ra.Compose(AuthView(Dict{io.insert(m, k, e)}), FragView(d)) + c := ra.Compose(AuthView(Dict{io.Insert(m, k, e)}), FragView(d)) assert ra.IsValid(a) ==> ra.IsValid(c) assert forall ee resalgebra.Elem :: ra.IsElem(ee) && ra.IsValid(ra.Compose(a, ee)) ==> (let ae := ra.Compose(a, ee).(AuthCarrier) in - (ae.fst == Bottom{} || dictLessThan(ae.snd.V, m))) + (ae.Fst == Bottom{} || DictLessThan(ae.Snd.V, m))) dictLessThanTransitiveQ() assert forall ee resalgebra.Elem :: ra.IsElem(ee) && ra.IsValid(ra.Compose(a, ee)) ==> - ee.(AuthCarrier).fst === Bottom{} && - dictLessThan(ee.(AuthCarrier).snd.V, m) && - dictLessThan(m, io.insert(m, k, e)) && - dictLessThan(ee.(AuthCarrier).snd.V, io.insert(m, k, e)) + ee.(AuthCarrier).Fst === Bottom{} && + DictLessThan(ee.(AuthCarrier).Snd.V, m) && + DictLessThan(m, io.Insert(m, k, e)) && + DictLessThan(ee.(AuthCarrier).Snd.V, io.Insert(m, k, e)) assert forall ee resalgebra.Elem :: ra.IsElem(ee) && ra.IsValid(ra.Compose(a, ee)) ==> - ee.(AuthCarrier).fst === Bottom{} && + ee.(AuthCarrier).Fst === Bottom{} && let ce := ra.Compose(c, ee).(AuthCarrier) in - ce.fst.(Dict).V === io.insert(m, k, e) + ce.Fst.(Dict).V === io.Insert(m, k, e) assert forall ee resalgebra.Elem :: ra.IsElem(ee) && ra.IsValid(ra.Compose(a, ee)) ==> - ee.(AuthCarrier).fst === Bottom{} && + ee.(AuthCarrier).Fst === Bottom{} && let ce := ra.Compose(c, ee).(AuthCarrier) in - ce.snd.V == dictMax(d.V, ee.(AuthCarrier).snd.V) && - dictLessThan(d.V, io.insert(m, k, e)) && - dictLessThan(ee.(AuthCarrier).snd.V, io.insert(m, k, e)) && - let _ := dictMaxIsLessThan(d.V, ee.(AuthCarrier).snd.V, io.insert(m, k, e)) in + ce.Snd.V == DictMax(d.V, ee.(AuthCarrier).Snd.V) && + DictLessThan(d.V, io.Insert(m, k, e)) && + DictLessThan(ee.(AuthCarrier).Snd.V, io.Insert(m, k, e)) && + let _ := dictMaxIsLessThan(d.V, ee.(AuthCarrier).Snd.V, io.Insert(m, k, e)) in true } @@ -622,7 +623,7 @@ func InitElemAuth(m dict[Key]Val) (y ElemRA) { ghost opaque -ensures dictLessThan(d1, res) && dictLessThan(d2, res) +ensures DictLessThan(d1, res) && DictLessThan(d2, res) decreases pure func dictUnion(d1 dict[Key]Val, d2 dict[Key]Val) (res dict[Key]Val) { return dictUnionAux(d1, d2) @@ -670,7 +671,7 @@ func dictUnionIsComm(d1 dict[Key]Val, d2 dict[Key]Val) { // dictUnion(d1, d2) is the smallest dict that is bigger than both d1 and d2 ghost -ensures dictLessThan(d1, d3) && dictLessThan(d2, d3) ==> dictLessThan(dictUnion(d1, d2), d3) +ensures DictLessThan(d1, d3) && DictLessThan(d2, d3) ==> DictLessThan(dictUnion(d1, d2), d3) decreases pure func dictUnionIsLessThan(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) U { return let u1 := reveal dictUnion(d1, d2) in diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index f6e3288f3..32791d30c 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -39,7 +39,16 @@ ghost const MutexPerm perm = 1/4 ghost const OutMutexPerm perm = 3/4 ghost const runningPerm perm = 1/2 -pred MutexInvariant(d *DataPlane) { +// MtxInv wraps the resources of, and the facts about, the non-exported mutex +// that protects the dataplane. The contracts of the exported methods of +// DataPlane use it so that they do not mention the non-exported field 'mtx'. +closed pred (d *DataPlane) MtxInv() { + d.mtx.LockP() && d.mtx.LockInv() == MutexInvariant{d} +} + +// The body of this predicate describes the private state of the dataplane, so +// it is closed. +closed pred MutexInvariant(d *DataPlane) { acc(&d.running, runningPerm) && (!d.running ==> acc(d.Mem(), MutexPerm)) } @@ -55,7 +64,9 @@ pred MutexInvariant(d *DataPlane) { // Note that the '...Inv' predicates take the relevant field by value, which // keeps them self-framing without holding the permission to the field itself // (that permission remains in 'Mem'). -pred (d *DataPlane) Mem() { +// The body of this predicate describes the private state of the dataplane, so +// it is closed. +closed pred (d *DataPlane) Mem() { // access to the field 'mtx' ommited acc(&d.external) && acc(&d.linkTypes) && @@ -290,7 +301,8 @@ pure func (d *DataPlane) getMacFactory() func() hash.Hash { ghost requires d.Mem() decreases -pure func (d *DataPlane) getDomForwardingMetrics() set[uint16] { +closed +pure func (d *DataPlane) GetDomForwardingMetrics() set[uint16] { return unfolding d.Mem() in unfolding forwardingMetricsInv(d.forwardingMetrics) in d.forwardingMetrics == nil ? @@ -302,6 +314,7 @@ pure func (d *DataPlane) getDomForwardingMetrics() set[uint16] { ghost requires d.Mem() decreases +closed pure func (d *DataPlane) GetDomInternalNextHops() set[uint16] { return unfolding d.Mem() in unfolding internalNextHopsInv(d.internalNextHops) in @@ -315,7 +328,8 @@ ghost opaque requires d.Mem() decreases -pure func (d *DataPlane) getDomExternal() set[uint16] { +closed +pure func (d *DataPlane) GetDomExternal() set[uint16] { return unfolding d.Mem() in unfolding externalInv(d.external) in d.external == nil ? @@ -327,7 +341,8 @@ pure func (d *DataPlane) getDomExternal() set[uint16] { ghost requires d.Mem() decreases -pure func (d *DataPlane) getDomNeighborIAs() set[uint16] { +closed +pure func (d *DataPlane) GetDomNeighborIAs() set[uint16] { return unfolding d.Mem() in unfolding neighborIAsInv(d.neighborIAs) in d.neighborIAs == nil ? @@ -337,7 +352,8 @@ pure func (d *DataPlane) getDomNeighborIAs() set[uint16] { ghost requires d.Mem() decreases -pure func (d *DataPlane) getDomLinkTypes() set[uint16] { +closed +pure func (d *DataPlane) GetDomLinkTypes() set[uint16] { return unfolding d.Mem() in unfolding linkTypesInv(d.linkTypes) in d.linkTypes == nil ? @@ -349,10 +365,10 @@ opaque requires d.Mem() decreases pure func (d *DataPlane) WellConfigured() bool { - return d.getDomNeighborIAs() == d.getDomExternal() && - d.getDomNeighborIAs() == d.getDomLinkTypes() && - !(0 elem d.getDomNeighborIAs()) && - d.getDomExternal() subset d.getDomForwardingMetrics() + return d.GetDomNeighborIAs() == d.GetDomExternal() && + d.GetDomNeighborIAs() == d.GetDomLinkTypes() && + !(0 elem d.GetDomNeighborIAs()) && + d.GetDomExternal() subset d.GetDomForwardingMetrics() } ghost @@ -360,15 +376,15 @@ opaque requires d.Mem() decreases pure func (d *DataPlane) PreWellConfigured() bool { - return d.getDomNeighborIAs() == d.getDomExternal() && - d.getDomExternal() == d.getDomLinkTypes() && - !(0 elem d.getDomNeighborIAs()) && - d.getDomExternal() intersection d.GetDomInternalNextHops() == set[uint16]{} + return d.GetDomNeighborIAs() == d.GetDomExternal() && + d.GetDomExternal() == d.GetDomLinkTypes() && + !(0 elem d.GetDomNeighborIAs()) && + d.GetDomExternal() intersection d.GetDomInternalNextHops() == set[uint16]{} } ghost requires acc(d.Mem(), _) -requires id elem d.getDomForwardingMetrics() +requires id elem d.GetDomForwardingMetrics() ensures acc(&d.forwardingMetrics, _) ensures acc(d.forwardingMetrics, _) ensures acc(forwardingMetricsMem(d.forwardingMetrics[id], id), _) @@ -376,8 +392,8 @@ decreases func (d *DataPlane) getForwardingMetricsMem(id uint16) { unfold acc(d.Mem(), _) unfold acc(forwardingMetricsInv(d.forwardingMetrics), _) - assert id elem d.getDomForwardingMetrics() - assert d.getDomForwardingMetrics() == (d.forwardingMetrics == nil ? + assert id elem d.GetDomForwardingMetrics() + assert d.GetDomForwardingMetrics() == (d.forwardingMetrics == nil ? set[uint16]{} : (unfolding acc(accForwardingMetrics(d.forwardingMetrics), _) in domain(d.forwardingMetrics))) @@ -465,6 +481,7 @@ pure func (d *DataPlane) getValSvc() *services { ghost requires d.Mem() decreases +closed pure func (d *DataPlane) SvcsAreSet() bool { return unfolding d.Mem() in d.svc != nil @@ -508,6 +525,7 @@ type Unit struct{} ghost requires d.Mem() decreases +closed pure func (d *DataPlane) IsRunning() bool { return unfolding d.Mem() in d.running @@ -527,6 +545,7 @@ pure func (d *DataPlane) isRunningEq() Unit { ghost requires d.Mem() decreases +closed pure func (d *DataPlane) InternalConnIsSet() bool { return unfolding d.Mem() in d.internal != nil @@ -554,6 +573,7 @@ pure func (d *DataPlane) internalIsSetEq() Unit { ghost requires d.Mem() decreases +closed pure func (d *DataPlane) KeyIsSet() bool { return unfolding d.Mem() in d.macFactory != nil @@ -573,6 +593,7 @@ pure func (d *DataPlane) keyIsSetEq() Unit { ghost requires d.Mem() decreases +closed pure func (d *DataPlane) LocalIA() addr.IA { return unfolding d.Mem() in d.localIA @@ -748,7 +769,7 @@ func ResetDecodingLayers( pred (d *DataPlane) validResult(result processResult, addrAliasesPkt bool) { acc(d.Mem(), _) && // EgressID - (result.EgressID != 0 ==> result.EgressID elem d.getDomForwardingMetrics()) && + (result.EgressID != 0 ==> result.EgressID elem d.GetDomForwardingMetrics()) && // OutConn (result.OutConn != nil ==> acc(result.OutConn.Mem(), _)) && // OutAddr @@ -759,9 +780,9 @@ pred (d *DataPlane) validResult(result processResult, addrAliasesPkt bool) { ghost requires acc(d.Mem(), _) && d.WellConfigured() -requires id elem d.getDomExternal() +requires id elem d.GetDomExternal() ensures acc(d.Mem(), _) -ensures id elem d.getDomForwardingMetrics() +ensures id elem d.GetDomForwardingMetrics() decreases func (d *DataPlane) InDomainExternalInForwardingMetrics(id uint16) { reveal d.WellConfigured() @@ -773,11 +794,11 @@ requires acc(&d.external, _) && acc(d.external, R55) requires id elem domain(d.external) ensures acc(d.Mem(), _) ensures acc(&d.external, _) && acc(d.external, R55) -ensures id elem d.getDomForwardingMetrics() +ensures id elem d.GetDomForwardingMetrics() decreases -func (d *DataPlane) InDomainExternalInForwardingMetrics3(id uint16) { +func (d *DataPlane) inDomainExternalInForwardingMetrics3(id uint16) { reveal d.WellConfigured() - reveal d.getDomExternal() + reveal d.GetDomExternal() assert unfolding acc(d.Mem(), _) in (unfolding acc(externalInv(d.external), _) in (unfolding acc(accBatchConn(d.external), _) in true)) @@ -795,6 +816,7 @@ pure func (d *DataPlane) domainForwardingMetrics() set[uint16] { ghost requires d.Mem() decreases +closed pure func (d *DataPlane) DomainForwardingMetrics() set[uint16] { return unfolding d.Mem() in unfolding forwardingMetricsInv(d.forwardingMetrics) in diff --git a/router/dataplane_spec_test.gobra b/router/dataplane_spec_test.gobra index a94975900..a68c6b7e6 100644 --- a/router/dataplane_spec_test.gobra +++ b/router/dataplane_spec_test.gobra @@ -47,13 +47,14 @@ func foldMem_test() { fold MutexInvariant{&d}() // testing initialization with the operations from dataplane d.mtx.SetInv(MutexInvariant{&d}) + fold (&d).MtxInv() d.AddNeighborIA(uint16(1), addr.IA(10)) d.AddNeighborIA(uint16(2), addr.IA(11)) } func foldScionPacketProcessorInitMem_test() { d := &scionPacketProcessor{} - fold slayers.PathPoolMem(d.scionLayer.pathPool, d.scionLayer.pathPoolRaw) + d.scionLayer.EstablishHiddenPathPoolMem() d.scionLayer.RecyclePaths() fold d.scionLayer.NonInitMem() fold d.initMem() @@ -163,18 +164,18 @@ func testRun( // `===` for ghost structs ensures dp != io.DataPlaneSpec{} ensures dp == io.DataPlaneSpec { - linkTypes: dict[io.Ifs]io.Link{ + LinkTypes: dict[io.Ifs]io.Link{ io.Ifs{1}: io.IO_ProvCust{}, io.Ifs{2}: io.IO_ProvCust{}, io.Ifs{3}: io.IO_ProvCust{}, }, - neighborIAs: dict[io.Ifs]io.AS{ + NeighborIAs: dict[io.Ifs]io.AS{ io.Ifs{1}: io.AS{1001}, io.Ifs{2}: io.AS{1002}, io.Ifs{3}: io.AS{1000}, }, - localIA: io.AS{1000}, - links: dict[io.AsIfsPair]io.AsIfsPair { + LocalIA: io.AS{1000}, + Links: dict[io.AsIfsPair]io.AsIfsPair { io.AsIfsPair{io.AS{1000}, io.Ifs{1}}: io.AsIfsPair{io.AS{1001}, io.Ifs{7}}, io.AsIfsPair{io.AS{1000}, io.Ifs{2}}: io.AsIfsPair{io.AS{1002}, io.Ifs{8}}, io.AsIfsPair{io.AS{1000}, io.Ifs{3}}: io.AsIfsPair{io.AS{1000}, io.Ifs{3}}, @@ -188,18 +189,18 @@ func testRun( pair5 := io.AsIfsPair{io.AS{1002}, io.Ifs{8}} dp := io.DataPlaneSpec { - linkTypes: dict[io.Ifs]io.Link{ + LinkTypes: dict[io.Ifs]io.Link{ io.Ifs{1}: io.IO_ProvCust{}, io.Ifs{2}: io.IO_ProvCust{}, io.Ifs{3}: io.IO_ProvCust{}, }, - neighborIAs: dict[io.Ifs]io.AS{ + NeighborIAs: dict[io.Ifs]io.AS{ io.Ifs{1}: io.AS{1001}, io.Ifs{2}: io.AS{1002}, io.Ifs{3}: io.AS{1000}, }, - localIA: io.AS{1000}, - links: dict[io.AsIfsPair]io.AsIfsPair { + LocalIA: io.AS{1000}, + Links: dict[io.AsIfsPair]io.AsIfsPair { pair1: pair4, pair2: pair5, pair3: pair3, @@ -212,17 +213,17 @@ func testRun( assert dp.Lookup(dp.Lookup(pair4)) == pair4 assert dp.Lookup(dp.Lookup(pair5)) == pair5 - assert forall ifs io.Ifs :: {ifs elem domain(dp.neighborIAs)} ifs elem domain(dp.neighborIAs) ==> - io.AsIfsPair{dp.localIA, ifs} elem domain(dp.links) - assert forall ifs io.Ifs :: {ifs elem domain(dp.neighborIAs)} ifs elem domain(dp.neighborIAs) ==> - dp.Lookup(io.AsIfsPair{dp.localIA, ifs}).asid == dp.neighborIAs[ifs] - assert forall ifs io.Ifs :: {ifs elem domain(dp.neighborIAs)} io.AsIfsPair{dp.localIA, ifs} elem domain(dp.links) ==> - ifs elem domain(dp.neighborIAs) - assert forall pair io.AsIfsPair :: {dp.Lookup(pair)} pair elem domain(dp.links) ==> + assert forall ifs io.Ifs :: {ifs elem domain(dp.NeighborIAs)} ifs elem domain(dp.NeighborIAs) ==> + io.AsIfsPair{dp.LocalIA, ifs} elem domain(dp.Links) + assert forall ifs io.Ifs :: {ifs elem domain(dp.NeighborIAs)} ifs elem domain(dp.NeighborIAs) ==> + dp.Lookup(io.AsIfsPair{dp.LocalIA, ifs}).Asid == dp.NeighborIAs[ifs] + assert forall ifs io.Ifs :: {ifs elem domain(dp.NeighborIAs)} io.AsIfsPair{dp.LocalIA, ifs} elem domain(dp.Links) ==> + ifs elem domain(dp.NeighborIAs) + assert forall pair io.AsIfsPair :: {dp.Lookup(pair)} pair elem domain(dp.Links) ==> let next_pair := dp.Lookup(pair) in - (next_pair elem domain(dp.links)) && + (next_pair elem domain(dp.Links)) && dp.Lookup(next_pair) == pair - assert domain(dp.linkTypes) == domain(dp.neighborIAs) + assert domain(dp.LinkTypes) == domain(dp.NeighborIAs) assert reveal dp.Valid() ) @@ -244,10 +245,10 @@ func testRun( fold metricsInv(d.Metrics) fold forwardingMetricsInv(d.forwardingMetrics) fold d.Mem() - assert d.getDomNeighborIAs() == reveal d.getDomExternal() - assert d.getDomNeighborIAs() == d.getDomLinkTypes() - assert !(0 elem d.getDomNeighborIAs()) - assert reveal d.getDomExternal() intersection d.GetDomInternalNextHops() == set[uint16]{} + assert d.GetDomNeighborIAs() == reveal d.GetDomExternal() + assert d.GetDomNeighborIAs() == d.GetDomLinkTypes() + assert !(0 elem d.GetDomNeighborIAs()) + assert reveal d.GetDomExternal() intersection d.GetDomInternalNextHops() == set[uint16]{} assert reveal d.DpAgreesWithSpec(dp) assert reveal d.PreWellConfigured() @@ -263,8 +264,8 @@ func testRun( assert d.mtx.LockInv() == MutexInvariant{d} // io-spec needs to be inhaled - inhale io.token(place) - inhale dp.dp3s_iospec_ordered(state, place) + inhale io.IOToken(place) + inhale dp.Dp3s_iospec_ordered(state, place) d.Run(ctx, place, state, dp) } diff --git a/router/io-spec-abstract-transitions.gobra b/router/io-spec-abstract-transitions.gobra index 9122b5bd2..355b6c6f4 100644 --- a/router/io-spec-abstract-transitions.gobra +++ b/router/io-spec-abstract-transitions.gobra @@ -42,7 +42,7 @@ ensures len(newPkt.CurrSeg.Future) == len(oldPkt.CurrSeg.Future) decreases pure func AbsUpdateNonConsDirIngressSegID(oldPkt io.Pkt, ingressID option[io.Ifs]) (newPkt io.Pkt) { return ingressID == none[io.Ifs] ? oldPkt : io.Pkt { - io.establishGuardTraversedseg(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), + io.EstablishGuardTraversedseg(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), oldPkt.LeftSeg, oldPkt.MidSeg, oldPkt.RightSeg, @@ -86,7 +86,7 @@ requires pkt.PathNotFullyTraversed() decreases pure func AbsValidateEgressIDConstraint(pkt io.Pkt, enter bool, dp io.DataPlaneSpec) bool { return let currseg := pkt.CurrSeg in - (enter ==> dp.dp2_check_interface_top(currseg.ConsDir, dp.Asid(), currseg.Future[0])) + (enter ==> dp.Dp2_check_interface_top(currseg.ConsDir, dp.Asid(), currseg.Future[0])) } ghost @@ -96,7 +96,7 @@ ensures len(newPkt.CurrSeg.Future) >= 0 decreases pure func AbsProcessEgress(oldPkt io.Pkt) (newPkt io.Pkt) { return io.Pkt { - io.establishGuardTraversedsegInc(oldPkt.CurrSeg, oldPkt.CurrSeg.ConsDir), + io.EstablishGuardTraversedsegInc(oldPkt.CurrSeg, oldPkt.CurrSeg.ConsDir), oldPkt.LeftSeg, oldPkt.MidSeg, oldPkt.RightSeg, @@ -118,7 +118,7 @@ pure func AbsDoXover(oldPkt io.Pkt) (newPkt io.Pkt) { get(oldPkt.LeftSeg), oldPkt.MidSeg, oldPkt.RightSeg, - some(io.establishGuardTraversedsegInc(oldPkt.CurrSeg, false)), + some(io.EstablishGuardTraversedsegInc(oldPkt.CurrSeg, false)), } } @@ -132,7 +132,7 @@ decreases pure func AbsValidateEgressIDConstraintXover(pkt io.Pkt, dp io.DataPlaneSpec) bool { return let currseg := pkt.CurrSeg in let rightseg := get(pkt.RightSeg) in - dp.xover2_link_type_dir(dp.Asid(), rightseg.ConsDir, rightseg.Past[0], + dp.Xover2_link_type_dir(dp.Asid(), rightseg.ConsDir, rightseg.Past[0], currseg.ConsDir, currseg.Future[0]) } @@ -146,7 +146,7 @@ pure func AbsVerifyCurrentMACConstraint(pkt io.Pkt, dp io.DataPlaneSpec) bool { let ts := currseg.AInfo in let hf := currseg.Future[0] in let uinfo := currseg.UInfo in - dp.hf_valid(d, ts.V, uinfo, hf) + dp.Hf_valid(d, ts.V, uinfo, hf) } // This executes the IO enter event whenever a pkt was received diff --git a/router/io-spec-atomic-events.gobra b/router/io-spec-atomic-events.gobra index fb5956c40..2efb6e7f9 100644 --- a/router/io-spec-atomic-events.gobra +++ b/router/io-spec-atomic-events.gobra @@ -34,17 +34,17 @@ requires dp.Valid() requires ingressID != none[io.Ifs] requires len(oldPkt.CurrSeg.Future) > 0 requires ElemWitness(ioSharedArg.IBufY, ingressID, oldPkt) -requires dp.dp2_enter_guard( +requires dp.Dp2_enter_guard( oldPkt, oldPkt.CurrSeg, - io.establishGuardTraversedseg(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), + io.EstablishGuardTraversedseg(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), dp.Asid(), oldPkt.CurrSeg.Future[0], get(ingressID), oldPkt.CurrSeg.Future[1:]) -requires dp.dp3s_forward( +requires dp.Dp3s_forward( io.Pkt { - io.establishGuardTraversedseg(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), + io.EstablishGuardTraversedseg(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), oldPkt.LeftSeg, oldPkt.MidSeg, oldPkt.RightSeg, @@ -59,16 +59,16 @@ func AtomicEnter(oldPkt io.Pkt, ingressID option[io.Ifs], newPkt io.Pkt, egressI ghost ioLock.Lock() unfold SharedInv{dp, ioSharedArg}() t, s := *ioSharedArg.Place, *ioSharedArg.State - ApplyElemWitness(s.ibuf, ioSharedArg.IBufY, ingressID, oldPkt) + ApplyElemWitness(s.Ibuf, ioSharedArg.IBufY, ingressID, oldPkt) ghost pkt_internal := io.Val(io.ValInternal1{oldPkt, get(ingressID), newPkt, egressID}) - assert dp.dp3s_iospec_bio3s_enter_guard(s, t, pkt_internal) - unfold dp.dp3s_iospec_ordered(s, t) - unfold dp.dp3s_iospec_bio3s_enter(s, t) + assert dp.Dp3s_iospec_bio3s_enter_guard(s, t, pkt_internal) + unfold dp.Dp3s_iospec_ordered(s, t) + unfold dp.Dp3s_iospec_bio3s_enter(s, t) io.TriggerBodyIoEnter(pkt_internal) tN := io.CBio_IN_bio3s_enter_T(t, pkt_internal) io.Enter(t, pkt_internal) //Event - UpdateElemWitness(s.obuf, ioSharedArg.OBufY, egressID, newPkt) - ghost *ioSharedArg.State = io.dp3s_add_obuf(s, egressID, newPkt) + UpdateElemWitness(s.Obuf, ioSharedArg.OBufY, egressID, newPkt) + ghost *ioSharedArg.State = io.Dp3s_add_obuf(s, egressID, newPkt) ghost *ioSharedArg.Place = tN fold SharedInv{dp, ioSharedArg}() ghost ioLock.Unlock() @@ -80,7 +80,7 @@ requires ingressID == none[io.Ifs] requires egressID != none[io.Ifs] requires len(oldPkt.CurrSeg.Future) > 0 requires ElemWitness(ioSharedArg.IBufY, ingressID, oldPkt) -requires dp.dp3s_forward_ext(oldPkt, newPkt, get(egressID)) +requires dp.Dp3s_forward_ext(oldPkt, newPkt, get(egressID)) preserves acc(ioLock.LockP(), _) preserves ioLock.LockInv() == SharedInv{dp, ioSharedArg} ensures ElemWitness(ioSharedArg.OBufY, egressID, newPkt) @@ -89,16 +89,16 @@ func AtomicExit(oldPkt io.Pkt, ingressID option[io.Ifs], newPkt io.Pkt, egressID ghost ioLock.Lock() unfold SharedInv{dp, ioSharedArg}() t, s := *ioSharedArg.Place, *ioSharedArg.State - ApplyElemWitness(s.ibuf, ioSharedArg.IBufY, ingressID, oldPkt) + ApplyElemWitness(s.Ibuf, ioSharedArg.IBufY, ingressID, oldPkt) ghost pkt_internal := io.Val(io.ValInternal2{oldPkt, newPkt, get(egressID)}) - assert dp.dp3s_iospec_bio3s_exit_guard(s, t, pkt_internal) - unfold dp.dp3s_iospec_ordered(s, t) - unfold dp.dp3s_iospec_bio3s_exit(s, t) + assert dp.Dp3s_iospec_bio3s_exit_guard(s, t, pkt_internal) + unfold dp.Dp3s_iospec_ordered(s, t) + unfold dp.Dp3s_iospec_bio3s_exit(s, t) io.TriggerBodyIoExit(pkt_internal) - tN := io.dp3s_iospec_bio3s_exit_T(t, pkt_internal) + tN := io.Dp3s_iospec_bio3s_exit_T(t, pkt_internal) io.Exit(t, pkt_internal) //Event - UpdateElemWitness(s.obuf, ioSharedArg.OBufY, egressID, newPkt) - ghost *ioSharedArg.State = io.dp3s_add_obuf(s, egressID, newPkt) + UpdateElemWitness(s.Obuf, ioSharedArg.OBufY, egressID, newPkt) + ghost *ioSharedArg.State = io.Dp3s_add_obuf(s, egressID, newPkt) ghost *ioSharedArg.Place = tN fold SharedInv{dp, ioSharedArg}() ghost ioLock.Unlock() @@ -111,28 +111,28 @@ requires len(oldPkt.CurrSeg.Future) > 0 requires len(get(oldPkt.LeftSeg).Future) > 0 requires ingressID != none[io.Ifs] requires ElemWitness(ioSharedArg.IBufY, ingressID, oldPkt) -requires dp.dp2_xover_guard( +requires dp.Dp2_xover_guard( oldPkt, oldPkt.CurrSeg, get(oldPkt.LeftSeg), - io.establishGuardTraversedsegInc(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), + io.EstablishGuardTraversedsegInc(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir), io.Pkt { get(oldPkt.LeftSeg), oldPkt.MidSeg, oldPkt.RightSeg, - some(io.establishGuardTraversedsegInc(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir)), + some(io.EstablishGuardTraversedsegInc(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir)), }, oldPkt.CurrSeg.Future[0], get(oldPkt.LeftSeg).Future[0], get(oldPkt.LeftSeg).Future[1:], dp.Asid(), get(ingressID)) -requires dp.dp3s_forward_xover( +requires dp.Dp3s_forward_xover( io.Pkt { get(oldPkt.LeftSeg), oldPkt.MidSeg, oldPkt.RightSeg, - some(io.establishGuardTraversedsegInc(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir)), + some(io.EstablishGuardTraversedsegInc(oldPkt.CurrSeg, !oldPkt.CurrSeg.ConsDir)), }, newPkt, egressID) @@ -144,16 +144,16 @@ func AtomicXover(oldPkt io.Pkt, ingressID option[io.Ifs], newPkt io.Pkt, egressI ghost ioLock.Lock() unfold SharedInv{dp, ioSharedArg}() t, s := *ioSharedArg.Place, *ioSharedArg.State - ApplyElemWitness(s.ibuf, ioSharedArg.IBufY, ingressID, oldPkt) + ApplyElemWitness(s.Ibuf, ioSharedArg.IBufY, ingressID, oldPkt) ghost pkt_internal := io.Val(io.ValInternal1{oldPkt, get(ingressID), newPkt, egressID}) - assert dp.dp3s_iospec_bio3s_xover_guard(s, t, pkt_internal) - unfold dp.dp3s_iospec_ordered(s, t) - unfold dp.dp3s_iospec_bio3s_xover(s, t) + assert dp.Dp3s_iospec_bio3s_xover_guard(s, t, pkt_internal) + unfold dp.Dp3s_iospec_ordered(s, t) + unfold dp.Dp3s_iospec_bio3s_xover(s, t) io.TriggerBodyIoXover(pkt_internal) - tN := io.dp3s_iospec_bio3s_xover_T(t, pkt_internal) + tN := io.Dp3s_iospec_bio3s_xover_T(t, pkt_internal) io.Xover(t, pkt_internal) //Event - UpdateElemWitness(s.obuf, ioSharedArg.OBufY, egressID, newPkt) - ghost *ioSharedArg.State = io.dp3s_add_obuf(s, egressID, newPkt) + UpdateElemWitness(s.Obuf, ioSharedArg.OBufY, egressID, newPkt) + ghost *ioSharedArg.State = io.Dp3s_add_obuf(s, egressID, newPkt) ghost *ioSharedArg.Place = tN fold SharedInv{dp, ioSharedArg}() ghost ioLock.Unlock() diff --git a/router/io-spec-lemmas.gobra b/router/io-spec-lemmas.gobra index 0cc1d6465..a5bcbdcf3 100644 --- a/router/io-spec-lemmas.gobra +++ b/router/io-spec-lemmas.gobra @@ -31,15 +31,15 @@ import ( ghost preserves acc(sl.Bytes(raw, 0, len(raw)), R55) ensures slayers.ValidPktMetaHdr(raw) && slayers.IsSupportedPkt(raw) ==> - absIO_val(raw, ingressID).isValPkt && - absIO_val(raw, ingressID).ValPkt_2 == absPkt(raw) && - absPkt(raw).PathNotFullyTraversed() + AbsIO_val(raw, ingressID).isValPkt && + AbsIO_val(raw, ingressID).ValPkt_2 == AbsPkt(raw) && + AbsPkt(raw).PathNotFullyTraversed() decreases func absIO_valLemma(raw []byte, ingressID uint16) { if(slayers.ValidPktMetaHdr(raw) && slayers.IsSupportedPkt(raw)){ - absIO := reveal absIO_val(raw, ingressID) + absIO := reveal AbsIO_val(raw, ingressID) assert absIO.isValPkt - assert absIO_val(raw, ingressID).ValPkt_2 == absPkt(raw) + assert AbsIO_val(raw, ingressID).ValPkt_2 == AbsPkt(raw) absPktFutureLemma(raw) } } @@ -49,7 +49,7 @@ requires acc(sl.Bytes(raw, 0, len(raw)), R56) requires slayers.ValidPktMetaHdr(raw) ensures acc(sl.Bytes(raw, 0, len(raw)), R56) ensures slayers.ValidPktMetaHdr(raw) -ensures absPkt(raw).PathNotFullyTraversed() +ensures AbsPkt(raw).PathNotFullyTraversed() decreases func absPktFutureLemma(raw []byte) { reveal slayers.ValidPktMetaHdr(raw) @@ -69,7 +69,7 @@ func absPktFutureLemma(raw []byte) { prevSegLen := segs.LengthOfPrevSeg(currHfIdx) numINF := segs.NumInfoFields() offset := scion.HopFieldOffset(numINF, prevSegLen, headerOffsetWithMetaLen) - pkt := reveal absPkt(raw) + pkt := reveal AbsPkt(raw) assert pkt.CurrSeg == reveal scion.CurrSeg(raw, offset, currInfIdx, currHfIdx-prevSegLen, segLen, headerOffsetWithMetaLen) assert pkt.PathNotFullyTraversed() } @@ -124,7 +124,7 @@ decreases pure func (p *scionPacketProcessor) LastHopLen(ub []byte) bool { return (unfolding p.scionLayer.Mem(ub) in (unfolding p.scionLayer.HeaderMem(ub[slayers.CmnHdrLen:]) in p.scionLayer.DstIA) == (unfolding p.d.Mem() in p.d.localIA)) ==> - len(absPkt(ub).CurrSeg.Future) == 1 + len(AbsPkt(ub).CurrSeg.Future) == 1 } //TODO: Does not work with --disableNL --unsafeWildcardoptimization @@ -145,7 +145,7 @@ ensures acc(&p.ingressID, R55) ensures acc(sl.Bytes(ub, 0, len(ub)), R56) ensures slayers.ValidPktMetaHdr(ub) ensures p.ingressID != 0 -ensures len(absPkt(ub).CurrSeg.Future) == 1 +ensures len(AbsPkt(ub).CurrSeg.Future) == 1 decreases func (p* scionPacketProcessor) LocalDstLemma(ub []byte) { reveal p.DstIsLocalIngressID(ub) @@ -176,21 +176,21 @@ pure func (p *scionPacketProcessor) NoBouncingPkt(pkt io.Pkt) bool { return let currseg := pkt.CurrSeg in let OptEgressID := CurrSegIO_ifs(pkt, false) in let egressID := path.IO_ifsToIfs(OptEgressID) in - ((egressID elem p.d.getDomExternal()) || p.ingressID != 0) + ((egressID elem p.d.GetDomExternal()) || p.ingressID != 0) } ghost requires acc(&p.d, R55) && acc(p.d.Mem(), _) requires acc(&p.ingressID, R55) requires pkt.PathNotFullyTraversed() -requires AbsEgressInterfaceConstraint(pkt, path.ifsToIO_ifs(egressID)) -requires (egressID elem p.d.getDomExternal()) || p.ingressID != 0 +requires AbsEgressInterfaceConstraint(pkt, path.IfsToIO_ifs(egressID)) +requires (egressID elem p.d.GetDomExternal()) || p.ingressID != 0 ensures acc(&p.d, R55) && acc(p.d.Mem(), _) ensures acc(&p.ingressID, R55) ensures p.NoBouncingPkt(pkt) decreases func (p *scionPacketProcessor) EstablishNoBouncingPkt(pkt io.Pkt, egressID uint16) { - reveal AbsEgressInterfaceConstraint(pkt, path.ifsToIO_ifs(egressID)) + reveal AbsEgressInterfaceConstraint(pkt, path.IfsToIO_ifs(egressID)) reveal p.NoBouncingPkt(pkt) } @@ -198,15 +198,15 @@ ghost requires acc(&p.d, R55) && acc(p.d.Mem(), _) requires acc(&p.ingressID, R55) requires pkt.PathNotFullyTraversed() -requires AbsEgressInterfaceConstraint(pkt, path.ifsToIO_ifs(egressID)) +requires AbsEgressInterfaceConstraint(pkt, path.IfsToIO_ifs(egressID)) requires p.NoBouncingPkt(pkt) -requires !(egressID elem p.d.getDomExternal()) +requires !(egressID elem p.d.GetDomExternal()) ensures acc(&p.d, R55) && acc(p.d.Mem(), _) ensures acc(&p.ingressID, R55) ensures p.ingressID != 0 decreases func (p *scionPacketProcessor) IngressIDNotZeroLemma(pkt io.Pkt, egressID uint16) { - reveal AbsEgressInterfaceConstraint(pkt, path.ifsToIO_ifs(egressID)) + reveal AbsEgressInterfaceConstraint(pkt, path.IfsToIO_ifs(egressID)) reveal p.NoBouncingPkt(pkt) } @@ -286,18 +286,18 @@ ensures end == p.scionLayer.PathScionEndIdx(ub) ensures p.scionLayer.GetPath(ub) === old(p.scionLayer.GetPath(ub)) ensures typeOf(p.scionLayer.GetPath(ub)) != (*epic.Path) ==> p.path === p.scionLayer.GetPath(ub) -ensures scion.validPktMetaHdr(ub[start:end]) +ensures scion.ValidPktMetaHdr(ub[start:end]) ensures p.path.GetBase(ub[start:end]).EqAbsHeader(ub[start:end]) ensures p.scionLayer.ValidHeaderOffset(ub, len(ub)) ensures p.path === p.scionLayer.GetScionPath(ub) -ensures absPkt(ub) == p.path.absPkt(ub[start:end]) +ensures AbsPkt(ub) == p.path.AbsPkt(ub[start:end]) decreases func (p* scionPacketProcessor) AbsPktToSubSliceAbsPkt(ub []byte, start int, end int) { unfold acc(sl.Bytes(ub, 0, len(ub)), R56) unfold acc(sl.Bytes(ub[start:end], 0, len(ub[start:end])), R56) reveal slayers.ValidPktMetaHdr(ub) reveal p.scionLayer.EqAbsHeader(ub) - assert reveal scion.validPktMetaHdr(ub[start:end]) + assert reveal scion.ValidPktMetaHdr(ub[start:end]) unfold acc(p.scionLayer.Mem(ub), R56) reveal p.scionLayer.ValidHeaderOffset(ub, len(ub)) if typeOf(p.scionLayer.Path) == *epic.Path { @@ -342,7 +342,7 @@ func (p* scionPacketProcessor) AbsPktToSubSliceAbsPkt(ub []byte, start int, end scion.WidenLeftSeg(ub, currInfIdx + 1, segs, headerOffsetWithMetaLen, start, end) scion.WidenMidSeg(ub, currInfIdx + 2, segs, headerOffsetWithMetaLen, start, end) scion.WidenRightSeg(ub, currInfIdx - 1, segs, headerOffsetWithMetaLen, start, end) - assert reveal absPkt(ub) == reveal p.path.absPkt(ub[start:end]) + assert reveal AbsPkt(ub) == reveal p.path.AbsPkt(ub[start:end]) } ghost @@ -352,7 +352,7 @@ requires acc(sl.Bytes(ub, 0, len(ub)), R50) requires acc(sl.Bytes(ub[start:end], 0, len(ub[start:end])), R50) requires acc(&p.path, R55) && acc(p.path.Mem(ub[start:end]), R55) requires p.path === p.scionLayer.GetScionPath(ub) -requires scion.validPktMetaHdr(ub[start:end]) +requires scion.ValidPktMetaHdr(ub[start:end]) requires start == p.scionLayer.PathScionStartIdx(ub) requires end == p.scionLayer.PathScionEndIdx(ub) requires p.path.GetBase(ub[start:end]).EqAbsHeader(ub[start:end]) @@ -370,10 +370,10 @@ ensures end == p.scionLayer.PathScionEndIdx(ub) ensures p.scionLayer.GetPath(ub) === old(p.scionLayer.GetPath(ub)) ensures typeOf(p.scionLayer.GetPath(ub)) != (*epic.Path) ==> p.path === p.scionLayer.GetPath(ub) -ensures scion.validPktMetaHdr(ub[start:end]) +ensures scion.ValidPktMetaHdr(ub[start:end]) ensures p.scionLayer.EqAbsHeader(ub) ensures p.path === p.scionLayer.GetScionPath(ub) -ensures absPkt(ub) == p.path.absPkt(ub[start:end]) +ensures AbsPkt(ub) == p.path.AbsPkt(ub[start:end]) ensures p.scionLayer.ValidHeaderOffset(ub, len(ub)) decreases func (p* scionPacketProcessor) SubSliceAbsPktToAbsPkt(ub []byte, start int, end int){ @@ -382,7 +382,7 @@ func (p* scionPacketProcessor) SubSliceAbsPktToAbsPkt(ub []byte, start int, end unfold acc(p.scionLayer.Mem(ub), R56) unfold acc(p.path.Mem(ub[start:end]), R56) reveal p.scionLayer.ValidHeaderOffset(ub, len(ub)) - reveal scion.validPktMetaHdr(ub[start:end]) + reveal scion.ValidPktMetaHdr(ub[start:end]) if typeOf(p.scionLayer.Path) == *epic.Path { startP := p.scionLayer.PathStartIdx(ub) unfold acc(p.scionLayer.Path.Mem(ub[startP:end]), R56) @@ -427,7 +427,7 @@ func (p* scionPacketProcessor) SubSliceAbsPktToAbsPkt(ub []byte, start int, end scion.WidenLeftSeg(ub, currInfIdx + 1, segs, headerOffsetWithMetaLen, start, end) scion.WidenMidSeg(ub, currInfIdx + 2, segs, headerOffsetWithMetaLen, start, end) scion.WidenRightSeg(ub, currInfIdx - 1, segs, headerOffsetWithMetaLen, start, end) - assert reveal absPkt(ub) == reveal p.path.absPkt(ub[start:end]) + assert reveal AbsPkt(ub) == reveal p.path.AbsPkt(ub[start:end]) } ghost diff --git a/router/io-spec.gobra b/router/io-spec.gobra index 3d813fbd8..311dc7324 100644 --- a/router/io-spec.gobra +++ b/router/io-spec.gobra @@ -35,7 +35,7 @@ opaque requires sl.Bytes(raw, 0, len(raw)) requires slayers.ValidPktMetaHdr(raw) decreases -pure func absPkt(raw []byte) (res io.Pkt) { +pure func AbsPkt(raw []byte) (res io.Pkt) { return let _ := reveal slayers.ValidPktMetaHdr(raw) in let headerOffset := slayers.GetScionPathOffset(raw) in let headerOffsetWithMetaLen := headerOffset + scion.MetaLen in @@ -63,11 +63,11 @@ pure func absPkt(raw []byte) (res io.Pkt) { ghost requires sl.Bytes(raw, 0, len(raw)) ensures val.isValUnsupported -ensures val.ValUnsupported_1 == path.ifsToIO_ifs(ingressID) +ensures val.ValUnsupported_1 == path.IfsToIO_ifs(ingressID) decreases pure func absValUnsupported(raw []byte, ingressID uint16) (val io.Val) { return io.Val(io.ValUnsupported { - path.ifsToIO_ifs(ingressID), + path.IfsToIO_ifs(ingressID), io.Unit{}, }) } @@ -77,9 +77,10 @@ opaque requires sl.Bytes(raw, 0, len(raw)) ensures val.isValPkt || val.isValUnsupported decreases -pure func absIO_val(raw []byte, ingressID uint16) (val io.Val) { +closed +pure func AbsIO_val(raw []byte, ingressID uint16) (val io.Val) { return (reveal slayers.ValidPktMetaHdr(raw) && slayers.IsSupportedPkt(raw)) ? - io.Val(io.ValPkt{path.ifsToIO_ifs(ingressID), absPkt(raw)}) : + io.Val(io.ValPkt{path.IfsToIO_ifs(ingressID), AbsPkt(raw)}) : absValUnsupported(raw, ingressID) } @@ -87,10 +88,10 @@ ghost requires acc(sl.Bytes(raw, 0, len(raw)), R56) requires !slayers.IsSupportedPkt(raw) ensures acc(sl.Bytes(raw, 0, len(raw)), R56) -ensures absIO_val(raw, ingressID).isValUnsupported +ensures AbsIO_val(raw, ingressID).isValUnsupported decreases func AbsUnsupportedPktIsUnsupportedVal(raw []byte, ingressID uint16) { - reveal absIO_val(raw, ingressID) + reveal AbsIO_val(raw, ingressID) } ghost @@ -99,7 +100,7 @@ requires respr.OutPkt != nil ==> decreases pure func absReturnErr(respr processResult) (val io.Val) { return respr.OutPkt == nil ? io.ValUnit{} : - absIO_val(respr.OutPkt, respr.EgressID) + AbsIO_val(respr.OutPkt, respr.EgressID) } ghost @@ -143,6 +144,7 @@ ghost opaque requires d.Mem() decreases +closed pure func (d *DataPlane) DpAgreesWithSpec(dp io.DataPlaneSpec) bool { return unfolding d.Mem() in unfolding neighborIAsInv(d.neighborIAs) in @@ -160,10 +162,10 @@ ensures acc(&d.linkTypes, _) ensures d.linkTypes != nil ==> acc(d.linkTypes, _) && !(0 elem domain(d.linkTypes)) ensures d.dpSpecWellConfiguredLinkTypes(dp) decreases -func (d *DataPlane) LinkTypesLemma(dp io.DataPlaneSpec) { +func (d *DataPlane) linkTypesLemma(dp io.DataPlaneSpec) { reveal d.WellConfigured() reveal d.DpAgreesWithSpec(dp) - assert !(0 elem d.getDomLinkTypes()) + assert !(0 elem d.GetDomLinkTypes()) unfold acc(d.Mem(), _) unfold acc(linkTypesInv(d.linkTypes), _) assert !(0 elem domain(d.linkTypes)) @@ -173,7 +175,7 @@ ghost requires acc(d.Mem(), _) requires d.DpAgreesWithSpec(dp) requires d.WellConfigured() -requires egressID elem d.getDomExternal() +requires egressID elem d.GetDomExternal() ensures egressID != 0 ensures io.Ifs{egressID} elem domain(dp.GetNeighborIAs()) decreases @@ -189,16 +191,16 @@ requires d.external != nil ==> acc(d.external, _) ensures acc(d.Mem(), _) ensures acc(&d.external, _) ensures d.external != nil ==> acc(d.external, _) -ensures d.getDomExternal() == domain(d.external) +ensures d.GetDomExternal() == domain(d.external) decreases func (d *DataPlane) getDomExternalLemma() { if (d.external != nil) { - assert reveal d.getDomExternal() == unfolding acc(d.Mem(), _) in + assert reveal d.GetDomExternal() == unfolding acc(d.Mem(), _) in (unfolding acc(externalInv(d.external), _) in (unfolding acc(accBatchConn(d.external), _) in domain(d.external))) } else { - assert reveal d.getDomExternal() == + assert reveal d.GetDomExternal() == unfolding acc(d.Mem(), _) in (unfolding acc(externalInv(d.external), _) in set[uint16]{}) } @@ -210,5 +212,5 @@ requires sl.Bytes(msg.GetFstBuffer(), 0, len(msg.GetFstBuffer())) decreases pure func MsgToAbsVal(msg *ipv4.Message, ingressID uint16) (res io.Val) { return unfolding msg.Mem() in - absIO_val(msg.Buffers[0], ingressID) + AbsIO_val(msg.Buffers[0], ingressID) } diff --git a/router/widen-lemma.gobra b/router/widen-lemma.gobra index 3c41ee431..6c0449016 100644 --- a/router/widen-lemma.gobra +++ b/router/widen-lemma.gobra @@ -34,8 +34,8 @@ requires acc(sl.Bytes(raw, 0, len(raw)), R49) requires acc(sl.Bytes(raw[:length], 0, len(raw[:length])), R49) ensures acc(sl.Bytes(raw, 0, len(raw)), R49) ensures acc(sl.Bytes(raw[:length], 0, len(raw[:length])), R49) -ensures absIO_val(raw[:length], ingressID).isValPkt ==> - absIO_val(raw[:length], ingressID) == absIO_val(raw, ingressID) +ensures AbsIO_val(raw[:length], ingressID).isValPkt ==> + AbsIO_val(raw[:length], ingressID) == AbsIO_val(raw, ingressID) decreases func absIO_valWidenLemma(raw []byte, ingressID uint16, length int) { var ret1 io.Val @@ -48,15 +48,15 @@ func absIO_valWidenLemma(raw []byte, ingressID uint16, length int) { assert slayers.IsSupportedPkt(raw) absPktWidenLemma(raw, length) - ret1 = io.Val(io.ValPkt{path.ifsToIO_ifs(ingressID), absPkt(raw)}) - ret2 = io.Val(io.ValPkt{path.ifsToIO_ifs(ingressID), absPkt(raw[:length])}) - assert ret1 == reveal absIO_val(raw, ingressID) - assert ret2 == reveal absIO_val(raw[:length], ingressID) + ret1 = io.Val(io.ValPkt{path.IfsToIO_ifs(ingressID), AbsPkt(raw)}) + ret2 = io.Val(io.ValPkt{path.IfsToIO_ifs(ingressID), AbsPkt(raw[:length])}) + assert ret1 == reveal AbsIO_val(raw, ingressID) + assert ret2 == reveal AbsIO_val(raw[:length], ingressID) assert ret1 == ret2 - assert absIO_val(raw[:length], ingressID).isValPkt ==> - absIO_val(raw[:length], ingressID) == absIO_val(raw, ingressID) + assert AbsIO_val(raw[:length], ingressID).isValPkt ==> + AbsIO_val(raw[:length], ingressID) == AbsIO_val(raw, ingressID) } else { - assert !(reveal absIO_val(raw[:length], ingressID).isValPkt) + assert !(reveal AbsIO_val(raw[:length], ingressID).isValPkt) } } @@ -110,7 +110,7 @@ ensures acc(sl.Bytes(raw, 0, len(raw)), R50) ensures acc(sl.Bytes(raw[:length], 0, len(raw[:length])), R50) ensures slayers.ValidPktMetaHdr(raw) ensures slayers.ValidPktMetaHdr(raw[:length]) -ensures absPkt(raw) == absPkt(raw[:length]) +ensures AbsPkt(raw) == AbsPkt(raw[:length]) decreases func absPktWidenLemma(raw []byte, length int) { @@ -147,5 +147,5 @@ func absPktWidenLemma(raw []byte, length int) { scion.WidenMidSeg(raw, currInfIdx + 2, segs, headerOffsetWithMetaLen, 0, length) scion.WidenRightSeg(raw, currInfIdx - 1, segs, headerOffsetWithMetaLen, 0, length) - assert reveal absPkt(raw) == reveal absPkt(raw[:length]) + assert reveal AbsPkt(raw) == reveal AbsPkt(raw[:length]) } diff --git a/verification/dependencies/crypto/rand/util.gobra b/verification/dependencies/crypto/rand/util.gobra index 6c52284e7..625707dab 100644 --- a/verification/dependencies/crypto/rand/util.gobra +++ b/verification/dependencies/crypto/rand/util.gobra @@ -21,10 +21,10 @@ var Reader io.Reader // Int returns a uniform random value in [0, max). It panics if max <= 0. preserves rand.Mem() requires acc(max.Mem(), R13) -requires max.toInt() > 0 +requires max.ToInt() > 0 ensures acc(max.Mem(), R13) ensures err != nil ==> err.ErrorMem() ensures err == nil ==> n.Mem() -ensures err == nil ==> n.toInt() >= 0 && n.toInt() < max.toInt() +ensures err == nil ==> n.ToInt() >= 0 && n.ToInt() < max.ToInt() decreases _ func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) diff --git a/verification/dependencies/github.com/google/gopacket/flows.gobra b/verification/dependencies/github.com/google/gopacket/flows.gobra index 585b46cdb..2d3fc0fa6 100644 --- a/verification/dependencies/github.com/google/gopacket/flows.gobra +++ b/verification/dependencies/github.com/google/gopacket/flows.gobra @@ -23,20 +23,50 @@ type EndpointType int64 decreases func RegisterEndpointType(num int, meta EndpointTypeMetadata) EndpointType -type Flow struct { +comparable type Flow struct { typ EndpointType slen, dlen int src, dst [MaxEndpointSize]byte } +// The fields of Flow are not exported, so the contract of NewFlow below +// describes the result through the following closed pure functions instead. + +ghost +decreases +closed +pure func (f Flow) GetEndpointType() EndpointType { return f.typ } + +ghost +decreases +closed +pure func (f Flow) SrcLen() int { return f.slen } + +ghost +decreases +closed +pure func (f Flow) DstLen() int { return f.dlen } + +ghost +requires 0 <= i && i < MaxEndpointSize +decreases +closed +pure func (f Flow) SrcByte(i int) byte { return f.src[i] } + +ghost +requires 0 <= i && i < MaxEndpointSize +decreases +closed +pure func (f Flow) DstByte(i int) byte { return f.dst[i] } + preserves acc(sl.Bytes(src, 0, len(src)), 1/10000) && acc(sl.Bytes(dst, 0, len(dst)), 1/10000) requires len(src) <= MaxEndpointSize && len(dst) <= MaxEndpointSize -ensures f.slen == len(src) -ensures f.dlen == len(dst) +ensures f.SrcLen() == len(src) +ensures f.DstLen() == len(dst) ensures unfolding acc(sl.Bytes(src, 0, len(src)), 1/10000) in - forall i int :: { &src[i] } 0 <= i && i < len(src) ==> f.src[i] == src[i] + forall i int :: { &src[i] } 0 <= i && i < len(src) ==> f.SrcByte(i) == src[i] ensures unfolding acc(sl.Bytes(dst, 0, len(dst)), 1/10000) in - forall i int :: { &dst[i] } 0 <= i && i < len(dst) ==> f.dst[i] == dst[i] -ensures f.typ == t + forall i int :: { &dst[i] } 0 <= i && i < len(dst) ==> f.DstByte(i) == dst[i] +ensures f.GetEndpointType() == t decreases func NewFlow(t EndpointType, src, dst []byte) (f Flow) diff --git a/verification/dependencies/github.com/google/gopacket/layers/tcpip.gobra b/verification/dependencies/github.com/google/gopacket/layers/tcpip.gobra deleted file mode 100644 index 4706f04c5..000000000 --- a/verification/dependencies/github.com/google/gopacket/layers/tcpip.gobra +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 Google, Inc. All rights reserved. -// Copyright 2009-2011 Andreas Krennmair. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. - -// +gobra - -package layers - -import "github.com/google/gopacket" - -type tcpipchecksum struct { - pseudoheader tcpipPseudoHeader -} - -type tcpipPseudoHeader interface { - pred Mem() - - preserves acc(Mem(), 1/10000) - decreases - pseudoheaderChecksum() (uint32, error) -} diff --git a/verification/dependencies/github.com/google/gopacket/layers/udp.gobra b/verification/dependencies/github.com/google/gopacket/layers/udp.gobra index 9385c0a3a..6e41142a9 100644 --- a/verification/dependencies/github.com/google/gopacket/layers/udp.gobra +++ b/verification/dependencies/github.com/google/gopacket/layers/udp.gobra @@ -15,5 +15,4 @@ type UDP struct { Length uint16 Checksum uint16 sPort, dPort []byte - tcpipchecksum } diff --git a/verification/dependencies/github.com/google/gopacket/layertype.gobra b/verification/dependencies/github.com/google/gopacket/layertype.gobra index b6b038ad6..c05da8b2f 100644 --- a/verification/dependencies/github.com/google/gopacket/layertype.gobra +++ b/verification/dependencies/github.com/google/gopacket/layertype.gobra @@ -54,7 +54,9 @@ ghost var RegisteredTypes = ms.Alloc(AbsMinLayerType, AbsMaxLayerType) /** End of Constants **/ /** Predicates and ghost helper members **/ -pred PkgMem() { +// PkgMem describes the private global state of this package. Importing +// packages may hold (fractions of) it, but they cannot unfold it. +closed pred PkgMem() { acc(<Meta) && acc(<MetaMap) && acc(ltMetaMap) && @@ -74,6 +76,7 @@ pred PkgMem() { ghost requires PkgMem() decreases +closed pure func Registered(t LayerType) (res bool) { return unfolding acc(PkgMem(), _) in 0 <= t && t < MaxLayerType? diff --git a/verification/dependencies/math/big/int.gobra b/verification/dependencies/math/big/int.gobra index 688e65f5a..c2c9cd996 100644 --- a/verification/dependencies/math/big/int.gobra +++ b/verification/dependencies/math/big/int.gobra @@ -25,28 +25,51 @@ type Int struct { abs nat // absolute value of the integer } -pred (i *Int) Mem() { +// The body exposes the non-exported representation of an Int, so importing +// packages may hold this predicate but cannot unfold it. +closed pred (i *Int) Mem() { acc(i) && i.abs.Mem() } // NewInt allocates and returns a new Int set to x. ensures n.Mem() -ensures n.toInt() == int(x) +ensures n.ToInt() == int(x) decreases func NewInt(x int64) (n *Int) // Uint64 returns the uint64 representation of x. // If x cannot be represented in a uint64, the result is undefined. preserves acc(x.Mem(), R13) -ensures unfolding acc(x.Mem(), R13) in len(x.abs) * _W <= 64 ==> toInt(res) == x.abs.toInt() +ensures x.FitsInUint64() ==> Uint64ToInt(res) == x.AbsToInt() decreases func (x *Int) Uint64() (res uint64) +// FitsInUint64 holds iff the magnitude of x is representable in a uint64. It +// abstracts over the non-exported representation of an Int. +ghost +requires x.Mem() +decreases +closed +pure func (x *Int) FitsInUint64() bool { + return unfolding x.Mem() in len(x.abs) * _W <= 64 +} + +// AbsToInt is the magnitude of x. It abstracts over the non-exported +// representation of an Int. +ghost +requires x.Mem() +decreases +closed +pure func (x *Int) AbsToInt() int { + return unfolding x.Mem() in x.abs.toInt() +} + // TODO: This returns int when it should return a mathematical Integer ghost requires i.Mem() decreases -pure func (i *Int) toInt() int { +closed +pure func (i *Int) ToInt() int { return (unfolding i.Mem() in i.neg) ? -((unfolding i.Mem() in i.abs.toInt())) : (unfolding i.Mem() in i.abs.toInt()) } @@ -54,4 +77,4 @@ pure func (i *Int) toInt() int { ghost trusted decreases -pure func toInt(n uint64) int +pure func Uint64ToInt(n uint64) int diff --git a/verification/dependencies/net/ip.gobra b/verification/dependencies/net/ip.gobra index fac00c253..579074f5b 100644 --- a/verification/dependencies/net/ip.gobra +++ b/verification/dependencies/net/ip.gobra @@ -65,8 +65,8 @@ preserves wildcard ==> forall i int :: { &ip[i] } 0 <= i && i < len(ip) ==> acc( preserves !wildcard ==> forall i int :: { &ip[i] } 0 <= i && i < len(ip) ==> acc(&ip[i], R20) ensures res != nil ==> len(res) == IPv4len ensures len(ip) == IPv4len ==> ip === res -ensures (len(ip) == IPv6len && isZeros(ip[0:10]) && ip[10] == 255 && ip[11] == 255) ==> res != nil -ensures (len(ip) == IPv6len && !(isZeros(ip[0:10]) && ip[10] == 255 && ip[11] == 255)) ==> res == nil +ensures (len(ip) == IPv6len && IsZeros(ip[0:10]) && ip[10] == 255 && ip[11] == 255) ==> res != nil +ensures (len(ip) == IPv6len && !(IsZeros(ip[0:10]) && ip[10] == 255 && ip[11] == 255)) ==> res == nil ensures (len(ip) == IPv6len && res != nil) ==> // even though it is technically unecessary, // this assertion allows us to change this contract @@ -92,6 +92,17 @@ requires forall i int :: { &s[i] } 0 <= i && i < len(s) ==> acc(&s[i]) decreases pure func isZeros(s []byte) bool +// IsZeros is the exported counterpart of the non-exported function isZeros. +// Contracts of exported members and importing packages may only mention +// exported names; the body is hidden from importers. +ghost +requires forall i int :: { &s[i] } 0 <= i && i < len(s) ==> acc(&s[i]) +decreases +closed +pure func IsZeros(s []byte) bool { + return isZeros(s) +} + // To16 converts the IP address ip to a 16-byte representation. preserves forall i int :: { &ip[i] } 0 <= i && i < len(ip) ==> acc(&ip[i], R15) ensures len(ip) == IPv4len ==> diff --git a/verification/io/dataplane_abstract.gobra b/verification/io/dataplane_abstract.gobra index 758df0db9..2aad21842 100644 --- a/verification/io/dataplane_abstract.gobra +++ b/verification/io/dataplane_abstract.gobra @@ -19,75 +19,75 @@ package io // links: representation of the network topology as a graph. // `links[(a1,x)] == (a2,y)` means that the interface x of AS a1 is connected // to the interface y of AS a2. -ghost type DataPlaneSpec ghost struct { - linkTypes dict[Ifs]Link - neighborIAs dict[Ifs]AS - localIA AS - links dict[AsIfsPair]AsIfsPair +ghost comparable type DataPlaneSpec ghost struct { + LinkTypes dict[Ifs]Link + NeighborIAs dict[Ifs]AS + LocalIA AS + Links dict[AsIfsPair]AsIfsPair } -ghost type AsIfsPair ghost struct { - asid AS - ifs Ifs +ghost comparable type AsIfsPair ghost struct { + Asid AS + Ifs Ifs } ghost opaque decreases pure func (dp DataPlaneSpec) Valid() bool { - return (forall ifs Ifs :: {ifs elem domain(dp.neighborIAs)} ifs elem domain(dp.neighborIAs) ==> - (AsIfsPair{dp.localIA, ifs} elem domain(dp.links) && - dp.Lookup(AsIfsPair{dp.localIA, ifs}).asid == dp.neighborIAs[ifs])) && - (forall ifs Ifs :: {ifs elem domain(dp.neighborIAs)} AsIfsPair{dp.localIA, ifs} elem domain(dp.links) ==> - ifs elem domain(dp.neighborIAs)) && - (forall pairs AsIfsPair :: {dp.Lookup(pairs)} pairs elem domain(dp.links) ==> + return (forall ifs Ifs :: {ifs elem domain(dp.NeighborIAs)} ifs elem domain(dp.NeighborIAs) ==> + (AsIfsPair{dp.LocalIA, ifs} elem domain(dp.Links) && + dp.Lookup(AsIfsPair{dp.LocalIA, ifs}).Asid == dp.NeighborIAs[ifs])) && + (forall ifs Ifs :: {ifs elem domain(dp.NeighborIAs)} AsIfsPair{dp.LocalIA, ifs} elem domain(dp.Links) ==> + ifs elem domain(dp.NeighborIAs)) && + (forall pairs AsIfsPair :: {dp.Lookup(pairs)} pairs elem domain(dp.Links) ==> let next_pair := dp.Lookup(pairs) in - (next_pair elem domain(dp.links)) && + (next_pair elem domain(dp.Links)) && dp.Lookup(next_pair) == pairs) && - domain(dp.linkTypes) == domain(dp.neighborIAs) + domain(dp.LinkTypes) == domain(dp.NeighborIAs) } ghost decreases pure func (dp DataPlaneSpec) GetLinkTypes() dict[Ifs]Link { - return dp.linkTypes + return dp.LinkTypes } ghost decreases -requires ifs elem domain(dp.linkTypes) +requires ifs elem domain(dp.LinkTypes) pure func (dp DataPlaneSpec) GetLinkType(ifs Ifs) Link { - return dp.linkTypes[ifs] + return dp.LinkTypes[ifs] } ghost decreases pure func (dp DataPlaneSpec) GetNeighborIAs() dict[Ifs]AS { - return dp.neighborIAs + return dp.NeighborIAs } ghost -requires ifs elem domain(dp.neighborIAs) +requires ifs elem domain(dp.NeighborIAs) decreases pure func (dp DataPlaneSpec) GetNeighborIA(ifs Ifs) AS { - return dp.neighborIAs[ifs] + return dp.NeighborIAs[ifs] } ghost decreases pure func (dp DataPlaneSpec) Asid() AS { - return dp.localIA + return dp.LocalIA } ghost decreases pure func (dp DataPlaneSpec) GetLinks() dict[AsIfsPair]AsIfsPair { - return dp.links + return dp.Links } ghost -requires pair elem domain(dp.links) +requires pair elem domain(dp.Links) decreases pure func(dp DataPlaneSpec) Lookup(pair AsIfsPair) AsIfsPair { - return dp.links[pair] + return dp.Links[pair] } \ No newline at end of file diff --git a/verification/io/hopfields.gobra b/verification/io/hopfields.gobra index c1580e20d..9f1c39af5 100644 --- a/verification/io/hopfields.gobra +++ b/verification/io/hopfields.gobra @@ -21,7 +21,7 @@ package io // Abstract representation of an HopField // We consider 0 to be the ID of the internal network in HopField. // We consider None to be the ID of the internal network in HF. -ghost type HF ghost struct { +ghost comparable type HF ghost struct { InIF2 option[Ifs] EgIF2 option[Ifs] HVF MsgTerm diff --git a/verification/io/io-spec.gobra b/verification/io/io-spec.gobra index 55a1b782e..2d8960331 100644 --- a/verification/io/io-spec.gobra +++ b/verification/io/io-spec.gobra @@ -19,30 +19,30 @@ package io // called BogusTrigger instead of Unit here because the name Unit is already in use. -type BogusTrigger struct{} +comparable type BogusTrigger struct{} // Unlike the original IO-spec from Isabelle, we need additional information about the network topology. // To ensure the well-formedness of all map accesses we require an additional conjunction // for all the events (dp.Valid()) // This is the main IO Specification. -pred (dp DataPlaneSpec) dp3s_iospec_ordered(s Dp3sStateLocal, t Place) { - dp.dp3s_iospec_bio3s_enter(s, t) && - dp.dp3s_iospec_bio3s_xover(s, t) && - dp.dp3s_iospec_bio3s_exit(s, t) && - dp.dp3s_iospec_bio3s_send(s, t) && - dp.dp3s_iospec_bio3s_recv(s, t) && - dp.dp3s_iospec_skip(s, t) && - dp.dp3s_iospec_stop(s, t) +pred (dp DataPlaneSpec) Dp3s_iospec_ordered(s Dp3sStateLocal, t Place) { + dp.Dp3s_iospec_bio3s_enter(s, t) && + dp.Dp3s_iospec_bio3s_xover(s, t) && + dp.Dp3s_iospec_bio3s_exit(s, t) && + dp.Dp3s_iospec_bio3s_send(s, t) && + dp.Dp3s_iospec_bio3s_recv(s, t) && + dp.Dp3s_iospec_skip(s, t) && + dp.Dp3s_iospec_stop(s, t) } type Place int -pred token(t Place) +pred IOToken(t Place) ghost decreases -pure func undefined() Dp3sStateLocal +pure func Undefined() Dp3sStateLocal pred CBio_IN_bio3s_enter(t Place, v Val) @@ -56,14 +56,14 @@ ghost requires v.isValInternal1 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_enter_guard(s Dp3sStateLocal, t Place, v Val) bool { - return some(v.ValInternal1_2) elem domain(s.ibuf) && - (let ibuf_set := s.ibuf[some(v.ValInternal1_2)] in (v.ValInternal1_1 elem ibuf_set)) && +pure func (dp DataPlaneSpec) Dp3s_iospec_bio3s_enter_guard(s Dp3sStateLocal, t Place, v Val) bool { + return some(v.ValInternal1_2) elem domain(s.Ibuf) && + (let ibuf_set := s.Ibuf[some(v.ValInternal1_2)] in (v.ValInternal1_1 elem ibuf_set)) && len(v.ValInternal1_1.CurrSeg.Future) > 0 && let currseg := v.ValInternal1_1.CurrSeg in let hf1, fut := currseg.Future[0], currseg.Future[1:] in - let traversedseg := establishGuardTraversedseg(currseg, !currseg.ConsDir) in - dp.dp2_enter_guard( + let traversedseg := EstablishGuardTraversedseg(currseg, !currseg.ConsDir) in + dp.Dp2_enter_guard( v.ValInternal1_1, currseg, traversedseg, @@ -71,7 +71,7 @@ pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_enter_guard(s Dp3sStateLocal, t P hf1, v.ValInternal1_2, fut) && - dp.dp3s_forward( + dp.Dp3s_forward( Pkt { traversedseg, v.ValInternal1_1.LeftSeg, @@ -82,7 +82,7 @@ pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_enter_guard(s Dp3sStateLocal, t P v.ValInternal1_4) } -pred (dp DataPlaneSpec) dp3s_iospec_bio3s_enter(s Dp3sStateLocal, t Place) { +pred (dp DataPlaneSpec) Dp3s_iospec_bio3s_enter(s Dp3sStateLocal, t Place) { forall v Val :: { TriggerBodyIoEnter(v) } ( match v { case ValInternal1{_, _, ?newpkt, ?nextif}: @@ -91,10 +91,10 @@ pred (dp DataPlaneSpec) dp3s_iospec_bio3s_enter(s Dp3sStateLocal, t Place) { // We named the variable `_ignored` because using `_` here leads to a strange // type error. let _ignored := TriggerBodyIoEnter(v) in - (dp.Valid() && dp.dp3s_iospec_bio3s_enter_guard(s, t, v) ==> + (dp.Valid() && dp.Dp3s_iospec_bio3s_enter_guard(s, t, v) ==> (CBio_IN_bio3s_enter(t, v) && - dp.dp3s_iospec_ordered( - dp3s_add_obuf(s, nextif, newpkt), + dp.Dp3s_iospec_ordered( + Dp3s_add_obuf(s, nextif, newpkt), CBio_IN_bio3s_enter_T(t, v)))) default: true @@ -110,14 +110,14 @@ pred CBio_IN_bio3s_xover(t Place, v Val) ghost requires CBio_IN_bio3s_xover(t, v) decreases -pure func dp3s_iospec_bio3s_xover_T(t Place, v Val) Place +pure func Dp3s_iospec_bio3s_xover_T(t Place, v Val) Place // This corresponds to the condition of the if statement in the io-spec case for xover ghost requires v.isValInternal1 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_xover_guard(s Dp3sStateLocal, t Place, v Val) bool { +pure func (dp DataPlaneSpec) Dp3s_iospec_bio3s_xover_guard(s Dp3sStateLocal, t Place, v Val) bool { return let currseg := v.ValInternal1_1.CurrSeg in match v.ValInternal1_1.LeftSeg{ case none[Seg]: @@ -127,9 +127,9 @@ pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_xover_guard(s Dp3sStateLocal, t P (len(nextseg.Future) > 0 && len(currseg.Future) > 0 && let hf1, hf2 := currseg.Future[0], nextseg.Future[0] in - let traversedseg := establishGuardTraversedsegInc(currseg, !currseg.ConsDir) in + let traversedseg := EstablishGuardTraversedsegInc(currseg, !currseg.ConsDir) in let nextfut := nextseg.Future[1:] in - dp.dp3s_xover_guard( + dp.Dp3s_xover_guard( s, v.ValInternal1_1, currseg, @@ -145,20 +145,20 @@ pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_xover_guard(s Dp3sStateLocal, t P } } -pred (dp DataPlaneSpec) dp3s_iospec_bio3s_xover(s Dp3sStateLocal, t Place) { +pred (dp DataPlaneSpec) Dp3s_iospec_bio3s_xover(s Dp3sStateLocal, t Place) { forall v Val :: { TriggerBodyIoXover(v) } ( match v { case ValInternal1{_, _, ?newpkt, ?nextif}: // Gobra requires the triggering term to occur inside the qtfier body, - // otherwise we get an error in the call to dp3s_iospec_bio3s_xover_T. + // otherwise we get an error in the call to Dp3s_iospec_bio3s_xover_T. // We named the variable `_ignored` because using `_` here leads to a strange // type error. let _ignored := TriggerBodyIoXover(v) in - (dp.Valid() && dp.dp3s_iospec_bio3s_xover_guard(s, t, v) ==> + (dp.Valid() && dp.Dp3s_iospec_bio3s_xover_guard(s, t, v) ==> (CBio_IN_bio3s_xover(t, v) && - dp.dp3s_iospec_ordered( - dp3s_add_obuf(s, nextif, newpkt), - dp3s_iospec_bio3s_xover_T(t, v)))) + dp.Dp3s_iospec_ordered( + Dp3s_add_obuf(s, nextif, newpkt), + Dp3s_iospec_bio3s_xover_T(t, v)))) default: true }) @@ -173,34 +173,34 @@ pred CBio_IN_bio3s_exit(t Place, v Val) ghost requires CBio_IN_bio3s_exit(t, v) decreases -pure func dp3s_iospec_bio3s_exit_T(t Place, v Val) Place +pure func Dp3s_iospec_bio3s_exit_T(t Place, v Val) Place // This corresponds to the condition of the if statement in the io-spec case for exit ghost requires v.isValInternal2 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_exit_guard(s Dp3sStateLocal, t Place, v Val) bool { - return none[Ifs] elem domain(s.ibuf) && - (let ibuf_set := s.ibuf[none[Ifs]] in (v.ValInternal2_1 elem ibuf_set)) && +pure func (dp DataPlaneSpec) Dp3s_iospec_bio3s_exit_guard(s Dp3sStateLocal, t Place, v Val) bool { + return none[Ifs] elem domain(s.Ibuf) && + (let ibuf_set := s.Ibuf[none[Ifs]] in (v.ValInternal2_1 elem ibuf_set)) && len(v.ValInternal2_1.CurrSeg.Future) > 0 && - dp.dp3s_forward_ext(v.ValInternal2_1, v.ValInternal2_2, v.ValInternal2_3) + dp.Dp3s_forward_ext(v.ValInternal2_1, v.ValInternal2_2, v.ValInternal2_3) } -pred (dp DataPlaneSpec) dp3s_iospec_bio3s_exit(s Dp3sStateLocal, t Place) { +pred (dp DataPlaneSpec) Dp3s_iospec_bio3s_exit(s Dp3sStateLocal, t Place) { forall v Val :: { TriggerBodyIoExit(v) } ( match v { case ValInternal2{_, ?newpkt, ?nextif}: // Gobra requires the triggering term to occur inside the qtfier body, - // otherwise we get an error in the call to dp3s_iospec_bio3s_exit_T. + // otherwise we get an error in the call to Dp3s_iospec_bio3s_exit_T. // We named the variable `_ignored` because using `_` here leads to a strange // type error. let _ignored := TriggerBodyIoExit(v) in - (dp.Valid() && dp.dp3s_iospec_bio3s_exit_guard(s, t, v) ==> + (dp.Valid() && dp.Dp3s_iospec_bio3s_exit_guard(s, t, v) ==> (CBio_IN_bio3s_exit(t, v) && - dp.dp3s_iospec_ordered( - dp3s_add_obuf(s, some(nextif), newpkt), - dp3s_iospec_bio3s_exit_T(t, v)))) + dp.Dp3s_iospec_ordered( + Dp3s_add_obuf(s, some(nextif), newpkt), + Dp3s_iospec_bio3s_exit_T(t, v)))) default: true }) @@ -215,38 +215,38 @@ pred CBioIO_bio3s_send(t Place, v Val) ghost requires CBioIO_bio3s_send(t, v) decreases -pure func dp3s_iospec_bio3s_send_T(t Place, v Val) Place +pure func Dp3s_iospec_bio3s_send_T(t Place, v Val) Place // This corresponds to the condition of the if statement in the io-spec case for send ghost requires v.isValPkt requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_iospec_bio3s_send_guard(s Dp3sStateLocal, t Place, v Val) bool { - return v.ValPkt_1 elem domain(s.obuf) && - (let obuf_set := s.obuf[v.ValPkt_1] in (v.ValPkt_2 elem obuf_set)) +pure func (dp DataPlaneSpec) Dp3s_iospec_bio3s_send_guard(s Dp3sStateLocal, t Place, v Val) bool { + return v.ValPkt_1 elem domain(s.Obuf) && + (let obuf_set := s.Obuf[v.ValPkt_1] in (v.ValPkt_2 elem obuf_set)) } -pred (dp DataPlaneSpec) dp3s_iospec_bio3s_send(s Dp3sStateLocal, t Place) { +pred (dp DataPlaneSpec) Dp3s_iospec_bio3s_send(s Dp3sStateLocal, t Place) { forall v Val :: { TriggerBodyIoSend(v) } ( match v { case ValPkt{_, _}: // Gobra requires the triggering term to occur inside the qtfier body, - // otherwise we get an error in the call to dp3s_iospec_bio3s_send_T. + // otherwise we get an error in the call to Dp3s_iospec_bio3s_send_T. // We named the variable `_ignored` because using `_` here leads to a strange // type error. let _ignored := TriggerBodyIoSend(v) in - (dp.Valid() && dp.dp3s_iospec_bio3s_send_guard(s, t, v) ==> + (dp.Valid() && dp.Dp3s_iospec_bio3s_send_guard(s, t, v) ==> CBioIO_bio3s_send(t, v) && - dp.dp3s_iospec_ordered(s, dp3s_iospec_bio3s_send_T(t, v))) + dp.Dp3s_iospec_ordered(s, Dp3s_iospec_bio3s_send_T(t, v))) case ValUnsupported{_, _}: // Gobra requires the triggering term to occur inside the qtfier body, - // otherwise we get an error in the call to dp3s_iospec_bio3s_send_T. + // otherwise we get an error in the call to Dp3s_iospec_bio3s_send_T. // We named the variable `_ignored` because using `_` here leads to a strange // type error. let _ignored := TriggerBodyIoSend(v) in (CBioIO_bio3s_send(t, v) && - dp.dp3s_iospec_ordered(s, dp3s_iospec_bio3s_send_T(t, v))) + dp.Dp3s_iospec_ordered(s, Dp3s_iospec_bio3s_send_T(t, v))) default: true }) @@ -261,7 +261,7 @@ pred CBioIO_bio3s_recv(t Place) ghost requires CBioIO_bio3s_recv(t) decreases -pure func dp3s_iospec_bio3s_recv_T(t Place) Place +pure func Dp3s_iospec_bio3s_recv_T(t Place) Place // We can safely make this assumption as Isabelle's IO-spec never // receives the other IO values (Unit and Internal). @@ -269,18 +269,18 @@ ghost requires CBioIO_bio3s_recv(t) ensures val.isValPkt || val.isValUnsupported decreases -pure func dp3s_iospec_bio3s_recv_R(t Place) (val Val) +pure func Dp3s_iospec_bio3s_recv_R(t Place) (val Val) -pred (dp DataPlaneSpec) dp3s_iospec_bio3s_recv(s Dp3sStateLocal, t Place) { +pred (dp DataPlaneSpec) Dp3s_iospec_bio3s_recv(s Dp3sStateLocal, t Place) { CBioIO_bio3s_recv(t) && - (match dp3s_iospec_bio3s_recv_R(t) { + (match Dp3s_iospec_bio3s_recv_R(t) { case ValPkt{?recvif, ?pkt}: - dp.dp3s_iospec_ordered( - dp3s_add_ibuf(s, recvif, pkt), dp3s_iospec_bio3s_recv_T(t)) + dp.Dp3s_iospec_ordered( + Dp3s_add_ibuf(s, recvif, pkt), Dp3s_iospec_bio3s_recv_T(t)) case ValUnsupported{_, _}: - dp.dp3s_iospec_ordered(s, dp3s_iospec_bio3s_recv_T(t)) + dp.Dp3s_iospec_ordered(s, Dp3s_iospec_bio3s_recv_T(t)) default: - dp.dp3s_iospec_ordered(undefined(), dp3s_iospec_bio3s_recv_T(t)) + dp.Dp3s_iospec_ordered(Undefined(), Dp3s_iospec_bio3s_recv_T(t)) }) } @@ -289,33 +289,33 @@ pred CBio_Skip(t Place) ghost requires CBio_Skip(t) decreases -pure func dp3s_iospec_skip_T(t Place) Place +pure func Dp3s_iospec_skip_T(t Place) Place -pred (dp DataPlaneSpec) dp3s_iospec_skip(s Dp3sStateLocal, t Place) { - CBio_Skip(t) && dp.dp3s_iospec_ordered(s, dp3s_iospec_skip_T(t)) +pred (dp DataPlaneSpec) Dp3s_iospec_skip(s Dp3sStateLocal, t Place) { + CBio_Skip(t) && dp.Dp3s_iospec_ordered(s, Dp3s_iospec_skip_T(t)) } -pred (dp DataPlaneSpec) dp3s_iospec_stop(s Dp3sStateLocal, t Place) { +pred (dp DataPlaneSpec) Dp3s_iospec_stop(s Dp3sStateLocal, t Place) { true } /** BIO operations **/ ghost decreases -requires token(t) && CBio_IN_bio3s_enter(t, v) -ensures token(old(CBio_IN_bio3s_enter_T(t, v))) +requires IOToken(t) && CBio_IN_bio3s_enter(t, v) +ensures IOToken(old(CBio_IN_bio3s_enter_T(t, v))) func Enter(ghost t Place, ghost v Val) ghost decreases -requires token(t) && CBio_IN_bio3s_xover(t, v) -ensures token(old(dp3s_iospec_bio3s_xover_T(t, v))) +requires IOToken(t) && CBio_IN_bio3s_xover(t, v) +ensures IOToken(old(Dp3s_iospec_bio3s_xover_T(t, v))) func Xover(ghost t Place, ghost v Val) ghost decreases -requires token(t) && CBio_IN_bio3s_exit(t, v) -ensures token(old(dp3s_iospec_bio3s_exit_T(t, v))) +requires IOToken(t) && CBio_IN_bio3s_exit(t, v) +ensures IOToken(old(Dp3s_iospec_bio3s_exit_T(t, v))) func Exit(ghost t Place, ghost v Val) /** End of helper functions to perfrom BIO operations **/ diff --git a/verification/io/io_spec_definitions.gobra b/verification/io/io_spec_definitions.gobra index ba376061d..dc6851b2e 100644 --- a/verification/io/io_spec_definitions.gobra +++ b/verification/io/io_spec_definitions.gobra @@ -22,9 +22,9 @@ package io ghost requires len(currseg.Future) > 0 decreases -pure func establishGuardTraversedseg(currseg Seg, direction bool) Seg { +pure func EstablishGuardTraversedseg(currseg Seg, direction bool) Seg { return let uinfo := direction ? - upd_uinfo(currseg.UInfo, currseg.Future[0]) : + Upd_uinfo(currseg.UInfo, currseg.Future[0]) : currseg.UInfo in Seg { AInfo: currseg.AInfo, @@ -41,9 +41,9 @@ pure func establishGuardTraversedseg(currseg Seg, direction bool) Seg { ghost requires len(currseg.Future) > 0 decreases -pure func establishGuardTraversedsegInc(currseg Seg, direction bool) Seg { +pure func EstablishGuardTraversedsegInc(currseg Seg, direction bool) Seg { return let uinfo := direction ? - upd_uinfo(currseg.UInfo, currseg.Future[0]) : + Upd_uinfo(currseg.UInfo, currseg.Future[0]) : currseg.UInfo in Seg { AInfo: currseg.AInfo, @@ -102,7 +102,7 @@ pure func (pkt Pkt) UpdateInfoField(info AbsInfoField) Pkt { // This type simplifies the infoField, making it easier // to use than the Seg from the IO-spec. -ghost type AbsInfoField ghost struct { +ghost comparable type AbsInfoField ghost struct { AInfo Ainfo UInfo set[MsgTerm] ConsDir bool @@ -112,7 +112,7 @@ ghost type AbsInfoField ghost struct { // The segment lengths of a packet are frequently used together. // This type combines them into a single structure to simplify // their specification. -ghost type SegLens ghost struct { +ghost comparable type SegLens ghost struct { Seg1Len int Seg2Len int Seg3Len int diff --git a/verification/io/other_defs.gobra b/verification/io/other_defs.gobra index 6cd451109..a96646b73 100644 --- a/verification/io/other_defs.gobra +++ b/verification/io/other_defs.gobra @@ -18,15 +18,15 @@ package io -ghost type Unit ghost struct{} +ghost comparable type Unit ghost struct{} // interface IDs -ghost type Ifs ghost struct { +ghost comparable type Ifs ghost struct { V uint16 } // type of AS identifiers. Matches the type 'as' in Isabelle. -ghost type AS ghost struct { +ghost comparable type AS ghost struct { V uint } @@ -84,7 +84,7 @@ ghost type Key adt { } // "authenticated hop information" -ghost type AHI ghost struct { +ghost comparable type AHI ghost struct { InIF option[Ifs] EgIF option[Ifs] ASID AS @@ -92,15 +92,15 @@ ghost type AHI ghost struct { ghost decreases -pure func (hf HF) extr_asid() AS { - return hf.HVF.extract_asid() +pure func (hf HF) Extr_asid() AS { + return hf.HVF.Extract_asid() } // function 'toab' in Isabelle, originally of type HF_scheme -> aahi_scheme ghost decreases pure func (h HF) Toab() AHI { - return AHI{h.InIF2, h.EgIF2, h.HVF.extract_asid()} + return AHI{h.InIF2, h.EgIF2, h.HVF.Extract_asid()} } /* Link Types */ @@ -118,7 +118,7 @@ ghost requires dp.Valid() requires p1 == dp.Asid() decreases -pure func (dp DataPlaneSpec) link_type(p1 AS, p2 Ifs) Link{ +pure func (dp DataPlaneSpec) Link_type(p1 AS, p2 Ifs) Link{ return p2 elem domain(dp.GetLinkTypes()) ? dp.GetLinkType(p2) : IO_NoLink{} } @@ -126,8 +126,8 @@ ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) egif_prov2(hf1 HF, asid AS) bool{ - return dp.egif2_type(hf1, asid, Link(IO_CustProv{})) +pure func (dp DataPlaneSpec) Egif_prov2(hf1 HF, asid AS) bool{ + return dp.Egif2_type(hf1, asid, Link(IO_CustProv{})) } @@ -135,58 +135,58 @@ ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) egif_core2(hf1 HF, asid AS) bool{ - return dp.egif2_type(hf1, asid, Link(IO_Core{})) +pure func (dp DataPlaneSpec) Egif_core2(hf1 HF, asid AS) bool{ + return dp.Egif2_type(hf1, asid, Link(IO_Core{})) } ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) egif_cust2(hf1 HF, asid AS) bool{ - return dp.egif2_type(hf1, asid, Link(IO_ProvCust{})) +pure func (dp DataPlaneSpec) Egif_cust2(hf1 HF, asid AS) bool{ + return dp.Egif2_type(hf1, asid, Link(IO_ProvCust{})) } ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) inif_cust2(hf1 HF, asid AS) bool{ - return dp.inif2_type(hf1, asid, Link(IO_ProvCust{})) +pure func (dp DataPlaneSpec) Inif_cust2(hf1 HF, asid AS) bool{ + return dp.Inif2_type(hf1, asid, Link(IO_ProvCust{})) } ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) inif_core2(hf1 HF, asid AS) bool{ - return dp.inif2_type(hf1, asid, Link(IO_Core{})) +pure func (dp DataPlaneSpec) Inif_core2(hf1 HF, asid AS) bool{ + return dp.Inif2_type(hf1, asid, Link(IO_Core{})) } ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) inif_prov2(hf1 HF, asid AS) bool{ - return dp.inif2_type(hf1, asid, Link(IO_CustProv{})) +pure func (dp DataPlaneSpec) Inif_prov2(hf1 HF, asid AS) bool{ + return dp.Inif2_type(hf1, asid, Link(IO_CustProv{})) } ghost requires dp.Valid() requires ifs != none[Ifs] ==> asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) if_type(asid AS, ifs option[Ifs], link Link) bool{ +pure func (dp DataPlaneSpec) If_type(asid AS, ifs option[Ifs], link Link) bool{ return match ifs { case none[Ifs]: false default: - dp.link_type(asid, get(ifs)) == link + dp.Link_type(asid, get(ifs)) == link } } ghost opaque decreases -pure func (m MsgTerm) extract_asid() AS { +pure func (m MsgTerm) Extract_asid() AS { return m.MsgTerm_Hash_.MsgTerm_MPair_1.MsgTerm_Key_.Key_macK_ } diff --git a/verification/io/packets.gobra b/verification/io/packets.gobra index 92ca2682f..42bce192e 100644 --- a/verification/io/packets.gobra +++ b/verification/io/packets.gobra @@ -21,7 +21,7 @@ package io // this type stands for the Isabelle type pkt2 instantiated with all its type paramenters, i.e., pkt3 // Here, we already instantiated the type params, instead of // leaving them generic as done in Isabelle. -ghost type Pkt ghost struct { +ghost comparable type Pkt ghost struct { CurrSeg Seg LeftSeg option[Seg] MidSeg option[Seg] diff --git a/verification/io/router.gobra b/verification/io/router.gobra index 7fc04377c..091390b59 100644 --- a/verification/io/router.gobra +++ b/verification/io/router.gobra @@ -22,7 +22,7 @@ package io ghost decreases -pure func if2term(ifs option[Ifs]) MsgTerm { +pure func If2term(ifs option[Ifs]) MsgTerm { return match ifs { case none[Ifs]: MsgTerm_Empty{} @@ -33,39 +33,39 @@ pure func if2term(ifs option[Ifs]) MsgTerm { ghost decreases -pure func (dp DataPlaneSpec) hf_valid(d bool, ts uint, uinfo set[MsgTerm], hf HF) bool { - return hf_valid_impl(dp.Asid(), ts, uinfo, hf) +pure func (dp DataPlaneSpec) Hf_valid(d bool, ts uint, uinfo set[MsgTerm], hf HF) bool { + return Hf_valid_impl(dp.Asid(), ts, uinfo, hf) } ghost decreases -pure func hf_valid_impl(asid AS, ts uint, uinfo set[MsgTerm], hf HF) bool { +pure func Hf_valid_impl(asid AS, ts uint, uinfo set[MsgTerm], hf HF) bool { return let inif := hf.InIF2 in let egif := hf.EgIF2 in let hvf := hf.HVF in - let next := nextMsgtermSpec(asid, inif, egif, ts, uinfo) in + let next := NextMsgtermSpec(asid, inif, egif, ts, uinfo) in hvf == next } ghost opaque -ensures result.extract_asid() == asid +ensures result.Extract_asid() == asid decreases -pure func nextMsgtermSpec(asid AS, inif option[Ifs], egif option[Ifs], ts uint, uinfo set[MsgTerm]) (result MsgTerm) { - return let l := plaintextToMac(inif, egif, ts, uinfo) in - let res := mac(macKey(asidToKey(asid)), l) in - let _ := reveal res.extract_asid() in +pure func NextMsgtermSpec(asid AS, inif option[Ifs], egif option[Ifs], ts uint, uinfo set[MsgTerm]) (result MsgTerm) { + return let l := PlaintextToMac(inif, egif, ts, uinfo) in + let res := Mac(MacKey(AsidToKey(asid)), l) in + let _ := reveal res.Extract_asid() in res } ghost decreases -pure func plaintextToMac(inif option[Ifs], egif option[Ifs], ts uint, uinfo set[MsgTerm]) MsgTerm { +pure func PlaintextToMac(inif option[Ifs], egif option[Ifs], ts uint, uinfo set[MsgTerm]) MsgTerm { return MsgTerm_L { seq[MsgTerm]{ MsgTerm_Num{ts}, - if2term(inif), - if2term(egif), + If2term(inif), + If2term(egif), MsgTerm_FS{uinfo}, }, } @@ -73,13 +73,13 @@ pure func plaintextToMac(inif option[Ifs], egif option[Ifs], ts uint, uinfo set[ ghost decreases -pure func macKey(key Key) MsgTerm { +pure func MacKey(key Key) MsgTerm { return MsgTerm_Key{key} } ghost decreases -pure func mac(fst MsgTerm, snd MsgTerm) MsgTerm { +pure func Mac(fst MsgTerm, snd MsgTerm) MsgTerm { return MsgTerm_Hash { MsgTerm_Hash_: MsgTerm_MPair { MsgTerm_MPair_1: fst, @@ -91,55 +91,48 @@ pure func mac(fst MsgTerm, snd MsgTerm) MsgTerm { // helper function, not defined in IO spec ghost decreases -pure func asidToKey(asid AS) Key { +pure func AsidToKey(asid AS) Key { return Key_macK{asid} } ghost decreases -pure func upd_uinfo(segid set[MsgTerm], hf HF) set[MsgTerm] { +pure func Upd_uinfo(segid set[MsgTerm], hf HF) set[MsgTerm] { return let setHVF := set[MsgTerm]{hf.HVF} in (segid union setHVF) setminus (segid intersection setHVF) } -ghost -decreases -pure func (dp DataPlaneSpec) asid() AS { - return dp.Asid() -} - - // This function is provided as locale in the Isabelle formalization. ghost requires dp.Valid() decreases -pure func (dp DataPlaneSpec) is_target(asid AS, nextif Ifs, a2 AS, i2 Ifs) bool { +pure func (dp DataPlaneSpec) Is_target(asid AS, nextif Ifs, a2 AS, i2 Ifs) bool { return AsIfsPair{asid, nextif} elem domain(dp.GetLinks()) && dp.Lookup(AsIfsPair{asid, nextif}) == AsIfsPair{a2, i2} } ghost decreases -pure func dp3s_add_ibuf(s Dp3sStateLocal, i option[Ifs], pkt Pkt) Dp3sStateLocal { +pure func Dp3s_add_ibuf(s Dp3sStateLocal, i option[Ifs], pkt Pkt) Dp3sStateLocal { return Dp3sStateLocal { - ibuf: insert(s.ibuf, i, pkt), - obuf: s.obuf, + Ibuf: Insert(s.Ibuf, i, pkt), + Obuf: s.Obuf, } } ghost decreases -pure func dp3s_add_obuf(s Dp3sStateLocal, i option[Ifs], pkt Pkt) Dp3sStateLocal { +pure func Dp3s_add_obuf(s Dp3sStateLocal, i option[Ifs], pkt Pkt) Dp3sStateLocal { return Dp3sStateLocal { - ibuf: s.ibuf, - obuf: insert(s.obuf, i, pkt), + Ibuf: s.Ibuf, + Obuf: Insert(s.Obuf, i, pkt), } } // helper func ghost decreases -pure func insert(buf dict[option[Ifs]](set[Pkt]), k option[Ifs], v Pkt) dict[option[Ifs]](set[Pkt]) { +pure func Insert(buf dict[option[Ifs]](set[Pkt]), k option[Ifs], v Pkt) dict[option[Ifs]](set[Pkt]) { return let newSet := (k elem domain(buf) ? (let pre := buf[k] in pre union set[Pkt]{v}) : set[Pkt]{v}) in buf[k = newSet] } @@ -148,44 +141,44 @@ ghost requires len(m.CurrSeg.Future) > 0 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_forward_ext(m Pkt, newpkt Pkt, nextif Ifs) bool { +pure func (dp DataPlaneSpec) Dp3s_forward_ext(m Pkt, newpkt Pkt, nextif Ifs) bool { return let _ := reveal dp.Valid() in let currseg := m.CurrSeg in let hf1, fut := currseg.Future[0], currseg.Future[1:] in let traversedseg := newpkt.CurrSeg in - dp.dp2_forward_ext_guard(dp.Asid(), m, nextif, currseg, traversedseg, newpkt, fut, hf1) && + dp.Dp2_forward_ext_guard(dp.Asid(), m, nextif, currseg, traversedseg, newpkt, fut, hf1) && (nextif elem domain(dp.GetNeighborIAs())) && let a2 := dp.GetNeighborIA(nextif) in - let i2 := dp.Lookup(AsIfsPair{dp.Asid(), nextif}).ifs in - dp.is_target(dp.Asid(), nextif, a2, i2) + let i2 := dp.Lookup(AsIfsPair{dp.Asid(), nextif}).Ifs in + dp.Is_target(dp.Asid(), nextif, a2, i2) } ghost requires len(m.CurrSeg.Future) > 0 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_forward_ext_xover(m Pkt, newpkt Pkt, nextif Ifs) bool { +pure func (dp DataPlaneSpec) Dp3s_forward_ext_xover(m Pkt, newpkt Pkt, nextif Ifs) bool { return let _ := reveal dp.Valid() in let currseg := m.CurrSeg in let hf1, fut := currseg.Future[0], currseg.Future[1:] in let traversedseg := newpkt.CurrSeg in - dp.dp2_forward_ext_guard(dp.Asid(), m, nextif, currseg, traversedseg, newpkt, fut, hf1) && + dp.Dp2_forward_ext_guard(dp.Asid(), m, nextif, currseg, traversedseg, newpkt, fut, hf1) && (nextif elem domain(dp.GetNeighborIAs())) && let a2 := dp.GetNeighborIA(nextif) in - let i2 := dp.Lookup(AsIfsPair{dp.Asid(), nextif}).ifs in - dp.is_target(dp.Asid(), nextif, a2, i2) + let i2 := dp.Lookup(AsIfsPair{dp.Asid(), nextif}).Ifs in + dp.Is_target(dp.Asid(), nextif, a2, i2) } ghost requires len(m.CurrSeg.Future) > 0 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_forward(m Pkt, newpkt Pkt, nextif option[Ifs]) bool { +pure func (dp DataPlaneSpec) Dp3s_forward(m Pkt, newpkt Pkt, nextif option[Ifs]) bool { return match nextif { case none[Ifs]: newpkt == m default: - dp.dp3s_forward_ext(m, newpkt, get(nextif)) + dp.Dp3s_forward_ext(m, newpkt, get(nextif)) } } @@ -193,12 +186,12 @@ ghost requires len(m.CurrSeg.Future) > 0 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_forward_xover(m Pkt, newpkt Pkt, nextif option[Ifs]) bool { +pure func (dp DataPlaneSpec) Dp3s_forward_xover(m Pkt, newpkt Pkt, nextif option[Ifs]) bool { return match nextif { case none[Ifs]: newpkt == m default: - dp.dp3s_forward_ext_xover(m, newpkt, get(nextif)) + dp.Dp3s_forward_ext_xover(m, newpkt, get(nextif)) } } @@ -206,7 +199,7 @@ ghost requires len(intermediatepkt.CurrSeg.Future) > 0 requires dp.Valid() decreases -pure func (dp DataPlaneSpec) dp3s_xover_guard( +pure func (dp DataPlaneSpec) Dp3s_xover_guard( s Dp3sStateLocal, m Pkt, currseg Seg, @@ -222,8 +215,8 @@ pure func (dp DataPlaneSpec) dp3s_xover_guard( ) bool { // the first conjunct was added to Gobra, even though it was not in the original isabelle spec. // this is because of the way math. maps are implemented, we can only obtain a key that is in the map before. - return some(recvif) elem domain(s.ibuf) && - (let lookupRes := s.ibuf[some(recvif)] in (m elem lookupRes)) && - dp.dp2_xover_guard(m, currseg, nextseg, traversedseg, intermediatepkt, hf1, hf2, nextfut, dp.Asid(), recvif) && - dp.dp3s_forward_xover(intermediatepkt, newpkt, nextif) + return some(recvif) elem domain(s.Ibuf) && + (let lookupRes := s.Ibuf[some(recvif)] in (m elem lookupRes)) && + dp.Dp2_xover_guard(m, currseg, nextseg, traversedseg, intermediatepkt, hf1, hf2, nextfut, dp.Asid(), recvif) && + dp.Dp3s_forward_xover(intermediatepkt, newpkt, nextif) } diff --git a/verification/io/router_events.gobra b/verification/io/router_events.gobra index 14aa665fa..b57d9522a 100644 --- a/verification/io/router_events.gobra +++ b/verification/io/router_events.gobra @@ -23,26 +23,26 @@ ghost requires dp.Valid() requires a == dp.Asid() decreases -pure func (dp DataPlaneSpec) valid_link_types2(hf1 HF, a AS) bool { - return (dp.egif_prov2(hf1, a) && dp.inif_cust2(hf1, a)) || - (dp.egif_core2(hf1, a) && dp.inif_core2(hf1, a)) || - (dp.egif_cust2(hf1, a) && dp.inif_prov2(hf1, a)) +pure func (dp DataPlaneSpec) Valid_link_types2(hf1 HF, a AS) bool { + return (dp.Egif_prov2(hf1, a) && dp.Inif_cust2(hf1, a)) || + (dp.Egif_core2(hf1, a) && dp.Inif_core2(hf1, a)) || + (dp.Egif_cust2(hf1, a) && dp.Inif_prov2(hf1, a)) } ghost requires dp.Valid() requires a == dp.Asid() decreases -pure func (dp DataPlaneSpec) valid_link_types_in2(hf1 HF, a AS) bool { - return (dp.inif_prov2(hf1, a) && dp.egif_cust2(hf1, a)) || - (dp.inif_core2(hf1, a) && dp.egif_core2(hf1, a)) || - (dp.inif_cust2(hf1, a) && dp.egif_prov2(hf1, a)) +pure func (dp DataPlaneSpec) Valid_link_types_in2(hf1 HF, a AS) bool { + return (dp.Inif_prov2(hf1, a) && dp.Egif_cust2(hf1, a)) || + (dp.Inif_core2(hf1, a) && dp.Egif_core2(hf1, a)) || + (dp.Inif_cust2(hf1, a) && dp.Egif_prov2(hf1, a)) } /* End of Abbreviations */ ghost decreases -pure func (dp DataPlaneSpec) dp2_enter_interface(d bool, asid AS, hf1 HF, recvif Ifs) bool { +pure func (dp DataPlaneSpec) Dp2_enter_interface(d bool, asid AS, hf1 HF, recvif Ifs) bool { return (d && hf1.InIF2 === some(recvif)) || (!d && hf1.EgIF2 === some(recvif)) } @@ -50,13 +50,13 @@ ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) dp2_check_interface_top(d bool, asid AS, hf1 HF) bool { - return (d && dp.valid_link_types_in2(hf1, asid)) || (!d && dp.valid_link_types2(hf1, asid)) +pure func (dp DataPlaneSpec) Dp2_check_interface_top(d bool, asid AS, hf1 HF) bool { + return (d && dp.Valid_link_types_in2(hf1, asid)) || (!d && dp.Valid_link_types2(hf1, asid)) } ghost decreases -pure func dp2_exit_interface(d bool, asid AS, hf1 HF, outif Ifs) bool { +pure func Dp2_exit_interface(d bool, asid AS, hf1 HF, outif Ifs) bool { return (d && hf1.EgIF2 == some(outif)) || (!d && hf1.InIF2 == some(outif)) } @@ -65,21 +65,21 @@ ghost requires dp.Valid() requires dp.Asid() == asid decreases -pure func (dp DataPlaneSpec) dp2_forward_ext_guard(asid AS, m Pkt, nextif Ifs, currseg, traversedseg Seg, newpkt Pkt, fut seq[HF], hf1 HF) bool { +pure func (dp DataPlaneSpec) Dp2_forward_ext_guard(asid AS, m Pkt, nextif Ifs, currseg, traversedseg Seg, newpkt Pkt, fut seq[HF], hf1 HF) bool { return m.CurrSeg == currseg && newpkt == Pkt{traversedseg, m.LeftSeg, m.MidSeg, m.RightSeg} && // The outgoing interface is correct: - dp2_exit_interface(currseg.ConsDir, asid, hf1, nextif) && + Dp2_exit_interface(currseg.ConsDir, asid, hf1, nextif) && // Next validate the current hop field with the *original* UInfo field): - dp.hf_valid(currseg.ConsDir, currseg.AInfo.V, currseg.UInfo, hf1) && - hf1.extr_asid() == asid && + dp.Hf_valid(currseg.ConsDir, currseg.AInfo.V, currseg.UInfo, hf1) && + hf1.Extr_asid() == asid && // Segment update: push current hop field into the Past path and History: - inc_seg2(currseg, traversedseg, hf1, fut) && + Inc_seg2(currseg, traversedseg, hf1, fut) && // If the current segment is an *down*-segment, then we need to update the // uinfo field *after* validating the hop field - update_uinfo(currseg.ConsDir, currseg, traversedseg, hf1) && + Update_uinfo(currseg.ConsDir, currseg, traversedseg, hf1) && // Other fields: no update - same_other2(currseg, traversedseg) + Same_other2(currseg, traversedseg) } // A packet is received from an ext state (i.e., an inter-AS channel) and is forwarded (either internally or externally) @@ -87,14 +87,14 @@ ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) dp2_enter_guard(m Pkt, currseg Seg, traversedseg Seg, asid AS, hf1 HF, recvif Ifs, fut seq[HF]) bool { +pure func (dp DataPlaneSpec) Dp2_enter_guard(m Pkt, currseg Seg, traversedseg Seg, asid AS, hf1 HF, recvif Ifs, fut seq[HF]) bool { return m.CurrSeg == currseg && currseg.Future == seq[HF]{hf1} ++ fut && - dp.dp2_enter_interface(currseg.ConsDir, asid, hf1, recvif) && - (dp.dp2_check_interface_top(currseg.ConsDir, asid, hf1) || fut == seq[HF]{}) && - update_uinfo(!currseg.ConsDir, currseg, traversedseg, hf1) && - same_segment2(currseg, traversedseg) && - same_other2(currseg, traversedseg) && - dp.hf_valid(currseg.ConsDir, currseg.AInfo.V, traversedseg.UInfo, hf1) && - hf1.extr_asid() == asid + dp.Dp2_enter_interface(currseg.ConsDir, asid, hf1, recvif) && + (dp.Dp2_check_interface_top(currseg.ConsDir, asid, hf1) || fut == seq[HF]{}) && + Update_uinfo(!currseg.ConsDir, currseg, traversedseg, hf1) && + Same_segment2(currseg, traversedseg) && + Same_other2(currseg, traversedseg) && + dp.Hf_valid(currseg.ConsDir, currseg.AInfo.V, traversedseg.UInfo, hf1) && + hf1.Extr_asid() == asid } diff --git a/verification/io/router_state.gobra b/verification/io/router_state.gobra index 081f1715b..09bdaba39 100644 --- a/verification/io/router_state.gobra +++ b/verification/io/router_state.gobra @@ -18,7 +18,7 @@ package io -ghost type Dp3sStateLocal ghost struct { - ibuf dict[option[Ifs]](set[Pkt]) - obuf dict[option[Ifs]](set[Pkt]) +ghost comparable type Dp3sStateLocal ghost struct { + Ibuf dict[option[Ifs]](set[Pkt]) + Obuf dict[option[Ifs]](set[Pkt]) } diff --git a/verification/io/segment-defs.gobra b/verification/io/segment-defs.gobra index 6b95f6208..c323c09ff 100644 --- a/verification/io/segment-defs.gobra +++ b/verification/io/segment-defs.gobra @@ -23,7 +23,7 @@ package io ghost decreases -pure func inc_seg2(currseg, traversedseg Seg, hf1 HF, fut seq[HF]) bool { +pure func Inc_seg2(currseg, traversedseg Seg, hf1 HF, fut seq[HF]) bool { return currseg.Future === seq[HF]{hf1} ++ fut && traversedseg.Future === fut && traversedseg.Past === seq[HF]{hf1} ++ currseg.Past && @@ -32,7 +32,7 @@ pure func inc_seg2(currseg, traversedseg Seg, hf1 HF, fut seq[HF]) bool { ghost decreases -pure func same_segment2(currseg, traversedseg Seg) bool { +pure func Same_segment2(currseg, traversedseg Seg) bool { return traversedseg.Future === currseg.Future && traversedseg.Past === currseg.Past && traversedseg.History === currseg.History @@ -40,25 +40,25 @@ pure func same_segment2(currseg, traversedseg Seg) bool { ghost decreases -pure func update_uinfo2(currseg, traversedseg Seg, hf1 HF) bool { - return traversedseg.UInfo === upd_uinfo(currseg.UInfo, hf1) +pure func Update_uinfo2(currseg, traversedseg Seg, hf1 HF) bool { + return traversedseg.UInfo === Upd_uinfo(currseg.UInfo, hf1) } ghost decreases -pure func same_uinfo2(currseg, traversedseg Seg) bool { +pure func Same_uinfo2(currseg, traversedseg Seg) bool { return currseg.UInfo === traversedseg.UInfo } ghost decreases -pure func update_uinfo(condition bool, currseg, traversedseg Seg, hf1 HF) bool { - return condition? update_uinfo2(currseg, traversedseg, hf1) : same_uinfo2(currseg, traversedseg) +pure func Update_uinfo(condition bool, currseg, traversedseg Seg, hf1 HF) bool { + return condition? Update_uinfo2(currseg, traversedseg, hf1) : Same_uinfo2(currseg, traversedseg) } ghost decreases -pure func same_other2(currseg, traversedseg Seg) bool { +pure func Same_other2(currseg, traversedseg Seg) bool { return traversedseg.AInfo === currseg.AInfo && traversedseg.ConsDir === currseg.ConsDir && traversedseg.Peer === currseg.Peer diff --git a/verification/io/segments.gobra b/verification/io/segments.gobra index 01f774f7a..6c89b838e 100644 --- a/verification/io/segments.gobra +++ b/verification/io/segments.gobra @@ -18,14 +18,14 @@ package io -ghost type Ainfo ghost struct { +ghost comparable type Ainfo ghost struct { V uint } // Here, we already instantiated the type params, contrary to what // is done in Isabelle, where they are left generic. //Ccorresponds to the isabelle types seg2 and seg3. -ghost type Seg ghost struct { +ghost comparable type Seg ghost struct { AInfo Ainfo // nat in Isabelle UInfo set[MsgTerm] ConsDir bool diff --git a/verification/io/xover.gobra b/verification/io/xover.gobra index b0c4c14b7..72b943701 100644 --- a/verification/io/xover.gobra +++ b/verification/io/xover.gobra @@ -34,7 +34,7 @@ ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) dp2_xover_guard(m Pkt, +pure func (dp DataPlaneSpec) Dp2_xover_guard(m Pkt, currseg Seg, nextseg Seg, traversedseg Seg, @@ -50,46 +50,46 @@ pure func (dp DataPlaneSpec) dp2_xover_guard(m Pkt, newpkt == Pkt{nextseg, m.MidSeg, m.RightSeg, some(traversedseg)} && currseg.Future == seq[HF]{hf1} && nextseg.Future == seq[HF]{hf2} ++ nextfut && - dp.dp2_enter_interface(currseg.ConsDir, asid, hf1, recvif) && - dp.xover2_link_type_dir(dp.Asid(), currseg.ConsDir, hf1, nextseg.ConsDir, hf2) && - update_uinfo(!currseg.ConsDir, currseg, traversedseg, hf1) && - inc_seg2(currseg, traversedseg, hf1, seq[HF]{}) && - dp.hf_valid(currseg.ConsDir, currseg.AInfo.V, traversedseg.UInfo, hf1) && - dp.hf_valid(nextseg.ConsDir, nextseg.AInfo.V, nextseg.UInfo, hf2) && - hf1.extr_asid() == asid && - hf2.extr_asid() == asid && - same_other2(currseg, traversedseg) + dp.Dp2_enter_interface(currseg.ConsDir, asid, hf1, recvif) && + dp.Xover2_link_type_dir(dp.Asid(), currseg.ConsDir, hf1, nextseg.ConsDir, hf2) && + Update_uinfo(!currseg.ConsDir, currseg, traversedseg, hf1) && + Inc_seg2(currseg, traversedseg, hf1, seq[HF]{}) && + dp.Hf_valid(currseg.ConsDir, currseg.AInfo.V, traversedseg.UInfo, hf1) && + dp.Hf_valid(nextseg.ConsDir, nextseg.AInfo.V, nextseg.UInfo, hf2) && + hf1.Extr_asid() == asid && + hf2.Extr_asid() == asid && + Same_other2(currseg, traversedseg) } ghost requires dp.Valid() requires a == dp.Asid() decreases -pure func (dp DataPlaneSpec) egif2_type(hf HF, a AS, link Link) bool { - return dp.if_type(a, hf.EgIF2, link) +pure func (dp DataPlaneSpec) Egif2_type(hf HF, a AS, link Link) bool { + return dp.If_type(a, hf.EgIF2, link) } ghost requires dp.Valid() requires a == dp.Asid() decreases -pure func (dp DataPlaneSpec) inif2_type(hf HF, a AS, link Link) bool { - return dp.if_type(a, hf.InIF2, link) +pure func (dp DataPlaneSpec) Inif2_type(hf HF, a AS, link Link) bool { + return dp.If_type(a, hf.InIF2, link) } ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) xover2_link_type(asid AS, hf1 HF, hf2 HF) bool { - return (dp.inif2_type(hf1, asid, IO_ProvCust{}) && dp.egif2_type(hf2, asid, IO_ProvCust{})) || - (dp.inif2_type(hf1, asid, IO_ProvCust{}) && dp.egif2_type(hf2, asid, IO_Core{})) || - (dp.inif2_type(hf1, asid, IO_Core{}) && dp.egif2_type(hf2, asid, IO_ProvCust{})) +pure func (dp DataPlaneSpec) Xover2_link_type(asid AS, hf1 HF, hf2 HF) bool { + return (dp.Inif2_type(hf1, asid, IO_ProvCust{}) && dp.Egif2_type(hf2, asid, IO_ProvCust{})) || + (dp.Inif2_type(hf1, asid, IO_ProvCust{}) && dp.Egif2_type(hf2, asid, IO_Core{})) || + (dp.Inif2_type(hf1, asid, IO_Core{}) && dp.Egif2_type(hf2, asid, IO_ProvCust{})) } ghost decreases -pure func swap_if_dir2(hf HF, d bool) HF { +pure func Swap_if_dir2(hf HF, d bool) HF { return HF { InIF2: d ? hf.InIF2 : hf.EgIF2, EgIF2: d ? hf.EgIF2 : hf.InIF2, @@ -101,8 +101,8 @@ ghost requires dp.Valid() requires asid == dp.Asid() decreases -pure func (dp DataPlaneSpec) xover2_link_type_dir(asid AS, d1 bool, hf1 HF, d2 bool, hf2 HF) bool { - return dp.xover2_link_type(asid, swap_if_dir2(hf1, d1), swap_if_dir2(hf2, d2)) +pure func (dp DataPlaneSpec) Xover2_link_type_dir(asid AS, d1 bool, hf1 HF, d2 bool, hf2 HF) bool { + return dp.Xover2_link_type(asid, Swap_if_dir2(hf1, d1), Swap_if_dir2(hf2, d2)) } diff --git a/verification/utils/ghost_sync/ghost-mutex.gobra b/verification/utils/ghost_sync/ghost-mutex.gobra index c49a4caaa..5325ed50f 100644 --- a/verification/utils/ghost_sync/ghost-mutex.gobra +++ b/verification/utils/ghost_sync/ghost-mutex.gobra @@ -29,7 +29,7 @@ import . "verification/utils/definitions" // Currently, Gobra does not check any of these two properties. Property (1) could be done // by using obligations. -type GhostMutex struct { +comparable type GhostMutex struct { privateField PrivateField } diff --git a/verification/utils/monoset/monoset.gobra b/verification/utils/monoset/monoset.gobra index d84b09a10..9454b00a8 100644 --- a/verification/utils/monoset/monoset.gobra +++ b/verification/utils/monoset/monoset.gobra @@ -26,7 +26,9 @@ type BoundedMonotonicSet struct { ghost End int64 } -pred (b BoundedMonotonicSet) Inv() { +// The body of this predicate exposes the private representation of the set, so +// importing packages may observe the predicate but not unfold it. +closed pred (b BoundedMonotonicSet) Inv() { (b.Start <= b.End) && (forall i int64 :: b.Start <= i && i <= b.End ==> (i elem domain(b.valuesMap) && acc(b.valuesMap[i], 1/2))) && @@ -39,6 +41,7 @@ ghost requires b.Inv() requires b.Start <= i && i <= b.End decreases +closed pure func (b BoundedMonotonicSet) FContains(i int64) bool { // extra indirection avoids a type-checking bug of Gobra. return unfolding acc(b.Inv(), _) in @@ -54,7 +57,7 @@ pure func (b BoundedMonotonicSet) fcontainshelper(i int64) bool { } -pred (b BoundedMonotonicSet) Contains(i int64) { +closed pred (b BoundedMonotonicSet) Contains(i int64) { b.Start <= i && i <= b.End && i elem domain(b.valuesMap) && acc(b.valuesMap[i], _) && @@ -80,7 +83,7 @@ func (b BoundedMonotonicSet) PromoteContains(i int64) { fold b.Contains(i) } -pred (b BoundedMonotonicSet) DoesNotContain(i int64) { +closed pred (b BoundedMonotonicSet) DoesNotContain(i int64) { b.Start <= i && i <= b.End && i elem domain(b.valuesMap) && acc(b.valuesMap[i], 1/2) && @@ -173,7 +176,8 @@ func Alloc(start, end int64) (res BoundedMonotonicSet) { } ghost -opaque // make this closed when that is supported +opaque +closed requires b.Inv() decreases pure func (b BoundedMonotonicSet) ToSet() set[int64] { diff --git a/verification/utils/resalgebra/auth.gobra b/verification/utils/resalgebra/auth.gobra index 96ba158ab..f75889d77 100644 --- a/verification/utils/resalgebra/auth.gobra +++ b/verification/utils/resalgebra/auth.gobra @@ -82,15 +82,15 @@ pure func (ra TypeAuthRA) Compose(e1 Elem, e2 Elem) (res Elem) { return let c1 := e1.(AuthCarrier) in let c2 := e2.(AuthCarrier) in (c1.Fst === Bottom{} ? - AuthCarrier{c2.Fst, max(c1.Snd, c2.Snd)} : + AuthCarrier{c2.Fst, Max(c1.Snd, c2.Snd)} : (c2.Fst === Bottom{} ? - AuthCarrier{c1.Fst, max(c1.Snd, c2.Snd)} : - AuthCarrier{Top{}, max(c1.Snd, c2.Snd)})) + AuthCarrier{c1.Fst, Max(c1.Snd, c2.Snd)} : + AuthCarrier{Top{}, Max(c1.Snd, c2.Snd)})) } ghost decreases -pure func max(a int, b int) int { +pure func Max(a int, b int) int { return a > b ? a : b } diff --git a/verification/utils/resalgebra/auth_test.gobra b/verification/utils/resalgebra/auth_test.gobra index 61f279ac6..c16909512 100644 --- a/verification/utils/resalgebra/auth_test.gobra +++ b/verification/utils/resalgebra/auth_test.gobra @@ -24,7 +24,9 @@ type MonoCounter struct { ghost loc LocName } -pred (c *MonoCounter) Mem() { +// The body exposes the private state of MonoCounter, so the predicate is only +// fully visible inside this package. +closed pred (c *MonoCounter) Mem() { acc(c) && c.authRes === AuthView(c.val) && AuthRA.IsElem(c.authRes) && @@ -35,6 +37,7 @@ pred (c *MonoCounter) Mem() { ghost requires c.Mem() decreases +closed pure func (c *MonoCounter) GetLocName() LocName { return unfolding c.Mem() in c.loc }