diff --git a/test/kontrol/lido-lemmas.k b/test/kontrol/lido-lemmas.k
index ec70db3f..5ec64a02 100644
--- a/test/kontrol/lido-lemmas.k
+++ b/test/kontrol/lido-lemmas.k
@@ -20,422 +20,28 @@ module LIDO-LEMMAS
// --------------------------------------
rule runLemma(T) => doneLemma(T) ...
- syntax Int ::= "ethMaxWidth" [macro]
- syntax Int ::= "ethUpperBound" [macro]
- // --------------------------------------
- rule ethMaxWidth => 96
- rule ethUpperBound => 2 ^Int ethMaxWidth
- // ----------------------------------------
-
- // chop and +Int
- rule [chop-plus]: chop (A +Int B) ==Int 0 => A ==Int (-1) *Int B
- requires #rangeUInt(256, A) andBool #rangeUInt(256, (-1) *Int B)
- [concrete(B), simplification, comm]
-
- // chop and -Int
- rule [chop-zero-minus]: chop (0 -Int A) ==Int B => A ==Int (pow256 -Int B) modInt pow256
- requires #rangeUInt(256, A) andBool #rangeUInt(256, B)
- [concrete(B), simplification, comm, preserves-definedness]
-
- // ==Int
- rule [int-eq-refl]: X ==Int X => true [simplification]
-
- // *Int
- rule A *Int B ==Int 0 => A ==Int 0 orBool B ==Int 0 [simplification]
-
- rule A *Int B => B *Int A [simplification(30), symbolic(A), concrete(B)]
-
- // /Int
- rule 0 /Int B => 0 requires B =/=Int 0 [simplification, preserves-definedness]
- rule A /Int B ==Int 0 => A ( A /Int C ) *Int B requires A modInt C ==Int 0 [simplification, concrete(A, C), preserves-definedness]
-
- // /Word
- rule _ /Word W1 => 0 requires W1 ==Int 0 [simplification]
- rule W0 /Word W1 => W0 /Int W1 requires W1 =/=Int 0 [simplification, preserves-definedness]
-
- // Further /Int and /Word arithmetic
- rule ( X *Int Y ) /Int Y => X requires Y =/=Int 0 [simplification, preserves-definedness]
- rule ( X *Int Y ) /Int X => Y requires X =/=Int 0 [simplification, preserves-definedness]
- rule ( X ==Int ( X *Int Y ) /Word Y ) orBool Y ==Int 0 => true [simplification, preserves-definedness]
- rule ( X ==Int ( Y *Int X ) /Word Y ) orBool Y ==Int 0 => true [simplification, preserves-definedness]
- rule ( 0 ==Int 0 /Word Y ) orBool Y ==Int 0 => true [simplification, preserves-definedness]
-
- rule A <=Int B /Int C => A *Int C <=Int B requires 0 (A +Int 1) *Int C <=Int B requires 0 Int B /Int C => A *Int C >Int B requires 0 =Int B /Int C => (A +Int 1) *Int C >Int B requires 0 =Int A => A *Int C <=Int B requires 0 Int A => (A +Int 1) *Int C <=Int B requires 0 A *Int C >Int B requires 0 (A +Int 1) *Int C >Int B requires 0 true
- requires C +Int D ==Int 0 [simplification, preserves-definedness]
-
- // modInt
- rule (X *Int Y) modInt Z => 0 requires X modInt Z ==Int 0 [simplification, concrete(X, Z), preserves-definedness]
-
- // Further generalization of: maxUIntXXX &Int #asWord ( BA )
- rule X &Int #asWord ( BA ) => #asWord ( #range(BA, lengthBytes(BA) -Int (log2Int(X +Int 1) /Int 8), log2Int(X +Int 1) /Int 8) )
- requires #rangeUInt(256, X)
- andBool X +Int 1 ==Int 2 ^Int log2Int(X +Int 1)
- andBool log2Int (X +Int 1) modInt 8 ==Int 0
- andBool (log2Int (X +Int 1)) /Int 8 <=Int lengthBytes(BA) andBool lengthBytes(BA) <=Int 32
- [simplification, concrete(X), preserves-definedness]
-
- // #asWord
- rule #asWord ( B1 +Bytes B2 ) => #asWord ( B2 )
- requires #asWord ( B1 ) ==Int 0
- [simplification, concrete(B1)]
-
- rule #asWord( BA ) >>Int N => #asWord( #range ( BA, 0, lengthBytes( BA ) -Int ( N /Int 8 ) ) )
- requires 0 <=Int N andBool N modInt 8 ==Int 0
- [simplification, concrete(N), preserves-definedness]
-
- // >>Int
- rule [shift-to-div]: X >>Int N => X /Int (2 ^Int N) [simplification(60), concrete(N)]
-
- // Boolean equality
- rule B ==K false => notBool B [simplification(30), comm]
- rule B ==K true => B [simplification(30), comm]
-
- // bool2Word
- rule bool2Word(X) ==Int 0 => notBool X [simplification(30), comm]
- rule bool2Word(X) =/=Int 0 => X [simplification(30), comm]
- rule bool2Word(X) ==Int 1 => X [simplification(30), comm]
- rule bool2Word(X) =/=Int 1 => notBool X [simplification(30), comm]
-
- rule [bool2Word-lt-true]: bool2Word(_:Bool) true requires 1 notBool B [simplification(30)]
- rule [bool2Word-gt-zero]: 0 B [simplification(30)]
- rule [bool2Word-gt-false]: X:Int false requires 1 true [simplification, smt-lemma]
- rule bool2Word(X) <=Int 1 => true [simplification, smt-lemma]
-
- //
- // .Bytes
- //
- rule .Bytes ==K b"" => true [simplification, comm]
-
- rule b"" ==K #buf(X, _) +Bytes _ => false requires 0 false requires 0 false requires 0 false requires 0 B:Bytes [simplification]
- rule [concat-neutral-right]: B:Bytes +Bytes b"" => B:Bytes [simplification]
-
- //
- // Alternative memory update
- //
- rule [memUpdate-concat-in-right]: (B1 +Bytes B2) [ S := B ] => B1 +Bytes (B2 [ S -Int lengthBytes(B1) := B ])
- requires lengthBytes(B1) <=Int S
- [simplification(40)]
-
- rule [memUpdate-concat-in-left]: (B1 +Bytes B2) [ S := B ] => (B1 [S := B]) +Bytes B2
- requires 0 <=Int S andBool S +Int lengthBytes(B) <=Int lengthBytes(B1)
- [simplification(45)]
-
- //
- // Equality of +Bytes
- //
- rule { B:Bytes #Equals B1:Bytes +Bytes B2:Bytes } =>
- { #range ( B, 0, lengthBytes(B1) ) #Equals B1 } #And
- { #range ( B, lengthBytes(B1), lengthBytes(B) -Int lengthBytes(B1) ) #Equals B2 }
- requires lengthBytes(B1) <=Int lengthBytes(B)
- [simplification(60), concrete(B, B1)]
-
- rule { B1:Bytes +Bytes B2:Bytes #Equals B } =>
- { #range ( B, 0, lengthBytes(B1) ) #Equals B1 } #And
- { #range ( B, lengthBytes(B1), lengthBytes(B) -Int lengthBytes(B1) ) #Equals B2 }
- requires lengthBytes(B1) <=Int lengthBytes(B)
- [simplification(60), concrete(B, B1)]
-
- rule { B:Bytes #Equals #buf( N, X:Int ) +Bytes B2:Bytes } =>
- { X #Equals #asWord ( #range ( B, 0, N ) ) } #And
- { #range ( B, N, lengthBytes(B) -Int N ) #Equals B2 }
- requires N <=Int lengthBytes(B)
- [simplification(60), concrete(B, N)]
-
- rule { #buf( N, X:Int ) +Bytes B2:Bytes #Equals B } =>
- { X #Equals #asWord ( #range ( B, 0, N ) ) } #And
- { #range ( B, N, lengthBytes(B) -Int N ) #Equals B2 }
- requires N <=Int lengthBytes(B)
- [simplification(60), concrete(B, N)]
-
- //
- // Specific simplifications
- //
- rule X &Int #asWord ( BA ) ==Int Y:Int => true
- requires 0 <=Int X andBool X false
- requires 0 <=Int X andBool X true
- requires 0 <=Int X andBool X false
- requires 0 <=Int X andBool X true
- requires 0 <=Int X andBool X false
- requires 0 <=Int X andBool X 0
- requires 0 <=Int X andBool 0 <=Int Y andBool 0 <=Int Z
- andBool X +Int 1 ==Int 2 ^Int log2Int(X +Int 1)
- andBool Y ==Int 2 ^Int log2Int(Y)
- andBool log2Int(X +Int 1) <=Int log2Int(Y)
- [simplification, concrete(X, Y), preserves-definedness]
-
- rule chop ( X *Int Y ) => X *Int Y
- requires 0 <=Int X andBool X X *Int Y { true #Equals X *Int Y C /Int A <=Int B
+ requires 0 <=Int C andBool 0 false
+ requires 0 <=Int A andBool B B <=Int A
+ [simplification, symbolic(A, B)]
+
+ rule ( ( A *Int B ) +Int C ) /Int D => ( ( ( A /Int 10 ) *Int B ) +Int ( ( D /Int 10 ) -Int 1 ) ) /Int ( D /Int 10 )
+ requires 0 <=Int A andBool 0 #asWord ( BA1 ) (A /Int 10) *Int B <=Int (C /Int 10) *Int D
- requires 0 <=Int A andBool 0 <=Int C andBool A modInt 10 ==Int 0 andBool C modInt 10 ==Int 0
- [simplification, concrete(A, C), preserves-definedness]
-
- rule [mul-cancel-10-lt]:
- A *Int B (A /Int 10) *Int B true requires X <=Int 0 andBool 0 <=Int A andBool 0 <=Int B [concrete(X), simplification, preserves-definedness]
- rule X <=Int A *Int B => true requires X <=Int 0 andBool 0 <=Int A andBool 0 <=Int B [concrete(X), simplification, preserves-definedness]
- rule X <=Int A /Int B => true requires X <=Int 0 andBool 0 <=Int A andBool 0 true requires X <=Int 0 andBool 0 true requires X <=Int 0 andBool 0 <=Int A andBool 0 true requires X <=Int 0 andBool 0 X +Int Y X +Int Y X *Int Y X *Int Y X /Int Y log2Int ( X &Int ( ( maxUInt256 xorInt X ) +Int 1 ) ) requires #rangeUInt(256, X) [concrete(X), simplification]
- rule #getFirstOneBit(X:Int) => -1 requires notBool #rangeUInt(256, X) [concrete(X), simplification]
-
- rule #getFirstZeroBit(X:Int) => #getFirstOneBit ( maxUInt256 xorInt X ) requires #rangeUInt(256, X) [concrete(X), simplification]
- rule #getFirstZeroBit(X:Int) => -1 requires notBool #rangeUInt(256, X) [concrete(X), simplification]
-
- syntax Int ::= #getMaskShiftBits(Int) [function, total]
- syntax Int ::= #getMaskShiftBytes(Int) [function, total]
-
- rule #getMaskShiftBits(X:Int) => #getFirstZeroBit(X) [concrete(X), simplification]
-
- rule #getMaskShiftBytes(X:Int) => #getFirstZeroBit(X) /Int 8 requires #getMaskShiftBits(X) modInt 8 ==Int 0 [concrete(X), simplification, preserves-definedness]
- rule #getMaskShiftBytes(X:Int) => -1 requires notBool ( #getMaskShiftBits(X) modInt 8 ==Int 0 ) [concrete(X), simplification, preserves-definedness]
-
- syntax Int ::= #getMaskWidthBits(Int) [function, total]
- syntax Int ::= #getMaskWidthBytes(Int) [function, total]
-
- rule #getMaskWidthBits(X:Int) => #getFirstOneBit(X >>Int #getMaskShiftBits(X:Int)) requires #rangeUInt(256, X) [concrete(X), simplification]
- rule #getMaskWidthBits(X:Int) => -1 requires notBool #rangeUInt(256, X) [concrete(X), simplification]
-
- rule #getMaskWidthBytes(X:Int) => #getMaskWidthBits(X) /Int 8 requires #getMaskWidthBits(X) modInt 8 ==Int 0 [concrete(X), simplification, preserves-definedness]
- rule #getMaskWidthBytes(X:Int) => -1 requires notBool ( #getMaskWidthBits(X) modInt 8 ==Int 0 ) [concrete(X), simplification, preserves-definedness]
-
- syntax Bool ::= #isMask(Int) [function, total]
-
- rule #isMask(X:Int) => maxUInt256 ==Int X |Int ( 2 ^Int ( #getMaskShiftBits(X) +Int #getMaskWidthBits(X) ) -Int 1 )
- requires 0 <=Int #getMaskShiftBytes(X) andBool 0 <=Int #getMaskWidthBytes(X)
- [concrete(X), simplification, preserves-definedness]
-
- rule #isMask(X:Int) => false
- requires notBool ( 0 <=Int #getMaskShiftBytes(X) andBool 0 <=Int #getMaskWidthBytes(X) )
- [concrete(X), simplification, preserves-definedness]
-
- // Actual masking lemmas
-
- // &Int masking
- rule MASK:Int &Int #asWord ( SLOT:Bytes ) =>
- #asWord ( ( #buf ( 32 -Int lengthBytes ( SLOT ), 0 ) +Bytes SLOT )
- [ 32 -Int ( #getMaskShiftBytes(MASK) +Int #getMaskWidthBytes(MASK) ) := #buf ( #getMaskWidthBytes(MASK), 0 ) ] )
- requires #rangeUInt(256, MASK) andBool lengthBytes(SLOT) <=Int 32
- andBool #isMask(MASK)
- [simplification, concrete(MASK), preserves-definedness]
-
- // |Int and +Bytes, into right
- rule [bor-concat-left]:
- A |Int #asWord ( B1 +Bytes B2 ) =>
- #asWord ( B1 +Bytes #buf ( lengthBytes(B2), A |Int #asWord ( B2 ) ) )
- requires 0 <=Int A andBool A
- #asWord ( #buf ( lengthBytes(B1), (A /Int (2 ^Int (8 *Int lengthBytes(B2)))) |Int #asWord ( B1 ) ) +Bytes B2 )
- requires #rangeUInt(256, A) andBool A modInt (2 ^Int (8 *Int lengthBytes(B2))) ==Int 0
- [simplification, preserves-definedness]
-
- // #buf and |Int
- rule [buf-bor-split-l]:
- #buf ( W, ( SHIFT *Int X ) |Int Y ) => #buf( W -Int ( log2Int(SHIFT) /Int 8 ), X ) +Bytes #buf( log2Int(SHIFT) /Int 8, Y)
- requires 0 <=Int W andBool W <=Int 32 andBool rangeUInt(256, SHIFT)
- andBool SHIFT ==Int 2 ^Int log2Int(SHIFT)
- andBool log2Int(SHIFT) modInt 8 ==Int 0
- andBool 0 <=Int X andBool X #buf(W -Int ( log2Int(SHIFT) /Int 8 ), X) +Bytes #buf(log2Int(SHIFT) /Int 8, Y)
- requires 0 <=Int W andBool W <=Int 32 andBool rangeUInt(256, SHIFT)
- andBool SHIFT ==Int 2 ^Int log2Int(SHIFT)
- andBool log2Int(SHIFT) modInt 8 ==Int 0
- andBool 0 <=Int X andBool X #buf( W -Int ( log2Int(SHIFT) /Int 8 ), X ) +Bytes #buf( log2Int(SHIFT) /Int 8, 0)
- requires 0 <=Int W andBool W <=Int 32 andBool rangeUInt(256, SHIFT)
- andBool SHIFT ==Int 2 ^Int log2Int(SHIFT)
- andBool log2Int(SHIFT) modInt 8 ==Int 0
- andBool 0 <=Int X andBool X #buf ( N -Int #getFirstOneBit(X) /Int 8, X /Int ( 2 ^Int ( 8 *Int ( #getFirstOneBit(X) /Int 8 ) ) ) ) +Bytes
- #buf ( #getFirstOneBit(X) /Int 8, Y )
- requires 0 <=Int N andBool N <=Int 32 andBool 0 <=Int #getFirstOneBit(X)
- andBool 0 <=Int Y andBool Y #buf ( N, X )
- requires 0 <=Int N andBool N <=Int 32
- andBool 0 <=Int X andBool X M:Map [ K1 <- V2 ] [simplification]
- rule M:Map [ K1 <- _ ] [ K2 <- V2 ] [ K1 <- V3 ] => M:Map [ K2 <- V2 ] [ K1 <- V3 ] [simplification]
- rule M:Map [ K1 <- _ ] [ K2 <- V2 ] [ K3 <- V3 ] [ K1 <- V4 ] => M:Map [ K2 <- V2 ] [ K3 <- V3 ] [ K1 <- V4 ] [simplification]
- rule M:Map [ K1 <- _ ] [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K1 <- V5 ] => M:Map [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K1 <- V5 ] [simplification]
- rule M:Map [ K1 <- _ ] [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K5 <- V5 ] [ K1 <- V6 ] => M:Map [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K5 <- V5 ] [ K1 <- V6 ] [simplification]
- rule M:Map [ K1 <- _ ] [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K5 <- V5 ] [ K6 <- V6 ] [ K1 <- V7 ] => M:Map [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K5 <- V5 ] [ K6 <- V6 ] [ K1 <- V7 ] [simplification]
- rule M:Map [ K1 <- _ ] [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K5 <- V5 ] [ K6 <- V6 ] [ K7 <- V7 ] [ K1 <- V8 ] => M:Map [ K2 <- V2 ] [ K3 <- V3 ] [ K4 <- V4 ] [ K5 <- V5 ] [ K6 <- V6 ] [ K7 <- V7 ] [ K1 <- V8 ] [simplification]
-
- //
- // keccak assumptions: these assumptions are not sound in principle, but are
- // required for verification - they should ideally be collected at the end of execution
- //
-
- rule 0 <=Int keccak( _ ) => true [simplification, smt-lemma]
- rule keccak( _ ) true [simplification, smt-lemma]
-
- // keccak does not equal a concrete value
- rule [keccak-eq-conc-false]: keccak(_A) ==Int _B => false [symbolic(_A), concrete(_B), simplification(30), comm]
- rule [keccak-neq-conc-true]: keccak(_A) =/=Int _B => true [symbolic(_A), concrete(_B), simplification(30), comm]
- rule [keccak-eq-conc-false-ml-lr]: { keccak(A) #Equals B } => { true #Equals keccak(A) ==Int B } [symbolic(A), concrete(B), simplification]
- rule [keccak-eq-conc-false-ml-rl]: { B #Equals keccak(A) } => { true #Equals keccak(A) ==Int B } [symbolic(A), concrete(B), simplification]
-
- // keccak is injective
- rule [keccak-inj]: keccak(A) ==Int keccak(B) => A ==K B [simplification]
- rule [keccak-inj-ml]: { keccak(A) #Equals keccak(B) } => { true #Equals A ==K B } [simplification]
-
- // chop of negative keccak
- rule chop (0 -Int keccak(BA)) => pow256 -Int keccak(BA)
- [simplification]
-
- // keccak cannot equal a number outside of its range
- rule { X #Equals keccak (_) } => #Bottom
- requires X =Int pow256
- [concrete(X), simplification]
-
- rule lengthBytes ( #padToWidth ( 32 , #asByteStack ( VALUE ) ) ) => 32
- requires #rangeUInt(256, VALUE)
- [simplification]
-
- rule chop ( X -Int Y ) => X -Int Y
- requires #rangeUInt(256, X)
- andBool #rangeUInt(256, Y)
- andBool Y <=Int X
- [simplification]
-
- rule X -Int Y <=Int Z => true
- requires X <=Int Z
- andBool 0 <=Int Y
- [simplification, smt-lemma]
-
- rule X modInt pow256 => X
- requires 0 <=Int X
- andBool X <=Int maxUInt128
- [simplification]
-
- rule X *Int Y true
- requires #rangeUInt(256, X)
- andBool #rangeUInt(256, Y)
- andBool #rangeUInt(256, Z)
- andBool X