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.

841 lines
31 KiB

  1. <!-- markdown-link-check-disable -->
  2. # Light Client Attack Detector
  3. In this specification, we strengthen the light client to be resistant
  4. against so-called light client attacks. In a light client attack, all
  5. the correct Tendermint full nodes agree on the sequence of generated
  6. blocks (no fork), but a set of faulty full nodes attack a light client
  7. by generating (signing) a block that deviates from the block of the
  8. same height on the blockchain. In order to do so, some of these faulty
  9. full nodes must have been validators before and violate the assumption
  10. of more than two thirds of "correct voting power"
  11. [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link], as otherwise, if
  12. [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link] would hold,
  13. [verification][verification] would satisfy
  14. [[LCV-SEQ-SAFE.1]][LCV-SEQ-SAFE-link].
  15. An attack detector (or detector for short) is a mechanism that is used
  16. by the light client [supervisor][supervisor] after
  17. [verification][verification] of a new light block
  18. with the primary, to cross-check the newly learned light block with
  19. other peers (secondaries). It expects as input a light block with some
  20. height *root* (that serves as a root of trust), and a verification
  21. trace (a sequence of lightblocks) that the primary provided.
  22. In case the detector observes a light client attack, it computes
  23. evidence data that can be used by Tendermint full nodes to isolate a
  24. set of faulty full nodes that are still within the unbonding period
  25. (more than 1/3 of the voting power of the validator set at some block
  26. of the chain), and report them via ABCI (application/blockchain
  27. interface)
  28. to the application of a
  29. Tendermint blockchain in order to punish faulty nodes.
  30. ## Context of this document
  31. The light client [verification][verification] specification is
  32. designed for the Tendermint failure model (1/3 assumption)
  33. [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link]. It is safe under this
  34. assumption, and live if it can reliably (that is, no message loss, no
  35. duplication, and eventually delivered) and timely communicate with a
  36. correct full node. If [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link]
  37. assumption is violated, the light client can be fooled to trust a
  38. light block that was not generated by Tendermint consensus.
  39. This specification, the attack detector, is a "second line of
  40. defense", in case the 1/3 assumption is violated. Its goal is to
  41. detect a light client attack (conflicting light blocks) and collect
  42. evidence. However, it is impractical to probe all full nodes. At this
  43. time we consider a simple scheme of maintaining an address book of
  44. known full nodes from which a small subset (e.g., 4) are chosen
  45. initially to communicate with. More involved book keeping with
  46. probabilistic guarantees can be considered at later stages of the
  47. project.
  48. The light client maintains a simple address book containing addresses
  49. of full nodes that it can pick as primary and secondaries. To obtain
  50. a new light block, the light client first does
  51. [verification][verification] with the primary, and then cross-checks
  52. the light block (and the trace of light blocks that led to it) with
  53. the secondaries using this specification.
  54. # Outline
  55. - [Part I](#part-i---Tendermint-Consensus-and-Light-Client-Attacks):
  56. Formal definitions of lightclient attacks, based on basic
  57. properties of Tendermint consensus.
  58. - [Node-based characterization of
  59. attacks](#Node-based-characterization-of-attacks). The
  60. definition of attacks used in the problem statement of
  61. this specification.
  62. - [Block-based characterization of attacks](#Block-based-characterization-of-attacks). Alternative definitions
  63. provided for future reference.
  64. - [Part II](#part-ii---problem-statement): Problem statement of
  65. lightclient attack detection
  66. - [Informal Problem Statement](#informal-problem-statement)
  67. - [Assumptions](#Assumptions)
  68. - [Definitions](#definitions)
  69. - [Distributed Problem statement](#Distributed-Problem-statement)
  70. - [Part III](#part-iii---protocol): The protocol
  71. - [Functions and Data defined in other Specifications](#Functions-and-Data-defined-in-other-Specifications)
  72. - [Outline of Solution](#Outline-of-solution)
  73. - [Details of the functions](#Details-of-the-functions)
  74. - [Correctness arguments](#Correctness-arguments)
  75. # Part I - Tendermint Consensus and Light Client Attacks
  76. In this section we will give some mathematical definitions of what we
  77. mean by light client attacks (that are considered in this
  78. specification) and how they differ from main-chain forks. To this end,
  79. we start by defining some properties of the sequence of blocks that is
  80. decided upon by Tendermint consensus in normal operation (if the
  81. Tendermint failure model holds
  82. [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link]),
  83. and then define different
  84. deviations that correspond to attack scenarios. We consider the notion
  85. of [light blocks][LCV-LB-link] and [headers][LVC-HD-link].
  86. #### **[TMBC-GENESIS.1]**
  87. Let *Genesis* be the agreed-upon initial block (file).
  88. #### **[TMBC-FUNC-SIGN.1]**
  89. Let *b* and *c* be two light blocks with *b.Header.Height + 1 =
  90. c.Header.Height*. We define the predicate **signs(b,c)** to hold
  91. iff *c.Header.LastCommit* is in *PossibleCommit(b)*.
  92. [[TMBC-SOUND-DISTR-POSS-COMMIT.1]][TMBC-SOUND-DISTR-POSS-COMMIT-link].
  93. > The above encodes sequential verification, that is, intuitively,
  94. > b.Header.NextValidators = c.Header.Validators and 2/3 of
  95. > these Validators signed c.
  96. #### **[TMBC-FUNC-SUPPORT.1]**
  97. Let *b* and *c* be two light blocks. We define the predicate
  98. **supports(b,c,t)** to hold iff
  99. - *t - trustingPeriod < b.Header.Time < t*
  100. - the voting power in *b.NextValidators* of nodes in *c.Commit*
  101. is more than 1/3 of *TotalVotingPower(b.Header.NextValidators)*
  102. > That is, if the [Tendermint failure model][TMBC-FM-2THIRDS-link]
  103. > holds, then *c* has been signed by at least one correct full node, cf.
  104. > [[TMBC-VAL-CONTAINS-CORR.1]][TMBC-VAL-CONTAINS-CORR-link].
  105. > The following formalizes that *b* was properly generated by
  106. > Tendermint; *b* can be traced back to genesis.
  107. #### **[TMBC-SEQ-ROOTED.1]**
  108. Let *b* be a light block.
  109. We define *sequ-rooted(b)* iff for all *i*, *1 <= i < h = b.Header.Height*,
  110. there exist light blocks *a(i)* s.t.
  111. - *a(1) = Genesis* and
  112. - *a(h) = b* and
  113. - *signs( a(i) , a(i+1) )*.
  114. > The following formalizes that *c* is trusted based on *b* in
  115. > skipping verification. Observe that we do not require here (yet)
  116. > that *b* was properly generated.
  117. #### **[TMBC-SKIP-TRACE.1]**
  118. Let *b* and *c* be light blocks. We define *skip-trace(b,c,t)* if at
  119. time t there exists an integer *h* and a sequence *a(1)*, ... *a(h)* s.t.
  120. - *a(1) = b* and
  121. - *a(h) = c* and
  122. - *supports( a(i), a(i+1), t)*, for all i, *1 <= i < h*.
  123. We call such a sequence *a(1)*, ... *a(h)* a **verification trace**.
  124. > The following formalizes that two light blocks of the same height
  125. > should agree on the content of the header. Observe that *b* and *c*
  126. > may disagree on the Commit. This is a special case if the canonical
  127. > commit has not been decided on yet, that is, if b.Header.Height is the
  128. > maximum height of all blocks decided upon by Tendermint at this
  129. > moment.
  130. #### **[TMBC-SIGN-SKIP-MATCH.1]**
  131. Let *a*, *b*, *c*, be light blocks and *t* a time, we define
  132. *sign-skip-match(a,b,c,t) = true* iff the following implication
  133. evaluates to true:
  134. - *sequ-rooted(a)* and
  135. - *b.Header.Height = c.Header.Height* and
  136. - *skip-trace(a,b,t)*
  137. - *skip-trace(a,c,t)*
  138. implies *b.Header = c.Header*.
  139. > Observe that *sign-skip-match* is defined via an implication. If it
  140. > evaluates to false this means that the left-hand-side of the
  141. > implication evaluates to true, and the right-hand-side evaluates to
  142. > false. In particular, there are two **different** headers *b* and
  143. > *c* that both can be verified from a common block *a* from the
  144. > chain. Thus, the following describes an attack.
  145. #### **[TMBC-ATTACK.1]**
  146. If there exists three light blocks a, b, and c, with
  147. *sign-skip-match(a,b,c,t) = false* then we have an *attack*. We say
  148. we have **an attack at height** *b.Header.Height* and write
  149. *attack(a,b,c,t)*.
  150. > The lightblock *a* need not be unique, that is, there may be
  151. > several blocks that satisfy the above requirement for the same
  152. > blocks *b* and *c*.
  153. [[TMBC-ATTACK.1]](#TMBC-ATTACK1) is a formalization of the violation
  154. of the agreement property based on the result of consensus, that is,
  155. the generated blocks.
  156. **Remark.**
  157. Violation of agreement is only possible if more than 1/3 of the validators (or
  158. next validators) of some previous block deviated from the protocol. The
  159. upcoming "accountability" specification will describe how to compute
  160. a set of at least 1/3 faulty nodes from two conflicting blocks. []
  161. There are different ways to characterize forks
  162. and attack scenarios. This specification uses the "node-based
  163. characterization of attacks" which focuses on what kinds of nodes are
  164. affected (light nodes vs. full nodes). For future reference and
  165. discussion we also provide a
  166. "block-based characterization of attacks" below.
  167. ## Node-based characterization of attacks
  168. #### **[TMBC-MC-FORK.1]**
  169. We say there is a (main chain) fork at time *t* if
  170. - there are two correct full nodes *i* and *j* and
  171. - *i* is different from *j* and
  172. - *i* has decided on *b* and
  173. - *j* has decided on *c* and
  174. - there exist *a* such that *attack(a,b,c,t)*.
  175. #### **[TMBC-LC-ATTACK.1]**
  176. We say there is a light client attack at time *t*, if
  177. - there is **no** (main chain) fork [[TMBC-MC-FORK.1]](#TMBC-MC-FORK1), and
  178. - there exist nodes that have computed light blocks *b* and *c* and
  179. - there exist *a* such that *attack(a,b,c,t)*.
  180. We say the attack is at height *a.Header.Height*.
  181. > In this specification we consider detection of light client
  182. > attacks. Intuitively, the case we consider is that
  183. > light block *b* is the one from the
  184. > blockchain, and some attacker has computed *c* and tries to wrongly
  185. > convince
  186. > the light client that *c* is the block from the chain.
  187. #### **[TMBC-LC-ATTACK-EVIDENCE.1]**
  188. We consider the following case of a light client attack
  189. [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1):
  190. - *attack(a,b,c,t)*
  191. - there is a peer p1 that has a sequence *chain* of blocks from *a* to *b*
  192. - *skip-trace(a,c,t)*: by [[TMBC-SKIP-TRACE.1]](#TMBC-SKIP-TRACE1) there is a
  193. verification trace *v* of the form *a = v(1)*, ... *v(h) = c*
  194. Evidence for p1 (that proves an attack to p1) consists for index i
  195. of v(i) and v(i+1) such that
  196. - E1(i). v(i) is equal to the block of *chain* at height v(i).Height, and
  197. - E2(i). v(i+1) that is different from the block of *chain* at
  198. height v(i+1).height
  199. > Observe p1 can
  200. >
  201. > - check that v(i+1) differs from its block at that height, and
  202. > - verify v(i+1) in one step from v(i) as v is a verification trace.
  203. #### **[TMBC-LC-EVIDENCE-DATA.1]**
  204. To prove the attack to p1, because of Point E1, it is sufficient to
  205. submit
  206. - v(i).Height (rather than v(i)).
  207. - v(i+1)
  208. This information is *evidence for height v(i).Height*.
  209. ## Block-based characterization of attacks
  210. In this section we provide a different characterization of attacks. It
  211. is not defined on the nodes that are affected but purely on the
  212. content of the blocks. In that sense these definitions are less
  213. operational.
  214. > They might be relevant for a closer analysis of fork scenarios on the
  215. > chain, which is out of the scope of this specification.
  216. #### **[TMBC-SIGN-UNIQUE.1]**
  217. Let *b* and *c* be light blocks, we define the predicate
  218. *sign-unique(b,c)* to evaluate to true iff the following implication
  219. evaluates to true:
  220. - *b.Header.Height = c.Header.Height* and
  221. - *sequ-rooted(b)* and
  222. - *sequ-rooted(c)*
  223. implies *b = c*.
  224. #### **[TMBC-BLOCKS-MCFORK.1]**
  225. If there exists two light blocks b and c, with *sign-unique(b,c) =
  226. false* then we have a *fork*.
  227. > The difference of the above definition to
  228. > [[TMBC-MC-FORK.1]](#TMBC-MC-FORK1) is subtle. The latter requires a
  229. > full node being affected by a bad block while
  230. > [[TMBC-BLOCKS-MCFORK.1]](#TMBC-BLOCKS-MCFORK1) just requires that a
  231. > bad block exists, possibly in memory of an attacker.
  232. > The following captures a light client fork. There is no fork up to
  233. > the height of block b. However, c is of that height, is different,
  234. > and passes skipping verification. It is a stricter property than
  235. > [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1), as
  236. > [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1) requires that no correct full
  237. > node is affected.
  238. #### **[TMBC-BLOCKS-LCFORK.1]**
  239. Let *a*, *b*, *c*, be light blocks and *t* a time. We define
  240. *light-client-fork(a,b,c,t)* iff
  241. - *sign-skip-match(a,b,c,t) = false* and
  242. - *sequ-rooted(b)* and
  243. - *b* is "unique", that is, for all *d*, *sequ-rooted(d)* and
  244. *d.Header.Height = b.Header.Height* implies *d = b*
  245. > Finally, let us also define bogus blocks that have no support.
  246. > Observe that bogus is even defined if there is a fork.
  247. > Also, for the definition it would be sufficient to restrict *a* to
  248. > *a.height < b.height* (which is implied by the definitions which
  249. > unfold until *supports()*).
  250. #### **[TMBC-BOGUS.1]**
  251. Let *b* be a light block and *t* a time. We define *bogus(b,t)* iff
  252. - *sequ-rooted(b) = false* and
  253. - for all *a*, *sequ-rooted(a)* implies *skip-trace(a,b,t) = false*
  254. # Part II - Problem Statement
  255. ## Informal Problem statement
  256. There is no sequential specification: the detector only makes sense
  257. in a distributed systems where some nodes misbehave.
  258. We work under the assumption that full nodes and validators are
  259. responsible for detecting attacks on the main chain, and the evidence
  260. reactor takes care of broadcasting evidence to communicate
  261. misbehaving nodes via ABCI to the application, and halt the chain in
  262. case of a fork. The point of this specification is to shield a light
  263. clients against attacks that cannot be detected by full nodes, and
  264. are fully addressed at light clients (and consequently IBC relayers,
  265. which use the light client protocols to observe the state of a
  266. blockchain). In order to provide full nodes the incentive to follow
  267. the protocols when communicating with the light client, this
  268. specification also considers the generation of evidence that will
  269. also be processed by the Tendermint blockchain.
  270. #### **[LCD-IP-MODEL.1]**
  271. The detector is designed under the assumption that
  272. - [[TMBC-FM-2THIRDS]][TMBC-FM-2THIRDS-link] may be violated
  273. - there is no fork on the main chain.
  274. > As a result some faulty full nodes may launch an attack on a light
  275. > client.
  276. The following requirements are operational in that they describe how
  277. things should be done, rather than what should be done. However, they
  278. do not constitute temporal logic verification conditions. For those,
  279. see [LCD-DIST-*] below.
  280. The detector is called in the [supervisor][supervisor] as follows
  281. ```go
  282. Evidences := AttackDetector(root_of_trust, verifiedLS);`
  283. ```
  284. where
  285. - `root-of-trust` is a light block that is trusted (that is,
  286. except upon initialization, the primary and the secondaries
  287. agreed on in the past), and
  288. - `verifiedLS` is a lightstore that contains a verification trace that
  289. starts from a lightblock that can be verified with the
  290. `root-of-trust` in one step and ends with a lightblock of the height
  291. requested by the user
  292. - `Evidences` is a list of evidences for misbehavior
  293. #### **[LCD-IP-STATEMENT.1]**
  294. Whenever AttackDetector is called, the detector should for each
  295. secondary cross check the largest header in verifiedLS with the
  296. corresponding header of the same height provided by the secondary. If
  297. there is a deviation, the detector should
  298. try to replay the verification trace `verifiedLS` with the
  299. secondary
  300. - in case replaying leads to detection of a light client attack
  301. (one of the lightblocks differ from the one in verifiedLS with
  302. the same height), we should return evidence
  303. - if the secondary cannot provide a verification trace, we have no
  304. proof for an attack. Block *b* may be bogus. In this case the
  305. secondary is faulty and it should be replaced.
  306. ## Assumptions
  307. It is not in the interest of faulty full nodes to talk to the
  308. detector as long as the detector is connected to at least one
  309. correct full node. This would only increase the likelihood of
  310. misbehavior being detected. Also we cannot punish them easily
  311. (cheaply). The absence of a response need not be the fault of the full
  312. node.
  313. Correct full nodes have the incentive to respond, because the
  314. detector may help them to understand whether their header is a good
  315. one. We can thus base liveness arguments of the detector on
  316. the assumptions that correct full nodes reliably talk to the
  317. detector.
  318. #### **[LCD-A-CorrFull.1]**
  319. At all times there is at least one correct full
  320. node among the primary and the secondaries.
  321. > For this version of the detection we take this assumption. It
  322. > allows us to establish the invariant that the lightblock
  323. > `root-of-trust` is always the one from the blockchain, and we can
  324. > use it as starting point for the evidence computation. Moreover, it
  325. > allows us to establish the invariant at the supervisor that any
  326. > lightblock in the (top-level) lightstore is from the blockchain.
  327. > In the future we might design a lightclient based on the assumption
  328. > that at least in regular intervals the lightclient is connected to a
  329. > correct full node. This will require the detector to reconsider
  330. > `root-of-trust`, and remove lightblocks from the top-level
  331. > lightstore.
  332. #### **[LCD-A-RelComm.1]**
  333. Communication between the detector and a correct full node is
  334. reliable and bounded in time. Reliable communication means that
  335. messages are not lost, not duplicated, and eventually delivered. There
  336. is a (known) end-to-end delay *Delta*, such that if a message is sent
  337. at time *t* then it is received and processed by time *t + Delta*.
  338. This implies that we need a timeout of at least *2 Delta* for remote
  339. procedure calls to ensure that the response of a correct peer arrives
  340. before the timeout expires.
  341. ## Definitions
  342. ### Evidence
  343. Following the definition of
  344. [[TMBC-LC-ATTACK-EVIDENCE.1]](#TMBC-LC-ATTACK-EVIDENCE1), by evidence
  345. we refer to a variable of the following type
  346. #### **[LC-DATA-EVIDENCE.1]**
  347. ```go
  348. type LightClientAttackEvidence struct {
  349. ConflictingBlock LightBlock
  350. CommonHeight int64
  351. // Evidence also includes application specific data which is not
  352. // part of verification but is sent to the application once the
  353. // evidence gets committed on chain.
  354. }
  355. ```
  356. As the above data is computed for a specific peer, the following
  357. data structure wraps the evidence and adds the peerID.
  358. #### **[LC-DATA-EVIDENCE-INT.1]**
  359. ```go
  360. type InternalEvidence struct {
  361. Evidence LightClientAttackEvidence
  362. Peer PeerID
  363. }
  364. ```
  365. #### **[LC-SUMBIT-EVIDENCE.1]**
  366. ```go
  367. func submitEvidence(Evidences []InternalEvidence)
  368. ```
  369. - Expected postcondition
  370. - for each `ev` in `Evidences`: submit `ev.Evidence` to `ev.Peer`
  371. ---
  372. ### LightStore
  373. Lightblocks and LightStores are defined in the verification
  374. specification [[LCV-DATA-LIGHTBLOCK.1]][LCV-LB-link]
  375. and [[LCV-DATA-LIGHTSTORE.2]][LCV-LS-link]. See
  376. the [verification specification][verification] for details.
  377. ## Distributed Problem statement
  378. > As the attack detector is there to reduce the impact of faulty
  379. > nodes, and faulty nodes imply that there is a distributed system,
  380. > there is no sequential specification to which this distributed
  381. > problem statement may refer to.
  382. The detector gets as input a trusted lightblock called *root* and an
  383. auxiliary lightstore called *primary_trace* with lightblocks that have
  384. been verified before, and that were provided by the primary.
  385. #### **[LCD-DIST-INV-ATTACK.1]**
  386. If the detector returns evidence for height *h*
  387. [[TMBC-LC-EVIDENCE-DATA.1]](#TMBC-LC-EVIDENCE-DATA1), then there is an
  388. attack at height *h*. [[TMBC-LC-ATTACK.1]](#TMBC-LC-ATTACK1)
  389. #### **[LCD-DIST-INV-STORE.1]**
  390. If the detector does not return evidence, then *primary_trace*
  391. contains only blocks from the blockchain.
  392. #### **[LCD-DIST-LIVE.1]**
  393. The detector eventually terminates.
  394. #### **[LCD-DIST-TERM-NORMAL.1]**
  395. If
  396. - the *primary_trace* contains only blocks from the blockchain, and
  397. - there is no attack, and
  398. - *Secondaries* is always non-empty, and
  399. - the age of *root* is always less than the trusting period,
  400. then the detector does not return evidence.
  401. #### **[LCD-DIST-TERM-ATTACK.1]**
  402. If
  403. - there is an attack, and
  404. - a secondary reports a block that conflicts
  405. with one of the blocks in *primary_trace*, and
  406. - *Secondaries* is always non-empty, and
  407. - the age of *root* is always less than the trusting period,
  408. then the detector returns evidence.
  409. > Observe that above we require that "a secondary reports a block that
  410. > conflicts". If there is an attack, but no secondary tries to launch
  411. > it against the detector (or the message from the secondary is lost
  412. > by the network), then there is nothing to detect for us.
  413. #### **[LCD-DIST-SAFE-SECONDARY.1]**
  414. No correct secondary is ever replaced.
  415. #### **[LCD-DIST-SAFE-BOGUS.1]**
  416. If
  417. - a secondary reports a bogus lightblock,
  418. - the age of *root* is always less than the trusting period,
  419. then the secondary is replaced before the detector terminates.
  420. > The above property is quite operational (e.g., the usage of
  421. > "reports"), but it captures closely the requirement. As the
  422. > detector only makes sense in a distributed setting, and does not
  423. > have a sequential specification, a less "pure" specification are
  424. > acceptable.
  425. # Part III - Protocol
  426. ## Functions and Data defined in other Specifications
  427. ### From the [supervisor][supervisor]
  428. [[LC-FUNC-REPLACE-SECONDARY.1]][repl]
  429. ```go
  430. Replace_Secondary(addr Address, root-of-trust LightBlock)
  431. ```
  432. ### From the [verifier][verification]
  433. [[LCV-FUNC-MAIN.2]][vtt]
  434. ```go
  435. func VerifyToTarget(primary PeerID, root LightBlock,
  436. targetHeight Height) (LightStore, Result)
  437. ```
  438. Observe that `VerifyToTarget` does communication with the secondaries
  439. via the function [FetchLightBlock][fetch].
  440. ### Shared data of the light client
  441. - a pool of full nodes *FullNodes* that have not been contacted before
  442. - peer set called *Secondaries*
  443. - primary
  444. > Note that the lightStore is not needed to be shared.
  445. ## Outline of solution
  446. The problem laid out is solved by calling the function `AttackDetector`
  447. with a lightstore that contains a light block that has just been
  448. verified by the verifier.
  449. Then `AttackDetector` downloads headers from the secondaries. In case
  450. a conflicting header is downloaded from a secondary, it calls
  451. `CreateEvidenceForPeer` which computes evidence in the case that
  452. indeed an attack is confirmed. It could be that the secondary reports
  453. a bogus block, which means that there need not be an attack, and the
  454. secondary is replaced.
  455. ## Details of the functions
  456. #### **[LCD-FUNC-DETECTOR.2]:**
  457. ```go
  458. func AttackDetector(root LightBlock, primary_trace []LightBlock)
  459. ([]InternalEvidence) {
  460. Evidences := new []InternalEvidence;
  461. for each secondary in Secondaries {
  462. lb, result := FetchLightBlock(secondary,primary_trace.Latest().Header.Height);
  463. if result != ResultSuccess {
  464. Replace_Secondary(root);
  465. }
  466. else if lb.Header != primary_trace.Latest().Header {
  467. // we replay the primary trace with the secondary, in
  468. // order to generate evidence that we can submit to the
  469. // secondary. We return the evidence + the trace the
  470. // secondary told us that spans the evidence at its local store
  471. EvidenceForSecondary, newroot, secondary_trace, result :=
  472. CreateEvidenceForPeer(secondary,
  473. root,
  474. primary_trace);
  475. if result == FaultyPeer {
  476. Replace_Secondary(root);
  477. }
  478. else if result == FoundEvidence {
  479. // the conflict is not bogus
  480. Evidences.Add(EvidenceForSecondary);
  481. // we replay the secondary trace with the primary, ...
  482. EvidenceForPrimary, _, result :=
  483. CreateEvidenceForPeer(primary,
  484. newroot,
  485. secondary_trace);
  486. if result == FoundEvidence {
  487. Evidences.Add(EvidenceForPrimary);
  488. }
  489. // At this point we do not care about the other error
  490. // codes. We already have generated evidence for an
  491. // attack and need to stop the lightclient. It does not
  492. // help to call replace_primary. Also we will use the
  493. // same primary to check with other secondaries in
  494. // later iterations of the loop
  495. }
  496. // In the case where the secondary reports NoEvidence
  497. // after initially it reported a conflicting header.
  498. // secondary is faulty
  499. Replace_Secondary(root);
  500. }
  501. }
  502. return Evidences;
  503. }
  504. ```
  505. - Expected precondition
  506. - root and primary trace are a verification trace
  507. - Expected postcondition
  508. - solves the problem statement (if attack found, then evidence is reported)
  509. - Error condition
  510. - `ErrorTrustExpired`: fails if root expires (outside trusting
  511. period) [[LCV-INV-TP.1]][LCV-INV-TP1-link]
  512. - `ErrorNoPeers`: if no peers are left to replace secondaries, and
  513. no evidence was found before that happened
  514. ---
  515. ```go
  516. func CreateEvidenceForPeer(peer PeerID, root LightBlock, trace LightStore)
  517. (Evidence, LightBlock, LightStore, result) {
  518. common := root;
  519. for i in 1 .. len(trace) {
  520. auxLS, result := VerifyToTarget(peer, common, trace[i].Header.Height)
  521. if result != ResultSuccess {
  522. // something went wrong; peer did not provide a verifiable block
  523. return (nil, nil, nil, FaultyPeer)
  524. }
  525. else {
  526. if auxLS.LatestVerified().Header != trace[i].Header {
  527. // the header reported by the peer differs from the
  528. // reference header in trace but both could be
  529. // verified from common in one step.
  530. // we can create evidence for submission to the secondary
  531. ev := new InternalEvidence;
  532. ev.Evidence.ConflictingBlock := trace[i];
  533. // CommonHeight is used to indicate the type of attack
  534. // if the CommonHeight != ConflictingBlock.Height this
  535. // is by definition a lunatic attack else it is an
  536. // equivocation attack
  537. ev.Evidence.CommonHeight := common.Height;
  538. ev.Peer := peer
  539. return (ev, common, auxLS, FoundEvidence)
  540. }
  541. else {
  542. // the peer agrees with the trace, we move common forward.
  543. // we could delete auxLS as it will be overwritten in
  544. // the next iteration
  545. common := trace[i]
  546. }
  547. }
  548. }
  549. return (nil, nil, nil, NoEvidence)
  550. }
  551. ```
  552. - Expected precondition
  553. - root and trace are a verification trace
  554. - Expected postcondition
  555. - finds evidence where trace and peer diverge
  556. - Error condition
  557. - `ErrorTrustExpired`: fails if root expires (outside trusting
  558. period) [[LCV-INV-TP.1]][LCV-INV-TP1-link]
  559. - If `VerifyToTarget` returns error but root is not expired then return
  560. `FaultyPeer`
  561. ---
  562. ## Correctness arguments
  563. #### On the existence of evidence
  564. **Proposition.** In the case of attack,
  565. evidence [[TMBC-LC-ATTACK-EVIDENCE.1]](#TMBC-LC-ATTACK-EVIDENCE1)
  566. exists.
  567. *Proof.* First observe that
  568. - (A). (NOT E2(i)) implies E1(i+1)
  569. Now by contradiction assume there is no evidence. Thus
  570. - for all i, we have NOT E1(i) or NOT E2(i)
  571. - for i = 1 we have E1(1) and thus NOT E2(1)
  572. thus by induction on i, by (A) we have for all i that **E1(i)**
  573. - from attack we have E2(h-1), and as there is no evidence for
  574. i = h - 1 we get **NOT E1(h-1)**. Contradiction.
  575. QED.
  576. #### Argument for [[LCD-DIST-INV-ATTACK.1]](#LCD-DIST-INV-ATTACK1)
  577. Under the assumption that root and trace are a verification trace,
  578. when in `CreateEvidenceForPeer` the detector creates
  579. evidence, then the lightclient has seen two different headers (one via
  580. `trace` and one via `VerifyToTarget`) for the same height that can both
  581. be verified in one step.
  582. #### Argument for [[LCD-DIST-INV-STORE.1]](#LCD-DIST-INV-STORE1)
  583. We assume that there is at least one correct peer, and there is no
  584. fork. As a result, the correct peer has the correct sequence of
  585. blocks. Since the primary_trace is checked block-by-block also against
  586. each secondary, and at no point evidence was generated that means at
  587. no point there were conflicting blocks.
  588. #### Argument for [[LCD-DIST-LIVE.1]](#LCD-DIST-LIVE1)
  589. At the latest when [[LCV-INV-TP.1]][LCV-INV-TP1-link] is violated,
  590. `AttackDetector` terminates.
  591. #### Argument for [[LCD-DIST-TERM-NORMAL.1]](#LCD-DIST-TERM-NORMAL1)
  592. As there are finitely many peers, eventually the main loop
  593. terminates. As there is no attack no evidence can be generated.
  594. #### Argument for [[LCD-DIST-TERM-ATTACK.1]](#LCD-DIST-TERM-ATTACK1)
  595. Argument similar to [[LCD-DIST-TERM-NORMAL.1]](#LCD-DIST-TERM-NORMAL1)
  596. #### Argument for [[LCD-DIST-SAFE-SECONDARY.1]](#LCD-DIST-SAFE-SECONDARY1)
  597. Secondaries are only replaced if they time-out or if they report bogus
  598. blocks. The former is ruled out by the timing assumption, the latter
  599. by correct peers only reporting blocks from the chain.
  600. #### Argument for [[LCD-DIST-SAFE-BOGUS.1]](#LCD-DIST-SAFE-BOGUS1)
  601. Once a bogus block is recognized as such the secondary is removed.
  602. # References
  603. > links to other specifications/ADRs this document refers to
  604. [[verification]] The specification of the light client verification.
  605. [[supervisor]] The specification of the light client supervisor.
  606. [verification]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md
  607. [supervisor]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/supervisor/supervisor_001_draft.md
  608. [block]: https://github.com/tendermint/spec/blob/d46cd7f573a2c6a2399fcab2cde981330aa63f37/spec/core/data_structures.md
  609. [TMBC-FM-2THIRDS-link]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-fm-2thirds1
  610. [TMBC-SOUND-DISTR-POSS-COMMIT-link]: https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-sound-distr-poss-commit1
  611. [LCV-SEQ-SAFE-link]:https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-seq-safe1
  612. [TMBC-VAL-CONTAINS-CORR-link]:
  613. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-val-contains-corr1
  614. [fetch]:
  615. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-func-fetch1
  616. [LCV-INV-TP1-link]:
  617. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-inv-tp1
  618. [LCV-LB-link]:
  619. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-data-lightblock1
  620. [LCV-LS-link]:
  621. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-data-lightstore2
  622. [LVC-HD-link]:
  623. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#tmbc-header-fields2
  624. [repl]:
  625. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/supervisor/supervisor_001_draft.md#lc-func-replace-secondary1
  626. [vtt]:
  627. https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/verification/verification_002_draft.md#lcv-func-main2