diff --git a/Cargo.lock b/Cargo.lock
index adfc6b8021bc6..bb9652f475855 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -101,15 +101,6 @@ dependencies = [
"memchr",
]
-[[package]]
-name = "aho-corasick"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
-dependencies = [
- "memchr",
-]
-
[[package]]
name = "aliasable"
version = "0.1.3"
@@ -4466,6 +4457,16 @@ dependencies = [
"regex-automata",
]
+[[package]]
+name = "buf_redux"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
+dependencies = [
+ "memchr",
+ "safemem",
+]
+
[[package]]
name = "bumpalo"
version = "3.11.0"
@@ -5017,7 +5018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd"
dependencies = [
"cookie",
- "idna 0.2.3",
+ "idna",
"log",
"publicsuffix",
"serde 1.0.149",
@@ -6152,10 +6153,11 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
-version = "1.2.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
+ "matches",
"percent-encoding",
]
@@ -6167,9 +6169,9 @@ checksum = "85dcb89d2b10c5f6133de2efd8c11959ce9dbb46a2f7a4cab208c4eeda6ce1ab"
[[package]]
name = "fs_extra"
-version = "1.3.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
+checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
[[package]]
name = "funty"
@@ -6484,7 +6486,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
dependencies = [
- "aho-corasick 0.7.18",
+ "aho-corasick",
"bstr",
"fnv",
"log",
@@ -6806,9 +6808,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "httpmock"
-version = "0.6.7"
+version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6b56b6265f15908780cbee987912c1e98dbca675361f748291605a8a3a1df09"
+checksum = "c159c4fc205e6c1a9b325cb7ec135d13b5f47188ce175dabb76ec847f331d9bd"
dependencies = [
"assert-json-diff",
"async-object-pool",
@@ -6938,16 +6940,6 @@ dependencies = [
"unicode-normalization",
]
-[[package]]
-name = "idna"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
-dependencies = [
- "unicode-bidi",
- "unicode-normalization",
-]
-
[[package]]
name = "ignore"
version = "0.4.18"
@@ -7468,7 +7460,7 @@ dependencies = [
"petgraph 0.6.2",
"pico-args",
"regex",
- "regex-syntax 0.6.27",
+ "regex-syntax",
"string_cache",
"term",
"tiny-keccak",
@@ -7638,12 +7630,6 @@ dependencies = [
"winapi 0.3.9",
]
-[[package]]
-name = "libm"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
-
[[package]]
name = "libnghttp2-sys"
version = "0.1.7+1.45.0"
@@ -9006,9 +8992,9 @@ dependencies = [
[[package]]
name = "multer"
-version = "2.1.0"
+version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2"
+checksum = "a30ba6d97eb198c5e8a35d67d5779d6680cca35652a60ee90fc23dc431d4fde8"
dependencies = [
"bytes",
"encoding_rs",
@@ -9023,6 +9009,24 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "multipart"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182"
+dependencies = [
+ "buf_redux",
+ "httparse",
+ "log",
+ "mime",
+ "mime_guess",
+ "quick-error 1.2.3",
+ "rand 0.8.5",
+ "safemem",
+ "tempfile",
+ "twoway",
+]
+
[[package]]
name = "named-lock"
version = "0.2.0"
@@ -9257,7 +9261,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
- "libm",
]
[[package]]
@@ -9612,9 +9615,9 @@ dependencies = [
[[package]]
name = "percent-encoding"
-version = "2.3.0"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
@@ -10178,22 +10181,22 @@ dependencies = [
[[package]]
name = "proptest"
-version = "1.2.0"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65"
+checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5"
dependencies = [
"bit-set",
"bitflags 1.3.2",
"byteorder",
"lazy_static 1.4.0",
"num-traits 0.2.15",
+ "quick-error 2.0.1",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand_xorshift",
- "regex-syntax 0.6.27",
+ "regex-syntax",
"rusty-fork",
"tempfile",
- "unarray",
]
[[package]]
@@ -10268,7 +10271,7 @@ version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aeeedb0b429dc462f30ad27ef3de97058b060016f47790c066757be38ef792b4"
dependencies = [
- "idna 0.2.3",
+ "idna",
"psl-types",
]
@@ -10303,6 +10306,12 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+[[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
[[package]]
name = "quick-xml"
version = "0.22.0"
@@ -10595,13 +10604,13 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.8.4"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
- "aho-corasick 1.0.2",
+ "aho-corasick",
"memchr",
- "regex-syntax 0.7.2",
+ "regex-syntax",
]
[[package]]
@@ -10610,7 +10619,7 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
- "regex-syntax 0.6.27",
+ "regex-syntax",
]
[[package]]
@@ -10619,12 +10628,6 @@ version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
-[[package]]
-name = "regex-syntax"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
-
[[package]]
name = "remove_dir_all"
version = "0.5.3"
@@ -10956,7 +10959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
dependencies = [
"fnv",
- "quick-error",
+ "quick-error 1.2.3",
"tempfile",
"wait-timeout",
]
@@ -10967,6 +10970,12 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+[[package]]
+name = "safemem"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
+
[[package]]
name = "same-file"
version = "1.0.6"
@@ -11322,17 +11331,6 @@ dependencies = [
"digest 0.10.5",
]
-[[package]]
-name = "sha1"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest 0.10.5",
-]
-
[[package]]
name = "sha1_smol"
version = "1.0.0"
@@ -12132,9 +12130,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "1.26.0"
+version = "1.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
+checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
dependencies = [
"autocfg",
"bytes",
@@ -12148,7 +12146,7 @@ dependencies = [
"socket2",
"tokio-macros",
"tracing",
- "windows-sys 0.45.0",
+ "winapi 0.3.9",
]
[[package]]
@@ -12241,9 +12239,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
-version = "0.18.0"
+version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
+checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181"
dependencies = [
"futures-util",
"log",
@@ -12597,9 +12595,9 @@ dependencies = [
[[package]]
name = "tungstenite"
-version = "0.18.0"
+version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
+checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
dependencies = [
"base64 0.13.0",
"byteorder",
@@ -12608,12 +12606,21 @@ dependencies = [
"httparse",
"log",
"rand 0.8.5",
- "sha1",
+ "sha-1",
"thiserror",
"url",
"utf-8",
]
+[[package]]
+name = "twoway"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "typed-arena"
version = "2.0.2"
@@ -12666,12 +12673,6 @@ dependencies = [
"static_assertions",
]
-[[package]]
-name = "unarray"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
-
[[package]]
name = "uncased"
version = "0.9.7"
@@ -12742,9 +12743,9 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.13"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
@@ -12763,9 +12764,9 @@ dependencies = [
[[package]]
name = "unicode-normalization"
-version = "0.1.22"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
dependencies = [
"tinyvec",
]
@@ -12835,12 +12836,13 @@ dependencies = [
[[package]]
name = "url"
-version = "2.4.0"
+version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
"form_urlencoded",
- "idna 0.4.0",
+ "idna",
+ "matches",
"percent-encoding",
"serde 1.0.149",
]
@@ -12965,9 +12967,9 @@ dependencies = [
[[package]]
name = "warp"
-version = "0.3.5"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69"
+checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d"
dependencies = [
"bytes",
"futures-channel",
@@ -12978,10 +12980,10 @@ dependencies = [
"log",
"mime",
"mime_guess",
- "multer",
+ "multipart",
"percent-encoding",
"pin-project",
- "rustls-pemfile 1.0.1",
+ "rustls-pemfile 0.2.1",
"scoped-tls",
"serde 1.0.149",
"serde_json",
diff --git a/aptos-move/aptos-gas/src/aptos_framework.rs b/aptos-move/aptos-gas/src/aptos_framework.rs
index 478eef0ec8908..550f4e490d1ef 100644
--- a/aptos-move/aptos-gas/src/aptos_framework.rs
+++ b/aptos-move/aptos-gas/src/aptos_framework.rs
@@ -163,7 +163,10 @@ crate::natives::define_gas_parameters_for_natives!(GasParameters, "aptos_framewo
[.util.from_bytes.base, "util.from_bytes.base", 300 * MUL],
[.util.from_bytes.per_byte, "util.from_bytes.per_byte", 5 * MUL],
+ [.transaction_context.get_txn_hash.base, { 10.. => "transaction_context.get_txn_hash.base" }, 200 * MUL],
[.transaction_context.get_script_hash.base, "transaction_context.get_script_hash.base", 200 * MUL],
+ // Based on SHA3-256's cost
+ [.transaction_context.generate_unique_address.base, { 10.. => "transaction_context.generate_unique_address.base" }, 4000 * MUL],
[.code.request_publish.base, "code.request_publish.base", 500 * MUL],
[.code.request_publish.per_byte, "code.request_publish.per_byte", 2 * MUL],
diff --git a/aptos-move/aptos-gas/src/gas_meter.rs b/aptos-move/aptos-gas/src/gas_meter.rs
index 93438c868456d..f49754cf551b5 100644
--- a/aptos-move/aptos-gas/src/gas_meter.rs
+++ b/aptos-move/aptos-gas/src/gas_meter.rs
@@ -34,6 +34,7 @@ use std::collections::BTreeMap;
// Change log:
// - V10
+// - Added generate_unique_address and get_txn_hash native functions
// - Storage gas charges (excluding "storage fees") stop respecting the storage gas curves
// - V9
// - Accurate tracking of the cost of loading resource groups
diff --git a/aptos-move/aptos-vm/src/move_vm_ext/vm.rs b/aptos-move/aptos-vm/src/move_vm_ext/vm.rs
index c4e6df56eeabd..56e263b05544b 100644
--- a/aptos-move/aptos-vm/src/move_vm_ext/vm.rs
+++ b/aptos-move/aptos-vm/src/move_vm_ext/vm.rs
@@ -113,7 +113,11 @@ impl MoveVmExt {
_ => vec![],
};
- extensions.add(NativeTransactionContext::new(script_hash, self.chain_id));
+ extensions.add(NativeTransactionContext::new(
+ txn_hash.to_vec(),
+ script_hash,
+ self.chain_id,
+ ));
extensions.add(NativeCodeContext::default());
extensions.add(NativeStateStorageContext::new(remote));
diff --git a/aptos-move/aptos-vm/src/natives.rs b/aptos-move/aptos-vm/src/natives.rs
index eb4dfef998e23..4ee79f9a027dc 100644
--- a/aptos-move/aptos-vm/src/natives.rs
+++ b/aptos-move/aptos-vm/src/natives.rs
@@ -91,7 +91,11 @@ pub fn configure_for_unit_test() {
#[cfg(feature = "testing")]
fn unit_test_extensions_hook(exts: &mut NativeContextExtensions) {
exts.add(NativeCodeContext::default());
- exts.add(NativeTransactionContext::new(vec![1], ChainId::test().id())); // We use the testing environment chain ID here
+ exts.add(NativeTransactionContext::new(
+ vec![1],
+ vec![1],
+ ChainId::test().id(),
+ )); // We use the testing environment chain ID here
exts.add(NativeAggregatorContext::new(
[0; 32],
&*DUMMY_RESOLVER,
diff --git a/aptos-move/framework/aptos-framework/doc/object.md b/aptos-move/framework/aptos-framework/doc/object.md
index 99ceda65c242d..ec9e34f94b1bd 100644
--- a/aptos-move/framework/aptos-framework/doc/object.md
+++ b/aptos-move/framework/aptos-framework/doc/object.md
@@ -42,6 +42,7 @@ make it so that a reference to a global object can be returned from a function.
- [Function `convert`](#0x1_object_convert)
- [Function `create_named_object`](#0x1_object_create_named_object)
- [Function `create_user_derived_object`](#0x1_object_create_user_derived_object)
+- [Function `create_object`](#0x1_object_create_object)
- [Function `create_object_from_account`](#0x1_object_create_object_from_account)
- [Function `create_object_from_object`](#0x1_object_create_object_from_object)
- [Function `create_object_from_guid`](#0x1_object_create_object_from_guid)
@@ -87,6 +88,7 @@ make it so that a reference to a global object can be returned from a function.
use 0x1::guid;
use 0x1::hash;
use 0x1::signer;
+use 0x1::transaction_context;
use 0x1::vector;
@@ -227,8 +229,7 @@ This is a one time ability given to the creator to configure the object as neces
can_delete: bool
const DERIVE_AUID_ADDRESS_SCHEME: u8 = 251;
+
+
+
+
The object does not allow for deletion
@@ -828,16 +839,51 @@ Derivde objects, similar to named objects, cannot be deleted.
+
+
+
+
+## Function `create_object`
+
+Create a new object by generating a random unique address based on transaction hash.
+The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]).
+The created object is deletable as we can guarantee the same unique address can
+never be regenerated with future txs.
+
+
+public fun create_object(owner_address: address): object::ConstructorRef
+
+
+
+
+public fun create_object(owner_address: address): ConstructorRef {
+ let unique_address = transaction_context::generate_auid_address();
+ create_object_internal(owner_address, unique_address, true)
+}
+
+
+
+
create_object
instead.
Create a new object from a GUID generated by an account.
+As the GUID creation internally increments a counter, two transactions that executes
+create_object_from_account
function for the same creator run sequentially.
+Therefore, using create_object
method for creating objects is preferrable as it
+doesn't have the same bottlenecks.
-public fun create_object_from_account(creator: &signer): object::ConstructorRef
+#[deprecated]
+public fun create_object_from_account(creator: &signer): object::ConstructorRef
@@ -860,10 +906,16 @@ Create a new object from a GUID generated by an account.
## Function `create_object_from_object`
+Use create_object
instead.
Create a new object from a GUID generated by an object.
+As the GUID creation internally increments a counter, two transactions that executes
+create_object_from_object
function for the same creator run sequentially.
+Therefore, using create_object
method for creating objects is preferrable as it
+doesn't have the same bottlenecks.
-public fun create_object_from_object(creator: &signer): object::ConstructorRef
+#[deprecated]
+public fun create_object_from_object(creator: &signer): object::ConstructorRef
diff --git a/aptos-move/framework/aptos-framework/doc/staking_config.md b/aptos-move/framework/aptos-framework/doc/staking_config.md
index 92e77e132bfdf..d0f21450963a2 100644
--- a/aptos-move/framework/aptos-framework/doc/staking_config.md
+++ b/aptos-move/framework/aptos-framework/doc/staking_config.md
@@ -1191,7 +1191,8 @@ StakingRewardsConfig does not exist under the aptos_framework before creating it
-aborts_if !exists<StakingRewardsConfig>(@aptos_framework);
+pragma verify_duration_estimate = 120;
+aborts_if !exists<StakingRewardsConfig>(@aptos_framework);
aborts_if !features::spec_periodical_reward_rate_decrease_enabled();
include StakingRewardsConfigRequirement;
diff --git a/aptos-move/framework/aptos-framework/doc/transaction_context.md b/aptos-move/framework/aptos-framework/doc/transaction_context.md
index 981c01a44b618..791e456e810d3 100644
--- a/aptos-move/framework/aptos-framework/doc/transaction_context.md
+++ b/aptos-move/framework/aptos-framework/doc/transaction_context.md
@@ -5,15 +5,178 @@
+- [Struct `AUID`](#0x1_transaction_context_AUID)
+- [Constants](#@Constants_0)
+- [Function `get_txn_hash`](#0x1_transaction_context_get_txn_hash)
+- [Function `get_transaction_hash`](#0x1_transaction_context_get_transaction_hash)
+- [Function `generate_unique_address`](#0x1_transaction_context_generate_unique_address)
+- [Function `generate_auid_address`](#0x1_transaction_context_generate_auid_address)
- [Function `get_script_hash`](#0x1_transaction_context_get_script_hash)
-- [Specification](#@Specification_0)
- - [Function `get_script_hash`](#@Specification_0_get_script_hash)
+- [Function `generate_auid`](#0x1_transaction_context_generate_auid)
+- [Function `auid_address`](#0x1_transaction_context_auid_address)
+- [Specification](#@Specification_1)
+ - [Function `get_txn_hash`](#@Specification_1_get_txn_hash)
+ - [Function `generate_unique_address`](#@Specification_1_generate_unique_address)
+ - [Function `get_script_hash`](#@Specification_1_get_script_hash)
-
+use 0x1::features;
+
+
+
+
+
+
+## Struct `AUID`
+
+A wrapper denoting aptos unique identifer (AUID)
+for storing an address
+
+
+struct AUID has drop, store
+
+
+
+
+
+Fields
+
+
+
+-
+
unique_address: address
+
+-
+
+
+
+
+
+
+
+
+
+## Constants
+
+
+
+
+AUID feature is not supported.
+
+
+const EAUID_NOT_SUPPORTED: u64 = 1;
+
+
+
+
+
+
+## Function `get_txn_hash`
+
+Return the transaction hash of the current transaction.
+
+
+fun get_txn_hash(): vector<u8>
+
+
+
+
+
+Implementation
+
+
+native fun get_txn_hash(): vector<u8>;
+
+
+
+
+
+
+
+
+## Function `get_transaction_hash`
+
+Return the transaction hash of the current transaction.
+Internally calls the private function get_txn_hash
.
+This function is created for to feature gate the get_txn_hash
function.
+
+
+public fun get_transaction_hash(): vector<u8>
+
+
+
+
+
+Implementation
+
+
+public fun get_transaction_hash(): vector<u8> {
+ assert!(features::auids_enabled(), EAUID_NOT_SUPPORTED);
+ get_txn_hash()
+}
+
+
+
+
+
+
+
+
+## Function `generate_unique_address`
+
+Return a universally unique identifier (of type address) generated
+by hashing the transaction hash of this transaction and a sequence number
+specific to this transaction. This function can be called any
+number of times inside a single transaction. Each such call increments
+the sequence number and generates a new unique address.
+Uses Scheme in types/src/transaction/authenticator.rs for domain separation
+from other ways of generating unique addresses.
+
+
+fun generate_unique_address(): address
+
+
+
+
+
+Implementation
+
+
+native fun generate_unique_address(): address;
+
+
+
+
+
+
+
+
+## Function `generate_auid_address`
+Return a aptos unique identifier. Internally calls
+the private function generate_unique_address
. This function is
+created for to feature gate the generate_unique_address
function.
+public fun generate_auid_address(): address
+
+
+
+
+
+Implementation
+
+
+public fun generate_auid_address(): address {
+ assert!(features::auids_enabled(), EAUID_NOT_SUPPORTED);
+ generate_unique_address()
+}
+
+
+
+
+
+
## Function `get_script_hash`
@@ -37,12 +200,108 @@ Return the script hash of the current entry function.
-
+
+
+## Function `generate_auid`
+
+This method runs generate_unique_address
native function and returns
+the generated unique address wrapped in the AUID class.
+
+
+public fun generate_auid(): transaction_context::AUID
+
+
+
+
+
+Implementation
+
+
+public fun generate_auid(): AUID {
+ assert!(features::auids_enabled(), EAUID_NOT_SUPPORTED);
+ return AUID {
+ unique_address: generate_unique_address()
+ }
+}
+
+
+
+
+
+
+
+
+## Function `auid_address`
+
+
+
+public fun auid_address(auid: &transaction_context::AUID): address
+
+
+
+
+
+Implementation
+
+
+public fun auid_address(auid: &AUID): address {
+ auid.unique_address
+}
+
+
+
+
+
+
+
## Specification
-
+
+
+
+
+fun spec_get_txn_hash(): vector<u8>;
+
+
+
+
+
+
+### Function `get_txn_hash`
+
+
+fun get_txn_hash(): vector<u8>
+
+
+
+
+
+pragma opaque;
+aborts_if false;
+ensures result == spec_get_txn_hash();
+
+
+
+
+
+
+### Function `generate_unique_address`
+
+
+fun generate_unique_address(): address
+
+
+
+
+
+pragma opaque;
+
+
+
+
+
### Function `get_script_hash`
diff --git a/aptos-move/framework/aptos-framework/doc/transaction_validation.md b/aptos-move/framework/aptos-framework/doc/transaction_validation.md
index 44896c2d6c0ac..c9eb48546eebc 100644
--- a/aptos-move/framework/aptos-framework/doc/transaction_validation.md
+++ b/aptos-move/framework/aptos-framework/doc/transaction_validation.md
@@ -698,7 +698,8 @@ Aborts if length of public key hashed vector
not equal the number of singers.
-let gas_payer = if (txn_sequence_number < GAS_PAYER_FLAG_BIT) {
+pragma verify_duration_estimate = 120;
+let gas_payer = if (txn_sequence_number < GAS_PAYER_FLAG_BIT) {
signer::address_of(sender)
} else {
secondary_signer_addresses[len(secondary_signer_addresses) - 1]
diff --git a/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move b/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move
index f87769d4a89a9..1de8d344a2670 100644
--- a/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move
+++ b/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move
@@ -83,6 +83,7 @@ spec aptos_framework::staking_config {
}
spec calculate_and_save_latest_epoch_rewards_rate(): FixedPoint64 {
+ pragma verify_duration_estimate = 120;
aborts_if !exists(@aptos_framework);
aborts_if !features::spec_periodical_reward_rate_decrease_enabled();
include StakingRewardsConfigRequirement;
diff --git a/aptos-move/framework/aptos-framework/sources/object.move b/aptos-move/framework/aptos-framework/sources/object.move
index 2594feeafcc42..e8473d1ced55b 100644
--- a/aptos-move/framework/aptos-framework/sources/object.move
+++ b/aptos-move/framework/aptos-framework/sources/object.move
@@ -22,6 +22,7 @@ module aptos_framework::object {
use std::vector;
use aptos_framework::account;
+ use aptos_framework::transaction_context;
use aptos_framework::create_signer::create_signer;
use aptos_framework::event;
use aptos_framework::from_bcs;
@@ -51,6 +52,9 @@ module aptos_framework::object {
/// nesting, but any checks such as transfer will only be evaluated this deep.
const MAXIMUM_OBJECT_NESTING: u8 = 8;
+ /// generate_unique_address uses this for domain separation within its native implementation
+ const DERIVE_AUID_ADDRESS_SCHEME: u8 = 0xFB;
+
/// Scheme identifier used to generate an object's address `obj_addr` as derived from another object.
/// The object's address is generated as:
/// ```
@@ -108,8 +112,7 @@ module aptos_framework::object {
/// This is a one time ability given to the creator to configure the object as necessary
struct ConstructorRef has drop {
self: address,
- /// Set to true so long as deleting the object is possible. For example, the object was
- /// created via create_object_from_guid.
+ /// True if the object can be deleted. Named objects are not deletable.
can_delete: bool,
}
@@ -210,13 +213,34 @@ module aptos_framework::object {
create_object_internal(creator_address, obj_addr, false)
}
+ /// Create a new object by generating a random unique address based on transaction hash.
+ /// The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]).
+ /// The created object is deletable as we can guarantee the same unique address can
+ /// never be regenerated with future txs.
+ public fun create_object(owner_address: address): ConstructorRef {
+ let unique_address = transaction_context::generate_auid_address();
+ create_object_internal(owner_address, unique_address, true)
+ }
+
+ #[deprecated]
+ /// Use `create_object` instead.
/// Create a new object from a GUID generated by an account.
+ /// As the GUID creation internally increments a counter, two transactions that executes
+ /// `create_object_from_account` function for the same creator run sequentially.
+ /// Therefore, using `create_object` method for creating objects is preferrable as it
+ /// doesn't have the same bottlenecks.
public fun create_object_from_account(creator: &signer): ConstructorRef {
let guid = account::create_guid(creator);
create_object_from_guid(signer::address_of(creator), guid)
}
+ #[deprecated]
+ /// Use `create_object` instead.
/// Create a new object from a GUID generated by an object.
+ /// As the GUID creation internally increments a counter, two transactions that executes
+ /// `create_object_from_object` function for the same creator run sequentially.
+ /// Therefore, using `create_object` method for creating objects is preferrable as it
+ /// doesn't have the same bottlenecks.
public fun create_object_from_object(creator: &signer): ConstructorRef acquires ObjectCore {
let guid = create_guid(creator);
create_object_from_guid(signer::address_of(creator), guid)
@@ -650,4 +674,25 @@ module aptos_framework::object {
assert!(owner(hero) == @0x456, 0);
transfer_with_ref(linear_transfer_ref_bad, @0x789);
}
+
+ #[test(fx = @std)]
+ fun test_correct_auid(fx: signer) {
+ use std::features;
+ let feature = features::get_auids();
+ features::change_feature_flags(&fx, vector[feature], vector[]);
+
+ let auid1 = aptos_framework::transaction_context::generate_auid_address();
+ let bytes = aptos_framework::transaction_context::get_transaction_hash();
+ std::vector::push_back(&mut bytes, 1);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, 0);
+ std::vector::push_back(&mut bytes, DERIVE_AUID_ADDRESS_SCHEME);
+ let auid2 = aptos_framework::from_bcs::to_address(std::hash::sha3_256(bytes));
+ assert!(auid1 == auid2, 0);
+ }
}
diff --git a/aptos-move/framework/aptos-framework/sources/transaction_context.move b/aptos-move/framework/aptos-framework/sources/transaction_context.move
index 45a371148cae0..b515ed1e1f2fd 100644
--- a/aptos-move/framework/aptos-framework/sources/transaction_context.move
+++ b/aptos-move/framework/aptos-framework/sources/transaction_context.move
@@ -1,4 +1,83 @@
module aptos_framework::transaction_context {
+
+ use std::features;
+
+ /// AUID feature is not supported.
+ const EAUID_NOT_SUPPORTED: u64 = 1;
+
+ /// A wrapper denoting aptos unique identifer (AUID)
+ /// for storing an address
+ struct AUID has drop, store {
+ unique_address: address
+ }
+
+ /// Return the transaction hash of the current transaction.
+ native fun get_txn_hash(): vector;
+
+ /// Return the transaction hash of the current transaction.
+ /// Internally calls the private function `get_txn_hash`.
+ /// This function is created for to feature gate the `get_txn_hash` function.
+ public fun get_transaction_hash(): vector {
+ assert!(features::auids_enabled(), EAUID_NOT_SUPPORTED);
+ get_txn_hash()
+ }
+
+ /// Return a universally unique identifier (of type address) generated
+ /// by hashing the transaction hash of this transaction and a sequence number
+ /// specific to this transaction. This function can be called any
+ /// number of times inside a single transaction. Each such call increments
+ /// the sequence number and generates a new unique address.
+ /// Uses Scheme in types/src/transaction/authenticator.rs for domain separation
+ /// from other ways of generating unique addresses.
+ native fun generate_unique_address(): address;
+
+ /// Return a aptos unique identifier. Internally calls
+ /// the private function `generate_unique_address`. This function is
+ /// created for to feature gate the `generate_unique_address` function.
+ public fun generate_auid_address(): address {
+ assert!(features::auids_enabled(), EAUID_NOT_SUPPORTED);
+ generate_unique_address()
+ }
+
/// Return the script hash of the current entry function.
public native fun get_script_hash(): vector;
+
+ /// This method runs `generate_unique_address` native function and returns
+ /// the generated unique address wrapped in the AUID class.
+ public fun generate_auid(): AUID {
+ assert!(features::auids_enabled(), EAUID_NOT_SUPPORTED);
+ return AUID {
+ unique_address: generate_unique_address()
+ }
+ }
+
+ public fun auid_address(auid: &AUID): address {
+ auid.unique_address
+ }
+
+ #[test(fx = @std)]
+ fun test_auid_uniquess(fx: signer) {
+ use std::features;
+ use std::vector;
+
+ let feature = features::get_auids();
+ features::change_feature_flags(&fx, vector[feature], vector[]);
+
+ let auids: vector = vector[];
+ let i: u64 = 0;
+ let count: u64 = 50;
+ while (i < count) {
+ i = i + 1;
+ vector::push_back(&mut auids, generate_auid_address());
+ };
+ i = 0;
+ while (i < count - 1) {
+ let j: u64 = i + 1;
+ while (j < count) {
+ assert!(*vector::borrow(&auids, i) != *vector::borrow(&auids, j), 0);
+ j = j + 1;
+ };
+ i = i + 1;
+ };
+ }
}
diff --git a/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move b/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move
index 0b1c59ee1a897..5d520bf261e59 100644
--- a/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move
+++ b/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move
@@ -4,6 +4,14 @@ spec aptos_framework::transaction_context {
aborts_if false;
ensures result == spec_get_script_hash();
}
-
spec fun spec_get_script_hash(): vector;
+ spec get_txn_hash(): vector {
+ pragma opaque;
+ aborts_if false;
+ ensures result == spec_get_txn_hash();
+ }
+ spec fun spec_get_txn_hash(): vector;
+ spec generate_unique_address(): address {
+ pragma opaque;
+ }
}
diff --git a/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move b/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move
index b997af5fad0f4..a125f1d344b12 100644
--- a/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move
+++ b/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move
@@ -110,6 +110,7 @@ spec aptos_framework::transaction_validation {
txn_expiration_time: u64,
chain_id: u8,
) {
+ pragma verify_duration_estimate = 120;
let gas_payer = if (txn_sequence_number < GAS_PAYER_FLAG_BIT) {
signer::address_of(sender)
} else {
diff --git a/aptos-move/framework/aptos-token-objects/doc/aptos_token.md b/aptos-move/framework/aptos-token-objects/doc/aptos_token.md
index 54c8cc83e58fc..8414f43ddfb13 100644
--- a/aptos-move/framework/aptos-token-objects/doc/aptos_token.md
+++ b/aptos-move/framework/aptos-token-objects/doc/aptos_token.md
@@ -58,6 +58,7 @@ The key features are:
use 0x1::error;
+use 0x1::features;
use 0x1::object;
use 0x1::option;
use 0x1::signer;
@@ -471,14 +472,25 @@ With an existing collection, directly mint a soul bound token into the recipient
property_types: vector<String>,
property_values: vector<vector<u8>>,
): ConstructorRef acquires AptosCollection {
- let constructor_ref = token::create_from_account(
- creator,
- collection,
- description,
- name,
- option::none(),
- uri,
- );
+ let constructor_ref = if (features::auids_enabled()) {
+ token::create(
+ creator,
+ collection,
+ description,
+ name,
+ option::none(),
+ uri,
+ )
+ } else {
+ token::create_from_account(
+ creator,
+ collection,
+ description,
+ name,
+ option::none(),
+ uri,
+ )
+ };
let object_signer = object::generate_signer(&constructor_ref);
diff --git a/aptos-move/framework/aptos-token-objects/doc/token.md b/aptos-move/framework/aptos-token-objects/doc/token.md
index 0b23237681a04..391ae97000cbd 100644
--- a/aptos-move/framework/aptos-token-objects/doc/token.md
+++ b/aptos-move/framework/aptos-token-objects/doc/token.md
@@ -16,6 +16,7 @@ token are:
- [Struct `MutationEvent`](#0x4_token_MutationEvent)
- [Constants](#@Constants_0)
- [Function `create_common`](#0x4_token_create_common)
+- [Function `create`](#0x4_token_create)
- [Function `create_named_token`](#0x4_token_create_named_token)
- [Function `create_from_account`](#0x4_token_create_from_account)
- [Function `create_token_address`](#0x4_token_create_token_address)
@@ -361,6 +362,42 @@ The token name is over the maximum length
+
+
+
+
+## Function `create`
+
+Creates a new token object with a unique address and returns the ConstructorRef
+for additional specialization.
+
+
+public fun create(creator: &signer, collection_name: string::String, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
+
+
+
+
+
+Implementation
+
+
+public fun create(
+ creator: &signer,
+ collection_name: String,
+ description: String,
+ name: String,
+ royalty: Option<Royalty>,
+ uri: String,
+): ConstructorRef {
+ let creator_address = signer::address_of(creator);
+ let constructor_ref = object::create_object(creator_address);
+ create_common(&constructor_ref, creator_address, collection_name, description, name, royalty, uri);
+ constructor_ref
+}
+
+
+
+
@@ -409,7 +446,8 @@ Creates a new token object from an account GUID and returns the ConstructorRef f
additional specialization.
-public fun create_from_account(creator: &signer, collection_name: string::String, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
+#[deprecated]
+public fun create_from_account(creator: &signer, collection_name: string::String, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
diff --git a/aptos-move/framework/aptos-token-objects/sources/aptos_token.move b/aptos-move/framework/aptos-token-objects/sources/aptos_token.move
index 17c77fa3fe3b4..f20cd7b600025 100644
--- a/aptos-move/framework/aptos-token-objects/sources/aptos_token.move
+++ b/aptos-move/framework/aptos-token-objects/sources/aptos_token.move
@@ -8,6 +8,7 @@
/// * Metadata property type
module aptos_token_objects::aptos_token {
use std::error;
+ use std::features;
use std::option::{Self, Option};
use std::string::String;
use std::signer;
@@ -199,14 +200,25 @@ module aptos_token_objects::aptos_token {
property_types: vector,
property_values: vector>,
): ConstructorRef acquires AptosCollection {
- let constructor_ref = token::create_from_account(
- creator,
- collection,
- description,
- name,
- option::none(),
- uri,
- );
+ let constructor_ref = if (features::auids_enabled()) {
+ token::create(
+ creator,
+ collection,
+ description,
+ name,
+ option::none(),
+ uri,
+ )
+ } else {
+ token::create_from_account(
+ creator,
+ collection,
+ description,
+ name,
+ option::none(),
+ uri,
+ )
+ };
let object_signer = object::generate_signer(&constructor_ref);
diff --git a/aptos-move/framework/aptos-token-objects/sources/token.move b/aptos-move/framework/aptos-token-objects/sources/token.move
index 2867bc18c2822..06e9bdfe529f4 100644
--- a/aptos-move/framework/aptos-token-objects/sources/token.move
+++ b/aptos-move/framework/aptos-token-objects/sources/token.move
@@ -106,6 +106,22 @@ module aptos_token_objects::token {
};
}
+ /// Creates a new token object with a unique address and returns the ConstructorRef
+ /// for additional specialization.
+ public fun create(
+ creator: &signer,
+ collection_name: String,
+ description: String,
+ name: String,
+ royalty: Option,
+ uri: String,
+ ): ConstructorRef {
+ let creator_address = signer::address_of(creator);
+ let constructor_ref = object::create_object(creator_address);
+ create_common(&constructor_ref, creator_address, collection_name, description, name, royalty, uri);
+ constructor_ref
+ }
+
/// Creates a new token object from a token name and returns the ConstructorRef for
/// additional specialization.
public fun create_named_token(
@@ -124,6 +140,7 @@ module aptos_token_objects::token {
constructor_ref
}
+ #[deprecated]
/// Creates a new token object from an account GUID and returns the ConstructorRef for
/// additional specialization.
public fun create_from_account(
@@ -514,7 +531,7 @@ module aptos_token_objects::token {
}
#[test(creator = @0x123)]
- fun test_burn_and_delete(creator: &signer) acquires Token {
+ fun test_create_from_account_burn_and_delete(creator: &signer) acquires Token {
use aptos_framework::account;
let collection_name = string::utf8(b"collection name");
@@ -538,6 +555,35 @@ module aptos_token_objects::token {
assert!(!object::is_object(token_addr), 2);
}
+ #[test(creator = @0x123,fx = @std)]
+ fun test_create_burn_and_delete(creator: &signer, fx: signer) acquires Token {
+ use aptos_framework::account;
+ use std::features;
+
+ let feature = features::get_auids();
+ features::change_feature_flags(&fx, vector[feature], vector[]);
+
+ let collection_name = string::utf8(b"collection name");
+ let token_name = string::utf8(b"token name");
+
+ create_collection_helper(creator, collection_name, 1);
+ account::create_account_for_test(signer::address_of(creator));
+ let constructor_ref = create(
+ creator,
+ collection_name,
+ string::utf8(b"token description"),
+ token_name,
+ option::none(),
+ string::utf8(b"token uri"),
+ );
+ let burn_ref = generate_burn_ref(&constructor_ref);
+ let token_addr = object::address_from_constructor_ref(&constructor_ref);
+ assert!(exists(token_addr), 0);
+ burn(burn_ref);
+ assert!(!exists(token_addr), 1);
+ assert!(!object::is_object(token_addr), 2);
+ }
+
#[test_only]
fun create_collection_helper(creator: &signer, collection_name: String, max_supply: u64) {
collection::create_fixed_collection(
diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md
index d1c4ce9535541..a237205951252 100644
--- a/aptos-move/framework/move-stdlib/doc/features.md
+++ b/aptos-move/framework/move-stdlib/doc/features.md
@@ -62,6 +62,8 @@ return true.
- [Function `get_delegation_pool_partial_governance_voting`](#0x1_features_get_delegation_pool_partial_governance_voting)
- [Function `delegation_pool_partial_governance_voting_enabled`](#0x1_features_delegation_pool_partial_governance_voting_enabled)
- [Function `gas_payer_enabled`](#0x1_features_gas_payer_enabled)
+- [Function `get_auids`](#0x1_features_get_auids)
+- [Function `auids_enabled`](#0x1_features_auids_enabled)
- [Function `change_feature_flags`](#0x1_features_change_feature_flags)
- [Function `is_enabled`](#0x1_features_is_enabled)
- [Function `set`](#0x1_features_set)
@@ -127,6 +129,17 @@ Lifetime: transient
+
+
+Whether enable MOVE functions to call create_auid method to create AUIDs.
+Lifetime: transient
+
+
+const APTOS_UNIQUE_IDENTIFIERS: u64 = 23;
+
+
+
+
Whether the new BLAKE2B-256 hash function native is enabled.
@@ -1067,6 +1080,52 @@ Lifetime: transient
+
+
+
+
+## Function `get_auids`
+
+
+
+public fun get_auids(): u64
+
+
+
+
+
+Implementation
+
+
+public fun get_auids(): u64 { APTOS_UNIQUE_IDENTIFIERS }
+
+
+
+
+
+
+
+
+## Function `auids_enabled`
+
+
+
+public fun auids_enabled(): bool
+
+
+
+
+
+Implementation
+
+
+public fun auids_enabled(): bool acquires Features {
+ is_enabled(APTOS_UNIQUE_IDENTIFIERS)
+}
+
+
+
+
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move
index 1e96cfb53cd21..9f64c9ee8be45 100644
--- a/aptos-move/framework/move-stdlib/sources/configs/features.move
+++ b/aptos-move/framework/move-stdlib/sources/configs/features.move
@@ -201,6 +201,14 @@ module std::features {
is_enabled(GAS_PAYER_ENABLED)
}
+ /// Whether enable MOVE functions to call create_auid method to create AUIDs.
+ /// Lifetime: transient
+ const APTOS_UNIQUE_IDENTIFIERS: u64 = 23;
+ public fun get_auids(): u64 { APTOS_UNIQUE_IDENTIFIERS }
+ public fun auids_enabled(): bool acquires Features {
+ is_enabled(APTOS_UNIQUE_IDENTIFIERS)
+ }
+
// ============================================================================================
// Feature Flag Implementation
diff --git a/aptos-move/framework/src/natives/mod.rs b/aptos-move/framework/src/natives/mod.rs
index 2089364b927ca..177b1c0416870 100644
--- a/aptos-move/framework/src/natives/mod.rs
+++ b/aptos-move/framework/src/natives/mod.rs
@@ -226,7 +226,11 @@ impl GasParameters {
},
},
transaction_context: transaction_context::GasParameters {
+ get_txn_hash: transaction_context::GetTxnHashGasParameters { base: 0.into() },
get_script_hash: transaction_context::GetScriptHashGasParameters { base: 0.into() },
+ generate_unique_address: transaction_context::GenerateUniqueAddressGasParameters {
+ base: 0.into(),
+ },
},
code: code::GasParameters {
request_publish: code::RequestPublishGasParameters {
diff --git a/aptos-move/framework/src/natives/transaction_context.rs b/aptos-move/framework/src/natives/transaction_context.rs
index ca6f2d970e727..44afefa15e33d 100644
--- a/aptos-move/framework/src/natives/transaction_context.rs
+++ b/aptos-move/framework/src/natives/transaction_context.rs
@@ -2,9 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use crate::natives::helpers::{make_safe_native, SafeNativeContext, SafeNativeResult};
-use aptos_types::on_chain_config::{Features, TimedFeatures};
+use aptos_types::{
+ on_chain_config::{Features, TimedFeatures},
+ transaction::authenticator::{AuthenticationKey, AuthenticationKeyPreimage},
+};
use better_any::{Tid, TidAble};
-use move_core_types::gas_algebra::InternalGas;
+use move_core_types::{account_address::AccountAddress, gas_algebra::InternalGas};
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{loaded_data::runtime_types::Type, values::Value};
use smallvec::{smallvec, SmallVec};
@@ -15,6 +18,9 @@ use std::{collections::VecDeque, fmt::Debug, sync::Arc};
/// natives of this extension.
#[derive(Tid)]
pub struct NativeTransactionContext {
+ txn_hash: Vec,
+ /// This is the number of AUIDs (Aptos unique identifiers) issued during the execution of this transaction
+ auid_counter: u64,
script_hash: Vec,
chain_id: u8,
}
@@ -22,8 +28,10 @@ pub struct NativeTransactionContext {
impl NativeTransactionContext {
/// Create a new instance of a native transaction context. This must be passed in via an
/// extension into VM session functions.
- pub fn new(script_hash: Vec, chain_id: u8) -> Self {
+ pub fn new(txn_hash: Vec, script_hash: Vec, chain_id: u8) -> Self {
Self {
+ txn_hash,
+ auid_counter: 0,
script_hash,
chain_id,
}
@@ -34,6 +42,68 @@ impl NativeTransactionContext {
}
}
+/***************************************************************************************************
+ * native fun get_txn_hash
+ *
+ * gas cost: base_cost
+ *
+ **************************************************************************************************/
+#[derive(Clone, Debug)]
+pub struct GetTxnHashGasParameters {
+ pub base: InternalGas,
+}
+
+fn native_get_txn_hash(
+ gas_params: &GetTxnHashGasParameters,
+ context: &mut SafeNativeContext,
+ mut _ty_args: Vec,
+ _args: VecDeque,
+) -> SafeNativeResult> {
+ context.charge(gas_params.base)?;
+
+ let transaction_context = context.extensions().get::();
+
+ Ok(smallvec![Value::vector_u8(
+ transaction_context.txn_hash.clone()
+ )])
+}
+
+/***************************************************************************************************
+ * native fun generate_unique_address
+ *
+ * gas cost: base_cost
+ *
+ **************************************************************************************************/
+#[derive(Clone, Debug)]
+pub struct GenerateUniqueAddressGasParameters {
+ pub base: InternalGas,
+}
+
+fn native_generate_unique_address(
+ gas_params: &GenerateUniqueAddressGasParameters,
+ context: &mut SafeNativeContext,
+ mut _ty_args: Vec,
+ _args: VecDeque,
+) -> SafeNativeResult> {
+ context.charge(gas_params.base)?;
+
+ let mut transaction_context = context
+ .extensions_mut()
+ .get_mut::();
+ transaction_context.auid_counter += 1;
+
+ let hash_vec = AuthenticationKey::from_preimage(&AuthenticationKeyPreimage::auid(
+ transaction_context.txn_hash.clone(),
+ transaction_context.auid_counter,
+ ));
+ Ok(smallvec![Value::address(AccountAddress::new(
+ hash_vec
+ .to_vec()
+ .try_into()
+ .expect("Unable to convert hash vector into [u8]")
+ ))])
+}
+
/***************************************************************************************************
* native fun get_script_hash
*
@@ -66,7 +136,9 @@ fn native_get_script_hash(
**************************************************************************************************/
#[derive(Debug, Clone)]
pub struct GasParameters {
+ pub get_txn_hash: GetTxnHashGasParameters,
pub get_script_hash: GetScriptHashGasParameters,
+ pub generate_unique_address: GenerateUniqueAddressGasParameters,
}
pub fn make_all(
@@ -74,15 +146,35 @@ pub fn make_all(
timed_features: TimedFeatures,
features: Arc,
) -> impl Iterator- {
- let natives = [(
- "get_script_hash",
- make_safe_native(
- gas_params.get_script_hash,
- timed_features,
- features,
- native_get_script_hash,
+ let natives = [
+ (
+ "get_script_hash",
+ make_safe_native(
+ gas_params.get_script_hash,
+ timed_features.clone(),
+ features.clone(),
+ native_get_script_hash,
+ ),
+ ),
+ (
+ "generate_unique_address",
+ make_safe_native(
+ gas_params.generate_unique_address,
+ timed_features.clone(),
+ features.clone(),
+ native_generate_unique_address,
+ ),
+ ),
+ (
+ "get_txn_hash",
+ make_safe_native(
+ gas_params.get_txn_hash,
+ timed_features,
+ features,
+ native_get_txn_hash,
+ ),
),
- )];
+ ];
crate::natives::helpers::make_module_natives(natives)
}
diff --git a/types/src/transaction/authenticator.rs b/types/src/transaction/authenticator.rs
index b65343501eeb7..82203a9fe1ded 100644
--- a/types/src/transaction/authenticator.rs
+++ b/types/src/transaction/authenticator.rs
@@ -246,6 +246,7 @@ pub enum Scheme {
/// resources accounts. This application serves to domain separate hashes. Without such
/// separation, an adversary could create (and get a signer for) a these accounts
/// when a their address matches matches an existing address of a MultiEd25519 wallet.
+ DeriveAuid = 251,
DeriveObjectAddressFromObject = 252,
DeriveObjectAddressFromGuid = 253,
DeriveObjectAddressFromSeed = 254,
@@ -257,6 +258,7 @@ impl fmt::Display for Scheme {
let display = match self {
Scheme::Ed25519 => "Ed25519",
Scheme::MultiEd25519 => "MultiEd25519",
+ Scheme::DeriveAuid => "DeriveAuid",
Scheme::DeriveObjectAddressFromObject => "DeriveObjectAddressFromObject",
Scheme::DeriveObjectAddressFromGuid => "DeriveObjectAddressFromGuid",
Scheme::DeriveObjectAddressFromSeed => "DeriveObjectAddressFromSeed",
@@ -461,6 +463,15 @@ impl AuthenticationKeyPreimage {
Self::new(public_key.to_bytes(), Scheme::MultiEd25519)
}
+ /// Construct a preimage from a transaction-derived AUID as (txn_hash || auid_scheme_id)
+ pub fn auid(txn_hash: Vec
, auid_counter: u64) -> AuthenticationKeyPreimage {
+ let mut hash_arg = Vec::new();
+ hash_arg.extend(txn_hash);
+ hash_arg.extend(auid_counter.to_le_bytes().to_vec());
+ hash_arg.push(Scheme::DeriveAuid as u8);
+ Self(hash_arg)
+ }
+
/// Construct a vector from this authentication key
pub fn into_vec(self) -> Vec {
self.0