You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

397 lines
21 KiB

  1. \section{Tendermint consensus algorithm} \label{sec:tendermint}
  2. \newcommand\Disseminate{\textbf{Disseminate}}
  3. \newcommand\Proposal{\mathsf{PROPOSAL}}
  4. \newcommand\ProposalPart{\mathsf{PROPOSAL\mbox{-}PART}}
  5. \newcommand\PrePrepare{\mathsf{INIT}} \newcommand\Prevote{\mathsf{PREVOTE}}
  6. \newcommand\Precommit{\mathsf{PRECOMMIT}}
  7. \newcommand\Decision{\mathsf{DECISION}}
  8. \newcommand\ViewChange{\mathsf{VC}}
  9. \newcommand\ViewChangeAck{\mathsf{VC\mbox{-}ACK}}
  10. \newcommand\NewPrePrepare{\mathsf{VC\mbox{-}INIT}}
  11. \newcommand\coord{\mathsf{proposer}}
  12. \newcommand\newHeight{newHeight} \newcommand\newRound{newRound}
  13. \newcommand\nil{nil} \newcommand\id{id} \newcommand{\propose}{propose}
  14. \newcommand\prevote{prevote} \newcommand\prevoteWait{prevoteWait}
  15. \newcommand\precommit{precommit} \newcommand\precommitWait{precommitWait}
  16. \newcommand\commit{commit}
  17. \newcommand\timeoutPropose{timeoutPropose}
  18. \newcommand\timeoutPrevote{timeoutPrevote}
  19. \newcommand\timeoutPrecommit{timeoutPrecommit}
  20. \newcommand\proofOfLocking{proof\mbox{-}of\mbox{-}locking}
  21. \begin{algorithm}[htb!] \def\baselinestretch{1} \scriptsize\raggedright
  22. \begin{algorithmic}[1]
  23. \SHORTSPACE
  24. \INIT{}
  25. \STATE $h_p := 0$
  26. \COMMENT{current height, or consensus instance we are currently executing}
  27. \STATE $round_p := 0$ \COMMENT{current round number}
  28. \STATE $step_p \in \set{\propose, \prevote, \precommit}$
  29. \STATE $decision_p[] := nil$
  30. \STATE $lockedValue_p := nil$
  31. \STATE $lockedRound_p := -1$
  32. \STATE $validValue_p := nil$
  33. \STATE $validRound_p := -1$
  34. \ENDINIT
  35. \SHORTSPACE
  36. \STATE \textbf{upon} start \textbf{do} $StartRound(0)$
  37. \SHORTSPACE
  38. \FUNCTION{$StartRound(round)$} \label{line:tab:startRound}
  39. \STATE $round_p \assign round$
  40. \STATE $step_p \assign \propose$
  41. \IF{$\coord(h_p, round_p) = p$}
  42. \IF{$validValue_p \neq \nil$} \label{line:tab:isThereLockedValue}
  43. \STATE $proposal \assign validValue_p$ \ELSE \STATE $proposal \assign
  44. getValue()$
  45. \label{line:tab:getValidValue}
  46. \ENDIF
  47. \STATE \Broadcast\ $\li{\Proposal,h_p, round_p, proposal, validRound_p}$
  48. \label{line:tab:send-proposal}
  49. \ELSE
  50. \STATE \textbf{schedule} $OnTimeoutPropose(h_p,
  51. round_p)$ to be executed \textbf{after} $\timeoutPropose(round_p)$
  52. \ENDIF
  53. \ENDFUNCTION
  54. \SPACE
  55. \UPON{$\li{\Proposal,h_p,round_p, v, -1}$ \From\ $\coord(h_p,round_p)$
  56. \With\ $step_p = \propose$} \label{line:tab:recvProposal}
  57. \IF{$valid(v) \wedge (lockedRound_p = -1 \vee lockedValue_p = v$)}
  58. \label{line:tab:accept-proposal-2}
  59. \STATE \Broadcast \ $\li{\Prevote,h_p,round_p,id(v)}$
  60. \label{line:tab:prevote-proposal}
  61. \ELSE
  62. \label{line:tab:acceptProposal1}
  63. \STATE \Broadcast \ $\li{\Prevote,h_p,round_p,\nil}$
  64. \label{line:tab:prevote-nil}
  65. \ENDIF
  66. \STATE $step_p \assign \prevote$ \label{line:tab:setStateToPrevote1}
  67. \ENDUPON
  68. \SPACE
  69. \UPON{$\li{\Proposal,h_p,round_p, v, vr}$ \From\ $\coord(h_p,round_p)$
  70. \textbf{AND} $2f+1$ $\li{\Prevote,h_p, vr,id(v)}$ \With\ $step_p = \propose \wedge (vr \ge 0 \wedge vr < round_p)$}
  71. \label{line:tab:acceptProposal}
  72. \IF{$valid(v) \wedge (lockedRound_p \le vr
  73. \vee lockedValue_p = v)$} \label{line:tab:cond-prevote-higher-proposal}
  74. \STATE \Broadcast \ $\li{\Prevote,h_p,round_p,id(v)}$
  75. \label{line:tab:prevote-higher-proposal}
  76. \ELSE
  77. \label{line:tab:acceptProposal2}
  78. \STATE \Broadcast \ $\li{\Prevote,h_p,round_p,\nil}$
  79. \label{line:tab:prevote-nil2}
  80. \ENDIF
  81. \STATE $step_p \assign \prevote$ \label{line:tab:setStateToPrevote3}
  82. \ENDUPON
  83. \SPACE
  84. \UPON{$2f+1$ $\li{\Prevote,h_p, round_p,*}$ \With\ $step_p = \prevote$ for the first time}
  85. \label{line:tab:recvAny2/3Prevote}
  86. \STATE \textbf{schedule} $OnTimeoutPrevote(h_p, round_p)$ to be executed \textbf{after} $\timeoutPrevote(round_p)$ \label{line:tab:timeoutPrevote}
  87. \ENDUPON
  88. \SPACE
  89. \UPON{$\li{\Proposal,h_p,round_p, v, *}$ \From\ $\coord(h_p,round_p)$
  90. \textbf{AND} $2f+1$ $\li{\Prevote,h_p, round_p,id(v)}$ \With\ $valid(v) \wedge step_p \ge \prevote$ for the first time}
  91. \label{line:tab:recvPrevote}
  92. \IF{$step_p = \prevote$}
  93. \STATE $lockedValue_p \assign v$ \label{line:tab:setLockedValue}
  94. \STATE $lockedRound_p \assign round_p$ \label{line:tab:setLockedRound}
  95. \STATE \Broadcast \ $\li{\Precommit,h_p,round_p,id(v))}$
  96. \label{line:tab:precommit-v}
  97. \STATE $step_p \assign \precommit$ \label{line:tab:setStateToCommit}
  98. \ENDIF
  99. \STATE $validValue_p \assign v$ \label{line:tab:setValidRound}
  100. \STATE $validRound_p \assign round_p$ \label{line:tab:setValidValue}
  101. \ENDUPON
  102. \SHORTSPACE
  103. \UPON{$2f+1$ $\li{\Prevote,h_p,round_p, \nil}$
  104. \With\ $step_p = \prevote$}
  105. \STATE \Broadcast \ $\li{\Precommit,h_p,round_p, \nil}$
  106. \label{line:tab:precommit-v-1}
  107. \STATE $step_p \assign \precommit$
  108. \ENDUPON
  109. \SPACE
  110. \UPON{$2f+1$ $\li{\Precommit,h_p,round_p,*}$ for the first time}
  111. \label{line:tab:startTimeoutPrecommit}
  112. \STATE \textbf{schedule} $OnTimeoutPrecommit(h_p, round_p)$ to be executed \textbf{after} $\timeoutPrecommit(round_p)$
  113. \ENDUPON
  114. \SPACE
  115. \UPON{$\li{\Proposal,h_p,r, v, *}$ \From\ $\coord(h_p,r)$ \textbf{AND}
  116. $2f+1$ $\li{\Precommit,h_p,r,id(v)}$ \With\ $decision_p[h_p] = \nil$}
  117. \label{line:tab:onDecideRule}
  118. \IF{$valid(v)$} \label{line:tab:validDecisionValue}
  119. \STATE $decision_p[h_p] = v$ \label{line:tab:decide}
  120. \STATE$h_p \assign h_p + 1$ \label{line:tab:increaseHeight}
  121. \STATE reset $lockedRound_p$, $lockedValue_p$, $validRound_p$ and $validValue_p$ to initial values
  122. and empty message log
  123. \STATE $StartRound(0)$
  124. \ENDIF
  125. \ENDUPON
  126. \SHORTSPACE
  127. \UPON{$f+1$ $\li{*,h_p,round, *, *}$ \textbf{with} $round > round_p$}
  128. \label{line:tab:skipRounds}
  129. \STATE $StartRound(round)$ \label{line:tab:nextRound2}
  130. \ENDUPON
  131. \SHORTSPACE
  132. \FUNCTION{$OnTimeoutPropose(height,round)$} \label{line:tab:onTimeoutPropose}
  133. \IF{$height = h_p \wedge round = round_p \wedge step_p = \propose$}
  134. \STATE \Broadcast \ $\li{\Prevote,h_p,round_p, \nil}$
  135. \label{line:tab:prevote-nil-on-timeout}
  136. \STATE $step_p \assign \prevote$
  137. \ENDIF
  138. \ENDFUNCTION
  139. \SHORTSPACE
  140. \FUNCTION{$OnTimeoutPrevote(height,round)$} \label{line:tab:onTimeoutPrevote}
  141. \IF{$height = h_p \wedge round = round_p \wedge step_p = \prevote$}
  142. \STATE \Broadcast \ $\li{\Precommit,h_p,round_p,\nil}$
  143. \label{line:tab:precommit-nil-onTimeout}
  144. \STATE $step_p \assign \precommit$
  145. \ENDIF
  146. \ENDFUNCTION
  147. \SHORTSPACE
  148. \FUNCTION{$OnTimeoutPrecommit(height,round)$} \label{line:tab:onTimeoutPrecommit}
  149. \IF{$height = h_p \wedge round = round_p$}
  150. \STATE $StartRound(round_p + 1)$ \label{line:tab:nextRound}
  151. \ENDIF
  152. \ENDFUNCTION
  153. \end{algorithmic} \caption{Tendermint consensus algorithm}
  154. \label{alg:tendermint}
  155. \end{algorithm}
  156. In this section we present the Tendermint Byzantine fault-tolerant consensus
  157. algorithm. The algorithm is specified by the pseudo-code shown in
  158. Algorithm~\ref{alg:tendermint}. We present the algorithm as a set of \emph{upon
  159. rules} that are executed atomically\footnote{In case several rules are active
  160. at the same time, the first rule to be executed is picked randomly. The
  161. correctness of the algorithm does not depend on the order in which rules are
  162. executed.}. We assume that processes exchange protocol messages using a gossip
  163. protocol and that both sent and received messages are stored in a local message
  164. log for every process. An upon rule is triggered once the message log contains
  165. messages such that the corresponding condition evaluates to $\tt{true}$. The
  166. condition that assumes reception of $X$ messages of a particular type and
  167. content denotes reception of messages whose senders have aggregate voting power at
  168. least equal to $X$. For example, the condition $2f+1$ $\li{\Precommit,h_p,r,id(v)}$,
  169. evaluates to true upon reception of $\Precommit$ messages for height $h_p$,
  170. a round $r$ and with value equal to $id(v)$ whose senders have aggregate voting
  171. power at least equal to $2f+1$. Some of the rules ends with "for the first time" constraint
  172. to denote that it is triggered only the first time a corresponding condition evaluates
  173. to $\tt{true}$. This is because those rules do not always change the state of algorithm
  174. variables so without this constraint, the algorithm could keep
  175. executing those rules forever. The variables with index $p$ are process local state
  176. variables, while variables without index $p$ are value placeholders. The sign
  177. $*$ denotes any value.
  178. We denote with $n$ the total voting power of processes in the system, and we
  179. assume that the total voting power of faulty processes in the system is bounded
  180. with a system parameter $f$. The algorithm assumes that $n > 3f$, i.e., it
  181. requires that the total voting power of faulty processes is smaller than one
  182. third of the total voting power. For simplicity we present the algorithm for
  183. the case $n = 3f + 1$.
  184. The algorithm proceeds in rounds, where each round has a dedicated
  185. \emph{proposer}. The mapping of rounds to proposers is known to all processes
  186. and is given as a function $\coord(h, round)$, returning the proposer for
  187. the round $round$ in the consensus instance $h$. We
  188. assume that the proposer selection function is weighted round-robin, where
  189. processes are rotated proportional to their voting power\footnote{A validator
  190. with more voting power is selected more frequently, proportional to its power.
  191. More precisely, during a sequence of rounds of size $n$, every process is
  192. proposer in a number of rounds equal to its voting power.}.
  193. The internal protocol state transitions are triggered by message reception and
  194. by expiration of timeouts. There are three timeouts in Algorithm \ref{alg:tendermint}:
  195. $\timeoutPropose$, $\timeoutPrevote$ and $\timeoutPrecommit$.
  196. The timeouts prevent the algorithm from blocking and
  197. waiting forever for some condition to be true, ensure that processes continuously
  198. transition between rounds, and guarantee that eventually (after GST) communication
  199. between correct processes is timely and reliable so they can decide.
  200. The last role is achieved by increasing the timeouts with every new round $r$,
  201. i.e, $timeoutX(r) = initTimeoutX + r*timeoutDelta$;
  202. they are reset for every new height (consensus
  203. instance).
  204. Processes exchange the following messages in Tendermint: $\Proposal$,
  205. $\Prevote$ and $\Precommit$. The $\Proposal$ message is used by the proposer of
  206. the current round to suggest a potential decision value, while $\Prevote$ and
  207. $\Precommit$ are votes for a proposed value. According to the classification of
  208. consensus algorithms from \cite{RMS10:dsn}, Tendermint, like PBFT
  209. \cite{CL02:tcs} and DLS \cite{DLS88:jacm}, belongs to class 3, so it requires
  210. two voting steps (three communication exchanges in total) to decide a value.
  211. The Tendermint consensus algorithm is designed for the blockchain context where
  212. the value to decide is a block of transactions (ie. it is potentially quite
  213. large, consisting of many transactions). Therefore, in the Algorithm
  214. \ref{alg:tendermint} (similar as in \cite{CL02:tcs}) we are explicit about
  215. sending a value (block of transactions) and a small, constant size value id (a
  216. unique value identifier, normally a hash of the value, i.e., if $\id(v) =
  217. \id(v')$, then $v=v'$). The $\Proposal$ message is the only one carrying the
  218. value; $\Prevote$ and $\Precommit$ messages carry the value id. A correct
  219. process decides on a value $v$ in Tendermint upon receiving the $\Proposal$ for
  220. $v$ and $2f+1$ voting-power equivalent $\Precommit$ messages for $\id(v)$ in
  221. some round $r$. In order to send $\Precommit$ message for $v$ in a round $r$, a
  222. correct process waits to receive the $\Proposal$ and $2f+1$ of the
  223. corresponding $\Prevote$ messages in the round $r$. Otherwise,
  224. it sends $\Precommit$ message with a special $\nil$ value.
  225. This ensures that correct processes can $\Precommit$ only a
  226. single value (or $\nil$) in a round. As
  227. proposers may be faulty, the proposed value is treated by correct processes as
  228. a suggestion (it is not blindly accepted), and a correct process tells others
  229. if it accepted the $\Proposal$ for value $v$ by sending $\Prevote$ message for
  230. $\id(v)$; otherwise it sends $\Prevote$ message with the special $\nil$ value.
  231. Every process maintains the following variables in the Algorithm
  232. \ref{alg:tendermint}: $step$, $lockedValue$, $lockedRound$, $validValue$ and
  233. $validRound$. The $step$ denotes the current state of the internal Tendermint
  234. state machine, i.e., it reflects the stage of the algorithm execution in the
  235. current round. The $lockedValue$ stores the most recent value (with respect to
  236. a round number) for which a $\Precommit$ message has been sent. The
  237. $lockedRound$ is the last round in which the process sent a $\Precommit$
  238. message that is not $\nil$. We also say that a correct process locks a value
  239. $v$ in a round $r$ by setting $lockedValue = v$ and $lockedRound = r$ before
  240. sending $\Precommit$ message for $\id(v)$. As a correct process can decide a
  241. value $v$ only if $2f+1$ $\Precommit$ messages for $\id(v)$ are received, this
  242. implies that a possible decision value is a value that is locked by at least
  243. $f+1$ voting power equivalent of correct processes. Therefore, any value $v$
  244. for which $\Proposal$ and $2f+1$ of the corresponding $\Prevote$ messages are
  245. received in some round $r$ is a \emph{possible decision} value. The role of the
  246. $validValue$ variable is to store the most recent possible decision value; the
  247. $validRound$ is the last round in which $validValue$ is updated. Apart from
  248. those variables, a process also stores the current consensus instance ($h_p$,
  249. called \emph{height} in Tendermint), and the current round number ($round_p$)
  250. and attaches them to every message. Finally, a process also stores an array of
  251. decisions, $decision_p$ (Tendermint assumes a sequence of consensus instances,
  252. one for each height).
  253. Every round starts by a proposer suggesting a value with the $\Proposal$
  254. message (see line \ref{line:tab:send-proposal}). In the initial round of each
  255. height, the proposer is free to chose the value to suggest. In the
  256. Algorithm~\ref{alg:tendermint}, a correct process obtains a value to propose
  257. using an external function $getValue()$ that returns a valid value to
  258. propose. In the following rounds, a correct proposer will suggest a new value
  259. only if $validValue = \nil$; otherwise $validValue$ is proposed (see
  260. lines~\ref{line:tab:isThereLockedValue}-\ref{line:tab:getValidValue}).
  261. In addition to the value proposed, the $\Proposal$ message also
  262. contains the $validRound$ so other processes are informed about the last round
  263. in which the proposer observed $validValue$ as a possible decision value.
  264. Note that if a correct proposer $p$ sends $validValue$ with the $validRound$ in the
  265. $\Proposal$, this implies that the process $p$ received $\Proposal$ and the
  266. corresponding $2f+1$ $\Prevote$ messages for $validValue$ in the round
  267. $validRound$.
  268. If a correct process sends $\Proposal$ message with $validValue$ ($validRound > -1$)
  269. at time $t > GST$, by the \emph{Gossip communication} property, the
  270. corresponding $\Proposal$ and the $\Prevote$ messages will be received by all
  271. correct processes before time $t+\Delta$. Therefore, all correct processes will
  272. be able to verify the correctness of the suggested value as it is supported by
  273. the $\Proposal$ and the corresponding $2f+1$ voting power equivalent $\Prevote$
  274. messages.
  275. A correct process $p$ accepts the proposal for a value $v$ (send $\Prevote$
  276. for $id(v)$) if an external \emph{valid} function returns $true$ for the value
  277. $v$, and if $p$ hasn't locked any value ($lockedRound = -1$) or $p$ has locked
  278. the value $v$ ($lockedValue = v$); see the line
  279. \ref{line:tab:accept-proposal-2}. In case the proposed pair is $(v,vr \ge 0)$ and a
  280. correct process $p$ has locked some value, it will accept
  281. $v$ if it is a more recent possible decision value\footnote{As
  282. explained above, the possible decision value in a round $r$ is the one for
  283. which $\Proposal$ and the corresponding $2f+1$ $\Prevote$ messages are received
  284. for the round $r$.}, $vr > lockedRound_p$, or if $lockedValue = v$
  285. (see line~\ref{line:tab:cond-prevote-higher-proposal}). Otherwise, a correct
  286. process will reject the proposal by sending $\Prevote$ message with $\nil$
  287. value. A correct process will send $\Prevote$ message with $\nil$ value also in
  288. case $\timeoutPropose$ expired (it is triggered when a correct process starts a
  289. new round) and a process has not sent $\Prevote$ message in the current round
  290. yet (see the line \ref{line:tab:onTimeoutPropose}).
  291. If a correct process receives $\Proposal$ message for some value $v$ and $2f+1$
  292. $\Prevote$ messages for $\id(v)$, then it sends $\Precommit$ message with
  293. $\id(v)$. Otherwise, it sends $\Precommit$ $\nil$. A correct process will send
  294. $\Precommit$ message with $\nil$ value also in case $\timeoutPrevote$ expired
  295. (it is started when a correct process sent $\Prevote$ message and received any
  296. $2f+1$ $\Prevote$ messages) and a process has not sent $\Precommit$ message in
  297. the current round yet (see the line \ref{line:tab:onTimeoutPrecommit}). A
  298. correct process decides on some value $v$ if it receives in some round $r$
  299. $\Proposal$ message for $v$ and $2f+1$ $\Precommit$ messages with $\id(v)$ (see
  300. the line \ref{line:tab:decide}). To prevent the algorithm from blocking and
  301. waiting forever for this condition to be true, the Algorithm
  302. \ref{alg:tendermint} relies on $\timeoutPrecommit$. It is triggered after a
  303. process receives any set of $2f+1$ $\Precommit$ messages for the current round.
  304. If the $\timeoutPrecommit$ expires and a process has not decided yet, the
  305. process starts the next round (see the line \ref{line:tab:onTimeoutPrecommit}).
  306. When a correct process $p$ decides, it starts the next consensus instance
  307. (for the next height). The \emph{Gossip communication} property ensures
  308. that $\Proposal$ and $2f+1$ $\Prevote$ messages that led $p$ to decide
  309. are eventually received by all correct processes, so they will also decide.
  310. \subsection{Termination mechanism}
  311. Tendermint ensures termination by a novel mechanism that benefits from the
  312. gossip based nature of communication (see \emph{Gossip communication}
  313. property). It requires managing two additional variables, $validValue$ and
  314. $validRound$ that are then used by the proposer during the propose step as
  315. explained above. The $validValue$ and $validRound$ are updated to $v$ and $r$
  316. by a correct process in a round $r$ when the process receives valid $\Proposal$
  317. message for the value $v$ and the corresponding $2f+1$ $\Prevote$ messages for
  318. $id(v)$ in the round $r$ (see the rule at line~\ref{line:tab:recvPrevote}).
  319. We now give briefly the intuition how managing and proposing $validValue$
  320. and $validRound$ ensures termination. Formal treatment is left for
  321. Section~\ref{sec:proof}.
  322. The first thing to note is that during good period, because of the
  323. \emph{Gossip communication} property, if a correct process $p$ locks a value
  324. $v$ in some round $r$, all correct processes will update $validValue$ to $v$
  325. and $validRound$ to $r$ before the end of the round $r$ (we prove this formally
  326. in the Section~\ref{sec:proof}). The intuition is that messages that led to $p$
  327. locking a value $v$ in the round $r$ will be gossiped to all correct processes
  328. before the end of the round $r$, so it will update $validValue$ and
  329. $validRound$ (the line~\ref{line:tab:recvPrevote}). Therefore, if a correct
  330. process locks some value during good period, $validValue$ and $validRound$ are
  331. updated by all correct processes so that the value proposed in the following
  332. rounds will be acceptable by all correct processes. Note
  333. that it could happen that during good period, no correct process locks a value,
  334. but some correct process $q$ updates $validValue$ and $validRound$ during some
  335. round. As no correct process locks a value in this case, $validValue_q$ and
  336. $validRound_q$ will also be acceptable by all correct processes as
  337. $validRound_q > lockedRound_c$ for every correct process $c$ and as the
  338. \emph{Gossip communication} property ensures that the corresponding $\Prevote$
  339. messages that $q$ received in the round $validRound_q$ are received by all
  340. correct processes $\Delta$ time later.
  341. Finally, it could happen that after GST, there is a long sequence of rounds in which
  342. no correct process neither locks a value nor update $validValue$ and $validRound$.
  343. In this case, during this sequence of rounds, the proposed value suggested by correct
  344. processes was not accepted by all correct processes. Note that this sequence of rounds
  345. is always finite as at the beginning of every
  346. round there is at least a single correct process $c$ such that $validValue_c$
  347. and $validRound_c$ are acceptable by every correct process. This is true as
  348. there exists a correct process $c$ such that for every other correct process
  349. $p$, $validRound_c > lockedRound_p$ or $validValue_c = lockedValue_p$. This is
  350. true as $c$ is the process that has locked a value in the most recent round
  351. among all correct processes (or no correct process locked any value). Therefore,
  352. eventually $c$ will be the proper in some round and the proposed value will be accepted
  353. by all correct processes, terminating therefore this sequence of
  354. rounds.
  355. Therefore, updating $validValue$ and $validRound$ variables, and the
  356. \emph{Gossip communication} property, together ensures that eventually, during
  357. the good period, there exists a round with a correct proposer whose proposed
  358. value will be accepted by all correct processes, and all correct processes will
  359. terminate in that round. Note that this mechanism, contrary to the common
  360. termination mechanism illustrated in the
  361. Figure~\ref{ch3:fig:coordinator-change}, does not require exchanging any
  362. additional information in addition to messages already sent as part of what is
  363. normally being called "normal" case.