tla-rs 0.1.0

Rust implementation of the IronFleet verified distributed systems framework
use builtin::*;
use builtin_macros::*;
use vstd::{map::*, modes::*, prelude::*, seq::*, seq_lib::*, *};
use vstd::{set::*, set_lib::*};
use crate::protocol::RSL::configuration::*;
use crate::protocol::RSL::constants::*;
use crate::protocol::RSL::broadcast::*;
use crate::protocol::RSL::environment::*;
use crate::protocol::RSL::types::*;
use crate::protocol::RSL::message::*;
use crate::protocol::RSL::state_machine::*;
use crate::services::RSL::app_state_machine::*;
use crate::common::framework::environment_s::*;
use crate::common::native::io_s::*;

verus! {
    pub struct LLearner {
        pub constants:LReplicaConstants,
        pub max_ballot_seen:Ballot,
        pub unexecuted_learner_state:LearnerState
    }

    pub open spec fn LLearnerInit(l:LLearner, c:LReplicaConstants) -> bool
    {
      &&& l.constants == c
      &&& l.max_ballot_seen == Ballot{seqno:0, proposer_id:0}
      &&& l.unexecuted_learner_state == Map::<OperationNumber, LearnerTuple>::empty()
    }

    pub open spec fn LLearnerProcess2b(
        s:LLearner, 
        s_:LLearner, 
        packet:RslPacket
    ) -> bool 
        recommends 
            packet.msg is RslMessage2b,
    {
        let m = packet.msg;
        let opn = m->opn_2b;
        if !s.constants.all.config.replica_ids.contains(packet.src) || BalLt(m->bal_2b, s.max_ballot_seen) {
            s_ == s 
        } else if BalLt(s.max_ballot_seen, m->bal_2b) {
            let tup_ = LearnerTuple{received_2b_message_senders:set![packet.src], candidate_learned_value:m->val_2b};
            s_ == LLearner{
                constants:s.constants,
                max_ballot_seen:m->bal_2b,
                unexecuted_learner_state:map![opn => tup_]
            }
        } else if !s.unexecuted_learner_state.contains_key(opn) {
            let tup_ = LearnerTuple{received_2b_message_senders:set![packet.src], candidate_learned_value:m->val_2b};
            s_ == LLearner{
                constants:s.constants,
                max_ballot_seen:m->bal_2b,
                unexecuted_learner_state:s.unexecuted_learner_state.insert(opn, tup_)
            }
        } else if s.unexecuted_learner_state[opn].received_2b_message_senders.contains(packet.src) {
            s_ == s 
        } else {
            let tup = s.unexecuted_learner_state[opn];
            let tup_ = LearnerTuple{received_2b_message_senders:tup.received_2b_message_senders+set![packet.src], candidate_learned_value:tup.candidate_learned_value};
            s_ == LLearner{
                constants:s.constants,
                max_ballot_seen:s.max_ballot_seen,
                unexecuted_learner_state:s.unexecuted_learner_state.insert(opn, tup_)
            }
        }
    }

    pub open spec fn LLearnerForgetDecision(
        s:LLearner, 
        s_:LLearner, 
        opn:OperationNumber
    ) -> bool
    {
        if s.unexecuted_learner_state.contains_key(opn) {
            s_ == LLearner{
                constants:s.constants,
                max_ballot_seen:s.max_ballot_seen,
                unexecuted_learner_state:s.unexecuted_learner_state.remove(opn)
            }
        } else {
            s_ == s
        }
    }

    pub open spec fn LLearnerForgetOperationsBefore(
        s:LLearner, 
        s_:LLearner, 
        ops_complete:OperationNumber
    ) -> bool 
    {
        &&& (forall |k:OperationNumber| s_.unexecuted_learner_state.contains_key(k) <==> k >= ops_complete && s.unexecuted_learner_state.contains_key(k))
        &&& (forall |k:OperationNumber| s_.unexecuted_learner_state.contains_key(k) ==> s_.unexecuted_learner_state[k] == s.unexecuted_learner_state[k])
        &&& s_ == LLearner{
            constants:s.constants,
            max_ballot_seen:s.max_ballot_seen,
            unexecuted_learner_state:s_.unexecuted_learner_state
        }
    }
}