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.

289 lines
8.8 KiB

  1. # Draft of Functions for Fork detection and Proof of Fork Submisstion
  2. This document collects drafts of function for generating and
  3. submitting proof of fork in the IBC context
  4. - [IBC](#on---chain-ibc-component)
  5. - [Relayer](#relayer)
  6. ## On-chain IBC Component
  7. > The following is a suggestions to change the function defined in ICS 007
  8. #### [TAG-IBC-MISBEHAVIOR.1]
  9. ```go
  10. func checkMisbehaviourAndUpdateState(cs: ClientState, PoF: LightNodeProofOfFork)
  11. ```
  12. **TODO:** finish conditions
  13. - Implementation remark
  14. - Expected precondition
  15. - PoF.TrustedBlock.Header is equal to lightBlock on store with
  16. same height
  17. - both traces end with header of same height
  18. - headers are different
  19. - both traces are supported by PoF.TrustedBlock (`supports`
  20. defined in [TMBC-FUNC]), that is, for `t = currentTimestamp()` (see
  21. ICS 024)
  22. - supports(PoF.TrustedBlock, PoF.PrimaryTrace[1], t)
  23. - supports(PoF.PrimaryTrace[i], PoF.PrimaryTrace[i+1], t) for
  24. *0 < i < length(PoF.PrimaryTrace)*
  25. - supports(PoF.TrustedBlock, PoF.SecondaryTrace[1], t)
  26. - supports(PoF.SecondaryTrace[i], PoF.SecondaryTrace[i+1], t) for
  27. *0 < i < length(PoF.SecondaryTrace)*
  28. - Expected postcondition
  29. - set cs.FrozenHeight to min(cs.FrozenHeight, PoF.TrustedBlock.Header.Height)
  30. - Error condition
  31. - none
  32. ----
  33. > The following is a suggestions to add functionality to ICS 002 and 007.
  34. > I suppose the above is the most efficient way to get the required
  35. > information. Another option is to subscribe to "header install"
  36. > events via CosmosSDK
  37. #### [TAG-IBC-HEIGHTS.1]
  38. ```go
  39. func QueryHeightsRange(id, from, to) ([]Height)
  40. ```
  41. - Expected postcondition
  42. - returns all heights *h*, with *from <= h <= to* for which the
  43. IBC component has a consensus state.
  44. ----
  45. > This function can be used if the relayer has no information about
  46. > the IBC component. This allows late-joining relayers to also
  47. > participate in fork dection and the generation in proof of
  48. > fork. Alternatively, we may also postulate that relayers are not
  49. > responsible to detect forks for heights before they started (and
  50. > subscribed to the transactions reporting fresh headers being
  51. > installed at the IBC component).
  52. ## Relayer
  53. ### Auxiliary Functions to be implemented in the Light Client
  54. #### [LCV-LS-FUNC-GET-PREV.1]
  55. ```go
  56. func (ls LightStore) GetPreviousVerified(height Height) (LightBlock, bool)
  57. ```
  58. - Expected postcondition
  59. - returns a verified LightBlock, whose height is maximal among all
  60. verified lightblocks with height smaller than `height`
  61. ----
  62. ### Relayer Submitting Proof of Fork to the IBC Component
  63. There are two ways the relayer can detect a fork
  64. - by the fork detector of one of its lightclients
  65. - be checking the consensus state of the IBC component
  66. The following function ignores how the proof of fork was generated.
  67. It takes a proof of fork as input and computes a proof of fork that
  68. will be accepted by the IBC component.
  69. The problem addressed here is that both, the relayer's light client
  70. and the IBC component have incomplete light stores, that might
  71. not have all light blocks in common.
  72. Hence the relayer has to figure out what the IBC component knows
  73. (intuitively, a meeting point between the two lightstores
  74. computed in `commonRoot`) and compute a proof of fork
  75. (`extendPoF`) that the IBC component will accept based on its
  76. knowledge.
  77. The auxiliary functions `commonRoot` and `extendPoF` are
  78. defined below.
  79. #### [TAG-SUBMIT-POF-IBC.1]
  80. ```go
  81. func SubmitIBCProofOfFork(
  82. lightStore LightStore,
  83. PoF: LightNodeProofOfFork,
  84. ibc IBCComponent) (Error) {
  85. if ibc.queryChainConsensusState(PoF.TrustedBlock.Height) = PoF.TrustedBlock {
  86. // IBC component has root of PoF on store, we can just submit
  87. ibc.submitMisbehaviourToClient(ibc.id,PoF)
  88. return Success
  89. // note sure about the id parameter
  90. }
  91. else {
  92. // the ibc component does not have the TrustedBlock and might
  93. // even be on yet a different branch. We have to compute a PoF
  94. // that the ibc component can verifiy based on its current
  95. // knowledge
  96. ibcLightBlock, lblock, _, result := commonRoot(lightStore, ibc, PoF.TrustedBlock)
  97. if result = Success {
  98. newPoF = extendPoF(ibcLightBlock, lblock, lightStore, PoF)
  99. ibc.submitMisbehaviourToClient(ibc.id, newPoF)
  100. return Success
  101. }
  102. else{
  103. return CouldNotGeneratePoF
  104. }
  105. }
  106. }
  107. ```
  108. **TODO:** finish conditions
  109. - Implementation remark
  110. - Expected precondition
  111. - Expected postcondition
  112. - Error condition
  113. - none
  114. ----
  115. ### Auxiliary Functions at the Relayer
  116. > If the relayer detects a fork, it has to compute a proof of fork that
  117. > will convince the IBC component. That is it has to compare the
  118. > relayer's local lightstore against the lightstore of the IBC
  119. > component, and find common ancestor lightblocks.
  120. #### [TAG-COMMON-ROOT.1]
  121. ```go
  122. func commonRoot(lightStore LightStore, ibc IBCComponent, lblock
  123. LightBlock) (LightBlock, LightBlock, LightStore, Result) {
  124. auxLS.Init
  125. // first we ask for the heights the ibc component is aware of
  126. ibcHeights = ibc.QueryHeightsRange(
  127. ibc.id,
  128. lightStore.LowestVerified().Height,
  129. lblock.Height - 1);
  130. // this function does not exist yet. Alternatively, we may
  131. // request all transactions that installed headers via CosmosSDK
  132. for {
  133. h, result = max(ibcHeights)
  134. if result = Empty {
  135. return (_, _, _, NoRoot)
  136. }
  137. ibcLightBlock = ibc.queryChainConsensusState(h)
  138. auxLS.Update(ibcLightBlock, StateVerified);
  139. connector, result := Connector(lightStore, ibcLightBlock, lblock.Header.Height)
  140. if result = success {
  141. return (ibcLightBlock, connector, auxLS, Success)
  142. }
  143. else{
  144. ibcHeights.remove(h)
  145. }
  146. }
  147. }
  148. ```
  149. - Expected postcondition
  150. - returns
  151. - a lightBlock b1 from the IBC component, and
  152. - a lightBlock b2
  153. from the local lightStore with height less than
  154. lblock.Header.Hight, s.t. b1 supports b2, and
  155. - a lightstore with the blocks downloaded from
  156. the ibc component
  157. ----
  158. #### [TAG-LS-FUNC-CONNECT.1]
  159. ```go
  160. func Connector (lightStore LightStore, lb LightBlock, h Height) (LightBlock, bool)
  161. ```
  162. - Expected postcondition
  163. - returns a verified LightBlock from lightStore with height less
  164. than *h* that can be
  165. verified by lb in one step.
  166. **TODO:** for the above to work we need an invariant that all verified
  167. lightblocks form a chain of trust. Otherwise, we need a lightblock
  168. that has a chain of trust to height.
  169. > Once the common root is found, a proof of fork that will be accepted
  170. > by the IBC component needs to be generated. This is done in the
  171. > following function.
  172. #### [TAG-EXTEND-POF.1]
  173. ```go
  174. func extendPoF (root LightBlock,
  175. connector LightBlock,
  176. lightStore LightStore,
  177. Pof LightNodeProofofFork) (LightNodeProofofFork}
  178. ```
  179. - Implementation remark
  180. - PoF is not sufficient to convince an IBC component, so we extend
  181. the proof of fork farther in the past
  182. - Expected postcondition
  183. - returns a newPOF:
  184. - newPoF.TrustedBlock = root
  185. - let prefix =
  186. connector +
  187. lightStore.Subtrace(connector.Header.Height, PoF.TrustedBlock.Header.Height-1) +
  188. PoF.TrustedBlock
  189. - newPoF.PrimaryTrace = prefix + PoF.PrimaryTrace
  190. - newPoF.SecondaryTrace = prefix + PoF.SecondaryTrace
  191. ### Detection a fork at the IBC component
  192. The following functions is assumed to be called regularly to check
  193. that latest consensus state of the IBC component. Alternatively, this
  194. logic can be executed whenever the relayer is informed (via an event)
  195. that a new header has been installed.
  196. #### [TAG-HANDLER-DETECT-FORK.1]
  197. ```go
  198. func DetectIBCFork(ibc IBCComponent, lightStore LightStore) (LightNodeProofOfFork, Error) {
  199. cs = ibc.queryClientState(ibc);
  200. lb, found := lightStore.Get(cs.Header.Height)
  201. if !found {
  202. **TODO:** need verify to target
  203. lb, result = LightClient.Main(primary, lightStore, cs.Header.Height)
  204. // [LCV-FUNC-IBCMAIN.1]
  205. **TODO** decide what to do following the outcome of Issue #499
  206. // I guess here we have to get into the light client
  207. }
  208. if cs != lb {
  209. // IBC component disagrees with my primary.
  210. // I fetch the
  211. ibcLightBlock, lblock, ibcStore, result := commonRoot(lightStore, ibc, lb)
  212. pof = new LightNodeProofOfFork;
  213. pof.TrustedBlock := ibcLightBlock
  214. pof.PrimaryTrace := ibcStore + cs
  215. pof.SecondaryTrace := lightStore.Subtrace(lblock.Header.Height,
  216. lb.Header.Height);
  217. return(pof, Fork)
  218. }
  219. return(nil , NoFork)
  220. }
  221. ```
  222. **TODO:** finish conditions
  223. - Implementation remark
  224. - we ask the handler for the lastest check. Cross-check with the
  225. chain. In case they deviate we generate PoF.
  226. - we assume IBC component is correct. It has verified the
  227. consensus state
  228. - Expected precondition
  229. - Expected postcondition