├── tla ├── .gitignore ├── Atomic.tla └── Universal.tla ├── figures ├── connector.pdf ├── parallel-path.pdf ├── payment-chain.pdf ├── sender-trust.pdf ├── three-bells.pdf ├── atomic-sequence.pdf ├── recipient-trust.pdf ├── transfer-states.pdf ├── web-of-ledgers.pdf ├── connector-escrow.pdf ├── settlement-trust.pdf ├── universal-sequence.pdf ├── connector-execution.pdf ├── transfer-states.xml ├── connector-execution.xml ├── connector-escrow.xml ├── parallel-path.xml ├── three-bells.xml ├── sender-trust.xml ├── recipient-trust.xml ├── settlement-trust.xml ├── connector.xml ├── payment-chain.xml ├── web-of-ledgers.xml └── universal-sequence.xml ├── README.md ├── specs ├── ilpspec.sty ├── atomic.tex └── universal.tex ├── usenix.sty ├── interledger.bib └── acm.bst /tla/.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | *.toolbox 3 | -------------------------------------------------------------------------------- /figures/connector.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/connector.pdf -------------------------------------------------------------------------------- /figures/parallel-path.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/parallel-path.pdf -------------------------------------------------------------------------------- /figures/payment-chain.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/payment-chain.pdf -------------------------------------------------------------------------------- /figures/sender-trust.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/sender-trust.pdf -------------------------------------------------------------------------------- /figures/three-bells.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/three-bells.pdf -------------------------------------------------------------------------------- /figures/atomic-sequence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/atomic-sequence.pdf -------------------------------------------------------------------------------- /figures/recipient-trust.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/recipient-trust.pdf -------------------------------------------------------------------------------- /figures/transfer-states.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/transfer-states.pdf -------------------------------------------------------------------------------- /figures/web-of-ledgers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/web-of-ledgers.pdf -------------------------------------------------------------------------------- /figures/connector-escrow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/connector-escrow.pdf -------------------------------------------------------------------------------- /figures/settlement-trust.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/settlement-trust.pdf -------------------------------------------------------------------------------- /figures/universal-sequence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/universal-sequence.pdf -------------------------------------------------------------------------------- /figures/connector-execution.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interledger/paper/HEAD/figures/connector-execution.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Interledger Protocol White Paper 2 | This folder contains the files used to publish the ILP white paper that can be downloaded as a PDF from http://interledger.org 3 | 4 | ## Contributions 5 | Please feel free to log issues or submit PRs to the editors 6 | -------------------------------------------------------------------------------- /figures/transfer-states.xml: -------------------------------------------------------------------------------- 1 | zZbNctowEMefxnewSIFjoDS9dCZTDj0r9sbWRPZ6ZDlAnz6StUI2UOq0aY0PjPXXaj9+ixYiti72D4pX+TdMQUbxJN1H7HMUx/PlzHxa4eCE2eKTEzIlUidNg7AVP4HECamNSKHuGWpEqUXVFxMsS0h0T3tG2Q9R8cy7D8I24fJc/SFSnVPKE8rF6l9BZLkPE9PGE09eMoVNSeGimD23j9suuHfV2rON4aUQjRf7VuzXIC0zz8M5/fKL3WOOCkrK4/oBs2UPvHLZUJmPCiusIXUbtT74+ne50LCteGLXO9PPiK1yXUizmprX88iUzCsoDdTxVqJMHgAL0OpgTPwuEaNvg1/uAu2pp513SM9I49T07Og4FG5eqPbLHNgFDmCLGYXD3Xgg6EZ2QGz2kDR6FBDxcjwQd2cg7p/QJH4LHOb/kQNN5E69kJq5SEtTk9CH7yC5Flhuws6qnXiGloPQ4VFrhS+wRomq9ccm7XONVI2NaumGiaW5yoCs6PLavAZdr5M5wz6A0vzGKBGSLiW62UMpxSdD6CMoLa5SMrcrxwxLLkciRFf+XxBqndwrxe15b1ChKHXdifFohU4Af8/7AY6/5b8xX7h6Qm9c/NCpY0mDmre8oeZdGALvbN57hsAfNW/qPQ5r3qn53zXPLMN/SGce/oCzzRs= -------------------------------------------------------------------------------- /figures/connector-execution.xml: -------------------------------------------------------------------------------- 1 | 7VrNc+o2EP9rOD7GQsTAMaFpe2hn3jSH9h2NrdiaJywqTD76179da2XLNiae4IZMXjgAWq1Wuz+t90Mw4evt028m2mV/6kSoySxInib8l8lsxuZ8Dh9IebaURRhaQmpkQkw14U7+J4gYEPUgE7FvMBZaq0LumsRY57mIiwbtXqvmFrsodeJrwl0cqS71b5kUmaXyJemC9N+FTDO3jZvYRPH31OhDTttNZvy+fNnpbeRElfz8FgAzWoMU/LZ9WguFoDk8rNBfe2YrHY3ISY/TC2AKFzxE6kBmWsK+eHZ2wwLAEwY3j5ksxN0uinHmEY4UaFmxVTBi8LW7N6nzIEwh3KFXRoJXCL0VhXkGFprlhBn5AykfPNZ4z4mUeVA7WkSnnlZya8vhCxl/HAjeAeJO5IkwHTjAEtjWt3tfGP1drLXSBii5zhGre6lUixQpmeYwjAEfEMxvEBcJDnZNE1uZJLjNUaA1cN8r/QiUDPgELBgDcfcoEeLsqgu5c2Qfcncy50BOD78H+do+pwDaR0fdwXwB2K+OPPKhQnSLaANAQMTSBj0f58J/DxiKbsAc97WhZTUfgGYg2WOqT88Radk1TDr+wPI6G49MWWW+xFqpqAxDyFONvA3DlD6tLRsNWaVNBMdqURJEkzyhlkbO0pEOPgPeQWsBaFx+lkAw9YQwJHZVPteI231swKNHtKI8spHs6LoNPvtfSJny8Hu0WGdKDzic128wmpFNyqbD06v8qxYeVQyJxx4RpNsw4OgvRmIvRmL8HSdCuuhHAXJgfHS0c+IjlaB+BZRAIUhDyiplPSdwBYYpDwzxJIt/vO/fkGV6haMcFMEpXFEO6rlewPb6YMp8VNdqRWRSQVwLS0IFh4C6WE6hxoYqa7WYzRlfUQauklA/eCTyq5agYC1vNQ0ZCxm/YnzJliEpTfL4crqCd2ALYFe+IP2deGsaSfRL1NYmHIOLL3bVlGPx6Mgpj7mCYNDJE5rvpRhmi4tVwwSxh8RfIpY7icZ88NJstrpcacactqc8ME+uDeZvwE1F+72MWwEod43y3A86dqoKOnxRhaSvwkjQtCz4MDTFB/NQRrZGOJsGAYDmhTQGNZodtwX0HsKLYcqD2KHuQ+xoRqiokA/Nvnx41GJh84TbSWNoYGrLKaugAZEJji9Cax3bDhn2J/Rt5UJy0NqnrMDXRj323u4AWi3pG4Y9RrcA7yP3D83q4CDjpvX2pUAb2sGZ+wU542Vu1r1L+Gxqh3ZvA/umz6b2Ek3tjd58trQfo6WtMtnb97SMmtpTOV7JMrsl0sAVrNT4kECgR826tb37AWSsTmdJOao/5btUMnrK7zZ9f2Di/fBX0K2i8k3bnOVPink7Arwp6N2e/qfqLXtukxzcA1vP4UV030bnXn/9X10mb/nmeV0mDOsfsS17/RcAfvsD -------------------------------------------------------------------------------- /figures/connector-escrow.xml: -------------------------------------------------------------------------------- 1 | 7VrPc+o2EP5rOD7GRsTAMaFpe2hnMi+HtkdhK1jzhEVlkx/969+utbJlGxNPcJNXGg6AVtJq99P6065gwta7518M36e/60SoySxInifsp8lsFs7ZHD5Q8mIliyiygq2RCQ2qBffyH0HCgKQHmYi8MbDQWhVy3xTGOstEXDRkD1o1l9jzrVNfC+5jrrrSP2RSpFbKlmQLyn8Vcpu6ZVzHhsfftkYfMlpuMmMP5ct277hTVY5ntwCY0Rq04Lfd81ooBM3hYZX+3NNb2WhERnacngBdOOGRqwO5aQV58eL8hgmAJzRunlJZiPs9j7HnCbYUZGmxU9AK4Wt3bTLnUZhCuE2vnISoEHonCvMCQ6iXEWYUD2R88FTjPSdR6kHtZJx2fVvprT2HL+T8cSBYB4h7kSXCdOAAT2BZ3++8MPqbWGulDUgynSFWD1Kplogruc2gGQM+oJjdIC4SAuyaOnYySXCZo0BrGP2g9BNIUhgnYMIYiLtHiRAPr7qQu0D2IXc7cw7k9PB7kK/tcwqgXTrqDuYPgP3qyCMfKUS34BsAAhhLG4x87Iv+PiAV3YA77mvDyqo/AMtAszeo3j0npGnX0OnGB3as8/FIlzXmS6yV4iUN4Ziq5S0YbenT+rLRcKq0hRBYLUmCaFIk1NooWDraIWYgOmguAI3Tz1JYOntCHQq7Rp/rxm0eG4jpEf0Yz4tu2OCz/4VMKTe/x4Z1qvSAzXn7AqM52ZRsOmN6jX/TxKOGofDYI4JySwNO/ioTexyJ/DsOQzr2I4IcyI9Odg4/UgrqZ0AJJILUpFOlzOcEzkCa8sAQz7L40/v+Fw6ZXmErA0OwC2eUjbov4XlaasNp2LjjBYQgPnsAUzA/hWmuD6Y8sup0ruBmK2jUworQhyG4L5ZTSMMhEVstZvOQreiQrs6pfnxJ5Z2WYGCtbzWNwjAK2VXIluEyIqNJH1tOV/AOwwJYlS3IfqfeukYa/Sy2tQhDFvXVrpp6LB4dPWUkVBAMCg5C80fJl8PFhyXMBLGHxFcRy71EZy48e5utPi57C521pyIwS64NHvCAm+J5LuMWR2WulkZiqXjJdlW8xBYVa90JI8HSMidE9ooP5rGiq4rxpkEAoHmsF0IaZ9ttBYPIjLjGJzMSvUpm3ka4vfE3wsmMULyQj80Cfzi3Vc8RxUHU2t+h9FXZQ3rap1gPfcEec3TWDdvjgLzf3OpGwt22NK4G4ItV+FZqDH+0u4RWafuO3BjSbcJ/JocYmh1ADI2bHrTvH9roD84AXtEzXgYQdq8tPuvnoWXiwBLts37+iPr5Rm8+q+fLqJ6rw+79y+eQ6udTaYCS5QGYSAO3vVLjIwJEj5Z1awT3W8tYFdOSzqj+rMAdJaNnBd3i8Tc8eC/+truVd75rubT8n2LeZoB3Bb17N3BJNerQZLl9K+XKw4HF6fAkum+hc6/R/qU6lLVC87w6FJr1z+V2eP1nA3b7HQ== -------------------------------------------------------------------------------- /figures/parallel-path.xml: -------------------------------------------------------------------------------- 1 | 7Vtdd+I2E/41uUwOtgkkl4F3d3vRnrOnuWh76dgK6FQgXmHy0V+/I2vGliUMAhyT0r0BPJZG8/HMaEY2V8l08fZNpav5bzJn4ioe5G9Xyf+u4ng4voNPTXgnwq0hzBTPDSmqCY/8H4bEAVI3PGfrxsBCSlHwVZOYyeWSZUWD9ixFc4lVOiP2NeExS4VP/YPnxdxQkzuURdN/YXw2x2XiGG+si3dikbPndCOK65IE9/TtRUqsyvHJF7CXkhK46F+LtykT2mZkD8P0a8vdSkbFlijH7gmJmfCSig3K+MiWOVOe6AV7A4aTebEQQIjg57pQ8m82lUIqoCzlEkZOnrkQDikVfLaEywxEAsbJ5IWpgoNdH/DGgue5XmbyOucFe1ylmV7zFRADNAmjn4V8BcocxjGYMPGVRL01Z4bgKkmo9DcmF6xQ7zCE7qJzEHjXCV6/1p4lx85tpyItRXzNKsa1jeEHmnm7yYeeyacGnlKtL97st+ezO6YWy+5X8Uho6xbpExgiHjxJpaGv743+v9EhOAF16GdDyur+ACQDztag2ntExGkPcJPGD8xY0nHLLSPMdSaFSFdrYKjHVFfWgqMZfhtdniRkU5cI8exQcm1NRELNDcHicQfMADpwLhhaTz+JYansDnaa6At9qhrTuZCdqtGdEj5qdOhfoyil71uVUhwSxz6ljl+gMyWblCdvTKvwR03cKpgmbosQTTdZgOh7E7GVInX67SZBUvKj/BgFJkiinZIgR57SLIcKCC9xW1FyA/WBnqHzlGUO0Fm9/4n08uIvfXFzu8swRapmDEljQ9JrhlhqfHcTj0dxMrgfx8MoucdttTLcCPP9Nosg0++Sgzz15kS7TCuPtdyojOE0u6pyOCU6uzU4DVFh4mQU9ziVLqp0DfLavbet/c4yvuLa1BdeTcT356smIpLWLifc8FnmD0qVamciXa955oYM9TRDO4CqaDIBlEBThITvTHGQtKxRdJhlG/VSxmI55Y0X5fSbwQCMVl4bDhGUFebaZdDqBIP0RuFkxyqS9saq5Qiq/GxHEE0xkRb8pdlohQduPHTDzfVwaOBWElWcKJL3BC74OdUK07CVHlCW8y25ZuwuhB1JDT/D8ti0EGFnd2w2JzA1gGSAWIEamQDla7kB7oZUaGKPo84zu9fuRYSYgwEy2rdHdJfZI79T/NmxnK3U144/Q8MSVNuHM9S4P3vHMpFPP/uVy+hXqlrqHA1LhC2DlSB/1bvMxZ9eul1in3UvHtn/52zuIb1Ho2/rLfpszUmH0BJutLuCiwdn7M0jr4JzU1F3FRw9Xvk8Rbjd1x3qVcD3brdGhxfmnluppf/MhfnWRwkH9v6109s93d63t50VjMyMbWcFl9Hqew+Q6PpgvHhHdB/V6XtHurhQV50+HZxe6ElUaHbyz1yJEIjMcBC2L3XyQXHgXnQoCBP3AATTbGcY9KvCf3FGPB5ytJ31ALljjzh7g5y3tXed9/wnHx7mZgCqVUulX70WVPbR1rsyPiR2IMCtJXG7tABQGcJGgHv+eFRXEBBzQsC7UG2dkhV8vuKVefd3SJaypFfXukafRlmqHyhselA+CVHe6whCGwmvbXDS33ZLNRqJc1aETkEYoXyHpkXnUaKbXbtrHpJtp/qHl2votbD2PsijdtFvwi34LISM3vm25ybYo5/rOUW4i5IO3YsLnXNX8h4uVs+/ekhWJO4HZerKvp9iW6qOEXcoK3iZjnOuwKtc6vNLgK2WzD8bpReLT9a9apc9vxMUOt+kAkzRO/Crw74esBDShp+A+/AD6z7KMXxXrCfcH/Ge8UfhHi7rt/PN/lD/tSH58gM= -------------------------------------------------------------------------------- /specs/ilpspec.sty: -------------------------------------------------------------------------------- 1 | 2 | % 3 | % USENIX wants margins of: 1" sides, 1" bottom, and 1" top. 4 | % 0.25" gutter between columns. 5 | % Gives active areas of 6.5" x 9" 6 | % 7 | \setlength{\textheight}{9.0in} 8 | \setlength{\columnsep}{0.25in} 9 | \setlength{\textwidth}{6.50in} 10 | 11 | \setlength{\topmargin}{0.0in} 12 | 13 | \setlength{\headheight}{0.0in} 14 | 15 | \setlength{\headsep}{0.0in} 16 | 17 | % Usenix wants no page numbers for camera-ready papers, so that they can 18 | % number them themselves. But submitted papers should have page numbers 19 | % for the reviewers' convenience. 20 | % 21 | % 22 | % \pagestyle{empty} 23 | 24 | % 25 | % Usenix titles are in 14-point bold type, with no date, and with no 26 | % change in the empty page headers. The whole author section is 12 point 27 | % italic--- you must use {\rm } around the actual author names to get 28 | % them in roman. 29 | % 30 | \def\maketitle{\par 31 | \begingroup 32 | \renewcommand\thefootnote{\fnsymbol{footnote}}% 33 | \def\@makefnmark{\hbox to\z@{$\m@th^{\@thefnmark}$\hss}}% 34 | \long\def\@makefntext##1{\parindent 1em\noindent 35 | \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}% 36 | \if@twocolumn 37 | \twocolumn[\@maketitle]% 38 | \else \newpage 39 | \global\@topnum\z@ 40 | \@maketitle \fi\@thanks 41 | \endgroup 42 | \setcounter{footnote}{0}% 43 | \let\maketitle\relax 44 | \let\@maketitle\relax 45 | \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\thanks\relax} 46 | 47 | \def\@maketitle{\newpage 48 | \vbox to 2.5in{ 49 | \vspace*{\fill} 50 | \vskip 2em 51 | \begin{center}% 52 | {\Large\bf \@title \par}% 53 | \vskip 0.375in minus 0.300in 54 | {\large\it 55 | \lineskip .5em 56 | \begin{tabular}[t]{c}\@author 57 | \end{tabular}\par}% 58 | \end{center}% 59 | \par 60 | \vspace*{\fill} 61 | % \vskip 1.5em 62 | } 63 | } 64 | 65 | % 66 | % The abstract is preceded by a 12-pt bold centered heading 67 | \def\abstract{\begin{center}% 68 | {\large\bf \abstractname\vspace{-.5em}\vspace{\z@}}% 69 | \end{center}} 70 | \def\endabstract{} 71 | 72 | % 73 | % Main section titles are 12-pt bold. Others can be same or smaller. 74 | % 75 | \def\section{\@startsection {section}{1}{\z@}{-3.5ex plus-1ex minus 76 | -.2ex}{2.3ex plus.2ex}{\reset@font\large\bf}} 77 | -------------------------------------------------------------------------------- /figures/three-bells.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /figures/sender-trust.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /figures/recipient-trust.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /usenix.sty: -------------------------------------------------------------------------------- 1 | % usenix.sty - to be used with latex2e for USENIX. 2 | % To use this style file, look at the template usenix_template.tex 3 | % 4 | % $Id: usenix.sty,v 1.2 2005/02/16 22:30:47 maniatis Exp $ 5 | % 6 | % The following definitions are modifications of standard article.sty 7 | % definitions, arranged to do a better job of matching the USENIX 8 | % guidelines. 9 | % It will automatically select two-column mode and the Times-Roman 10 | % font. 11 | 12 | % 13 | % USENIX papers are two-column. 14 | % Times-Roman font is nice if you can get it (requires NFSS, 15 | % which is in latex2e. 16 | 17 | \if@twocolumn\fi 18 | \usepackage{mathptmx} % times roman, including math (where possible) 19 | 20 | % 21 | % USENIX wants margins of: 1" sides, 1" bottom, and 1" top. 22 | % 0.25" gutter between columns. 23 | % Gives active areas of 6.5" x 9" 24 | % 25 | \setlength{\textheight}{9.0in} 26 | \setlength{\columnsep}{0.25in} 27 | \setlength{\textwidth}{6.50in} 28 | 29 | \setlength{\topmargin}{0.0in} 30 | 31 | \setlength{\headheight}{0.0in} 32 | 33 | \setlength{\headsep}{0.0in} 34 | 35 | % Usenix wants no page numbers for camera-ready papers, so that they can 36 | % number them themselves. But submitted papers should have page numbers 37 | % for the reviewers' convenience. 38 | % 39 | % 40 | % \pagestyle{empty} 41 | 42 | % 43 | % Usenix titles are in 14-point bold type, with no date, and with no 44 | % change in the empty page headers. The whole author section is 12 point 45 | % italic--- you must use {\rm } around the actual author names to get 46 | % them in roman. 47 | % 48 | \def\maketitle{\par 49 | \begingroup 50 | \renewcommand\thefootnote{\fnsymbol{footnote}}% 51 | \def\@makefnmark{\hbox to\z@{$\m@th^{\@thefnmark}$\hss}}% 52 | \long\def\@makefntext##1{\parindent 1em\noindent 53 | \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}% 54 | \if@twocolumn 55 | \twocolumn[\@maketitle]% 56 | \else \newpage 57 | \global\@topnum\z@ 58 | \@maketitle \fi\@thanks 59 | \endgroup 60 | \setcounter{footnote}{0}% 61 | \let\maketitle\relax 62 | \let\@maketitle\relax 63 | \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\thanks\relax} 64 | 65 | \def\@maketitle{\newpage 66 | \vbox to 2.5in{ 67 | \vspace*{\fill} 68 | \vskip 2em 69 | \begin{center}% 70 | {\Large\bf \@title \par}% 71 | \vskip 0.375in minus 0.300in 72 | {\large\it 73 | \lineskip .5em 74 | \begin{tabular}[t]{c}\@author 75 | \end{tabular}\par}% 76 | \end{center}% 77 | \par 78 | \vspace*{\fill} 79 | % \vskip 1.5em 80 | } 81 | } 82 | 83 | % 84 | % The abstract is preceded by a 12-pt bold centered heading 85 | \def\abstract{\begin{center}% 86 | {\large\bf \abstractname\vspace{-.5em}\vspace{\z@}}% 87 | \end{center}} 88 | \def\endabstract{} 89 | 90 | % 91 | % Main section titles are 12-pt bold. Others can be same or smaller. 92 | % 93 | \def\section{\@startsection {section}{1}{\z@}{-3.5ex plus-1ex minus 94 | -.2ex}{2.3ex plus.2ex}{\reset@font\large\bf}} 95 | 96 | % 97 | % Shortcut for typesetting tuples 98 | % 99 | \newcommand{\tuple}[1]{\langle #1 \rangle} -------------------------------------------------------------------------------- /figures/settlement-trust.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /figures/connector.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /interledger.bib: -------------------------------------------------------------------------------- 1 | @article{Bitcoin, 2 | abstract = {A purely peer-to-peer version of electronic cash would allow online 3 | payments to be sent directly from one party to another without going through a 4 | financial institution. Digital signatures provide part of the solution, but the main benefits are lost if a trusted third party is still required to prevent double-spending. 5 | We propose a solution to the double-spending problem using a peer-to-peer network. The network timestamps transactions by hashing them into an ongoing chain of hash-based proof-of-work, forming a record that cannot be changed without redoing the proof-of-work. The longest chain not only serves as proof of the sequence of events witnessed, but proof that it came from the largest pool of {CPU} power. As long as a majority of {CPU} power is controlled by nodes that are not cooperating to attack the network, they'll generate the longest chain and outpace attackers. The network itself requires minimal structure. Messages are broadcast on a best effort 6 | basis, and nodes can leave and rejoin the network at will, accepting the longest proof-of-work chain as proof of what happened while they were gone.}, 7 | author = {Nakamoto, Satoshi}, 8 | keywords = {bitcoin, cryptographic\_protocols, cryptography, electronic\_cash\_system, electronic\_commerce, hashcash, peer\_to\_peer\_network, proof\_of\_work}, 9 | posted-at = {2011-01-01 14:24:54}, 10 | priority = {0}, 11 | title = {Bitcoin: A {Peer-to-Peer} Electronic Cash System}, 12 | url = {http:bitcoin.org/bitcoin.pdf} 13 | } 14 | @article{1_mohan_lindsay_1985, 15 | author={Mohan, C. and Lindsay, B.}, 16 | title={Efficient Commit Protocols for the Tree of Processes Model of Distributed Transactions}, 17 | volume={19}, 18 | url={http://doi.acm.org/10.1145/850770.850772}, 19 | number={2}, 20 | journal={SIGOPS Oper. Syst. Rev.}, 21 | year={1985}, 22 | pages={40--52} 23 | }, 24 | 25 | @article{2_reed_1983, 26 | author={Reed, David P.}, 27 | title={Implementing Atomic Actions on Decentralized Data}, 28 | volume={1}, 29 | url={http://doi.acm.org/10.1145/357353.357355}, 30 | number={1}, 31 | journal={ACM Trans. Comput. Syst.}, 32 | year={1983}, 33 | pages={3--23} 34 | } 35 | @inproceedings{Gray:1978:NDB:647433.723863, 36 | author = {Gray, Jim}, 37 | title = {Notes on Data Base Operating Systems}, 38 | booktitle = {Operating Systems, An Advanced Course}, 39 | year = {1978}, 40 | isbn = {3-540-08755-9}, 41 | pages = {393--481}, 42 | numpages = {89}, 43 | url = {http://dl.acm.org/citation.cfm?id=647433.723863}, 44 | acmid = {723863}, 45 | publisher = {Springer-Verlag}, 46 | address = {London, UK, UK}, 47 | } 48 | 49 | @inproceedings{chaum1990untraceable, 50 | title={Untraceable electronic cash}, 51 | author={Chaum, David and Fiat, Amos and Naor, Moni}, 52 | booktitle={Proceedings on Advances in cryptology}, 53 | pages={319--327}, 54 | year={1990}, 55 | organization={Springer-Verlag New York, Inc.} 56 | } 57 | 58 | @inproceedings{rompel1990one, 59 | title={One-way functions are necessary and sufficient for secure signatures}, 60 | author={Rompel, John}, 61 | booktitle={Proceedings of the twenty-second annual ACM symposium on Theory of computing}, 62 | pages={387--394}, 63 | year={1990}, 64 | organization={ACM} 65 | } 66 | 67 | @article{black1973pricing, 68 | title={The pricing of options and corporate liabilities}, 69 | author={Black, Fischer and Scholes, Myron}, 70 | journal={The journal of political economy}, 71 | pages={637--654}, 72 | year={1973}, 73 | publisher={JSTOR} 74 | } 75 | 76 | @inproceedings{castro1999practical, 77 | title={Practical Byzantine fault tolerance}, 78 | author={Castro, Miguel and Liskov, Barbara and others}, 79 | booktitle={OSDI}, 80 | volume={99}, 81 | pages={173--186}, 82 | year={1999} 83 | } 84 | 85 | @article{back2014enabling, 86 | title={Enabling blockchain innovations with pegged sidechains}, 87 | author={Back, Adam and Corallo, Matt and Dashjr, Luke and Friedenbach, Mark and Maxwell, Gregory and Miller, Andrew and Poelstra, Andrew and Tim{\'o}n, Jorge and Wuille, Pieter}, 88 | journal={URL: http://www. opensciencereview. com/papers/123/enablingblockchain-innovations-with-pegged-sidechains}, 89 | year={2014} 90 | } 91 | 92 | @article{alpern1985defining, 93 | title={Defining liveness}, 94 | author={Alpern, Bowen and Schneider, Fred B}, 95 | journal={Information processing letters}, 96 | volume={21}, 97 | number={4}, 98 | pages={181--185}, 99 | year={1985}, 100 | publisher={Elsevier} 101 | } 102 | 103 | @article{brennan1977valuation, 104 | title={The valuation of American put options}, 105 | author={Brennan, Michael J and Schwartz, Eduardo S}, 106 | journal={Journal of Finance}, 107 | pages={449--462}, 108 | year={1977}, 109 | publisher={JSTOR} 110 | } 111 | 112 | @article{gray2006consensus, 113 | title={Consensus on transaction commit}, 114 | author={Gray, Jim and Lamport, Leslie}, 115 | journal={ACM Transactions on Database Systems (TODS)}, 116 | volume={31}, 117 | number={1}, 118 | pages={133--160}, 119 | year={2006}, 120 | publisher={ACM} 121 | } 122 | 123 | @article{copelandtangaroa, 124 | title={Tangaroa: a Byzantine Fault Tolerant Raft}, 125 | author={Copeland, Christopher and Zhong, Hongxia} 126 | } 127 | 128 | @article{dwork1988consensus, 129 | title={Consensus in the presence of partial synchrony}, 130 | author={Dwork, Cynthia and Lynch, Nancy and Stockmeyer, Larry}, 131 | journal={Journal of the ACM (JACM)}, 132 | volume={35}, 133 | number={2}, 134 | pages={288--323}, 135 | year={1988}, 136 | publisher={ACM} 137 | } 138 | 139 | @inproceedings{mohan1983method, 140 | title={Method for distributed transaction commit and recovery using Byzantine agreement within clusters of processors}, 141 | author={Mohan, C and Strong, R and Finkelstein, Shel}, 142 | booktitle={Proceedings of the second annual ACM symposium on Principles of distributed computing}, 143 | pages={89--103}, 144 | year={1983}, 145 | organization={ACM} 146 | } 147 | 148 | @techreport{ahuja1988network, 149 | title={Network flows}, 150 | author={Ahuja, Ravindra K and Magnanti, Thomas L and Orlin, James B}, 151 | year={1988}, 152 | institution={DTIC Document}, 153 | pages={97--152} 154 | } 155 | 156 | @article{wagner1959class, 157 | title={On a class of capacitated transportation problems}, 158 | author={Wagner, Harvey M}, 159 | journal={Management Science}, 160 | volume={5}, 161 | number={3}, 162 | pages={304--318}, 163 | year={1959}, 164 | publisher={INFORMS} 165 | } 166 | 167 | @article{cai2001time, 168 | title={Time-varying minimum cost flow problems}, 169 | author={Cai, X and Sha, D and Wong, CK}, 170 | journal={European Journal of Operational Research}, 171 | volume={131}, 172 | number={2}, 173 | pages={352--374}, 174 | year={2001}, 175 | publisher={Elsevier} 176 | } 177 | 178 | @article{dolev1983authenticated, 179 | title={Authenticated algorithms for Byzantine agreement}, 180 | author={Dolev, Danny and Strong, H. Raymond}, 181 | journal={SIAM Journal on Computing}, 182 | volume={12}, 183 | number={4}, 184 | pages={656--666}, 185 | year={1983}, 186 | publisher={SIAM} 187 | } 188 | 189 | @article{schwartz2014ripple, 190 | title={The Ripple protocol consensus algorithm}, 191 | author={Schwartz, David and Youngs, Noah and Britto, Arthur}, 192 | journal={Ripple Labs Inc White Paper}, 193 | year={2014} 194 | } 195 | 196 | @article{mazieresstellar, 197 | title={The Stellar Consensus Protocol: A Federated Model for Internet-level Consensus}, 198 | author={Mazi{\`e}res, David} 199 | } 200 | 201 | @article{poonbitcoin, 202 | title={The Bitcoin Lightning Network}, 203 | author={Poon, Joseph and Dryja, Thaddeus} 204 | } 205 | 206 | @misc{wood2014ethereum, 207 | title={ETHEREUM: A SECURE DECENTRALISED GENERALISED TRANSACTION LEDGER}, 208 | author={WOOD, DR GAVIN}, 209 | year={2014}, 210 | publisher={Ethereum} 211 | } 212 | 213 | @book{davies1989security, 214 | title={Security for computer networks: and introduction to data security in teleprocessing and electronic funds transfer}, 215 | author={Davies, Donald Watts and Price, Wyn L}, 216 | year={1989}, 217 | publisher={John Wiley \& Sons, Inc.} 218 | } 219 | 220 | @inproceedings{aiyer2005bar, 221 | title={BAR fault tolerance for cooperative services}, 222 | author={Aiyer, Amitanand S and Alvisi, Lorenzo and Clement, Allen and Dahlin, Mike and Martin, Jean-Philippe and Porth, Carl}, 223 | booktitle={ACM SIGOPS Operating Systems Review}, 224 | volume={39}, 225 | number={5}, 226 | pages={45--58}, 227 | year={2005}, 228 | organization={ACM} 229 | } 230 | 231 | @article{lamport1982byzantine, 232 | title={The Byzantine generals problem}, 233 | author={Lamport, Leslie and Shostak, Robert and Pease, Marshall}, 234 | journal={ACM Transactions on Programming Languages and Systems (TOPLAS)}, 235 | volume={4}, 236 | number={3}, 237 | pages={382--401}, 238 | year={1982}, 239 | publisher={ACM} 240 | } 241 | 242 | @article{watts1998collective, 243 | title={Collective dynamics of ‘small-world’networks}, 244 | author={Watts, Duncan J and Strogatz, Steven H}, 245 | journal={nature}, 246 | volume={393}, 247 | number={6684}, 248 | pages={440--442}, 249 | year={1998}, 250 | publisher={Nature Publishing Group} 251 | } 252 | 253 | @article{albert1999internet, 254 | title={Internet: Diameter of the world-wide web}, 255 | author={Albert, R{\'e}ka and Jeong, Hawoong and Barab{\'a}si, Albert-L{\'a}szl{\'o}}, 256 | journal={Nature}, 257 | volume={401}, 258 | number={6749}, 259 | pages={130--131}, 260 | year={1999}, 261 | publisher={Nature Publishing Group} 262 | } 263 | 264 | @article{bracha1985asynchronous, 265 | title={Asynchronous consensus and broadcast protocols}, 266 | author={Bracha, Gabriel and Toueg, Sam}, 267 | journal={Journal of the ACM (JACM)}, 268 | volume={32}, 269 | number={4}, 270 | pages={824--840}, 271 | year={1985}, 272 | publisher={ACM} 273 | } -------------------------------------------------------------------------------- /figures/payment-chain.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tla/Atomic.tla: -------------------------------------------------------------------------------- 1 | ------------------------------- MODULE Atomic ------------------------------- 2 | (***************************************************************************) 3 | (* Formal Specification in TLA^+ of the *) 4 | (* Interledger Protocol Atomic (ILP/A) *) 5 | (* *) 6 | (*`. *) 7 | (* Modeled after the excellent Raft specification by Diego Ongaro. *) 8 | (* Available at https://github.com/ongardie/raft.tla *) 9 | (* *) 10 | (* Copyright 2014 Diego Ongaro. *) 11 | (* This work is licensed under the Creative Commons Attribution-4.0 *) 12 | (* International License https://creativecommons.org/licenses/by/4.0/ .'*) 13 | (***************************************************************************) 14 | 15 | EXTENDS Naturals, Sequences, Bags, TLC 16 | 17 | \* The set of ledger IDs 18 | CONSTANTS Ledger 19 | 20 | \* The set of participant IDs 21 | CONSTANTS Participant 22 | 23 | \* The notary 24 | CONSTANTS Notary 25 | 26 | \* Sender states 27 | CONSTANTS S_Ready, S_Waiting, S_Done 28 | 29 | \* Notary states 30 | CONSTANTS N_Waiting, N_Committed, N_Aborted 31 | 32 | \* Notary decisions 33 | CONSTANTS D_Execute, D_Abort 34 | 35 | \* Ledger states 36 | CONSTANTS L_Proposed, L_Prepared, L_Executed, L_Aborted 37 | 38 | \* Message types 39 | CONSTANTS M_PrepareRequest, M_ExecuteRequest, M_AbortRequest, 40 | M_PrepareNotify, M_ExecuteNotify, M_AbortNotify, 41 | M_SubmitReceiptRequest 42 | 43 | \* Receipt signature 44 | CONSTANTS R_ReceiptSignature 45 | 46 | ---- 47 | \* Global variables 48 | 49 | \* A bag of records representing requests and responses sent from one process 50 | \* to another 51 | VARIABLE messages 52 | 53 | ---- 54 | \* Sender variables 55 | 56 | \* State of the sender (S_Ready, S_Waiting, S_Done) 57 | VARIABLE senderState 58 | 59 | \* All sender variables 60 | senderVars == <> 61 | ---- 62 | \* The following variables are all per ledger (functions with domain Ledger) 63 | 64 | \* The ledger state (L_Proposed, L_Prepared, L_Executed or L_Aborted) 65 | VARIABLE ledgerState 66 | 67 | \* All ledger variables 68 | ledgerVars == <> 69 | ---- 70 | \* Notary variables 71 | 72 | \* State of the notary (N_Waiting, N_Committed, N_Aborted) 73 | VARIABLE notaryState 74 | 75 | \* All notary variables 76 | notaryVars == <> 77 | ---- 78 | 79 | \* All variables; used for stuttering (asserting state hasn't changed) 80 | vars == <> 81 | 82 | ---- 83 | \* Helpers 84 | 85 | \* Add a set of new messages in transit 86 | Broadcast(m) == messages' = messages (+) SetToBag(m) 87 | 88 | \* Add a message to the bag of messages 89 | Send(m) == Broadcast({m}) 90 | 91 | \* Remove a message from the bag of messages. Used when a process is done 92 | \* processing a message. 93 | Discard(m) == messages' = messages (-) SetToBag({m}) 94 | 95 | \* Respond to a message by sending multiple messages 96 | ReplyBroadcast(responses, request) == 97 | messages' = messages (-) SetToBag({request}) (+) SetToBag(responses) 98 | 99 | \* Combination of Send and Discard 100 | Reply(response, request) == 101 | ReplyBroadcast({response}, request) 102 | 103 | 104 | \* Return the minimum value from a set, or undefined if the set is empty. 105 | Min(s) == CHOOSE x \in s : \A y \in s : x <= y 106 | \* Return the maximum value from a set, or undefined if the set is empty. 107 | Max(s) == CHOOSE x \in s : \A y \in s : x >= y 108 | 109 | \* Is a final ledger state 110 | IsFinalLedgerState(i) == i \in {L_Executed, L_Aborted} 111 | 112 | \* Sender 113 | Sender == Min(Participant) 114 | 115 | \* Recipient 116 | Recipient == Max(Participant) 117 | 118 | \* Set of connectors 119 | Connector == Participant \ {Sender, Recipient} 120 | 121 | ---- 122 | \* Define type specification for all variables 123 | 124 | TypeOK == /\ IsABag(messages) 125 | /\ senderState \in {S_Ready, S_Waiting, S_Done} 126 | /\ ledgerState \in [Ledger -> {L_Proposed, L_Prepared, L_Executed, L_Aborted}] 127 | 128 | Consistency == 129 | \A l1, l2 \in Ledger : \lnot /\ ledgerState[l1] = L_Aborted 130 | /\ ledgerState[l2] = L_Executed 131 | 132 | Inv == /\ TypeOK 133 | /\ Consistency 134 | 135 | ---- 136 | \* Define initial values for all variables 137 | 138 | InitSenderVars == /\ senderState = S_Ready 139 | 140 | InitLedgerVars == /\ ledgerState = [i \in Ledger |-> L_Proposed] 141 | 142 | InitNotaryVars == /\ notaryState = N_Waiting 143 | 144 | Init == /\ messages = EmptyBag 145 | /\ InitSenderVars 146 | /\ InitLedgerVars 147 | /\ InitNotaryVars 148 | 149 | ---- 150 | \* Define state transitions 151 | 152 | \* Participant i starts off the chain 153 | Start(i) == 154 | /\ senderState = S_Ready 155 | /\ senderState' = S_Waiting 156 | /\ Send([mtype |-> M_PrepareRequest, 157 | msource |-> i, 158 | mdest |-> i+1]) 159 | /\ UNCHANGED <> 160 | 161 | \* Notary times out 162 | NotaryTimeout == 163 | /\ notaryState = N_Waiting 164 | /\ notaryState' = N_Aborted 165 | /\ Broadcast( 166 | {[mtype |-> M_AbortRequest, 167 | msource |-> Notary, 168 | mdest |-> k, 169 | msig |-> D_Abort] : k \in Ledger}) 170 | /\ UNCHANGED <> 171 | 172 | \* Ledger spontaneously aborts 173 | LedgerAbort(l) == 174 | /\ ledgerState[l] = L_Proposed 175 | /\ ledgerState' = [ledgerState EXCEPT ![l] = L_Aborted] 176 | /\ Send([mtype |-> M_AbortNotify, 177 | msource |-> l, 178 | mdest |-> l-1]) 179 | /\ UNCHANGED <> 180 | 181 | ---- 182 | \* Message handlers 183 | \* i = recipient, j = sender, m = message 184 | 185 | \* Ledger i receives a Prepare request from process j 186 | LedgerHandlePrepareRequest(i, j, m) == 187 | LET valid == /\ ledgerState[i] = L_Proposed 188 | /\ j = i - 1 189 | IN \/ /\ valid 190 | /\ ledgerState' = [ledgerState EXCEPT ![i] = L_Prepared] 191 | /\ Reply([mtype |-> M_PrepareNotify, 192 | msource |-> i, 193 | mdest |-> i+1], m) 194 | /\ UNCHANGED <> 195 | \/ /\ \lnot valid 196 | /\ Discard(m) 197 | /\ UNCHANGED <> 198 | 199 | \* Ledger i receives an Execute request from process j 200 | LedgerHandleExecuteRequest(i, j, m) == 201 | LET valid == /\ ledgerState[i] = L_Prepared 202 | /\ m.msig = D_Execute 203 | IN \/ /\ valid 204 | /\ ledgerState' = [ledgerState EXCEPT ![i] = L_Executed] 205 | /\ Reply([mtype |-> M_ExecuteNotify, 206 | msource |-> i, 207 | mdest |-> i-1], m) 208 | /\ UNCHANGED <> 209 | \/ /\ \lnot valid 210 | /\ Discard(m) 211 | /\ UNCHANGED <> 212 | 213 | \* Ledger i receives an Abort request from process j 214 | LedgerHandleAbortRequest(i, j, m) == 215 | LET valid == /\ ledgerState[i] \in { L_Proposed, L_Prepared } 216 | /\ m.msig = D_Abort 217 | IN \/ /\ valid 218 | /\ ledgerState' = [ledgerState EXCEPT ![i] = L_Aborted] 219 | /\ Reply([mtype |-> M_AbortNotify, 220 | msource |-> i, 221 | mdest |-> i-1], m) 222 | /\ UNCHANGED <> 223 | \/ /\ \lnot valid 224 | /\ Discard(m) 225 | /\ UNCHANGED <> 226 | 227 | \* Ledger i receives a message 228 | LedgerReceive(i, j, m) == 229 | \/ /\ m.mtype = M_PrepareRequest 230 | /\ LedgerHandlePrepareRequest(i, j, m) 231 | \/ /\ m.mtype = M_ExecuteRequest 232 | /\ LedgerHandleExecuteRequest(i, j, m) 233 | \/ /\ m.mtype = M_AbortRequest 234 | /\ LedgerHandleAbortRequest(i, j, m) 235 | 236 | \* Ledger j notifies sender that the transfer is executed 237 | SenderHandleExecuteNotify(i, j, m) == 238 | \/ /\ senderState = S_Waiting 239 | /\ senderState' = S_Done 240 | /\ Discard(m) 241 | /\ UNCHANGED <> 242 | \/ /\ senderState # S_Waiting 243 | /\ Discard(m) 244 | /\ UNCHANGED <> 245 | 246 | \* Ledger j notifies sender that the transfer is aborted 247 | SenderHandleAbortNotify(i, j, m) == 248 | LET isSenderWaiting == senderState \in { S_Waiting, S_Ready } 249 | IN \/ /\ isSenderWaiting 250 | /\ senderState' = S_Done 251 | /\ Discard(m) 252 | /\ UNCHANGED <> 253 | \/ /\ \lnot isSenderWaiting 254 | /\ Discard(m) 255 | /\ UNCHANGED <> 256 | 257 | \* Sender receives a message 258 | SenderReceive(i, j, m) == 259 | \/ /\ m.mtype = M_ExecuteNotify 260 | /\ SenderHandleExecuteNotify(i, j, m) 261 | \/ /\ m.mtype = M_AbortNotify 262 | /\ SenderHandleAbortNotify(i, j, m) 263 | 264 | \* Ledger j notifies recipient that the transfer is prepared 265 | RecipientHandlePrepareNotify(i, j, m) == 266 | /\ Reply([mtype |-> M_SubmitReceiptRequest, 267 | msource |-> i, 268 | mdest |-> Notary, 269 | mreceipt |-> R_ReceiptSignature], m) 270 | /\ UNCHANGED <> 271 | 272 | \* Recipient receives a message 273 | RecipientReceive(i, j, m) == 274 | /\ m.mtype = M_PrepareNotify 275 | /\ RecipientHandlePrepareNotify(i, j, m) 276 | 277 | \* Ledger j notifies connector i that the transfer is prepared 278 | ConnectorHandlePrepareNotify(i, j, m) == 279 | /\ Reply([mtype |-> M_PrepareRequest, 280 | msource |-> i, 281 | mdest |-> i+1], m) 282 | /\ UNCHANGED <> 283 | 284 | \* Ledger j notifies connector i that the transfer is executed 285 | ConnectorHandleExecuteNotify(i, j, m) == 286 | /\ Discard(m) 287 | /\ UNCHANGED <> 288 | 289 | \* Ledger j notifies connector i that the transfer is aborted 290 | ConnectorHandleAbortNotify(i, j, m) == 291 | /\ Discard(m) 292 | /\ UNCHANGED <> 293 | 294 | \* Connector receives a message 295 | ConnectorReceive(i, j, m) == 296 | \/ /\ m.mtype = M_PrepareNotify 297 | /\ ConnectorHandlePrepareNotify(i, j, m) 298 | \/ /\ m.mtype = M_ExecuteNotify 299 | /\ ConnectorHandleExecuteNotify(i, j, m) 300 | \/ /\ m.mtype = M_AbortNotify 301 | /\ ConnectorHandleAbortNotify(i, j, m) 302 | 303 | \* Notary receives a signed receipt 304 | NotaryHandleSubmitReceiptRequest(i, j, m) == 305 | \/ /\ m.mreceipt = R_ReceiptSignature 306 | /\ notaryState = N_Waiting 307 | /\ notaryState' = N_Committed 308 | /\ ReplyBroadcast( 309 | {[mtype |-> M_ExecuteRequest, 310 | msource |-> i, 311 | mdest |-> k, 312 | msig |-> D_Execute] : k \in Ledger}, m) 313 | /\ UNCHANGED <> 314 | \/ /\ notaryState # N_Waiting 315 | /\ Discard(m) 316 | /\ UNCHANGED <> 317 | 318 | \* Notary receives a message 319 | NotaryReceive(i, j, m) == 320 | /\ m.mtype = M_SubmitReceiptRequest 321 | /\ NotaryHandleSubmitReceiptRequest(i, j, m) 322 | 323 | \* Receive a message 324 | Receive(m) == 325 | LET i == m.mdest 326 | j == m.msource 327 | IN \/ /\ i \in Ledger 328 | /\ LedgerReceive(i, j, m) 329 | \/ /\ i = Sender 330 | /\ SenderReceive(i, j, m) 331 | \/ /\ i = Recipient 332 | /\ RecipientReceive(i, j, m) 333 | \/ /\ i \in Connector 334 | /\ ConnectorReceive(i, j, m) 335 | \/ /\ i = Notary 336 | /\ NotaryReceive(i, j, m) 337 | 338 | \* End of message handlers 339 | ---- 340 | \* Defines how the variables may transition 341 | 342 | Termination == 343 | /\ \A l \in Ledger : IsFinalLedgerState(ledgerState[l]) 344 | /\ senderState = S_Done 345 | /\ UNCHANGED vars 346 | 347 | Next == \/ Start(Sender) 348 | \/ NotaryTimeout 349 | \/ \E l \in Ledger : LedgerAbort(l) 350 | \/ \E m \in DOMAIN messages : Receive(m) 351 | \/ Termination 352 | 353 | \* The specification must start with the initial state and transition according 354 | \* to Next. 355 | Spec == Init /\ [][Next]_vars 356 | 357 | ============================================================================= 358 | -------------------------------------------------------------------------------- /tla/Universal.tla: -------------------------------------------------------------------------------- 1 | ------------------------------- MODULE Universal ------------------------------- 2 | (***************************************************************************) 3 | (* Formal Specification in TLA^+ of the *) 4 | (* Interledger Protocol Universal (ILP/U) *) 5 | (* *) 6 | (*`. *) 7 | (* Modeled after the excellent Raft specification by Diego Ongaro. *) 8 | (* Available at https://github.com/ongardie/raft.tla *) 9 | (* *) 10 | (* Copyright 2014 Diego Ongaro. *) 11 | (* This work is licensed under the Creative Commons Attribution-4.0 *) 12 | (* International License https://creativecommons.org/licenses/by/4.0/ .'*) 13 | (***************************************************************************) 14 | 15 | EXTENDS Naturals, Sequences, FiniteSets, Bags, TLC 16 | 17 | \* The set of ledger IDs 18 | CONSTANTS Ledger 19 | 20 | \* The set of participant IDs 21 | CONSTANTS Participant 22 | 23 | \* Sender states 24 | CONSTANTS S_Ready, S_ProposalWaiting, S_Waiting, S_Done 25 | 26 | \* Connector states 27 | CONSTANTS C_Ready, C_Proposed 28 | 29 | \* Ledger states 30 | CONSTANTS L_Proposed, L_Prepared, L_Executed, L_Aborted 31 | 32 | \* Message types 33 | CONSTANTS PrepareRequest, ExecuteRequest, AbortRequest, 34 | PrepareNotify, ExecuteNotify, AbortNotify, 35 | SubpaymentProposalRequest, SubpaymentProposalResponse 36 | 37 | \* Receipt signature 38 | CONSTANTS R_ReceiptSignature 39 | 40 | ---- 41 | \* Global variables 42 | 43 | \* Under synchrony we are allowed to have a global clock 44 | VARIABLE clock 45 | 46 | \* A bag of records representing requests and responses sent from one process 47 | \* to another 48 | VARIABLE messages 49 | 50 | ---- 51 | \* Sender variables 52 | 53 | \* State of the sender (S_Ready, S_Waiting, S_Done) 54 | VARIABLE senderState 55 | 56 | \* Whether the sender has received a response from a given connector 57 | VARIABLE senderProposalResponses 58 | 59 | \* All sender variables 60 | senderVars == <> 61 | ---- 62 | \* Connector variables 63 | 64 | \* State of the connector (C_Ready, C_Proposed) 65 | VARIABLE connectorState 66 | 67 | \* All sender variables 68 | connectorVars == <> 69 | ---- 70 | \* The following variables are all per ledger (functions with domain Ledger) 71 | 72 | \* The ledger state (L_Proposed, L_Prepared, L_Executed or L_Aborted) 73 | VARIABLE ledgerState 74 | 75 | \* The timeouts for each of the the transfers 76 | VARIABLE ledgerExpiration 77 | 78 | \* All ledger variables 79 | ledgerVars == <> 80 | ---- 81 | 82 | \* All variables; used for stuttering (asserting state hasn't changed) 83 | vars == <> 84 | 85 | ---- 86 | \* Helpers 87 | 88 | \* Add a set of new messages in transit 89 | Broadcast(m) == messages' = messages (+) SetToBag(m) 90 | 91 | \* Add a message to the bag of messages 92 | Send(m) == Broadcast({m}) 93 | 94 | \* Remove a message from the bag of messages. Used when a process is done 95 | \* processing a message. 96 | Discard(m) == messages' = messages (-) SetToBag({m}) 97 | 98 | \* Respond to a message by sending multiple messages 99 | ReplyBroadcast(responses, request) == 100 | messages' = messages (-) SetToBag({request}) (+) SetToBag(responses) 101 | 102 | \* Combination of Send and Discard 103 | Reply(response, request) == 104 | ReplyBroadcast({response}, request) 105 | 106 | 107 | \* Return the minimum value from a set, or undefined if the set is empty. 108 | Min(s) == CHOOSE x \in s : \A y \in s : x <= y 109 | \* Return the maximum value from a set, or undefined if the set is empty. 110 | Max(s) == CHOOSE x \in s : \A y \in s : x >= y 111 | 112 | \* Is a final ledger state 113 | IsFinalLedgerState(i) == i \in {L_Executed, L_Aborted} 114 | 115 | \* Sender 116 | Sender == Min(Participant) 117 | 118 | \* Recipient 119 | Recipient == Max(Participant) 120 | 121 | \* Set of connectors 122 | Connector == Participant \ {Sender, Recipient} 123 | 124 | \* The clock value we expect to be at after the proposal phase 125 | ClockAfterProposal == 2 * Cardinality(Connector) + 2 126 | 127 | \* The clock value we expect after the preparation phase 128 | ClockAfterPrepare == ClockAfterProposal + 2 * Cardinality(Ledger) + 1 129 | 130 | \* The clock value we expect to be at after the execution phase 131 | ClockAfterExecution == ClockAfterPrepare + 2 * Cardinality(Ledger) + 1 132 | ---- 133 | \* Define type specification for all variables 134 | 135 | TypeOK == /\ clock \in Nat 136 | /\ IsABag(messages) 137 | /\ senderState \in {S_Ready, S_ProposalWaiting, S_Waiting, S_Done} 138 | /\ senderProposalResponses \in [Connector -> BOOLEAN] 139 | /\ connectorState \in [Connector -> {C_Ready, C_Proposed}] 140 | /\ ledgerState \in [Ledger -> {L_Proposed, L_Prepared, L_Executed, L_Aborted}] 141 | /\ ledgerExpiration \in [Ledger -> Nat] 142 | 143 | Consistency == 144 | \A l1, l2 \in Ledger : \lnot /\ ledgerState[l1] = L_Aborted 145 | /\ ledgerState[l2] = L_Executed 146 | 147 | Inv == /\ TypeOK 148 | /\ Consistency 149 | 150 | ---- 151 | \* Define initial values for all variables 152 | 153 | InitSenderVars == /\ senderState = S_Ready 154 | /\ senderProposalResponses = [i \in Connector |-> FALSE] 155 | 156 | InitConnectorVars == connectorState = [i \in Connector |-> C_Ready] 157 | 158 | InitLedgerVars == /\ ledgerState = [i \in Ledger |-> L_Proposed] 159 | /\ ledgerExpiration = [i \in Ledger |-> ClockAfterExecution - i] 160 | 161 | Init == /\ clock = 0 162 | /\ messages = EmptyBag 163 | /\ InitSenderVars 164 | /\ InitConnectorVars 165 | /\ InitLedgerVars 166 | 167 | ---- 168 | \* Define state transitions 169 | 170 | \* Participant i proposes all the subpayments 171 | StartProposalPhase(i) == 172 | /\ senderState = S_Ready 173 | /\ senderState' = S_ProposalWaiting 174 | /\ Broadcast({[ 175 | mtype |-> SubpaymentProposalRequest, 176 | msource |-> i, 177 | mdest |-> k 178 | ] : k \in Connector}) 179 | /\ UNCHANGED <> 180 | 181 | \* Participant i starts off the preparation chain 182 | StartPreparationPhase(i) == 183 | /\ senderState = S_ProposalWaiting 184 | /\ \E p \in DOMAIN senderProposalResponses : senderProposalResponses[p] 185 | /\ senderState' = S_Waiting 186 | /\ Send([mtype |-> PrepareRequest, 187 | msource |-> i, 188 | mdest |-> i+1]) 189 | /\ UNCHANGED <> 190 | 191 | \* Ledger spontaneously aborts 192 | LedgerAbort(l) == 193 | /\ ledgerState[l] = L_Proposed 194 | /\ ledgerState' = [ledgerState EXCEPT ![l] = L_Aborted] 195 | /\ Send([mtype |-> AbortNotify, 196 | msource |-> l, 197 | mdest |-> l-1]) 198 | /\ UNCHANGED <> 199 | 200 | \* Transfer times out 201 | LedgerTimeout(l) == 202 | /\ \lnot IsFinalLedgerState(ledgerState[l]) 203 | /\ ledgerExpiration[l] =< clock 204 | /\ ledgerState' = [ledgerState EXCEPT ![l] = L_Aborted] 205 | /\ Send([mtype |-> AbortNotify, 206 | msource |-> l, 207 | mdest |-> l-1]) 208 | /\ UNCHANGED <> 209 | 210 | \* If no messages are in flight and the sender isn't doing anything, advance the 211 | \* clock 212 | NothingHappens == 213 | /\ clock \leq Max({ledgerExpiration[x] : x \in Ledger}) 214 | /\ BagCardinality(messages) = 0 215 | /\ senderState # S_Ready 216 | /\ \/ senderState # S_ProposalWaiting 217 | \/ \A p \in DOMAIN senderProposalResponses : \lnot senderProposalResponses[p] 218 | /\ UNCHANGED <> 219 | 220 | ---- 221 | \* Message handlers 222 | \* i = recipient, j = sender, m = message 223 | 224 | \* Ledger i receives a Prepare request from participant j 225 | LedgerHandlePrepareRequest(i, j, m) == 226 | LET valid == /\ ledgerState[i] = L_Proposed 227 | /\ j = i - 1 228 | IN \/ /\ valid 229 | /\ i \in Ledger 230 | /\ ledgerState' = [ledgerState EXCEPT ![i] = L_Prepared] 231 | /\ Reply([mtype |-> PrepareNotify, 232 | msource |-> i, 233 | mdest |-> i+1], m) 234 | /\ UNCHANGED <> 235 | \/ /\ \lnot valid 236 | /\ i \in Ledger 237 | /\ Discard(m) 238 | /\ UNCHANGED <> 239 | 240 | \* Ledger i receives an Execute request from process j 241 | LedgerHandleExecuteRequest(i, j, m) == 242 | LET valid == /\ ledgerState[i] = L_Prepared 243 | /\ ledgerExpiration[i] > clock 244 | /\ m.mreceipt = R_ReceiptSignature 245 | IN \/ /\ valid 246 | /\ ledgerState' = [ledgerState EXCEPT ![i] = L_Executed] 247 | /\ Reply([mtype |-> ExecuteNotify, 248 | msource |-> i, 249 | mdest |-> i-1, 250 | mreceipt |-> m.mreceipt], m) 251 | /\ UNCHANGED <> 252 | \/ /\ \lnot valid 253 | /\ Discard(m) 254 | /\ UNCHANGED <> 255 | 256 | \* Ledger i receives a message 257 | LedgerReceive(i, j, m) == 258 | \/ /\ m.mtype = PrepareRequest 259 | /\ LedgerHandlePrepareRequest(i, j, m) 260 | \/ /\ m.mtype = ExecuteRequest 261 | /\ LedgerHandleExecuteRequest(i, j, m) 262 | 263 | \* Sender receives a SubpaymentProposal request 264 | SenderHandleSubpaymentProposalResponse(i, j, m) == 265 | /\ i = Sender 266 | /\ senderProposalResponses' = [senderProposalResponses EXCEPT ![j] = TRUE] 267 | /\ Discard(m) 268 | /\ UNCHANGED <> 269 | 270 | \* Ledger j notifies sender that the transfer is executed 271 | SenderHandleExecuteNotify(i, j, m) == 272 | \/ /\ senderState = S_Waiting 273 | /\ senderState' = S_Done 274 | /\ Discard(m) 275 | /\ UNCHANGED <> 276 | \/ /\ senderState # S_Waiting 277 | /\ Discard(m) 278 | /\ UNCHANGED <> 279 | 280 | \* Ledger j notifies sender that the transfer is aborted 281 | SenderHandleAbortNotify(i, j, m) == 282 | LET isSenderWaiting == senderState \in { S_ProposalWaiting, S_Waiting, S_Ready } 283 | IN \/ /\ isSenderWaiting 284 | /\ senderState' = S_Done 285 | /\ Discard(m) 286 | /\ UNCHANGED <> 287 | \/ /\ \lnot isSenderWaiting 288 | /\ Discard(m) 289 | /\ UNCHANGED <> 290 | 291 | \* Sender receives a message 292 | SenderReceive(i, j, m) == 293 | \/ /\ m.mtype = SubpaymentProposalResponse 294 | /\ SenderHandleSubpaymentProposalResponse(i, j, m) 295 | \/ /\ m.mtype = ExecuteNotify 296 | /\ SenderHandleExecuteNotify(i, j, m) 297 | \/ /\ m.mtype = AbortNotify 298 | /\ SenderHandleAbortNotify(i, j, m) 299 | 300 | \* Ledger j notifies recipient that the transfer is prepared 301 | RecipientHandlePrepareNotify(i, j, m) == 302 | \/ /\ Reply([mtype |-> ExecuteRequest, 303 | msource |-> i, 304 | mdest |-> i-1, 305 | mreceipt |-> R_ReceiptSignature], m) 306 | /\ UNCHANGED <> 307 | 308 | \* Recipient receives a message 309 | RecipientReceive(i, j, m) == 310 | \/ /\ m.mtype = PrepareNotify 311 | /\ RecipientHandlePrepareNotify(i, j, m) 312 | 313 | \* Connector i receives a SubpaymentProposal request 314 | ConnectorHandleSubpaymentProposalRequest(i, j, m) == 315 | /\ connectorState' = [connectorState EXCEPT ![i] = C_Proposed] 316 | /\ Reply([mtype |-> SubpaymentProposalResponse, 317 | msource |-> i, 318 | mdest |-> j], m) 319 | /\ UNCHANGED <> 320 | 321 | \* Ledger j notifies connector i that the transfer is prepared 322 | ConnectorHandlePrepareNotify(i, j, m) == 323 | \/ /\ Reply([mtype |-> PrepareRequest, 324 | msource |-> i, 325 | mdest |-> i+1], m) 326 | /\ UNCHANGED <> 327 | 328 | \* Ledger j notifies connector i that the transfer is executed 329 | ConnectorHandleExecuteNotify(i, j, m) == 330 | /\ Reply([mtype |-> ExecuteRequest, 331 | msource |-> i, 332 | mdest |-> i-1, 333 | mreceipt |-> m.mreceipt], m) 334 | /\ UNCHANGED <> 335 | 336 | \* Ledger j notifies connector i that the transfer is aborted 337 | ConnectorHandleAbortNotify(i, j, m) == 338 | /\ Discard(m) 339 | /\ UNCHANGED <> 340 | 341 | \* Connector receives a message 342 | ConnectorReceive(i, j, m) == 343 | \/ /\ m.mtype = SubpaymentProposalRequest 344 | /\ ConnectorHandleSubpaymentProposalRequest(i, j, m) 345 | \/ /\ m.mtype = PrepareNotify 346 | /\ ConnectorHandlePrepareNotify(i, j, m) 347 | \/ /\ m.mtype = ExecuteNotify 348 | /\ ConnectorHandleExecuteNotify(i, j, m) 349 | \/ /\ m.mtype = AbortNotify 350 | /\ ConnectorHandleAbortNotify(i, j, m) 351 | 352 | \* Receive a message 353 | Receive(m) == 354 | LET i == m.mdest 355 | j == m.msource 356 | IN \/ /\ i \in Ledger 357 | /\ LedgerReceive(i, j, m) 358 | \/ /\ i = Sender 359 | /\ SenderReceive(i, j, m) 360 | \/ /\ i = Recipient 361 | /\ RecipientReceive(i, j, m) 362 | \/ /\ i \in Connector 363 | /\ ConnectorReceive(i, j, m) 364 | 365 | \* End of message handlers 366 | ---- 367 | \* Defines how the variables may transition 368 | 369 | Termination == 370 | /\ \A l \in Ledger : IsFinalLedgerState(ledgerState[l]) 371 | /\ senderState = S_Done 372 | /\ UNCHANGED vars 373 | 374 | Next == \/ /\ \/ StartProposalPhase(Sender) 375 | \/ StartPreparationPhase(Sender) 376 | \/ \E l \in Ledger : LedgerAbort(l) 377 | \/ \E l \in Ledger : LedgerTimeout(l) 378 | \/ \E m \in DOMAIN messages : Receive(m) 379 | \/ NothingHappens 380 | /\ clock' = clock + 1 381 | \/ Termination 382 | 383 | \* The specification must start with the initial state and transition according 384 | \* to Next. 385 | Spec == Init /\ [][Next]_vars 386 | 387 | ============================================================================= 388 | -------------------------------------------------------------------------------- /figures/web-of-ledgers.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /specs/atomic.tex: -------------------------------------------------------------------------------- 1 | \batchmode %% Suppresses most terminal output. 2 | \documentclass[letterpaper,twocolumn,10pt]{article} 3 | \usepackage{color} 4 | \usepackage{ilpspec} 5 | % \usepackage{usenix} 6 | \definecolor{boxshade}{gray}{0.95} 7 | 8 | \setlength{\headheight}{0.0in} 9 | 10 | \usepackage{latexsym} 11 | \usepackage{ifthen} 12 | % \usepackage{color} 13 | \usepackage{tlatex} 14 | 15 | \begin{document} 16 | \onecolumn 17 | \appendix 18 | \stepcounter{section} 19 | \stepcounter{subsection} 20 | \stepcounter{subsection} 21 | \setcounter{page}{12} 22 | \subsection{Formal Specification: Atomic mode} 23 | \label{sec:atomic-spec} 24 | \tlatex 25 | \setboolean{shading}{true} 26 | \@x{}\moduleLeftDash\@xx{ {\MODULE} Atomic}\moduleRightDash\@xx{}% 27 | \begin{lcom}{0}% 28 | \begin{cpar}{0}{T}{F}{2.5}{0}{}% 29 | Formal Specification in TLA\ensuremath{\.{\mbox{}^+}} of the 30 | Interledger Protocol \ensuremath{Atomic} (\ensuremath{ILP}/A) 31 | \end{cpar}% 32 | \vshade{10.0}% 33 | \begin{cpar}{1}{F}{F}{0}{0}{}% 34 | \begin{minipage}[t]{\linewidth} 35 | \begin{verbatim} 36 | Modeled after the excellent Raft specification by Diego Ongaro. 37 | Available at https://github.com/ongardie/raft.tla 38 | \end{verbatim} 39 | \end{minipage} 40 | \end{cpar}% 41 | \vshade{5.0}% 42 | \begin{cpar}{0}{F}{F}{0}{0}{}% 43 | \begin{minipage}[t]{\linewidth} 44 | \begin{verbatim} 45 | Copyright 2014 Diego Ongaro. 46 | This work is licensed under the Creative Commons Attribution-4.0 47 | International License https://creativecommons.org/licenses/by/4.0/ 48 | \end{verbatim} 49 | \end{minipage} 50 | \end{cpar}% 51 | \end{lcom}% 52 | \@pvspace{8.0pt}% 53 | \@x{ {\EXTENDS} Naturals ,\, Sequences ,\, Bags ,\, TLC}% 54 | \@pvspace{8.0pt}% 55 | \@x{}% 56 | \@y{\@s{0}% 57 | The set of ledger \ensuremath{IDs 58 | }}% 59 | \@xx{}% 60 | \@x{ {\CONSTANTS} Ledger}% 61 | \@pvspace{8.0pt}% 62 | \@x{}% 63 | \@y{\@s{0}% 64 | The set of participant \ensuremath{IDs 65 | }}% 66 | \@xx{}% 67 | \@x{ {\CONSTANTS} Participant}% 68 | \@pvspace{8.0pt}% 69 | \@x{}% 70 | \@y{\@s{0}% 71 | The notary 72 | }% 73 | \@xx{}% 74 | \@x{ {\CONSTANTS} Notary}% 75 | \@pvspace{8.0pt}% 76 | \@x{}% 77 | \@y{\@s{0}% 78 | Sender states 79 | }% 80 | \@xx{}% 81 | \@x{ {\CONSTANTS} S\_Ready ,\, S\_Waiting ,\, S\_Done}% 82 | \@pvspace{8.0pt}% 83 | \@x{}% 84 | \@y{\@s{0}% 85 | Notary states 86 | }% 87 | \@xx{}% 88 | \@x{ {\CONSTANTS} N\_Waiting ,\, N\_Committed ,\, N\_Aborted}% 89 | \@pvspace{8.0pt}% 90 | \@x{}% 91 | \@y{\@s{0}% 92 | Ledger states 93 | }% 94 | \@xx{}% 95 | \@x{ {\CONSTANTS} L\_Proposed ,\, L\_Prepared ,\, L\_Executed ,\, L\_Aborted}% 96 | \@pvspace{8.0pt}% 97 | \@x{}% 98 | \@y{\@s{0}% 99 | Message types 100 | }% 101 | \@xx{}% 102 | \@x{ {\CONSTANTS} PrepareRequest ,\, ExecuteRequest ,\, AbortRequest ,\,}% 103 | \@x{\@s{54.75} PrepareNotify ,\, ExecuteNotify ,\, AbortNotify ,\,}% 104 | \@x{\@s{54.75} SubmitReceiptRequest}% 105 | \@pvspace{8.0pt}% 106 | \@x{}% 107 | \@y{\@s{0}% 108 | Receipt signature 109 | }% 110 | \@xx{}% 111 | \@x{ {\CONSTANTS} R\_ReceiptSignature}% 112 | \@pvspace{8.0pt}% 113 | \@x{}\midbar\@xx{}% 114 | \@x{}% 115 | \@y{\@s{0}% 116 | Global variables 117 | }% 118 | \@xx{}% 119 | \@pvspace{8.0pt}% 120 | \@x{}% 121 | \@y{\@s{0}% 122 | A bag of records representing requests and responses sent from one process 123 | }% 124 | \@xx{}% 125 | \@x{}% 126 | \@y{\@s{0}% 127 | to another 128 | }% 129 | \@xx{}% 130 | \@x{ {\VARIABLE} messages}% 131 | \@pvspace{8.0pt}% 132 | \@x{}\midbar\@xx{}% 133 | \@x{}% 134 | \@y{\@s{0}% 135 | Sender variables 136 | }% 137 | \@xx{}% 138 | \@pvspace{8.0pt}% 139 | \@x{}% 140 | \@y{\@s{0}% 141 | State of the sender (\ensuremath{S\_Ready}, \ensuremath{S\_Waiting}, 142 | \ensuremath{S\_Done}) 143 | }% 144 | \@xx{}% 145 | \@x{ {\VARIABLE} senderState}% 146 | \@pvspace{8.0pt}% 147 | \@x{}% 148 | \@y{\@s{0}% 149 | All sender variables 150 | }% 151 | \@xx{}% 152 | \@x{ senderVars \.{\defeq} {\langle} senderState {\rangle}}% 153 | \@x{}\midbar\@xx{}% 154 | \@x{}% 155 | \@y{\@s{0}% 156 | The following variables are all per ledger (functions with domain 157 | \ensuremath{Ledger}) 158 | }% 159 | \@xx{}% 160 | \@pvspace{8.0pt}% 161 | \@x{}% 162 | \@y{\@s{0}% 163 | The ledger state (\ensuremath{L\_Proposed}, \ensuremath{L\_Prepared}, 164 | \ensuremath{L\_Executed} or \ensuremath{L\_Aborted}) 165 | }% 166 | \@xx{}% 167 | \@x{ {\VARIABLE} ledgerState}% 168 | \@pvspace{8.0pt}% 169 | \@x{}% 170 | \@y{\@s{0}% 171 | All ledger variables 172 | }% 173 | \@xx{}% 174 | \@x{ ledgerVars \.{\defeq} {\langle} ledgerState {\rangle}}% 175 | \@x{}\midbar\@xx{}% 176 | \@x{}% 177 | \@y{\@s{0}% 178 | Notary variables 179 | }% 180 | \@xx{}% 181 | \@pvspace{8.0pt}% 182 | \@x{}% 183 | \@y{\@s{0}% 184 | State of the notary (\ensuremath{N\_Waiting}, \ensuremath{N\_Committed}, 185 | \ensuremath{N\_Aborted}) 186 | }% 187 | \@xx{}% 188 | \@x{ {\VARIABLE} notaryState}% 189 | \@pvspace{8.0pt}% 190 | \@x{}% 191 | \@y{\@s{0}% 192 | All notary variables 193 | }% 194 | \@xx{}% 195 | \@x{ notaryVars \.{\defeq} {\langle} notaryState {\rangle}}% 196 | \@x{}\midbar\@xx{}% 197 | \@pvspace{8.0pt}% 198 | \@x{}% 199 | \@y{\@s{0}% 200 | All variables; used for stuttering (asserting state hasn\mbox{'}t changed) 201 | }% 202 | \@xx{}% 203 | \@x{ vars \.{\defeq} {\langle} messages ,\, senderVars ,\, ledgerVars ,\, 204 | notaryVars {\rangle}}% 205 | \@pvspace{8.0pt}% 206 | \@x{}\midbar\@xx{}% 207 | \@x{}% 208 | \@y{\@s{0}% 209 | Helpers 210 | }% 211 | \@xx{}% 212 | \@pvspace{8.0pt}% 213 | \@x{}% 214 | \@y{\@s{0}% 215 | Add a set of new messages in transit 216 | }% 217 | \@xx{}% 218 | \@x{ Broadcast ( m ) \.{\defeq} messages \.{'} \.{=} messages \.{\oplus} 219 | SetToBag ( m )}% 220 | \@pvspace{8.0pt}% 221 | \@x{}% 222 | \@y{\@s{0}% 223 | Add a message to the bag of messages 224 | }% 225 | \@xx{}% 226 | \@x{ Send ( m ) \.{\defeq} Broadcast ( \{ m \} )}% 227 | \@pvspace{8.0pt}% 228 | \@x{}% 229 | \@y{\@s{0}% 230 | Remove a message from the bag of messages. Used when a process is done 231 | }% 232 | \@xx{}% 233 | \@x{}% 234 | \@y{\@s{0}% 235 | processing a message. 236 | }% 237 | \@xx{}% 238 | \@x{ Discard ( m ) \.{\defeq} messages \.{'} \.{=} messages \.{\ominus} 239 | SetToBag ( \{ m \} )}% 240 | \@pvspace{8.0pt}% 241 | \@x{}% 242 | \@y{\@s{0}% 243 | Respond to a message by sending multiple messages 244 | }% 245 | \@xx{}% 246 | \@x{ ReplyBroadcast ( responses ,\, request ) \.{\defeq}}% 247 | \@x{\@s{16.4} messages \.{'} \.{=} messages \.{\ominus} SetToBag ( \{ request 248 | \} ) \.{\oplus} SetToBag ( responses )}% 249 | \@pvspace{8.0pt}% 250 | \@x{}% 251 | \@y{\@s{0}% 252 | Combination of \ensuremath{Send} and \ensuremath{Discard 253 | }}% 254 | \@xx{}% 255 | \@x{ Reply ( response ,\, request ) \.{\defeq}}% 256 | \@x{\@s{16.4} ReplyBroadcast ( \{ response \} ,\, request )}% 257 | \@pvspace{16.0pt}% 258 | \@x{}% 259 | \@y{\@s{0}% 260 | Return the minimum value from a set, or undefined if the set is empty. 261 | }% 262 | \@xx{}% 263 | \@x{ Min ( s ) \.{\defeq} {\CHOOSE} x \.{\in} s \.{:} \A\, y \.{\in} s \.{:} 264 | x \.{\leq} y}% 265 | \@x{}% 266 | \@y{\@s{0}% 267 | Return the maximum value from a set, or undefined if the set is empty. 268 | }% 269 | \@xx{}% 270 | \@x{ Max ( s ) \.{\defeq} {\CHOOSE} x \.{\in} s \.{:} \A\, y \.{\in} s \.{:} 271 | x \.{\geq} y}% 272 | \@pvspace{8.0pt}% 273 | \@x{}% 274 | \@y{\@s{0}% 275 | Is a final ledger state 276 | }% 277 | \@xx{}% 278 | \@x{ IsFinalLedgerState ( i ) \.{\defeq} i \.{\in} \{ L\_Executed ,\, 279 | L\_Aborted \}}% 280 | \@pvspace{8.0pt}% 281 | \@x{}% 282 | \@y{\@s{0}% 283 | Sender 284 | }% 285 | \@xx{}% 286 | \@x{ Sender \.{\defeq} Min ( Participant )}% 287 | \@pvspace{8.0pt}% 288 | \@x{}% 289 | \@y{\@s{0}% 290 | Recipient 291 | }% 292 | \@xx{}% 293 | \@x{ Recipient \.{\defeq} Max ( Participant )}% 294 | \@pvspace{8.0pt}% 295 | \@x{}% 296 | \@y{\@s{0}% 297 | Set of connectors 298 | }% 299 | \@xx{}% 300 | \@x{ Connector \.{\defeq} Participant \.{\,\backslash\,} \{ Sender ,\, 301 | Recipient \}}% 302 | \@pvspace{8.0pt}% 303 | \@x{}\midbar\@xx{}% 304 | \@x{}% 305 | \@y{\@s{0}% 306 | Define type specification for all variables 307 | }% 308 | \@xx{}% 309 | \@pvspace{8.0pt}% 310 | \@x{ TypeOK \.{\defeq} \.{\land} IsABag ( messages )}% 311 | \@x{\@s{56.14} \.{\land} senderState \.{\in} \{ S\_Ready ,\, S\_Waiting ,\, 312 | S\_Done \}}% 313 | \@x{\@s{56.14} \.{\land} ledgerState\@s{3.06} \.{\in} [ Ledger 314 | \.{\rightarrow} \{ L\_Proposed ,\, L\_Prepared ,\, L\_Executed ,\, 315 | L\_Aborted \} ]}% 316 | \@pvspace{8.0pt}% 317 | \@x{ Consistency \.{\defeq}}% 318 | \@x{\@s{16.4} \A\, l1 ,\, l2 \.{\in} Ledger \.{:} {\lnot} \.{\land} 319 | ledgerState [ l1 ] \.{=} L\_Aborted}% 320 | \@x{\@s{104.69} \.{\land} ledgerState [ l2 ] \.{=} L\_Executed}% 321 | \@pvspace{8.0pt}% 322 | \@x{ Inv \.{\defeq} \.{\land} TypeOK}% 323 | \@x{\@s{34.04} \.{\land} Consistency}% 324 | \@pvspace{8.0pt}% 325 | \@x{}\midbar\@xx{}% 326 | \@x{}% 327 | \@y{\@s{0}% 328 | Define initial values for all variables 329 | }% 330 | \@xx{}% 331 | \@pvspace{8.0pt}% 332 | \@x{ InitSenderVars\@s{0.27} \.{\defeq} \.{\land} senderState \.{=} S\_Ready}% 333 | \@pvspace{8.0pt}% 334 | \@x{ InitLedgerVars\@s{1.67} \.{\defeq} \.{\land} ledgerState\@s{3.06} \.{=} 335 | [ i \.{\in} Ledger \.{\mapsto} L\_Proposed ]}% 336 | \@pvspace{8.0pt}% 337 | \@x{ InitNotaryVars \.{\defeq} \.{\land} notaryState \.{=} N\_Waiting}% 338 | \@pvspace{8.0pt}% 339 | \@x{ Init \.{\defeq} \.{\land} messages \.{=} EmptyBag}% 340 | \@x{\@s{35.70} \.{\land} InitSenderVars}% 341 | \@x{\@s{35.70} \.{\land} InitLedgerVars}% 342 | \@x{\@s{35.70} \.{\land} InitNotaryVars}% 343 | \@pvspace{8.0pt}% 344 | \@x{}\midbar\@xx{}% 345 | \@x{}% 346 | \@y{\@s{0}% 347 | Define state transitions 348 | }% 349 | \@xx{}% 350 | \@pvspace{8.0pt}% 351 | \@x{}% 352 | \@y{\@s{0}% 353 | Participant \ensuremath{i} starts off the chain 354 | }% 355 | \@xx{}% 356 | \@x{ Start ( i ) \.{\defeq}}% 357 | \@x{\@s{16.4} \.{\land} senderState \.{=} S\_Ready}% 358 | \@x{\@s{16.4} \.{\land} senderState \.{'} \.{=} S\_Waiting}% 359 | \@x{\@s{16.4} \.{\land} Send ( [ mtype\@s{9.58} \.{\mapsto} PrepareRequest 360 | ,\,}% 361 | \@x{\@s{56.16} msource \.{\mapsto} i ,\,}% 362 | \@x{\@s{56.16} mdest\@s{9.64} \.{\mapsto} i \.{+} 1 ] )}% 363 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, notaryVars 364 | {\rangle}}% 365 | \@pvspace{8.0pt}% 366 | \@x{}% 367 | \@y{\@s{0}% 368 | Notary times out 369 | }% 370 | \@xx{}% 371 | \@x{ NotaryTimeout \.{\defeq}}% 372 | \@x{\@s{16.4} \.{\land} notaryState \.{=} N\_Waiting}% 373 | \@x{\@s{16.4} \.{\land} notaryState \.{'} \.{=} N\_Aborted}% 374 | \@x{\@s{16.4} \.{\land} Broadcast (}% 375 | \@x{\@s{48.01} \{ [ mtype\@s{13.68} \.{\mapsto} AbortRequest ,\,}% 376 | \@x{\@s{55.78} msource\@s{4.10} \.{\mapsto} Notary ,\,}% 377 | \@x{\@s{55.78} mdest\@s{13.74} \.{\mapsto} k ] \.{:} k \.{\in} Ledger \} )}% 378 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars 379 | {\rangle}}% 380 | \@pvspace{8.0pt}% 381 | \@x{}% 382 | \@y{\@s{0}% 383 | Ledger spontaneously aborts 384 | }% 385 | \@xx{}% 386 | \@x{ LedgerAbort ( l ) \.{\defeq}}% 387 | \@x{\@s{16.4} \.{\land} ledgerState [ l ] \.{=} L\_Proposed}% 388 | \@x{\@s{16.4} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 389 | {\bang} [ l ] \.{=} L\_Aborted ]}% 390 | \@x{\@s{16.4} \.{\land} Send ( [ mtype\@s{9.58} \.{\mapsto} AbortNotify ,\,}% 391 | \@x{\@s{56.16} msource \.{\mapsto} l ,\,}% 392 | \@x{\@s{56.16} mdest\@s{9.64} \.{\mapsto} l \.{-} 1 ] )}% 393 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, notaryVars 394 | {\rangle}}% 395 | \@pvspace{8.0pt}% 396 | \@x{}\midbar\@xx{}% 397 | \@x{}% 398 | \@y{\@s{0}% 399 | Message handlers 400 | }% 401 | \@xx{}% 402 | \@x{}% 403 | \@y{\@s{0}% 404 | \ensuremath{i \.{=}} recipient, \ensuremath{j \.{=}} sender, \ensuremath{m 405 | \.{=}} message 406 | }% 407 | \@xx{}% 408 | \@pvspace{8.0pt}% 409 | \@x{}% 410 | \@y{\@s{0}% 411 | Ledger \ensuremath{i} receives a Prepare request from process \ensuremath{j 412 | }}% 413 | \@xx{}% 414 | \@x{ LedgerHandlePrepareRequest ( i ,\, j ,\, m ) \.{\defeq}}% 415 | \@x{\@s{16.4} \.{\LET} valid \.{\defeq} \.{\land} ledgerState [ i ] \.{=} 416 | L\_Proposed}% 417 | \@x{\@s{77.16} \.{\land} j \.{=} i \.{-} 1}% 418 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} valid}% 419 | \@x{\@s{47.91} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 420 | {\bang} [ i ] \.{=} L\_Prepared ]}% 421 | \@x{\@s{47.91} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} PrepareNotify 422 | ,\,}% 423 | \@x{\@s{90.47} msource \.{\mapsto} i ,\,}% 424 | \@x{\@s{90.47} mdest\@s{9.64} \.{\mapsto} i \.{+} 1 ] ,\, m )}% 425 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, notaryVars 426 | {\rangle}}% 427 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} valid}% 428 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 429 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 430 | notaryVars {\rangle}}% 431 | \@pvspace{8.0pt}% 432 | \@x{}% 433 | \@y{\@s{0}% 434 | Ledger \ensuremath{i} receives an Execute request from process \ensuremath{j 435 | }}% 436 | \@xx{}% 437 | \@x{ LedgerHandleExecuteRequest ( i ,\, j ,\, m ) \.{\defeq}}% 438 | \@x{\@s{16.4} \.{\LET} valid \.{\defeq} \.{\land} ledgerState [ i ] \.{=} 439 | L\_Prepared}% 440 | \@x{\@s{77.16} \.{\land} j \.{=} Notary}% 441 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} valid}% 442 | \@x{\@s{47.91} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 443 | {\bang} [ i ] \.{=} L\_Executed ]}% 444 | \@x{\@s{47.91} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} ExecuteNotify 445 | ,\,}% 446 | \@x{\@s{90.47} msource \.{\mapsto} i ,\,}% 447 | \@x{\@s{90.47} mdest\@s{9.64} \.{\mapsto} i \.{-} 1 ] ,\, m )}% 448 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, notaryVars 449 | {\rangle}}% 450 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} valid}% 451 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 452 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 453 | notaryVars {\rangle}}% 454 | \@pvspace{8.0pt}% 455 | \@x{}% 456 | \@y{\@s{0}% 457 | Ledger \ensuremath{i} receives an Abort request from process \ensuremath{j 458 | }}% 459 | \@xx{}% 460 | \@x{ LedgerHandleAbortRequest ( i ,\, j ,\, m ) \.{\defeq}}% 461 | \@x{\@s{16.4} \.{\LET} valid \.{\defeq} \.{\land} \.{\lor} ledgerState [ i ] 462 | \.{=} L\_Proposed}% 463 | \@x{\@s{88.27} \.{\lor} ledgerState [ i ] \.{=} L\_Prepared}% 464 | \@x{\@s{77.16} \.{\land} j \.{=} Notary}% 465 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} valid}% 466 | \@x{\@s{47.91} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 467 | {\bang} [ i ] \.{=} L\_Aborted ]}% 468 | \@x{\@s{47.91} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} AbortNotify 469 | ,\,}% 470 | \@x{\@s{90.47} msource \.{\mapsto} i ,\,}% 471 | \@x{\@s{90.47} mdest\@s{9.64} \.{\mapsto} i \.{-} 1 ] ,\, m )}% 472 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, notaryVars 473 | {\rangle}}% 474 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} valid}% 475 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 476 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 477 | notaryVars {\rangle}}% 478 | \@pvspace{8.0pt}% 479 | \@x{}% 480 | \@y{\@s{0}% 481 | Ledger \ensuremath{i} receives a message 482 | }% 483 | \@xx{}% 484 | \@x{ LedgerReceive ( i ,\, j ,\, m ) \.{\defeq}}% 485 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} PrepareRequest}% 486 | \@x{\@s{27.51} \.{\land} LedgerHandlePrepareRequest ( i ,\, j ,\, m )}% 487 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} ExecuteRequest}% 488 | \@x{\@s{27.51} \.{\land} LedgerHandleExecuteRequest ( i ,\, j ,\, m )}% 489 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} AbortRequest}% 490 | \@x{\@s{27.51} \.{\land} LedgerHandleAbortRequest ( i ,\, j ,\, m )}% 491 | \@pvspace{8.0pt}% 492 | \@x{}% 493 | \@y{\@s{0}% 494 | Ledger \ensuremath{j} notifies sender that the transfer is executed 495 | }% 496 | \@xx{}% 497 | \@x{ SenderHandleExecuteNotify ( i ,\, j ,\, m ) \.{\defeq}}% 498 | \@x{\@s{16.4} \.{\lor} \.{\land} senderState \.{=} S\_Waiting}% 499 | \@x{\@s{27.51} \.{\land} senderState \.{'} \.{=} S\_Done}% 500 | \@x{\@s{27.51} \.{\land} Discard ( m )}% 501 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, notaryVars 502 | {\rangle}}% 503 | \@x{\@s{16.4} \.{\lor} \.{\land} senderState \.{\neq} S\_Waiting}% 504 | \@x{\@s{27.51} \.{\land} Discard ( m )}% 505 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 506 | notaryVars {\rangle}}% 507 | \@pvspace{8.0pt}% 508 | \@x{}% 509 | \@y{\@s{0}% 510 | Ledger \ensuremath{j} notifies sender that the transfer is aborted 511 | }% 512 | \@xx{}% 513 | \@x{ SenderHandleAbortNotify ( i ,\, j ,\, m ) \.{\defeq}}% 514 | \@x{\@s{16.4} \.{\LET} isSenderWaiting \.{\defeq} \.{\lor} senderState \.{=} 515 | S\_Waiting}% 516 | \@x{\@s{128.27} \.{\lor} senderState \.{=} S\_Ready}% 517 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} isSenderWaiting}% 518 | \@x{\@s{47.91} \.{\land} senderState \.{'} \.{=} S\_Done}% 519 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 520 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, notaryVars 521 | {\rangle}}% 522 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} isSenderWaiting}% 523 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 524 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 525 | notaryVars {\rangle}}% 526 | \@pvspace{8.0pt}% 527 | \@x{}% 528 | \@y{\@s{0}% 529 | Sender receives a message 530 | }% 531 | \@xx{}% 532 | \@x{ SenderReceive ( i ,\, j ,\, m ) \.{\defeq}}% 533 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} ExecuteNotify}% 534 | \@x{\@s{27.51} \.{\land} SenderHandleExecuteNotify ( i ,\, j ,\, m )}% 535 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} AbortNotify}% 536 | \@x{\@s{27.51} \.{\land} SenderHandleAbortNotify ( i ,\, j ,\, m )}% 537 | \@pvspace{8.0pt}% 538 | \@x{}% 539 | \@y{\@s{0}% 540 | Ledger \ensuremath{j} notifies recipient that the transfer is prepared 541 | }% 542 | \@xx{}% 543 | \@x{ RecipientHandlePrepareNotify ( i ,\, j ,\, m ) \.{\defeq}}% 544 | \@x{\@s{16.4} \.{\land} Reply ( [ mtype\@s{12.29} \.{\mapsto} 545 | SubmitReceiptRequest ,\,}% 546 | \@x{\@s{58.96} msource\@s{2.71} \.{\mapsto} i ,\,}% 547 | \@x{\@s{58.96} mdest\@s{12.35} \.{\mapsto} Notary ,\,}% 548 | \@x{\@s{58.96} mreceipt\@s{1.49} \.{\mapsto} R\_ReceiptSignature ] ,\, m )}% 549 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 550 | notaryVars {\rangle}}% 551 | \@pvspace{8.0pt}% 552 | \@x{}% 553 | \@y{\@s{0}% 554 | Recipient receives a message 555 | }% 556 | \@xx{}% 557 | \@x{ RecipientReceive ( i ,\, j ,\, m ) \.{\defeq}}% 558 | \@x{\@s{16.4} \.{\land} m . mtype \.{=} PrepareNotify}% 559 | \@x{\@s{16.4} \.{\land} RecipientHandlePrepareNotify ( i ,\, j ,\, m )}% 560 | \@pvspace{8.0pt}% 561 | \@x{}% 562 | \@y{\@s{0}% 563 | Ledger \ensuremath{j} notifies connector \ensuremath{i} that the transfer is 564 | prepared 565 | }% 566 | \@xx{}% 567 | \@x{ ConnectorHandlePrepareNotify ( i ,\, j ,\, m ) \.{\defeq}}% 568 | \@x{\@s{16.4} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} PrepareRequest 569 | ,\,}% 570 | \@x{\@s{58.96} msource \.{\mapsto} i ,\,}% 571 | \@x{\@s{58.96} mdest\@s{9.64} \.{\mapsto} i \.{+} 1 ] ,\, m )}% 572 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 573 | notaryVars {\rangle}}% 574 | \@pvspace{8.0pt}% 575 | \@x{}% 576 | \@y{\@s{0}% 577 | Ledger \ensuremath{j} notifies connector \ensuremath{i} that the transfer is 578 | executed 579 | }% 580 | \@xx{}% 581 | \@x{ ConnectorHandleExecuteNotify ( i ,\, j ,\, m ) \.{\defeq}}% 582 | \@x{\@s{16.4} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} ExecuteRequest 583 | ,\,}% 584 | \@x{\@s{58.96} msource \.{\mapsto} i ,\,}% 585 | \@x{\@s{58.96} mdest\@s{9.64} \.{\mapsto} i \.{-} 1 ] ,\, m )}% 586 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 587 | notaryVars {\rangle}}% 588 | \@pvspace{8.0pt}% 589 | \@x{}% 590 | \@y{\@s{0}% 591 | Ledger \ensuremath{j} notifies connector \ensuremath{i} that the transfer is 592 | aborted 593 | }% 594 | \@xx{}% 595 | \@x{ ConnectorHandleAbortNotify ( i ,\, j ,\, m ) \.{\defeq}}% 596 | \@x{\@s{16.4} \.{\land} Discard ( m )}% 597 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 598 | notaryVars {\rangle}}% 599 | \@pvspace{8.0pt}% 600 | \@x{}% 601 | \@y{\@s{0}% 602 | Connector receives a message 603 | }% 604 | \@xx{}% 605 | \@x{ ConnectorReceive ( i ,\, j ,\, m ) \.{\defeq}}% 606 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} PrepareNotify}% 607 | \@x{\@s{27.51} \.{\land} ConnectorHandlePrepareNotify ( i ,\, j ,\, m )}% 608 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} ExecuteNotify}% 609 | \@x{\@s{27.51} \.{\land} ConnectorHandleExecuteNotify ( i ,\, j ,\, m )}% 610 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} AbortNotify}% 611 | \@x{\@s{27.51} \.{\land} ConnectorHandleAbortNotify ( i ,\, j ,\, m )}% 612 | \@pvspace{8.0pt}% 613 | \@x{}% 614 | \@y{\@s{0}% 615 | Notary receives a signed receipt 616 | }% 617 | \@xx{}% 618 | \@x{ NotaryHandleSubmitReceiptRequest ( i ,\, j ,\, m ) \.{\defeq}}% 619 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mreceipt \.{=} R\_ReceiptSignature}% 620 | \@x{\@s{27.51} \.{\land} notaryState \.{=} N\_Waiting}% 621 | \@x{\@s{27.51} \.{\land} notaryState \.{'} \.{=} N\_Committed}% 622 | \@x{\@s{27.51} \.{\land} ReplyBroadcast (}% 623 | \@x{\@s{46.82} \{ [ mtype\@s{13.68} \.{\mapsto} ExecuteRequest ,\,}% 624 | \@x{\@s{54.59} msource\@s{4.1} \.{\mapsto} i ,\,}% 625 | \@x{\@s{54.59} mdest\@s{13.74} \.{\mapsto} k ] \.{:} k \.{\in} Ledger \} ,\, 626 | m )}% 627 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars 628 | {\rangle}}% 629 | \@x{\@s{16.4} \.{\lor} \.{\land} notaryState \.{\neq} N\_Waiting}% 630 | \@x{\@s{27.51} \.{\land} Discard ( m )}% 631 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars ,\, 632 | notaryVars {\rangle}}% 633 | \@pvspace{8.0pt}% 634 | \@x{}% 635 | \@y{\@s{0}% 636 | Notary receives a message 637 | }% 638 | \@xx{}% 639 | \@x{ NotaryReceive ( i ,\, j ,\, m ) \.{\defeq}}% 640 | \@x{\@s{16.4} \.{\land} m . mtype \.{=} SubmitReceiptRequest}% 641 | \@x{\@s{16.4} \.{\land} NotaryHandleSubmitReceiptRequest ( i ,\, j ,\, m )}% 642 | \@pvspace{8.0pt}% 643 | \@x{}% 644 | \@y{\@s{0}% 645 | Receive a message 646 | }% 647 | \@xx{}% 648 | \@x{ Receive ( m ) \.{\defeq}}% 649 | \@x{\@s{16.4} \.{\LET} i\@s{0.42} \.{\defeq} m . mdest}% 650 | \@x{\@s{36.79} j \.{\defeq} m . msource}% 651 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} i \.{\in} Ledger}% 652 | \@x{\@s{47.91} \.{\land} LedgerReceive ( i ,\, j ,\, m )}% 653 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{=} Sender}% 654 | \@x{\@s{47.91} \.{\land} SenderReceive ( i ,\, j ,\, m )}% 655 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{=} Recipient}% 656 | \@x{\@s{47.91} \.{\land} RecipientReceive ( i ,\, j ,\, m )}% 657 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{\in} Connector}% 658 | \@x{\@s{47.91} \.{\land} ConnectorReceive ( i ,\, j ,\, m )}% 659 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{=} Notary}% 660 | \@x{\@s{47.91} \.{\land} NotaryReceive ( i ,\, j ,\, m )}% 661 | \@pvspace{8.0pt}% 662 | \@x{}% 663 | \@y{\@s{0}% 664 | End of message handlers 665 | }% 666 | \@xx{}% 667 | \@x{}\midbar\@xx{}% 668 | \@x{}% 669 | \@y{\@s{0}% 670 | Defines how the variables may transition 671 | }% 672 | \@xx{}% 673 | \@pvspace{8.0pt}% 674 | \@x{ Termination \.{\defeq}}% 675 | \@x{\@s{16.4} \.{\land} \A\, l \.{\in} Ledger \.{:} IsFinalLedgerState ( 676 | ledgerState [ l ] )}% 677 | \@x{\@s{16.4} \.{\land} senderState \.{=} S\_Done}% 678 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} vars}% 679 | \@pvspace{8.0pt}% 680 | \@x{ Next \.{\defeq} \.{\lor} Start ( Sender )}% 681 | \@x{\@s{39.83} \.{\lor} NotaryTimeout}% 682 | \@x{\@s{39.83} \.{\lor} \E\, l\@s{5.35} \.{\in} Ledger \.{:} LedgerAbort ( l 683 | )}% 684 | \@x{\@s{39.83} \.{\lor} \E\, m \.{\in} {\DOMAIN} messages \.{:} Receive ( m 685 | )}% 686 | \@x{\@s{39.83} \.{\lor} Termination}% 687 | \@pvspace{8.0pt}% 688 | \@x{}% 689 | \@y{\@s{0}% 690 | The specification must start with the initial state and transition according 691 | }% 692 | \@xx{}% 693 | \@x{}% 694 | \@y{\@s{0}% 695 | to \ensuremath{Next}. 696 | }% 697 | \@xx{}% 698 | \@x{ Spec \.{\defeq} Init \.{\land} {\Box} [ Next ]_{ vars}}% 699 | \@pvspace{8.0pt}% 700 | \@x{}\bottombar\@xx{}% 701 | \end{document} -------------------------------------------------------------------------------- /specs/universal.tex: -------------------------------------------------------------------------------- 1 | \batchmode %% Suppresses most terminal output. 2 | \documentclass[letterpaper,twocolumn,10pt]{article} 3 | \usepackage{color} 4 | \usepackage{ilpspec} 5 | % \usepackage{usenix} 6 | \definecolor{boxshade}{gray}{0.95} 7 | 8 | \setlength{\headheight}{0.0in} 9 | 10 | \usepackage{latexsym} 11 | \usepackage{ifthen} 12 | % \usepackage{color} 13 | \usepackage{tlatex} 14 | 15 | \begin{document} 16 | \onecolumn 17 | \appendix 18 | \stepcounter{section} 19 | \stepcounter{subsection} 20 | \stepcounter{subsection} 21 | \stepcounter{subsection} 22 | \setcounter{page}{19} 23 | \subsection{Formal Specification: Universal mode} 24 | \label{sec:universal-spec} 25 | \tlatex 26 | \setboolean{shading}{true} 27 | \@x{}\moduleLeftDash\@xx{ {\MODULE} Universal}\moduleRightDash\@xx{}% 28 | \begin{lcom}{0}% 29 | \begin{cpar}{0}{T}{F}{2.5}{0}{}% 30 | Formal Specification in TLA\ensuremath{\.{\mbox{}^+}} of the 31 | Interledger Protocol \ensuremath{Universal} (\ensuremath{ILP}/\ensuremath{U}) 32 | \end{cpar}% 33 | \vshade{10.0}% 34 | \begin{cpar}{1}{F}{F}{0}{0}{}% 35 | \begin{minipage}[t]{\linewidth} 36 | \begin{verbatim} 37 | Modeled after the excellent Raft specification by Diego Ongaro. 38 | Available at https://github.com/ongardie/raft.tla 39 | \end{verbatim} 40 | \end{minipage} 41 | \end{cpar}% 42 | \vshade{5.0}% 43 | \begin{cpar}{0}{F}{F}{0}{0}{}% 44 | \begin{minipage}[t]{\linewidth} 45 | \begin{verbatim} 46 | Copyright 2014 Diego Ongaro. 47 | This work is licensed under the Creative Commons Attribution-4.0 48 | International License https://creativecommons.org/licenses/by/4.0/ 49 | \end{verbatim} 50 | \end{minipage} 51 | \end{cpar}% 52 | \end{lcom}% 53 | \@pvspace{8.0pt}% 54 | \@x{ {\EXTENDS} Naturals ,\, Sequences ,\, FiniteSets ,\, Bags ,\, TLC}% 55 | \@pvspace{8.0pt}% 56 | \@x{}% 57 | \@y{\@s{0}% 58 | The set of ledger \ensuremath{IDs 59 | }}% 60 | \@xx{}% 61 | \@x{ {\CONSTANTS} Ledger}% 62 | \@pvspace{8.0pt}% 63 | \@x{}% 64 | \@y{\@s{0}% 65 | The set of participant \ensuremath{IDs 66 | }}% 67 | \@xx{}% 68 | \@x{ {\CONSTANTS} Participant}% 69 | \@pvspace{8.0pt}% 70 | \@x{}% 71 | \@y{\@s{0}% 72 | Sender states 73 | }% 74 | \@xx{}% 75 | \@x{ {\CONSTANTS} S\_Ready ,\, S\_ProposalWaiting ,\, S\_Waiting ,\, S\_Done}% 76 | \@pvspace{8.0pt}% 77 | \@x{}% 78 | \@y{\@s{0}% 79 | Connector states 80 | }% 81 | \@xx{}% 82 | \@x{ {\CONSTANTS} C\_Ready ,\, C\_Proposed}% 83 | \@pvspace{8.0pt}% 84 | \@x{}% 85 | \@y{\@s{0}% 86 | Ledger states 87 | }% 88 | \@xx{}% 89 | \@x{ {\CONSTANTS} L\_Proposed ,\, L\_Prepared ,\, L\_Executed ,\, L\_Aborted}% 90 | \@pvspace{8.0pt}% 91 | \@x{}% 92 | \@y{\@s{0}% 93 | Message types 94 | }% 95 | \@xx{}% 96 | \@x{ {\CONSTANTS} PrepareRequest ,\, ExecuteRequest ,\, AbortRequest ,\,}% 97 | \@x{\@s{54.75} PrepareNotify ,\, ExecuteNotify ,\, AbortNotify ,\,}% 98 | \@x{\@s{54.75} SubpaymentProposalRequest ,\, SubpaymentProposalResponse}% 99 | \@pvspace{8.0pt}% 100 | \@x{}% 101 | \@y{\@s{0}% 102 | Receipt signature 103 | }% 104 | \@xx{}% 105 | \@x{ {\CONSTANTS} R\_ReceiptSignature}% 106 | \@pvspace{8.0pt}% 107 | \@x{}\midbar\@xx{}% 108 | \@x{}% 109 | \@y{\@s{0}% 110 | Global variables 111 | }% 112 | \@xx{}% 113 | \@pvspace{8.0pt}% 114 | \@x{}% 115 | \@y{\@s{0}% 116 | Under synchrony we are allowed to have a global clock 117 | }% 118 | \@xx{}% 119 | \@x{ {\VARIABLE} clock}% 120 | \@pvspace{8.0pt}% 121 | \@x{}% 122 | \@y{\@s{0}% 123 | A bag of records representing requests and responses sent from one process 124 | }% 125 | \@xx{}% 126 | \@x{}% 127 | \@y{\@s{0}% 128 | to another 129 | }% 130 | \@xx{}% 131 | \@x{ {\VARIABLE} messages}% 132 | \@pvspace{8.0pt}% 133 | \@x{}\midbar\@xx{}% 134 | \@x{}% 135 | \@y{\@s{0}% 136 | Sender variables 137 | }% 138 | \@xx{}% 139 | \@pvspace{8.0pt}% 140 | \@x{}% 141 | \@y{\@s{0}% 142 | State of the sender (\ensuremath{S\_Ready}, \ensuremath{S\_Waiting}, 143 | \ensuremath{S\_Done}) 144 | }% 145 | \@xx{}% 146 | \@x{ {\VARIABLE} senderState}% 147 | \@pvspace{8.0pt}% 148 | \@x{}% 149 | \@y{\@s{0}% 150 | Whether the sender has received a response from a given connector 151 | }% 152 | \@xx{}% 153 | \@x{ {\VARIABLE} senderProposalResponses}% 154 | \@pvspace{8.0pt}% 155 | \@x{}% 156 | \@y{\@s{0}% 157 | All sender variables 158 | }% 159 | \@xx{}% 160 | \@x{ senderVars \.{\defeq} {\langle} senderState ,\, senderProposalResponses 161 | {\rangle}}% 162 | \@x{}\midbar\@xx{}% 163 | \@x{}% 164 | \@y{\@s{0}% 165 | Connector variables 166 | }% 167 | \@xx{}% 168 | \@pvspace{8.0pt}% 169 | \@x{}% 170 | \@y{\@s{0}% 171 | State of the connector (\ensuremath{C\_Ready}, \ensuremath{C\_Proposed}) 172 | }% 173 | \@xx{}% 174 | \@x{ {\VARIABLE} connectorState}% 175 | \@pvspace{8.0pt}% 176 | \@x{}% 177 | \@y{\@s{0}% 178 | All sender variables 179 | }% 180 | \@xx{}% 181 | \@x{ connectorVars \.{\defeq} {\langle} connectorState {\rangle}}% 182 | \@x{}\midbar\@xx{}% 183 | \@x{}% 184 | \@y{\@s{0}% 185 | The following variables are all per ledger (functions with domain 186 | \ensuremath{Ledger}) 187 | }% 188 | \@xx{}% 189 | \@pvspace{8.0pt}% 190 | \@x{}% 191 | \@y{\@s{0}% 192 | The ledger state (\ensuremath{L\_Proposed}, \ensuremath{L\_Prepared}, 193 | \ensuremath{L\_Executed} or \ensuremath{L\_Aborted}) 194 | }% 195 | \@xx{}% 196 | \@x{ {\VARIABLE} ledgerState}% 197 | \@pvspace{8.0pt}% 198 | \@x{}% 199 | \@y{\@s{0}% 200 | The timeouts for each of the the transfers 201 | }% 202 | \@xx{}% 203 | \@x{ {\VARIABLE} ledgerExpiration}% 204 | \@pvspace{8.0pt}% 205 | \@x{}% 206 | \@y{\@s{0}% 207 | All ledger variables 208 | }% 209 | \@xx{}% 210 | \@x{ ledgerVars \.{\defeq} {\langle} ledgerState ,\, ledgerExpiration 211 | {\rangle}}% 212 | \@x{}\midbar\@xx{}% 213 | \@pvspace{8.0pt}% 214 | \@x{}% 215 | \@y{\@s{0}% 216 | All variables; used for stuttering (asserting state hasn\mbox{'}t changed) 217 | }% 218 | \@xx{}% 219 | \@x{ vars \.{\defeq} {\langle} clock ,\, messages ,\, senderVars ,\, 220 | connectorVars ,\, ledgerVars {\rangle}}% 221 | \@pvspace{8.0pt}% 222 | \@x{}\midbar\@xx{}% 223 | \@x{}% 224 | \@y{\@s{0}% 225 | Helpers 226 | }% 227 | \@xx{}% 228 | \@pvspace{8.0pt}% 229 | \@x{}% 230 | \@y{\@s{0}% 231 | Add a set of new messages in transit 232 | }% 233 | \@xx{}% 234 | \@x{ Broadcast ( m ) \.{\defeq} messages \.{'} \.{=} messages \.{\oplus} 235 | SetToBag ( m )}% 236 | \@pvspace{8.0pt}% 237 | \@x{}% 238 | \@y{\@s{0}% 239 | Add a message to the bag of messages 240 | }% 241 | \@xx{}% 242 | \@x{ Send ( m ) \.{\defeq} Broadcast ( \{ m \} )}% 243 | \@pvspace{8.0pt}% 244 | \@x{}% 245 | \@y{\@s{0}% 246 | Remove a message from the bag of messages. Used when a process is done 247 | }% 248 | \@xx{}% 249 | \@x{}% 250 | \@y{\@s{0}% 251 | processing a message. 252 | }% 253 | \@xx{}% 254 | \@x{ Discard ( m ) \.{\defeq} messages \.{'} \.{=} messages \.{\ominus} 255 | SetToBag ( \{ m \} )}% 256 | \@pvspace{8.0pt}% 257 | \@x{}% 258 | \@y{\@s{0}% 259 | Respond to a message by sending multiple messages 260 | }% 261 | \@xx{}% 262 | \@x{ ReplyBroadcast ( responses ,\, request ) \.{\defeq}}% 263 | \@x{\@s{16.4} messages \.{'} \.{=} messages \.{\ominus} SetToBag ( \{ request 264 | \} ) \.{\oplus} SetToBag ( responses )}% 265 | \@pvspace{8.0pt}% 266 | \@x{}% 267 | \@y{\@s{0}% 268 | Combination of \ensuremath{Send} and \ensuremath{Discard 269 | }}% 270 | \@xx{}% 271 | \@x{ Reply ( response ,\, request ) \.{\defeq}}% 272 | \@x{\@s{16.4} ReplyBroadcast ( \{ response \} ,\, request )}% 273 | \@pvspace{16.0pt}% 274 | \@x{}% 275 | \@y{\@s{0}% 276 | Return the minimum value from a set, or undefined if the set is empty. 277 | }% 278 | \@xx{}% 279 | \@x{ Min ( s ) \.{\defeq} {\CHOOSE} x \.{\in} s \.{:} \A\, y \.{\in} s \.{:} 280 | x \.{\leq} y}% 281 | \@x{}% 282 | \@y{\@s{0}% 283 | Return the maximum value from a set, or undefined if the set is empty. 284 | }% 285 | \@xx{}% 286 | \@x{ Max ( s ) \.{\defeq} {\CHOOSE} x \.{\in} s \.{:} \A\, y \.{\in} s \.{:} 287 | x \.{\geq} y}% 288 | \@pvspace{8.0pt}% 289 | \@x{}% 290 | \@y{\@s{0}% 291 | Is a final ledger state 292 | }% 293 | \@xx{}% 294 | \@x{ IsFinalLedgerState ( i ) \.{\defeq} i \.{\in} \{ L\_Executed ,\, 295 | L\_Aborted \}}% 296 | \@pvspace{8.0pt}% 297 | \@x{}% 298 | \@y{\@s{0}% 299 | Sender 300 | }% 301 | \@xx{}% 302 | \@x{ Sender \.{\defeq} Min ( Participant )}% 303 | \@pvspace{8.0pt}% 304 | \@x{}% 305 | \@y{\@s{0}% 306 | Recipient 307 | }% 308 | \@xx{}% 309 | \@x{ Recipient \.{\defeq} Max ( Participant )}% 310 | \@pvspace{8.0pt}% 311 | \@x{}% 312 | \@y{\@s{0}% 313 | Set of connectors 314 | }% 315 | \@xx{}% 316 | \@x{ Connector \.{\defeq} Participant \.{\,\backslash\,} \{ Sender ,\, 317 | Recipient \}}% 318 | \@pvspace{8.0pt}% 319 | \@x{}% 320 | \@y{\@s{0}% 321 | The clock value we expect to be at after the proposal phase 322 | }% 323 | \@xx{}% 324 | \@x{ ClockAfterProposal \.{\defeq} 2 \.{*} Cardinality ( Connector ) \.{+} 2}% 325 | \@pvspace{8.0pt}% 326 | \@x{}% 327 | \@y{\@s{0}% 328 | The clock value we expect after the preparation phase 329 | }% 330 | \@xx{}% 331 | \@x{ ClockAfterPrepare \.{\defeq} ClockAfterProposal \.{+} 2 \.{*} 332 | Cardinality ( Ledger ) \.{+} 1}% 333 | \@pvspace{8.0pt}% 334 | \@x{}% 335 | \@y{\@s{0}% 336 | The clock value we expect to be at after the execution phase 337 | }% 338 | \@xx{}% 339 | \@x{ ClockAfterExecution \.{\defeq} ClockAfterPrepare \.{+} 2 \.{*} 340 | Cardinality ( Ledger ) \.{+} 1}% 341 | \@x{}\midbar\@xx{}% 342 | \@x{}% 343 | \@y{\@s{0}% 344 | Define type specification for all variables 345 | }% 346 | \@xx{}% 347 | \@pvspace{8.0pt}% 348 | \@x{ TypeOK \.{\defeq} \.{\land} clock \.{\in} Nat}% 349 | \@x{\@s{56.14} \.{\land} IsABag ( messages )}% 350 | \@x{\@s{56.14} \.{\land} senderState \.{\in} \{ S\_Ready ,\, 351 | S\_ProposalWaiting ,\, S\_Waiting ,\, S\_Done \}}% 352 | \@x{\@s{56.14} \.{\land} senderProposalResponses \.{\in} [ Connector 353 | \.{\rightarrow} {\BOOLEAN} ]}% 354 | \@x{\@s{56.14} \.{\land} connectorState \.{\in} [ Connector \.{\rightarrow} 355 | \{ C\_Ready ,\, C\_Proposed \} ]}% 356 | \@x{\@s{56.14} \.{\land} ledgerState \.{\in} [ Ledger \.{\rightarrow} \{ 357 | L\_Proposed ,\, L\_Prepared ,\, L\_Executed ,\, L\_Aborted \} ]}% 358 | \@x{\@s{56.14} \.{\land} ledgerExpiration \.{\in} [ Ledger \.{\rightarrow} 359 | Nat ]}% 360 | \@pvspace{8.0pt}% 361 | \@x{ Consistency \.{\defeq}}% 362 | \@x{\@s{16.4} \A\, l1 ,\, l2 \.{\in} Ledger \.{:} {\lnot} \.{\land} 363 | ledgerState [ l1 ] \.{=} L\_Aborted}% 364 | \@x{\@s{104.69} \.{\land} ledgerState [ l2 ] \.{=} L\_Executed}% 365 | \@pvspace{8.0pt}% 366 | \@x{ Inv \.{\defeq} \.{\land} TypeOK}% 367 | \@x{\@s{34.04} \.{\land} Consistency}% 368 | \@pvspace{8.0pt}% 369 | \@x{}\midbar\@xx{}% 370 | \@x{}% 371 | \@y{\@s{0}% 372 | Define initial values for all variables 373 | }% 374 | \@xx{}% 375 | \@pvspace{8.0pt}% 376 | \@x{ InitSenderVars \.{\defeq} \.{\land} senderState \.{=} S\_Ready}% 377 | \@x{\@s{85.43} \.{\land} senderProposalResponses \.{=} [ i \.{\in} Connector 378 | \.{\mapsto} {\FALSE} ]}% 379 | \@pvspace{8.0pt}% 380 | \@x{ InitConnectorVars \.{\defeq} connectorState \.{=} [ i \.{\in} Connector 381 | \.{\mapsto} C\_Ready ]}% 382 | \@pvspace{8.0pt}% 383 | \@x{ InitLedgerVars \.{\defeq} \.{\land} ledgerState \.{=} [ i\@s{3.38} 384 | \.{\in} Ledger \.{\mapsto} L\_Proposed ]}% 385 | \@x{\@s{84.03} \.{\land} ledgerExpiration \.{=} [ i \.{\in} Ledger 386 | \.{\mapsto} ClockAfterExecution \.{-} i ]}% 387 | \@pvspace{8.0pt}% 388 | \@x{ Init \.{\defeq} \.{\land} clock \.{=} 0}% 389 | \@x{\@s{35.70} \.{\land} messages \.{=} EmptyBag}% 390 | \@x{\@s{35.70} \.{\land} InitSenderVars}% 391 | \@x{\@s{35.70} \.{\land} InitConnectorVars}% 392 | \@x{\@s{35.70} \.{\land} InitLedgerVars}% 393 | \@pvspace{8.0pt}% 394 | \@x{}\midbar\@xx{}% 395 | \@x{}% 396 | \@y{\@s{0}% 397 | Define state transitions 398 | }% 399 | \@xx{}% 400 | \@pvspace{8.0pt}% 401 | \@x{}% 402 | \@y{\@s{0}% 403 | Participant \ensuremath{i} proposes all the subpayments 404 | }% 405 | \@xx{}% 406 | \@x{ StartProposalPhase ( i ) \.{\defeq}}% 407 | \@x{\@s{16.4} \.{\land} senderState \.{=} S\_Ready}% 408 | \@x{\@s{16.4} \.{\land} senderState \.{'} \.{=} S\_ProposalWaiting}% 409 | \@x{\@s{16.4} \.{\land} Broadcast ( \{ [}% 410 | \@x{\@s{35.71} mtype\@s{13.68} \.{\mapsto} SubpaymentProposalRequest ,\,}% 411 | \@x{\@s{35.71} msource\@s{4.1} \.{\mapsto} i ,\,}% 412 | \@x{\@s{35.71} mdest\@s{13.74} \.{\mapsto} k}% 413 | \@x{\@s{27.51} ] \.{:} k \.{\in} Connector \} )}% 414 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, connectorVars 415 | ,\, senderProposalResponses {\rangle}}% 416 | \@pvspace{8.0pt}% 417 | \@x{}% 418 | \@y{\@s{0}% 419 | Participant \ensuremath{i} starts off the preparation chain 420 | }% 421 | \@xx{}% 422 | \@x{ StartPreparationPhase ( i ) \.{\defeq}}% 423 | \@x{\@s{16.4} \.{\land} senderState \.{=} S\_ProposalWaiting}% 424 | \@x{\@s{16.4} \.{\land} \E\, p \.{\in} {\DOMAIN} senderProposalResponses 425 | \.{:} senderProposalResponses [ p ]}% 426 | \@x{\@s{16.4} \.{\land} senderState \.{'} \.{=} S\_Waiting}% 427 | \@x{\@s{16.4} \.{\land} Send ( [ mtype\@s{9.58} \.{\mapsto} PrepareRequest 428 | ,\,}% 429 | \@x{\@s{56.16} msource \.{\mapsto} i ,\,}% 430 | \@x{\@s{56.16} mdest\@s{9.64} \.{\mapsto} i \.{+} 1 ] )}% 431 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, connectorVars 432 | ,\, senderProposalResponses {\rangle}}% 433 | \@pvspace{8.0pt}% 434 | \@x{}% 435 | \@y{\@s{0}% 436 | Ledger spontaneously aborts 437 | }% 438 | \@xx{}% 439 | \@x{ LedgerAbort ( l ) \.{\defeq}}% 440 | \@x{\@s{16.4} \.{\land} ledgerState [ l ] \.{=} L\_Proposed}% 441 | \@x{\@s{16.4} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 442 | {\bang} [ l ] \.{=} L\_Aborted ]}% 443 | \@x{\@s{16.4} \.{\land} Send ( [ mtype\@s{9.58} \.{\mapsto} AbortNotify ,\,}% 444 | \@x{\@s{56.16} msource \.{\mapsto} l ,\,}% 445 | \@x{\@s{56.16} mdest\@s{9.64} \.{\mapsto} l \.{-} 1 ] )}% 446 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 447 | ,\, ledgerExpiration {\rangle}}% 448 | \@pvspace{8.0pt}% 449 | \@x{}% 450 | \@y{\@s{0}% 451 | Transfer times out 452 | }% 453 | \@xx{}% 454 | \@x{ LedgerTimeout ( l ) \.{\defeq}}% 455 | \@x{\@s{16.4} \.{\land} {\lnot} IsFinalLedgerState ( ledgerState [ l ] )}% 456 | \@x{\@s{16.4} \.{\land} ledgerExpiration [ l ] \.{\leq} clock}% 457 | \@x{\@s{16.4} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 458 | {\bang} [ l ] \.{=} L\_Aborted ]}% 459 | \@x{\@s{16.4} \.{\land} Send ( [ mtype\@s{9.58} \.{\mapsto} AbortNotify ,\,}% 460 | \@x{\@s{56.16} msource \.{\mapsto} l ,\,}% 461 | \@x{\@s{56.16} mdest\@s{9.64} \.{\mapsto} l \.{-} 1 ] )}% 462 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 463 | ,\, ledgerExpiration {\rangle}}% 464 | \@pvspace{8.0pt}% 465 | \@x{}% 466 | \@y{\@s{0}% 467 | If no messages are in flight and the sender isn\mbox{'}t doing anything, 468 | advance the 469 | }% 470 | \@xx{}% 471 | \@x{}% 472 | \@y{\@s{0}% 473 | clock 474 | }% 475 | \@xx{}% 476 | \@x{ NothingHappens \.{\defeq}}% 477 | \@x{\@s{16.4} \.{\land} clock \.{\leq} Max ( \{ ledgerExpiration [ x ] \.{:} 478 | x \.{\in} Ledger \} )}% 479 | \@x{\@s{16.4} \.{\land} BagCardinality ( messages ) \.{=} 0}% 480 | \@x{\@s{16.4} \.{\land} senderState \.{\neq} S\_Ready}% 481 | \@x{\@s{16.4} \.{\land} \.{\lor} senderState \.{\neq} S\_ProposalWaiting}% 482 | \@x{\@s{27.51} \.{\lor} \A\, p \.{\in} {\DOMAIN} senderProposalResponses 483 | \.{:} {\lnot} senderProposalResponses [ p ]}% 484 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} messages ,\, senderVars ,\, 485 | connectorVars ,\, ledgerVars {\rangle}}% 486 | \@pvspace{8.0pt}% 487 | \@x{}\midbar\@xx{}% 488 | \@x{}% 489 | \@y{\@s{0}% 490 | Message handlers 491 | }% 492 | \@xx{}% 493 | \@x{}% 494 | \@y{\@s{0}% 495 | \ensuremath{i \.{=}} recipient, \ensuremath{j \.{=}} sender, \ensuremath{m 496 | \.{=}} message 497 | }% 498 | \@xx{}% 499 | \@pvspace{8.0pt}% 500 | \@x{}% 501 | \@y{\@s{0}% 502 | Ledger \ensuremath{i} receives a Prepare request from participant 503 | \ensuremath{j 504 | }}% 505 | \@xx{}% 506 | \@x{ LedgerHandlePrepareRequest ( i ,\, j ,\, m ) \.{\defeq}}% 507 | \@x{\@s{16.4} \.{\LET} valid \.{\defeq} \.{\land} ledgerState [ i ] \.{=} 508 | L\_Proposed}% 509 | \@x{\@s{77.16} \.{\land} j \.{=} i \.{-} 1}% 510 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} valid}% 511 | \@x{\@s{47.91} \.{\land} i \.{\in} Ledger}% 512 | \@x{\@s{47.91} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 513 | {\bang} [ i ] \.{=} L\_Prepared ]}% 514 | \@x{\@s{47.91} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} PrepareNotify 515 | ,\,}% 516 | \@x{\@s{90.47} msource \.{\mapsto} i ,\,}% 517 | \@x{\@s{90.47} mdest\@s{9.64} \.{\mapsto} i \.{+} 1 ] ,\, m )}% 518 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 519 | ,\, ledgerExpiration {\rangle}}% 520 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} valid}% 521 | \@x{\@s{47.91} \.{\land} i \.{\in} Ledger}% 522 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 523 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 524 | ,\, ledgerVars {\rangle}}% 525 | \@pvspace{8.0pt}% 526 | \@x{}% 527 | \@y{\@s{0}% 528 | Ledger \ensuremath{i} receives an Execute request from process \ensuremath{j 529 | }}% 530 | \@xx{}% 531 | \@x{ LedgerHandleExecuteRequest ( i ,\, j ,\, m ) \.{\defeq}}% 532 | \@x{\@s{16.4} \.{\LET} valid \.{\defeq} \.{\land} ledgerState [ i ] \.{=} 533 | L\_Prepared}% 534 | \@x{\@s{77.16} \.{\land} ledgerExpiration [ i ] \.{>} clock}% 535 | \@x{\@s{77.16} \.{\land} m . mreceipt \.{=} R\_ReceiptSignature}% 536 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} valid}% 537 | \@x{\@s{47.91} \.{\land} ledgerState \.{'} \.{=} [ ledgerState {\EXCEPT} 538 | {\bang} [ i ] \.{=} L\_Executed ]}% 539 | \@x{\@s{47.91} \.{\land} Reply ( [ mtype\@s{12.29} \.{\mapsto} ExecuteNotify 540 | ,\,}% 541 | \@x{\@s{90.47} msource\@s{2.71} \.{\mapsto} i ,\,}% 542 | \@x{\@s{90.47} mdest\@s{12.35} \.{\mapsto} i \.{-} 1 ,\,}% 543 | \@x{\@s{90.47} mreceipt\@s{1.49} \.{\mapsto} m . mreceipt ] ,\, m )}% 544 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 545 | ,\, ledgerExpiration {\rangle}}% 546 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} valid}% 547 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 548 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 549 | ,\, ledgerVars {\rangle}}% 550 | \@pvspace{8.0pt}% 551 | \@x{}% 552 | \@y{\@s{0}% 553 | Ledger \ensuremath{i} receives a message 554 | }% 555 | \@xx{}% 556 | \@x{ LedgerReceive ( i ,\, j ,\, m ) \.{\defeq}}% 557 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} PrepareRequest}% 558 | \@x{\@s{27.51} \.{\land} LedgerHandlePrepareRequest ( i ,\, j ,\, m )}% 559 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} ExecuteRequest}% 560 | \@x{\@s{27.51} \.{\land} LedgerHandleExecuteRequest ( i ,\, j ,\, m )}% 561 | \@pvspace{8.0pt}% 562 | \@x{}% 563 | \@y{\@s{0}% 564 | Sender receives a \ensuremath{SubpaymentProposal} request 565 | }% 566 | \@xx{}% 567 | \@x{ SenderHandleSubpaymentProposalResponse ( i ,\, j ,\, m ) \.{\defeq}}% 568 | \@x{\@s{16.4} \.{\land} i \.{=} Sender}% 569 | \@x{\@s{16.4} \.{\land} senderProposalResponses \.{'} \.{=} [ 570 | senderProposalResponses {\EXCEPT} {\bang} [ j ] \.{=} {\TRUE} ]}% 571 | \@x{\@s{16.4} \.{\land} Discard ( m )}% 572 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} connectorVars ,\, ledgerVars 573 | ,\, senderState {\rangle}}% 574 | \@pvspace{8.0pt}% 575 | \@x{}% 576 | \@y{\@s{0}% 577 | Ledger \ensuremath{j} notifies sender that the transfer is executed 578 | }% 579 | \@xx{}% 580 | \@x{ SenderHandleExecuteNotify ( i ,\, j ,\, m ) \.{\defeq}}% 581 | \@x{\@s{16.4} \.{\lor} \.{\land} senderState \.{=} S\_Waiting}% 582 | \@x{\@s{27.51} \.{\land} senderState \.{'} \.{=} S\_Done}% 583 | \@x{\@s{27.51} \.{\land} Discard ( m )}% 584 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, connectorVars 585 | ,\, senderProposalResponses {\rangle}}% 586 | \@x{\@s{16.4} \.{\lor} \.{\land} senderState \.{\neq} S\_Waiting}% 587 | \@x{\@s{27.51} \.{\land} Discard ( m )}% 588 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 589 | ,\, ledgerVars {\rangle}}% 590 | \@pvspace{8.0pt}% 591 | \@x{}% 592 | \@y{\@s{0}% 593 | Ledger \ensuremath{j} notifies sender that the transfer is aborted 594 | }% 595 | \@xx{}% 596 | \@x{ SenderHandleAbortNotify ( i ,\, j ,\, m ) \.{\defeq}}% 597 | \@x{\@s{16.4} \.{\LET} isSenderWaiting \.{\defeq} senderState \.{\in} \{ 598 | S\_ProposalWaiting ,\, S\_Waiting ,\, S\_Ready \}}% 599 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} isSenderWaiting}% 600 | \@x{\@s{47.91} \.{\land} senderState \.{'} \.{=} S\_Done}% 601 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 602 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} ledgerVars ,\, connectorVars 603 | ,\, senderProposalResponses {\rangle}}% 604 | \@x{\@s{36.79} \.{\lor} \.{\land} {\lnot} isSenderWaiting}% 605 | \@x{\@s{47.91} \.{\land} Discard ( m )}% 606 | \@x{\@s{47.91} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 607 | ,\, ledgerVars {\rangle}}% 608 | \@pvspace{8.0pt}% 609 | \@x{}% 610 | \@y{\@s{0}% 611 | Sender receives a message 612 | }% 613 | \@xx{}% 614 | \@x{ SenderReceive ( i ,\, j ,\, m ) \.{\defeq}}% 615 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} SubpaymentProposalResponse}% 616 | \@x{\@s{27.51} \.{\land} SenderHandleSubpaymentProposalResponse ( i ,\, j ,\, 617 | m )}% 618 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} ExecuteNotify}% 619 | \@x{\@s{27.51} \.{\land} SenderHandleExecuteNotify ( i ,\, j ,\, m )}% 620 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} AbortNotify}% 621 | \@x{\@s{27.51} \.{\land} SenderHandleAbortNotify ( i ,\, j ,\, m )}% 622 | \@pvspace{8.0pt}% 623 | \@x{}% 624 | \@y{\@s{0}% 625 | Ledger \ensuremath{j} notifies recipient that the transfer is prepared 626 | }% 627 | \@xx{}% 628 | \@x{ RecipientHandlePrepareNotify ( i ,\, j ,\, m ) \.{\defeq}}% 629 | \@x{\@s{16.4} \.{\lor} \.{\land} Reply ( [ mtype\@s{12.29} \.{\mapsto} 630 | ExecuteRequest ,\,}% 631 | \@x{\@s{70.07} msource\@s{2.71} \.{\mapsto} i ,\,}% 632 | \@x{\@s{70.07} mdest\@s{12.35} \.{\mapsto} i \.{-} 1 ,\,}% 633 | \@x{\@s{70.07} mreceipt\@s{1.49} \.{\mapsto} R\_ReceiptSignature ] ,\, m )}% 634 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 635 | ,\, ledgerVars {\rangle}}% 636 | \@pvspace{8.0pt}% 637 | \@x{}% 638 | \@y{\@s{0}% 639 | Recipient receives a message 640 | }% 641 | \@xx{}% 642 | \@x{ RecipientReceive ( i ,\, j ,\, m ) \.{\defeq}}% 643 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} PrepareNotify}% 644 | \@x{\@s{27.51} \.{\land} RecipientHandlePrepareNotify ( i ,\, j ,\, m )}% 645 | \@pvspace{8.0pt}% 646 | \@x{}% 647 | \@y{\@s{0}% 648 | Connector \ensuremath{i} receives a \ensuremath{SubpaymentProposal} request 649 | }% 650 | \@xx{}% 651 | \@x{ ConnectorHandleSubpaymentProposalRequest ( i ,\, j ,\, m ) \.{\defeq}}% 652 | \@x{\@s{16.4} \.{\land} connectorState \.{'} \.{=} [ connectorState {\EXCEPT} 653 | {\bang} [ i ] \.{=} C\_Proposed ]}% 654 | \@x{\@s{16.4} \.{\land} Reply ( [ mtype\@s{13.68} \.{\mapsto} 655 | SubpaymentProposalResponse ,\,}% 656 | \@x{\@s{58.96} msource\@s{4.1} \.{\mapsto} i ,\,}% 657 | \@x{\@s{58.96} mdest\@s{13.74} \.{\mapsto} j ] ,\, m )}% 658 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, ledgerVars 659 | {\rangle}}% 660 | \@pvspace{8.0pt}% 661 | \@x{}% 662 | \@y{\@s{0}% 663 | Ledger \ensuremath{j} notifies connector \ensuremath{i} that the transfer is 664 | prepared 665 | }% 666 | \@xx{}% 667 | \@x{ ConnectorHandlePrepareNotify ( i ,\, j ,\, m ) \.{\defeq}}% 668 | \@x{\@s{16.4} \.{\lor} \.{\land} Reply ( [ mtype\@s{9.58} \.{\mapsto} 669 | PrepareRequest ,\,}% 670 | \@x{\@s{70.07} msource \.{\mapsto} i ,\,}% 671 | \@x{\@s{70.07} mdest\@s{9.64} \.{\mapsto} i \.{+} 1 ] ,\, m )}% 672 | \@x{\@s{27.51} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 673 | ,\, ledgerVars {\rangle}}% 674 | \@pvspace{8.0pt}% 675 | \@x{}% 676 | \@y{\@s{0}% 677 | Ledger \ensuremath{j} notifies connector \ensuremath{i} that the transfer is 678 | executed 679 | }% 680 | \@xx{}% 681 | \@x{ ConnectorHandleExecuteNotify ( i ,\, j ,\, m ) \.{\defeq}}% 682 | \@x{\@s{16.4} \.{\land} Reply ( [ mtype\@s{12.29} \.{\mapsto} ExecuteRequest 683 | ,\,}% 684 | \@x{\@s{58.96} msource\@s{2.71} \.{\mapsto} i ,\,}% 685 | \@x{\@s{58.96} mdest\@s{12.35} \.{\mapsto} i \.{-} 1 ,\,}% 686 | \@x{\@s{58.96} mreceipt\@s{1.49} \.{\mapsto} m . mreceipt ] ,\, m )}% 687 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 688 | ,\, ledgerVars {\rangle}}% 689 | \@pvspace{8.0pt}% 690 | \@x{}% 691 | \@y{\@s{0}% 692 | Ledger \ensuremath{j} notifies connector \ensuremath{i} that the transfer is 693 | aborted 694 | }% 695 | \@xx{}% 696 | \@x{ ConnectorHandleAbortNotify ( i ,\, j ,\, m ) \.{\defeq}}% 697 | \@x{\@s{16.4} \.{\land} Discard ( m )}% 698 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} {\langle} senderVars ,\, connectorVars 699 | ,\, ledgerVars {\rangle}}% 700 | \@pvspace{8.0pt}% 701 | \@x{}% 702 | \@y{\@s{0}% 703 | Connector receives a message 704 | }% 705 | \@xx{}% 706 | \@x{ ConnectorReceive ( i ,\, j ,\, m ) \.{\defeq}}% 707 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} SubpaymentProposalRequest}% 708 | \@x{\@s{27.51} \.{\land} ConnectorHandleSubpaymentProposalRequest ( i ,\, j 709 | ,\, m )}% 710 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} PrepareNotify}% 711 | \@x{\@s{27.51} \.{\land} ConnectorHandlePrepareNotify ( i ,\, j ,\, m )}% 712 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} ExecuteNotify}% 713 | \@x{\@s{27.51} \.{\land} ConnectorHandleExecuteNotify ( i ,\, j ,\, m )}% 714 | \@x{\@s{16.4} \.{\lor} \.{\land} m . mtype \.{=} AbortNotify}% 715 | \@x{\@s{27.51} \.{\land} ConnectorHandleAbortNotify ( i ,\, j ,\, m )}% 716 | \@pvspace{8.0pt}% 717 | \@x{}% 718 | \@y{\@s{0}% 719 | Receive a message 720 | }% 721 | \@xx{}% 722 | \@x{ Receive ( m ) \.{\defeq}}% 723 | \@x{\@s{16.4} \.{\LET} i\@s{0.42} \.{\defeq} m . mdest}% 724 | \@x{\@s{36.79} j \.{\defeq} m . msource}% 725 | \@x{\@s{16.4} \.{\IN} \.{\lor} \.{\land} i \.{\in} Ledger}% 726 | \@x{\@s{47.91} \.{\land} LedgerReceive ( i ,\, j ,\, m )}% 727 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{=} Sender}% 728 | \@x{\@s{47.91} \.{\land} SenderReceive ( i ,\, j ,\, m )}% 729 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{=} Recipient}% 730 | \@x{\@s{47.91} \.{\land} RecipientReceive ( i ,\, j ,\, m )}% 731 | \@x{\@s{36.79} \.{\lor} \.{\land} i \.{\in} Connector}% 732 | \@x{\@s{47.91} \.{\land} ConnectorReceive ( i ,\, j ,\, m )}% 733 | \@pvspace{8.0pt}% 734 | \@x{}% 735 | \@y{\@s{0}% 736 | End of message handlers 737 | }% 738 | \@xx{}% 739 | \@x{}\midbar\@xx{}% 740 | \@x{}% 741 | \@y{\@s{0}% 742 | Defines how the variables may transition 743 | }% 744 | \@xx{}% 745 | \@pvspace{8.0pt}% 746 | \@x{ Termination \.{\defeq}}% 747 | \@x{\@s{16.4} \.{\land} \A\, l \.{\in} Ledger \.{:} IsFinalLedgerState ( 748 | ledgerState [ l ] )}% 749 | \@x{\@s{16.4} \.{\land} senderState \.{=} S\_Done}% 750 | \@x{\@s{16.4} \.{\land} {\UNCHANGED} vars}% 751 | \@pvspace{8.0pt}% 752 | \@x{ Next \.{\defeq} \.{\lor} \.{\land} \.{\lor} StartProposalPhase ( Sender 753 | )}% 754 | \@x{\@s{62.05} \.{\lor} StartPreparationPhase ( Sender )}% 755 | \@x{\@s{62.05} \.{\lor} \E\, l\@s{5.35} \.{\in} Ledger \.{:} LedgerAbort ( l 756 | )}% 757 | \@x{\@s{62.05} \.{\lor} \E\, l\@s{5.35} \.{\in} Ledger \.{:} LedgerTimeout ( 758 | l )}% 759 | \@x{\@s{62.05} \.{\lor} \E\, m \.{\in} {\DOMAIN} messages \.{:} Receive ( m 760 | )}% 761 | \@x{\@s{62.05} \.{\lor} NothingHappens}% 762 | \@x{\@s{50.94} \.{\land} clock \.{'} \.{=} clock \.{+} 1}% 763 | \@x{\@s{39.83} \.{\lor} Termination}% 764 | \@pvspace{8.0pt}% 765 | \@x{}% 766 | \@y{\@s{0}% 767 | The specification must start with the initial state and transition according 768 | }% 769 | \@xx{}% 770 | \@x{}% 771 | \@y{\@s{0}% 772 | to \ensuremath{Next}. 773 | }% 774 | \@xx{}% 775 | \@x{ Spec \.{\defeq} Init \.{\land} {\Box} [ Next ]_{ vars}}% 776 | \@pvspace{8.0pt}% 777 | \@x{}\bottombar\@xx{}% 778 | \end{document} -------------------------------------------------------------------------------- /acm.bst: -------------------------------------------------------------------------------- 1 | % Copyright (C) 1986, 1988, 2010 Howard Trickey and Oren Patashnik. 2 | % Unlimited copying and redistribution of this file are permitted as long as 3 | % it is unmodified. Modifications (and redistribution of modified versions) 4 | % are also permitted, but only if the resulting file is renamed. 5 | % 6 | % ACM Transactions bibliography style (8-Dec-10 version) 7 | % A lot like abbrv.bst, but names come out "Last, initials", and in \sc. 8 | % Some dates are parenthesized. 9 | % 10 | % History 11 | % 2/ 6/86 (HWT) Original version, by Howard Trickey. 12 | % 3/ 5/86 (HWT) Put in pp. everywhere but articles, as per ACM style. 13 | % 1/24/88 (OP&HWT) Updated for BibTeX version 0.99a, Oren Patashnik; 14 | % corrected the abbreviations to "Mar." and "Sept."; 15 | % THIS `acm' VERSION DOES NOT WORK WITH BIBTEX 0.98i. 16 | % 12/ 8/10 (OP&HWT) Clarify license. 17 | 18 | ENTRY 19 | { address 20 | author 21 | booktitle 22 | chapter 23 | edition 24 | editor 25 | howpublished 26 | institution 27 | journal 28 | key 29 | month 30 | note 31 | number 32 | organization 33 | pages 34 | publisher 35 | school 36 | series 37 | title 38 | type 39 | volume 40 | year 41 | } 42 | {} 43 | { label } 44 | 45 | INTEGERS { output.state before.all mid.sentence after.sentence after.block } 46 | 47 | FUNCTION {init.state.consts} 48 | { #0 'before.all := 49 | #1 'mid.sentence := 50 | #2 'after.sentence := 51 | #3 'after.block := 52 | } 53 | 54 | STRINGS { s t } 55 | 56 | FUNCTION {output.nonnull} 57 | { 's := 58 | output.state mid.sentence = 59 | { ", " * write$ } 60 | { output.state after.block = 61 | { add.period$ write$ 62 | newline$ 63 | "\newblock " write$ 64 | } 65 | { output.state before.all = 66 | 'write$ 67 | { add.period$ " " * write$ } 68 | if$ 69 | } 70 | if$ 71 | mid.sentence 'output.state := 72 | } 73 | if$ 74 | s 75 | } 76 | 77 | FUNCTION {output} 78 | { duplicate$ empty$ 79 | 'pop$ 80 | 'output.nonnull 81 | if$ 82 | } 83 | 84 | FUNCTION {output.check} 85 | { 't := 86 | duplicate$ empty$ 87 | { pop$ "empty " t * " in " * cite$ * warning$ } 88 | 'output.nonnull 89 | if$ 90 | } 91 | 92 | FUNCTION {output.bibitem} 93 | { newline$ 94 | "\bibitem{" write$ 95 | cite$ write$ 96 | "}" write$ 97 | newline$ 98 | "" 99 | before.all 'output.state := 100 | } 101 | 102 | FUNCTION {fin.entry} 103 | { add.period$ 104 | write$ 105 | newline$ 106 | } 107 | 108 | FUNCTION {new.block} 109 | { output.state before.all = 110 | 'skip$ 111 | { after.block 'output.state := } 112 | if$ 113 | } 114 | 115 | FUNCTION {new.sentence} 116 | { output.state after.block = 117 | 'skip$ 118 | { output.state before.all = 119 | 'skip$ 120 | { after.sentence 'output.state := } 121 | if$ 122 | } 123 | if$ 124 | } 125 | 126 | FUNCTION {not} 127 | { { #0 } 128 | { #1 } 129 | if$ 130 | } 131 | 132 | FUNCTION {and} 133 | { 'skip$ 134 | { pop$ #0 } 135 | if$ 136 | } 137 | 138 | FUNCTION {or} 139 | { { pop$ #1 } 140 | 'skip$ 141 | if$ 142 | } 143 | 144 | FUNCTION {new.block.checka} 145 | { empty$ 146 | 'skip$ 147 | 'new.block 148 | if$ 149 | } 150 | 151 | FUNCTION {new.block.checkb} 152 | { empty$ 153 | swap$ empty$ 154 | and 155 | 'skip$ 156 | 'new.block 157 | if$ 158 | } 159 | 160 | FUNCTION {field.or.null} 161 | { duplicate$ empty$ 162 | { pop$ "" } 163 | 'skip$ 164 | if$ 165 | } 166 | 167 | FUNCTION {emphasize} 168 | { duplicate$ empty$ 169 | { pop$ "" } 170 | { "{\em " swap$ * "}" * } 171 | if$ 172 | } 173 | 174 | FUNCTION {emphasizeic} 175 | { duplicate$ empty$ 176 | { pop$ "" } 177 | { "{\em " swap$ * "\/}" * } 178 | if$ 179 | } 180 | 181 | FUNCTION {scapify} 182 | { duplicate$ empty$ 183 | { pop$ "" } 184 | { "{\sc " swap$ * "}" * } 185 | if$ 186 | } 187 | 188 | INTEGERS { nameptr namesleft numnames } 189 | 190 | FUNCTION {format.names} 191 | { 's := 192 | #1 'nameptr := 193 | s num.names$ 'numnames := 194 | numnames 'namesleft := 195 | { namesleft #0 > } 196 | { s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't := 197 | nameptr #1 > 198 | { namesleft #1 > 199 | { ", " * t * } 200 | { t "others" = 201 | { ", et~al." * } 202 | { ", and " * t * } 203 | if$ 204 | } 205 | if$ 206 | } 207 | 't 208 | if$ 209 | nameptr #1 + 'nameptr := 210 | namesleft #1 - 'namesleft := 211 | } 212 | while$ 213 | } 214 | 215 | % For names inside entries (e.g., editors of an "In ..."); 216 | % this is exactly ABBRV.BST's `format.names' function. 217 | FUNCTION {format.innames} 218 | { 's := 219 | #1 'nameptr := 220 | s num.names$ 'numnames := 221 | numnames 'namesleft := 222 | { namesleft #0 > } 223 | { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't := 224 | nameptr #1 > 225 | { namesleft #1 > 226 | { ", " * t * } 227 | { numnames #2 > 228 | { "," * } 229 | 'skip$ 230 | if$ 231 | t "others" = 232 | { " et~al." * } 233 | { " and " * t * } 234 | if$ 235 | } 236 | if$ 237 | } 238 | 't 239 | if$ 240 | nameptr #1 + 'nameptr := 241 | namesleft #1 - 'namesleft := 242 | } 243 | while$ 244 | } 245 | 246 | FUNCTION {format.authors} 247 | { author empty$ 248 | { "" } 249 | { author format.names scapify } 250 | if$ 251 | } 252 | 253 | FUNCTION {format.editors} 254 | { editor empty$ 255 | { "" } 256 | { editor format.names scapify 257 | editor num.names$ #1 > 258 | { ", Eds." * } 259 | { ", Ed." * } 260 | if$ 261 | } 262 | if$ 263 | } 264 | 265 | FUNCTION {format.ineditors} 266 | { editor empty$ 267 | { "" } 268 | { editor format.innames 269 | editor num.names$ #1 > 270 | { ", Eds." * } 271 | { ", Ed." * } 272 | if$ 273 | } 274 | if$ 275 | } 276 | 277 | FUNCTION {format.title} 278 | { title empty$ 279 | { "" } 280 | { title "t" change.case$ } 281 | if$ 282 | } 283 | 284 | FUNCTION {n.dashify} 285 | { 't := 286 | "" 287 | { t empty$ not } 288 | { t #1 #1 substring$ "-" = 289 | { t #1 #2 substring$ "--" = not 290 | { "--" * 291 | t #2 global.max$ substring$ 't := 292 | } 293 | { { t #1 #1 substring$ "-" = } 294 | { "-" * 295 | t #2 global.max$ substring$ 't := 296 | } 297 | while$ 298 | } 299 | if$ 300 | } 301 | { t #1 #1 substring$ * 302 | t #2 global.max$ substring$ 't := 303 | } 304 | if$ 305 | } 306 | while$ 307 | } 308 | 309 | FUNCTION {format.date} 310 | { year empty$ 311 | { month empty$ 312 | { "" } 313 | { "there's a month but no year in " cite$ * warning$ 314 | month 315 | } 316 | if$ 317 | } 318 | { month empty$ 319 | 'year 320 | { month " " * year * } 321 | if$ 322 | } 323 | if$ 324 | } 325 | 326 | FUNCTION {format.btitle} 327 | { title emphasize 328 | } 329 | 330 | FUNCTION {tie.or.space.connect} 331 | { duplicate$ text.length$ #3 < 332 | { "~" } 333 | { " " } 334 | if$ 335 | swap$ * * 336 | } 337 | 338 | FUNCTION {either.or.check} 339 | { empty$ 340 | 'pop$ 341 | { "can't use both " swap$ * " fields in " * cite$ * warning$ } 342 | if$ 343 | } 344 | 345 | FUNCTION {format.bvolume} 346 | { volume empty$ 347 | { "" } 348 | { "vol.~" volume * 349 | series empty$ 350 | 'skip$ 351 | { " of " * series emphasize * } 352 | if$ 353 | "volume and number" number either.or.check 354 | } 355 | if$ 356 | } 357 | 358 | FUNCTION {format.number.series} 359 | { volume empty$ 360 | { number empty$ 361 | { series field.or.null } 362 | { output.state mid.sentence = 363 | { "no.~" } 364 | { "No.~" } 365 | if$ 366 | number * 367 | series empty$ 368 | { "there's a number but no series in " cite$ * warning$ } 369 | { " in " * series * } 370 | if$ 371 | } 372 | if$ 373 | } 374 | { "" } 375 | if$ 376 | } 377 | 378 | FUNCTION {format.edition} 379 | { edition empty$ 380 | { "" } 381 | { output.state mid.sentence = 382 | { edition "l" change.case$ "~ed." * } 383 | { edition "t" change.case$ "~ed." * } 384 | if$ 385 | } 386 | if$ 387 | } 388 | 389 | FUNCTION {format.pages} 390 | { pages empty$ 391 | { "" } 392 | { pages n.dashify } 393 | if$ 394 | } 395 | 396 | INTEGERS { multiresult } 397 | 398 | FUNCTION {multi.page.check} 399 | { 't := 400 | #0 'multiresult := 401 | { multiresult not 402 | t empty$ not 403 | and 404 | } 405 | { t #1 #1 substring$ 406 | duplicate$ "-" = 407 | swap$ duplicate$ "," = 408 | swap$ "+" = 409 | or or 410 | { #1 'multiresult := } 411 | { t #2 global.max$ substring$ 't := } 412 | if$ 413 | } 414 | while$ 415 | multiresult 416 | } 417 | 418 | FUNCTION {format.pp.pages} 419 | { pages empty$ 420 | { "" } 421 | { pages multi.page.check 422 | { "pp.~" pages n.dashify * } 423 | { "p.~" pages * } 424 | if$ 425 | } 426 | if$ 427 | } 428 | 429 | FUNCTION {format.journal.vol.num.date} 430 | { journal empty$ 431 | { "empty journal in " cite$ * warning$ 432 | "" 433 | } 434 | { journal 435 | volume empty$ 436 | 'skip$ 437 | { " " * volume * } 438 | if$ 439 | number empty$ 440 | 'emphasizeic 441 | { emphasize ", " * number * } 442 | if$ 443 | year empty$ 444 | { "empty year in " cite$ * warning$ } 445 | { " (" * format.date * ")" * } 446 | if$ 447 | } 448 | if$ 449 | } 450 | 451 | FUNCTION {format.chapter.pages} 452 | { chapter empty$ 453 | 'format.pp.pages 454 | { type empty$ 455 | { "ch.~" chapter * } 456 | { type "l" change.case$ chapter tie.or.space.connect } 457 | if$ 458 | pages empty$ 459 | 'skip$ 460 | { ", " * format.pp.pages * } 461 | if$ 462 | } 463 | if$ 464 | } 465 | 466 | FUNCTION {format.in.ed.booktitle} 467 | { booktitle empty$ 468 | { "" } 469 | { "In " booktitle emphasize * 470 | editor empty$ 471 | 'skip$ 472 | { ", " * format.ineditors * } 473 | if$ 474 | } 475 | if$ 476 | } 477 | 478 | % The proceedings title (it's on the stack) gets an (address, date) appended 479 | FUNCTION {format.proc.date} 480 | { duplicate$ empty$ 481 | { pop$ "" } 482 | { year empty$ 483 | { "empty year in " cite$ * warning$ 484 | address empty$ 485 | 'emphasize 486 | { emphasizeic 487 | " (" * address * ")" * 488 | } 489 | if$ 490 | } 491 | { emphasizeic 492 | " (" * 493 | address empty$ 494 | 'skip$ 495 | { address * ", " * } 496 | if$ 497 | format.date * 498 | ")" * 499 | } 500 | if$ 501 | } 502 | if$ 503 | } 504 | 505 | FUNCTION {format.in.proc.date} 506 | { booktitle empty$ 507 | { "" } 508 | { "In " booktitle format.proc.date * } 509 | if$ 510 | } 511 | 512 | FUNCTION {empty.misc.check} 513 | { author empty$ title empty$ howpublished empty$ 514 | month empty$ year empty$ note empty$ 515 | and and and and and 516 | key empty$ not and 517 | { "all relevant fields are empty in " cite$ * warning$ } 518 | 'skip$ 519 | if$ 520 | } 521 | 522 | FUNCTION {format.thesis.type} 523 | { type empty$ 524 | 'skip$ 525 | { pop$ 526 | type "t" change.case$ 527 | } 528 | if$ 529 | } 530 | 531 | FUNCTION {format.tr.number} 532 | { type empty$ 533 | { "Tech. Rep." } 534 | 'type 535 | if$ 536 | number empty$ 537 | { "t" change.case$ } 538 | { number tie.or.space.connect } 539 | if$ 540 | } 541 | 542 | FUNCTION {format.article.crossref} 543 | { key empty$ 544 | { journal empty$ 545 | { "need key or journal for " cite$ * " to crossref " * crossref * 546 | warning$ 547 | "" 548 | } 549 | { "In {\em " journal * "\/}" * } 550 | if$ 551 | } 552 | { "In " key * } 553 | if$ 554 | " \cite{" * crossref * "}" * 555 | } 556 | 557 | FUNCTION {format.crossref.editor} 558 | { editor #1 "{vv~}{ll}" format.name$ 559 | editor num.names$ duplicate$ 560 | #2 > 561 | { pop$ " et~al." * } 562 | { #2 < 563 | 'skip$ 564 | { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = 565 | { " et~al." * } 566 | { " and " * editor #2 "{vv~}{ll}" format.name$ * } 567 | if$ 568 | } 569 | if$ 570 | } 571 | if$ 572 | } 573 | 574 | FUNCTION {format.book.crossref} 575 | { volume empty$ 576 | { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ 577 | "In " 578 | } 579 | { "Vol.~" volume * 580 | " of " * 581 | } 582 | if$ 583 | editor empty$ 584 | editor field.or.null author field.or.null = 585 | or 586 | { key empty$ 587 | { series empty$ 588 | { "need editor, key, or series for " cite$ * " to crossref " * 589 | crossref * warning$ 590 | "" * 591 | } 592 | { "{\em " * series * "\/}" * } 593 | if$ 594 | } 595 | { key * } 596 | if$ 597 | } 598 | { format.crossref.editor * } 599 | if$ 600 | " \cite{" * crossref * "}" * 601 | } 602 | 603 | FUNCTION {format.incoll.inproc.crossref} 604 | { editor empty$ 605 | editor field.or.null author field.or.null = 606 | or 607 | { key empty$ 608 | { booktitle empty$ 609 | { "need editor, key, or booktitle for " cite$ * " to crossref " * 610 | crossref * warning$ 611 | "" 612 | } 613 | { "In {\em " booktitle * "\/}" * } 614 | if$ 615 | } 616 | { "In " key * } 617 | if$ 618 | } 619 | { "In " format.crossref.editor * } 620 | if$ 621 | " \cite{" * crossref * "}" * 622 | } 623 | 624 | FUNCTION {article} 625 | { output.bibitem 626 | format.authors "author" output.check 627 | new.block 628 | format.title "title" output.check 629 | new.block 630 | crossref missing$ 631 | { format.journal.vol.num.date output 632 | format.pages output 633 | } 634 | { format.article.crossref output.nonnull 635 | format.pp.pages output 636 | } 637 | if$ 638 | new.block 639 | note output 640 | fin.entry 641 | } 642 | 643 | FUNCTION {book} 644 | { output.bibitem 645 | author empty$ 646 | { format.editors "author and editor" output.check } 647 | { format.authors output.nonnull 648 | crossref missing$ 649 | { "author and editor" editor either.or.check } 650 | 'skip$ 651 | if$ 652 | } 653 | if$ 654 | new.block 655 | format.btitle "title" output.check 656 | format.edition output 657 | crossref missing$ 658 | { format.bvolume output 659 | new.block 660 | format.number.series output 661 | new.sentence 662 | publisher "publisher" output.check 663 | address output 664 | } 665 | { new.block 666 | format.book.crossref output.nonnull 667 | } 668 | if$ 669 | format.date "year" output.check 670 | new.block 671 | note output 672 | fin.entry 673 | } 674 | 675 | FUNCTION {booklet} 676 | { output.bibitem 677 | format.authors output 678 | new.block 679 | format.title "title" output.check 680 | howpublished address new.block.checkb 681 | howpublished output 682 | address output 683 | format.date output 684 | new.block 685 | note output 686 | fin.entry 687 | } 688 | 689 | FUNCTION {inbook} 690 | { output.bibitem 691 | author empty$ 692 | { format.editors "author and editor" output.check } 693 | { format.authors output.nonnull 694 | crossref missing$ 695 | { "author and editor" editor either.or.check } 696 | 'skip$ 697 | if$ 698 | } 699 | if$ 700 | new.block 701 | format.btitle "title" output.check 702 | format.edition output 703 | crossref missing$ 704 | { format.bvolume output 705 | new.block 706 | format.number.series output 707 | new.sentence 708 | publisher "publisher" output.check 709 | address output 710 | } 711 | { new.block 712 | format.book.crossref output.nonnull 713 | } 714 | if$ 715 | format.date "year" output.check 716 | format.chapter.pages "chapter and pages" output.check 717 | new.block 718 | note output 719 | fin.entry 720 | } 721 | 722 | FUNCTION {incollection} 723 | { output.bibitem 724 | format.authors "author" output.check 725 | new.block 726 | format.title "title" output.check 727 | new.block 728 | crossref missing$ 729 | { format.in.ed.booktitle "booktitle" output.check 730 | format.edition output 731 | format.bvolume output 732 | format.number.series output 733 | new.sentence 734 | publisher "publisher" output.check 735 | address output 736 | format.date "year" output.check 737 | } 738 | { format.incoll.inproc.crossref output.nonnull } 739 | if$ 740 | format.chapter.pages output 741 | new.block 742 | note output 743 | fin.entry 744 | } 745 | 746 | FUNCTION {inproceedings} 747 | { output.bibitem 748 | format.authors "author" output.check 749 | new.block 750 | format.title "title" output.check 751 | new.block 752 | crossref missing$ 753 | { format.in.proc.date "booktitle" output.check 754 | format.ineditors output 755 | format.bvolume output 756 | format.number.series output 757 | organization output 758 | publisher output 759 | } 760 | { format.incoll.inproc.crossref output.nonnull } 761 | if$ 762 | format.pp.pages output 763 | new.block 764 | note output 765 | fin.entry 766 | } 767 | 768 | FUNCTION {conference} { inproceedings } 769 | 770 | FUNCTION {manual} 771 | { output.bibitem 772 | author empty$ 773 | { organization scapify output } 774 | { format.authors output.nonnull } 775 | if$ 776 | new.block 777 | format.btitle "title" output.check 778 | format.edition output 779 | author empty$ 780 | { address new.block.checka } 781 | { organization address new.block.checkb 782 | organization output 783 | } 784 | if$ 785 | address output 786 | format.date output 787 | new.block 788 | note output 789 | fin.entry 790 | } 791 | 792 | FUNCTION {mastersthesis} 793 | { output.bibitem 794 | format.authors "author" output.check 795 | new.block 796 | format.title "title" output.check 797 | new.block 798 | "Master's thesis" format.thesis.type output.nonnull 799 | school "school" output.check 800 | address output 801 | format.date "year" output.check 802 | new.block 803 | note output 804 | fin.entry 805 | } 806 | 807 | FUNCTION {misc} 808 | { output.bibitem 809 | format.authors output 810 | title howpublished new.block.checkb 811 | format.title output 812 | howpublished new.block.checka 813 | howpublished output 814 | format.date output 815 | new.block 816 | note output 817 | fin.entry 818 | empty.misc.check 819 | } 820 | 821 | FUNCTION {phdthesis} 822 | { output.bibitem 823 | format.authors "author" output.check 824 | new.block 825 | format.btitle "title" output.check 826 | new.block 827 | "PhD thesis" format.thesis.type output.nonnull 828 | school "school" output.check 829 | address output 830 | format.date "year" output.check 831 | new.block 832 | note output 833 | fin.entry 834 | } 835 | 836 | FUNCTION {proceedings} 837 | { output.bibitem 838 | editor empty$ 839 | { organization scapify output } 840 | { format.editors output.nonnull } 841 | if$ 842 | new.block 843 | title format.proc.date "title" output.check 844 | format.bvolume output 845 | format.number.series output 846 | editor empty$ 847 | 'skip$ 848 | { organization output } 849 | if$ 850 | publisher output 851 | new.block 852 | note output 853 | fin.entry 854 | } 855 | 856 | FUNCTION {techreport} 857 | { output.bibitem 858 | format.authors "author" output.check 859 | new.block 860 | format.title "title" output.check 861 | new.block 862 | format.tr.number output.nonnull 863 | institution "institution" output.check 864 | address output 865 | format.date "year" output.check 866 | new.block 867 | note output 868 | fin.entry 869 | } 870 | 871 | FUNCTION {unpublished} 872 | { output.bibitem 873 | format.authors "author" output.check 874 | new.block 875 | format.title "title" output.check 876 | new.block 877 | note "note" output.check 878 | format.date output 879 | fin.entry 880 | } 881 | 882 | FUNCTION {default.type} { misc } 883 | 884 | MACRO {jan} {"Jan."} 885 | 886 | MACRO {feb} {"Feb."} 887 | 888 | MACRO {mar} {"Mar."} 889 | 890 | MACRO {apr} {"Apr."} 891 | 892 | MACRO {may} {"May"} 893 | 894 | MACRO {jun} {"June"} 895 | 896 | MACRO {jul} {"July"} 897 | 898 | MACRO {aug} {"Aug."} 899 | 900 | MACRO {sep} {"Sept."} 901 | 902 | MACRO {oct} {"Oct."} 903 | 904 | MACRO {nov} {"Nov."} 905 | 906 | MACRO {dec} {"Dec."} 907 | 908 | MACRO {acmcs} {"ACM Comput. Surv."} 909 | 910 | MACRO {acta} {"Acta Inf."} 911 | 912 | MACRO {cacm} {"Commun. ACM"} 913 | 914 | MACRO {ibmjrd} {"IBM J. Res. Dev."} 915 | 916 | MACRO {ibmsj} {"IBM Syst.~J."} 917 | 918 | MACRO {ieeese} {"IEEE Trans. Softw. Eng."} 919 | 920 | MACRO {ieeetc} {"IEEE Trans. Comput."} 921 | 922 | MACRO {ieeetcad} 923 | {"IEEE Trans. Comput.-Aided Design Integrated Circuits"} 924 | 925 | MACRO {ipl} {"Inf. Process. Lett."} 926 | 927 | MACRO {jacm} {"J.~ACM"} 928 | 929 | MACRO {jcss} {"J.~Comput. Syst. Sci."} 930 | 931 | MACRO {scp} {"Sci. Comput. Programming"} 932 | 933 | MACRO {sicomp} {"SIAM J. Comput."} 934 | 935 | MACRO {tocs} {"ACM Trans. Comput. Syst."} 936 | 937 | MACRO {tods} {"ACM Trans. Database Syst."} 938 | 939 | MACRO {tog} {"ACM Trans. Gr."} 940 | 941 | MACRO {toms} {"ACM Trans. Math. Softw."} 942 | 943 | MACRO {toois} {"ACM Trans. Office Inf. Syst."} 944 | 945 | MACRO {toplas} {"ACM Trans. Program. Lang. Syst."} 946 | 947 | MACRO {tcs} {"Theoretical Comput. Sci."} 948 | 949 | READ 950 | 951 | FUNCTION {sortify} 952 | { purify$ 953 | "l" change.case$ 954 | } 955 | 956 | INTEGERS { len } 957 | 958 | FUNCTION {chop.word} 959 | { 's := 960 | 'len := 961 | s #1 len substring$ = 962 | { s len #1 + global.max$ substring$ } 963 | 's 964 | if$ 965 | } 966 | 967 | FUNCTION {sort.format.names} 968 | { 's := 969 | #1 'nameptr := 970 | "" 971 | s num.names$ 'numnames := 972 | numnames 'namesleft := 973 | { namesleft #0 > } 974 | { nameptr #1 > 975 | { " " * } 976 | 'skip$ 977 | if$ 978 | s nameptr "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" format.name$ 't := 979 | nameptr numnames = t "others" = and 980 | { "et al" * } 981 | { t sortify * } 982 | if$ 983 | nameptr #1 + 'nameptr := 984 | namesleft #1 - 'namesleft := 985 | } 986 | while$ 987 | } 988 | 989 | FUNCTION {sort.format.title} 990 | { 't := 991 | "A " #2 992 | "An " #3 993 | "The " #4 t chop.word 994 | chop.word 995 | chop.word 996 | sortify 997 | #1 global.max$ substring$ 998 | } 999 | 1000 | FUNCTION {author.sort} 1001 | { author empty$ 1002 | { key empty$ 1003 | { "to sort, need author or key in " cite$ * warning$ 1004 | "" 1005 | } 1006 | { key sortify } 1007 | if$ 1008 | } 1009 | { author sort.format.names } 1010 | if$ 1011 | } 1012 | 1013 | FUNCTION {author.editor.sort} 1014 | { author empty$ 1015 | { editor empty$ 1016 | { key empty$ 1017 | { "to sort, need author, editor, or key in " cite$ * warning$ 1018 | "" 1019 | } 1020 | { key sortify } 1021 | if$ 1022 | } 1023 | { editor sort.format.names } 1024 | if$ 1025 | } 1026 | { author sort.format.names } 1027 | if$ 1028 | } 1029 | 1030 | FUNCTION {author.organization.sort} 1031 | { author empty$ 1032 | { organization empty$ 1033 | { key empty$ 1034 | { "to sort, need author, organization, or key in " cite$ * warning$ 1035 | "" 1036 | } 1037 | { key sortify } 1038 | if$ 1039 | } 1040 | { "The " #4 organization chop.word sortify } 1041 | if$ 1042 | } 1043 | { author sort.format.names } 1044 | if$ 1045 | } 1046 | 1047 | FUNCTION {editor.organization.sort} 1048 | { editor empty$ 1049 | { organization empty$ 1050 | { key empty$ 1051 | { "to sort, need editor, organization, or key in " cite$ * warning$ 1052 | "" 1053 | } 1054 | { key sortify } 1055 | if$ 1056 | } 1057 | { "The " #4 organization chop.word sortify } 1058 | if$ 1059 | } 1060 | { editor sort.format.names } 1061 | if$ 1062 | } 1063 | 1064 | FUNCTION {presort} 1065 | { type$ "book" = 1066 | type$ "inbook" = 1067 | or 1068 | 'author.editor.sort 1069 | { type$ "proceedings" = 1070 | 'editor.organization.sort 1071 | { type$ "manual" = 1072 | 'author.organization.sort 1073 | 'author.sort 1074 | if$ 1075 | } 1076 | if$ 1077 | } 1078 | if$ 1079 | " " 1080 | * 1081 | year field.or.null sortify 1082 | * 1083 | " " 1084 | * 1085 | title field.or.null 1086 | sort.format.title 1087 | * 1088 | #1 entry.max$ substring$ 1089 | 'sort.key$ := 1090 | } 1091 | 1092 | ITERATE {presort} 1093 | 1094 | SORT 1095 | 1096 | STRINGS { longest.label } 1097 | 1098 | INTEGERS { number.label longest.label.width } 1099 | 1100 | FUNCTION {initialize.longest.label} 1101 | { "" 'longest.label := 1102 | #1 'number.label := 1103 | #0 'longest.label.width := 1104 | } 1105 | 1106 | FUNCTION {longest.label.pass} 1107 | { number.label int.to.str$ 'label := 1108 | number.label #1 + 'number.label := 1109 | label width$ longest.label.width > 1110 | { label 'longest.label := 1111 | label width$ 'longest.label.width := 1112 | } 1113 | 'skip$ 1114 | if$ 1115 | } 1116 | 1117 | EXECUTE {initialize.longest.label} 1118 | 1119 | ITERATE {longest.label.pass} 1120 | 1121 | FUNCTION {begin.bib} 1122 | { preamble$ empty$ 1123 | 'skip$ 1124 | { preamble$ write$ newline$ } 1125 | if$ 1126 | "\begin{thebibliography}{" longest.label * "}" * write$ newline$ 1127 | } 1128 | 1129 | EXECUTE {begin.bib} 1130 | 1131 | EXECUTE {init.state.consts} 1132 | 1133 | ITERATE {call.type$} 1134 | 1135 | FUNCTION {end.bib} 1136 | { newline$ 1137 | "\end{thebibliography}" write$ newline$ 1138 | } 1139 | 1140 | EXECUTE {end.bib} 1141 | -------------------------------------------------------------------------------- /figures/universal-sequence.xml: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------