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::distributed_system::*;
use crate::protocol::RSL::constants::*;
use crate::protocol::RSL::types::*;
use crate::protocol::RSL::environment::*;
use crate::protocol::RSL::acceptor::*;
use crate::protocol::RSL::executor::*;
use crate::protocol::RSL::replica::*;
use crate::protocol::RSL::common_proof::assumptions::*;
use crate::protocol::RSL::common_proof::constants::*;

use crate::common::logic::temporal_s::*;
use crate::common::logic::heuristics_i::*;
use crate::common::framework::environment_s::*;
use crate::common::framework::environment_s::LEnvStep;
use crate::common::native::io_s::*;
use crate::common::collections::maps2::*;

verus!{
    // proof fn choose_satisfies<T>(p: spec_fn(T) -> bool)
    //     ensures p(choose |x: T| p(x))
    // {}

    // proof fn choose2_satisfies<A, B>(p: spec_fn(A, B) -> bool)
    //     ensures p(choose |a: A, b: B| p(a, b))
    // {}

    // #[verifier::external_body]
    pub proof fn lemma_ActionThatSendsPacketIsActionOfSource(
        ps:RslState,
        ps_:RslState,
        p:RslPacket
    ) -> (rc:(int,Seq<RslIo>))
    requires ps.constants.config.replica_ids.contains(p.src),
             ps_.environment.sentPackets.contains(p),
             !ps.environment.sentPackets.contains(p),
             RslNext(ps, ps_),
    ensures 0 <= rc.0 < ps.constants.config.replica_ids.len(),
            0 <= rc.0 < ps_.constants.config.replica_ids.len(),
            p.src == ps.constants.config.replica_ids[rc.0],
            RslNextOneReplica(ps, ps_, rc.0, rc.1),
            rc.1.contains(LIoOp::Send{s:p}),
    {
        assert(ps.environment.nextStep is LEnvStepHostIos);
        assert(ps.environment.nextStep->ios.contains(LIoOp::Send{s:p}));
        let (idx, ios) = choose |idx:int, ios:Seq<RslIo>| RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p});
        assume(RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p}));
        assert(RslNextOneReplica(ps, ps_, idx, ios));
        assert(ps.environment.nextStep == LEnvStep::LEnvStepHostIos{actor:ps.constants.config.replica_ids[idx], ios:ios});
        assert(LEnvironment_Next(ps.environment, ps_.environment));
        assert(IsValidLEnvStep(ps.environment, ps.environment.nextStep));
        assert(forall |io| ios.contains(io) ==>  #[trigger] IsValidLIoOp(io, ps.constants.config.replica_ids[idx], ps.environment));
        assert(ios.contains(LIoOp::Send{s:p}));
        assert(IsValidLIoOp(LIoOp::Send{s:p}, ps.constants.config.replica_ids[idx], ps.environment));
        assert(p.src == ps.constants.config.replica_ids[idx]);
        assert(0 <= idx < ps.constants.config.replica_ids.len());
        (idx, ios)
    }

    // #[verifier::external_body]
    pub proof fn lemma_ActionThatSends2aIsMaybeNominateValueAndSend2a(
        ps:RslState,
        ps_:RslState,
        p:RslPacket
    ) -> (
        rc:(int,Seq<RslIo>)
    )
        requires ps.constants.config.replica_ids.contains(p.src),
                p.msg is RslMessage2a,
                ps_.environment.sentPackets.contains(p),
                !ps.environment.sentPackets.contains(p),
                RslNext(ps, ps_),
        ensures 0 <= rc.0 < ps.constants.config.replica_ids.len(),
                0 <= rc.0 < ps_.constants.config.replica_ids.len(),
                p.src == ps.constants.config.replica_ids[rc.0],
                RslNextOneReplica(ps, ps_, rc.0, rc.1),
                rc.1.contains(LIoOp::Send{s:p}),
                SpontaneousIos(rc.1, 1),
                LReplicaNextReadClockMaybeNominateValueAndSend2a(ps.replicas[rc.0].replica, ps_.replicas[rc.0].replica,
                                                                  SpontaneousClock(rc.1), ExtractSentPacketsFromIos(rc.1)),
    {
        assert(ps.environment.nextStep is LEnvStepHostIos);
        assert(ps.environment.nextStep->ios.contains(LIoOp::Send{s:p}));
        let (idx, ios) = choose |idx:int, ios:Seq<RslIo>| RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p});
        let nextActionIndex = ps.replicas[idx].nextActionIndex;
        assume(RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p}));
        assert(RslNextOneReplica(ps, ps_, idx, ios));
        assert(ps.environment.nextStep == LEnvStep::LEnvStepHostIos{actor:ps.constants.config.replica_ids[idx], ios:ios});
        assert(LEnvironment_Next(ps.environment, ps_.environment));
        assert(IsValidLEnvStep(ps.environment, ps.environment.nextStep));
        assert(forall |io| ios.contains(io) ==>  #[trigger] IsValidLIoOp(io, ps.constants.config.replica_ids[idx], ps.environment));
        assert(ios.contains(LIoOp::Send{s:p}));
        assert(IsValidLIoOp(LIoOp::Send{s:p}, ps.constants.config.replica_ids[idx], ps.environment));
        assert(p.src == ps.constants.config.replica_ids[idx]);
        assert(0 <= idx < ps.constants.config.replica_ids.len());

        let pkts = ExtractSentPacketsFromIos(ios);
        lemma_ExtractSentPacketsFromIos(ios);
        // assume(forall |p:RslPacket| pkts.contains(p) <==> ios.contains(LIoOp::Send{s:p}));
        // // assert(forall |p:RslPacket| pkts.contains(p) ==> p.msg is RslMessage2a);
        // assert(ios.contains(LIoOp::Send{s:p}));
        assert(pkts.contains(p));
        assert(p.msg is RslMessage2a);

        if nextActionIndex != 3
        {
            assert(!exists |p:RslPacket| pkts.contains(p) && p.msg is RslMessage2a);
            assert(false);
        }
        (idx, ios)
    }

    // #[verifier::external_body]
    pub proof fn lemma_ActionThatSends1bIsProcess1a(
        ps:RslState,
        ps_:RslState,
        p:RslPacket
    ) -> (
        rc:(int,Seq<RslIo>)
    )
        requires ps.constants.config.replica_ids.contains(p.src),
                p.msg is RslMessage1b,
                ps_.environment.sentPackets.contains(p),
                !ps.environment.sentPackets.contains(p),
                RslNext(ps, ps_),
        ensures 0 <= rc.0 < ps.constants.config.replica_ids.len(),
                0 <= rc.0 < ps_.constants.config.replica_ids.len(),
                p.src == ps.constants.config.replica_ids[rc.0],
                RslNextOneReplica(ps, ps_, rc.0, rc.1),
                rc.1.len() > 0,
                rc.1[0] is Receive,
                rc.1[0]->r.msg is RslMessage1a,
                rc.1.contains(LIoOp::Send{s:p}),
                LReplicaNextProcessPacketWithoutReadingClock(ps.replicas[rc.0].replica, ps_.replicas[rc.0].replica, rc.1),
                LAcceptorProcess1a(ps.replicas[rc.0].replica.acceptor, ps_.replicas[rc.0].replica.acceptor, rc.1[0]->r, seq![p]),
    {
        assert(ps.environment.nextStep is LEnvStepHostIos);
        assert(ps.environment.nextStep->ios.contains(LIoOp::Send{s:p}));
        let (idx, ios) = choose |idx:int, ios:Seq<RslIo>| RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p});
        let nextActionIndex = ps.replicas[idx].nextActionIndex;
        assume(RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p}));
        assert(RslNextOneReplica(ps, ps_, idx, ios));
        assert(ps.environment.nextStep == LEnvStep::LEnvStepHostIos{actor:ps.constants.config.replica_ids[idx], ios:ios});
        assert(LEnvironment_Next(ps.environment, ps_.environment));
        assert(IsValidLEnvStep(ps.environment, ps.environment.nextStep));
        assert(forall |io| ios.contains(io) ==>  #[trigger] IsValidLIoOp(io, ps.constants.config.replica_ids[idx], ps.environment));
        assert(ios.contains(LIoOp::Send{s:p}));
        assert(IsValidLIoOp(LIoOp::Send{s:p}, ps.constants.config.replica_ids[idx], ps.environment));
        assert(p.src == ps.constants.config.replica_ids[idx]);
        assert(0 <= idx < ps.constants.config.replica_ids.len());

        // assert(nextActionIndex == 0);
        let pkts = ExtractSentPacketsFromIos(ios);
        lemma_ExtractSentPacketsFromIos(ios);
        assert(pkts.contains(p));
        assert(p.msg is RslMessage1b);
        if nextActionIndex!= 0 {
            assert(false);
        }
        (idx, ios)
    }

    // #[verifier::external_body]
    pub proof fn lemma_ActionThatSends2bIsProcess2a(
        ps:RslState,
        ps_:RslState,
        p:RslPacket
    ) -> (
        rc:(int,Seq<RslIo>)
    )
        requires ps.constants.config.replica_ids.contains(p.src),
                p.msg is RslMessage2b,
                ps_.environment.sentPackets.contains(p),
                !ps.environment.sentPackets.contains(p),
                RslNext(ps, ps_),
        ensures 0 <= rc.0 < ps.constants.config.replica_ids.len(),
                0 <= rc.0 < ps_.constants.config.replica_ids.len(),
                p.src == ps.constants.config.replica_ids[rc.0],
                RslNextOneReplica(ps, ps_, rc.0, rc.1),
                rc.1.len() > 0,
                rc.1[0] is Receive,
                rc.1.contains(LIoOp::Send{s:p}),
                LReplicaNextProcess2a(ps.replicas[rc.0].replica, ps_.replicas[rc.0].replica, rc.1[0]->r, ExtractSentPacketsFromIos(rc.1)),
    {
        assert(ps.environment.nextStep is LEnvStepHostIos);
        assert(ps.environment.nextStep->ios.contains(LIoOp::Send{s:p}));
        let (idx, ios) = choose |idx:int, ios:Seq<RslIo>| RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p});
        let nextActionIndex = ps.replicas[idx].nextActionIndex;
        assume(RslNextOneReplica(ps, ps_, idx, ios) && ios.contains(LIoOp::Send{s:p}));
        assert(RslNextOneReplica(ps, ps_, idx, ios));
        assert(ps.environment.nextStep == LEnvStep::LEnvStepHostIos{actor:ps.constants.config.replica_ids[idx], ios:ios});
        assert(LEnvironment_Next(ps.environment, ps_.environment));
        assert(IsValidLEnvStep(ps.environment, ps.environment.nextStep));
        assert(forall |io| ios.contains(io) ==>  #[trigger] IsValidLIoOp(io, ps.constants.config.replica_ids[idx], ps.environment));
        assert(ios.contains(LIoOp::Send{s:p}));
        assert(IsValidLIoOp(LIoOp::Send{s:p}, ps.constants.config.replica_ids[idx], ps.environment));
        assert(p.src == ps.constants.config.replica_ids[idx]);
        assert(0 <= idx < ps.constants.config.replica_ids.len());

        let pkts = ExtractSentPacketsFromIos(ios);
        lemma_ExtractSentPacketsFromIos(ios);
        assert(pkts.contains(p));
        assert(p.msg is RslMessage2b);
        if nextActionIndex!= 0 {
            assert(false);
        }
        (idx, ios)
    }

    // #[verifier::external_body]
    pub proof fn lemma_ActionThatSendsAppStateSupplyIsProcessAppStateRequest(
        ps: RslState,
        ps_prime: RslState,
        p: RslPacket
    ) -> (rc:(int, Seq<RslIo>))
        requires
            ps.constants.config.replica_ids.contains(p.src),
            p.msg is RslMessageAppStateSupply,
            ps_prime.environment.sentPackets.contains(p),
            !ps.environment.sentPackets.contains(p),
            RslNext(ps, ps_prime),
        ensures
            ({
                let idx = rc.0;
                let ios = rc.1;
                &&& (0 <= idx < ps.constants.config.replica_ids.len())
                &&& (0 <= idx < ps_prime.constants.config.replica_ids.len())
                &&& p.src == ps.constants.config.replica_ids[idx]
                &&& RslNextOneReplica(ps, ps_prime, idx, ios)
                &&& ios.len() > 0
                &&& ios[0] is Receive
                &&& ios[0]->r.msg is RslMessageAppStateRequest
                &&& ios.contains(LIoOp::Send{s:p})
                &&& LReplicaNextProcessPacketWithoutReadingClock(
                    ps.replicas[idx].replica, ps_prime.replicas[idx].replica, ios
                )
                &&& LExecutorProcessAppStateRequest(
                    ps.replicas[idx].replica.executor, ps_prime.replicas[idx].replica.executor, ios[0]->r, seq![p]
                )
            }),
    {
        assert(ps.environment.nextStep is LEnvStepHostIos);
        assert(ps.environment.nextStep->ios.contains(LIoOp::Send{s:p}));
        let (idx, ios) = choose |idx: int, ios: Seq<RslIo>| 
            RslNextOneReplica(ps, ps_prime, idx, ios) && ios.contains(LIoOp::Send{s:p});
        let nextActionIndex = ps.replicas[idx].nextActionIndex;
        assume(RslNextOneReplica(ps, ps_prime, idx, ios) && ios.contains(LIoOp::Send{s:p}));
        assert(RslNextOneReplica(ps, ps_prime, idx, ios));
        assert(ps.environment.nextStep == LEnvStep::LEnvStepHostIos{actor:ps.constants.config.replica_ids[idx], ios:ios});
        assert(LEnvironment_Next(ps.environment, ps_prime.environment));
        assert(IsValidLEnvStep(ps.environment, ps.environment.nextStep));
        assert(forall |io| ios.contains(io) ==>  #[trigger] IsValidLIoOp(io, ps.constants.config.replica_ids[idx], ps.environment));
        assert(ios.contains(LIoOp::Send{s:p}));
        assert(IsValidLIoOp(LIoOp::Send{s:p}, ps.constants.config.replica_ids[idx], ps.environment));
        assert(p.src == ps.constants.config.replica_ids[idx]);
        assert(0 <= idx < ps.constants.config.replica_ids.len());

        let pkts = ExtractSentPacketsFromIos(ios);
        lemma_ExtractSentPacketsFromIos(ios);
        assert(pkts.contains(p));
        assert(p.msg is RslMessageAppStateSupply);
        if nextActionIndex!= 0 {
            assert(false);
        }
        (idx, ios)
    }
    
}