Statically Verified Refinements for Multiparty Protocols
Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, Nobuko Yoshida
aa r X i v : . [ c s . P L ] S e p FANGYI ZHOU,
Imperial College London, United Kingdom
FRANCISCO FERREIRA,
Imperial College London, United Kingdom
RAYMOND HU,
University of Hertfordshire, United Kingdom
RUMYANA NEYKOVA,
Brunel University London, United Kingdom
NOBUKO YOSHIDA,
Imperial College London, United KingdomWith distributed computing becoming ubiquitous in the modern era, safe distributed programming is an openchallenge. To address this, multiparty session types (MPST) provide a typing discipline for message-passingconcurrency, guaranteeing communication safety properties such as deadlock freedom.While originally MPST focus on the communication aspects, and employ a simple typing system for com-munication payloads, communication protocols in the real world usually contain constraints on the payload.We introduce refined multiparty session types (RMPST) , an extension of MPST, that express data dependentprotocols via refinement types on the data types.We provide an implementation of RMPST, in a toolchain called
Session ⋆ , using Scribble , a multipartyprotocol description toolchain, and targeting F ⋆ , a verification-oriented functional programming language.Users can describe a protocol in Scribble and implement the endpoints in F ⋆ using refinement-typed APIsgenerated from the protocol. The F ⋆ compiler can then statically verify the refinements. Moreover, we use anovel approach of callback-styled API generation, providing static linearity guarantees with the inversion ofcontrol. We evaluate our approach with real world examples and show that it has little overhead comparedto a naïve implementation, while guaranteeing safety properties from the underlying theory.CCS Concepts: • Theory of computation → Automated reasoning ; Distributed computing models ; • Soft-ware and its engineering → Source code generation ; ACM Reference Format:
Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida. 2018. StaticallyVerified Refinements for Multiparty Protocols.
Proc. ACM Program. Lang.
1, CONF, Article 1 (January 2018),37 pages.
Distributed interactions and message passing are fundamental elements of the modern comput-ing landscape. Unfortunately, language features and support for high-level and safe programmingof communication-oriented and distributed programs are much lacking, in comparison to thoseenjoyed for more traditional “localised” models of computation. One of the research directions to-wards addressing this challenge is concurrent behavioural types [Ancona et al. 2016; Gay and Ravara2017], which seek to extend the benefits of conventional type systems, as the most successful formof lightweight formal verification, to communication and concurrency.
Multiparty session types (MPST) [Honda et al. 2008, 2016], one of the most active topics in thisarea, offer a theoretical framework for specifying message passing protocols between multipleparticipants. MPST use a type system–based approach to statically verify whether a system of pro-cesses implements a given protocol safely. The type system guarantees key execution properties A uthors’ addresses: Fangyi Zhou, Imperial College London, United Kingdom, [email protected]; FranciscoFerreira, Imperial College London, United Kingdom, [email protected]; Raymond Hu, University of Hertford-shire, United Kingdom, [email protected]; Rumyana Neykova, Brunel University London, United Kingdom, [email protected]; Nobuko Yoshida, Imperial College London, United Kingdom, [email protected]. 2475-1421/2018/1-ART1 $15.00https://doi.org/ Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :2 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida G = A → B : Count ( count : int { count ≥ }) . µ t ( curr : int { curr ≥ ∧ curr ≤ count })h curr : = i . B → C (cid:26) Hello ( it : int { curr < count ∧ it = count }) . t h curr : = curr + i Finish ( it : int { curr = count ∧ it = count }) . end (cid:27) A Global Type G Projection ontoeach Participant
Local Type for A L A Local Type for B L B Local Type for C L C Fig. 1. Top-down View of (R)MPST such as freedom from message reception errors or deadlocks. However, despite much recent pro-gress, there remain large gaps between the current state of the art and (i) powerful and practical languages and techniques available to programmers today, and (ii) more advanced type disciplinesneeded to express a wider variety of constraints of interaction found in real-world protocols.This paper presents and combines two main developments: a theory of MPST enriched with re-finement types [Freeman and Pfenning 1991], and a practical method, callback-based programming ,for safe session programming. The key ideas are as follows:
Refined
Multiparty Session Types (RMPST) . The MPST theory [Honda et al. 2008, 2016] providesa core framework for decomposing (or projecting ) a global type structure, describing the collectivebehaviour of a distributed system, into a set of participant-specific local types (see Fig. 1). The localtypes are then used to implement endpoints.Our theory of RMPST follows the same top-down methodology, but enriches MPST with fea-tures from refinement types [Freeman and Pfenning 1991], to support the elaboration of data typesin global and local types. Refinement types allow refinements in the form of logical predicates andconstraints to be attached to a base type. This allows to express various constraints in protocols.To motivate our refinement type extension, we use a counting protocol shown in Fig. 1, andleave the details to § 4. Participant A sends B a number with a Count message. In this message, therefinement type count : int { count ≥ } restricts the value for count to be a natural number. Then B sends C exactly that number of Hello messages, followed by a
Finish message.We demonstrate how refinement types are used to better specify the protocol: The counting partof the protocol is described using a recursive type with two branches, where we use refinementtypes to restrict the protocol flow. The variable curr is a recursion variable , which remembersthe current iteration, initialised to , and increments on each recursion ( curr : = curr + ). Therefinement curr = count in the Finish branch specifies that the branch may only be taken at thelast iteration; the refinement it = count in both Hello and
Finish branches specifies a payload value dependent on the recursion variable curr and the variable count transmitted in the first message.We establish the correctness of Refined MPST. In particular, we show that projection is behaviour-preserving and that well-formed global types with refinements satisfy progress, i.e. they do notget stuck. Therefore, if the endpoints follow the behaviour prescribed by the local types, derived(via projection) from a well-formed global type with refinements, the system is deadlock-free.
Callback-styled, Refinement-typed
APIs for Endpoint Implementations . One of the mainchallenges in applying session types in practice is dealing with session linearity : a session channelis used once and only once . Session typing relies on a linear treatment of communication chan-nels, in order to track the I/O actions performed on the channel against the intended session type.Most existing implementations adopt one of two approaches: monadic interfaces in functional
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:3 languages [Imai et al. 2020, 2019; Orchard and Yoshida 2017], or “hybrid” approaches that comple-ment static typing with dynamic linearity checks [Hu and Yoshida 2016; Scalas et al. 2017].This paper proposes a fresh look to session-based programming that does not require linearitychecking for static safety. We promote a form of session programming where session I/O is impli-citly implemented by callback functions — we say “implicitly” because the user does not write anyI/O operations themself: an input callback is written to take a received message as a parameter,and an output callback is written to simply return the label and value of the message to be sent.The callbacks are supported by a runtime, generated along with APIs in refinement types ac-cording to the local type. The runtime performs communication and invokes user-specified call-back functions upon corresponding communication events. We provide a code generation tool tostreamline the writing of callback functions for the projected local type.The inversion of control allows us to dispense with linearity checking, because our approachdoes not expose communication channels to the user. Our approach is a natural fit to functionalprogramming settings, but also directly applicable to any statically typed language. Moreover, thelinearity guarantee is achieved statically without the use of a linear type system, a feature that isusually not supported by mainstream programming languages. We follow the principle of event-based programming via the use of callbacks, prevalent in modern days of computing.
A Toolchain Implementation:
Session ⋆ . To evaluate our proposal, we implement RMPSTwith a toolchain —
Session ⋆ , as an extension to the Scribble F ⋆ [Swamy et al. 2016] as the target endpoint language.Building on our callback approach, we show how to integrate RMPST with the verification-oriented functional programming language F ⋆ , exploiting its capabilities of refinement types andstatic verification to extend our fully static safety guarantees to data refinements in sessions. Ourexperience of specifying and implementing protocols drawn from the literature and real-world ap-plications attests to the practicality of our approach and the value of statically verified refinements.Our integration of RMPST and F ⋆ allows developers to utilise advanced type system features toimplement safe distributed application protocols. Paper Summary and Contributions . § 2 We present an overview of our toolchain: Session ⋆ , and provide background knowledge of Scribble and MPST. We use a number guessing game,
HigherLower , as our running example.§ 3 We introduce
Session ⋆ , a toolchain for RMPST. We describe in detail how our generated APIscan be used to implement multiparty protocols with refinements.§ 4 We establish the metatheory of RMPST, which gives semantics of global and local types with re-finements. We prove trace equivalence of global and local types w.r.t. projection (Theorem 4.10),and show progress and type safety of well-formed global types (Theorem 4.14 and Theorem 4.15).§ 5 We evaluate our toolchain with examples from the session type literature, and measure thetime taken for compilation and execution. We show that our toolchain does not have a longcompilation time, and our runtime does not incur a large overhead on execution time.We submitted an artifact for evaluation [Zhou et al. 2020], containing the source code of ourtoolchain Session ⋆ , with examples and benchmarks used in the evaluation. The artifact is availableas a Docker image, and can be accessed on the Docker Hub. The source files are available onGitHub (https://github.com/sessionstar/oopsla20-artifact). We present the proof of our theorems,and additional technical details of the toolchain, in the appendix. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :4 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida global protocol HigherLower(role A, role B, role C) {start(n0:int) from A to B;...} type state = ...type callbacks = ...type conn = ...let run callbacks conn = ... let callbacks = ...let connection = ...let () = run callbacks connection ExtractedOCaml Program program.ml
Projectionvia
Scribble
Generates Implements Extractsinto
Scribble
Protocol (§ 2.2) Endpoint Implementation (§ 3.2)CFSM Representation F ⋆ API
User Input
Internal/Generated
Fig. 2. Overview of Toolchain
In this section, we give an overview of our toolchain:
Session ⋆ , describing its key toolchain stages. Session ⋆ extends the Scribble toolchain with refinement types and uses F ⋆ as a target language.We begin with a short background on basic multiparty session types and Scribble , then demon-strate the specification of distributed applications with refinements using the extended
Scribble . We present an overview of our toolchain in Fig. 2, where we distinguish user provided input bydevelopers in solid boxes , from generated code or toolchain internals in dashed boxes .Development begins with specifying a protocol using an extended
Scribble protocol descriptionlanguage.
Scribble is closely associated with the MPST theory [Hu 2017; Neykova and Yoshida2019], and provides a user-friendly syntax for multiparty protocols. We extend the
Scribble tool-chain to support RMPST, allowing refinements to be added via annotations. The extended
Scribble toolchain (as part of
Session ⋆ ) validates the well-formedness of the protocol, and produces a rep-resentation in the form of a communicating finite state machine (CFSM, [Brand and Zafiropulo1983]) for a given participant.We then use a code generator (also as part of Session ⋆ ) to generate F ⋆ APIs from the CFSM,utilising a number of advanced type system features available in F ⋆ (explained later in § 3.1). Thegenerated APIs, described in detail in § 3, consist of various type definitions, and an entry pointfunction taking callbacks and connections as arguments.In our design methodology, we separate the concern of communication and program logic . Thecallbacks, corresponding to program logic, do not involve communication primitives — they are in-voked to prompt a value to be sent, or to process a received value. Separately, developers provide aconnection that allows base types to be serialised and transmitted to other participants. Developersimplement the endpoint by providing both callbacks and connections , according to the generatedrefinement typed APIs. They can run the protocol by invoking the generated entry point. Finally,the F ⋆ source files can be verified using the F ⋆ compiler, and extracted to an OCaml program (orother supported targets) for efficient execution. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:5 global protocol HigherLower(role A, role B, role C) { // A tells B a secret number `n0`, // and the number `t0` of attempts that C has to guess it start(n0:int) from A to B; @'0 ≤ n0 < limit(t0:int) from A to B; @'0 < t0' do Aux(A, B, C); @'B[n0, t0]' } aux global protocol Aux(role A, role B, role C) @'B[n:int{0 ≤ n < < t}]' { guess(x:int) from C to B; @'0 ≤ x < choice at B { higher() from B to C; @'n > x ∧ t >
1' // Secret is higher higher() from B to A; do Aux(A, B, C); @'B[n, t-1]' } or { win() from B to C; @'n = x' // C wins, A loses lose() from B to A; } or { lower() from B to C; @'n < x ∧ t >
1' // Secret is lower lower() from B to A; do Aux(A, B, C); @'B[n, t-1]' } or { lose() from B to C; @'n , x ∧ t =
1' // A wins, C loses win() from B to A; } } Fig. 3. A
Refined
Scribble
Global Protocol for a
HigherLower
Game.
Scribble
The workflow in the standard MPST theory [Honda et al. 2008], as is generally the case in dis-tributed application development, starts from identifying the intended protocol for participantinteractions. In our toolchain, a global protocol —the description of the whole protocol betweenall participants from a bird eye’s view—is specified using our RMPST extension of the
Scribble protocol description language [Hu 2017; Scribble Authors 2015]. Figure 3 gives the global protocolfor a three-party game,
HigherLower , which we use as a running example.
Basic
Scribble /MPST . We first explain basic
Scribble (corresponding to the standard MPST) without the @ -annotations (annotations are extensions to the basic Scribble ).(1) The main protocol
HigherLower declares three roles A , B and C , representing the runtime com-munication session participants. The protocol starts with A sending B a start message and a limit message, each carrying an int payload.(2) The do construct specifies all three roles to proceed according to the (recursive) Aux sub-protocol. C sends B a guess message, also carrying an int . (The aux keyword simply tells Scribble thata sub-protocol does not need to be verified as a top-level entry protocol.)(3) The choice at B construct specifies at this point that B should decide (make an internal choice)by which one of the four cases the protocol should proceed. This decision is explicitly commu-nicated (as an external choice) to A and C via the messages in each case. The higher and lower cases are the recursive cases, leading to another round of Aux (i.e. another guess by C ); theother two cases, win and lose , end the protocol.To sum up, A sends B two numbers, and C sends a number (at least one) to B for as long as B replies with either higher or lower to C (and A ). Next we demonstrate how we can express datadependencies using refinements with our extended Scribble . Extended
Scribble /RMPST . As described above, a basic global protocol (equivalent to a stand-ard MPST global type ) specifies the structure of participant interactions, but is not very informative
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :6 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida about the behaviour of the application in the aspect of data transmitted. This limitation can be con-trasted against standardised (but informal) specifications of real-world application protocols, e.g.HTTP, OAuth, where a significant part, if not the majority, of the specification is devoted to the data side of the protocol. It goes without saying, details missing from the specification cannot beverified on an implementation.We go through Fig. 3 again, this time including the practical extensions proposed by this pa-per to address these limitations: RMPST enables a refinement type–based treatment of protocols,capturing and integrating both data constraints and interactions. While refinement types by them-selves can already greatly enrich the specification of individual messages, the most valuable andinteresting aspect is the interplay between data refinements and the consequent interactions (i.e.the protocol flow) in the distributed, multiparty setting. In our setup, we allow data-dependentrefinements to be specified in the global protocol, we explain various ways of using them in therunning example: • Message Values.
A basic use of refinements is on message values , specifically their payloadcontents. The annotation on the first interaction (Line 4) specifies that A and B not only com-municate an n0:int , but that ≤ n0 < is a post condition for the value produced by A and a pre condition on the value received by B . Similarly, the int carried by limit must be positive. • Local Protocol State.
RMPST also supports refinements on the recursions that a protocol trans-itions through. The
B[...] annotation (Line 7) in the
Aux header specifies the local state knownby B during the recursion, whenever B reaches this point in the ongoing protocol. The local stateincludes an int n such that ≤ n < and an int t such that . These extra variables are avail-able for all enactments of this subprotocol. That is, on the first entry from HigherLower , wherethe do annotation B[n0, t0] (Line 6) specifies the initial values; and from the recursive entries(Line 11).By known state, we mean that B will have access to the exact values at runtime, although stat-ically we can only be sure that they lie within the intervals specified in the refinements. Othersession participants can only use the type information, without knowing the value, e.g. C doesnot know the exact value of n (which is the main point of this game), but knows the range viathe refinements, and hence the endpoint may utilise this knowledge for reasoning. • Protocol Flow.
As mentioned, RMPST combines protocol specifications with refinements inorder to direct the flow of the protocol — specifically at internal choices. The annotation on the win interaction (Line 12) from B to C specifies that B can only send this message, and thus selectthis choice case, after a correct guess by C . Similarly, B can only select the other cases after anincorrect guess: lose (Line 17) when C is on its last attempt, or the corresponding higher (Line 9)or lower (Line 14) cases otherwise. We exploit the fact that a refinement type can be uninhabiteddue to the impossibility to satisfy the constraint on the type, to encode protocol flow conditions.Refinements allow a basic description of an interaction structure to be elaborated into a moreexpressive application specification. Note the t > in the higher and lower refinements are neces-sary to ensure that the < t in the Aux refinement is satisfied, given that the do annotations specify Aux to be recursively enacted with t-1 . Albeit simple, the protocol shows how we can use refine-ments in various means to express data and control flow dependencies and recursive invariants ina multiparty setup. Once the protocol is specified, our toolchain allows the refinements in RMPSTto be directly mapped to data refinements in F* through a callback-styled API generation. F ⋆ In this section, we demonstrate our callback-styled, refinement-typed APIs for implementing en-dpoints in F ⋆ [Swamy et al. 2016]. We introduced earlier the workflow of our toolchain (§ 2.1). Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:7
In § 3.1, we summarise the key features of F ⋆ utilised in our implementation. Using our runningexample, we explain the generated APIs in F ⋆ in § 3.2, and how to implement endpoints in § 3.3.We outline the function we generate for executing the endpoint in § 3.4.Developers using Session ⋆ implement the callbacks in F ⋆ , to utilise the functionality of refine-ment types provided by the F ⋆ type-checker. The F ⋆ compiler can verify statically whether theprovided implementation by the developer satisfies the refinements as specified in the protocol.The verified code can be extracted via the F ⋆ compiler to OCaml and executed.The verified implementation enjoys properties both from the MPST theory, such as session fidel-ity and deadlock freedom , but also from refinement types, that the data dependencies are verifiedto be correct according to the protocol. Additional details on code generation can be found inAppendix B. F ⋆ and Implementing Endpoints F ⋆ [Swamy et al. 2016] is a verification-oriented programming language, with a rich set of features.Our method of API generation and example programs utilise the following F ⋆ features: • Refinement Types. A refinement type has the form x:t{E} , where t is the base type, x is avariable that stands for values of this type, and E is a pure boolean expression for refinement ,possibly containing x . In short, the values of this refinement type are the subset of values of t that make E evaluate to true , e.g. natural numbers are defined as x:int{x ≥ . We use this featureto express data and control flow constraints in protocols.In F ⋆ , type-checking refinement types are done with the assistance of the Z3 SMT solver [De Moura and Bjørner2008]. Refinements are encoded into SMT formulae and the solver decides the satisfiability ofSMT formulae during type-checking. This feature enables automation in reasoning and savesthe need for manual proofs in many scenarios. • Indexed Types.
Types can take pure expressions as arguments. For example, a declaration type t (i:t') = ... prescribes the family of types given by applying the type constructor t to values of type t' . We use this feature to generate type definitions for payload items in aninternal choice, where the refinements in payload types refer to a state type. • Dependent Functions with Effects.
A (dependent) function in F ⋆ has a type of the form (x:t ) → E t , where t is the argument type, E describes the effect of the function, and t is the result type, which may also refer to the argument x .The default effect is Tot , for pure total expressions (i.e. terminating and side-effect free). At theother end of the spectrum is the arbitrary effect ML (correspondent to all possible side effects inan ML language), which permits state mutation, non-terminating recursion, I/O, exceptions, etc. • The
Ghost
Effect and the erased
Type.
A type can be marked erased in F ⋆ , so that valuesof such types are not available for computation (after extracting into target language), but onlyfor proof purposes (during type-checking). The type constructor is accompanied with the Ghost effect to mark computationally irrelevant code, where the type system prevents the use of erasedvalues in computationally relevant code, so that the values can really be safely erased. In thefollowing snippet, we quickly demonstrate this feature:
GTot stands for
Ghost and total, andcannot be mixed with the default pure effect (the function not_allowed does not type-check).We use the erased type to mark variables known to the endpoint via the protocol specification,whose values are not known due to not being a party of the message interaction. For example,in Fig. 3, the endpoint C does not know the value of n0 , but knowns its type from the protocol. A comprehensive F ⋆ Pure in this context means pure terminating computation, i.e. no side-effects including global state modifcations, I/Oactions or infinite recursions, etc. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :8 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida type t = { x1: int; x2: erased int; } (* Definition in standard library *) val reveal: erased a → GTot a (* The following access is not allowed *) let not_allowed (o: t) = reveal o.x2 (* Accessing at type level is allowed *) val allowed: (o: t{reveal o.x2 ≥ → int Our generated code consists of multiple type definitions and an entry point function (as shownin Fig. 2, F ⋆ API), including:
State Types:
Allowing developers to access variables known at a given CFSM state.
Callbacks:
A record of functions corresponding to CFSM transitions, used to implement programlogic of the local endpoint.
Connections:
A record of functions for sending and receiving values to and from other roles inthe global protocol, used to handle the communication aspects of the local endpoint.
Entry Point:
A function taking callbacks and connections to run the local endpoint.To implement an endpoint, the developer needs to provide implementations for the generatedcallback and connection types, using appropriate functions to handle the program logic and com-munications. The F ⋆ compiler checks whether the implemented functions type-check against theprescribed types. If the endpoint implementation succeeds the type-checking, the developer maychoose to extract to a target language (e.g. OCaml, C) for execution. F ⋆ API Generation – Communicating Finite State Machine–basedCallbacks for Session I/O
As in the standard MPST workflow, the next step (Fig. 2) is to project our refined global protocolonto each role. This decomposes the global protocol into a set of local protocols, prescribing theview of the protocol from each role. Projection is the definitive mechanism in MPST: althoughall endpoints together must comply to global protocol, projection allows each endpoint to be sep-arately implemented and verified, a key requirement for practical distributed programming. Aswe shall see, the way projection treats refinements—we must consider the local knowledge of val-ues propagated through the multiparty protocol—is crucial to verifying refined implementations,including our simple running example.
Projection onto B . We first look at the projection onto B : although it is the largest of the threeprojections, it is unique among them because B is involved in every interaction of the protocol, and(consequently) B has explicit knowledge of the value of every refinement variable during execution.Formally, projection is defined as a syntactic function (explained in detail later in § 4.3); it is a par-tial function, designed conservatively to reject protocols that are not safely realisable in asynchron-ous distributed settings. However, we show in Fig. 4a the representation of projections employed inour toolchain based on communicating finite state machines (CFSMs) [Brand and Zafiropulo 1983],where the transitions are the localised I/O actions performed by B in this protocol. Projected CFSMactions preserve their refinements: as before, an action refinement serves as a precondition for anoutput transition to be fired, and a postcondition when an input transition is fired. For example, A ? start ( n ){ ≤ n < } is an input of a start message from A , with a refinement on the int payload value. Similarly, C ! higher { n > x ∧ t > } expresses a protocol flow refinement on anoutput of a higher message to C . For brevity, we omit the payload data types in the CFSM edges,as this example features only int s; we omit empty payloads “ () ” likewise.We show the local state refinements as annotations on the corresponding CFSM states (shadedin grey, with an arrow to the state). Refined API Generation for B . CFSMs offer an intuitive understanding of the semantics of end-point projections. Building on recent work [Castro et al. 2019; Hu and Yoshida 2016; Neykova et al.
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:9 n { ≤ n < } , t { < t }
56 4 78 A ? start ( n ){ ≤ n < } A ? limit ( t ){ ≤ t } C ? guess ( x ){ ≤ x < } C ! higher { n > x ∧ t > } A ! higher C ! lower { n < x ∧ t > } A ! lower C ! win { n = x } A ! lose C ! lose { n , x ∧ t = } A ! win (a) CFSM Representation of the Projection. ! stands for sending actions, and ? for receiving actions on edges. Generated F ⋆ API
State Edge Generated Callback Type A ? start s1 → (n:int{0 ≤ n < → ML unit A ? limit s2 → (t:int{0 < t}) → ML unit C ? guess s3 → (x:int{0 ≤ x}) → ML unit [multiple] (s:s4) → ML (s4Cases s) A ! higher s5 → ML unit A ! lower s6 → ML unit A ! lose s7 → ML unit A ! win s8 → ML unit (b) Generated I/O Callback Types type s4Cases (s:s4) = | s4_lower ofunit{s.n < s.x ∧ s.t > , s.x ∧ s.t = = s.x}| s4_higher ofunit{s.n > s.x ∧ s.t > (c) Generated Data Type for theOutput ChoiceFig. 4. Projection and F ⋆ API Generation for B in HigherLower generate protocol- and role-specific APIs for implementing each role in F ⋆ . We highlight a novel and crucial development:we exploit the approach of type generation to produce functional-style callback -based APIs that internalise all of the actual communication channels and I/O actions. In short, the transitions ofthe CFSM are rendered as a set of transition-specific function types to be implemented by the user— each of these functions take and return only the user-level data related to I/O actions and therunning of the protocol. The transition function of the CFSM itself is embedded into the API bythe generation, exporting a user interface to execute the protocol by calling back the appropriateuser-supplied functions according to the current CFSM state and I/O event occurrences.We continue with our example, Fig. 4b lists the function types for B , detailed as follows. Note, acharacteristic of MPST-based CFSMs is that each non-terminal state is either input- or output-only. • State Types.
For each state, we generate a separate type (named by enumerating the states, bydefault). Each is defined as a record containing previously known payload values and its localrecursion variables, or unit if none, for example: type s3 = (cid:8) n0: int{0 ≤ n0 < < t0}; n: int{0 ≤ n < < t} (cid:9) • Basic I/O Callbacks.
For each input transition we generate a function type s → σ → ML unit ,where s is the predecessor state type, and σ is the refined payload type received. The return typeis unit and the function can perform side effects, i.e. the callback is able to modify global state,interact with the console, etc, instead of merely pure computation. If an input transition is firedduring execution, the generated runtime will invoke a user-supplied function of this type withthe appropriately populated value of s , including any payload values received in the messagethat triggered this transition. Note, any data or protocol refinements are embedded into the typesof these fields.Similarly, for each transition of an output state with a single outgoing transition, we generate afunction type s → ML τ , where τ is the refined type for the output payload. • Internal Choices.
For each output state with more than 1 outgoing transition, we generate anadditional sum type ρ with the cases of the choice, e.g. Fig. 4c. This sum type (i.e. s4Cases ) is Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :10 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida indexed by the corresponding state type (i.e. s ) to make any required knowledge available forexpressing the protocol flow refinement of each case. Its constructors indicate the label of theinternal choice.We then generate a single function type for this state, s → ML ρ : the user implementation selectswhich choice case to follow by returning a corresponding ρ value, under the constraints ofany refinements. For example, a s4_win value can only be constructed, thus this choice caseonly be selected, when s.n = s.x for the given s . The state machine is advanced according to theconstructor of the returned value (corresponding to the label of the message), and the generatedruntime sends the payload value to the intended recipient.An asynchronous output event, i.e. the trigger for the API to call back an output function, re-quires the communication medium to be ready to accept the message (e.g. there is enough memoryin the local output buffer). For simplicity, in this work we consider the callbacks of an output stateto always be immediately fireable. Concretely, we delegate these concerns to the underlying lib-raries and runtime system. Projection and API Generation for C . The projection onto C raises an interesting questionrelated to the refinement of multiparty protocols: how should we treat refinements on variablesthat the target role does not itself know ? C does not know the value of the secret n (otherwise thisgame would be quite boring), but it does know that this information exists in the protocol and issubject to the specified refinement. In standard MPST, it is essentially the main point of projectionthat interactions not involving the target role can be simply (and safely) dropped outright; e.g. thecommunication of the start message would simply not appear in the projection of C . However,naively taking the same approach in RMPST would be inadequate: although the target role maynot know some exact value, the role may still need the associated “latent information” to fulfil thedesired application behaviour.Our framework introduces a notion of erased variables for RMPST — in short, our projectiondoes drop third-party interactions , but retains the latent information as refinement-typed erased variables, as illustrated by the annotation on state in Fig. 5a. Thanks to the SMT-based refinementtype system of F ⋆ , the type-checker can still take advatange of the refined types of erased vari-ables to prove properties of the endpoint implementation; however, these variables cannot actuallybe used computationally in the implementation (since their values are not known). Conveniently, F ⋆ supports erased types (described briefly in § 3.1), and provides ways (i.e. Ghost effects) to en-sure that such variables are not used in the computation. We demonstrate this for our examplein the next subsection. Our approach can be considered a version of irrelevant variables from[Abel and Scherer 2012; Pfenning 2001] for the setting of typed, distributed interactions. F ⋆ Implementation – Protocol Validation and Verification by Refinement Types
Finally, the generated APIs—embodying the refined projections—are used to implement the end-point processes. As mentioned, the user implements the program logic as callback functions ofthe generated (refinement) types, supplied to the entry point along with code for establishing thecommunication channels between the session peers. Assuming a record callbacks containing therequired functions (static typing ensures all are covered), Fig. 6a bootstraps a C endpoint.The API takes care of endpoint execution by monitoring the channels, and calling the appropri-ate callback based on the current protocol state and I/O event occurrences. For example, a minimal,well-typed implementation of B could comprise the internal choice callback above (Fig. 6b) (im-plementing the type in Fig. 4c), cf. state , and an empty function for all others (i.e. fun _ → () ).We can highlight how protocol violations are ruled out by static refinement typing, which is ulti-mately the practical purpose of RMPST. In the above callback code, changing, say, the condition Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:11 n : erased int { ≤ n < } , t : erased int { < t } B ! guess ( x ){ ≤ x < } B ? lower { n < x ∧ t > } B ? higher { n > x ∧ t > } B ? win { n = x } B ? lose { n , x ∧ t = } (a) CFSM Representation of the Projection User implementation (* Allocate a refined int reference *)
State Edge Generated type let next: ref (x:int{0 ≤ x < = alloc 50 B ! guess s1 → ML (x:int{0 ≤ x < → !next (*Deref next*) B ? higher s2 → unit{n > x ∧ t > → ML unit fun s → next ≔ s.x + 1 B ? lower s2 → unit{n < x ∧ t > → ML unit fun s → next ≔ s.x - 1 B ? win s2 → unit{n = x} → ML unit fun _ → () B ? lose s2 → unit{n , x ∧ t = → ML unit fun _ → () (b) Generated I/O Callback TypesFig. 5. Projection and F ⋆ API Generation for C in HigherLowerlet main () = (* connect to B via TCP *)let server_B = connect ip_B port_B in(* Setup connection from TCP *)let conn = mk_conn server_B in(* Invoke the Entry Point `run` *)let () = run callbacks conn in(* Close TCP connection *)close server_B (a) Running the Endpoint C (* Signature (s:s4) → ML (s4Cases s) *)fun (s:s4) → (* Win if guessed number is correct *)if s.x = s.n then s4_win ()(* Lose if running out of attempts *)else if s.t = > s.x then s4_higher ()else s4_lower () (b) Implementing the Internal Choice for B Fig. 6. Selected Snippets of Endpoint Implementation for the lose case to s.t = would directly violate the refinement on the s4_lose constructor, cf.Fig. 4c. Omitting the lose case altogether would break both the lower and higher cases, as the typechecker would not be able to prove s.t > as required by the subsequent constructors.Lastly, Fig. 5b implements C to guess the secret by a simple search, given we know its value isbounded within the specified interval. We draw attention to the input callback for higher , wherewe adjust the next value. Given that the value being assigned is one more than the existing value,it might have been the case that the new value falls out of the range (in the case where next is99), hence violating the prescribed type. However, despite that the value of n is unknown, we haveknown from the refinement attached to the edge that n > x holds, hence it must have been the casethat our last guess x is strictly less than the secret n , which rules out the possibility that x can be99 (the maximal value of n ). Had the refinement and the erased variable not been present, the type-checker would not be able to accept this implementation, and it demonstrates that our encodingallows such reasoning with latent information from the protocol.Moreover, the type and effect system of F ⋆ prevents the erased variables from being used inthe callbacks. On one hand, int and erased int types are not compatible, because they are not thesame type. This prevents an irrelevant variable from being used in place of a concrete variable. Onthe other hand, the function reveal converts a value of erased 'a to a value of 'a with Ghost effect.A function with
Ghost effect cannot be mixed with a function with ML effect (as in the case of ourcallbacks), so irrelevant variables cannot be used in the implementation via the reveal function. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :12 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida
Interested readers are invited to try the running example out with our accompanying artifact.We propose a few modifications on the implementation code and the protocol, and invite the read-ers to observe errors when implementations no longer correctly conforms to the prescribed pro-tocol.
As mentioned earlier, our API design sepearates the concern of program logic (with callbacks) andcommunication (with connections). A crucial piece of the generated code involves threading thetwo parts together — the execution function performs the communications actions and invokes theappropriate callbacks for handling. In this way, we do not expose explicit communication channels,so linearity can be achieved with ease by construction in our generated code.The entry point function, named run , takes callbacks and connections as arguments, and ex-ecutes the CFSM for the specified endpoint. The signature uses the permissive ML effect, sincecommunicating with the external world performs side effects. We traverse the states (the set ofstates is denoted Q ) in the CFSM and generate appropriate code depending on the nature of thestate and its outgoing transitions.Internally, we define mutually recursive functions for each state q ∈ Q , named run q , taking thestate record n q o as argument ( n q o stands for the state record for a given state q ), which performsthe required actions at state q . The run state function for a state q either (1) invokes callbacksand communication primitives, then calls the run state function for the successor state q ′ , or (2)returns directly for termination if q is a terminal state (without outgoing transitions). The mainentry point invokes the run function for the initial state q , starting the finite state machine.The internal run state functions are not exposed to the developer, hence it is not possible totamper with the internal state with usual means of programming. This allows us to guaranteelinearity of communication channels by construction. In the following text, we outline how to runeach state, depending on whether the state is a sending state or a receiving state. Note that CFSMsconstructed from local types do not have mixed states [Deniélou and Yoshida 2013, Prop. 3.1] let rec run_ q (st: state q ) = let choice = callbacks.state q _send stin match choice with| Choice ql i payload → comm.send_string q " l i ";comm.send_ S q payload;let st = { · · · ; x i = payload } inrun_ q ′ st Repeatfor i ∈ I (a) Template for Sending State q let rec run_ q (st: state q ) = let label = comm.recv_string p () inmatch label with| " l i " → let payload = comm.recv_ S p () incallbacks.state q _receive_ l i st payload;let st = { · · · ; x i = payload } inrun_ q ′ st (b) Template for Receiving State q Fig. 7. Template for run q Running the CFSM at a Sending State . For a sending state q ∈ Q , the developer makes aninternal choice on how the protocol proceeds, among the possible outgoing transitions. This isdone by invoking the sending callback state q _send with the current state record, to obtain achoice with the associated payload. We pattern match on the constructor of the label l i of themessage, and find the corresponding successor state q ′ .The label l i is encoded as a string and sent via the sending primitive to q . It is followed by thepayload specified in the return value of the callback, via corresponding sending primitive accordingto the base type with refinement erased. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:13
We construct a state record of n q ′ o from the existing record n q o , adding the new field x i inthe action using the callback return value. In the case of recursive protocols, we also update therecursion variable according to the definition in the protocol when constructing n q ′ o . Finally, wecall the run state function run q ′ to continue the CFSM, effectively making the transition to state q ′ .Following the procedure, run q is generated as shown in Fig. 7a. Running the CFSM at a Receiving State . For a receiving state q ∈ Q , how the protocol pro-ceeds is determined by an external choice, among the possible outgoint actions. To know whatchoice is made by the other party, we first receive a string and decode it into a label l , via thereceiving primitive for string.Subsequently, according to the label l , we can look up the label in the possible transitions, andfind the state successor q ′ . By invoking the appropriate receiving primitive, we obtain the payloadvalue. We note that the receiving primitive has a return type without refinements. In order to re-attach the refinements, we use the F ⋆ builtin assume to reinstate the refinements according to theprotocol before using the value.According the label l received, we can call the corresponding receiving callback with the re-ceived value. This allows the developer to process the received value and perform any relevantprogram logic. This is followed by the same procedure for constructing the state record for thenext state q ′ and invoking the run function for q ′ .Following the procedure, run q is generated as shown in Fig. 7b. We demonstrated with our running example,
HigherLower , how to implement a refined multipartyprotocol with our toolchain
Session ⋆ .Exploiting the powerful type system of F ⋆ , our approach has several key benefits: First, it guar-antees fully static session type safety in a lightweight, practical manner — the callback-style API isportable to any statically typed language. Existing work based on code generation has consideredonly hybrid approaches that supplement static typing with dynamically checked linearity of expli-cit communication channel usages. Moreover, the separation of program logic and communicationleads to a modular implementation of protocols.Second, it is well suited to functional languages like F ⋆ ; in particular, the data -oriented natureof the user interface allows the refinements in RMPST to be directly mapped to data refinementsin F ⋆ , allowing the refinements constraints to be discharged at the user implementation level bythe F ⋆ compiler — again, fully statically.Furthermore, our endpoint implementation inherits core communication safety properties suchas freedom from deadlock or communication mismatches, based on the original MPST theory. Weuse the F ⋆ type-checker to validate statically that an endpoint implementation is correctly typedwith respect to the prescribed type obtained via projection of the global protocol. Therefore, theimplementation benefits from additional guarantees from the refinement types. In this section, we introduce refined multiparty session types ( RMPST for short). We give the syntaxof types in § 4.1, extending original multiparty session types (MPST) with refinement types . Wedescribe the refinement typing system that we use to type expressions in RMPST in § 4.2.We follow the standard MPST methodology.
Global session types describe communication struc-tures of many participants (also known as roles ). Local session types , describing communication
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :14 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida structures of a single participant, can be obtained via projection (explain in § 4.3). Endpoint pro-cesses implement local types obtained from projection. We give semantics of global types andlocal types in § 4.4, and show the equivalence of semantics with respect to projection. As a con-sequence, we can compose all endpoint processes implementing local types for roles in a globaltype, obtained via projection, to implement the global type correctly.
We define the syntax of refined multiparty session types (refined MPST) in Fig. 8. We use differentcolours for different syntactical categories to help disambiguation, but the syntax can be under-stood without colours. We use pink for global types, dark blue for local types, blue for expressions,purple for base types, indigo for labels, and
Teal with bold fonts for participants. S :: = int | bool | . . . Base Types T :: = x : S { E } Refinement Types E :: = x | n | op E | E op E . . . Expressions G :: = Global Types | p → q { l i ( x i : T i ) . G i } i ∈ I Message | µ t ( x : T )h x : = E i . G Recursion | t h x : = E i | end Type Var., End L :: = Local Types | p & { l i ( x i : T i ) . L i } i ∈ I Receiving | p ⊕{ l i ( x i : T i ) . L i } i ∈ I Sending | l ( x : T ) . L Silent Prefix | µ t ( x : T )h x : = E i . L Recursion | t h x : = E i | end Type Var., End
Fig. 8. Syntax of Refined Multiparty Session Types
Value Types and Expressions . We use S for base types of values, ranging over integers, booleans,etc. Values of the base types must be able to be communicated.The base type S can be refined by a boolean expression, acting as a predicate on the membersof the base type. A refinement type is of the form ( x : S { E }) . A value x of the type has base type S , and is refined by a boolean expression E . The boolean expression E acts as a predicate on themembers x (possibly involving the variable x ). For example, we can express natural numbers as ( x : int { x ≥ } ). We use fv (·) to denote the free variables in refinement types, expressions, etc. Weconsider variable x be bound in the refinement expression E , i.e. fv ( x : S { E }) = fv ( E ) \ { x } .Where there is no ambiguity, we use the base type S directly as an abbreviation of a refinementtype ( x : S { true }) , where x is a fresh variable, and true acts as a predicate that accepts all values. Global Session Types . Global session types ( global types or protocols for short) range over G , G ′ , G i , . . . Global types give an overview of the overall communication structure. We extend the standardglobal types [Deniélou and Yoshida 2013] with refinement types and variable bindings in messageprefixes. Extensions to the syntax are shaded in the following explanations. p → q n l i ( x i : T i ) . G i o i ∈ I is a message from p to q , which branches into one or more continu-ations with label l i , carrying a payload variable x i with type T i . We omit the curly braces whenthere is only one branch, like p → q : l ( x : T ) . We highlight the difference from the standard syn-tax, i.e. the variable binding. The payload variable x i occurs bound in the continuation global type G i , for all i ∈ I . We sometimes omit the variable if it is not used in the continuations. The freevariables are defined as: fv ( p → q { l i ( x i : T i ) . G i } i ∈ I ) = Ø i ∈ I fv ( T i ) ∪ Ø i ∈ I ( fv ( G i ) \ { x i }) We require that the index set I is not empty, and all labels l i are distinct. To prevent duplication, wewrite l ( x : S { E }) instead of l ( x : ( x : S { E })) (the first x occurs as a variable binding in the message,the second x occurs as a variable representing member values in the refinement types). Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:15
We extend the construct of recursive protocols to include a variable carrying a value in the innerprotocol. In this way, we enhance the expressiveness of the global types by allowing a recursionvariable to be maintained across iterations of global protocols.The recursive global type µ t ( x : T )h x : = E i . G specifies a variable x carrying type T in therecursive type, initialised with expression E . The type variable t h x : = E i is annotated with anassignment of expression E to variable x . The assignment updates the variable x in the currentrecursive protocol to expression E . The free variables in recursive type is defined as fv ( µ t ( x : T )h x : = E i . G ) = fv ( T ) ∪ fv ( E ) ∪ ( fv ( G ) \ { x }) We require that recursive types are contractive [Pierce 2002, §21], so that recursive protocolshave at least a message prefix, and protocols such as µ t ( x : T )h x : = E i . t h x : = E i are not allowed.We also require recursive types to be closed with respect to type variables, e.g. protocols such as t h x : = E i alone are not allowed.We write G [ µ t ( x : T ) . G / t ] to substitute all occurrences of type variables with expressions t h x : = E i into µ t ( x : T )h x : = E i . G . We write r ∈ G to say r is a participating role in the global type G . Example 4.1 (Global Types).
We give the following examples of global types.(1) G = A → B : Fst ( x : int ) . B → C : Snd ( y : int { x = y }) . C → D : Trd ( z : int { x = z }) . end . G describes a protocol where A sends an int to B , and B relays the same int to C , similarfor C to D . Note that we can write x = z in the refinement of z , whilst x is not known to C .(2) G = A → B : Number ( x : int ) . B → C Positive ( unit { x > }) . end Zero ( unit { x = }) . end N eдative ( unit { x < }) . end G describes a protocol where A sends an int to B , and B tells C whether the int is positive,zero, or negative. We omit the variable here since it is not used later in the continuation.(3) G = µ t ( try : int { try ≥ ∧ try ≤ })h try : = i . A → B : Password ( pwd : string ) . B → A Correct ( unit ) . end Retry ( unit { try < }) . t h try : = try + i Denied ( unit { try = }) . end G describes a protocol where A authenticates with B with maximum 3 tries. Local Session Types . Local session types ( local types for short) range over L , L ′ , L i , . . . Localtypes give a view of the communication structure of an endpoint, usually obtained from a globaltype. In addition to standard syntax, the recursive types are similarly extended as those of globaltypes.Suppose the current role is q , the local type p ⊕{ l i ( x i : T i ) . L i } i ∈ I describes that the role q sendsa message to the partner role p with label l i (where i is selected from an index set I ), carryingpayload variable x i with type T i , and continues with L i . It is also said that the role q takes an internal choice . Similarly, the local type p & { l i ( x i : T i ) . L i } i ∈ I describes that the role q receives amessage from the partner role p . In this case, it is also said that the role q offers an external choice .We omit curly braces when there is only a single branch (as is done for global messages).We add a new syntax construct of l ( x : T ) . L for silent local types . We motivate this introductionof the new prefix to represent knowledge obtained from the global protocol, but not in the form ofa message. Silent local types are useful to model variables obtained with irrelevant quantification[Abel and Scherer 2012; Pfenning 2001]. These variables can be used in the construction of a type,but cannot be used in that of an expression, as we explain later in § 4.2. We show an example of a Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :16 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida [WF-Rty] Σ + , x : S ⊢ E : bool Σ ⊢ ( x : S { E }) ty [TE-Var] Σ , x ω : T , Σ ⊢ x : T [TE-Plus] Σ ⊢ E : int Σ ⊢ E : int Σ ⊢ E + E : ( v : int { v = E + E }) [TE-Sub] Σ ⊢ E : ( v : S { E }) Valid ( n Σ o ∧ n E o = ⇒ n E o ) Σ ⊢ E : ( v : S { E }) [TE-Const] Σ ⊢ n : ( v : int { v = n }) Fig. 9. Selected Typing Rules for Expressions in a Local Typing Context silent local type later in Example 4.3, after we define endpoint projection , the process of obtaininglocal types from a global type.
We use E , E ′ , E i to range over expressions. Expressions consist of variables x , constants (e.g. integerliterals n ), and unary and binary operations. We use an SMT assisted refinement type system fortyping expressions, in the style of [Rondon et al. 2008]. The simple syntax of expressions allows allexpressions to be encoded into SMT logic, for deciding a semantic subtyping relation of refinementtypes [Bierman et al. 2012]. Typing Contexts . We define two categories of typing contexts, for use in handling global typesand local types respectively. Γ :: = œ | Γ , x P : T Σ :: = œ | Σ , x θ : T θ :: = | ω We annotate global and local typing contexts differently. For global contexts Γ , variables carry theannotation of a set of roles P , to denote the set of roles that have the knowledge of its value.For local contexts Σ , variables carry the annotation of their multiplicity θ . A variable with mul-tiplicity is an irrelevantly quantified variable (irrelevant variable for short), which cannot appearin the expression when typing (also denoted as x ÷ T in the literature [Abel and Scherer 2012;Pfenning 2001]). Such a variable can only appear in an expression used as a predicate, when de-fining a refinement type. A variable with multiplicity ω is a variable without restriction. We oftenomit the multiplicity ω . Well-formedness . Since a refinement type can contain free variables, it is necessary to definewell-formedness judgements on refinement types, and henceforth on typing contexts.We define Σ + to be the local typing context where all irrelevant variables x become unrestricted x ω , i.e. (œ) + = œ ; ( Σ , x θ : T ) + = Σ + , x ω : T .We show the well-formedness judgement of a refinement type [ WF-Rty ] in Fig. 9. For a refine-ment type ( x : S { E }) to be a well-formed type, the expression E must have a boolean type underthe context Σ + , extended with variable x (representing the members of the type) with type S . Thetyping context Σ + promotes the irrelevant quantified variables into unrestricted variables, so theycan be used in the expression E inside the refinement type.The well-formedness of a typing context is defined inductively, requiring all refinement typesin the context to be well-formed. We omit the judgements for brevity. Typing Expressions . We type expressions in local contexts, forming judgements of form Σ ⊢ E : T , and show key typing rules in Fig. 9. We modify the typing rules in a standard refinementtype system [Rondon et al. 2008; Vazou et al. 2014, 2017], adding distinction between irrelevantand unrestricted variables. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:17 Γ ∪ { x P : T } = Γ , x P : T if x < ΓΓ , x P : T , Γ if Γ = Γ , x œ : T , Γ Γ , x P : T , Γ if Γ = Γ , x P : T , Γ undefined otherwise Σ ∪ { x θ : T } = Σ , x θ : T if x < ΣΣ , x θ : T , Σ if Σ = Σ , x : T , Σ Σ , x ω : T , Σ if Σ = Σ , x ω : T , Σ undefined otherwise Fig. 10. Typing Context Extension [ TE-Const ] gives constant values in the expression a refinement type that only contains theconstant value. Similarly, [
TE-Plus ] gives typing derivations for the plus operator, with a corres-ponding refinement type encoding the addition.We draw attention to the handling of variables ([
TE-Var ]). An irrelevant variable in the typingcontext cannot appear in an expression, i.e. there is no derivation for Σ , x : T , Σ ⊢ x : T . Thesevariables can only be used in an refinement type (see [ WF-Rty ]).The key feature of the refinement type system is the semantic subtyping relation decided by SMT[Bierman et al. 2012], we describe the feature in [
TE-Sub ]. We use n E o to denote the encoding ofexpresion E into the SMT logic. We encode a type binding x θ : ( v : S { E }) in a typing context byencoding the term E [ x / v ] , and define the encoding of a typing context n Σ o inductively.We define the extension of typing contexts ( Γ ∪ { x P : T } ; Σ ∪ { x θ : T } ) in Fig. 10, used indefinitions of semantics. We say a global type G (resp. a local type L ) is closed under a globalcontext Γ (resp. a local context Σ ), if all free variables in the type are in the domain of the context. Remark 4.2 (Empty Type).
A refinement type may be empty , with no inhabited member.We can construct such a type under the empty context œ as ( x : S { false }) with any base types S . A more specific example is a refinement type for an integer that is both negative and pos-itive ( x : int { x > ∧ x < }) . Similarly, under the context x ω : int { x > } , the refinement type y : int { y < ∧ y > x } is empty. In these cases, the typing context with the specified type becomesinconsistent, i.e. the encoded context gives a proof of falsity.Moreover, an empty type can also occur without inconsistency. For instance, in a typing contextof x : int , the type y : int { y > x } is empty — it is not possible to produce such a value withoutreferring to x (cf. [ TE-Var ]).
In the methodology of multiparty session types, developers specify a global type, and obtain localtypes for the participants via endpoint projection ( projection for short). In the original theory, pro-jection is a partial function that takes a global type G and a participant p , and returns a local type L . The resulting local type L describes a the local communication behaviour for participant p inthe global scenario. Such workflow has the advantage that each endpoint can obtain a local typeseparately, and implement a process of the given type, hence providing modularity and scalability.Projection is defined as a partial function, since only well-formed global types can be projected toall participants. In particular, a partial merge operator ⊔ is used during the projection, for creatinga local type Σ ⊢ L ⊔ L = L merged that captures the behaviour of two local types, under context Σ .In RMPST, we first define the projection of global typing contexts (Fig. 11), and then define theprojection of global types under a global typing context (Fig. 12). We use expression typing judge-ments in the definition of projection, to type-check expressions against their prescribed types. Projection of Global Contexts . We define the judgement Γ ↾ p = Σ for the projection of globaltyping context Γ to participant p in Fig. 11. In the global context Γ , a variable x is annotated withthe set of participants P who know the value. If the projected participant p is in the set P , [ P-Var- ω ] is applied to obtain an unrestricted variable in the resulting local context; Otherwise, [ P-Var-0 ]is applied to obtain an irrelevant variable.
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :18 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida Γ ↾ p = Σ [P-Empty] œ ↾ p = œ [P-Var- ω ] p ∈ P Γ ↾ p = ΣΓ , x P : T ↾ p = Σ , x ω : T [P-Var-0] p < P Γ ↾ p = ΣΓ , x P : T ↾ p = Σ , x : T Fig. 11. Projection Rules for Global Contexts [P-Send] Γ ↾ p = Σ ∀ i ∈ I . Σ ⊢ T i ty h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ p = h Σ i ≺ L i ih Γ ≺ ( p → q { l i ( x i : T i ) . G i } i ∈ I )i ↾ p = h Σ ≺ q ⊕{ l i ( x i : T i ) . L i } i ∈ I i [P -Recv] Γ ↾ q = Σ ∀ i ∈ I . Σ ⊢ T i ty h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ q = h Σ i ≺ L i ih Γ ≺ ( p → q { l i ( x i : T i ) . G i } i ∈ I )i ↾ q = h Σ ≺ p & { l i ( x i : T i ) . L i } i ∈ I i [P-Phi] Γ ↾ r = Σ r < { p, q } ∀ i ∈ I . Σ ⊢ T i ty h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ r = h Σ i ≺ L i ih Γ ≺ ( p → q { l i ( x i : T i ) . G i } i ∈ I )i ↾ r = h Σ ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i [P-Rec-In] Γ ↾ r = Σ r ∈ G h Γ ∪ { x { r | r ∈ G } : T } ≺ G i ↾ r = h Σ ′ ≺ L i Σ ⊢ T ty Σ ⊢ E : T h Γ ≺ µ t ( x : T )h x : = E i . G )i ↾ r = h Σ ≺ µ t ( x : T )h x : = E i . L i [P-Rec-Out] Γ ↾ r = Σ r < G h Γ ≺ µ t ( x : T )h x : = E i . G )i ↾ r = h Σ ≺ end i [P-End] Γ ↾ r = Σ h Γ ≺ end i ↾ r = h Σ ≺ end ih Γ ≺ G i ↾ p = h Σ ≺ L i [P-Var] Γ ↾ r = Σ = Σ , x : T , Σ Σ , x : T , Σ ⊢ E : T h Γ ≺ t h x : = E ii ↾ r = h Σ ≺ t h x : = E ii Fig. 12. Projection Rules for Global Types
Projection of Global Types with a Global Context . When projecting a global type G , weinclude a global context Γ , forming a judgement of form h Γ ≺ G i ↾ p = h Σ ≺ L i . Projectionrules are shown in Fig. 12. Including a typing context allows us to type-check expressions duringprojection, hence ensuring that variables attached to recursive protocols are well-typed.If the prefix of G is a message from role p to role q , the projection results a local type witha send (resp. receive) prefix into role p (resp. q ) via [ P-Send ] (resp. [ P -Recv ]). For other roles r , the projection results in a local type with a silent label via [ P-Phi ], with prefix l ( x : T ) . Thisfollows the concept of a coordinated distributed system, where all the processes follow a globalprotocol, and base assumptions of their local actions on actions of other roles not involving them.The projection defined in the original MPST theory does not contain information for role r abouta message between p and q . We use the silent prefix to retain such information, especially therefinement type T of the payload. For merging two local types (as used in [ P-Phi ]), we use asimple plain merge operator defined as Σ ⊢ L ⊔ L = L , requiring two local types to be identical inorder to be merged. If the prefix of G is a recursive protocol µ t ( x : T )h x : = E i . G , the projection preserves the recur-sion construct if the projected role is in the inner protocol via [ P-Rec-In ] and that the expression E can be typed with type T under the projected local context. Typing expressions under localcontexts ensures that no irrelevant variables x are used in the expression E , as no typing deriva-tion exists for irrelevant variables. Otherwise projection results in end via [ P-Rec-Out ]. If G is atype variable t h x : = E i , we similarly validate that the expression E carries the specified type in thecorrespondent recursion definition, and its projection also preserves the type variable construct. We build upon the standard MPST theory with plain merging. Full merge [Denielou et al. 2012], allowing certain differentindex sets to be merged, is an alternative, more permissive merge operator. Our implementation
Session ⋆ uses the morepermissive merge operator for better expressiveness.Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:19 Example 4.3 (Projection of Global Types of Example 4.1 (1)).
We draw attention to the projectionof G to C , under the empty context œ . hœ ≺ G i ↾ C = hœ ≺ Fst ( x : int ) . B & Snd ( y : int { x = y }) . D ⊕ Trd ( z : int { x = z }) . end i We note that the local type for C has a silent prefix Fst ( x : int ) , which binds the variable x in thecontinuation. The silent prefix adds the variable x and its type to the “local knowledge” of theendpoint C , yet the actual value of x is unknown. Remark 4.4 (Empty Session Type).
Global types G and local types L can be empty because oneof the value types in the protocol in an empty type (cf. Remark 4.2).For example, the local type A ⊕ Impossible ( x : int { x > ∧ x < }) . end cannot be implemented,since such an x cannot be provided.For the same reason, the local type Pos ( x : int { x > }) . A ⊕ Impossible ( y : int { y > x }) . end can-not be implemented. Remark 4.5 (Implementable Session Types).
Consider the following session type: L = B & Num ( x : int ) . B ⊕ (cid:26) Pos ( unit { x > }) . end N eд ( unit { x < }) . end (cid:27) . When the variable x has the value , neither of the choices Pos or N eд could be selected, as therefinements are not satisfied. In this case, the local type L cannot be implemented, as the internalchoice callback may not be implemented in a total way, i.e. the callback returns a choice label forall possible inputs of integer x . We define the labelled transition system (LTS) semantics for global types and local types. We showthe trace equivalence of a global type and the collection of local types projected from the globaltype, to demonstrate that projection preserves LTS semantics. The equivalence result allows us touse the projected local types for the implementation of local roles separately. Therefore, we canimplement the endpoints in F ⋆ separately, and they compose to the specified protocol.We also prove a type safety result that well-formed global types cannot be stuck. This, combinedwith the trace equivalence result, guarantees that endpoints are free from deadlocks. Actions . We begin with defining actions in the LTS system. We define the label in the LTS as α :: = p → q : l ( x : T ) , a message from role p to q with label l carrying a value named x withtype T . We define subj ( α ) = { p, q } to be the subjects of the action α , namely the two roles in theaction. Semantics of Global Types . We define the LTS semantics of global types in Fig. 13. Differentfrom the original LTS semantics in [Deniélou and Yoshida 2013], we include the context Γ in thesemantics along with the global type G . Therefore, the judgements of global LTS reduction haveform h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i .[ G-Pfx ] allows the reduction of the prefix action in a global type. An action, matching thedefinition in set defined in the prefix, allows the correspondent continuation to be selected. Theresulting global type is the matching continuation and the resulting context contains the variablebinding in the action.[
G-Cnt ] allows the reduction of an action that is causally independent of the prefix action ina global type, here, the subjects of the action are disjoint from the prefix of the global type. If Since we use a permissive ML effect in the callback type, allowing all side effects to be performed in the callback, thecallback may throw exceptions or diverge in case of unable to return a value.Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :20 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida [G-Pfx] j ∈ I h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i p → q : l j ( x j : T j ) −−−−−−−−−−→ h Γ ∪ { x { p, q } j : T j } ≺ G j i [G-Cnt] { p, q } ∩ subj ( α ) = œ ∀ j ∈ I . h Γ ∪ { x œ j : T j } ≺ G j i α −→ h Γ ′ ≺ G ′ j ih Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i α −→ h Γ ′ ≺ p → q (cid:8) l i ( x i : T i ) . G ′ i (cid:9) i ∈ I ih Γ ≺ G i α −→ h Γ ′ ≺ G ′ i [G-Rec] h Γ ∪ { x { r | r ∈ G } : T } ≺ G [ µ t ( x : T ) . G / t ]i α −→ h Γ ′ ≺ G ′ ih Γ ≺ µ t ( x : T )h x : = E i . G i α −→ h Γ ′ ≺ G ′ i Fig. 13. LTS Semantics for Global Types all continuations in the global types can make the reduction of that action to the same context,then the result context is that context and the result global type is one with continuations afterreduction. When reducing the continuations, we add the variable of the prefix action into the con-text, but tagged with an empty set of known roles. This addition ensures that relevant informationobtainable from the prefix message is not lost when performing reduction.[
G-Rec ] allows the reduction of a recursive type by unfolding the type once.
Example 4.6 (Global Type Reductions).
We demonstrate two reduction paths for a global type G = p → q : Hello ( x : int { x < }) . r → s : Hola ( y : int { y > x }) . end . Note that the two messages are not causally related (they have disjoint subjects). We have thefollowing two reduction paths of hœ ≺ G i (omitting payload in LTS actions): hœ ≺ G i [ G-Pfx ] p → q : Hello −−−−−−−−−→ h x { p, q } : int { x < } ≺ r → s : Hola ( y : int { y > x }) . end i [ G-Pfx ] r → s : Hola −−−−−−−−→ h x { p, q } : int { x < } , y { r, s } : int { y > x } ≺ end ihœ ≺ G i [ G-Cnt ] r → s : Hola −−−−−−−−→ h x œ : int { x < } , y { r, s } : int { y > x } ≺ p → q : Hello ( x : int { x < }) . end i [ G-Pfx ] p → q : Hello −−−−−−−−−→ h x { p, q } : int { x < } , y { r, s } : int { y > x } ≺ end i Semantics of Local Types . We define the LTS semantics of local types in Fig. 14. Similar toglobal type LTS semantics, we include the local context Σ in the semantics. Therefore, the judge-ments of local LTS reductions have form h Σ ≺ L i α −→ h Σ ′ ≺ L ′ i . When defining the LTS semantics,we also use judgements of form h Σ ≺ L i ϵ −→ h Σ ′ ≺ L ′ i . It represents a silent action that can occurwithout an observed action. We write ϵ −→ ∗ to denote the reflexive transition closure of silent actions ϵ −→ .We first have a look at silent transitions. [ E-Phi ] allows the variable in a silent type to be addedinto the local context in the irrelevant form. This rule allows local roles to obtain knowledge fromthe messages in the global protocol without their participation.[
E-Cnt ] allows prefixed local type to make a silent transition, if all of its continuations areallowed to make a silent transition to reach the same context. The rule allows a prefixed localtype to obtain new knowledge about irrelevant variables, if such can be obtained in all possiblecontinuations.[
E-Rec ] unfolds recursive local types, analogous to the unfolding of global types.
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:21 [E-Cnt] † ∈ { & , ⊕} ∀ j ∈ I . h Σ ∪ { x j : T j } ≺ L j i ϵ −→ h Σ ′ ≺ L ′ j ih Σ ≺ q †{ l i ( x i : T i ) . L i } i ∈ I i ϵ −→ h Σ ′ ≺ q † (cid:8) l i ( x i : T i ) . L ′ i (cid:9) i ∈ I i [E-Rec] h Σ ≺ µ t ( x : T )h x : = E i . L i ϵ −→ h Σ ∪ { x ω : T } ≺ L [ µ t ( x : T ) . L / t ]ih Σ ≺ L i ϵ −→ h Σ ′ ≺ L ′ i [E-Phi] h Σ ≺ l ( x : T ) . L i ϵ −→ h Σ ∪ { x : T } ≺ L i [L-Send] j ∈ I h Σ ≺ q ⊕{ l i ( x i : T i ) . L i } i ∈ I i p → q : l j ( x j : T j ) −−−−−−−−−−→ h Σ ∪ { x ωj : T j } ≺ L j i [L-Recv] j ∈ I h Σ ≺ p & { l i ( x i : T i ) . L i } i ∈ I i p → q : l j ( x j : T j ) −−−−−−−−−−→ h Σ ∪ { x ωj : T j } ≺ L j ih Σ ≺ L i α −→ h Σ ′ ≺ L ′ i [L-Eps] h Σ ≺ L i ϵ −→ h Σ ′′ ≺ L ′′ i h Σ ′′ ≺ L ′′ i α −→ h Σ ′ ≺ L ′ ih Σ ≺ L i α −→ h Σ ′ ≺ L ′ i Fig. 14. LTS Semantics for Local Types
For concrete transitions, we have [
L-Send ] (resp. [
L-Recv ]) to reduce a local type with a sending(resp. receiving) prefix, if the action label is in the set of labels in the local type. The resultingcontext contains the variable in the message as a concrete variable, since the role knows the valuevia communication. The resulting local type is the continuation corresponding to the action label.In addition, [
L-Eps ] permits any number of silent actions to be taken before a concrete action.
Remark 4.7 (Reductions for Empty Session Types).
We consider empty session types to bereducible, since it is not possible to distinguish which types are inhabited. However, it does notinvalidate the safety properties of endpoints, since no such endpoints can be implemented for anempty session type.
Relating Semantics of Global and Local Types . We extend the LTS semantics to a collectionof local types in Definition 4.8, in order to prove that projection preserves semantics. We definethe semantics in a synchronous fashion.The set of local types reduces with an action α = p → q : l ( x : T ) , if the local type for role p and q both reduce with that action α . All other roles in the set of the local types are permitted tomake silent actions ( ϵ actions).Our definition deviates from the standard definition [Deniélou and Yoshida 2013, Def. 3.3] intwo ways: One is that we use a synchronous semantics, so that one action involves two reductions,namely at the sending and receiving sides. Second is that we use contexts and silent transitionsin the LTS semantics. The original definition requires all non-action roles to be identical, whereaswe relax the requirement to allow silent transitions. Definition 4.8 (LTS over a collection of local types).
A configuration s = {h Σ r ≺ L r i} r ∈ P is acollection of local types and contexts, indexable via participants.Let p ∈ P and q ∈ P . We say s = {h Σ r ≺ L r i} r ∈ P α = p → q : l ( x : T ) −−−−−−−−−−−→ s ′ = {h Σ ′ r ≺ L ′ r i} r ∈ P if(1) h Σ p ≺ L p i α −→ h Σ ′ p ≺ L ′ p i and, h Σ q ≺ L q i α −→ h Σ ′ q ≺ L ′ q i and, Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :22 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida (2) for all s ∈ P , s , p , s , q . h Σ s ≺ L s i ϵ −→ ∗ h Σ ′ s ≺ L ′ s i For a closed global type G under context Γ , we show that the global type makes the same trace ofreductions as the collection of local types obtained from projection. We prove it in Theorem 4.10. Definition 4.9 (Association of Global Types and Configurations).
Let h Γ ≺ G i be a global context.The collection of local contexts associated to h Γ ≺ G i , is defined as the configuration {h Γ ≺ G i ↾ r } r ∈ G . We write s ⇔ h Γ ≺ G i if a configuration s is the associated to h Γ ≺ G i . Theorem 4.10 (Trace Eqivalence).
Let h Γ ≺ G i be a closed global context and s ⇔ h Γ ≺ G i be a configuration associated with the global context. h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i if and only if s α −→ s ′ , where s ′ ⇔ h Γ ′ ≺ G ′ i . The theorem states that semantics are preserved after projection. Practically, we can implementlocal processes separately, and run them in parallel with preserved semantics.We also show that a well-formed global type G has progress. This means that a well-formedglobal type does not get stuck , which implies deadlock freedom. Definition 4.11 (Well-formed Global Types).
A global type under typing context h Γ ≺ G i iswell-formed, if (1) G does not contain free type variables, (2) G is contractive [Pierce 2002, §21],and (3) for all roles in the protocol r ∈ G , the projection h Γ ≺ G i ↾ r is defined.We also say a global type G is well-formed, if hœ ≺ G i is well-formed. Theorem 4.12 (Preservation of Well-formedness). If h Γ ≺ G i is a well-formed global typeunder typing context, and h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i , then h Γ ′ ≺ G ′ i is well-formed.Definition 4.13 (Progress). A configuration s satisfies progress, if either (1) For all participants p ∈ s , L p = end , or (2) there exists an action α and a configuration s ′ such that s α −→ s ′ .A global type under typing context h Γ ≺ G i satisfies progress, if its associated configuration s ⇔ h Γ ≺ G i , exists and satisfies progress.We also say a global type G satisfies progress, if hœ ≺ G i satisfies progress. Theorem 4.14 (Progress). If h Γ ≺ G i is a well-formed global type under typing context, then h Γ ≺ G i satisfies progress. Theorem 4.15 (Type Safety). If G is a well-formed global type, then for any global type undertyping context h Γ ′ ≺ G ′ i such that hœ ≺ G i −−→ ∗ h Γ ′ ≺ G ′ i , h Γ ′ ≺ G ′ i satisfies progress. Proof.
Direct consequence of Theorem 4.12 and Theorem 4.14. (cid:3)
We evaluate the expressiveness and performance of our toolchain
Session ⋆ . We describe the meth-odology and setup (§ 5.1), and comment on the compilation time (§ 5.2) and the execution time(§ 5.3). We demonstrate the expressiveness of Session ⋆ (§ 5.4) by implementing examples fromthe session type literature and comparing with related work. The source files of the benchmarksused in this section are included in our artifact, along with a script to reproduce the results. We measure the time to generate the CFSM representation from a
Scribble protocol (
CFSM ), andthe time to generate F ⋆ code from the CFSM representation ( F ⋆ APIs ). Since the generated APIs in F ⋆ need to be type-checked before use, we also measure the type-checking time for the generatedcode ( Gen. Code ). Finally, we provide a simple implementation of the callbacks and measure thetype-checking time for the callbacks against the generated type (
Callbacks ). Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:23 global protocol PingPong n (role A, role B) {choice at A { Ping(x :int) from A to B; Pong(y :int) from B to A; @"y > x "Ping(x :int) from A to B; @"x > y " Pong(y :int) from B to A; @"y > x " · · · Ping(x n :int) from A to B; @"x n > y n − " Pong(y n :int) from B to A; @"y n > x n "do PingPong n (A, B); }or { Bye() from A to B; Bye() from B to A; } } Fig. 15. Ping Pong Protocol (Parameterised by Protocol Length n ) To execute the protocols, we need a network transport to connect the participants by providingappropriate sending and receiving primitives. In our experiment setup, we use the standard lib-rary module
FStar.Tcp to establish TCP connections between participants, and provide a simpleserialisation module for base types. Due to the small size of our payloads, we set
TCP_NODELAY to avoid the delays introduced by the congestion control algorithms. Since our entry point to ex-ecute the protocol is parameterised by the connection/transport type, the implementation may useother connections if developers wish, e.g. an in-memory queue for local setups. We measure theexecution time of the protocol (
Execution Time ).To measure the overhead of our implementation, we compare against an implementation ofthe protocol without session types or refinement types, which we call bare implementation . Inthis implementation, we use the same sending and receiving primitives (i.e. connection ) as in thetoolchain implementation. The bare implementation is in a series of direct calls of sending andreceiving primitives, for the same communication pattern, but without the generated APIs.We use a Ping Pong protocol (Fig. 15), parameterised by the protocol length, i.e. the number ofPing Pong messages n in a protocol iteration. When the protocol length n increases, the numberof CFSM states increases linearly, which gives rise to longer generated code and larger generatedtypes. In each Ping Pong message, we include payload of increasing numbers, and encode theconstraints as protocol refinements.We study its effect on the compilation time (§ 5.2) and the execution time (§ 5.3). We run theexperiment on varying sizes of n , up to 25. Larger sizes of n leads to unreasonably large resourceusage during type-checking in F ⋆ . Table 1 reports the results for the Ping Pong protocol in Fig. 15.We run the experiments under a network of latency of 0.340ms (64 bytes ping), and repeat eachexperiment 30 times. Measurements are taken using a machine with Intel i7-7700K CPU (4.20 GHz,4 cores, 8 threads), 16 GiB RAM, operating system Ubuntu 18.04, OCaml compiler version 4.08.1, F ⋆ compiler commit , Z3 version 4.8.5. CFSM and F ⋆ Generation Time . We measure the time taken for
Scribble to generate theCFSM from the protocol in Fig. 15, and for the code generation tool to convert the CFSM to F ⋆ APIs. We observe from Table 1 that the generation time for CFSMs and F ⋆ APIs is short. It takesless than 1 second to complete the generation phase for each case.
Type-checking Time of Generated Code and Callbacks . We measure the time taken for thegenerated APIs to type-check in F ⋆ . We provide a simple F ⋆ implementation of the callbacks fol-lowing the generated APIs, and measure the time taken to type-check the callbacks.The increase of type-checking time is non-linear with regard to the protocol length. We encodeCFSM states as records corresponding to local typing contexts. In this case, the size of local typ-ing contexts and the number of type definitions grows linearly, giving rise to a non-linear increase.Moreover, the entry point function is likely to cause non-linear increases in the type-checking time. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :24 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida
Protocol Generation Time Type Checking Time Execution TimeLength ( n ) CFSM F ⋆ APIs Gen. Code Callbacks (100 000 ping-pongs)bare n/a n/a n/a n/a 28.79s1 0.38s 0.01s 1.28s 0.34s 28.75s5 0.48s 0.01s 3.81s 1.12s 28.82s10 0.55s 0.01s 14.83s 1.34s 28.84s15 0.61s 0.01s 42.78s 1.78s n/a20 0.69s 0.02s 98.35s 2.54s 28.81s25 0.78s 0.02s 206.82s 3.87s 28.76s
Table 1. Time Measurements for Ping Pong Protocol
The long type-checking time of the generated code could be avoided if the developer chooses totrust our toolchain to always generate well-typed F ⋆ code for the entry point. The entry pointwould be available in an interface file (cf. OCaml .mli files), with the actual implementation inOCaml instead of F ⋆ . There would otherwise be no changes in the development workflow. Al-though neither does type-checking time of the callback implementation fit a linear pattern, itremains within reasonable time frame. We measure the execution time taken for an exchange of 100,000 ping pongs for the toolchain andbare implementation under the experiment network. The execution time is dominated by networkcommunication, since there is little computation to be performed at each endpoint.We provide a bare implementation using a series of direct invocations of sending and receivingprimitives, in a compatible way to communicate with generated APIs. The bare implementationdoes not involve a record of callbacks, which is anticipated to run faster, since the bare implement-ation involves fewer function pointers when calling callbacks. Moreover, the bare implementationdoes not construct state records , which record a backlog of the communication, as the protocolprogresses. To measure the performance impact of book-keeping of callback and state records, werun the Ping Pong protocol from Fig. 15 for a protocol of increasing size (number of states andgenerated types), i.e. for increasing values of n . All implementations, including bare are run until100,000 ping pong messages in total are exchanged .We summarise the results in Table 1. Despite the different protocol lengths, there are no signific-ant changes in execution time. Since the execution is dominated by time spent on communication,the measurements are subject to network fluctuations, difficult to avoid during the experiments.We conclude that our implementation does not impose a large overhead on the execution time. We implement examples from the session type literature, and add refinements to encode datadependencies in the protocols. We measure the time taken for code generation and type-checking,and present them in Table 2. The time taken in the toolchain for examples in the session typeliterature is usually short, yet we demonstrate that we are able to implement the examples easilywith our callback style API. Moreover, the time taken is incurred at the compilation stage, hencethere is no overhead for checking refinements by our runtime. Defining a signature in an interface file, and providing an implementation in the target language (OCaml) allows the F ⋆ compiler to assume the implementation is correct. This technique is used frequently in the standard library of F ⋆ . This isnot to be confused with implementing the endpoints in OCaml instead of F ⋆ , as that would bypass the F ⋆ type-checking. For n = , we run 100,000 iterations of recursion; for n = , we run 10,000 iterations, etc. Total number of ping pongmessages exchanged by two parties remain the same.Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:25 Example (Endpoint) Gen. / TC. Time MP RV IV STPTwo Buyer a ( A ) 0.46s / 2.33s X ✗ X X † Negotiation b ( C ) 0.46s / 1.59s ✗ X ✗ ✗ Fibonacci c ( A ) 0.44s / 1.58s ✗ X ✗ ✗ Travel Agency d ( C ) 0.62s / 2.36s X ✗ ✗ X † Calculator c ( C ) 0.51s / 2.30s ✗ ✗ ✗ X SH e ( P ) 1.16s / 4.31s X ✗ X X † Online Wallet f ( C ) 0.62s / 2.67s X X ✗ ✗
Ticket д ( C ) 0.45s / 1.90s ✗ X ✗ ✗ HTTP h ( S ) 0.55s / 1.79s ✗ ✗ ✗ X † MP Multiparty ProtocolRV Uses Recursion VariablesIV Irrelevant VariablesSTP Implementable in STP X † STP requires dynamic checks a [Honda et al. 2016] b [Demangeon and Honda 2012] c [Hu and Yoshida 2016] d [Hu et al. 2008] e [Neykova et al. 2018] f [Neykova et al. 2013] д [Bocchi et al. 2013] h [Fielding and Reschke 2014] Table 2. Selected Examples from Literature
We also compare the expressiveness of our work with two most closely related works, namelyBocchi et al. [2010] and Neykova et al. [2018], which study refinements in MPST (also see § 6).Neykova et al. [2018] (Session Type Provider, STP) implements limited version of refinements inthe
Scribble toolchain. Our version is strictly more expressive than STP for two reasons: (1) sup-port for recursive variables to express invariants and (2) support for irrelevant variables. Fig. 16illustrates those features and Table 2 identifies which of the implemented examples use them. protocol Adder(role S, role C)@"S[acc: = ≥ = acc+x"do Adder(S, C); @"S[sum]" } (a) Accumulator (using Recursive Invariants) protocol Broadcast(role A, role B, role C){ Broadcast(x:int) from A to B; @"x ≥ ≥ = y" } (b) Broadcasting (using Irrelevant Variables)Fig. 16. Example Protocols Demonstrating Additional Expressiveness to [Neykova et al. 2018] In STP, when recursion occurs, all information about the variables is lost at the end of an itera-tion, hence their tool does not support even the simple example in Fig. 16a. In contrast, our workretains the recursion variables, which are available throughout the recursion. Additionally, theendpoint projection in STP is more conservative with regards to refinements. Whilst there mustbe no variables unknown to a role in the refinements attached to a message for the sending role,there may be unknown variables to the receiving role. The part unknown to the receiving role isdiscarded (hence weakening the pre-condition). In our work such information can still be retainedand used for type checking, thanks to irrelevant variables.In Bocchi et al. [2010], a global protocol with assertions must be well-asserted (§3.1). In particu-lar, the history sensitivity requirement states: "A predicate guaranteed by a participant p can onlycontain those interaction variables that p knows." Our theory lifts this restriction by allowing vari-ables unknown to a sending role to be used in the global or local type, whereas such variablescannot be used in the implementation. For example, Example 4.1 fails the well-asserted require-ment in [Bocchi et al. 2010]. In the refinement x = z for variable z (for message label Trd ), thevariable x is not known to C , hence the protocol would not be well-asserted. In our setup, suchprotocol is permitted, the endpoint implementation for C can provide the value y received from B to satisfy the refinement type — The SMT solver can validate the refinement from the transitivityof equality. We summarise the most closely related works in the areas of refinement and session types. For adetailed survey on theory and implementations of session types, see Gay and Ravara [2017].
Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :26 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida
Refinement Types for Verification and Reasoning . Refinement types were introduced to al-low recursive data structures to be specified in more details using predicates [Freeman and Pfenning1991]. Subsequent works on the topic [Bengtson et al. 2011; Schmid and Kuncak 2016; Vazou et al.2014, 2017] utilise SMT solvers, such as Z3 [De Moura and Bjørner 2008], to aid the type systemto decide a semantic subtyping relation [Bierman et al. 2012] using SMT encodings. Refinementtypes have been applied to numerous domains, such as resource usage analysis [Handley et al.2019; Knoth et al. 2020], secure implementations [Bengtson et al. 2011; Bhargavan et al. 2010], in-formation control flow enforcements [Polikarpova et al. 2020], and theorem proving [Vazou et al.2017]. Our aim is to utilise refinement types for the specification and verification of distributedprotocols, by combining refinement and session types in a single practical framework.
Implementation of Session Types . Neykova et al. [2018] provides an implementation of MPSTwith assertions using
Scribble and F
Scribble toolchain to support recursionvariables , allowing refinements on recursions, hence improving expressiveness. In this way, de-velopers can specify dependencies across recursive calls, which is not supported in STP. Second,we depart from the class-based API generation, and generate a callback-based API. Our approachhas the advantage that the linear usage of channels is ensured by construction, saving dynamicchecks for channels. Third, we use refinement types in F ⋆ to verify refinements statically, in con-trast, STP performs dynamic evaluations to validate assertions in protocols. Finally, the metatheoryof session types extended with refinements was not developed in their work.Several other MPST works follow a similar technique of class-based API generation to overcomelimitations of the type system in the target language, e.g. Castro et al. [2019] for Go, Ng et al. [2015]for C. All of the above works, suffer from the same limitations – they detect linearity violationsat runtime, and offer no static alternative. Indeed, to our knowledge, Imai et al. [2020] providethe only MPST implementation which statically checks linearity violation. It relies on specifictype-level OCaml features, and a monadic programming style. Our work proposes generation ofa callback-styled API from MPST protocols. To our knowledge, it is the first work that ensureslinear channel usage by construction. Although our target language is F*, the callback-styled APIcode generation technique is applicable to any mainstream programming language. Dependent and Refinement Session Types . Bocchi et al. [2010] propose a multiparty session π -calculus with logical assertions. By contrast, our formulation of RMPST is based on refinementtypes, projection with silent prefixes and correspondence with CFSMs, to target practical codegeneration, such as for F ⋆ . They do not formulate any semantics for global types nor prove anequivalence between refined global types and projections, as in this paper. Toninho and Yoshida[2017] extend MPST with value dependent types. Invariants on values are witnessed by proofobjects, which then may be erased at runtime. Our work uses refinement types, which follows theprinciple naturally, since refinements that appear in types are proof-irrelevant and can be erasedsafely. These works are limited to theory, whereas we provide an implementation.De Muijnck-Hughes et al. [2019] propose an Embedded Domain Specific Language (EDSL) ap-proach of implementing multiparty sessions (analogous to MPST) in Idris. They use value depend-ent types in Idris to define combinators, with options to specify data dependencies, contrary to our Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:27 approach of code generation. However, the combinators only describe the sessions, and how to im-plement and execute the sessions remains unanswered. Our work provides a complete toolchainfrom protocol description to implementation and verification.In the setting of binary session types, Das and Pfenning [2020] extend session types with arith-metic refinements, with application to work analysis for computing upper bounds of work froma given session type. Thiemann and Vasconcelos [2019] extend binary session types with labeldependent types. In the setup of their work, specification of arithmetic properties involves com-plicated definitions of inductive arithmetic relations and functions. In contrast, we use SMT solvers,which have built-in functions and relations for arithmetic. Furthermore, there is no need to con-struct proofs manually, since SMT solvers find the proof automatically, which enhances usabilityand ergonomics. Hinrichsen et al. [2019] combine binary session types with concurrent separationlogic, allowing reasoning about mixed-paradigm concurrent programs, and planned to extend theframework to MPST. Along similar lines, Swamy et al. [2020] provide a framework of concurrentseparation logic in F ⋆ , and demonstrate its expressiveness by showing how (dependent) binarysession types can be represented in the logic and used in reasoning. Our work is based on thetheory of MPST, subsuming the binary session types. Furthermore, we implement a toolchain thatdevelopers can use.Bhargavan et al. [2009] use refinement types to implement a limited form of multiparty sessiontypes. Session types are encoded in refinement types via code generation. The specification lan-guage they use, albeit similar to MPST, has limited expressive power. Only patterns of interactionswhere participants alternate between sending and receiving are permitted. Moreover, they do notstudy data dependencies in protocols, hence they can neither specify, nor verify constraints on pay-loads or recursions. We use refinement types to specify constraints and dependencies in multipartyprotocols, and use the F ⋆ compiler [Swamy et al. 2016] for verifying the endpoint implementations.The verified endpoint program does not only comply to the multiparty protocol, enjoying the guar-antees provided by the original MPST theory (deadlock freedom, session fidelity), but also satisfiesadditional guarantees provided by refinement types with respect to data constraints. We present a novel toolchain for implementing refined multiparty session types (RMPST), whichenables developers to use
Scribble , a protocol description language for multiparty session types,and F ⋆ , a state-of-the-art verification-oriented programming language, to implement a multipartyprotocol and statically verify endpoint implementations. To the best of the authors’ knowledge,this is the first work on statically verified multiparty protocols with refinement types. We extendthe theory of multiparty session types with data refinements, and present a toolchain that enablesdevelopers to specify multiparty protocols with data dependencies, and implement the endpointsusing generated APIs in F ⋆ . We leverage the advanced typing system in F ⋆ to encode local sessiontypes for endpoints, and validate the data dependencies in the protocol statically.The verified endpoint program in F ⋆ is extracted into OCaml, where the refinements are erased — adding no runtime overhead for refinements. The callback-styled API avoids linearity checks ofchannel usage by internalising communications in generated code. We evaluate our toolchain anddemonstrate that our overhead is small compared to an implementation without session types.Whereas refinement types express the data dependencies of multiparty protocols, the availab-ility of refinement types in general purpose mainstream programming languages is limited. Forfuture work, we wish to study how to mix participants with refined implementation and thosewithout, possibly using a gradual typing system [Igarashi et al. 2019; Lehmann and Tanter 2017]. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :28 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida
ACKNOWLEDGMENTS
We thank the OOPSLA reviewers for their comments and suggestions, and David Castro, Julia Ga-bet and Lorenzo Gheri for proofreading. We thank Wei Jiang and Qianyi Shu for testing the arti-fact. The work is supported by EPSRC EP/T006544/1, EP/K011715/1, EP/K034413/1, EP/L00058X/1,EP/N027833/1, EP/N028201/1, EP/T006544/1, EP/T014709/1 and EP/V000462/1, and NCSS/EPSRCVeTSS.
REFERENCES
Andreas Abel and Gabriel Scherer. 2012. On Irrelevance and Algorithmic Equality in Predicative Type Theory.
LogicalMethods in Computer Science
Volume 8, Issue 1 (March 2012). https://doi.org/10.2168/LMCS-8(1:29)2012Davide Ancona, Viviana Bono, Mario Bravetti, Joana Campos, Giuseppe Castagna, Pierre-Malo Deniélou, Simon J. Gay, NilsGesbert, Elena Giachino, Raymond Hu, Einar Broch Johnsen, Francisco Martins, Viviana Mascardi, Fabrizio Montesi,Rumyana Neykova, Nicholas Ng, Luca Padovani, Vasco T. Vasconcelos, and Nobuko Yoshida. 2016. Behavioral Types inProgramming Languages.
Found. Trends Program. Lang.
3, 2–3 (July 2016), 95–230. https://doi.org/10.1561/2500000031Jesper Bengtson, Karthikeyan Bhargavan, Cédric Fournet, Andrew D Gordon, and Sergio Maffeis. 2011. Refinement typesfor secure implementations.
ACM Transactions on Programming Languages and Systems (TOPLAS)
33, 2 (2011), 8.Karthikeyan Bhargavan, Ricardo Corin, Pierre-Malo Deniélou, Cédric Fournet, and James J. Leifer. 2009. CryptographicProtocol Synthesis and Verification for Multiparty Sessions. In .124–140. https://doi.org/10.1109/CSF.2009.26Karthikeyan Bhargavan, Cédric Fournet, and Andrew D. Gordon. 2010. Modular Verification of Security Protocol Code byTyping. In
Proceedings of the 37th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages(POPL ’10) . ACM, New York, NY, USA, 445–456. https://doi.org/10.1145/1706299.1706350Gavin M Bierman, Andrew D Gordon, Cătălin Hriţcu, and David Langworthy. 2012. Semantic subtyping with an SMTsolver.
Journal of Functional Programming
22, 1 (2012), 31–105. https://doi.org/10.1017/S0956796812000032Laura Bocchi, Romain Demangeon, and Nobuko Yoshida. 2013. A Multiparty Multi-session Logic. In
Trustworthy GlobalComputing , Catuscia Palamidessi and Mark D. Ryan (Eds.). Springer Berlin Heidelberg, Berlin, Heidelberg, 97–111.Laura Bocchi, Kohei Honda, Emilio Tuosto, and Nobuko Yoshida. 2010. A Theory of Design-by-Contract for DistributedMultiparty Interactions. In
CONCUR 2010 - Concurrency Theory , Paul Gastin and François Laroussinie (Eds.). SpringerBerlin Heidelberg, Berlin, Heidelberg, 162–176.Daniel Brand and Pitro Zafiropulo. 1983. On Communicating Finite-State Machines.
J. ACM
30, 2 (April 1983), 323–342.https://doi.org/10.1145/322374.322380David Castro, Raymond Hu, Sung-Shik Jongmans, Nicholas Ng, and Nobuko Yoshida. 2019. Distributed Programming UsingRole-parametric Session Types in Go: Statically-typed Endpoint APIs for Dynamically-instantiated CommunicationStructures.
Proc. ACM Program. Lang.
3, POPL, Article 29 (Jan. 2019), 30 pages. https://doi.org/10.1145/3290342Ankush Das and Frank Pfenning. 2020. Session Types with Arithmetic Refinements. In , Igor Konnov andLaura Kovács (Eds.), Vol. 171. Schloss Dagstuhl–Leibniz-Zentrum für Informatik, Dagstuhl, Germany, 13:1–13:18.https://doi.org/10.4230/LIPIcs.CONCUR.2020.13Leonardo De Moura and Nikolaj Bjørner. 2008. Z3: An Efficient SMT Solver. In
Proceedings of the Theory and Prac-tice of Software, 14th International Conference on Tools and Algorithms for the Construction and Analysis of Systems(TACAS’08/ETAPS’08) . Springer-Verlag, Berlin, Heidelberg, 337–340. http://dl.acm.org/citation.cfm?id=1792734.1792766Jan de Muijnck-Hughes, Edwin Brady, and Wim Vanderbauwhede. 2019. Value-Dependent Session Design in a DependentlyTyped Language. In Proceedings
Programming Language Approaches to Concurrency- and Communication-cEntric Soft-ware,
Prague, Czech Republic, 7th April 2019 (Electronic Proceedings in Theoretical Computer Science) , Francisco Martinsand Dominic Orchard (Eds.), Vol. 291. Open Publishing Association, 47–59. https://doi.org/10.4204/EPTCS.291.5Romain Demangeon and Kohei Honda. 2012. Nested Protocols in Session Types. In
CONCUR 2012 - ConcurrencyTheory - 23rd International Conference, CONCUR 2012, Newcastle upon Tyne, UK, September 4-7, 2012. Proceed-ings (Lecture Notes in Computer Science) , Maciej Koutny and Irek Ulidowski (Eds.), Vol. 7454. Springer, 272–286.https://doi.org/10.1007/978-3-642-32940-1_20Pierre-Malo Denielou, Nobuko Yoshida, Andi Bejleri, and Raymond Hu. 2012. Parameterised Multiparty Session Types.
Logical Methods in Computer Science
Volume 8, Issue 4 (Oct. 2012). https://doi.org/10.2168/LMCS-8(4:6)2012Pierre-Malo Deniélou and Nobuko Yoshida. 2013. Multiparty Compatibility in Communicating Automata: Characterisationand Synthesis of Global Session Types. In , Vol. 7966. Springer, Berlin, Heidelberg, 174–186. https://doi.org/10.1007/978-3-642-39212-2_18Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:29
Roy T. (Ed.) Fielding and Julian F. (Ed.) Reschke. 2014.
Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
Proceedings of the ACM SIGPLAN 1991 Con-ference on Programming Language Design and Implementation (PLDI ’91) . ACM, New York, NY, USA, 268–277.https://doi.org/10.1145/113445.113468Simon Gay and António Ravara (Eds.). 2017.
Behavioural Types: from Theory to Tools . River Publishers.https://doi.org/10.13052/rp-9788793519817Martin A. T. Handley, Niki Vazou, and Graham Hutton. 2019. Liquidate Your Assets: Reasoning about Resource Usage in Li-quid Haskell.
Proc. ACM Program. Lang.
4, POPL, Article Article 24 (Dec. 2019), 27 pages. https://doi.org/10.1145/3371092Jonas Kastberg Hinrichsen, Jesper Bengtson, and Robbert Krebbers. 2019. Actris: Session-Type Based Reasoning in Separ-ation Logic.
Proc. ACM Program. Lang.
4, POPL, Article Article 6 (Dec. 2019), 30 pages. https://doi.org/10.1145/3371074Kohei Honda, Nobuko Yoshida, and Marco Carbone. 2008. Multiparty Asynchronous Session Types. In
Proceedings of the35th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL ’08) . ACM, New York,NY, USA, 273–284. https://doi.org/10.1145/1328438.1328472Kohei Honda, Nobuko Yoshida, and Marco Carbone. 2016. Multiparty Asynchronous Session Types.
J. ACM
63 (2016),1–67. Issue 1-9. https://doi.org/10.1145/2827695Raymond Hu. 2017. Distributed Programming Using Java APIs Generated from Session Types.
Behavioural Types: fromTheory to Tools (2017), 287–308.Raymond Hu and Nobuko Yoshida. 2016. Hybrid Session Verification through Endpoint API Generation. In , Vol. 9633. Springer, Berlin, Heidelberg,401–418. https://doi.org/10.1007/978-3-662-49665-7_24Raymond Hu, Nobuko Yoshida, and Kohei Honda. 2008. Session-Based Distributed Programming in Java. In
ECOOP 2008- Object-Oriented Programming, 22nd European Conference, Paphos, Cyprus, July 7-11, 2008, Proceedings (Lecture Notes inComputer Science) , Jan Vitek (Ed.), Vol. 5142. Springer, 516–541. https://doi.org/10.1007/978-3-540-70592-5_22Atsushi Igarashi, Peter Thiemann, Yuya Tsuda, Vasco T. Vasconcelos, and Philip Wadler. 2019. Gradual session types.
Journal of Functional Programming
29 (2019), e17. https://doi.org/10.1017/S0956796819000169Keigo Imai, Rumyana Neykova, Nobuko Yoshida, and Shoji Yuen. 2020. Multiparty Session Programming with Global Pro-tocol Combinators. https://github.com/keigoi/ocaml-mpst (LIPIcs) . Schloss Dagstuhl - Leibniz-Zentrum für Informatik.To appear in ECOOP’20.Keigo Imai, Nobuko Yoshida, and Shoji Yuen. 2019. Session-ocaml: A session-based library with polarities and lenses.
Science of Computer Programming
172 (2019), 135 – 159. https://doi.org/10.1016/j.scico.2018.08.005Tristan Knoth, Di Wang, Adam Reynolds, Jan Hoffmann, and Nadia Polikarpova. 2020. Liquid Resource Types.
Proc. ACMProgram. Lang.
4, ICFP, Article 106 (Aug. 2020), 29 pages. https://doi.org/10.1145/3408988Nico Lehmann and Éric Tanter. 2017. Gradual Refinement Types. In
Proceedings of the 44th ACM SIGPLAN Symposium onPrinciples of Programming Languages (POPL 2017) . Association for Computing Machinery, New York, NY, USA, 775–788.https://doi.org/10.1145/3009837.3009856Rumyana Neykova, Raymond Hu, Nobuko Yoshida, and Fahd Abdeljallal. 2018. A Session Type Provider: Compile-timeAPI Generation of Distributed Protocols with Refinements in F
Proceedings of the 27th International Conference onCompiler Construction (CC 2018) . ACM, New York, NY, USA, 128–138. https://doi.org/10.1145/3178372.3179495Rumyana Neykova and Nobuko Yoshida. 2019.
Featherweight Scribble . Springer International Publishing, Cham, 236–259.https://doi.org/10.1007/978-3-030-21485-2_14Rumyana Neykova, Nobuko Yoshida, and Raymond Hu. 2013. SPY: Local Verification of Global Protocols. In
RuntimeVerification , Axel Legay and Saddek Bensalem (Eds.). Springer Berlin Heidelberg, Berlin, Heidelberg, 358–363.Nicholas Ng, Jose G.F. Coutinho, and Nobuko Yoshida. 2015. Protocols by Default: Safe MPI Code Generation basedon Session Types. In , Vol. 9031. Springer, 212–232.https://doi.org/10.1007/978-3-662-46663-6_11Dominic Orchard and Nobuko Yoshida. 2017. Session Types with Linearity in Haskell.
Behavioural Types: from Theory toTools (2017), 219–241.Frank Pfenning. 2001. Intensionality, extensionality, and proof irrelevance in modal type theory. In
Proceedings 16th AnnualIEEE Symposium on Logic in Computer Science . IEEE, 221–230.Benjamin C. Pierce. 2002.
Types and Programming Languages (1st ed.). The MIT Press.Nadia Polikarpova, Deian Stefan, Jean Yang, Shachar Itzhaky, Travis Hance, and Armando Solar-Lezama. 2020.Liquid Information Flow Control.
Proc. ACM Program. Lang.
4, ICFP, Article 105 (Aug. 2020), 30 pages.https://doi.org/10.1145/3408987Patrick M. Rondon, Ming Kawaguchi, and Ranjit Jhala. 2008. Liquid Types. In
Proceedings of the 29th ACM SIGPLANConference on Programming Language Design and Implementation (PLDI ’08) . ACM, New York, NY, USA, 159–169.https://doi.org/10.1145/1375581.1375602Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :30 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida
Alceste Scalas, Ornela Dardha, Raymond Hu, and Nobuko Yoshida. 2017. A Linear Decomposition of Multiparty Sessionsfor Safe Distributed Programming. In
ECOOP . https://doi.org/10.4230/LIPIcs.ECOOP.2017.24Georg Stefan Schmid and Viktor Kuncak. 2016. SMT-based Checking of Predicate-qualified Types for Scala. In
Pro-ceedings of the 2016 7th ACM SIGPLAN Symposium on Scala (SCALA 2016)
Proceedings of the 43rd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL ’16) . ACM, St. Petersburg, FL, USA, 256–270.https://doi.org/10.1145/2837614.2837655Nikhil Swamy, Aseem Rastogi, Aymeric Fromherz, Denis Merigoux, Danel Ahman, and Guido Martínez. 2020. SteelCore:An Extensible Concurrent Separation Logic for Effectful Dependently Typed Programs.
Proc. ACM Program. Lang.
Proc. ACM Program. Lang. , Article Article67 (Dec. 2019), 29 pages. https://doi.org/10.1145/3371135Bernardo Toninho and Nobuko Yoshida. 2017. Certifying data in multiparty session types.
Journal of Logical and AlgebraicMethods in Programming
90 (2017), 61 – 83. https://doi.org/10.1016/j.jlamp.2016.11.005Niki Vazou, Eric L. Seidel, Ranjit Jhala, Dimitrios Vytiniotis, and Simon Peyton-Jones. 2014. Refinement Types for Haskell.In
Proceedings of the 19th ACM SIGPLAN International Conference on Functional Programming (ICFP ’14) . ACM, NewYork, NY, USA, 269–282. https://doi.org/10.1145/2628136.2628161Niki Vazou, Anish Tondwalkar, Vikraman Choudhury, Ryan G. Scott, Ryan R. Newton, Philip Wadler, and Ranjit Jhala.2017. Refinement Reflection: Complete Verification with SMT.
Proc. ACM Program. Lang.
2, POPL, Article 53 (Dec.2017), 31 pages. https://doi.org/10.1145/3158141Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida. 2020. Statically Verified Refine-ments for Multiparty Protocols. https://doi.org/10.5281/zenodo.3970760
A PROOFS FOR § 4A.1 Auxiliary lemmas
Lemma A.1.
Given a participant p , a global typing context Γ and a local typing context Σ such that Γ ↾ p = Σ .Then, the projection of global typing context Γ with x P : T to p satisfies that Γ ∪ { x P : T } ↾ p = ( Σ ∪ { x ω : T } if p ∈ P Σ ∪ { x : T } if p < P Proof.
By expanding defintion and case analysis. (cid:3)
Lemma A.2.
Given a participant p , global typing contexts Γ , Γ , a global type G .If the two typing contexts have the same projection on p : Γ ↾ p = Γ ↾ p , then the projection ofglobal types under the two contexts are the same: h Γ ≺ G i ↾ p = h Γ ≺ G i ↾ p . Proof.
By induction on the derivation of projection of global types. (cid:3)
Lemma A.3.
Given a global typing context Γ , a set of participants P , a participant p , a variable x ,a well-formed type T and a global type G .If h Γ ∪ { x œ : T } ≺ G i ↾ p = h Σ ≺ L i , then h Γ ∪ { x P : T } ≺ G i ↾ p = h Σ ≺ L i . Proof.
By induction on derivation of projection of global types, via weakening of local typingrules: Σ , x : T , Σ ⊢ E : T ′ = ⇒ Σ , x ω : T , Σ ⊢ E : T ′ (cid:3) Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:31
Lemma A.4 (Inversion of Projection).
Given a global typing context Γ , a global type G , a par-ticipant p , a local typing context Σ , a local type L , such that h Γ ≺ G i ↾ p = h Σ ≺ L i .If L is of form:(1) L = q ⊕{ l i ( x i : T i ) . L i } i ∈ I , then G is of form p → q { l i ( x i : T i ) . G i } i ∈ I .(2) L = q & { l i ( x i : T i ) . L i } i ∈ I , then G is of form q → p { l i ( x i : T i ) . G i } i ∈ I .(3) L = l ( x : T ) . L , then G is of form s → t { l i ( x i : T i ) . G i } i ∈ I , where p < { s, t } and l ( x : T ) . L = ⊔ i ∈ I l i ( x i : T i ) . L i , where L i is obtained via the projection of G i .(4) L = µ t ( x : T )h x : = E i . L ′ , then G is of form µ t ( x : T )h x : = E i . G ′ , and p ∈ G . Proof.
A direct consequence of projections rules h Γ ≺ G i ↾ p — The results of projections arenot overlapping. (cid:3) Lemma A.5 (Determinancy).
Let h Γ ≺ G i be a global type under a global typing context, and α be a labelled action.If h Γ ≺ G i α −→ h Γ ≺ G i and h Γ ≺ G i α −→ h Γ ≺ G i , then h Γ ≺ G i = h Γ ≺ G i . Proof.
By induction on global type reduction rules. (cid:3)
A.2 Proof of Theorem 4.10
Let h Γ ≺ G i be a global type under a global typing context and s ⇔ h Γ ≺ G i be aconfiguration associated with the global type and context. h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i if and only if s α −→ s ′ , where s ′ ⇔ h Γ ′ ≺ G ′ i . Proof.
Soundness ( ⇒ ): By induction on the reduction rules of global types h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i .(1) [ G-Pfx ]For p :We project the global context before transition to p . h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i ↾ p = h Σ p ≺ q ⊕{ l i ( x i : T i ) . L i } i ∈ I i where Σ p = Γ ↾ p and h Σ i ≺ L i i = h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ p for i ∈ I We have h Σ p ≺ q ⊕{ l i ( x i : T i ) . L i } i ∈ I i p → q : l j ( x j : T j ) −−−−−−−−−−→ h Σ p ∪ { x j : T j } ≺ L j i by [ L-Send ].We project the global context after transition to p (via Lemma A.1). h Γ ∪ { x { p, q } j : T j } ≺ G j i ↾ p = h Σ p ∪ { x j : T j } ≺ L j i which is the same as the result of applying [ L-Send ].For q :Similar to the case of p , using [ L-Recv ].For r ( r , p , r , q ):We project the global context before transition to r . h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i ↾ p = h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i where Σ r = Γ ↾ r and h Σ i ≺ L i i = h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ r for i ∈ I We project the global context after transition to r (via Lemma A.1). h Γ ∪ { x { p, q } j : T j } ≺ G j i ↾ r = h Σ r ∪ { x j : T j } ≺ L j i We have h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i ϵ −→ h Σ r ∪ { x j : T j } ≺ L j i by [ E-Phi ] and plain merging.(2) [
G-Cnt ]By inductive hypothesis, we have ∀ j ∈ I . {h Γ ∪ { x œ j : T j } ≺ G j i ↾ r } r ∈ G j α −→ {h Γ ′ ≺ G ′ j i ↾ r } r ∈ G j If r ∈ subj ( α ) , then h Γ ∪ { x œ j : T j } ≺ G j i ↾ r α −→ h Γ ′ ≺ G ′ j i ↾ r . Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :32 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida If r’ < subj ( α ) , then h Γ ∪ { x œ j : T j } ≺ G j i ↾ r’ ϵ −→ h Γ ′ ≺ G ′ j i ↾ r’ .For p :We project the global context before transition to p . h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i ↾ p = h Σ p ≺ q ⊕{ l i ( x i : T i ) . L i }i i ∈ I where Σ p = Γ ↾ p and h Σ i ≺ L i i = h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ p for i ∈ I We project the global context after transition to p . h Γ ′ ≺ p → q (cid:8) l i ( x i : T i ) . G ′ i (cid:9) i ∈ I i ↾ p = h Σ p ′ ≺ q ⊕ (cid:8) l i ( x i : T i ) . L ′ i (cid:9) i i ∈ I where Σ p ′ = Γ ′ ↾ p and h Σ ′ i ≺ L ′ i i = h Γ ′ ∪ { x { p, q } i : T i } ≺ G ′ i i ↾ p for i ∈ I Since p < subj ( α ) , we have h Σ p ∪ { x j : T j } ≺ L j i ϵ −→ h Σ p ′ ≺ L ′ j i = h Γ ′ ≺ G ′ j i ↾ p from theinductive hypothesis.By [ E-Cnt ], we have h Σ p ≺ q ⊕{ l i ( x i : T i ) . L i } i ∈ I i ϵ −→ h Σ p ′ ≺ q ⊕ (cid:8) l i ( x i : T i ) . L ′ i (cid:9) i ∈ I i .For q , the proof is similar.For r , where r , p , r , q , and r < subj ( α ) :We project the global context before transition to r . h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i ↾ r = h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i where Σ r = Γ ↾ r and h Σ i ≺ L i i = h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ r for i ∈ I We project the global context after transition to r . h Γ ′ ≺ p → q (cid:8) l i ( x i : T i ) . G ′ i (cid:9) i ∈ I i ↾ r = h Σ r ′ ≺ ⊔ i ∈ I l i ( x i : T i ) . L ′ i i where Σ r ′ = Γ ′ ↾ r and h Σ ′ i ≺ L ′ i i = h Γ ′ ∪ { x { p, q } i : T i } ≺ G ′ i i ↾ r for i ∈ I Since r < subj ( α ) , we have h Σ r ∪ { x j : T j } ≺ L j i ϵ −→ h Σ r ′ ≺ L ′ j i = h Γ ′ ≺ G ′ j i ↾ r from theinductive hypothesis.By [ E-Phi ], we have h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i ϵ −→ h Σ r ∪ { x j : T j } ≺ L j i where j ∈ I By transitivity, we have h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i ϵ −→ h Σ r ′ ≺ L ′ j i For r , where r , p , r , q , and r ∈ subj ( α ) :Since r ∈ subj ( α ) , we have h Σ r ∪ { x j : T j } ≺ L j i α −→ h Σ r ′ ≺ L ′ j i = h Γ ′ ≺ G ′ j i ↾ r from theinductive hypothesis.By [ E-Phi ], we have h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i ϵ −→ h Σ r ∪ { x j : T j } ≺ L j i where j ∈ I By [
L-Eps ], we have h Σ r ≺ ⊔ i ∈ I l i ( x i : T i ) . L i i α −→ h Σ r ′ ≺ L ′ j i (3) [ G-Rec ]By inductive hypothesis.Completeness ( ⇐ ): Fix the transition label α = p → q : l ( x : T ) .We prove by induction on the reduction of s α −→ s ′ , and consider the local types for after projec-tion. • [ L-Send ] and [
L-Recv ]. This case arises from the projection of G = p → q { l i ( x i : T i ) . G i } i ∈ I (Lemma A.4 case (1) and (2)).Let Γ ′ = Γ ∪ { x { p, q } : T } .By projection ([ P-Send ], [
P-Recv ]), we have h Σ p ≺ L p i = q ⊕ (cid:8) l i ( x i : T i ) . L p i (cid:9) and h Σ q ≺ L q i = p & (cid:8) l i ( x i : T i ) . L q i (cid:9) , where L p i is obtained by h Γ ′ ≺ G i i ↾ p , resp. for q .Since s α −→ s ′ , by inversion of [ L-Send ] on h Σ p ≺ L p i and [ L-Recv ] on h Σ q ≺ L q i , we have j ∈ I with l j = l , x j = x and T j = T . By [ L-Send ] and [
L-Recv ], the configuration s ′ has h Σ p ∪ { x : T } ≺ L p j i , resp. for q .We can obtain that h Γ ≺ G i l −→ h Γ ∪ { x { p, q } j : T j } ≺ G j i , via [ G-Pfx ]. Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:33
For p and q , the association with s ′ is straight forward. We further show the association for r ( r , p, q ). By projection ([ P-Phi ]) and plain merging, we have h Σ r ≺ L r i = l ( x : T ) . L r j ,where L r j is obtained by the projection h Γ ′ ≺ G j i ↾ r .[ E-Phi ] can occur when s l −→ s ′ , and h Σ r ∪ { x : T } ≺ L r j i is associated with h Γ ≺ G j i . • [ L-Eps ] ([
E-Phi ]) and [
L-Eps ] ([
E-Phi ]). This case arises from the projection of G = s → t { l i ( x i : T i ) . G i } i ∈ I ( { s, t } ∩ { p, q } = œ , Lemma A.4 case (3)).Let Γ ′ i = Γ ∪ { x { s, t } i : T } , Γ i = Γ ∪ { x œ i : T } .By projection ([ P-Send ], [
P-Recv ]), we have h Σ p ≺ L s i = q ⊕{ l i ( x i : T i ) . L s i } and h Σ q ≺ L t i = p & { l i ( x i : T i ) . L t i } , where L s i is obtained by h Γ ′ i ≺ G i i ↾ s , resp. for t .For r , s, t , the projection gives a uniform silent prefix ([ P-Phi ]), h Σ r ≺ L r i = ⊔ i ∈ I l i ( x i : T i ) . L r i ,where L r i is obtained by projection h Γ ′ ≺ G i i ↾ r .Let the merged label be l , variable be x , value type be T and session type be L r . We have h Σ r ≺ L r i = l ( x : T ) . L r .Let Γ = Γ ∪ { x œ i : T } .In this case, [ L-Send ] (resp. [ L-Recv ]) cannot apply directly on L p (resp. L q ), so the ruleapplied must be [ L-Eps ].By inversion of [ L-Eps ] with [ E-Phi ] , we have that h Σ p i ∪ { x : T } ≺ L p i α −→ h Σ p ′ ≺ L p ′ i (resp. q ).Take arbitrary i ∈ I , let s i be the configuration associated to h Γ ≺ G i i .We note that h Σ r ≺ L r i = l ( x : T ) . L r ϵ −→ h Σ r ∪ { x : T } ≺ L r i = h Σ r i ≺ L r i i ([ E-Phi ]).Despite that L r i is obtained from projection with context Γ ′ , the same local type is projec-ted with context Γ (Lemma A.2). Therefore, we can apply the action α on s i , and use theinductive hypothesis on h Γ ≺ G i i and s i .We thus have with arbitrary i ∈ I , h Γ ≺ G i i α −→ h Γ ′ i ≺ G ′ i i for some h Γ ′ i ≺ G ′ i i associatedwith s ′ i . By Lemma A.5, the h Γ ′ i ≺ G ′ i i are identical, we denote it h Γ ′ ≺ G ′ i .We can therefore obtain that h Γ ≺ G i α −→ h Γ ′ ≺ s → t { l i ( x i : T i ) . G ′ } i ∈ I i via [ G-Cnt ].We are now left to show the association with s ′ :From the inductive hypothesis, we have s ′ i ⇔ h Γ ′ ≺ G ′ i .For r , s, t , the association result follows from Lemma A.2 and inductive hypothesis, since Γ ′ i projects x i to an irrelevant quantified variable. For s, t , we use Lemma A.3, which weakensthe projected x i to a concrete variable. • [ L-Eps ] ([
E-Rec ]) and [
L-Eps ] ([
E-Rec ]). This case arises from the projection of G = µ t ( x ′ : T ′ )h x ′ : = E i . G (Lemma A.4, case (4)).We discuss the case where the projection uses [ P-Rec-In ], since [
P-Rec-Out ] projects to end with no actions to be taken.Let Γ ′ = Γ ∪ { x ′{ r | r ∈ G } : T } .For all roles r ∈ G , by projection ([ P-Rec-In ]), we have h Σ p ≺ µ t ( x ′ : T ′ )h x ′ : = E i . L r i ,where where L r is obtained by h Γ ′ ≺ G i ↾ r .In this case, [ L-Send ] (resp. [
L-Recv ]) cannot apply directly on L p (resp. L q ), so the ruleapplied must be [ L-Eps ].By inversion of [
L-Eps ] with [
E-Rec ], we have that h Σ p ∪ { x ′ ω : T ′ } ≺ L p [ µ t ( x ′ : T ′ ) . L p / t ]i α −→h Σ p ′ ≺ L p ′ i .For other roles s , p, q , by inverting [ E-Rec ], we have that h Σ s ∪ { x ′ ω : T ′ } ≺ L s [ µ t ( x ′ : T ′ ) . L s / t ]i α −→ h Σ s ′ ≺ L s ′ i .Combining all roles, we can use the inductive hypothesis and obtain Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :34 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida h Γ ∪ { x ′{ r | r ∈ G } : T ′ } ≺ G [ µ t ( x ′ : T ′ ) . G / t ]i α −→ h Γ ′ ≺ G ′ i via [ G-Rec ], and association with h Γ ′ ≺ G ′ i . • The rest of the cases are vacuous, since inverting the projections (Lemma A.4) of L p and L q leads to incompatible shapes of global type G . (cid:3) A.3 Proof of Theorem 4.12 If h Γ ≺ G i is a well-formed global type under typing context, and h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i , then h Γ ′ ≺ G ′ i is well-formed. Proof.
By induction on the reduction of global type h Γ ≺ G i α −→ h Γ ′ ≺ G i . • [ G-Pfx ] h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i p → q : l j ( x j : T j ) −−−−−−−−−−→ h Γ ∪ { x { p, q } j : T j } ≺ G j i There are three cases for projection to consider: [
P-Send ], [
P-Recv ], and [
P-Phi ]. In all cases,the premises state that h Γ ∪ { x { p, q } i : T i } ≺ G i i ↾ p = h Σ i ≺ L i i , which indicates that allcontinuations are projectable for all indices. • [ G-Cnt ] h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i α −→ h Γ ′ ≺ p → q (cid:8) l i ( x i : T i ) . G ′ i (cid:9) i ∈ I i From inductive hypothesis, we have that for all index i ∈ I , if h Γ ∪ { x œ j : T j } ≺ G j i is well-formed, then h Γ ′ ≺ G ′ j i is well-formed.In all three cases of projection, the premises state that Σ ⊢ T i ty for all index i ∈ I . Therefore,the context h Γ ∪ { x œ j : T j } ≺ G j i is also well-formed.We are left to show that h Γ ′ ≺ p → q (cid:8) l i ( x i : T i ) . G ′ i (cid:9) i ∈ I i is well-formed: we invert thepremise of projection of h Γ ≺ p → q { l i ( x i : T i ) . G i } i ∈ I i and apply Lemma A.3. • [ G-Rec ] h Γ ≺ µ t ( x : T )h x : = E i . G i α −→ h Γ ′ ≺ G ′ i By inductive hypothesis. (cid:3)
A.4 Proof of Theorem 4.14 If h Γ ≺ G i is a well-formed global type under context, then h Γ ≺ G i satisfies progress. Proof.
By induction on the structure of global types G . Using Theorem 4.10, we are sufficientto show that h Γ ≺ G i α −→ h Γ ′ ≺ G ′ i , and apply the theorem for the progress of associated config-uration. • G = p → q { l i ( x i : T i ) . G i } i ∈ I .Since the index set I must not be empty, we can pick an index i ∈ I and apply [ G-Pfx ]. • G = µ t ( x : T )h x : = E i . G ′ Since recursive types must be contractive, we have that G ′ [ µ t ( x : T ) . G ′ / t ] , G ′ . Furthermore,the substituted type is closed. We can apply [ G-Rec ]. • G = t h x : = E i Vacuous, since well-formed global type cannot have free type variable. • G = end Corresponds to the case where all local types are end . (cid:3) Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:35
B ADDITIONAL DETAILS ON CODE GENERATIONB.1 Communicating Finite State Machines (CFSMs) (Toolchain Internals)
Communicating Finite State Machines (CFSMs, [Brand and Zafiropulo 1983]) correspond to localtypes projected from global types, as shown in [Deniélou and Yoshida 2013]. We define the CFSMas a tuple ( Q , q , δ ) , where Q is set of states, q ∈ Q is an initial state, and δ ⊆ Q × A × Q is atransition relation, where A is the set of labelled actions (cf. § 4.4). Conversion to Communicating Finite State Machines (CFSMs) . Scribble follows the pro-jection defined in § 4.3, and projects a global protocol into local types. Local types can be convertedeasily into a Communicating Finite State Machine (CFSM), such that the resulting CFSM does nothave mixed state (i.e. a state does not contain a mixture of sending and receiving outgoing trans-itions), and that the states are directed (i.e. they only contain sending or receiving actions towardsan identical participant) [Deniélou and Yoshida 2013, Def. 3.4, Prop. 3.1]. We follow the same ap-proach to obtain a CFSM from the local types with their typing contexts. The CFSM has the sametrace of actions as the local types [Deniélou and Yoshida 2013, Prop. 3.2].We generate F ⋆ code from the CFSM obtained from projection. We generate records for eachstate to correspond to the typing context (explained in Appendix B.2.3), and functions for trans-itions to correspond to actions (explained in Appendix B.2.1). The execution of the CFSM is detailedin § 3.4. B.2 Generated APIs with Refinement Types (Toolchain Output)
Our code generator takes a CFSM as an input to produce type definitions and an entry point toexecute the protocol. As previously introduced, our design separates program logic and communic-ations, corresponding to the callbacks type (Appendix B.2.1) and connection type (Appendix B.2.2).The generated entry point function takes callbacks and a connection, and runs the protocol, whichwe detail the internals in § 3.4.
B.2.1 Callbacks.
We generate function types for handling transitions in the CFSM, and collectthem into a record of callbacks . When running the CFSM for a participant, appropriate callbackwill be invoked when the transition occurs. For sending transitions, the sending callback is invokedto prompt a value to be sent. For receiving transitions, the receiving callback is invoked with thevalue received, so the developer may use the value for processing.
Generating Handlers for Receiving States . For a receiving state q ∈ Q with receiving action p → q : l ( x : T ) (assuming the current role is q ), the receiving callback is a function that takesthe record n q o and the received value of type T , that returns unit (with possible side-effects). Thefunction signature is given by state q _receive_ l : ( st : n q o ) → n T o st → ML unit The constructor ML is an effect specification in F ⋆ , which permits all side effects in ML language(e.g. using references, performing I/O), in contrast to a pure total function permitting no side effects. n q o is a record correspondent to the local typing context of the state, n T o st is a refinement type,but the free variables in the refinement types are bound to the record st . We generate one callbackfor each receiving action, so that it can be invoked upon receiving a message according to themessage label. Generating Handlers for Sending States . For a sending state q ∈ Q with send actions p → q : l i ( x i : T i ) (assuming the current role is p ), for some index i ∈ I , the sending callback is afunction that takes the record n q o , and returns a disjoint union of allowed messages (with possible Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. :36 Fangyi Zhou, Francisco Ferreira, Raymond Hu, Rumyana Neykova, and Nobuko Yoshida side-effects). The constructor of of the disjoint union determines the label of the message, andtakes the payload as its parameter. The function signature is given by state q _send : ( st : n q o ) → ML Ú i ∈ I l i ( n T i o st ) Different from receiving callbacks, only one sending callback is generated for each sending state.This corresponds to the nature of internal choices, that the process implementing a sending prefixmakes a single selection; on the contrary, the process implementing a receiving prefix must beable to handle all branches.
Remark B.1 (Handlers and LTS Transitions).
If the callback returns a choice with the re-finements satisfied, the CFSM is able to make a transition to the next state. When a callback isprovided, against its prescribed type, then the type of the callback type is inhabited and we caninvoke the callback to obtain the label and the value of the payload. A callback function type maybe uninhabited, for instance, when none of the choices are applicable. In this case, the endpointcannot be implemented (we show an example below). If the developer provides a callback, then itmust be the case that the specified type is inhabited. In this way, we ensure the protocol is able tomake progress, and is not stuck due to empty value types . B.2.2 Connections.
The connection type is a record type with functions for sending and receivingbase types. The primitives for communications are collected in a record with fields as follows ( S range over base types int , bool , unit , etc.): send_ S : n P o → n S o → ML unit recv_ S : n P o → unit → ML n S o where n P o is a disjoint union of participants roles and n S o is the data type for S in the programminglanguage. The communication primitives do not use refinement types in the type signature. Wecan safely do so by exploiting the property that refinements can be erased at runtime after statictype-checking. B.2.3 State Records with Refinements.
We generate a type n q o for each state q ∈ Q in the CFSM.The type n q o is a record type corresponding to the local typing context in the state. For eachvariable in the local typing context, we define a field in the encoded record type, correspondingto the refinement type in the typing context. Since refinement types allow dependencies in thetyping context, we exploit the feature of dependent records in F ⋆ to encode the dependencies.We use the smallest typing context associated with the CFSM state for the generated record type.The typing context can be computed via a graph traversal of the CFSM, accumulating variables inthe local type prefix along the traversal. B.3 Verified Endpoint Implementation (User Input)
To implement an endpoint, a developer needs to provide a record of type callback , containingindividual callbacks for transitions, and a record of type connection , containing functions to sendand receive values of different base types. The two records are passed as arguments to the entrypoint function run to execute the protocol.The design of connection record gives freedom for the developer to implement any transportlayer satisfying first-in-first-out (FIFO) delivery without loss of messages. These assumptions ori-ginate from the network assumptions in MPST. TCP connections are a good candidate to connectthe participants in the protocol, since they satisfy the assumptions. Since we use a permissive ML effect in the callback type, the callback may throw exceptions or diverge in case of unableto return. Such behaviours are not in the scope of our interest when we talk about progress.Proc. ACM Program. Lang., Vol. 1, No. CONF, Article 1. Publication date: January 2018. tatically Verified Refinements for Multiparty Protocols 1:37 To satisfy the data dependencies as specified in the protocol, the provided callbacks must matchthe generated refinement type. The F ⋆ compiler utilises the Z3 SMT solver [De Moura and Bjørner2008] for type-checking, saving developers the need for manual proofs of arithmetic properties.After type-checking, the compiler can extract the F ⋆ code into OCaml (or other targets), wherethe refinements at the type level are erased. Developers can then compile the extracted OCamlprogram to execute the protocol.The resulting program has data dependencies verified by F ⋆ using refinement types. Moreover,the MPST theory guarantees that the endpoints are free for deadlocks or communication mis-matches, and conform to the global types.using refinement types. Moreover,the MPST theory guarantees that the endpoints are free for deadlocks or communication mis-matches, and conform to the global types.