diff --git a/aptos-move/framework/aptos-stdlib/doc/any.md b/aptos-move/framework/aptos-stdlib/doc/any.md index 1893839049b17..1f9e53191d6e6 100644 --- a/aptos-move/framework/aptos-stdlib/doc/any.md +++ b/aptos-move/framework/aptos-stdlib/doc/any.md @@ -10,6 +10,10 @@ - [Function `pack`](#0x1_any_pack) - [Function `unpack`](#0x1_any_unpack) - [Function `type_name`](#0x1_any_type_name) +- [Specification](#@Specification_1) + - [Function `pack`](#@Specification_1_pack) + - [Function `unpack`](#@Specification_1_unpack) + - [Function `type_name`](#@Specification_1_type_name)
use 0x1::bcs;
@@ -160,5 +164,64 @@ Returns the type name of this Any
+
+
+## Specification
+
+
+
+
+### Function `pack`
+
+
+public fun pack<T: drop, store>(x: T): any::Any
+
+
+
+
+
+aborts_if false;
+ensures result == Any {
+ type_name: type_info::type_name<T>(),
+ data: bcs::serialize<T>(x)
+};
+
+
+
+
+
+
+### Function `unpack`
+
+
+public fun unpack<T>(x: any::Any): T
+
+
+
+
+
+pragma aborts_if_is_partial;
+aborts_if type_info::type_name<T>() != x.type_name;
+aborts_if !from_bcs::deserializable<T>(x.data);
+ensures result == from_bcs::deserialize<T>(x.data);
+
+
+
+
+
+
+### Function `type_name`
+
+
+public fun type_name(x: &any::Any): &string::String
+
+
+
+
+
+aborts_if false;
+ensures result == x.type_name;
+
+
[move-book]: https://move-language.github.io/move/introduction.html
diff --git a/aptos-move/framework/aptos-stdlib/doc/copyable_any.md b/aptos-move/framework/aptos-stdlib/doc/copyable_any.md
index 6c1b583d5f91e..10787b97bd27a 100644
--- a/aptos-move/framework/aptos-stdlib/doc/copyable_any.md
+++ b/aptos-move/framework/aptos-stdlib/doc/copyable_any.md
@@ -10,6 +10,10 @@
- [Function `pack`](#0x1_copyable_any_pack)
- [Function `unpack`](#0x1_copyable_any_unpack)
- [Function `type_name`](#0x1_copyable_any_type_name)
+- [Specification](#@Specification_1)
+ - [Function `pack`](#@Specification_1_pack)
+ - [Function `unpack`](#@Specification_1_unpack)
+ - [Function `type_name`](#@Specification_1_type_name)
use 0x1::bcs;
@@ -150,5 +154,64 @@ Returns the type name of this Any
+
+
+## Specification
+
+
+
+
+### Function `pack`
+
+
+public fun pack<T: copy, drop, store>(x: T): copyable_any::Any
+
+
+
+
+
+aborts_if false;
+ensures result == Any {
+ type_name: type_info::type_name<T>(),
+ data: bcs::serialize<T>(x)
+};
+
+
+
+
+
+
+### Function `unpack`
+
+
+public fun unpack<T>(x: copyable_any::Any): T
+
+
+
+
+
+pragma aborts_if_is_partial;
+aborts_if type_info::type_name<T>() != x.type_name;
+aborts_if !from_bcs::deserializable<T>(x.data);
+ensures result == from_bcs::deserialize<T>(x.data);
+
+
+
+
+
+
+### Function `type_name`
+
+
+public fun type_name(x: ©able_any::Any): &string::String
+
+
+
+
+
+aborts_if false;
+ensures result == x.type_name;
+
+
[move-book]: https://move-language.github.io/move/introduction.html
diff --git a/aptos-move/framework/aptos-stdlib/doc/from_bcs.md b/aptos-move/framework/aptos-stdlib/doc/from_bcs.md
index 6ee7866e0eb45..5f5ee2191db6e 100644
--- a/aptos-move/framework/aptos-stdlib/doc/from_bcs.md
+++ b/aptos-move/framework/aptos-stdlib/doc/from_bcs.md
@@ -228,6 +228,17 @@ owned.
## Specification
+
+
+
+
+fun deserialize<T>(bytes: vector<u8>): T;
+
+fun deserializable<T>(bytes: vector<u8>): bool;
+
+
+
+
### Function `from_bytes`
@@ -240,6 +251,8 @@ owned.
pragma opaque;
+aborts_if !deserializable<T>(bytes);
+ensures result == deserialize<T>(bytes);
diff --git a/aptos-move/framework/aptos-stdlib/doc/type_info.md b/aptos-move/framework/aptos-stdlib/doc/type_info.md
index ab46f716682c5..34eaff24de6ea 100644
--- a/aptos-move/framework/aptos-stdlib/doc/type_info.md
+++ b/aptos-move/framework/aptos-stdlib/doc/type_info.md
@@ -19,6 +19,7 @@
- [Function `verify_type_of_generic`](#0x1_type_info_verify_type_of_generic)
- [Specification](#@Specification_1)
- [Function `chain_id_internal`](#@Specification_1_chain_id_internal)
+ - [Function `verify_type_of_generic`](#@Specification_1_verify_type_of_generic)
use 0x1::bcs;
@@ -364,6 +365,42 @@ analysis of vector size dynamism.
pragma opaque;
+aborts_if false;
+ensures result == spec_chain_id_internal();
+
+
+
+
+
+
+### Function `verify_type_of_generic`
+
+
+fun verify_type_of_generic<T>()
+
+
+
+
+
+aborts_if !spec_is_struct<T>();
+
+
+
+
+
+
+
+
+native fun spec_is_struct<T>(): bool;
+
+
+
+
+
+
+
+
+fun spec_chain_id_internal(): u8;
diff --git a/aptos-move/framework/aptos-stdlib/sources/any.spec.move b/aptos-move/framework/aptos-stdlib/sources/any.spec.move
index b921ec56b0d93..aa697260e7ca3 100644
--- a/aptos-move/framework/aptos-stdlib/sources/any.spec.move
+++ b/aptos-move/framework/aptos-stdlib/sources/any.spec.move
@@ -1 +1,29 @@
-spec aptos_std::any {}
+spec aptos_std::any {
+
+ // -----------------------
+ // Function specifications
+ // -----------------------
+
+ spec pack(x: T): Any {
+ use std::bcs;
+ aborts_if false;
+ ensures result == Any {
+ type_name: type_info::type_name(),
+ data: bcs::serialize(x)
+ };
+ }
+
+ spec unpack(x: Any): T {
+ use aptos_std::from_bcs;
+ // TODO: timeout without this.
+ pragma aborts_if_is_partial;
+ aborts_if type_info::type_name() != x.type_name;
+ aborts_if !from_bcs::deserializable(x.data);
+ ensures result == from_bcs::deserialize(x.data);
+ }
+
+ spec type_name(x: &Any): &String {
+ aborts_if false;
+ ensures result == x.type_name;
+ }
+}
diff --git a/aptos-move/framework/aptos-stdlib/sources/copyable_any.spec.move b/aptos-move/framework/aptos-stdlib/sources/copyable_any.spec.move
new file mode 100644
index 0000000000000..f8df857dffd12
--- /dev/null
+++ b/aptos-move/framework/aptos-stdlib/sources/copyable_any.spec.move
@@ -0,0 +1,29 @@
+spec aptos_std::copyable_any {
+
+ // -----------------------
+ // Function specifications
+ // -----------------------
+
+ spec pack(x: T): Any {
+ use std::bcs;
+ aborts_if false;
+ ensures result == Any {
+ type_name: type_info::type_name(),
+ data: bcs::serialize(x)
+ };
+ }
+
+ spec unpack(x: Any): T {
+ use aptos_std::from_bcs;
+ // TODO: timeout without this.
+ pragma aborts_if_is_partial;
+ aborts_if type_info::type_name() != x.type_name;
+ aborts_if !from_bcs::deserializable(x.data);
+ ensures result == from_bcs::deserialize(x.data);
+ }
+
+ spec type_name(x: &Any): &String {
+ aborts_if false;
+ ensures result == x.type_name;
+ }
+}
diff --git a/aptos-move/framework/aptos-stdlib/sources/from_bcs.spec.move b/aptos-move/framework/aptos-stdlib/sources/from_bcs.spec.move
index ed03b967dc5bf..28415ae9b7258 100644
--- a/aptos-move/framework/aptos-stdlib/sources/from_bcs.spec.move
+++ b/aptos-move/framework/aptos-stdlib/sources/from_bcs.spec.move
@@ -1,6 +1,37 @@
spec aptos_std::from_bcs {
- spec from_bytes {
- // TODO: temporary mockup.
+ // ----------------------------------
+ // Uninterpreted functions and axioms
+ // ----------------------------------
+ spec module {
+ // An uninterpreted function to represent the desrialization.
+ fun deserialize(bytes: vector): T;
+
+ // Checks if `bytes` is valid so that it can be deserialized into type T.
+ // This is modeled as an uninterpreted function.
+ fun deserializable(bytes: vector): bool;
+
+ // `deserialize` is an injective function.
+ // TODO: disabled due to the issue with generic axioms.
+ // axiom forall b1: vector, b2: vector:
+ // (deserialize(b1) == deserialize(b2) ==> b1 == b2);
+
+ // `deserialize` is an inverse function of `bcs::serialize`.
+ // TODO: disabled due to the issue with generic axioms.
+ // axiom forall v: T: deserialize(bcs::serialize(v)) == v;
+
+ // All serialized bytes are deserializable.
+ // TODO: disabled due to the issue with generic axioms.
+ // axiom forall v: T: deserializable(bcs::serialize(v));
+ }
+
+
+ // -----------------------
+ // Function specifications
+ // -----------------------
+
+ spec from_bytes(bytes: vector): T {
pragma opaque;
+ aborts_if !deserializable(bytes);
+ ensures result == deserialize(bytes);
}
}
diff --git a/aptos-move/framework/aptos-stdlib/sources/type_info.move b/aptos-move/framework/aptos-stdlib/sources/type_info.move
index 035206bcc70f9..c758476426b17 100644
--- a/aptos-move/framework/aptos-stdlib/sources/type_info.move
+++ b/aptos-move/framework/aptos-stdlib/sources/type_info.move
@@ -134,6 +134,9 @@ module aptos_std::type_info {
assert struct_name == type_of().struct_name;
};
}
+ spec verify_type_of_generic {
+ aborts_if !spec_is_struct();
+ }
#[test_only]
struct CustomType has drop {}
diff --git a/aptos-move/framework/aptos-stdlib/sources/type_info.spec.move b/aptos-move/framework/aptos-stdlib/sources/type_info.spec.move
index 880ad5fd1e652..f73b3f11e2595 100644
--- a/aptos-move/framework/aptos-stdlib/sources/type_info.spec.move
+++ b/aptos-move/framework/aptos-stdlib/sources/type_info.spec.move
@@ -1,8 +1,14 @@
spec aptos_std::type_info {
// Move Prover natively supports `type_of` and `type_name`.
- spec chain_id_internal {
- // TODO: temporary mockup.
+ spec native fun spec_is_struct(): bool;
+
+ // The chain ID is modeled as an uninterpreted function.
+ spec fun spec_chain_id_internal(): u8;
+
+ spec chain_id_internal(): u8 {
pragma opaque;
+ aborts_if false;
+ ensures result == spec_chain_id_internal();
}
}