Skip to content

Commit

Permalink
[Spec] Specs for math64, math128 and type_info (aptos-labs#5341)
Browse files Browse the repository at this point in the history
- Specified the `math64` and `math128` modules
- Updated the spec of `type_info`
  - `type_of` and `type_name` are natively supported by Prover now.
  - added a `[verify_only]` function to test the feature

TODO:
- the `pow` functions have non trivial loops, which still need abort-conditions and loop invariants.
  • Loading branch information
junkil-park authored Oct 28, 2022
1 parent 8958b01 commit 40ffbdf
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 32 deletions.
96 changes: 96 additions & 0 deletions aptos-move/framework/aptos-stdlib/doc/math128.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ Standard math utilities missing in the Move Language.
- [Function `min`](#0x1_math128_min)
- [Function `average`](#0x1_math128_average)
- [Function `pow`](#0x1_math128_pow)
- [Specification](#@Specification_0)
- [Function `max`](#@Specification_0_max)
- [Function `min`](#@Specification_0_min)
- [Function `average`](#@Specification_0_average)
- [Function `pow`](#@Specification_0_pow)


<pre><code></code></pre>
Expand Down Expand Up @@ -132,5 +137,96 @@ Return the value of n raised to power e

</details>

<a name="@Specification_0"></a>

## Specification


<a name="@Specification_0_max"></a>

### Function `max`


<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_max">max</a>(a: u128, b: u128): u128
</code></pre>




<pre><code><b>aborts_if</b> <b>false</b>;
<b>ensures</b> a &gt;= b ==&gt; result == a;
<b>ensures</b> a &lt; b ==&gt; result == b;
</code></pre>



<a name="@Specification_0_min"></a>

### Function `min`


<pre><code><b>public</b> <b>fun</b> <b>min</b>(a: u128, b: u128): u128
</code></pre>




<pre><code><b>aborts_if</b> <b>false</b>;
<b>ensures</b> a &lt; b ==&gt; result == a;
<b>ensures</b> a &gt;= b ==&gt; result == b;
</code></pre>



<a name="@Specification_0_average"></a>

### Function `average`


<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_average">average</a>(a: u128, b: u128): u128
</code></pre>




<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> <b>false</b>;
<b>ensures</b> result == (a + b) / 2;
</code></pre>



<a name="@Specification_0_pow"></a>

### Function `pow`


<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_pow">pow</a>(n: u128, e: u128): u128
</code></pre>




<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> [abstract] <a href="math128.md#0x1_math128_spec_pow">spec_pow</a>(n, e) &gt; MAX_U128;
<b>ensures</b> [abstract] result == <a href="math128.md#0x1_math128_spec_pow">spec_pow</a>(n, e);
</code></pre>




<a name="0x1_math128_spec_pow"></a>


<pre><code><b>fun</b> <a href="math128.md#0x1_math128_spec_pow">spec_pow</a>(e: u128, n: u128): u128 {
<b>if</b> (e == 0) {
1
}
<b>else</b> {
n * <a href="math128.md#0x1_math128_spec_pow">spec_pow</a>(n, e-1)
}
}
</code></pre>


[move-book]: https://move-language.github.io/move/introduction.html
73 changes: 73 additions & 0 deletions aptos-move/framework/aptos-stdlib/doc/math64.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ Standard math utilities missing in the Move Language.
- [Function `average`](#0x1_math64_average)
- [Function `pow`](#0x1_math64_pow)
- [Specification](#@Specification_0)
- [Function `max`](#@Specification_0_max)
- [Function `min`](#@Specification_0_min)
- [Function `average`](#@Specification_0_average)
- [Function `pow`](#@Specification_0_pow)


<pre><code></code></pre>
Expand Down Expand Up @@ -139,6 +142,42 @@ Return the value of n raised to power e
## Specification


<a name="@Specification_0_max"></a>

### Function `max`


<pre><code><b>public</b> <b>fun</b> <a href="math64.md#0x1_math64_max">max</a>(a: u64, b: u64): u64
</code></pre>




<pre><code><b>aborts_if</b> <b>false</b>;
<b>ensures</b> a &gt;= b ==&gt; result == a;
<b>ensures</b> a &lt; b ==&gt; result == b;
</code></pre>



<a name="@Specification_0_min"></a>

### Function `min`


<pre><code><b>public</b> <b>fun</b> <b>min</b>(a: u64, b: u64): u64
</code></pre>




<pre><code><b>aborts_if</b> <b>false</b>;
<b>ensures</b> a &lt; b ==&gt; result == a;
<b>ensures</b> a &gt;= b ==&gt; result == b;
</code></pre>



<a name="@Specification_0_average"></a>

### Function `average`
Expand All @@ -156,4 +195,38 @@ Return the value of n raised to power e
</code></pre>



<a name="@Specification_0_pow"></a>

### Function `pow`


<pre><code><b>public</b> <b>fun</b> <a href="math64.md#0x1_math64_pow">pow</a>(n: u64, e: u64): u64
</code></pre>




<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> [abstract] <a href="math64.md#0x1_math64_spec_pow">spec_pow</a>(n, e) &gt; MAX_U64;
<b>ensures</b> [abstract] result == <a href="math64.md#0x1_math64_spec_pow">spec_pow</a>(n, e);
</code></pre>




<a name="0x1_math64_spec_pow"></a>


<pre><code><b>fun</b> <a href="math64.md#0x1_math64_spec_pow">spec_pow</a>(e: u64, n: u64): u64 {
<b>if</b> (e == 0) {
1
}
<b>else</b> {
n * <a href="math64.md#0x1_math64_spec_pow">spec_pow</a>(n, e-1)
}
}
</code></pre>


[move-book]: https://move-language.github.io/move/introduction.html
58 changes: 43 additions & 15 deletions aptos-move/framework/aptos-stdlib/doc/type_info.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
- [Function `struct_name`](#0x1_type_info_struct_name)
- [Function `type_of`](#0x1_type_info_type_of)
- [Function `type_name`](#0x1_type_info_type_name)
- [Specification](#@Specification_0)
- [Function `type_of`](#@Specification_0_type_of)
- [Function `type_name`](#@Specification_0_type_name)
- [Function `verify_type_of`](#0x1_type_info_verify_type_of)
- [Function `verify_type_of_generic`](#0x1_type_info_verify_type_of_generic)


<pre><code><b>use</b> <a href="../../move-stdlib/doc/string.md#0x1_string">0x1::string</a>;
Expand Down Expand Up @@ -176,40 +175,69 @@

</details>

<a name="@Specification_0"></a>
<a name="0x1_type_info_verify_type_of"></a>

## Specification
## Function `verify_type_of`


<a name="@Specification_0_type_of"></a>

### Function `type_of`


<pre><code><b>public</b> <b>fun</b> <a href="type_info.md#0x1_type_info_type_of">type_of</a>&lt;T&gt;(): <a href="type_info.md#0x1_type_info_TypeInfo">type_info::TypeInfo</a>
<pre><code><b>fun</b> <a href="type_info.md#0x1_type_info_verify_type_of">verify_type_of</a>()
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>pragma</b> opaque;
<pre><code><b>fun</b> <a href="type_info.md#0x1_type_info_verify_type_of">verify_type_of</a>() {
<b>let</b> <a href="type_info.md#0x1_type_info">type_info</a> = <a href="type_info.md#0x1_type_info_type_of">type_of</a>&lt;<a href="type_info.md#0x1_type_info_TypeInfo">TypeInfo</a>&gt;();
<b>let</b> account_address = <a href="type_info.md#0x1_type_info_account_address">account_address</a>(&<a href="type_info.md#0x1_type_info">type_info</a>);
<b>let</b> module_name = <a href="type_info.md#0x1_type_info_module_name">module_name</a>(&<a href="type_info.md#0x1_type_info">type_info</a>);
<b>let</b> struct_name = <a href="type_info.md#0x1_type_info_struct_name">struct_name</a>(&<a href="type_info.md#0x1_type_info">type_info</a>);
<b>spec</b> {
<b>assert</b> account_address == @aptos_std;
<b>assert</b> module_name == b"<a href="type_info.md#0x1_type_info">type_info</a>";
<b>assert</b> struct_name == b"<a href="type_info.md#0x1_type_info_TypeInfo">TypeInfo</a>";
};
}
</code></pre>



<a name="@Specification_0_type_name"></a>
</details>

### Function `type_name`
<a name="0x1_type_info_verify_type_of_generic"></a>

## Function `verify_type_of_generic`

<pre><code><b>public</b> <b>fun</b> <a href="type_info.md#0x1_type_info_type_name">type_name</a>&lt;T&gt;(): <a href="../../move-stdlib/doc/string.md#0x1_string_String">string::String</a>


<pre><code><b>fun</b> <a href="type_info.md#0x1_type_info_verify_type_of_generic">verify_type_of_generic</a>&lt;T&gt;()
</code></pre>



<details>
<summary>Implementation</summary>

<pre><code><b>pragma</b> opaque;

<pre><code><b>fun</b> <a href="type_info.md#0x1_type_info_verify_type_of_generic">verify_type_of_generic</a>&lt;T&gt;() {
<b>let</b> <a href="type_info.md#0x1_type_info">type_info</a> = <a href="type_info.md#0x1_type_info_type_of">type_of</a>&lt;T&gt;();
<b>let</b> account_address = <a href="type_info.md#0x1_type_info_account_address">account_address</a>(&<a href="type_info.md#0x1_type_info">type_info</a>);
<b>let</b> module_name = <a href="type_info.md#0x1_type_info_module_name">module_name</a>(&<a href="type_info.md#0x1_type_info">type_info</a>);
<b>let</b> struct_name = <a href="type_info.md#0x1_type_info_struct_name">struct_name</a>(&<a href="type_info.md#0x1_type_info">type_info</a>);
<b>spec</b> {
<b>assert</b> account_address == <a href="type_info.md#0x1_type_info_type_of">type_of</a>&lt;T&gt;().account_address;
<b>assert</b> module_name == <a href="type_info.md#0x1_type_info_type_of">type_of</a>&lt;T&gt;().module_name;
<b>assert</b> struct_name == <a href="type_info.md#0x1_type_info_type_of">type_of</a>&lt;T&gt;().struct_name;
};
}
</code></pre>



</details>


[move-book]: https://move-language.github.io/move/introduction.html
36 changes: 36 additions & 0 deletions aptos-move/framework/aptos-stdlib/sources/math128.spec.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
spec aptos_std::math128 {

spec max(a: u128, b: u128): u128 {
aborts_if false;
ensures a >= b ==> result == a;
ensures a < b ==> result == b;
}

spec min(a: u128, b: u128): u128 {
aborts_if false;
ensures a < b ==> result == a;
ensures a >= b ==> result == b;
}

spec average(a: u128, b: u128): u128 {
pragma opaque;
aborts_if false;
ensures result == (a + b) / 2;
}

spec pow(n: u128, e: u128): u128 {
pragma opaque;
// TODO: verify the spec.
aborts_if [abstract] spec_pow(n, e) > MAX_U128;
ensures [abstract] result == spec_pow(n, e);
}

spec fun spec_pow(e: u128, n: u128): u128 {
if (e == 0) {
1
}
else {
n * spec_pow(n, e-1)
}
}
}
6 changes: 0 additions & 6 deletions aptos-move/framework/aptos-stdlib/sources/math64.move
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ module aptos_std::math64 {
}
}

spec average {
pragma opaque;
aborts_if false;
ensures result == (a + b) / 2;
}

/// Return the value of n raised to power e
public fun pow(n: u64, e: u64): u64 {
if (e == 0) {
Expand Down
36 changes: 36 additions & 0 deletions aptos-move/framework/aptos-stdlib/sources/math64.spec.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
spec aptos_std::math64 {

spec max(a: u64, b: u64): u64 {
aborts_if false;
ensures a >= b ==> result == a;
ensures a < b ==> result == b;
}

spec min(a: u64, b: u64): u64 {
aborts_if false;
ensures a < b ==> result == a;
ensures a >= b ==> result == b;
}

spec average(a: u64, b: u64): u64 {
pragma opaque;
aborts_if false;
ensures result == (a + b) / 2;
}

spec pow(n: u64, e: u64): u64 {
pragma opaque;
// TODO: verify the spec.
aborts_if [abstract] spec_pow(n, e) > MAX_U64;
ensures [abstract] result == spec_pow(n, e);
}

spec fun spec_pow(e: u64, n: u64): u64 {
if (e == 0) {
1
}
else {
n * spec_pow(n, e-1)
}
}
}
Loading

0 comments on commit 40ffbdf

Please sign in to comment.