Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f7f1fea
stdlib: basic commutative algebra
strub Aug 21, 2024
744726e
CommAlgebra: witness-level (comax) CRT layer
strub Jul 17, 2026
e0559cc
CommAlgebra: stack as Base / Euclidean; guard dvdw
strub Jul 17, 2026
849bd69
Poly: evaluation lemma library; tighten the peval definition
strub Jul 17, 2026
8552b01
Poly, ZModP: keep instance members as aliases; export IDPoly
strub Jul 17, 2026
d5468de
Poly: evaluation of polynomial products
strub Jul 17, 2026
0d95a1a
Poly: rename peval_big to peval_sum
strub Jul 17, 2026
845b893
Poly: products of monic linear factors
strub Jul 17, 2026
4fa084d
Poly: mprod does not vanish outside its roots
strub Jul 17, 2026
306c718
Poly: simplify the monic-linear-factor lemmas
strub Jul 17, 2026
00b4e51
Poly: PolyField, polynomials over a field; Lagrange interpolation
strub Jul 17, 2026
87d2303
Poly: package Lagrange interpolation in a sub-theory; tidy proofs
strub Jul 17, 2026
ac5a7aa
CommAlgebra: Base owns its big operators and pushes them into Ideal
strub Jul 17, 2026
40e48db
Ring, ZModP: delta-only mixins for IDomain and Field (pilot)
strub Jul 18, 2026
db50e32
Ring, ZModP: reference-bundles for domains and fields
strub Jul 18, 2026
ba115dc
Poly: mixin architecture for the IDomain and Field levels
strub Jul 18, 2026
3bad478
ZModP: remove the bundled ZModpField clone
strub Jul 18, 2026
9086adf
Ideal, CommAlgebra: mixin parameters; BigPoly's CR slot as alias
strub Jul 18, 2026
a3d177a
CommAlgebra: generic congruence modulo an element (eqm)
strub Jul 18, 2026
76dff10
Packed theory aliases: theory A = T1 + ... + Tn
strub Jul 19, 2026
0dec6fa
ZModP: restore the flat ZModpField namespace as a packed alias
strub Jul 19, 2026
eb2701d
Proof-local reduction-opacity overrides: [-delta op] / [+delta op]
strub Jul 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/SchnorrPK.ec
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ clone G.PowZMod as GP with

clone GP.FDistr as FD.

clone GP.ZModE.ZModpField as ZPF.
clone GP.ZModE.ZModpFieldBd as ZPF.

import G GP GP.ZModE FD.

Expand Down Expand Up @@ -145,7 +145,7 @@ section SchnorrPKSecurity.
auto; rewrite /R /R_DL /oget => &hr /> hne 2!-> /=.
rewrite expM !expB accepting_transcript_1 accepting_transcript_2.
rewrite invM (mulcC m{hr}) -mulcA (mulcA m{hr}) mulcV mulcA mulc1 -expB -expM.
by rewrite ZPF.divrr ?ZPF.subr_eq0 // exp1.
by rewrite ZPF.F.divff ?ZPF.R.subr_eq0 // exp1.
qed.

(* Special honest verifier zero knowledge *)
Expand Down
4 changes: 2 additions & 2 deletions examples/UC/dh_enc.ec
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ require DiffieHellman.
clone DiffieHellman as DH.
import DH.DDH DH.G DH.GP DH.FD DH.GP.ZModE.

clone DH.GP.ZModE.ZModpField as ZPF.
clone DH.GP.ZModE.ZModpFieldBd as ZPF.

