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.

831 lines
30 KiB

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