github.com/aakash4dev/cometbft@v0.38.2/spec/ivy-proofs/tendermint_test.ivy (about) 1 #lang ivy1.7 2 3 include tendermint 4 include abstract_tendermint 5 6 isolate ghost_ = { 7 instantiate abstract_tendermint 8 } 9 10 isolate protocol = { 11 instantiate tendermint(ghost_) # here we instantiate the parameter of the tendermint module with `ghost_`; however note that we don't extract any code for `ghost_` (it's not in the list of object in the extract, and it's thus sliced away). 12 implementation { 13 definition init_val(n:node) = <<< `n`%2 >>> 14 } 15 # attribute test = impl 16 } with ghost_, shim, value, round, proposers 17 18 # Here we run a simple scenario that exhibits an execution in which nodes make 19 # a decision. We do this to rule out trivial modeling errors. 20 21 # One option to check that this scenario is valid is to run it in Ivy's REPL. 22 # For this, first compile the scenario: 23 #```ivyc target=repl isolate=code trace=true tendermint_test.ivy 24 # Then, run the produced binary (e.g. for 4 nodes): 25 #``` ./tendermint_test 4 26 # Finally, call the action: 27 #``` scenarios.scenario_1 28 # Note that Ivy will check at runtime that all action preconditions are 29 # satisfied. For example, runing the scenario twice will cause a violation of 30 # the precondition of the `start` action, because a node cannot start twice 31 # (see `require ~_has_started` in action `start`). 32 33 # Another possibility would be to run `ivy_check` on the scenario, but that 34 # does not seem to work at the moment. 35 36 isolate scenarios = { 37 individual all:nset # will be used as parameter to actions requiring a quorum 38 39 after init { 40 var iter := node.iter.create(0); 41 while ~iter.is_end 42 { 43 all := all.insert(iter.val); 44 iter := iter.next; 45 }; 46 assert nset.is_quorum(all); # we can also use asserts to make sure we are getting what we expect 47 } 48 49 export action scenario_1 = { 50 # all nodes start: 51 var iter := node.iter.create(0); 52 while ~iter.is_end 53 { 54 call protocol.server.start(iter.val); 55 iter := iter.next; 56 }; 57 # all nodes receive the leader's proposal: 58 var m:msg; 59 m.m_kind := msg_kind.proposal; 60 m.m_src := 0; 61 m.m_round := 0; 62 m.m_value := 0; 63 m.m_vround := round.minus_one; 64 iter := node.iter.create(0); 65 while ~iter.is_end 66 { 67 call net.recv(iter.val,m); 68 iter := iter.next; 69 }; 70 # all nodes prevote: 71 iter := node.iter.create(0); 72 while ~iter.is_end 73 { 74 call protocol.server.l_22(iter.val,0); 75 iter := iter.next; 76 }; 77 # all nodes receive each other's prevote messages; 78 m.m_kind := msg_kind.prevote; 79 m.m_vround := 0; 80 iter := node.iter.create(0); 81 while ~iter.is_end 82 { 83 var iter2 := node.iter.create(0); # the sender 84 while ~iter2.is_end 85 { 86 m.m_src := iter2.val; 87 call net.recv(iter.val,m); 88 iter2 := iter2.next; 89 }; 90 iter := iter.next; 91 }; 92 # all nodes precommit: 93 iter := node.iter.create(0); 94 while ~iter.is_end 95 { 96 call protocol.server.l_36(iter.val,0,0,all); 97 iter := iter.next; 98 }; 99 # all nodes receive each other's pre-commits 100 m.m_kind := msg_kind.precommit; 101 iter := node.iter.create(0); 102 while ~iter.is_end 103 { 104 var iter2 := node.iter.create(0); # the sender 105 while ~iter2.is_end 106 { 107 m.m_src := iter2.val; 108 call net.recv(iter.val,m); 109 iter2 := iter2.next; 110 }; 111 iter := iter.next; 112 }; 113 # now all nodes can decide: 114 iter := node.iter.create(0); 115 while ~iter.is_end 116 { 117 call protocol.server.l_49_decide(iter.val,0,0,all); 118 iter := iter.next; 119 }; 120 } 121 122 # TODO: add more scenarios 123 124 } with round, node, proposers, value, nset, protocol, shim, net 125 126 # extract code = protocol, shim, round, node 127 extract code = round, node, proposers, value, nset, protocol, shim, net, scenarios