(* Such statements make no sense when we don't restrict to a
complexity class
Expand Down Expand Up @@ -896,7 +896,7 @@ wp;call (_: ={glob HybFChan.F2Auth.F2Auth,
); last first.

(* Init *)
by auto => /> &2; rewrite expM /= -expM ZPF.mulrC expM.
by auto => /> &2; rewrite expM /= -expM ZPF.R.mulrC expM.
(* Now the call *)
+ by proc;inline *; auto => /> /#.
+ by sim />.
Expand Down
8 changes: 4 additions & 4 deletions examples/cramer-shoup/cramer_shoup.ec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require DiffieHellman.
clone DiffieHellman as DH.
import DH.DDH DH.G DH.GP DH.FD DH.GP.ZModE.

clone DH.GP.ZModE.ZModpField as ZPF.
clone DH.GP.ZModE.ZModpFieldBd as ZPF.

lemma gt1_q : 1 < order by smt(ge2_p).

Expand Down Expand Up @@ -576,7 +576,7 @@ section Security_Aux.
move=> kL _ xL _ x2L _ yL _ y2L _ zL _ resu bL _.
have H1 : (-uL) * wL + u'L * wL = wL * (u'L - uL) by ring.
have H2 : (-uL) * wL + u'L * wL <> zero.
+ rewrite H1 ZPF.mulf_eq0 negb_or HwL /=.
+ rewrite H1 ZPF.F.mulf_eq0 negb_or HwL /=.
by move: Hu'L;apply: contra => H;ring H.
split => [? _ | _ ]; 1: by field.
move=> z2L _; split => [ | _]; 1: by field.
Expand Down Expand Up @@ -605,7 +605,7 @@ section Security_Aux.
move=> kL _ yL _ y2L _ zL _ r'L _ xL _.
have H1 : (-uL) * wL + u'L * wL = wL * (u'L - uL) by ring.
have H2 : (-uL) * wL + u'L * wL <> zero.
+ rewrite H1 ZPF.mulf_eq0 negb_or HwL /=.
+ rewrite H1 ZPF.F.mulf_eq0 negb_or HwL /=.
by move: Hu'L;apply: contra => H;ring H.
split => [? _ | _ ]; 1: by field.
move=> z2L _; split => [ | _]; 1: by field.
Expand Down Expand Up @@ -751,7 +751,7 @@ section Security_Aux.
move=> yL _ y2L _ zL _ r'L _ xL _ rL _.
have H1 : (-uL) * wL + u'L * wL = wL * (u'L - uL) by ring.
have H2 : (-uL) * wL + u'L * wL <> zero.
+ rewrite H1 ZPF.mulf_eq0 negb_or HwL0 /=.
+ rewrite H1 ZPF.F.mulf_eq0 negb_or HwL0 /=.
by move: HuL;apply: contra => H;ring H.
split => [ | _ /#].
rewrite log_bij !(logg1, logrzM, logDr); field.
Expand Down
6 changes: 3 additions & 3 deletions examples/elgamal.ec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pragma +implicits.
clone DiffieHellman as DH.
import DH.DDH DH.G DH.GP DH.FD DH.GP.ZModE.

clone DH.GP.ZModE.ZModpField as ZPF.
clone DH.GP.ZModE.ZModpFieldBd as ZPF.

(** Construction: a PKE **)
type pkey = group.
Expand Down Expand Up @@ -107,8 +107,8 @@ section Security.
(fun z, z - loge (if b then m1 else m0){2}).
auto; call (_:true).
auto; progress.
- by rewrite ZPF.addrAC -ZPF.addrA ZPF.subrr ZPF.addr0.
- by rewrite -ZPF.addrA ZPF.subrr ZPF.addr0.
- by rewrite ZPF.R.addrAC -ZPF.R.addrA ZPF.R.subrr ZPF.R.addr0.
- by rewrite -ZPF.R.addrA ZPF.R.subrr ZPF.R.addr0.
- by rewrite expD expgK.
qed.

Expand Down
8 changes: 7 additions & 1 deletion src/ecCallbyValue.ml
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ and try_reduce_fixdef
if not (st.st_ri.iota && is_fix_def st p) then
raise Bailout;

(match st.st_ri.delta_p p with
| `Force -> ()
| _ ->
if EcReduction.reduction_opaque st.st_ri st.st_env p then
raise Bailout);

let Args.{ resty = ty; stack = args; } = args in
let op = oget (oper st p) in
let fix = EcDecl.operator_as_fix op in
Expand Down Expand Up @@ -424,7 +430,7 @@ and reduce_user_delta st f1 p tys args =
match reduce_user_with_exn st f2 with
| f -> f
| exception NotReducible ->
let mode = st.st_ri.delta_p p in
let mode = EcReduction.opacity_mode st.st_ri p (st.st_ri.delta_p p) in
let nargs = List.length args.stack in
match mode with
| #Op.redmode as mode -> begin
Expand Down
2 changes: 1 addition & 1 deletion src/ecCommands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ and process_th_clone (scope : EcScope.scope) thcl =
EcScope.Cloning.clone scope (Pragma.get ()).pm_check thcl

(* -------------------------------------------------------------------- *)
and process_th_alias (scope : EcScope.scope) (thcl : psymbol * pqsymbol) =
and process_th_alias (scope : EcScope.scope) (thcl : psymbol * pqsymbol list) =
EcScope.check_state `InTop "theory alias" scope;
EcScope.Theory.alias scope thcl

Expand Down
98 changes: 85 additions & 13 deletions src/ecEnv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,29 @@ let empty_mc params = {
mc_components = MMsym.empty;
}

(* -------------------------------------------------------------------- *)
(* Merge the members of [mc2] into [mc1]. Entries keep their original
* paths; bindings of [mc2] shadow same-named bindings of [mc1] (the
* most recently merged component wins, as with imports). *)
let mc_merge (mc1 : mc) (mc2 : mc) =
let merge m1 m2 =
MMsym.fold
(fun x vs acc -> List.fold_right (fun v acc -> MMsym.add x v acc) vs acc)
m2 m1 in

{ mc_parameters = mc1.mc_parameters;
mc_modules = merge mc1.mc_modules mc2.mc_modules;
mc_modsigs = merge mc1.mc_modsigs mc2.mc_modsigs;
mc_tydecls = merge mc1.mc_tydecls mc2.mc_tydecls;
mc_operators = merge mc1.mc_operators mc2.mc_operators;
mc_axioms = merge mc1.mc_axioms mc2.mc_axioms;
mc_theories = merge mc1.mc_theories mc2.mc_theories;
mc_variables = merge mc1.mc_variables mc2.mc_variables;
mc_functions = merge mc1.mc_functions mc2.mc_functions;
mc_typeclasses= merge mc1.mc_typeclasses mc2.mc_typeclasses;
mc_rwbase = merge mc1.mc_rwbase mc2.mc_rwbase;
mc_components = merge mc1.mc_components mc2.mc_components; }

(* -------------------------------------------------------------------- *)
let empty_norm_cache =
{ norm_mp = Mm.empty;
Expand Down Expand Up @@ -1153,9 +1176,37 @@ module MC = struct
| Th_baserw (x, _) ->
(add2mc _up_rwbase x (expath x) mc, None)

| Th_alias _ ->
(* FIXME:ALIAS *)
(mc, None)
| Th_alias (name, targets) -> begin
(* Alias entries resolve to their targets. A single-target
* alias is a pure component redirection; a packed alias
* (several targets) gets a merged component built from the
* sibling targets (enforced in [EcScope.Theory.alias]),
* whose entries keep the targets' paths. *)
match targets with
| [target] ->
(_up_mc ~name false mc (IPPath target), None)

| targets ->
let mc_of_target (target : path) =
let tname = EcPath.basename target in
let tcth =
List.find_map_opt
(fun item ->
match item.ti_item with
| Th_theory (x, tcth) when x = tname -> Some tcth
| _ -> None)
cth.cth_items in
(* enforced by [EcScope.Theory.alias] *)
let tcth = oget tcth in
let ((_, tmc), _) = mc_of_theory_r subscope (tname, tcth) in
tmc in

let merged =
List.fold_left mc_merge (empty_mc None)
(List.map mc_of_target targets) in
let mc = _up_mc false mc (IPPath (expath name)) in
(mc, Some ((name, merged), []))
end
| Th_export _
| Th_addrw _
| Th_instance _
Expand Down Expand Up @@ -3498,18 +3549,39 @@ module Theory = struct
Option.get (Mp.find_opt p env.env_thenvs)

(* ------------------------------------------------------------------ *)
let rebind_alias (name : symbol) (path : path) (env : env) =
let th = by_path path env in
let src = EcPath.pqname (root env) name in
let env = MC.import_theory ~name path th env in
let env = MC.import_mc ~name (IPPath path) env in
let env = { env with env_albase = Mp.add path src env.env_albase } in
env
let rebind_alias (name : symbol) (paths : path list) (env : env) =
match paths with
| [path] ->
let th = by_path path env in
let src = EcPath.pqname (root env) name in
let env = MC.import_theory ~name path th env in
let env = MC.import_mc ~name (IPPath path) env in
let env = { env with env_albase = Mp.add path src env.env_albase } in
env

| paths ->
(* Packed alias: merge the targets' components under the alias
* name. Entries keep their original paths, so resolution
* always yields the aliased objects -- no copies. Contrary to
* [MC.bind_mc], rebinding must be idempotent: the alias is
* rebound on every import of the enclosing theory. *)
let mc_of (p : path) =
oget (Mip.find_opt (IPPath p) env.env_comps) in
let merged =
List.fold_left mc_merge (empty_mc None) (List.map mc_of paths) in
let apath = IPPath (EcPath.pqname (root env) name) in
{ env with
env_current = MC._up_mc true env.env_current apath;
env_comps =
Mip.change
(fun mc -> Some (MC._up_mc true (oget mc) apath))
(IPPath (root env))
(Mip.add apath merged env.env_comps); }

(* ------------------------------------------------------------------ *)
let alias ?(import = true) (name : symbol) (path : path) (env : env) =
let env = if import then rebind_alias name path env else env in
{ env with env_item = mkitem ~import (Th_alias (name, path)) :: env.env_item }
let alias ?(import = true) (name : symbol) (paths : path list) (env : env) =
let env = if import then rebind_alias name paths env else env in
{ env with env_item = mkitem ~import (Th_alias (name, paths)) :: env.env_item }

(* ------------------------------------------------------------------ *)
let aliases (env : env) =
Expand Down
2 changes: 1 addition & 1 deletion src/ecEnv.mli
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ module Theory : sig
-> EcTheory.thmode
-> env -> compiled_theory option

val alias : ?import:bool -> symbol -> path -> env -> env
val alias : ?import:bool -> symbol -> path list -> env -> env
val aliases : env -> path Mp.t
end

Expand Down
27 changes: 25 additions & 2 deletions src/ecHiGoal.ml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ let process_change fp (tc : tcenv1) =
let fp = TTC.tc1_process_formula tc fp in
t_change fp tc

(* -------------------------------------------------------------------- *)
(* Resolve the [-delta ops] / [+delta ops] items of a hint clause and
record them as reduction-opacity overrides in the simplify context. *)
let apply_hint_opacity tc env (specs : (bool * pqsymbol list) list) simpl =
List.fold_left (fun simpl (opq, ops) ->
let ops =
List.map (fun ps ->
match EcEnv.Op.lookup_opt (unloc ps) env with
| None -> tc_lookup_error !!tc ~loc:ps.pl_loc `Operator (unloc ps)
| Some p -> fst p) ops
in
EcEnv.SimplifyContext.set_opacity
(List.map (fun p -> (p, opq)) ops) simpl)
simpl specs

(* -------------------------------------------------------------------- *)
let process_local_hint (hint : plocalhint) (tc : tcenv1) =
let env = FApi.tc1_env tc in
Expand Down Expand Up @@ -137,8 +152,13 @@ let process_local_hint (hint : plocalhint) (tc : tcenv1) =
in
(mode, List.rev ops))
in
hd |> Option.fold ~none:simpl ~some:(fun hd ->
EcEnv.SimplifyContext.set_default_hd (Some hd) simpl)
let simpl =
hd |> Option.fold ~none:simpl ~some:(fun hd ->
EcEnv.SimplifyContext.set_default_hd (Some hd) simpl)
in

(* reduction-opacity overrides ([-delta ops] / [+delta ops]) *)
apply_hint_opacity tc env h.ph_opacity simpl

| PLHClear base ->
EcEnv.SimplifyContext.clear ?base simpl
Expand Down Expand Up @@ -205,6 +225,9 @@ let process_simplify_info ri (tc : tcenv1) =
) simpl hint.ph_lemmas
in

(* Per-call reduction-opacity overrides ([-delta ops] / [+delta ops]). *)
let simpl = apply_hint_opacity tc env hint.ph_opacity simpl in

(* Database list consulted by this call: the unsigned selection if any
(else the proof-local default / active set), with the signed
activate / deactivate deltas applied in order. [None] when no [hint]
Expand Down
21 changes: 19 additions & 2 deletions src/ecLowGoal.ml
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,13 @@ let rec t_lazy_match ?(reduce = `Full) ?(texn = fun _ -> raise InvalidGoalShape)
| `None -> raise InvalidGoalShape
| `Full -> EcReduction.full_red
| `NoDelta -> EcReduction.nodelta in
(* honor proof-local [-delta op] opacity overrides without changing
which simplify databases the strategy consults *)
let strategy =
{ strategy with
EcReduction.user_local =
EcEnv.SimplifyContext.opacity_only
(FApi.tc1_simplify_context tc) } in
FApi.t_seq (FApi.t_or (t_hred_with_info strategy) texn) (t_lazy_match ~reduce tx) tc

(* -------------------------------------------------------------------- *)
Expand Down Expand Up @@ -2542,7 +2549,12 @@ let t_crush ?(delta = true) ?tsolve (tc : tcenv1) =
{ cs_undosubst = Sid.empty (*Sid.of_list (List.map fst (LDecl.tohyps (FApi.tc1_hyps tc)).h_local)*) ;
cs_sbeq = (* Sid.of_list (List.map fst (LDecl.tohyps (FApi.tc1_hyps tc)).h_local)*) Sid.empty;
} in
FApi.t_seq (entry state) (t_simplify_with_info EcReduction.nodelta) tc
let final =
{ EcReduction.nodelta with
EcReduction.user_local =
EcEnv.SimplifyContext.opacity_only
(FApi.tc1_simplify_context tc) } in
FApi.t_seq (entry state) (t_simplify_with_info final) tc


(* -------------------------------------------------------------------- *)
Expand Down Expand Up @@ -2914,6 +2926,11 @@ let t_crush_fwd ?(delta = true) nb_intros (tc : tcenv1) =
| _ -> t_fail tc
in

let final =
{ EcReduction.nodelta with
EcReduction.user_local =
EcEnv.SimplifyContext.opacity_only
(FApi.tc1_simplify_context tc) } in
FApi.t_seq
(aux0 nb_intros)
(t_simplify_with_info EcReduction.nodelta) tc
(t_simplify_with_info final) tc
4 changes: 3 additions & 1 deletion src/ecParser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,7 @@ simplify_hint_item:
| m=pmode x=lident { `Db (m = `Plus, unloc x) }
| m=pmode l=bracket(qoident+) { `Hd (m, l) }
| l=brace(qident+) { `Lemma l }
| m=pmode DELTA l=qoident+ { `Opacity (m = `Minus, l) }

(* The body of a [hint] clause: an unsigned base database selection
followed by items. A clause may not both select databases (unsigned
Expand All @@ -2568,6 +2569,7 @@ simplify_hint_body:
let m = match m with `Plus -> `Include | `Minus -> `Exclude in
{ h with ph_hd = Some (m, l) }
| `Lemma l -> { h with ph_lemmas = h.ph_lemmas @ l }
| `Opacity (b, l) -> { h with ph_opacity = h.ph_opacity @ [(b, l)] }
in
let h =
List.fold_left doit
Expand Down Expand Up @@ -3948,7 +3950,7 @@ realize:
(* Theory aliasing *)

theory_alias: (* FIXME: THEORY ALIAS -> S/R conflict *)
| THEORY name=uident EQ target=uqident { (name, target) }
| THEORY name=uident EQ targets=plist1(uqident, PLUS) { (name, targets) }

(* -------------------------------------------------------------------- *)
(* Printing *)
Expand Down
14 changes: 8 additions & 6 deletions src/ecParsetree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -575,14 +575,16 @@ type pmpred_args = (osymbol * pformula) list
[ph_lemmas] are lemmas added to the default DB for this call (lemma
sets are add-only -- the head filter restricts which rules apply). *)
type psimplify_hint = {
ph_select : symbol list;
ph_dbs : (bool * symbol) list;
ph_hd : ([`Include | `Exclude] * pqsymbol list) option;
ph_lemmas : pqsymbol list;
ph_select : symbol list;
ph_dbs : (bool * symbol) list;
ph_hd : ([`Include | `Exclude] * pqsymbol list) option;
ph_lemmas : pqsymbol list;
(* [-delta ops] / [+delta ops]: true = make reduction-opaque *)
ph_opacity : (bool * pqsymbol list) list;
}

let empty_simplify_hint = {
ph_select = []; ph_dbs = []; ph_hd = None; ph_lemmas = [];
ph_select = []; ph_dbs = []; ph_hd = None; ph_lemmas = []; ph_opacity = [];
}

(* -------------------------------------------------------------------- *)
Expand Down Expand Up @@ -1509,7 +1511,7 @@ type global_action =
| GthImport of pqsymbol list
| GthExport of pqsymbol list
| GthClone of theory_cloning
| GthAlias of (psymbol * pqsymbol)
| GthAlias of (psymbol * pqsymbol list)
| GModImport of pmsymbol located list
| GsctOpen of osymbol_r
| GsctClose of osymbol_r
Expand Down
Loading
Loading