Compiler Optimisations: Security-Preserving Refinement (NuSMV)¶
Description of the Case Study¶
We study three compiler optimisation patterns and analyse whether they preserve the security guarantees of the original program. Each optimisation transforms a loop-based routine into a more efficient variant: Loop Peeling (LP) moves one iteration outside the loop, Expression Folding Loop Peeling (EFLP) normalises arithmetic expressions, and Dead Branch Elimination (DBE) removes infeasible public branches. For every pair, the source model captures the original program and the target model implements the optimised version. The HyperLTL specification requires that public outputs remain indistinguishable across both programs, ensuring that the transformation does not introduce information leaks.
The NuSMV model(s)¶
 MODULE main
 VAR
    step: 0..9;
    int_x: 0..15;
    int_k: 0..3;
    in_secret: 0..3;
    out_public: 0..3;
  ASSIGN
    -- D = 32
    -- L0:
    -- L1: x = 0
    -- L2: k = 0
    -- L3: while (k < 3) {
    -- L4: if (k == 0) {
    -- L5:  x := in_secretput();}
    -- L6: else {x := x + x;}
    -- L7: k := k + 1;
    -- L8: out_publicput(x % k);
    -- L9: END
  init(step):= 0;
  next(step):=
    case
      (step=0): {1};
      (step=1): {2};
      (step=2): {3};
      ((step=3) &  (int_k<3)): {4};
      ((step=3) & !(int_k<3)): {9};
      ((step=4) &  (int_k=0)): {5};
      ((step=4) & !(int_k=0)): {6};
      (step=5): {7};
      (step=6): {7};
      (step=7): {8};
      (step=8): {3};
      (step=9): {9};
      TRUE: step;
    esac;
  init(int_x) := 0;
  next(int_x) :=
    case
      -- ((int_x+int_x)>15): 15;
      (int_x > 7): 15;
      (step=5) : in_secret;
      (step=6) : (int_x + int_x);
      TRUE: int_x;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=7) : int_k + 1;
      TRUE: int_k;
    esac;
  init(out_public) := 0;
  next(out_public) :=
    case
      ((step=8)& !(int_k=0)): (int_x mod int_k);
      TRUE: out_public;
    esac;
  init(in_secret) := {0, 1, 2, 3};
  next(in_secret) := in_secret;
  DEFINE
  halt := (step=9);
 MODULE main
 VAR
    step: 0..14;
    int_x: 0..15;
    int_k: 0..3;
    in_secret: 0..3;
    out_public: 0..3;
  ASSIGN
    -- L0:
    -- L1: x = 0
    -- L2: k = 0
    -- L3: if (k == 0)
    -- L4: {x := in_secretput();}
    -- L5: else {x := x + x;}
    -- L6: k := k + 1;
    -- L7: out_publicput = (x % k);
    -- L8: while (k < 3) {
    -- L9: if (k == 0) {
    -- L10:  x := in_secretput();}
    -- L11: else {x := x + x;}
    -- L12: k := k + 1;
    -- L13: out_publicput(x % k);
    -- L14: END
  init(step):= 0;
  next(step):=
    case
      (step=0): {1};
      (step=1): {2};
      (step=2): {3};
      ((step=3) &  (int_k=0)): {4};
      ((step=3) & !(int_k=0)): {5};
      (step=4): {6};
      (step=5): {6};
      (step=6): {7};
      (step=7): {8};
      ((step=8) &  (int_k<3)): {9};
      ((step=8) & !(int_k<3)): {14};
      ((step=9) &  (int_k=0)): {10};
      ((step=9) & !(int_k=0)): {11};
      (step=10): {12};
      (step=11): {12};
      (step=12): {13};
      (step=13): {8};
      (step=14): {14};
      TRUE: step;
    esac;
  init(int_x) := 0;
  next(int_x) :=
    case
      (int_x > 7): 15;
      (step=4) : in_secret;
      (step=5) : (int_x + int_x);
      (step=10) : in_secret;
      (step=11) : (int_x + int_x);
      TRUE: int_x;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=6) : int_k+1;
      (step=12) : int_k+1;
      TRUE: int_k;
    esac;
  init(out_public) := 0;
  next(out_public) :=
    case
      ((step=7)& !(int_k=0)): (int_x mod int_k);
      ((step=13)& !(int_k=0)): (int_x mod int_k);
      TRUE: out_public;
    esac;
  init(in_secret) := {0, 1, 2, 3};
  next(in_secret) := in_secret;
  DEFINE
  halt := (step=14);
 MODULE main
 VAR
    step: 0..6;
    in_int_x: 0..9;
    in_int_y: 0..3;
    secret: 0..9;
    int_k: 0..3;
    obs_public_out: 0..3;
  ASSIGN
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: while (k < 3) {
    -- L1: if (k == 0 || k == y) {
    -- L2:  x := secretput();}
    -- L3: else {x := x + x;}
    -- L4: k := k + 1;
    -- L5: obs_public_output(x % k);
    -- L6: END
  init(step):= 0;
  next(step):=
    case
      ((step=0) & (int_k<3)): {1};
      ((step=0) & !(int_k<3)): {6};
      ((step=1) & ((int_k=0) | (int_k=in_int_y))): {2};
      ((step=1) & !((int_k=0) | (int_k=in_int_y))): {3};
      (step=2): {4};
      (step=3): {4};
      (step=4): {5};
      (step=5): {0};
      (step=6): {6};
      TRUE: step;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      -- ((in_int_x+in_int_x)>9): 9;
      (in_int_x>4): 9;
      (step=2) : secret;
      (step=3) : in_int_x+in_int_x;
      TRUE: in_int_x;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=5) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=4) : int_k+1;
      TRUE: int_k;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=1) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      ((step=5)& !(int_k=0)): in_int_x mod int_k;
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=6);
 MODULE main
 VAR
    step: 0..12;
    in_int_x: 0..9;
    in_int_y: 0..3;
    int_k: 0..3;
    secret: 0..9;
    obs_public_out: 0..3;
  ASSIGN
    -- L0:
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: if (k == 0 || k == y)
    -- L1: {x := in_secretput();}
    -- L2: else {x := x + x;}
    -- L3: k := k + 1;
    -- L4: obs_public_output = (x % k);
    -- L5: while (k < 3) {
    -- L6: y = input()
    -- L7: if (k == 0 ||  k == y) {
    -- L8:  x := in_secretput();}
    -- L9: else {x := x + x;}
    -- L10: k := k + 1;
    -- L11: obs_public_output(x % k);
    -- L12: END
  init(step):= 0;
  next(step):=
    case
      ((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
      ((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
      (step=1): {3};
      (step=2): {3};
      (step=3): {4};
      (step=4): {5};
      ((step=5) & (int_k<3)): {6};
      ((step=5) & !(int_k<3)): {11};
      ((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
      ((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
      (step=7): {9};
      (step=8): {9};
      (step=9): {10};
      (step=10): {5};
      (step=11): {11};
      TRUE: step;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      -- ((in_int_x+in_int_x)>9): 9;
      (in_int_x > 4): 9;
      (step=1) : secret;
      (step=2) : in_int_x+in_int_x;
      (step=7) : secret;
      (step=8) : in_int_x+in_int_x;
      TRUE: in_int_x;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=0 | step=7) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=0) : {1,2,3};
      (step=6) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=3) : int_k+1;
      (step=9) : int_k+1;
      TRUE: int_k;
    esac;
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      ((step=4)& !(int_k=0)): in_int_x mod int_k;
      ((step=10)& !(int_k=0)): in_int_x mod int_k;
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=11);
 MODULE main
 VAR
    step: 0..12;
    in_int_x: 0..9;
    in_int_y: 0..3;
    int_k: 0..3;
    secret: 0..9;
    obs_public_out: 0..3;
  ASSIGN
    -- L0:
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: if (k == 0 || k == y)
    -- L1: {x := in_secretput();}
    -- L2: else {x := x + x;}
    -- L3: k := k + 1;
    -- L4: obs_public_output = (x % k);
    -- L5: while (k < 3) {
    -- L6: y = input()
    -- L7: if (k == 0 ||  k == y) {
    -- L8:  x := in_secretput();}
    -- L9: else {x := x;} --error
    -- L10: k := k + 1;
    -- L11: obs_public_output(x % k);
    -- L12: END
  init(step):= 0;
  next(step):=
    case
      ((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
      ((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
      (step=1): {3};
      (step=2): {3};
      (step=3): {4};
      (step=4): {5};
      ((step=5) & (int_k<3)): {6};
      ((step=5) & !(int_k<3)): {11};
      ((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
      ((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
      (step=7): {9};
      (step=8): {9};
      (step=9): {10};
      (step=10): {5};
      (step=11): {11};
      TRUE: step;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      (in_int_x>4): 9;
      (step=1) : secret;
      (step=2) : in_int_x;--error
      (step=7) : secret;
      (step=8) : in_int_x;--error
      TRUE: in_int_x;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=0 | step=7) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=0) : {1,2,3};
      (step=6) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=3) : int_k+1;
      (step=9) : int_k+1;
      TRUE: int_k;
    esac;
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      ((step=4)& !(int_k=0)): in_int_x mod int_k;
      ((step=10)& !(int_k=0)): in_int_x mod int_k;
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=11);
 MODULE main
 VAR
    step: 0..12;
    in_int_x: 0..9;
    in_int_y: 0..3;
    secret: 0..9;
    int_k: 0..3;
    obs_public_out: 0..3;
    loop_count: 0..2;
  ASSIGN
    -- for loop i in range(2)
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L1: while (k < 3) {
    -- L2: if (k == 0 || k == y) {
    -- L3:  x := secretput();}
    -- L4: else {x := x + x;}
    -- L5: k := k + 1;
    -- L6: obs_public_output(x % k);
    -- L7: END
  init(step):= 0;
  next(step):=
    case
      (loop_count=2):  step; -- terminate
      (step=0): {1};
      ((step=1) & (int_k<3)): {2};
      ((step=1) & !(int_k<3)): {6};
      ((step=2) & ((int_k=0) | (int_k=in_int_y))): {3};
      ((step=2) & !((int_k=0) | (int_k=in_int_y))): {4};
      (step=3): {5};
      (step=4): {5};
      (step=4): {5};
      (step=5): {1};
      (step=6): {7};
      (step=7): {0};
      TRUE: step;
    esac;
  init(loop_count) := 0;
  next(loop_count) :=
    case
      (loop_count=2): loop_count;
      (step=7): loop_count+1;
      TRUE: loop_count;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      (step=0) : 0;
      ((in_int_x+in_int_x)>9): 9;
      (step=3) : secret;
      (step=4) : in_int_x+in_int_x;
      TRUE: in_int_x;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=0) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (step=0) : 0;
      (int_k=3): 3;
      (step=5) : int_k+1;
      TRUE: int_k;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=0) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      ((step=6)& !(int_k=0)): in_int_x mod int_k;
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=0 & loop_count=2);
 MODULE main
 VAR
    step: 0..12;
    in_int_x: 0..9;
    in_int_y: 0..3;
    int_k: 0..3;
    secret: 0..9;
    obs_public_out: 0..3;
    loop_count: 0..2;
  ASSIGN
    -- L0: for i in range(2)
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: if (k == 0 || k == y)
    -- L1: {x := in_secretput();}
    -- L2: else {x := x + x;}
    -- L3: k := k + 1;
    -- L4: obs_public_output = (x % k);
    -- L5: while (k < 3) {
    -- L6: y = input()
    -- L7: if (k == 0 ||  k == y) {
    -- L8:  x := in_secretput();}
    -- L9: else {x := x + x;}
    -- L10: k := k + 1; }
    -- L11: obs_public_output(x % k) ;
    -- L12: END
  init(step):= 0;
  next(step):=
    case
      (loop_count=2):  step; -- terminate
      ((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
      ((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
      (step=1): {3};
      (step=2): {3};
      (step=3): {4};
      (step=4): {5};
      ((step=5) & (int_k<3)): {6};
      ((step=5) & !(int_k<3)): {11};
      (step=6): {7};
      ((step=7) & ((int_k=0) | (int_k=in_int_y))): {8};
      ((step=7) & !((int_k=0) | (int_k=in_int_y))): {9};
      (step=8): {10};
      (step=9): {10};
      (step=10): {5};
      (step=11): {12};
      (step=12): {0};
      TRUE: step;
  esac;
  init(loop_count) := 0;
  next(loop_count) :=
    case
      (loop_count=2): loop_count;
      (step=12): loop_count+1;
      TRUE: loop_count;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      (step=0) : 0;
      ((in_int_x+in_int_x)>9): 9;
      (step=1) : secret;
      (step=2) : in_int_x+in_int_x;
      (step=7) : secret;
      (step=8) : in_int_x+in_int_x;
      TRUE: in_int_x;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=0 | step=7) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=0) : {1,2,3};
      (step=6) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (step=0) : 0;
      (int_k=3): 3;
      (step=3) : int_k+1;
      (step=9) : int_k+1;
      TRUE: int_k;
    esac;
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      ((step=4)& !(int_k=0)): in_int_x mod int_k;
      ((step=11)& !(int_k=0)): in_int_x mod int_k;
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=0 & loop_count=2);
 MODULE main
 VAR
    step: 0..12;
    in_int_x: 0..9;
    in_int_y: 0..3;
    int_k: 0..3;
    secret: 0..9;
    obs_public_out: 0..3;
  ASSIGN
    -- L0:
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: if (k == 0 || k == y)
    -- L1: {x := in_secretput();}
    -- L2: else {x := x + x;}
    -- L3: k := k + 1;
    -- L4: obs_public_output = (x % k);
    -- L5: while (k < 3) {
    -- L6: y = input()
    -- L7: if (k == 0 ||  k == y) {
    -- L8:  x := in_secretput();}
    -- L9: else {x := x;} --error
    -- L10: k := k + 1;
    -- L11: obs_public_output(x % k);
    -- L12: END
  init(step):= 0;
  next(step):=
    case
      ((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
      ((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
      (step=1): {3};
      (step=2): {3};
      (step=3): {4};
      (step=4): {5};
      ((step=5) & (int_k<3)): {6};
      ((step=5) & !(int_k<3)): {11};
      ((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
      ((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
      (step=7): {9};
      (step=8): {9};
      (step=9): {10};
      (step=10): {5};
      (step=11): {11};
      TRUE: step;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      ((in_int_x+in_int_x)>9): 9;
      (step=1) : secret;
      (step=2) : in_int_x;--error
      (step=7) : secret;
      (step=8) : in_int_x;--error
      TRUE: in_int_x;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=0 | step=7) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=0) : {1,2,3};
      (step=6) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=3) : int_k+1;
      (step=9) : int_k+1;
      TRUE: int_k;
    esac;
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      ((step=4)& !(int_k=0)): in_int_x mod int_k;
      ((step=10)& !(int_k=0)): in_int_x mod int_k;
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=11);
 MODULE main
 VAR
    step: 0..9;
    int_x: 0..15;
    int_k: 0..3;
    in_secret: 0..3;
    out_public: 0..3;
  ASSIGN
    -- D = 32
    -- L0:
    -- L1: x = 0
    -- L2: k = 0
    -- L3: while (k < 3) {
    -- L4: if (k == 0) {
    -- L5:  x := in_secretput();}
    -- L6: else {x := x + x;}
    -- L7: k := k + 1;
    -- L8: out_public((4 + (x - 4)) % ((k - k) + 3));
    -- L9: END
  init(step):= 0;
  next(step):=
    case
      (step=0): {1};
      (step=1): {2};
      (step=2): {3};
      ((step=3) &  (int_k<3)): {4};
      ((step=3) & !(int_k<3)): {9};
      ((step=4) &  (int_k=0)): {5};
      ((step=4) & !(int_k=0)): {6};
      (step=5): {7};
      (step=6): {7};
      (step=7): {8};
      (step=8): {3};
      (step=9): {9};
      TRUE: step;
    esac;
  init(int_x) := 0;
  next(int_x) :=
    case
      (int_x > 7): 15;
      (step=5) : in_secret;
      (step=6) : int_x + int_x;
      TRUE: int_x;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=7) : int_k + 1;
      TRUE: int_k;
    esac;
  init(out_public) := 0;
  next(out_public) :=
    case
      -- ((step=8)& !(int_k=0)): (4 + (int_x - 4)) mod ((int_k - int_k) + 3);
      ((step=8)& !(int_k=0)): int_x mod 3;
      TRUE: out_public;
    esac;
  init(in_secret) := {0, 1, 2, 3};
  next(in_secret) := in_secret;
  DEFINE
  halt := (step=9);
 MODULE main
 VAR
    step: 0..22;
    int_x: 0..9;
    int_k: 0..3;
    in_secret: 0..3;
    out_public: 0..3;
    move: boolean;
    temp0: 0..7;
    temp1: 0..11;
    temp2: 0..5;
    temp3: 0..5;
  ASSIGN
    -- (diameter: 25)
    -- L0:
    -- L1: x = 0
    -- L2: k = 0
    -- L3: if (k == 0)
    -- L4: {x := in_secretput();}
    -- L5: else {x := x + x;}
    -- L6: k := k + 1;
    -- L7: temp0 = (x-4);
    -- L8: temp1 = (4+temp0)
    -- L9: temp2 = (k-k);
    -- L10: temp3 = (temp2-3);
    -- L11: public_output = (x % k);
    -- L12: while (k < 3) {
    -- L13: if (k == 0) {
    -- L14:  x := in_secretput();}
    -- L15: else {x := x + x;}
    -- L16: k := k + 1;
    -- L17: temp0 = (x-4);
    -- L18: temp1 = (4+temp0);
    -- L19: temp2 = (k-k);
    -- L20: temp3 = (temp2-3);
    -- L21: out_public=temp1 % temp3; }
    -- L22: END
  init(step):= 0;
  next(step):=
    case
      (step=0): {1};
      (step=1): {2};
      (step=2): {3};
      ((step=3) &   (int_k=0)): {4};
      ((step=3) & (!(int_k=0))): {5};
      (step=4): {6};
      (step=5): {6};
      (step=6): {7};
      (step=7): {8};
      (step=8): {9};
      (step=9): {10};
      (step=10): {11};
      (step=11): {12};
      ((step=12) & (int_k<3)): {13};
      ((step=12) & (!(int_k<3))): {22};
      ((step=13) & (int_k=0)): {14};
      ((step=13) & (!(int_k=0))): {15};
      (step=14): {16};
      (step=15): {16};
      (step=16): {17};
      (step=17): {18};
      (step=18): {19};
      (step=19): {20};
      (step=20): {21};
      (step=21): {12};
      (step=22): {22};
      TRUE: step;
    esac;
  init(temp0) := 0;
  next(temp0) :=
    case
      ((step=7) & (int_x>4)): (int_x - 4);
      ((step=7) & (int_x<=4)): 0;
      ((step=17) & (int_x>4)): (int_x - 4);
      ((step=17) & (int_x<=4)): 0;
      TRUE: temp0;
    esac;
  init(temp1) := 0;
  next(temp1) :=
    case
      (step=8): (4+temp0);
      (step=18): (4+temp0);
      TRUE: temp1;
    esac;
  init(temp2) := 0;
  next(temp2) :=
    case
      (step=9): (int_k - int_k);
      (step=19): (int_k - int_k);
      TRUE: temp2;
    esac;
  init(temp3) := 0;
  next(temp3) :=
    case
      ((step=10) & (temp2>3)): (temp2 - 3);
      ((step=10) & (temp2<=3)): 0;
      ((step=20) & (temp2>3)): (temp2 - 3);
      ((step=20) & (temp2<=3)): 0;
      TRUE: temp3;
    esac;
  init(int_x) := 0;
  next(int_x) :=
    case
      -- ((int_x+int_x)>9): 9;
      (int_x > 4): 9;
      (step=4) : in_secret;
      (step=5) : int_x+int_x;
      (step=14) : in_secret;
      (step=15) : int_x+int_x;
      TRUE: int_x;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=6) : int_k+1;
      (step=16) : int_k+1;
      TRUE: int_k;
    esac;
  init(out_public) := 0;
  next(out_public) :=
    case
      -- ((step=11)& !(int_k=0)): temp1 mod temp3;
      -- ((step=21)& !(int_k=0)): temp1 mod temp3;
      ((step=11)& !(int_k=0)): int_x mod 3;
      ((step=21)& !(int_k=0)): int_x mod 3;
      TRUE: out_public;
    esac;
  init(in_secret) := {0, 1, 2, 3};
  next(in_secret) := in_secret;
  DEFINE
  halt := (step=22);
 MODULE main
 VAR
    step: 0..15;
    in_int_x: 0..9;
    in_int_y: 0..3;
    secret: 0..9;
    int_k: 0..3;
    obs_public_out: 0..3;
  ASSIGN
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: while (k < 3) {
    -- L1: if (k == 0 || k == y) {
    -- L2:  x := secretput();}
    -- L3: else {x := x + x;}
    -- L4: k := k + 1;
    -- L5: obs_public_output(x % k);
    -- L6: END
  init(step):= 0;
  next(step):=
    case
      ((step=0) & (int_k<3)): {1};
      ((step=0) & !(int_k<3)): {6};
      ((step=1) & ((int_k=0) | (int_k=in_int_y))): {2};
      ((step=1) & !((int_k=0) | (int_k=in_int_y))): {3};
      (step=2): {4};
      (step=3): {4};
      (step=4): {5};
      (step=5): {0};
      (step=6): {6};
      TRUE: step;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      ((in_int_x+in_int_x)>9): 9;
      (step=2) : secret;
      (step=3) : in_int_x+in_int_x;
      TRUE: in_int_x;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=5) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=4) : int_k+1;
      TRUE: int_k;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=1) : {0,1,2,3};
      TRUE: secret;
    esac;
  --  obs_public = (4 + (x - 4)) % (( k - k ) + 3) }
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      -- ((step=5) & (in_int_x <= 4)): obs_public_out;
      ((step=5)): (in_int_x) mod ((int_k - int_k) + 3);
      TRUE: obs_public_out;
    esac;
  DEFINE
  halt := (step=6);
 MODULE main
 VAR
    step: 0..15;
    in_int_x: 0..9;
    in_int_y: 0..3;
    int_k: 0..3;
    secret: 0..9;
    obs_public_out: 0..3;
    temp0: 0..5;
    temp2: 0..1;
    temp3: 0..3;
  ASSIGN
    -- L0:
    -- L0: x = 0
    -- L0: k = 0
    -- L0: y = input()
    -- L0: if (k == 0 || k == y)
    -- L1: {x := in_secretput();}
    -- L2: else {x := x + x;}
    -- L3: k := k + 1;
    -- L4: obs_public_output = (x % k);
    -- L5: while (k < 3) {
    -- L6: y = input()
    -- L7: if (k == 0 ||  k == y) {
    -- L8:  x := in_secretput();}
    -- L9: else {x := x + x;}
    -- L10: k := k + 1;
    -- L11: temp0 = x-4, temp1 = temp0+4
    -- L12: temp2 = k - k
    -- L13: temp3 = temp2 + 3
    -- L14: obs_public = (4 + temp0) % temp3 }
    -- L15: END
  init(step):= 0;
  next(step):=
    case
      ((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
      ((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
      (step=1): {3};
      (step=2): {3};
      (step=3): {4};
      (step=4): {5};
      ((step=5) & (int_k<3)): {6};
      ((step=5) & !(int_k<3)): {11};
      ((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
      ((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
      (step=7): {9};
      (step=8): {9};
      (step=9): {10};
      (step=10): {5};
      (step=11): {12};
      (step=12): {13};
      (step=13): {14};
      (step=14): {15};
      TRUE: step;
    esac;
  init(in_int_x) := 0;
  next(in_int_x) :=
    case
      ((in_int_x+in_int_x)>9): 9;
      (step=1) : secret;
      (step=2) : in_int_x+in_int_x;
      (step=7) : secret;
      (step=8) : in_int_x+in_int_x;
      TRUE: in_int_x;
    esac;
  init(secret) := 0;
  next(secret) :=
    case
      (step=0 | step=7) : {0,1,2,3};
      TRUE: secret;
    esac;
  init(in_int_y) := 0;
  next(in_int_y) :=
    case
      (step=0) : {1,2,3};
      (step=6) : {1,2,3};
      TRUE: in_int_y;
    esac;
  init(int_k) := 0;
  next(int_k) :=
    case
      (int_k=3): 3;
      (step=3) : int_k+1;
      (step=9) : int_k+1;
      TRUE: int_k;
    esac;
  --  obs_public = (4 + (x - 4)) % (( k - k ) + 3) }
  init(obs_public_out) := 0;
  next(obs_public_out) :=
    case
      -- ((step=4) & (in_int_x <= 4)): obs_public_out;
      -- ((step=12) & (in_int_x <= 4)): obs_public_out;
      ((step=4) & !(temp3=0)): (in_int_x) mod (temp3);
      ((step=14) & !(temp3=0)): (in_int_x) mod (temp3);
      TRUE: obs_public_out;
    esac;
  init(temp0) := 0;
  next(temp0) :=
    case
      (step=11 & (in_int_x <= 4)): 0;
      (step=11): (in_int_x - 4);
      TRUE: temp0;
    esac;
  init(temp2) := 0;
  next(temp2) :=
    case
      (step=12): (int_k - int_k);
      -- (step=12): 0;
      TRUE: temp2;
    esac;
  init(temp3) := 0;
  next(temp3) :=
    case
      (step=13 & !(temp2=0)): 3;
      (step=13): (temp2 + 3);
      TRUE: 3;
    esac;
  DEFINE
  halt := (step=15);
 MODULE main
 VAR
    PC: 0..4;
    in_secret: 0..3;
    out_secret: 0..3;
    out_public: 0..3;
  ASSIGN
    -- L0: x := in_secretput()
    -- L1: if (0):
    -- L2: out_publicput(x)
    -- L3: else: out_secretput(x)
    -- L4: END
  init(PC):= 0;
  next(PC):=
    case
      (PC=0): {1};
      ((PC=1) & (FALSE)): {2};
      ((PC=1) & (!(FALSE))): {3};
      (PC=2): {4};
      (PC=3): {4};
      TRUE: PC;
    esac;
  init(out_public) := 0;
  next(out_public) :=
    case
      (PC=2): in_secret;
      TRUE: out_public;
    esac;
  init(out_secret) := 0;
  next(out_secret) :=
    case
      (PC=3): in_secret;
      TRUE: out_secret;
    esac;
  init(in_secret) := {0, 1};
  next(in_secret) := in_secret;
  DEFINE
    halt := (PC=4);
 MODULE main
 VAR
    PC: 0..2;
    in_secret: 0..3;
    out_secret: 0..3;
    out_public: 0..3;
  ASSIGN
    -- L0: x := in_secretput()
    -- L1: out_secretput(x)
    -- L2: END
  init(PC):= 0;
  next(PC):=
    case
      (PC=0): {1};
      (PC=1): {2};
      TRUE: PC;
    esac;
  init(out_public) := 0;
  next(out_public) := out_public;
  init(out_secret) := 0;
  next(out_secret) := in_secret;
  init(in_secret) := {0, 1};
  next(in_secret) := in_secret;
  DEFINE
    halt := (PC=2);
 MODULE main
 VAR
    PC: 0..6;
    loop_count: 0..3;
    -- secret_in: 0..1;
    -- ndet_in: 0..1;
    in_var_x: 0..1;
    in_var_y: 0..1;
    obs_out: 0..2;
  ASSIGN
    -- for i in rnage(3) -- loop 3 times
    -- L0: x := secret_input()
    -- L0: y := ndet_input()
    -- L1: if (x == y):
    -- L2:  if (0):
    -- L3:  out(x)
    -- L4:  else: out(x)
    -- L5: else: out(!x)
    -- L6: END
  init(PC):= 0;
  next(PC):=
    case
      (PC=0): {1};
      ((PC=1) & (in_var_x=in_var_y)): {2};
      ((PC=1) & (!(in_var_x=in_var_y))): {5};
      ((PC=2) & (FALSE)): {3};
      ((PC=2) & (!(FALSE))): {4};
      (PC=3): {6};
      (PC=4): {6};
      (PC=5): {6};
      ((PC=6) & (loop_count<3)): {0}; -- loop back
      ((PC=6) & (loop_count=3)): {6}; -- terminate
      TRUE: PC;
    esac;
  init(loop_count) := 0;
  next(loop_count) :=
    case
      (loop_count=3): loop_count;
      (PC=0): loop_count+1;
      TRUE: loop_count;
    esac;
  init(obs_out) := 0;
  next(obs_out) :=
    case
      ((PC=6) & (loop_count=3)): obs_out;
      (PC=3): in_var_x;
      (PC=4): in_var_x;
      ((PC=5) & (in_var_x=0)): 1;
      ((PC=5) & (in_var_x=1)): 0;
      TRUE: obs_out;
    esac;
  init(in_var_x) := {0, 1};
  next(in_var_x) :=
    case
      ((PC=6) & (loop_count=3)) : in_var_x; -- terminate
      (PC=6) : {0, 1}; --re-fetch input
      TRUE: in_var_x;
    esac;
  init(in_var_y) := {0, 1};
  next(in_var_y) :=
    case
      ((PC=6) & (loop_count=3)) : in_var_y; -- terminate
      (PC=6) : {0, 1}; --re-fetch input
      TRUE: in_var_y;
    esac;
  DEFINE
    halt := ((PC=6) & (loop_count=3));
 MODULE main
 VAR
    PC: 0..4;
    loop_count: 0..3;
    -- secret_in: 0..1;
    -- ndet_in: 0..1;
    in_var_x: 0..1;
    in_var_y: 0..1;
    obs_out: 0..3;
  ASSIGN
    -- for i in rnage(3) -- loop 3 times
    -- L0: x := secret_input()
    -- L0: y := ndet_input()
    -- L1: if (x == y):
    -- L2:  out(x)
    -- L3: else: out(!x)
    -- L4: END
  init(PC):= 0;
  next(PC):=
    case
      (PC=0): {1};
      ((PC=1) & (in_var_x=in_var_y)): {2};
      ((PC=1) & (!(in_var_x=in_var_y))): {3};
      (PC=2): {4};
      (PC=3): {4};
      ((PC=4) & (loop_count<3)): {0}; -- loop back
      ((PC=4) & (loop_count=3)): {4}; -- terminate
      TRUE: PC;
    esac;
  init(loop_count) := 0;
  next(loop_count) :=
    case
      (loop_count=3): loop_count;
      (PC=0): loop_count+1;
      TRUE: loop_count;
    esac;
  init(obs_out) := 0;
  next(obs_out) :=
    case
      ((PC=4) & (loop_count=3)) : obs_out; --terminate
      (PC=2): in_var_x;
      ((PC=3)&(in_var_x=1)): 0;
      ((PC=3)&(in_var_x=0)): 1;
      TRUE: obs_out;
    esac;
  init(in_var_x) := {0, 1};
  next(in_var_x) :=
    case
      ((PC=4) & (loop_count=3)) : in_var_x; --terminate
      (PC=4) : {0, 1}; --re-fetch input
      TRUE: in_var_x;
    esac;
  init(in_var_y) := {0, 1};
  next(in_var_y) :=
    case
      ((PC=4) & (loop_count=3)) : in_var_y; --terminate
      (PC=4) : {0, 1}; --re-fetch input
      TRUE: in_var_y;
    esac;
  DEFINE
    halt := ((PC=4) & (loop_count=3));
The HyperLTL formula¶
All three optimisations reuse the same observational determinism property: any two traces of the source must match the public outputs of a witness trace, reflecting that the optimised program does not expose new public information.
Forall A . Forall B . E t . G(((out_public[A][t] = 0) & (out_public[B][t] = 0)) | ((out_public[A][t] = 1) & (out_public[B][t] = 1)) | ((out_public[A][t] = 2) & (out_public[B][t] = 2)) | ((out_public[A][t] = 3) & (out_public[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((out_public[A][t] = 0) & (out_public[B][t] = 0)) | ((out_public[A][t] = 1) & (out_public[B][t] = 1)) | ((out_public[A][t] = 2) & (out_public[B][t] = 2)) | ((out_public[A][t] = 3) & (out_public[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((out_public[A][t] = 0) & (out_public[B][t] = 0)) | ((out_public[A][t] = 1) & (out_public[B][t] = 1)) | ((out_public[A][t] = 2) & (out_public[B][t] = 2)) | ((out_public[A][t] = 3) & (out_public[B][t] = 3)))
Forall A . Forall B . E t . G
((obs_out[A][t] = 0) & (obs_out[B][t] = 0) 
|
(obs_out[A][t] = 1) & (obs_out[B][t] = 1) 
|
(obs_out[A][t] = 2) & (obs_out[B][t] = 2))
Forall A . Forall B . E t . G
((obs_out[A][t] = 0) & (obs_out[B][t] = 0) 
|
(obs_out[A][t] = 1) & (obs_out[B][t] = 1) 
|
(obs_out[A][t] = 2) & (obs_out[B][t] = 2))