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.

90 lines
2.9 KiB

  1. #lang ivy1.7
  2. # ---
  3. # layout: page
  4. # title: Proof of Classic Safety
  5. # ---
  6. include order # this is a file from the standard library (`ivy/ivy/include/1.7/order.ivy`)
  7. isolate round = {
  8. type this
  9. individual minus_one:this
  10. relation succ(R1:round, R2:round)
  11. action incr(i:this) returns (j:this)
  12. specification {
  13. # to simplify verification, we treat rounds as an abstract totally ordered set with a successor relation.
  14. instantiate totally_ordered(this)
  15. property minus_one < 0
  16. property succ(X,Z) -> (X < Z & ~(X < Y & Y < Z))
  17. after incr {
  18. ensure succ(i,j)
  19. }
  20. }
  21. implementation {
  22. # here we prove that the abstraction is sound.
  23. interpret this -> int # rounds are integers in the Tendermint specification.
  24. definition minus_one = 0-1
  25. definition succ(R1,R2) = R2 = R1 + 1
  26. implement incr {
  27. j := i+1;
  28. }
  29. }
  30. }
  31. instance node : iterable # nodes are a set with an order, that can be iterated over (see order.ivy in the standard library)
  32. relation well_behaved(N:node) # whether a node is well-behaved or not. NOTE: Use only in the proof! Nodes do know know that.
  33. isolate proposers = {
  34. # each round has a unique proposer in Tendermint. In order to avoid a
  35. # function from round to node (which makes verification more difficult), we
  36. # abstract over this function using a relation.
  37. relation is_proposer(N:node, R:round)
  38. action get_proposer(r:round) returns (n:node)
  39. specification {
  40. property is_proposer(N1,R) & is_proposer(N2,R) -> N1 = N2
  41. after get_proposer {
  42. ensure is_proposer(n,r);
  43. }
  44. }
  45. implementation {
  46. # here we prove that the abstraction is sound
  47. function f(R:round):node
  48. definition is_proposer(N,R) = N = f(R)
  49. implement get_proposer {
  50. n := f(r);
  51. }
  52. }
  53. }
  54. isolate value = { # the type of values
  55. type this
  56. relation valid(V:value)
  57. individual nil:value
  58. specification {
  59. property ~valid(nil)
  60. }
  61. implementation {
  62. definition valid(V) = V ~= nil
  63. }
  64. }
  65. object nset = { # the type of node sets
  66. type this # a set of N=3f+i nodes for 0<i<=3
  67. relation member(N:node, S:nset) # set-membership relation
  68. relation is_quorum(S:nset) # intent: sets of cardinality at least 2f+i+1
  69. relation is_blocking(S:nset) # intent: at least f+1 nodes
  70. }
  71. object classic_bft = {
  72. relation quorum_intersection
  73. private {
  74. definition [quorum_intersection_def] quorum_intersection = forall Q1,Q2. exists N. well_behaved(N) & nset.member(N, Q1) & nset.member(N, Q2) # every two quorums have a well-behaved node in common
  75. }
  76. }
  77. trusted isolate accountable_bft = {
  78. # this is our baseline assumption about quorums:
  79. private {
  80. property [max_2f_byzantine] exists N . well_behaved(N) & nset.member(N,Q) # every quorum has a well-behaved member
  81. }
  82. }# with nset