Skip to content

Commit 75baf9b

Browse files
hjorthjortehildenb
andauthored
Wrc20 balance fixes (#310)
* Add #wrap rules corresponding to modInt Rules * Fix existential variable * More wrapping rules * WIP: Add speed-up lemma Causes infinite loop, it seems, not actually a speed up. Not worth investigating, I think, at least for now. * Clean up general lemmas * Start moving exact values in simplifications to side conditions * Simplify modInts to #wraps * Bugfix: missing syntax production * Make setRange total * New #getRange lemmas * Formatting * Remove the loop-lemma, not giving any speed-up * Formatting * Documentation update * Remove unused and bad lemma, caused branching * Nits * Update lemmas * Fix side condition * Remove commented out lemma * Specilalize #getRange lemma * Fix getRange side conditions for when WIDTH <= 0 * Typo in annotation Co-authored-by: ehildenb <[email protected]>
1 parent efffc53 commit 75baf9b

File tree

4 files changed

+79
-19
lines changed

4 files changed

+79
-19
lines changed

data.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -510,8 +510,8 @@ However, `ByteMap` is just a wrapper around regular `Map`s.
510510
`#setRange(BM, START, VAL, WIDTH)` writes the integer `I` to memory as bytes (little-endian), starting at index `N`.
511511

512512
```k
513-
syntax ByteMap ::= #setRange(ByteMap, Int, Int, Int) [function]
514-
// ---------------------------------------------------------------
513+
syntax ByteMap ::= #setRange(ByteMap, Int, Int, Int) [function, functional, smtlib(setRange)]
514+
// ---------------------------------------------------------------------------------------------
515515
rule #setRange(BM, _, _, WIDTH) => BM
516516
requires notBool (WIDTH >Int 0)
517517
rule #setRange(BM, IDX, VAL, WIDTH) => #setRange(#set(BM, IDX, VAL modInt 256), IDX +Int 1, VAL /Int 256, WIDTH -Int 1)

kwasm-lemmas.md

+52-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Not however that K defines `X modInt N ==Int X modInt (-N)`.
3434

3535
#### Rules for Expressions With Only Modulus
3636

37+
These are given in pure modulus form, and in form with `#wrap`, which is modulus with a power of 2 for positive `N`.
38+
3739
```k
3840
rule X modInt N => X
3941
requires 0 <=Int X
@@ -57,6 +59,10 @@ Not however that K defines `X modInt N ==Int X modInt (-N)`.
5759
requires M >Int 0
5860
andBool M <=Int N
5961
[simplification]
62+
63+
rule #wrap(N, #wrap(M, X)) => #wrap(M, X)
64+
requires M <=Int N
65+
[simplification]
6066
```
6167

6268
Proof:
@@ -71,6 +77,10 @@ Since 0 <= x mod m < m <= n, (x mod m) mod n = x mod m
7177
andBool N >Int 0
7278
andBool M modInt N ==Int 0
7379
[simplification]
80+
81+
rule #wrap(N, #wrap(M, X)) => #wrap(N, X)
82+
requires notBool (M <=Int N)
83+
[simplification]
7484
```
7585

7686
Proof:
@@ -101,12 +111,12 @@ x = m * q + r, for a unique q and r s.t. 0 <= r < m
101111
[simplification]
102112
103113
rule #wrap(N, (X <<Int M) +Int Y) => #wrap(N, Y)
104-
requires 0 <=Int N
114+
requires 0 <=Int M
105115
andBool N <=Int M
106116
[simplification]
107117
108118
rule #wrap(N, Y +Int (X <<Int M)) => #wrap(N, Y)
109-
requires 0 <=Int N
119+
requires 0 <=Int M
110120
andBool N <=Int M
111121
[simplification]
112122
```
@@ -130,6 +140,14 @@ x * m + y mod n = x * (k * n) + y mod n = y mod n
130140
andBool N >Int 0
131141
andBool M modInt N ==Int 0
132142
[simplification]
143+
144+
rule #wrap(N, #wrap(M, X) +Int Y) => #wrap(N, X +Int Y)
145+
requires N <=Int M
146+
[simplification]
147+
148+
rule #wrap(N, X +Int #wrap(M, Y)) => #wrap(N, X +Int Y)
149+
requires N <=Int M
150+
[simplification]
133151
```
134152

135153
Proof:
@@ -150,8 +168,12 @@ x mod m + y = r + y
150168
We want K to understand what a bit-shift is.
151169

152170
```k
153-
rule (X <<Int N) modInt M ==Int 0 => true
154-
requires M modInt (2 ^Int N) ==Int 0
171+
rule (X <<Int N) modInt M => 0
172+
requires (2 ^Int N) modInt M ==Int 0
173+
[simplification]
174+
175+
rule #wrap(M, X <<Int N) => 0
176+
requires M <=Int N
155177
[simplification]
156178
157179
rule (X >>Int N) => 0 requires X <Int 2 ^Int N [simplification]
@@ -324,8 +346,15 @@ They are non-trivial in their implementation, but the following should obviously
324346
requires WIDTH ==Int 1
325347
[simplification]
326348
327-
rule #getRange(BM, ADDR, WIDTH) modInt 256 => #get(BM, ADDR)
328-
requires notBool (WIDTH ==Int 0)
349+
rule #getRange(BM, ADDR, WIDTH) modInt BYTE_SIZE => #get(BM, ADDR)
350+
requires BYTE_SIZE ==Int 256
351+
andBool notBool (WIDTH <=Int 0)
352+
andBool #isByteMap(BM)
353+
[simplification]
354+
355+
rule #wrap(N, #getRange(BM, ADDR, WIDTH)) => #get(BM, ADDR)
356+
requires N ==Int 8
357+
andBool notBool (WIDTH <=Int 0)
329358
andBool #isByteMap(BM)
330359
[simplification]
331360
@@ -334,6 +363,23 @@ They are non-trivial in their implementation, but the following should obviously
334363
[simplification]
335364
```
336365

366+
`#getRange` over `#setRange`
367+
368+
```k
369+
rule #getRange(#setRange(BM, EA, VALUE, SET_WIDTH), EA, GET_WIDTH)
370+
=> #wrap(GET_WIDTH *Int 8, VALUE)
371+
requires GET_WIDTH <=Int SET_WIDTH
372+
[simplification]
373+
374+
rule #getRange(#setRange(BM, EA, VALUE, SET_WIDTH), EA, GET_WIDTH)
375+
=> #wrap(SET_WIDTH *Int 8, VALUE)
376+
requires (notBool GET_WIDTH <=Int SET_WIDTH)
377+
andBool #getRange(BM, EA +Int SET_WIDTH, GET_WIDTH -Int SET_WIDTH) ==Int 0
378+
[simplification]
379+
380+
rule #getRange(ByteMap <| .Map |>, _, _) => 0 [simplification]
381+
```
382+
337383
`#get` over `#setRange`.
338384

339385
```k

tests/proofs/wrc20-spec.k

-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ requires "wrc20.k"
55
module WRC20-SPEC
66
imports WRC20-LEMMAS
77

8-
// Main spec.
9-
// There is no specified behavior yet, so this claim is commented out.
10-
//
11-
// rule <k> #wrc20 </k>
12-
138
// Reverse bytes spec.
149

1510
rule <k> #wrc20ReverseBytes // TODO: Have this pre-loaded in the store.
@@ -44,7 +39,6 @@ module WRC20-SPEC
4439
requires notBool unnameFuncType(asFuncType(#wrc20ReverseBytesTypeDecls)) in values(TYPES)
4540
andBool ADDR +Int #numBytes(i64) <=Int SIZE *Int #pageSize()
4641
andBool #isByteMap(BM)
47-
// andBool #inUnsignedRange(i64, X) X is not bound in the LHS
4842
andBool #inUnsignedRange(i32, ADDR)
4943
ensures #get(BM, ADDR +Int 0) ==Int #get(?BM', ADDR +Int 7 )
5044
andBool #get(BM, ADDR +Int 1) ==Int #get(?BM', ADDR +Int 6 )

wrc20.md

+25-5
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,34 @@ module WRC20-LEMMAS [symbolic]
1414
imports KWASM-LEMMAS
1515
```
1616

17-
This conversion turns out to be helpful in this particular proof, but we don't want to apply it on all KWasm proofs.
17+
These conversions turns out to be helpful in this particular proof, but we don't want to apply it on all KWasm proofs.
1818

1919
```k
20-
rule X /Int 256 => X >>Int 8
20+
rule X /Int N => X >>Int 8 requires N ==Int 256 [simplification]
2121
```
2222

23-
TODO: The two `#get` theorems below theorems handle special cases in this proof, but we should be able to use some more general theorems to prove them.
23+
TODO: The `#get` theorems below theorems handle special cases in this proof, but we should be able to use some more general theorems to prove them.
2424

2525
```k
26-
rule (#get(BM, ADDR) +Int (X +Int Y)) modInt 256 => (#get(BM, ADDR) +Int ((X +Int Y) modInt 256)) modInt 256 [simplification]
27-
rule (#get(BM, ADDR) +Int X) >>Int 8 => X >>Int 8 requires X modInt 256 ==Int 0 andBool #isByteMap(BM) [simplification]
26+
rule (#get(BM, ADDR) +Int (X +Int Y)) modInt N => (#get(BM, ADDR) +Int ((X +Int Y) modInt 256)) modInt 256
27+
requires N ==Int 256
28+
[simplification]
29+
30+
rule #wrap(N, #get(BM, ADDR) +Int (X +Int Y)) => #wrap(8, #get(BM, ADDR) +Int #wrap(8, X +Int Y))
31+
requires N ==Int 8
32+
[simplification]
33+
34+
rule (#get(BM, ADDR) +Int X) >>Int N => X >>Int 8
35+
requires N ==Int 8
36+
andBool X modInt 256 ==Int 0
37+
andBool #isByteMap(BM)
38+
[simplification]
2839
```
2940

3041
TODO: The following theorems should be generalized and proven, and moved to the set of general lemmas.
3142
Perhaps using `requires N ==Int 2 ^Int log2Int(N)`?
43+
Also, some of these have concrete integers on the LHS.
44+
It may be better to use a symbolic value as a side condition, e.g. `rule N => foo requires N ==Int 8`, because simplifications rely on exact matching of the LHS.
3245

3346
```k
3447
rule X *Int 256 >>Int N => (X >>Int (N -Int 8)) requires N >=Int 8 [simplification]
@@ -54,6 +67,13 @@ Perhaps using `requires N ==Int 2 ^Int log2Int(N)`?
5467
andBool X <Int 256
5568
andBool M >=Int 8
5669
[simplification]
70+
71+
rule #wrap(N, (X +Int (Y <<Int M))) => X +Int (#wrap(N, Y <<Int M))
72+
requires N >=Int 8
73+
andBool 0 <=Int X
74+
andBool X <Int 256
75+
andBool M >=Int 8
76+
[simplification]
5777
```
5878

5979
TODO: The following theorem should be proven, and moved to the set of general lemmas.

0 commit comments

Comments
 (0)