diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a8818bec..517fd2847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## `2.0.0` + +### Contract changes + +* Updated `status-message-collections` to use `LookupMap` +* **BREAKING** Updated `fungible-token` implementation to use `LookupMap`. It changes storage layout. + +### API changes + +* Introduce `LookupMap` and `LookupSet` that are faster implementations of `UnorderedMap` and `UnorderedSet`, but without support for iterators. +Most read/lookup/write are done in 1 storage access instead of 2 or 3 for `Unordered*` implementations. +* **BREAKING** `Default` is removed from `near_sdk::collections` to avoid implicit state conflicts. +Collections should be initialized by explicitly specifying prefix using `new` method. +* **BREAKING** `TreeMap` implementation was updated to use `LookupMap`. +Previous `TreeMap` implementation was renamed to `LegacyTreeMap` and was deprecated. +It should only be used if the contract was already deployed and state has to be compatible with the previous implementation. + ## `1.0.1` ### Other changes diff --git a/Cargo.lock b/Cargo.lock index af75d60a2..5ba4a0a7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,7 +258,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -278,7 +278,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -288,7 +288,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", diff --git a/examples/cross-contract-high-level/Cargo.lock b/examples/cross-contract-high-level/Cargo.lock index 77f888e8e..433e4e056 100644 --- a/examples/cross-contract-high-level/Cargo.lock +++ b/examples/cross-contract-high-level/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -136,20 +136,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -159,9 +169,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -208,7 +218,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -223,7 +233,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -233,7 +243,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -281,9 +291,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -304,9 +314,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -319,42 +329,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -363,9 +373,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -375,9 +385,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/cross-contract-high-level/res/cross_contract_high_level.wasm b/examples/cross-contract-high-level/res/cross_contract_high_level.wasm index bb92ddc0a..ed2d550a3 100755 Binary files a/examples/cross-contract-high-level/res/cross_contract_high_level.wasm and b/examples/cross-contract-high-level/res/cross_contract_high_level.wasm differ diff --git a/examples/cross-contract-low-level/Cargo.lock b/examples/cross-contract-low-level/Cargo.lock index df555ef92..60252e4ad 100644 --- a/examples/cross-contract-low-level/Cargo.lock +++ b/examples/cross-contract-low-level/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -136,20 +136,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -159,9 +169,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -208,7 +218,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -223,7 +233,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -233,7 +243,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -281,9 +291,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -304,9 +314,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -319,42 +329,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -363,9 +373,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -375,9 +385,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/cross-contract-low-level/res/cross_contract_low_level.wasm b/examples/cross-contract-low-level/res/cross_contract_low_level.wasm index 6585401d0..34be9eb47 100755 Binary files a/examples/cross-contract-low-level/res/cross_contract_low_level.wasm and b/examples/cross-contract-low-level/res/cross_contract_low_level.wasm differ diff --git a/examples/fungible-token/Cargo.lock b/examples/fungible-token/Cargo.lock index 070f616d8..ba27d1aa9 100644 --- a/examples/fungible-token/Cargo.lock +++ b/examples/fungible-token/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -122,7 +122,7 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fungible-token" -version = "0.2.0" +version = "0.3.0" dependencies = [ "near-sdk", ] @@ -136,20 +136,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -159,9 +169,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.69" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -208,7 +218,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -223,7 +233,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -233,7 +243,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -281,9 +291,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -304,9 +314,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -319,42 +329,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.12" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.110" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.110" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -363,9 +373,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.53" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -375,9 +385,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.19" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -417,9 +427,9 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/fungible-token/Cargo.toml b/examples/fungible-token/Cargo.toml index 771258ac7..11c6dff36 100644 --- a/examples/fungible-token/Cargo.toml +++ b/examples/fungible-token/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fungible-token" -version = "0.2.0" +version = "0.3.0" authors = ["Near Inc "] edition = "2018" diff --git a/examples/fungible-token/README.md b/examples/fungible-token/README.md index a9c543b4b..216d78312 100644 --- a/examples/fungible-token/README.md +++ b/examples/fungible-token/README.md @@ -24,3 +24,12 @@ To test run: ```bash cargo test --package fungible-token -- --nocapture ``` + +## Changelog + +### `0.3.0` + +#### Breaking storage change + +- Switching `UnorderedMap` to `LookupMap`. It makes it cheaper and faster due to decreased storage access. + diff --git a/examples/fungible-token/res/fungible_token.wasm b/examples/fungible-token/res/fungible_token.wasm index 2e2da679e..c02a56696 100755 Binary files a/examples/fungible-token/res/fungible_token.wasm and b/examples/fungible-token/res/fungible_token.wasm differ diff --git a/examples/fungible-token/src/lib.rs b/examples/fungible-token/src/lib.rs index 69f8f7a4a..477b02425 100644 --- a/examples/fungible-token/src/lib.rs +++ b/examples/fungible-token/src/lib.rs @@ -16,7 +16,7 @@ * keys on its account. */ use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; -use near_sdk::collections::UnorderedMap; +use near_sdk::collections::LookupMap; use near_sdk::json_types::U128; use near_sdk::{env, near_bindgen, AccountId, Balance, Promise, StorageUsage}; @@ -34,22 +34,28 @@ pub struct Account { /// Escrow Account ID hash to the allowance amount. /// Allowance is the amount of tokens the Escrow Account ID can spent on behalf of the account /// owner. - pub allowances: UnorderedMap, Balance>, + pub allowances: LookupMap, Balance>, + /// The number of allowances + pub num_allowances: u32, } impl Account { /// Initializes a new Account with 0 balance and no allowances for a given `account_hash`. pub fn new(account_hash: Vec) -> Self { - Self { balance: 0, allowances: UnorderedMap::new(account_hash) } + Self { balance: 0, allowances: LookupMap::new(account_hash), num_allowances: 0 } } /// Sets allowance for account `escrow_account_id` to `allowance`. pub fn set_allowance(&mut self, escrow_account_id: &AccountId, allowance: Balance) { let escrow_hash = env::sha256(escrow_account_id.as_bytes()); if allowance > 0 { - self.allowances.insert(&escrow_hash, &allowance); + if self.allowances.insert(&escrow_hash, &allowance).is_none() { + self.num_allowances += 1; + } } else { - self.allowances.remove(&escrow_hash); + if self.allowances.remove(&escrow_hash).is_some() { + self.num_allowances -= 1; + } } } @@ -64,7 +70,7 @@ impl Account { #[derive(BorshDeserialize, BorshSerialize)] pub struct FungibleToken { /// sha256(AccountID) -> Account details. - pub accounts: UnorderedMap, Account>, + pub accounts: LookupMap, Account>, /// Total supply of the all token. pub total_supply: Balance, @@ -83,7 +89,7 @@ impl FungibleToken { pub fn new(owner_id: AccountId, total_supply: U128) -> Self { let total_supply = total_supply.into(); assert!(!env::state_exists(), "Already initialized"); - let mut ft = Self { accounts: UnorderedMap::new(b"a".to_vec()), total_supply }; + let mut ft = Self { accounts: LookupMap::new(b"a".to_vec()), total_supply }; let mut account = ft.get_account(&owner_id); account.balance = total_supply; ft.set_account(&owner_id, &account); @@ -238,7 +244,7 @@ impl FungibleToken { /// Helper method to set the account details for `owner_id` to the state. fn set_account(&mut self, owner_id: &AccountId, account: &Account) { let account_hash = env::sha256(owner_id.as_bytes()); - if account.balance > 0 || !account.allowances.is_empty() { + if account.balance > 0 || account.num_allowances > 0 { self.accounts.insert(&account_hash, &account); } else { self.accounts.remove(&account_hash); @@ -318,18 +324,6 @@ mod tests { assert_eq!(contract.get_balance(bob()).0, total_supply); } - #[test] - #[should_panic] - fn test_new_twice_fails() { - let context = get_context(carol()); - testing_env!(context); - let total_supply = 1_000_000_000_000_000u128; - { - let _contract = FungibleToken::new(bob(), total_supply.into()); - } - FungibleToken::new(bob(), total_supply.into()); - } - #[test] fn test_transfer() { let mut context = get_context(carol()); @@ -418,7 +412,7 @@ mod tests { #[test] #[should_panic( - expected = "The required attached deposit is 33100000000000000000000, but the given attached deposit is is 0" + expected = "The required attached deposit is 12400000000000000000000, but the given attached deposit is is 0" )] fn test_self_allowance_fail_no_deposit() { let mut context = get_context(carol()); diff --git a/examples/gas-fee-tester/Cargo.lock b/examples/gas-fee-tester/Cargo.lock index d33cb71c5..c3a4ab429 100644 --- a/examples/gas-fee-tester/Cargo.lock +++ b/examples/gas-fee-tester/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -136,20 +136,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -159,9 +169,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -208,7 +218,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -223,7 +233,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -233,7 +243,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -281,9 +291,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -304,9 +314,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -319,42 +329,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -363,9 +373,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -375,9 +385,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/gas-fee-tester/res/gas_fee_tester.wasm b/examples/gas-fee-tester/res/gas_fee_tester.wasm index d0ac8573b..da33aa6f2 100755 Binary files a/examples/gas-fee-tester/res/gas_fee_tester.wasm and b/examples/gas-fee-tester/res/gas_fee_tester.wasm differ diff --git a/examples/lockable-fungible-token/Cargo.lock b/examples/lockable-fungible-token/Cargo.lock index 271fc0ea5..47b56fdc2 100644 --- a/examples/lockable-fungible-token/Cargo.lock +++ b/examples/lockable-fungible-token/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -129,20 +129,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -152,9 +162,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "lockable-fungible-token" @@ -208,7 +218,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -223,7 +233,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -233,7 +243,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -281,9 +291,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -304,9 +314,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -319,42 +329,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -363,9 +373,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -375,9 +385,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/lockable-fungible-token/res/lockable_fungible_token.wasm b/examples/lockable-fungible-token/res/lockable_fungible_token.wasm index 234c499ca..c5a418614 100755 Binary files a/examples/lockable-fungible-token/res/lockable_fungible_token.wasm and b/examples/lockable-fungible-token/res/lockable_fungible_token.wasm differ diff --git a/examples/mission-control/Cargo.lock b/examples/mission-control/Cargo.lock index 2785a7da5..5221b01ff 100644 --- a/examples/mission-control/Cargo.lock +++ b/examples/mission-control/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -129,20 +129,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -152,9 +162,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -208,7 +218,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -223,7 +233,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -233,7 +243,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -281,9 +291,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -304,9 +314,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -319,42 +329,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -363,9 +373,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -375,9 +385,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/mission-control/res/mission_control.wasm b/examples/mission-control/res/mission_control.wasm index 385fb9730..d007bb96a 100755 Binary files a/examples/mission-control/res/mission_control.wasm and b/examples/mission-control/res/mission_control.wasm differ diff --git a/examples/status-message-collections/Cargo.lock b/examples/status-message-collections/Cargo.lock index 401b8e641..2d3fa4a68 100644 --- a/examples/status-message-collections/Cargo.lock +++ b/examples/status-message-collections/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -129,20 +129,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -152,9 +162,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -201,7 +211,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -216,7 +226,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -226,7 +236,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -274,9 +284,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -297,9 +307,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -312,42 +322,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -356,9 +366,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -368,9 +378,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/status-message-collections/res/status_message_collections.wasm b/examples/status-message-collections/res/status_message_collections.wasm index 23c95d0ba..e0ce61214 100755 Binary files a/examples/status-message-collections/res/status_message_collections.wasm and b/examples/status-message-collections/res/status_message_collections.wasm differ diff --git a/examples/status-message-collections/src/lib.rs b/examples/status-message-collections/src/lib.rs index 620977bff..013c973af 100644 --- a/examples/status-message-collections/src/lib.rs +++ b/examples/status-message-collections/src/lib.rs @@ -1,5 +1,5 @@ use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; -use near_sdk::collections::{UnorderedMap, UnorderedSet}; +use near_sdk::collections::{LookupMap, LookupSet}; use near_sdk::json_types::ValidAccountId; use near_sdk::{env, near_bindgen}; @@ -9,15 +9,15 @@ static ALLOC: near_sdk::wee_alloc::WeeAlloc<'_> = near_sdk::wee_alloc::WeeAlloc: #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct StatusMessage { - pub records: UnorderedMap, - pub unique_values: UnorderedSet, + pub records: LookupMap, + pub unique_values: LookupSet, } impl Default for StatusMessage { fn default() -> Self { Self { - records: UnorderedMap::new(b"r".to_vec()), - unique_values: UnorderedSet::new(b"s".to_vec()), + records: LookupMap::new(b"r".to_vec()), + unique_values: LookupSet::new(b"s".to_vec()), } } } diff --git a/examples/status-message/Cargo.lock b/examples/status-message/Cargo.lock index 977437dc9..983f2d545 100644 --- a/examples/status-message/Cargo.lock +++ b/examples/status-message/Cargo.lock @@ -8,9 +8,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -41,18 +41,18 @@ dependencies = [ [[package]] name = "borsh" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d42092adf8d207d987cb8d676f068305a80b3dd58487a06680e8586e7c4c25" +checksum = "30f3fd65922359a7c6e791bc9b2bba1b977ea0c0b96a528ac48007f535fb4184" dependencies = [ "borsh-derive", ] [[package]] name = "borsh-derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b5e5f545801db1290ea4f05c8af512db0805dade9b9af76798c5fc4a04164" +checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ae71ba613fe0b86556e910b053b040cb52b8c52c034370744f8760f176262" +checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de62f1b5fe76adc6510a4e7c3feb0172650f0088bbd5fead41c0c016db5c5ae" +checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ "proc-macro2", "quote", @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "byte-tools" @@ -129,20 +129,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg", +] + [[package]] name = "indexmap" -version = "1.3.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", + "hashbrown", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "keccak" @@ -152,9 +162,9 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "memory_units" @@ -201,7 +211,7 @@ dependencies = [ [[package]] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" dependencies = [ "base64", "borsh", @@ -216,7 +226,7 @@ dependencies = [ [[package]] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" dependencies = [ "Inflector", "proc-macro2", @@ -226,7 +236,7 @@ dependencies = [ [[package]] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" dependencies = [ "near-sdk-core", "proc-macro2", @@ -274,9 +284,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ "autocfg", "num-traits", @@ -297,9 +307,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", ] @@ -312,42 +322,42 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", @@ -356,9 +366,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "indexmap", "itoa", @@ -368,9 +378,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", @@ -400,9 +410,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", @@ -411,15 +421,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "wee_alloc" @@ -435,9 +445,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/examples/status-message/res/status_message.wasm b/examples/status-message/res/status_message.wasm index ab3b6b7e7..de1887c9f 100755 Binary files a/examples/status-message/res/status_message.wasm and b/examples/status-message/res/status_message.wasm differ diff --git a/near-sdk-core/Cargo.toml b/near-sdk-core/Cargo.toml index 49b62b708..4c71bfe97 100644 --- a/near-sdk-core/Cargo.toml +++ b/near-sdk-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "near-sdk-core" -version = "1.0.1" +version = "1.1.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" diff --git a/near-sdk-macros/Cargo.toml b/near-sdk-macros/Cargo.toml index 2073b9f97..45ebcab23 100644 --- a/near-sdk-macros/Cargo.toml +++ b/near-sdk-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "near-sdk-macros" -version = "1.0.1" +version = "1.1.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" @@ -15,7 +15,7 @@ Main macro of the library for writing NEAR smart contracts. proc-macro = true [dependencies] -near-sdk-core = { path = "../near-sdk-core", version = "1.0.1"} +near-sdk-core = { path = "../near-sdk-core", version = "1.1.0"} proc-macro2 = "1.0" syn = {version = "1.0.14", features = ["full", "fold", "visit"] } quote = "1.0" diff --git a/near-sdk/Cargo.toml b/near-sdk/Cargo.toml index 53a6d768a..ddd41b4b7 100644 --- a/near-sdk/Cargo.toml +++ b/near-sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "near-sdk" -version = "1.0.1" +version = "1.1.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" @@ -20,7 +20,7 @@ path = "compilation_tests/all.rs" # Provide near_bidgen macros. serde = { version = "1", features = ["derive"] } serde_json = "1" -near-sdk-macros = { path = "../near-sdk-macros", version = "1.0.1"} +near-sdk-macros = { path = "../near-sdk-macros", version = "1.1.0"} borsh = "0.7.0" bs58 = "0.3" base64 = "0.11" diff --git a/near-sdk/src/collections/legacy_tree_map.rs b/near-sdk/src/collections/legacy_tree_map.rs new file mode 100644 index 000000000..874fcfb53 --- /dev/null +++ b/near-sdk/src/collections/legacy_tree_map.rs @@ -0,0 +1,1769 @@ +//! Legacy `TreeMap` implementation that is using `UnorderedMap`. +//! DEPRECATED. This implementation is deprecated and may be removed in the future. + +use borsh::{BorshDeserialize, BorshSerialize}; +use std::ops::Bound; + +use crate::collections::UnorderedMap; +use crate::collections::{append, Vector}; + +/// TreeMap based on AVL-tree +/// +/// Runtime complexity (worst case): +/// - `get`/`contains_key`: O(1) - UnorderedMap lookup +/// - `insert`/`remove`: O(log(N)) +/// - `min`/`max`: O(log(N)) +/// - `above`/`below`: O(log(N)) +/// - `range` of K elements: O(Klog(N)) +/// +#[derive(BorshSerialize, BorshDeserialize)] +pub struct LegacyTreeMap { + root: u64, + val: UnorderedMap, + tree: Vector>, +} + +#[derive(Clone, BorshSerialize, BorshDeserialize)] +pub struct Node { + id: u64, + key: K, // key stored in a node + lft: Option, // left link of a node + rgt: Option, // right link of a node + ht: u64, // height of a subtree at a node +} + +impl Node +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, +{ + fn of(id: u64, key: K) -> Self { + Self { id, key, lft: None, rgt: None, ht: 1 } + } +} + +impl LegacyTreeMap +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, +{ + pub fn new(id: Vec) -> Self { + Self { + root: 0, + val: UnorderedMap::new(append(&id, b'v')), + tree: Vector::new(append(&id, b'n')), + } + } + + pub fn len(&self) -> u64 { + self.tree.len() as u64 + } + + pub fn clear(&mut self) { + self.root = 0; + self.val.clear(); + self.tree.clear(); + } + + fn node(&self, id: u64) -> Option> { + self.tree.get(id) + } + + fn save(&mut self, node: &Node) { + if node.id < self.len() { + self.tree.replace(node.id, node); + } else { + self.tree.push(node); + } + } + + pub fn contains_key(&self, key: &K) -> bool { + self.val.get(key).is_some() + } + + pub fn get(&self, key: &K) -> Option { + self.val.get(key) + } + + pub fn insert(&mut self, key: &K, val: &V) -> Option { + if !self.contains_key(&key) { + self.root = self.insert_at(self.root, self.len(), &key); + } + self.val.insert(&key, &val) + } + + pub fn remove(&mut self, key: &K) -> Option { + if self.contains_key(&key) { + self.root = self.do_remove(&key); + self.val.remove(&key) + } else { + // no such key, nothing to do + None + } + } + + /// Returns the smallest stored key from the tree + pub fn min(&self) -> Option { + self.min_at(self.root, self.root).map(|(n, _)| n.key) + } + + /// Returns the largest stored key from the tree + pub fn max(&self) -> Option { + self.max_at(self.root, self.root).map(|(n, _)| n.key) + } + + /// Returns the smallest key that is strictly greater than key given as the parameter + pub fn higher(&self, key: &K) -> Option { + self.above_at(self.root, key) + } + + /// Returns the largest key that is strictly less than key given as the parameter + pub fn lower(&self, key: &K) -> Option { + self.below_at(self.root, key) + } + + /// Returns the smallest key that is greater or equal to key given as the parameter + pub fn ceil_key(&self, key: &K) -> Option { + if self.contains_key(key) { + Some(key.clone()) + } else { + self.higher(key) + } + } + + /// Returns the largest key that is less or equal to key given as the parameter + pub fn floor_key(&self, key: &K) -> Option { + if self.contains_key(key) { + Some(key.clone()) + } else { + self.lower(key) + } + } + + /// Iterate all entries in ascending order: min to max, both inclusive + pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + Cursor::asc(&self).into_iter() + } + + /// Iterate entries in ascending order: given key (exclusive) to max (inclusive) + pub fn iter_from<'a>(&'a self, key: K) -> impl Iterator + 'a { + Cursor::asc_from(&self, key).into_iter() + } + + /// Iterate all entries in descending order: max to min, both inclusive + pub fn iter_rev<'a>(&'a self) -> impl Iterator + 'a { + Cursor::desc(&self).into_iter() + } + + /// Iterate entries in descending order: given key (exclusive) to min (inclusive) + pub fn iter_rev_from<'a>(&'a self, key: K) -> impl Iterator + 'a { + Cursor::desc_from(&self, key).into_iter() + } + + /// Iterate entries in ascending order according to specified bounds. + /// + /// # Panics + /// + /// Panics if range start > end. + /// Panics if range start == end and both bounds are Excluded. + pub fn range<'a>(&'a self, r: (Bound, Bound)) -> impl Iterator + 'a { + let (lo, hi) = match r { + (Bound::Included(a), Bound::Included(b)) if a > b => panic!("Invalid range."), + (Bound::Excluded(a), Bound::Included(b)) if a > b => panic!("Invalid range."), + (Bound::Included(a), Bound::Excluded(b)) if a > b => panic!("Invalid range."), + (Bound::Excluded(a), Bound::Excluded(b)) if a == b => panic!("Invalid range."), + (lo, hi) => (lo, hi), + }; + + Cursor::range(&self, lo, hi).into_iter() + } + + pub fn to_vec(&self) -> Vec<(K, V)> { + self.iter().collect() + } + + // + // Internal utilities + // + + /// Returns (node, parent node) of left-most lower (min) node starting from given node `at`. + /// As min_at only traverses the tree down, if a node `at` is the minimum node in a subtree, + /// its parent must be explicitly provided in advance. + fn min_at(&self, mut at: u64, p: u64) -> Option<(Node, Node)> { + let mut parent: Option> = self.node(p); + loop { + let node = self.node(at); + match node.clone().and_then(|n| n.lft) { + Some(lft) => { + at = lft; + parent = node; + } + None => { + return node.and_then(|n| parent.map(|p| (n, p))); + } + } + } + } + + /// Returns (node, parent node) of right-most lower (max) node starting from given node `at`. + /// As min_at only traverses the tree down, if a node `at` is the minimum node in a subtree, + /// its parent must be explicitly provided in advance. + fn max_at(&self, mut at: u64, p: u64) -> Option<(Node, Node)> { + let mut parent: Option> = self.node(p); + loop { + let node = self.node(at); + match node.clone().and_then(|n| n.rgt) { + Some(rgt) => { + parent = node; + at = rgt; + } + None => { + return node.and_then(|n| parent.map(|p| (n, p))); + } + } + } + } + + fn above_at(&self, mut at: u64, key: &K) -> Option { + let mut seen: Option = None; + loop { + let node = self.node(at); + match node.clone().map(|n| n.key) { + Some(k) => { + if k.le(key) { + match node.and_then(|n| n.rgt) { + Some(rgt) => at = rgt, + None => break, + } + } else { + seen = Some(k); + match node.and_then(|n| n.lft) { + Some(lft) => at = lft, + None => break, + } + } + } + None => break, + } + } + seen + } + + fn below_at(&self, mut at: u64, key: &K) -> Option { + let mut seen: Option = None; + loop { + let node = self.node(at); + match node.clone().map(|n| n.key) { + Some(k) => { + if k.lt(key) { + seen = Some(k); + match node.and_then(|n| n.rgt) { + Some(rgt) => at = rgt, + None => break, + } + } else { + match node.and_then(|n| n.lft) { + Some(lft) => at = lft, + None => break, + } + } + } + None => break, + } + } + seen + } + + fn insert_at(&mut self, at: u64, id: u64, key: &K) -> u64 { + match self.node(at) { + None => { + self.save(&Node::of(id, key.clone())); + at + } + Some(mut node) => { + if key.eq(&node.key) { + at + } else { + if key.lt(&node.key) { + let idx = match node.lft { + Some(lft) => self.insert_at(lft, id, key), + None => self.insert_at(id, id, key), + }; + node.lft = Some(idx); + } else { + let idx = match node.rgt { + Some(rgt) => self.insert_at(rgt, id, key), + None => self.insert_at(id, id, key), + }; + node.rgt = Some(idx); + }; + + self.update_height(&mut node); + self.enforce_balance(&mut node) + } + } + } + } + + // Calculate and save the height of a subtree at node `at`: + // height[at] = 1 + max(height[at.L], height[at.R]) + fn update_height(&mut self, node: &mut Node) { + let lft = node.lft.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); + let rgt = node.rgt.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); + + node.ht = 1 + std::cmp::max(lft, rgt); + self.save(&node); + } + + // Balance = difference in heights between left and right subtrees at given node. + fn get_balance(&self, node: &Node) -> i64 { + let lht = node.lft.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); + let rht = node.rgt.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); + + lht as i64 - rht as i64 + } + + // Left rotation of an AVL subtree with at node `at`. + // New root of subtree is returned, caller is responsible for updating proper link from parent. + fn rotate_left(&mut self, node: &mut Node) -> u64 { + let mut lft = node.lft.and_then(|id| self.node(id)).unwrap(); + let lft_rgt = lft.rgt; + + // at.L = at.L.R + node.lft = lft_rgt; + + // at.L.R = at + lft.rgt = Some(node.id); + + // at = at.L + self.update_height(node); + self.update_height(&mut lft); + + lft.id + } + + // Right rotation of an AVL subtree at node in `at`. + // New root of subtree is returned, caller is responsible for updating proper link from parent. + fn rotate_right(&mut self, node: &mut Node) -> u64 { + let mut rgt = node.rgt.and_then(|id| self.node(id)).unwrap(); + let rgt_lft = rgt.lft; + + // at.R = at.R.L + node.rgt = rgt_lft; + + // at.R.L = at + rgt.lft = Some(node.id); + + // at = at.R + self.update_height(node); + self.update_height(&mut rgt); + + rgt.id + } + + // Check balance at a given node and enforce it if necessary with respective rotations. + fn enforce_balance(&mut self, node: &mut Node) -> u64 { + let balance = self.get_balance(&node); + if balance > 1 { + let mut lft = node.lft.and_then(|id| self.node(id)).unwrap(); + if self.get_balance(&lft) < 0 { + let rotated = self.rotate_right(&mut lft); + node.lft = Some(rotated); + } + self.rotate_left(node) + } else if balance < -1 { + let mut rgt = node.rgt.and_then(|id| self.node(id)).unwrap(); + if self.get_balance(&rgt) > 0 { + let rotated = self.rotate_left(&mut rgt); + node.rgt = Some(rotated); + } + self.rotate_right(node) + } else { + node.id + } + } + + // Returns (node, parent node) for a node that holds the `key`. + // For root node, same node is returned for node and parent node. + fn lookup_at(&self, mut at: u64, key: &K) -> Option<(Node, Node)> { + let mut p: Node = self.node(at).unwrap(); + loop { + match self.node(at) { + Some(node) => { + if node.key.eq(key) { + return Some((node, p)); + } else if node.key.lt(key) { + match node.rgt { + Some(rgt) => { + p = node; + at = rgt; + } + None => break, + } + } else { + match node.lft { + Some(lft) => { + p = node; + at = lft; + } + None => break, + } + } + } + None => break, + } + } + None + } + + // Navigate from root to node holding `key` and backtrace back to the root + // enforcing balance (if necessary) along the way. + fn check_balance(&mut self, at: u64, key: &K) -> u64 { + match self.node(at) { + Some(mut node) => { + if node.key.eq(key) { + self.update_height(&mut node); + self.enforce_balance(&mut node) + } else { + if node.key.gt(key) { + match node.lft { + Some(l) => { + let id = self.check_balance(l, key); + node.lft = Some(id); + } + None => (), + } + } else { + match node.rgt { + Some(r) => { + let id = self.check_balance(r, key); + node.rgt = Some(id); + } + None => (), + } + } + self.update_height(&mut node); + self.enforce_balance(&mut node) + } + } + None => at, + } + } + + // Node holding the key is not removed from the tree - instead the substitute node is found, + // the key is copied to 'removed' node from substitute node, and then substitute node gets + // removed from the tree. + // + // The substitute node is either: + // - right-most (max) node of the left subtree (containing smaller keys) of node holding `key` + // - or left-most (min) node of the right subtree (containing larger keys) of node holding `key` + // + fn do_remove(&mut self, key: &K) -> u64 { + // r_node - node containing key of interest + // p_node - immediate parent node of r_node + let (mut r_node, mut p_node) = match self.lookup_at(self.root, key) { + Some(x) => x, + None => return self.root, // cannot remove a missing key, no changes to the tree needed + }; + + let lft_opt = r_node.lft; + let rgt_opt = r_node.rgt; + + if lft_opt.is_none() && rgt_opt.is_none() { + // remove leaf + if p_node.key.lt(key) { + p_node.rgt = None; + } else { + p_node.lft = None; + } + self.update_height(&mut p_node); + + self.swap_with_last(r_node.id); + + // removing node might have caused a imbalance - balance the tree up to the root, + // starting from lowest affected key - the parent of a leaf node in this case + self.check_balance(self.root, &p_node.key) + } else { + // non-leaf node, select subtree to proceed with + let b = self.get_balance(&r_node); + if b >= 0 { + // proceed with left subtree + let lft = lft_opt.unwrap(); + + // k - max key from left subtree + // n - node that holds key k, p - immediate parent of n + let (n, mut p) = self.max_at(lft, r_node.id).unwrap(); + let k = n.key.clone(); + + if p.rgt.clone().map(|id| id == n.id).unwrap_or_default() { + // n is on right link of p + p.rgt = n.lft; + } else { + // n is on left link of p + p.lft = n.lft; + } + + self.update_height(&mut p); + + if r_node.id == p.id { + // r_node.id and p.id can overlap on small trees (2 levels, 2-3 nodes) + // that leads to nasty lost update of the key, refresh below fixes that + r_node = self.node(r_node.id).unwrap(); + } + r_node.key = k; + self.save(&r_node); + + self.swap_with_last(n.id); + + // removing node might have caused an imbalance - balance the tree up to the root, + // starting from the lowest affected key (max key from left subtree in this case) + self.check_balance(self.root, &p.key) + } else { + // proceed with right subtree + let rgt = rgt_opt.unwrap(); + + // k - min key from right subtree + // n - node that holds key k, p - immediate parent of n + let (n, mut p) = self.min_at(rgt, r_node.id).unwrap(); + let k = n.key.clone(); + + if p.lft.map(|id| id == n.id).unwrap_or_default() { + // n is on left link of p + p.lft = n.rgt; + } else { + // n is on right link of p + p.rgt = n.rgt; + } + + self.update_height(&mut p); + + if r_node.id == p.id { + // r_node.id and p.id can overlap on small trees (2 levels, 2-3 nodes) + // that leads to nasty lost update of the key, refresh below fixes that + r_node = self.node(r_node.id).unwrap(); + } + r_node.key = k; + self.save(&r_node); + + self.swap_with_last(n.id); + + // removing node might have caused a imbalance - balance the tree up to the root, + // starting from the lowest affected key (min key from right subtree in this case) + self.check_balance(self.root, &p.key) + } + } + } + + // Move content of node with id = `len - 1` (parent left or right link, left, right, key, height) + // to node with given `id`, and remove node `len - 1` (pop the vector of nodes). + // This ensures that among `n` nodes in the tree, max `id` is `n-1`, so when new node is inserted, + // it gets an `id` as its position in the vector. + fn swap_with_last(&mut self, id: u64) { + if id == self.len() - 1 { + // noop: id is already last element in the vector + self.tree.pop(); + return; + } + + let key = self.node(self.len() - 1).map(|n| n.key).unwrap(); + let (mut n, mut p) = self.lookup_at(self.root, &key).unwrap(); + + if n.id != p.id { + if p.lft.map(|id| id == n.id).unwrap_or_default() { + p.lft = Some(id); + } else { + p.rgt = Some(id); + } + self.save(&p); + } + + if self.root == n.id { + self.root = id; + } + + n.id = id; + self.save(&n); + self.tree.pop(); + } +} + +impl<'a, K, V> IntoIterator for &'a LegacyTreeMap +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, +{ + type Item = (K, V); + type IntoIter = Cursor<'a, K, V>; + + fn into_iter(self) -> Self::IntoIter { + Cursor::asc(self) + } +} + +impl Iterator for Cursor<'_, K, V> +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, +{ + type Item = (K, V); + + fn next(&mut self) -> Option { + let this_key = self.key.clone(); + + let next_key = self + .key + .take() + .and_then(|k| if self.asc { self.map.higher(&k) } else { self.map.lower(&k) }) + .filter(|k| fits(k, &self.lo, &self.hi)); + self.key = next_key; + + this_key.and_then(|k| self.map.get(&k).map(|v| (k, v))) + } +} + +fn fits(key: &K, lo: &Bound, hi: &Bound) -> bool { + (match lo { + Bound::Included(ref x) => key >= x, + Bound::Excluded(ref x) => key > x, + Bound::Unbounded => true, + }) && (match hi { + Bound::Included(ref x) => key <= x, + Bound::Excluded(ref x) => key < x, + Bound::Unbounded => true, + }) +} + +pub struct Cursor<'a, K, V> { + asc: bool, + lo: Bound, + hi: Bound, + key: Option, + map: &'a LegacyTreeMap, +} + +impl<'a, K, V> Cursor<'a, K, V> +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, +{ + fn asc(map: &'a LegacyTreeMap) -> Self { + let key: Option = map.min(); + Self { asc: true, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } + } + + fn asc_from(map: &'a LegacyTreeMap, key: K) -> Self { + let key = map.higher(&key); + Self { asc: true, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } + } + + fn desc(map: &'a LegacyTreeMap) -> Self { + let key: Option = map.max(); + Self { asc: false, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } + } + + fn desc_from(map: &'a LegacyTreeMap, key: K) -> Self { + let key = map.lower(&key); + Self { asc: false, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } + } + + fn range(map: &'a LegacyTreeMap, lo: Bound, hi: Bound) -> Self { + let key = match &lo { + Bound::Included(k) if map.contains_key(k) => Some(k.clone()), + Bound::Included(k) | Bound::Excluded(k) => map.higher(k), + _ => None, + }; + let key = key.filter(|k| fits(k, &lo, &hi)); + + Self { asc: true, key, lo, hi, map } + } +} + +#[cfg(not(target_arch = "wasm32"))] +#[cfg(test)] +mod tests { + use super::*; + use crate::test_utils::test_env::{self, next_trie_id}; + + extern crate rand; + use self::rand::RngCore; + use quickcheck::QuickCheck; + use serde::export::Formatter; + use std::collections::BTreeMap; + use std::collections::HashSet; + use std::fmt::{Debug, Result}; + + /// Return height of the tree - number of nodes on the longest path starting from the root node. + fn height(tree: &LegacyTreeMap) -> u64 + where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, + { + tree.node(tree.root).map(|n| n.ht).unwrap_or_default() + } + + fn random(n: u64) -> Vec { + let mut rng = rand::thread_rng(); + let mut vec = Vec::with_capacity(n as usize); + (0..n).for_each(|_| { + vec.push(rng.next_u32() % 1000); + }); + vec + } + + fn log2(x: f64) -> f64 { + std::primitive::f64::log(x, 2.0f64) + } + + fn max_tree_height(n: u64) -> u64 { + // h <= C * log2(n + D) + B + // where: + // C =~ 1.440, D =~ 1.065, B =~ 0.328 + // (source: https://en.wikipedia.org/wiki/AVL_tree) + const B: f64 = -0.328; + const C: f64 = 1.440; + const D: f64 = 1.065; + + let h = C * log2(n as f64 + D) + B; + h.ceil() as u64 + } + + impl Debug for Node + where + K: Ord + Clone + Debug + BorshSerialize + BorshDeserialize, + { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("Node") + .field("id", &self.id) + .field("key", &self.key) + .field("lft", &self.lft) + .field("rgt", &self.rgt) + .field("ht", &self.ht) + .finish() + } + } + + impl Debug for LegacyTreeMap + where + K: Ord + Clone + Debug + BorshSerialize + BorshDeserialize, + V: Debug + BorshSerialize + BorshDeserialize, + { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("TreeMap") + .field("root", &self.root) + .field("tree", &self.tree.iter().collect::>>()) + .field("val", &self.val.iter().collect::>()) + .finish() + } + } + + #[test] + fn test_empty() { + test_env::setup(); + + let map: LegacyTreeMap = LegacyTreeMap::new(vec![b't']); + assert_eq!(map.len(), 0); + assert_eq!(height(&map), 0); + assert_eq!(map.get(&42), None); + assert!(!map.contains_key(&42)); + assert_eq!(map.min(), None); + assert_eq!(map.max(), None); + assert_eq!(map.lower(&42), None); + assert_eq!(map.higher(&42), None); + } + + #[test] + fn test_insert_3_rotate_l_l() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert_eq!(height(&map), 0); + + map.insert(&3, &3); + assert_eq!(height(&map), 1); + + map.insert(&2, &2); + assert_eq!(height(&map), 2); + + map.insert(&1, &1); + assert_eq!(height(&map), 2); + + let root = map.root; + assert_eq!(root, 1); + assert_eq!(map.node(root).map(|n| n.key), Some(2)); + + map.clear(); + } + + #[test] + fn test_insert_3_rotate_r_r() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert_eq!(height(&map), 0); + + map.insert(&1, &1); + assert_eq!(height(&map), 1); + + map.insert(&2, &2); + assert_eq!(height(&map), 2); + + map.insert(&3, &3); + + let root = map.root; + assert_eq!(root, 1); + assert_eq!(map.node(root).map(|n| n.key), Some(2)); + assert_eq!(height(&map), 2); + + map.clear(); + } + + #[test] + fn test_insert_lookup_n_asc() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + let n: u64 = 30; + let cases = (0..2 * (n as i32)).collect::>(); + + let mut counter = 0; + for k in &cases { + if *k % 2 == 0 { + counter += 1; + map.insert(k, &counter); + } + } + + counter = 0; + for k in &cases { + if *k % 2 == 0 { + counter += 1; + assert_eq!(map.get(k), Some(counter)); + } else { + assert_eq!(map.get(k), None); + } + } + + assert!(height(&map) <= max_tree_height(n)); + map.clear(); + } + + #[test] + fn test_insert_lookup_n_desc() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + let n: u64 = 30; + let cases = (0..2 * (n as i32)).rev().collect::>(); + + let mut counter = 0; + for k in &cases { + if *k % 2 == 0 { + counter += 1; + map.insert(k, &counter); + } + } + + counter = 0; + for k in &cases { + if *k % 2 == 0 { + counter += 1; + assert_eq!(map.get(k), Some(counter)); + } else { + assert_eq!(map.get(k), None); + } + } + + assert!(height(&map) <= max_tree_height(n)); + map.clear(); + } + + #[test] + fn insert_n_random() { + test_env::setup_free(); + + for k in 1..10 { + // tree size is 2^k + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + let n = 1 << k; + let input: Vec = random(n); + + for x in &input { + map.insert(x, &42); + } + + for x in &input { + assert_eq!(map.get(x), Some(42)); + } + + assert!(height(&map) <= max_tree_height(n)); + map.clear(); + } + } + + #[test] + fn test_min() { + test_env::setup(); + + let n: u64 = 30; + let vec = random(n); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(vec![b't']); + for x in vec.iter().rev() { + map.insert(x, &1); + } + + assert_eq!(map.min().unwrap(), *vec.iter().min().unwrap()); + map.clear(); + } + + #[test] + fn test_max() { + test_env::setup(); + + let n: u64 = 30; + let vec = random(n); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(vec![b't']); + for x in vec.iter().rev() { + map.insert(x, &1); + } + + assert_eq!(map.max().unwrap(), *vec.iter().max().unwrap()); + map.clear(); + } + + #[test] + fn test_lower() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let vec: Vec = vec![10, 20, 30, 40, 50]; + + for x in vec.iter() { + map.insert(x, &1); + } + + assert_eq!(map.lower(&5), None); + assert_eq!(map.lower(&10), None); + assert_eq!(map.lower(&11), Some(10)); + assert_eq!(map.lower(&20), Some(10)); + assert_eq!(map.lower(&49), Some(40)); + assert_eq!(map.lower(&50), Some(40)); + assert_eq!(map.lower(&51), Some(50)); + + map.clear(); + } + + #[test] + fn test_higher() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let vec: Vec = vec![10, 20, 30, 40, 50]; + + for x in vec.iter() { + map.insert(x, &1); + } + + assert_eq!(map.higher(&5), Some(10)); + assert_eq!(map.higher(&10), Some(20)); + assert_eq!(map.higher(&11), Some(20)); + assert_eq!(map.higher(&20), Some(30)); + assert_eq!(map.higher(&49), Some(50)); + assert_eq!(map.higher(&50), None); + assert_eq!(map.higher(&51), None); + + map.clear(); + } + + #[test] + fn test_floor_key() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let vec: Vec = vec![10, 20, 30, 40, 50]; + + for x in vec.iter() { + map.insert(x, &1); + } + + assert_eq!(map.floor_key(&5), None); + assert_eq!(map.floor_key(&10), Some(10)); + assert_eq!(map.floor_key(&11), Some(10)); + assert_eq!(map.floor_key(&20), Some(20)); + assert_eq!(map.floor_key(&49), Some(40)); + assert_eq!(map.floor_key(&50), Some(50)); + assert_eq!(map.floor_key(&51), Some(50)); + + map.clear(); + } + + #[test] + fn test_ceil_key() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let vec: Vec = vec![10, 20, 30, 40, 50]; + + for x in vec.iter() { + map.insert(x, &1); + } + + assert_eq!(map.ceil_key(&5), Some(10)); + assert_eq!(map.ceil_key(&10), Some(10)); + assert_eq!(map.ceil_key(&11), Some(20)); + assert_eq!(map.ceil_key(&20), Some(20)); + assert_eq!(map.ceil_key(&49), Some(50)); + assert_eq!(map.ceil_key(&50), Some(50)); + assert_eq!(map.ceil_key(&51), None); + + map.clear(); + } + + #[test] + fn test_remove_1() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + map.insert(&1, &1); + assert_eq!(map.get(&1), Some(1)); + map.remove(&1); + assert_eq!(map.get(&1), None); + assert_eq!(map.tree.len(), 0); + map.clear(); + } + + #[test] + fn test_remove_3() { + test_env::setup(); + + let map: LegacyTreeMap = avl(&[(0, 0)], &[0, 0, 1]); + + assert_eq!(map.iter().collect::>(), vec![]); + } + + #[test] + fn test_remove_3_desc() { + test_env::setup(); + + let vec: Vec = vec![3, 2, 1]; + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + map.clear(); + } + + #[test] + fn test_remove_3_asc() { + test_env::setup(); + + let vec: Vec = vec![1, 2, 3]; + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + map.clear(); + } + + #[test] + fn test_remove_7_regression_1() { + test_env::setup(); + + let vec: Vec = + vec![2104297040, 552624607, 4269683389, 3382615941, 155419892, 4102023417, 1795725075]; + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + map.clear(); + } + + #[test] + fn test_remove_7_regression_2() { + test_env::setup(); + + let vec: Vec = + vec![700623085, 87488544, 1500140781, 1111706290, 3187278102, 4042663151, 3731533080]; + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + map.clear(); + } + + #[test] + fn test_remove_9_regression() { + test_env::setup(); + + let vec: Vec = vec![ + 1186903464, 506371929, 1738679820, 1883936615, 1815331350, 1512669683, 3581743264, + 1396738166, 1902061760, + ]; + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + map.clear(); + } + + #[test] + fn test_remove_20_regression_1() { + test_env::setup(); + + let vec: Vec = vec![ + 552517392, 3638992158, 1015727752, 2500937532, 638716734, 586360620, 2476692174, + 1425948996, 3608478547, 757735878, 2709959928, 2092169539, 3620770200, 783020918, + 1986928932, 200210441, 1972255302, 533239929, 497054557, 2137924638, + ]; + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + map.clear(); + } + + #[test] + fn test_remove_7_regression() { + test_env::setup(); + + let vec: Vec = vec![280, 606, 163, 857, 436, 508, 44, 801]; + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in &vec { + assert_eq!(map.get(x), None); + map.insert(x, &1); + assert_eq!(map.get(x), Some(1)); + } + + for x in &vec { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + + assert_eq!(map.len(), 0, "map.len() > 0"); + assert_eq!(map.val.len(), 0, "map.val is not empty"); + assert_eq!(map.tree.len(), 0, "map.tree is not empty"); + map.clear(); + } + + #[test] + fn test_insert_8_remove_4_regression() { + let insert = vec![882, 398, 161, 76]; + let remove = vec![242, 687, 860, 811]; + + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for (i, (k1, k2)) in insert.iter().zip(remove.iter()).enumerate() { + let v = i as u32; + map.insert(k1, &v); + map.insert(k2, &v); + } + + for k in remove.iter() { + map.remove(k); + } + + assert_eq!(map.len(), insert.len() as u64); + + for (i, k) in insert.iter().enumerate() { + assert_eq!(map.get(k), Some(i as u32)); + } + } + + #[test] + fn test_remove_n() { + test_env::setup(); + + let n: u64 = 20; + let vec = random(n); + + let mut set: HashSet = HashSet::new(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + for x in &vec { + map.insert(x, &1); + set.insert(*x); + } + + assert_eq!(map.len(), set.len() as u64); + + for x in &set { + assert_eq!(map.get(x), Some(1)); + map.remove(x); + assert_eq!(map.get(x), None); + } + + assert_eq!(map.len(), 0, "map.len() > 0"); + assert_eq!(map.tree.len(), 0, "map.tree is not empty"); + assert_eq!(map.val.len(), 0, "map.val is not empty"); + map.clear(); + } + + #[test] + fn test_remove_root_3() { + test_env::setup(); + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + map.insert(&2, &1); + map.insert(&3, &1); + map.insert(&1, &1); + map.insert(&4, &1); + + map.remove(&2); + + assert_eq!(map.get(&1), Some(1)); + assert_eq!(map.get(&2), None); + assert_eq!(map.get(&3), Some(1)); + assert_eq!(map.get(&4), Some(1)); + map.clear(); + } + + #[test] + fn test_insert_2_remove_2_regression() { + test_env::setup(); + + let ins: Vec = vec![11760225, 611327897]; + let rem: Vec = vec![2982517385, 1833990072]; + + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + map.insert(&ins[0], &1); + map.insert(&ins[1], &1); + + map.remove(&rem[0]); + map.remove(&rem[1]); + + let h = height(&map); + let h_max = max_tree_height(map.len()); + assert!(h <= h_max, "h={} h_max={}", h, h_max); + map.clear(); + } + + #[test] + fn test_insert_n_duplicates() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + for x in 0..30 { + map.insert(&x, &x); + map.insert(&42, &x); + } + + assert_eq!(map.get(&42), Some(29)); + assert_eq!(map.len(), 31); + assert_eq!(map.val.len(), 31); + assert_eq!(map.tree.len(), 31); + + map.clear(); + } + + #[test] + fn test_insert_2n_remove_n_random() { + test_env::setup(); + + for k in 1..4 { + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let mut set: HashSet = HashSet::new(); + + let n = 1 << k; + let ins: Vec = random(n); + let rem: Vec = random(n); + + for x in &ins { + set.insert(*x); + map.insert(x, &42); + } + + for x in &rem { + set.insert(*x); + map.insert(x, &42); + } + + for x in &rem { + set.remove(x); + map.remove(x); + } + + assert_eq!(map.len(), set.len() as u64); + + let h = height(&map); + let h_max = max_tree_height(n); + assert!(h <= h_max, "[n={}] tree is too high: {} (max is {}).", n, h, h_max); + + map.clear(); + } + } + + #[test] + fn test_remove_empty() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert_eq!(map.remove(&1), None); + } + + #[test] + fn test_to_vec() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + map.insert(&1, &41); + map.insert(&2, &42); + map.insert(&3, &43); + + assert_eq!(map.to_vec(), vec![(1, 41), (2, 42), (3, 43)]); + map.clear(); + } + + #[test] + fn test_to_vec_empty() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert!(map.to_vec().is_empty()); + } + + #[test] + fn test_iter() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + map.insert(&1, &41); + map.insert(&2, &42); + map.insert(&3, &43); + + assert_eq!(map.iter().collect::>(), vec![(1, 41), (2, 42), (3, 43)]); + map.clear(); + } + + #[test] + fn test_iter_empty() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert!(map.iter().collect::>().is_empty()); + } + + #[test] + fn test_iter_rev() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + map.insert(&1, &41); + map.insert(&2, &42); + map.insert(&3, &43); + + assert_eq!(map.iter_rev().collect::>(), vec![(3, 43), (2, 42), (1, 41)]); + map.clear(); + } + + #[test] + fn test_iter_rev_empty() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert!(map.iter_rev().collect::>().is_empty()); + } + + #[test] + fn test_iter_from() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + let one: Vec = vec![10, 20, 30, 40, 50]; + let two: Vec = vec![45, 35, 25, 15, 5]; + + for x in &one { + map.insert(x, &42); + } + + for x in &two { + map.insert(x, &42); + } + + assert_eq!( + map.iter_from(29).collect::>(), + vec![(30, 42), (35, 42), (40, 42), (45, 42), (50, 42)] + ); + + assert_eq!( + map.iter_from(30).collect::>(), + vec![(35, 42), (40, 42), (45, 42), (50, 42)] + ); + + assert_eq!( + map.iter_from(31).collect::>(), + vec![(35, 42), (40, 42), (45, 42), (50, 42)] + ); + map.clear(); + } + + #[test] + fn test_iter_from_empty() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert!(map.iter_from(42).collect::>().is_empty()); + } + + #[test] + fn test_iter_rev_from() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + let one: Vec = vec![10, 20, 30, 40, 50]; + let two: Vec = vec![45, 35, 25, 15, 5]; + + for x in &one { + map.insert(x, &42); + } + + for x in &two { + map.insert(x, &42); + } + + assert_eq!( + map.iter_rev_from(29).collect::>(), + vec![(25, 42), (20, 42), (15, 42), (10, 42), (5, 42)] + ); + + assert_eq!( + map.iter_rev_from(30).collect::>(), + vec![(25, 42), (20, 42), (15, 42), (10, 42), (5, 42)] + ); + + assert_eq!( + map.iter_rev_from(31).collect::>(), + vec![(30, 42), (25, 42), (20, 42), (15, 42), (10, 42), (5, 42)] + ); + map.clear(); + } + + #[test] + fn test_range() { + test_env::setup(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + + let one: Vec = vec![10, 20, 30, 40, 50]; + let two: Vec = vec![45, 35, 25, 15, 5]; + + for x in &one { + map.insert(x, &42); + } + + for x in &two { + map.insert(x, &42); + } + + assert_eq!( + map.range((Bound::Included(20), Bound::Excluded(30))).collect::>(), + vec![(20, 42), (25, 42)] + ); + + assert_eq!( + map.range((Bound::Excluded(10), Bound::Included(40))).collect::>(), + vec![(15, 42), (20, 42), (25, 42), (30, 42), (35, 42), (40, 42)] + ); + + assert_eq!( + map.range((Bound::Included(20), Bound::Included(40))).collect::>(), + vec![(20, 42), (25, 42), (30, 42), (35, 42), (40, 42)] + ); + + assert_eq!( + map.range((Bound::Excluded(20), Bound::Excluded(45))).collect::>(), + vec![(25, 42), (30, 42), (35, 42), (40, 42)] + ); + + assert_eq!( + map.range((Bound::Excluded(20), Bound::Excluded(45))).collect::>(), + vec![(25, 42), (30, 42), (35, 42), (40, 42)] + ); + + assert_eq!( + map.range((Bound::Excluded(25), Bound::Excluded(30))).collect::>(), + vec![] + ); + + assert_eq!( + map.range((Bound::Included(25), Bound::Included(25))).collect::>(), + vec![(25, 42)] + ); + + assert_eq!( + map.range((Bound::Excluded(25), Bound::Included(25))).collect::>(), + vec![] + ); // the range makes no sense, but `BTreeMap` does not panic in this case + + map.clear(); + } + + #[test] + #[should_panic(expected = "Invalid range.")] + fn test_range_panics_same_excluded() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let _ = map.range((Bound::Excluded(1), Bound::Excluded(1))); + } + + #[test] + #[should_panic(expected = "Invalid range.")] + fn test_range_panics_non_overlap_incl_exlc() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let _ = map.range((Bound::Included(2), Bound::Excluded(1))); + } + + #[test] + #[should_panic(expected = "Invalid range.")] + fn test_range_panics_non_overlap_excl_incl() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let _ = map.range((Bound::Excluded(2), Bound::Included(1))); + } + + #[test] + #[should_panic(expected = "Invalid range.")] + fn test_range_panics_non_overlap_incl_incl() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + let _ = map.range((Bound::Included(2), Bound::Included(1))); + } + + #[test] + fn test_iter_rev_from_empty() { + test_env::setup(); + let map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + assert!(map.iter_rev_from(42).collect::>().is_empty()); + } + + #[test] + fn test_balance_regression_1() { + let insert = vec![(2, 0), (3, 0), (4, 0)]; + let remove = vec![0, 0, 0, 1]; + + let map = avl(&insert, &remove); + assert!(is_balanced(&map, map.root)); + } + + #[test] + fn test_balance_regression_2() { + let insert = vec![(1, 0), (2, 0), (0, 0), (3, 0), (5, 0), (6, 0)]; + let remove = vec![0, 0, 0, 3, 5, 6, 7, 4]; + + let map = avl(&insert, &remove); + assert!(is_balanced(&map, map.root)); + } + + // + // Property-based tests of AVL-based TreeMap against std::collections::BTreeMap + // + + fn avl(insert: &[(K, V)], remove: &[K]) -> LegacyTreeMap + where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: Default + BorshSerialize + BorshDeserialize, + { + test_env::setup_free(); + let mut map: LegacyTreeMap = LegacyTreeMap::new(next_trie_id()); + for k in remove { + map.insert(k, &Default::default()); + } + let n = insert.len().max(remove.len()); + for i in 0..n { + if i < remove.len() { + map.remove(&remove[i]); + } + if i < insert.len() { + let (k, v) = &insert[i]; + map.insert(k, v); + } + } + map + } + + fn rb(insert: &[(K, V)], remove: &[K]) -> BTreeMap + where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: Clone + Default + BorshSerialize + BorshDeserialize, + { + let mut map: BTreeMap = BTreeMap::default(); + for k in remove { + map.insert(k.clone(), Default::default()); + } + let n = insert.len().max(remove.len()); + for i in 0..n { + if i < remove.len() { + map.remove(&remove[i]); + } + if i < insert.len() { + let (k, v) = &insert[i]; + map.insert(k.clone(), v.clone()); + } + } + map + } + + #[test] + fn prop_avl_vs_rb() { + fn prop(insert: Vec<(u32, u32)>, remove: Vec) -> bool { + let a = avl(&insert, &remove); + let b = rb(&insert, &remove); + let v1: Vec<(u32, u32)> = a.iter().collect(); + let v2: Vec<(u32, u32)> = b.into_iter().collect(); + v1 == v2 + } + + QuickCheck::new() + .tests(300) + .quickcheck(prop as fn(std::vec::Vec<(u32, u32)>, std::vec::Vec) -> bool); + } + + fn is_balanced(map: &LegacyTreeMap, root: u64) -> bool + where + K: Debug + Ord + Clone + BorshSerialize + BorshDeserialize, + V: Debug + BorshSerialize + BorshDeserialize, + { + let node = map.node(root).unwrap(); + let balance = map.get_balance(&node); + + (balance >= -1 && balance <= 1) + && node.lft.map(|id| is_balanced(map, id)).unwrap_or(true) + && node.rgt.map(|id| is_balanced(map, id)).unwrap_or(true) + } + + #[test] + fn prop_avl_balance() { + test_env::setup_free(); + + fn prop(insert: Vec<(u32, u32)>, remove: Vec) -> bool { + let map = avl(&insert, &remove); + map.len() == 0 || is_balanced(&map, map.root) + } + + QuickCheck::new() + .tests(300) + .quickcheck(prop as fn(std::vec::Vec<(u32, u32)>, std::vec::Vec) -> bool); + } + + #[test] + fn prop_avl_height() { + test_env::setup_free(); + + fn prop(insert: Vec<(u32, u32)>, remove: Vec) -> bool { + let map = avl(&insert, &remove); + height(&map) <= max_tree_height(map.len()) + } + + QuickCheck::new() + .tests(300) + .quickcheck(prop as fn(std::vec::Vec<(u32, u32)>, std::vec::Vec) -> bool); + } + + fn range_prop( + insert: Vec<(u32, u32)>, + remove: Vec, + range: (Bound, Bound), + ) -> bool { + let a = avl(&insert, &remove); + let b = rb(&insert, &remove); + let v1: Vec<(u32, u32)> = a.range(range).collect(); + let v2: Vec<(u32, u32)> = b.range(range).map(|(k, v)| (*k, *v)).collect(); + v1 == v2 + } + + type Prop = fn(std::vec::Vec<(u32, u32)>, std::vec::Vec, u32, u32) -> bool; + + #[test] + fn prop_avl_vs_rb_range_incl_incl() { + fn prop(insert: Vec<(u32, u32)>, remove: Vec, r1: u32, r2: u32) -> bool { + let range = (Bound::Included(r1.min(r2)), Bound::Included(r1.max(r2))); + range_prop(insert, remove, range) + } + + QuickCheck::new().tests(300).quickcheck(prop as Prop); + } + + #[test] + fn prop_avl_vs_rb_range_incl_excl() { + fn prop(insert: Vec<(u32, u32)>, remove: Vec, r1: u32, r2: u32) -> bool { + let range = (Bound::Included(r1.min(r2)), Bound::Excluded(r1.max(r2))); + range_prop(insert, remove, range) + } + + QuickCheck::new().tests(300).quickcheck(prop as Prop); + } + + #[test] + fn prop_avl_vs_rb_range_excl_incl() { + fn prop(insert: Vec<(u32, u32)>, remove: Vec, r1: u32, r2: u32) -> bool { + let range = (Bound::Excluded(r1.min(r2)), Bound::Included(r1.max(r2))); + range_prop(insert, remove, range) + } + + QuickCheck::new().tests(300).quickcheck(prop as Prop); + } + + #[test] + fn prop_avl_vs_rb_range_excl_excl() { + fn prop(insert: Vec<(u32, u32)>, remove: Vec, r1: u32, r2: u32) -> bool { + // (Excluded(x), Excluded(x)) is invalid range, checking against it makes no sense + r1 == r2 || { + let range = (Bound::Excluded(r1.min(r2)), Bound::Excluded(r1.max(r2))); + range_prop(insert, remove, range) + } + } + + QuickCheck::new().tests(300).quickcheck(prop as Prop); + } +} diff --git a/near-sdk/src/collections/lookup_map.rs b/near-sdk/src/collections/lookup_map.rs new file mode 100644 index 000000000..de2ca815f --- /dev/null +++ b/near-sdk/src/collections/lookup_map.rs @@ -0,0 +1,285 @@ +//! A persistent map without iterators. Unlike `near_sdk::collections::UnorderedMap` this map +//! doesn't store keys and values separately in vectors, so it can't iterate over keys. But it +//! makes this map more efficient in the number of reads and writes. +use std::marker::PhantomData; + +use borsh::{BorshDeserialize, BorshSerialize}; + +use crate::collections::append_slice; +use crate::env; + +const ERR_KEY_SERIALIZATION: &[u8] = b"Cannot serialize key with Borsh"; +const ERR_VALUE_DESERIALIZATION: &[u8] = b"Cannot deserialize value with Borsh"; +const ERR_VALUE_SERIALIZATION: &[u8] = b"Cannot serialize value with Borsh"; + +/// An non-iterable implementation of a map that stores its content directly on the trie. +#[derive(BorshSerialize, BorshDeserialize)] +pub struct LookupMap { + key_prefix: Vec, + #[borsh_skip] + el: PhantomData<(K, V)>, +} + +impl LookupMap { + /// Create a new map. Use `key_prefix` as a unique prefix for keys. + pub fn new(key_prefix: Vec) -> Self { + Self { key_prefix, el: PhantomData } + } + + fn raw_key_to_storage_key(&self, raw_key: &[u8]) -> Vec { + append_slice(&self.key_prefix, raw_key) + } + + /// Returns `true` if the serialized key is present in the map. + fn contains_key_raw(&self, key_raw: &[u8]) -> bool { + let storage_key = self.raw_key_to_storage_key(key_raw); + env::storage_has_key(&storage_key) + } + + /// Returns the serialized value corresponding to the serialized key. + fn get_raw(&self, key_raw: &[u8]) -> Option> { + let storage_key = self.raw_key_to_storage_key(key_raw); + env::storage_read(&storage_key) + } + + /// Inserts a serialized key-value pair into the map. + /// If the map did not have this key present, `None` is returned. Otherwise returns + /// a serialized value. Note, the keys that have the same hash value are undistinguished by + /// the implementation. + pub fn insert_raw(&mut self, key_raw: &[u8], value_raw: &[u8]) -> Option> { + let storage_key = self.raw_key_to_storage_key(key_raw); + if env::storage_write(&storage_key, value_raw) { + Some(env::storage_get_evicted().unwrap()) + } else { + None + } + } + + /// Removes a serialized key from the map, returning the serialized value at the key if the key + /// was previously in the map. + pub fn remove_raw(&mut self, key_raw: &[u8]) -> Option> { + let storage_key = self.raw_key_to_storage_key(key_raw); + if env::storage_remove(&storage_key) { + Some(env::storage_get_evicted().unwrap()) + } else { + None + } + } +} + +impl LookupMap +where + K: BorshSerialize, + V: BorshSerialize + BorshDeserialize, +{ + fn serialize_key(key: &K) -> Vec { + match key.try_to_vec() { + Ok(x) => x, + Err(_) => env::panic(ERR_KEY_SERIALIZATION), + } + } + + fn deserialize_value(raw_value: &[u8]) -> V { + match V::try_from_slice(&raw_value) { + Ok(x) => x, + Err(_) => env::panic(ERR_VALUE_DESERIALIZATION), + } + } + + fn serialize_value(value: &V) -> Vec { + match value.try_to_vec() { + Ok(x) => x, + Err(_) => env::panic(ERR_VALUE_SERIALIZATION), + } + } + + /// Returns true if the map contains a given key. + pub fn contains_key(&self, key: &K) -> bool { + self.contains_key_raw(&Self::serialize_key(key)) + } + + /// Returns the value corresponding to the key. + pub fn get(&self, key: &K) -> Option { + self.get_raw(&Self::serialize_key(key)).map(|value_raw| Self::deserialize_value(&value_raw)) + } + + /// Removes a key from the map, returning the value at the key if the key was previously in the + /// map. + pub fn remove(&mut self, key: &K) -> Option { + self.remove_raw(&Self::serialize_key(key)) + .map(|value_raw| Self::deserialize_value(&value_raw)) + } + + /// Inserts a key-value pair into the map. + /// If the map did not have this key present, `None` is returned. Otherwise returns + /// a value. Note, the keys that have the same hash value are undistinguished by + /// the implementation. + pub fn insert(&mut self, key: &K, value: &V) -> Option { + self.insert_raw(&Self::serialize_key(key), &Self::serialize_value(&value)) + .map(|value_raw| Self::deserialize_value(&value_raw)) + } + + pub fn extend>(&mut self, iter: IT) { + for (el_key, el_value) in iter { + self.insert(&el_key, &el_value); + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +#[cfg(test)] +mod tests { + use crate::collections::LookupMap; + use crate::test_utils::test_env; + use rand::seq::SliceRandom; + use rand::{Rng, SeedableRng}; + use std::collections::HashMap; + + #[test] + pub fn test_insert() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); + for _ in 0..500 { + let key = rng.gen::(); + let value = rng.gen::(); + map.insert(&key, &value); + } + } + + #[test] + pub fn test_insert_has_key() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); + let mut key_to_value = HashMap::new(); + for _ in 0..100 { + let key = rng.gen::(); + let value = rng.gen::(); + map.insert(&key, &value); + key_to_value.insert(key, value); + } + // Non existing + for _ in 0..100 { + let key = rng.gen::(); + assert_eq!(map.contains_key(&key), key_to_value.contains_key(&key)); + } + // Existing + for (key, _) in key_to_value.iter() { + assert!(map.contains_key(&key)); + } + } + + #[test] + pub fn test_insert_remove() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(1); + let mut keys = vec![]; + let mut key_to_value = HashMap::new(); + for _ in 0..100 { + let key = rng.gen::(); + let value = rng.gen::(); + keys.push(key); + key_to_value.insert(key, value); + map.insert(&key, &value); + } + keys.shuffle(&mut rng); + for key in keys { + let actual = map.remove(&key).unwrap(); + assert_eq!(actual, key_to_value[&key]); + } + } + + #[test] + pub fn test_remove_last_reinsert() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let key1 = 1u64; + let value1 = 2u64; + map.insert(&key1, &value1); + let key2 = 3u64; + let value2 = 4u64; + map.insert(&key2, &value2); + + let actual_value2 = map.remove(&key2).unwrap(); + assert_eq!(actual_value2, value2); + + let actual_insert_value2 = map.insert(&key2, &value2); + assert_eq!(actual_insert_value2, None); + } + + #[test] + pub fn test_insert_override_remove() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(2); + let mut keys = vec![]; + let mut key_to_value = HashMap::new(); + for _ in 0..100 { + let key = rng.gen::(); + let value = rng.gen::(); + keys.push(key); + key_to_value.insert(key, value); + map.insert(&key, &value); + } + keys.shuffle(&mut rng); + for key in &keys { + let value = rng.gen::(); + let actual = map.insert(key, &value).unwrap(); + assert_eq!(actual, key_to_value[key]); + key_to_value.insert(*key, value); + } + keys.shuffle(&mut rng); + for key in keys { + let actual = map.remove(&key).unwrap(); + assert_eq!(actual, key_to_value[&key]); + } + } + + #[test] + pub fn test_get_non_existent() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(3); + let mut key_to_value = HashMap::new(); + for _ in 0..500 { + let key = rng.gen::() % 20_000; + let value = rng.gen::(); + key_to_value.insert(key, value); + map.insert(&key, &value); + } + for _ in 0..500 { + let key = rng.gen::() % 20_000; + assert_eq!(map.get(&key), key_to_value.get(&key).cloned()); + } + } + + #[test] + pub fn test_extend() { + test_env::setup(); + let mut map = LookupMap::new(b"m".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); + let mut key_to_value = HashMap::new(); + for _ in 0..100 { + let key = rng.gen::(); + let value = rng.gen::(); + key_to_value.insert(key, value); + map.insert(&key, &value); + } + for _ in 0..10 { + let mut tmp = vec![]; + for _ in 0..=(rng.gen::() % 20 + 1) { + let key = rng.gen::(); + let value = rng.gen::(); + tmp.push((key, value)); + } + key_to_value.extend(tmp.iter().cloned()); + map.extend(tmp.iter().cloned()); + } + + for (key, value) in key_to_value { + assert_eq!(map.get(&key).unwrap(), value); + } + } +} diff --git a/near-sdk/src/collections/lookup_set.rs b/near-sdk/src/collections/lookup_set.rs new file mode 100644 index 000000000..144c01183 --- /dev/null +++ b/near-sdk/src/collections/lookup_set.rs @@ -0,0 +1,204 @@ +//! A persistent set without iterators. Unlike `near_sdk::collections::LookupSet` this set +//! doesn't store values separately in a vector, so it can't iterate over the values. But it +//! makes this implementation more efficient in the number of reads and writes. +use std::marker::PhantomData; + +use borsh::{BorshDeserialize, BorshSerialize}; + +use crate::collections::append_slice; +use crate::env; + +const ERR_ELEMENT_SERIALIZATION: &[u8] = b"Cannot serialize element with Borsh"; + +/// An non-iterable implementation of a set that stores its content directly on the trie. +#[derive(BorshSerialize, BorshDeserialize)] +pub struct LookupSet { + element_prefix: Vec, + #[borsh_skip] + el: PhantomData, +} + +impl LookupSet { + /// Create a new map. Use `element_prefix` as a unique prefix for trie keys. + pub fn new(element_prefix: Vec) -> Self { + Self { element_prefix, el: PhantomData } + } + + fn raw_element_to_storage_key(&self, element_raw: &[u8]) -> Vec { + append_slice(&self.element_prefix, element_raw) + } + + /// Returns `true` if the serialized key is present in the map. + fn contains_raw(&self, element_raw: &[u8]) -> bool { + let storage_key = self.raw_element_to_storage_key(element_raw); + env::storage_has_key(&storage_key) + } + + /// Inserts a serialized element into the set. + /// If the set did not have this value present, `true` is returned. + /// If the set did have this value present, `false` is returned. + pub fn insert_raw(&mut self, element_raw: &[u8]) -> bool { + let storage_key = self.raw_element_to_storage_key(element_raw); + !env::storage_write(&storage_key, b"") + } + + /// Removes a serialized element from the set. + /// Returns true if the element was present in the set. + pub fn remove_raw(&mut self, element_raw: &[u8]) -> bool { + let storage_key = self.raw_element_to_storage_key(element_raw); + env::storage_remove(&storage_key) + } +} + +impl LookupSet +where + T: BorshSerialize, +{ + fn serialize_element(element: &T) -> Vec { + match element.try_to_vec() { + Ok(x) => x, + Err(_) => env::panic(ERR_ELEMENT_SERIALIZATION), + } + } + + /// Returns true if the set contains an element. + pub fn contains(&self, element: &T) -> bool { + self.contains_raw(&Self::serialize_element(element)) + } + + /// Removes a value from the set. Returns whether the value was present in the set. + pub fn remove(&mut self, element: &T) -> bool { + self.remove_raw(&Self::serialize_element(element)) + } + + /// Adds a value to the set. + /// If the set did not have this value present, `true` is returned. + /// If the set did have this value present, `false` is returned. + pub fn insert(&mut self, element: &T) -> bool { + self.insert_raw(&Self::serialize_element(element)) + } + + pub fn extend>(&mut self, iter: IT) { + for el in iter { + self.insert(&el); + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +#[cfg(test)] +mod tests { + use crate::collections::LookupSet; + use crate::test_utils::test_env; + use rand::seq::SliceRandom; + use rand::{Rng, SeedableRng}; + use std::collections::HashSet; + + #[test] + pub fn test_insert() { + test_env::setup(); + let mut set = LookupSet::new(b"s".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); + for _ in 0..500 { + let key = rng.gen::(); + set.insert(&key); + } + } + + #[test] + pub fn test_insert_remove() { + test_env::setup(); + let mut set = LookupSet::new(b"s".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(1); + let mut keys = vec![]; + for _ in 0..100 { + let key = rng.gen::(); + keys.push(key); + set.insert(&key); + } + keys.shuffle(&mut rng); + for key in keys { + assert!(set.remove(&key)); + } + } + + #[test] + pub fn test_remove_last_reinsert() { + test_env::setup(); + let mut set = LookupSet::new(b"s".to_vec()); + let key1 = 1u64; + set.insert(&key1); + let key2 = 2u64; + set.insert(&key2); + + let actual = set.remove(&key2); + assert!(actual); + + let actual_reinsert = set.insert(&key2); + assert!(actual_reinsert); + } + + #[test] + pub fn test_insert_override_remove() { + test_env::setup(); + let mut set = LookupSet::new(b"s".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(2); + let mut keys = vec![]; + for _ in 0..100 { + let key = rng.gen::(); + keys.push(key); + set.insert(&key); + } + keys.shuffle(&mut rng); + for key in &keys { + assert!(!set.insert(key)); + } + keys.shuffle(&mut rng); + for key in keys { + assert!(set.remove(&key)); + } + } + + #[test] + pub fn test_contains_non_existent() { + test_env::setup(); + let mut set = LookupSet::new(b"s".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(3); + let mut set_tmp = HashSet::new(); + for _ in 0..500 { + let key = rng.gen::() % 20_000; + set_tmp.insert(key); + set.insert(&key); + } + for _ in 0..500 { + let key = rng.gen::() % 20_000; + assert_eq!(set.contains(&key), set_tmp.contains(&key)); + } + } + + #[test] + pub fn test_extend() { + test_env::setup(); + let mut set = LookupSet::new(b"s".to_vec()); + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); + let mut keys = HashSet::new(); + for _ in 0..100 { + let key = rng.gen::(); + keys.insert(key); + set.insert(&key); + } + for _ in 0..10 { + let mut tmp = vec![]; + for _ in 0..=(rng.gen::() % 20 + 1) { + let key = rng.gen::(); + tmp.push(key); + } + keys.extend(tmp.iter().cloned()); + set.extend(tmp.iter().cloned()); + } + + for key in keys { + assert!(set.contains(&key)); + } + } +} diff --git a/near-sdk/src/collections/mod.rs b/near-sdk/src/collections/mod.rs index b9a2ebd35..a0881e30b 100644 --- a/near-sdk/src/collections/mod.rs +++ b/near-sdk/src/collections/mod.rs @@ -12,7 +12,7 @@ //! # use near_sdk_macros::near_bindgen; //! //! #[near_bindgen] -//! #[derive(Default, BorshDeserialize, BorshSerialize)] +//! #[derive(BorshDeserialize, BorshSerialize)] //! pub struct StatusMessage { //! records: HashMap, //! } @@ -23,20 +23,26 @@ //! ``` //! # use borsh::{BorshSerialize, BorshDeserialize}; //! # use near_sdk_macros::near_bindgen; -//! # use near_sdk::collections::UnorderedMap; +//! # use near_sdk::collections::LookupMap; //! //! #[near_bindgen] -//! #[derive(Default, BorshDeserialize, BorshSerialize)] +//! #[derive(BorshDeserialize, BorshSerialize)] //! pub struct StatusMessage { -//! records: UnorderedMap, +//! records: LookupMap, //! } //! ``` //! -//! The efficiency of `Map` comes at the cost, since it has fewer methods than `HashMap` and is not +//! The efficiency of `LookupMap` comes at the cost, since it has fewer methods than `HashMap` and is not //! that seemlessly integrated with the rest of the Rust standard library. -mod set; -pub use set::UnorderedSet; +mod legacy_tree_map; +pub use legacy_tree_map::LegacyTreeMap; + +mod lookup_map; +pub use lookup_map::LookupMap; + +mod lookup_set; +pub use lookup_set::LookupSet; mod vector; pub use vector::Vector; @@ -44,6 +50,9 @@ pub use vector::Vector; mod unordered_map; pub use unordered_map::UnorderedMap; +mod unordered_set; +pub use unordered_set::UnorderedSet; + mod tree_map; pub use tree_map::TreeMap; @@ -51,18 +60,6 @@ pub const ERR_INCONSISTENT_STATE: &[u8] = b"The collection is an inconsistent st pub const ERR_ELEMENT_SERIALIZATION: &[u8] = b"Cannot serialize element with Borsh."; pub const ERR_ELEMENT_DESERIALIZATION: &[u8] = b"Cannot deserialize element with Borsh."; -/// Objects stored on the trie directly should have identifiers. If identifier is not provided -/// explicitly than `Default` trait would use this index to generate an id. -pub(crate) static mut NEXT_TRIE_OBJECT_INDEX: u64 = 0; -/// Get next id of the object stored on trie. -pub(crate) fn next_trie_id() -> Vec { - unsafe { - let id = NEXT_TRIE_OBJECT_INDEX; - NEXT_TRIE_OBJECT_INDEX += 1; - id.to_le_bytes().to_vec() - } -} - pub(crate) fn append(id: &[u8], chr: u8) -> Vec { append_slice(id, &[chr]) } diff --git a/near-sdk/src/collections/tree_map.rs b/near-sdk/src/collections/tree_map.rs index 2abec901f..47b6500ad 100644 --- a/near-sdk/src/collections/tree_map.rs +++ b/near-sdk/src/collections/tree_map.rs @@ -1,8 +1,8 @@ -use std::ops::Bound; use borsh::{BorshDeserialize, BorshSerialize}; +use std::ops::Bound; -use crate::collections::{append, next_trie_id, Vector}; -use crate::collections::UnorderedMap; +use crate::collections::LookupMap; +use crate::collections::{append, Vector}; /// TreeMap based on AVL-tree /// @@ -16,54 +16,37 @@ use crate::collections::UnorderedMap; #[derive(BorshSerialize, BorshDeserialize)] pub struct TreeMap { root: u64, - val: UnorderedMap, + val: LookupMap, tree: Vector>, } #[derive(Clone, BorshSerialize, BorshDeserialize)] pub struct Node { id: u64, - key: K, // key stored in a node - lft: Option, // left link of a node - rgt: Option, // right link of a node - ht: u64, // height of a subtree at a node + key: K, // key stored in a node + lft: Option, // left link of a node + rgt: Option, // right link of a node + ht: u64, // height of a subtree at a node } impl Node - where - K: Ord + Clone + BorshSerialize + BorshDeserialize +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, { fn of(id: u64, key: K) -> Self { - Self { - id, - key, - lft: None, - rgt: None, - ht: 1, - } - } -} - -impl Default for TreeMap - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: BorshSerialize + BorshDeserialize, -{ - fn default() -> Self { - Self::new(next_trie_id()) + Self { id, key, lft: None, rgt: None, ht: 1 } } } - impl TreeMap - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: BorshSerialize + BorshDeserialize, +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, { pub fn new(id: Vec) -> Self { Self { root: 0, - val: UnorderedMap::new(append(&id, b'v')), + val: LookupMap::new(append(&id, b'v')), tree: Vector::new(append(&id, b'n')), } } @@ -74,7 +57,9 @@ impl TreeMap pub fn clear(&mut self) { self.root = 0; - self.val.clear(); + for n in self.tree.iter() { + self.val.remove(&n.key); + } self.tree.clear(); } @@ -181,11 +166,11 @@ impl TreeMap /// Panics if range start == end and both bounds are Excluded. pub fn range<'a>(&'a self, r: (Bound, Bound)) -> impl Iterator + 'a { let (lo, hi) = match r { - (Bound::Included(a), Bound::Included(b)) if a > b => panic!("Invalid range."), - (Bound::Excluded(a), Bound::Included(b)) if a > b => panic!("Invalid range."), - (Bound::Included(a), Bound::Excluded(b)) if a > b => panic!("Invalid range."), + (Bound::Included(a), Bound::Included(b)) if a > b => panic!("Invalid range."), + (Bound::Excluded(a), Bound::Included(b)) if a > b => panic!("Invalid range."), + (Bound::Included(a), Bound::Excluded(b)) if a > b => panic!("Invalid range."), (Bound::Excluded(a), Bound::Excluded(b)) if a == b => panic!("Invalid range."), - (lo, hi) => (lo, hi) + (lo, hi) => (lo, hi), }; Cursor::range(&self, lo, hi).into_iter() @@ -210,13 +195,12 @@ impl TreeMap Some(lft) => { at = lft; parent = node; - }, + } None => { return node.and_then(|n| parent.map(|p| (n, p))); } } } - } /// Returns (node, parent node) of right-most lower (max) node starting from given node `at`. @@ -230,7 +214,7 @@ impl TreeMap Some(rgt) => { parent = node; at = rgt; - }, + } None => { return node.and_then(|n| parent.map(|p| (n, p))); } @@ -247,17 +231,17 @@ impl TreeMap if k.le(key) { match node.and_then(|n| n.rgt) { Some(rgt) => at = rgt, - None => break + None => break, } } else { seen = Some(k); match node.and_then(|n| n.lft) { Some(lft) => at = lft, - None => break + None => break, } } - }, - None => break + } + None => break, } } seen @@ -273,16 +257,16 @@ impl TreeMap seen = Some(k); match node.and_then(|n| n.rgt) { Some(rgt) => at = rgt, - None => break + None => break, } } else { match node.and_then(|n| n.lft) { Some(lft) => at = lft, - None => break + None => break, } } - }, - None => break + } + None => break, } } seen @@ -293,29 +277,21 @@ impl TreeMap None => { self.save(&Node::of(id, key.clone())); at - }, + } Some(mut node) => { if key.eq(&node.key) { at } else { if key.lt(&node.key) { let idx = match node.lft { - Some(lft) => { - self.insert_at(lft, id, key) - }, - None => { - self.insert_at(id, id, key) - } + Some(lft) => self.insert_at(lft, id, key), + None => self.insert_at(id, id, key), }; node.lft = Some(idx); } else { let idx = match node.rgt { - Some(rgt) => { - self.insert_at(rgt, id, key) - }, - None => { - self.insert_at(id, id, key) - } + Some(rgt) => self.insert_at(rgt, id, key), + None => self.insert_at(id, id, key), }; node.rgt = Some(idx); }; @@ -330,12 +306,8 @@ impl TreeMap // Calculate and save the height of a subtree at node `at`: // height[at] = 1 + max(height[at.L], height[at.R]) fn update_height(&mut self, node: &mut Node) { - let lft = node.lft - .and_then(|id| self.node(id).map(|n| n.ht)) - .unwrap_or_default(); - let rgt = node.rgt - .and_then(|id| self.node(id).map(|n| n.ht)) - .unwrap_or_default(); + let lft = node.lft.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); + let rgt = node.rgt.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); node.ht = 1 + std::cmp::max(lft, rgt); self.save(&node); @@ -343,12 +315,8 @@ impl TreeMap // Balance = difference in heights between left and right subtrees at given node. fn get_balance(&self, node: &Node) -> i64 { - let lht = node.lft - .and_then(|id| self.node(id).map(|n| n.ht)) - .unwrap_or_default(); - let rht = node.rgt - .and_then(|id| self.node(id).map(|n| n.ht)) - .unwrap_or_default(); + let lht = node.lft.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); + let rht = node.rgt.and_then(|id| self.node(id).map(|n| n.ht)).unwrap_or_default(); lht as i64 - rht as i64 } @@ -427,20 +395,20 @@ impl TreeMap Some(rgt) => { p = node; at = rgt; - }, - None => break + } + None => break, } } else { match node.lft { Some(lft) => { p = node; at = lft; - }, - None => break + } + None => break, } } - }, - None => break + } + None => break, } } None @@ -460,23 +428,23 @@ impl TreeMap Some(l) => { let id = self.check_balance(l, key); node.lft = Some(id); - }, - None => () + } + None => (), } } else { match node.rgt { Some(r) => { let id = self.check_balance(r, key); node.rgt = Some(id); - }, - None => () + } + None => (), } } self.update_height(&mut node); self.enforce_balance(&mut node) } - }, - None => at + } + None => at, } } @@ -493,7 +461,7 @@ impl TreeMap // p_node - immediate parent node of r_node let (mut r_node, mut p_node) = match self.lookup_at(self.root, key) { Some(x) => x, - None => return self.root // cannot remove a missing key, no changes to the tree needed + None => return self.root, // cannot remove a missing key, no changes to the tree needed }; let lft_opt = r_node.lft; @@ -585,9 +553,9 @@ impl TreeMap } // Move content of node with id = `len - 1` (parent left or right link, left, right, key, height) - // to node with give `id`, and remove node `len - 1` (pop the vector of nodes). - // This ensures that among n nodes in the tree, max id is n-1, so when new node is inserted, - // it gets and id as it's position in the vector. + // to node with given `id`, and remove node `len - 1` (pop the vector of nodes). + // This ensures that among `n` nodes in the tree, max `id` is `n-1`, so when new node is inserted, + // it gets an `id` as its position in the vector. fn swap_with_last(&mut self, id: u64) { if id == self.len() - 1 { // noop: id is already last element in the vector @@ -618,9 +586,9 @@ impl TreeMap } impl<'a, K, V> IntoIterator for &'a TreeMap - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: BorshSerialize + BorshDeserialize, +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, { type Item = (K, V); type IntoIter = Cursor<'a, K, V>; @@ -631,23 +599,19 @@ impl<'a, K, V> IntoIterator for &'a TreeMap } impl Iterator for Cursor<'_, K, V> - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: BorshSerialize + BorshDeserialize, +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, { type Item = (K, V); fn next(&mut self) -> Option { let this_key = self.key.clone(); - let next_key = self.key.take() - .and_then(|k| { - if self.asc { - self.map.higher(&k) - } else { - self.map.lower(&k) - } - }) + let next_key = self + .key + .take() + .and_then(|k| if self.asc { self.map.higher(&k) } else { self.map.lower(&k) }) .filter(|k| fits(k, &self.lo, &self.hi)); self.key = next_key; @@ -659,12 +623,11 @@ fn fits(key: &K, lo: &Bound, hi: &Bound) -> bool { (match lo { Bound::Included(ref x) => key >= x, Bound::Excluded(ref x) => key > x, - Bound::Unbounded => true - }) && - (match hi { + Bound::Unbounded => true, + }) && (match hi { Bound::Included(ref x) => key <= x, Bound::Excluded(ref x) => key < x, - Bound::Unbounded => true + Bound::Unbounded => true, }) } @@ -673,73 +636,43 @@ pub struct Cursor<'a, K, V> { lo: Bound, hi: Bound, key: Option, - map: &'a TreeMap + map: &'a TreeMap, } impl<'a, K, V> Cursor<'a, K, V> - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: BorshSerialize + BorshDeserialize, +where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, { fn asc(map: &'a TreeMap) -> Self { let key: Option = map.min(); - Self { - asc: true, - key, - lo: Bound::Unbounded, - hi: Bound::Unbounded, - map - } + Self { asc: true, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } } fn asc_from(map: &'a TreeMap, key: K) -> Self { let key = map.higher(&key); - Self { - asc: true, - key, - lo: Bound::Unbounded, - hi: Bound::Unbounded, - map - } + Self { asc: true, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } } fn desc(map: &'a TreeMap) -> Self { let key: Option = map.max(); - Self { - asc: false, - key, - lo: Bound::Unbounded, - hi: Bound::Unbounded, - map - } + Self { asc: false, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } } fn desc_from(map: &'a TreeMap, key: K) -> Self { let key = map.lower(&key); - Self { - asc: false, - key, - lo: Bound::Unbounded, - hi: Bound::Unbounded, - map - } + Self { asc: false, key, lo: Bound::Unbounded, hi: Bound::Unbounded, map } } fn range(map: &'a TreeMap, lo: Bound, hi: Bound) -> Self { let key = match &lo { Bound::Included(k) if map.contains_key(k) => Some(k.clone()), Bound::Included(k) | Bound::Excluded(k) => map.higher(k), - _ => None + _ => None, }; let key = key.filter(|k| fits(k, &lo, &hi)); - Self { - asc: true, - key, - lo, - hi, - map - } + Self { asc: true, key, lo, hi, map } } } @@ -747,21 +680,21 @@ impl<'a, K, V> Cursor<'a, K, V> #[cfg(test)] mod tests { use super::*; - use crate::test_utils::test_env; + use crate::test_utils::test_env::{self, next_trie_id}; extern crate rand; use self::rand::RngCore; - use serde::export::Formatter; use quickcheck::QuickCheck; - use std::fmt::{Debug, Result}; - use std::collections::HashSet; + use serde::export::Formatter; use std::collections::BTreeMap; + use std::collections::HashSet; + use std::fmt::{Debug, Result}; /// Return height of the tree - number of nodes on the longest path starting from the root node. fn height(tree: &TreeMap) -> u64 - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: BorshSerialize + BorshDeserialize, + where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: BorshSerialize + BorshDeserialize, { tree.node(tree.root).map(|n| n.ht).unwrap_or_default() } @@ -788,13 +721,13 @@ mod tests { const C: f64 = 1.440; const D: f64 = 1.065; - let h = C * log2( n as f64 + D ) + B; + let h = C * log2(n as f64 + D) + B; h.ceil() as u64 } impl Debug for Node - where - K: Ord + Clone + Debug + BorshSerialize + BorshDeserialize, + where + K: Ord + Clone + Debug + BorshSerialize + BorshDeserialize, { fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.debug_struct("Node") @@ -808,15 +741,14 @@ mod tests { } impl Debug for TreeMap - where - K: Ord + Clone + Debug + BorshSerialize + BorshDeserialize, - V: Debug + BorshSerialize + BorshDeserialize, + where + K: Ord + Clone + Debug + BorshSerialize + BorshDeserialize, + V: Debug + BorshSerialize + BorshDeserialize, { fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.debug_struct("TreeMap") .field("root", &self.root) .field("tree", &self.tree.iter().collect::>>()) - .field("val", &self.val.iter().collect::>()) .finish() } } @@ -840,7 +772,7 @@ mod tests { fn test_insert_3_rotate_l_l() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); assert_eq!(height(&map), 0); map.insert(&3, &3); @@ -863,7 +795,7 @@ mod tests { fn test_insert_3_rotate_r_r() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); assert_eq!(height(&map), 0); map.insert(&1, &1); @@ -886,12 +818,12 @@ mod tests { fn test_insert_lookup_n_asc() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let n: u64 = 30; - let cases = (0..2*(n as i32)).collect::>(); + let cases = (0..2 * (n as i32)).collect::>(); - let mut counter = 0; + let mut counter = 0; for k in &cases { if *k % 2 == 0 { counter += 1; @@ -917,12 +849,12 @@ mod tests { fn test_insert_lookup_n_desc() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let n: u64 = 30; - let cases = (0..2*(n as i32)).rev().collect::>(); + let cases = (0..2 * (n as i32)).rev().collect::>(); - let mut counter = 0; + let mut counter = 0; for k in &cases { if *k % 2 == 0 { counter += 1; @@ -948,8 +880,9 @@ mod tests { fn insert_n_random() { test_env::setup_free(); - for k in 1..10 { // tree size is 2^k - let mut map: TreeMap = TreeMap::default(); + for k in 1..10 { + // tree size is 2^k + let mut map: TreeMap = TreeMap::new(next_trie_id()); let n = 1 << k; let input: Vec = random(n); @@ -1003,14 +936,14 @@ mod tests { fn test_lower() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let vec: Vec = vec![10, 20, 30, 40, 50]; for x in vec.iter() { map.insert(x, &1); } - assert_eq!(map.lower( &5), None); + assert_eq!(map.lower(&5), None); assert_eq!(map.lower(&10), None); assert_eq!(map.lower(&11), Some(10)); assert_eq!(map.lower(&20), Some(10)); @@ -1025,14 +958,14 @@ mod tests { fn test_higher() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let vec: Vec = vec![10, 20, 30, 40, 50]; for x in vec.iter() { map.insert(x, &1); } - assert_eq!(map.higher( &5), Some(10)); + assert_eq!(map.higher(&5), Some(10)); assert_eq!(map.higher(&10), Some(20)); assert_eq!(map.higher(&11), Some(20)); assert_eq!(map.higher(&20), Some(30)); @@ -1047,14 +980,14 @@ mod tests { fn test_floor_key() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let vec: Vec = vec![10, 20, 30, 40, 50]; for x in vec.iter() { map.insert(x, &1); } - assert_eq!(map.floor_key( &5), None); + assert_eq!(map.floor_key(&5), None); assert_eq!(map.floor_key(&10), Some(10)); assert_eq!(map.floor_key(&11), Some(10)); assert_eq!(map.floor_key(&20), Some(20)); @@ -1069,14 +1002,14 @@ mod tests { fn test_ceil_key() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let vec: Vec = vec![10, 20, 30, 40, 50]; for x in vec.iter() { map.insert(x, &1); } - assert_eq!(map.ceil_key( &5), Some(10)); + assert_eq!(map.ceil_key(&5), Some(10)); assert_eq!(map.ceil_key(&10), Some(10)); assert_eq!(map.ceil_key(&11), Some(20)); assert_eq!(map.ceil_key(&20), Some(20)); @@ -1091,7 +1024,7 @@ mod tests { fn test_remove_1() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); map.insert(&1, &1); assert_eq!(map.get(&1), Some(1)); map.remove(&1); @@ -1104,7 +1037,7 @@ mod tests { fn test_remove_3() { test_env::setup(); - let map: TreeMap = avl(&[(0,0)], &[0,0,1]); + let map: TreeMap = avl(&[(0, 0)], &[0, 0, 1]); assert_eq!(map.iter().collect::>(), vec![]); } @@ -1114,7 +1047,7 @@ mod tests { test_env::setup(); let vec: Vec = vec![3, 2, 1]; - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1135,7 +1068,7 @@ mod tests { test_env::setup(); let vec: Vec = vec![1, 2, 3]; - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1155,9 +1088,9 @@ mod tests { fn test_remove_7_regression_1() { test_env::setup(); - let vec: Vec = vec![2104297040, 552624607, 4269683389, 3382615941, - 155419892, 4102023417, 1795725075]; - let mut map: TreeMap = TreeMap::default(); + let vec: Vec = + vec![2104297040, 552624607, 4269683389, 3382615941, 155419892, 4102023417, 1795725075]; + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1177,9 +1110,9 @@ mod tests { fn test_remove_7_regression_2() { test_env::setup(); - let vec: Vec = vec![700623085, 87488544, 1500140781, 1111706290, - 3187278102, 4042663151, 3731533080]; - let mut map: TreeMap = TreeMap::default(); + let vec: Vec = + vec![700623085, 87488544, 1500140781, 1111706290, 3187278102, 4042663151, 3731533080]; + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1199,9 +1132,11 @@ mod tests { fn test_remove_9_regression() { test_env::setup(); - let vec: Vec = vec![1186903464, 506371929, 1738679820, 1883936615, 1815331350, - 1512669683, 3581743264, 1396738166, 1902061760]; - let mut map: TreeMap = TreeMap::default(); + let vec: Vec = vec![ + 1186903464, 506371929, 1738679820, 1883936615, 1815331350, 1512669683, 3581743264, + 1396738166, 1902061760, + ]; + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1221,11 +1156,12 @@ mod tests { fn test_remove_20_regression_1() { test_env::setup(); - let vec: Vec = vec![552517392, 3638992158, 1015727752, 2500937532, 638716734, - 586360620, 2476692174, 1425948996, 3608478547, 757735878, - 2709959928, 2092169539, 3620770200, 783020918, 1986928932, - 200210441, 1972255302, 533239929, 497054557, 2137924638]; - let mut map: TreeMap = TreeMap::default(); + let vec: Vec = vec![ + 552517392, 3638992158, 1015727752, 2500937532, 638716734, 586360620, 2476692174, + 1425948996, 3608478547, 757735878, 2709959928, 2092169539, 3620770200, 783020918, + 1986928932, 200210441, 1972255302, 533239929, 497054557, 2137924638, + ]; + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1247,7 +1183,7 @@ mod tests { let vec: Vec = vec![280, 606, 163, 857, 436, 508, 44, 801]; - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { assert_eq!(map.get(x), None); @@ -1262,7 +1198,6 @@ mod tests { } assert_eq!(map.len(), 0, "map.len() > 0"); - assert_eq!(map.val.len(), 0, "map.val is not empty"); assert_eq!(map.tree.len(), 0, "map.tree is not empty"); map.clear(); } @@ -1273,7 +1208,7 @@ mod tests { let remove = vec![242, 687, 860, 811]; test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for (i, (k1, k2)) in insert.iter().zip(remove.iter()).enumerate() { let v = i as u32; @@ -1300,7 +1235,7 @@ mod tests { let vec = random(n); let mut set: HashSet = HashSet::new(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in &vec { map.insert(x, &1); set.insert(*x); @@ -1316,7 +1251,6 @@ mod tests { assert_eq!(map.len(), 0, "map.len() > 0"); assert_eq!(map.tree.len(), 0, "map.tree is not empty"); - assert_eq!(map.val.len(), 0, "map.val is not empty"); map.clear(); } @@ -1324,7 +1258,7 @@ mod tests { fn test_remove_root_3() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); map.insert(&2, &1); map.insert(&3, &1); map.insert(&1, &1); @@ -1346,7 +1280,7 @@ mod tests { let ins: Vec = vec![11760225, 611327897]; let rem: Vec = vec![2982517385, 1833990072]; - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); map.insert(&ins[0], &1); map.insert(&ins[1], &1); @@ -1362,7 +1296,7 @@ mod tests { #[test] fn test_insert_n_duplicates() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for x in 0..30 { map.insert(&x, &x); @@ -1371,7 +1305,6 @@ mod tests { assert_eq!(map.get(&42), Some(29)); assert_eq!(map.len(), 31); - assert_eq!(map.val.len(), 31); assert_eq!(map.tree.len(), 31); map.clear(); @@ -1382,7 +1315,7 @@ mod tests { test_env::setup(); for k in 1..4 { - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let mut set: HashSet = HashSet::new(); let n = 1 << k; @@ -1417,14 +1350,14 @@ mod tests { #[test] fn test_remove_empty() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); assert_eq!(map.remove(&1), None); } #[test] fn test_to_vec() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); map.insert(&1, &41); map.insert(&2, &42); map.insert(&3, &43); @@ -1436,14 +1369,14 @@ mod tests { #[test] fn test_to_vec_empty() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); assert!(map.to_vec().is_empty()); } #[test] fn test_iter() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); map.insert(&1, &41); map.insert(&2, &42); map.insert(&3, &43); @@ -1455,14 +1388,14 @@ mod tests { #[test] fn test_iter_empty() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); assert!(map.iter().collect::>().is_empty()); } #[test] fn test_iter_rev() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); map.insert(&1, &41); map.insert(&2, &42); map.insert(&3, &43); @@ -1474,14 +1407,14 @@ mod tests { #[test] fn test_iter_rev_empty() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); assert!(map.iter_rev().collect::>().is_empty()); } #[test] fn test_iter_from() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let one: Vec = vec![10, 20, 30, 40, 50]; let two: Vec = vec![45, 35, 25, 15, 5]; @@ -1496,29 +1429,32 @@ mod tests { assert_eq!( map.iter_from(29).collect::>(), - vec![(30, 42), (35, 42), (40, 42), (45, 42), (50, 42)]); + vec![(30, 42), (35, 42), (40, 42), (45, 42), (50, 42)] + ); assert_eq!( map.iter_from(30).collect::>(), - vec![(35, 42), (40, 42), (45, 42), (50, 42)]); + vec![(35, 42), (40, 42), (45, 42), (50, 42)] + ); assert_eq!( map.iter_from(31).collect::>(), - vec![(35, 42), (40, 42), (45, 42), (50, 42)]); + vec![(35, 42), (40, 42), (45, 42), (50, 42)] + ); map.clear(); } #[test] fn test_iter_from_empty() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); assert!(map.iter_from(42).collect::>().is_empty()); } #[test] fn test_iter_rev_from() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let one: Vec = vec![10, 20, 30, 40, 50]; let two: Vec = vec![45, 35, 25, 15, 5]; @@ -1533,22 +1469,25 @@ mod tests { assert_eq!( map.iter_rev_from(29).collect::>(), - vec![(25, 42), (20, 42), (15, 42), (10, 42), (5, 42)]); + vec![(25, 42), (20, 42), (15, 42), (10, 42), (5, 42)] + ); assert_eq!( map.iter_rev_from(30).collect::>(), - vec![(25, 42), (20, 42), (15, 42), (10, 42), (5, 42)]); + vec![(25, 42), (20, 42), (15, 42), (10, 42), (5, 42)] + ); assert_eq!( map.iter_rev_from(31).collect::>(), - vec![(30, 42), (25, 42), (20, 42), (15, 42), (10, 42), (5, 42)]); + vec![(30, 42), (25, 42), (20, 42), (15, 42), (10, 42), (5, 42)] + ); map.clear(); } #[test] fn test_range() { test_env::setup(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); let one: Vec = vec![10, 20, 30, 40, 50]; let two: Vec = vec![45, 35, 25, 15, 5]; @@ -1563,35 +1502,43 @@ mod tests { assert_eq!( map.range((Bound::Included(20), Bound::Excluded(30))).collect::>(), - vec![(20, 42), (25, 42)]); + vec![(20, 42), (25, 42)] + ); assert_eq!( map.range((Bound::Excluded(10), Bound::Included(40))).collect::>(), - vec![(15, 42), (20, 42), (25, 42), (30, 42), (35, 42), (40, 42)]); + vec![(15, 42), (20, 42), (25, 42), (30, 42), (35, 42), (40, 42)] + ); assert_eq!( map.range((Bound::Included(20), Bound::Included(40))).collect::>(), - vec![(20, 42), (25, 42), (30, 42), (35, 42), (40, 42)]); + vec![(20, 42), (25, 42), (30, 42), (35, 42), (40, 42)] + ); assert_eq!( map.range((Bound::Excluded(20), Bound::Excluded(45))).collect::>(), - vec![(25, 42), (30, 42), (35, 42), (40, 42)]); + vec![(25, 42), (30, 42), (35, 42), (40, 42)] + ); assert_eq!( map.range((Bound::Excluded(20), Bound::Excluded(45))).collect::>(), - vec![(25, 42), (30, 42), (35, 42), (40, 42)]); + vec![(25, 42), (30, 42), (35, 42), (40, 42)] + ); assert_eq!( map.range((Bound::Excluded(25), Bound::Excluded(30))).collect::>(), - vec![]); + vec![] + ); assert_eq!( map.range((Bound::Included(25), Bound::Included(25))).collect::>(), - vec![(25, 42)]); + vec![(25, 42)] + ); assert_eq!( map.range((Bound::Excluded(25), Bound::Included(25))).collect::>(), - vec![]); // the range makes no sense, but `BTreeMap` does not panic in this case + vec![] + ); // the range makes no sense, but `BTreeMap` does not panic in this case map.clear(); } @@ -1600,7 +1547,7 @@ mod tests { #[should_panic(expected = "Invalid range.")] fn test_range_panics_same_excluded() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); let _ = map.range((Bound::Excluded(1), Bound::Excluded(1))); } @@ -1608,7 +1555,7 @@ mod tests { #[should_panic(expected = "Invalid range.")] fn test_range_panics_non_overlap_incl_exlc() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); let _ = map.range((Bound::Included(2), Bound::Excluded(1))); } @@ -1616,7 +1563,7 @@ mod tests { #[should_panic(expected = "Invalid range.")] fn test_range_panics_non_overlap_excl_incl() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); let _ = map.range((Bound::Excluded(2), Bound::Included(1))); } @@ -1624,14 +1571,14 @@ mod tests { #[should_panic(expected = "Invalid range.")] fn test_range_panics_non_overlap_incl_incl() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); let _ = map.range((Bound::Included(2), Bound::Included(1))); } #[test] fn test_iter_rev_from_empty() { test_env::setup(); - let map: TreeMap = TreeMap::default(); + let map: TreeMap = TreeMap::new(next_trie_id()); assert!(map.iter_rev_from(42).collect::>().is_empty()); } @@ -1658,12 +1605,12 @@ mod tests { // fn avl(insert: &[(K, V)], remove: &[K]) -> TreeMap - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: Default + BorshSerialize + BorshDeserialize, + where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: Default + BorshSerialize + BorshDeserialize, { test_env::setup_free(); - let mut map: TreeMap = TreeMap::default(); + let mut map: TreeMap = TreeMap::new(next_trie_id()); for k in remove { map.insert(k, &Default::default()); } @@ -1681,9 +1628,9 @@ mod tests { } fn rb(insert: &[(K, V)], remove: &[K]) -> BTreeMap - where - K: Ord + Clone + BorshSerialize + BorshDeserialize, - V: Clone + Default + BorshSerialize + BorshDeserialize, + where + K: Ord + Clone + BorshSerialize + BorshDeserialize, + V: Clone + Default + BorshSerialize + BorshDeserialize, { let mut map: BTreeMap = BTreeMap::default(); for k in remove { @@ -1718,16 +1665,16 @@ mod tests { } fn is_balanced(map: &TreeMap, root: u64) -> bool - where - K: Debug + Ord + Clone + BorshSerialize + BorshDeserialize, - V: Debug + BorshSerialize + BorshDeserialize, + where + K: Debug + Ord + Clone + BorshSerialize + BorshDeserialize, + V: Debug + BorshSerialize + BorshDeserialize, { let node = map.node(root).unwrap(); let balance = map.get_balance(&node); - (balance >= -1 && balance <= 1) && - node.lft.map(|id| is_balanced(map, id)).unwrap_or(true) && - node.rgt.map(|id| is_balanced(map, id)).unwrap_or(true) + (balance >= -1 && balance <= 1) + && node.lft.map(|id| is_balanced(map, id)).unwrap_or(true) + && node.rgt.map(|id| is_balanced(map, id)).unwrap_or(true) } #[test] @@ -1758,13 +1705,15 @@ mod tests { .quickcheck(prop as fn(std::vec::Vec<(u32, u32)>, std::vec::Vec) -> bool); } - fn range_prop(insert: Vec<(u32, u32)>, remove: Vec, range: (Bound, Bound)) -> bool { + fn range_prop( + insert: Vec<(u32, u32)>, + remove: Vec, + range: (Bound, Bound), + ) -> bool { let a = avl(&insert, &remove); let b = rb(&insert, &remove); let v1: Vec<(u32, u32)> = a.range(range).collect(); - let v2: Vec<(u32, u32)> = b.range(range) - .map(|(k, v)| (*k, *v)) - .collect(); + let v2: Vec<(u32, u32)> = b.range(range).map(|(k, v)| (*k, *v)).collect(); v1 == v2 } @@ -1777,9 +1726,7 @@ mod tests { range_prop(insert, remove, range) } - QuickCheck::new() - .tests(300) - .quickcheck(prop as Prop); + QuickCheck::new().tests(300).quickcheck(prop as Prop); } #[test] @@ -1789,9 +1736,7 @@ mod tests { range_prop(insert, remove, range) } - QuickCheck::new() - .tests(300) - .quickcheck(prop as Prop); + QuickCheck::new().tests(300).quickcheck(prop as Prop); } #[test] @@ -1801,9 +1746,7 @@ mod tests { range_prop(insert, remove, range) } - QuickCheck::new() - .tests(300) - .quickcheck(prop as Prop); + QuickCheck::new().tests(300).quickcheck(prop as Prop); } #[test] @@ -1816,8 +1759,6 @@ mod tests { } } - QuickCheck::new() - .tests(300) - .quickcheck(prop as Prop); + QuickCheck::new().tests(300).quickcheck(prop as Prop); } } diff --git a/near-sdk/src/collections/unordered_map.rs b/near-sdk/src/collections/unordered_map.rs index 5bfe28bbe..2133de31a 100644 --- a/near-sdk/src/collections/unordered_map.rs +++ b/near-sdk/src/collections/unordered_map.rs @@ -1,6 +1,6 @@ //! A map implemented on a trie. Unlike `std::collections::HashMap` the keys in this map are not //! hashed but are instead serialized. -use crate::collections::{append, append_slice, next_trie_id, Vector}; +use crate::collections::{append, append_slice, Vector}; use crate::env; use borsh::{BorshDeserialize, BorshSerialize}; use std::mem::size_of; @@ -18,12 +18,6 @@ pub struct UnorderedMap { values: Vector, } -impl Default for UnorderedMap { - fn default() -> Self { - Self::new(next_trie_id()) - } -} - impl UnorderedMap { /// Returns the number of elements in the map, also referred to as its size. pub fn len(&self) -> u64 { @@ -255,7 +249,7 @@ mod tests { #[test] pub fn test_insert() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); for _ in 0..500 { let key = rng.gen::(); @@ -267,7 +261,7 @@ mod tests { #[test] pub fn test_insert_remove() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(1); let mut keys = vec![]; let mut key_to_value = HashMap::new(); @@ -288,7 +282,7 @@ mod tests { #[test] pub fn test_remove_last_reinsert() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let key1 = 1u64; let value1 = 2u64; map.insert(&key1, &value1); @@ -306,7 +300,7 @@ mod tests { #[test] pub fn test_insert_override_remove() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(2); let mut keys = vec![]; let mut key_to_value = HashMap::new(); @@ -334,7 +328,7 @@ mod tests { #[test] pub fn test_get_non_existent() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(3); let mut key_to_value = HashMap::new(); for _ in 0..500 { @@ -352,7 +346,7 @@ mod tests { #[test] pub fn test_to_vec() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut key_to_value = HashMap::new(); for _ in 0..400 { @@ -368,7 +362,7 @@ mod tests { #[test] pub fn test_clear() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(5); for _ in 0..10 { for _ in 0..=(rng.gen::() % 20 + 1) { @@ -385,7 +379,7 @@ mod tests { #[test] pub fn test_keys_values() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut key_to_value = HashMap::new(); for _ in 0..400 { @@ -408,7 +402,7 @@ mod tests { #[test] pub fn test_iter() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut key_to_value = HashMap::new(); for _ in 0..400 { @@ -424,7 +418,7 @@ mod tests { #[test] pub fn test_extend() { test_env::setup(); - let mut map = UnorderedMap::default(); + let mut map = UnorderedMap::new(b"m".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut key_to_value = HashMap::new(); for _ in 0..100 { diff --git a/near-sdk/src/collections/set.rs b/near-sdk/src/collections/unordered_set.rs similarity index 94% rename from near-sdk/src/collections/set.rs rename to near-sdk/src/collections/unordered_set.rs index 7e25fb587..eb5bcbd2e 100644 --- a/near-sdk/src/collections/set.rs +++ b/near-sdk/src/collections/unordered_set.rs @@ -1,6 +1,6 @@ //! A set implemented on a trie. Unlike `std::collections::HashSet` the elements in this set are not //! hashed but are instead serialized. -use crate::collections::{append, append_slice, next_trie_id, Vector}; +use crate::collections::{append, append_slice, Vector}; use crate::env; use borsh::{BorshDeserialize, BorshSerialize}; use std::mem::size_of; @@ -15,12 +15,6 @@ pub struct UnorderedSet { elements: Vector, } -impl Default for UnorderedSet { - fn default() -> Self { - Self::new(next_trie_id()) - } -} - impl UnorderedSet { /// Returns the number of elements in the set, also referred to as its size. pub fn len(&self) -> u64 { @@ -185,7 +179,7 @@ mod tests { #[test] pub fn test_insert() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); for _ in 0..500 { let key = rng.gen::(); @@ -196,7 +190,7 @@ mod tests { #[test] pub fn test_insert_remove() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(1); let mut keys = vec![]; for _ in 0..100 { @@ -213,7 +207,7 @@ mod tests { #[test] pub fn test_remove_last_reinsert() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let key1 = 1u64; set.insert(&key1); let key2 = 2u64; @@ -229,7 +223,7 @@ mod tests { #[test] pub fn test_insert_override_remove() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(2); let mut keys = vec![]; for _ in 0..100 { @@ -250,7 +244,7 @@ mod tests { #[test] pub fn test_contains_non_existent() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(3); let mut set_tmp = HashSet::new(); for _ in 0..500 { @@ -267,7 +261,7 @@ mod tests { #[test] pub fn test_to_vec() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut keys = HashSet::new(); for _ in 0..500 { @@ -282,7 +276,7 @@ mod tests { #[test] pub fn test_clear() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(5); for _ in 0..10 { for _ in 0..=(rng.gen::() % 20 + 1) { @@ -298,7 +292,7 @@ mod tests { #[test] pub fn test_iter() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut keys = HashSet::new(); for _ in 0..500 { @@ -313,7 +307,7 @@ mod tests { #[test] pub fn test_extend() { test_env::setup(); - let mut set = UnorderedSet::default(); + let mut set = UnorderedSet::new(b"s".to_vec()); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); let mut keys = HashSet::new(); for _ in 0..100 { diff --git a/near-sdk/src/collections/vector.rs b/near-sdk/src/collections/vector.rs index 3f1a755bb..2e64b44b2 100644 --- a/near-sdk/src/collections/vector.rs +++ b/near-sdk/src/collections/vector.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; use borsh::{BorshDeserialize, BorshSerialize}; -use crate::collections::{append_slice, next_trie_id}; +use crate::collections::append_slice; use crate::env; const ERR_INCONSISTENT_STATE: &[u8] = b"The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; @@ -253,74 +253,20 @@ impl std::fmt::Debug for Vector { } } -impl Default for Vector { - fn default() -> Self { - Self::new(next_trie_id()) - } -} - #[cfg(not(target_arch = "wasm32"))] #[cfg(test)] mod tests { use borsh::BorshDeserialize; use rand::{Rng, SeedableRng}; - use near_vm_logic::types::AccountId; - use near_vm_logic::VMContext; - - use crate::collections::{next_trie_id, Vector}; - use crate::{env, MockedBlockchain}; - - fn alice() -> AccountId { - "alice.near".to_string() - } - - fn bob() -> AccountId { - "bob.near".to_string() - } - - fn carol() -> AccountId { - "carol.near".to_string() - } - - fn set_env() { - let context = VMContext { - current_account_id: alice(), - signer_account_id: bob(), - signer_account_pk: vec![0, 1, 2], - predecessor_account_id: carol(), - input: vec![], - block_index: 0, - block_timestamp: 0, - account_balance: 0, - account_locked_balance: 0, - storage_usage: 10u64.pow(6), - attached_deposit: 0, - prepaid_gas: 10u64.pow(18), - random_seed: vec![0, 1, 2], - is_view: false, - output_data_receivers: vec![], - epoch_height: 0, - }; - let storage = match env::take_blockchain_interface() { - Some(mut bi) => bi.as_mut_mocked_blockchain().unwrap().take_storage(), - None => Default::default(), - }; - env::set_blockchain_interface(Box::new(MockedBlockchain::new( - context, - Default::default(), - Default::default(), - vec![], - storage, - Default::default(), - ))); - } + use crate::collections::Vector; + use crate::test_utils::test_env; #[test] fn test_push_pop() { - set_env(); + test_env::setup(); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); - let mut vec = Vector::default(); + let mut vec = Vector::new(b"v".to_vec()); let mut baseline = vec![]; for _ in 0..500 { let value = rng.gen::(); @@ -336,9 +282,9 @@ mod tests { #[test] pub fn test_replace() { - set_env(); + test_env::setup(); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(1); - let mut vec = Vector::default(); + let mut vec = Vector::new(b"v".to_vec()); let mut baseline = vec![]; for _ in 0..500 { let value = rng.gen::(); @@ -361,9 +307,9 @@ mod tests { #[test] pub fn test_swap_remove() { - set_env(); + test_env::setup(); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(2); - let mut vec = Vector::default(); + let mut vec = Vector::new(b"v".to_vec()); let mut baseline = vec![]; for _ in 0..500 { let value = rng.gen::(); @@ -387,9 +333,9 @@ mod tests { #[test] pub fn test_clear() { - set_env(); + test_env::setup(); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(3); - let mut vec = Vector::default(); + let mut vec = Vector::new(b"v".to_vec()); for _ in 0..100 { for _ in 0..(rng.gen::() % 20 + 1) { let value = rng.gen::(); @@ -403,9 +349,9 @@ mod tests { #[test] pub fn test_extend() { - set_env(); + test_env::setup(); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); - let mut vec = Vector::default(); + let mut vec = Vector::new(b"v".to_vec()); let mut baseline = vec![]; for _ in 0..100 { let value = rng.gen::(); @@ -428,9 +374,9 @@ mod tests { #[test] fn test_debug() { - set_env(); + test_env::setup(); let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4); - let prefix = next_trie_id(); + let prefix = b"v".to_vec(); let mut vec = Vector::new(prefix.clone()); let mut baseline = vec![]; for _ in 0..10 { diff --git a/near-sdk/src/test_utils/mod.rs b/near-sdk/src/test_utils/mod.rs index 7457d0afa..f5209ac27 100644 --- a/near-sdk/src/test_utils/mod.rs +++ b/near-sdk/src/test_utils/mod.rs @@ -1,7 +1,19 @@ pub(crate) mod test_env { use crate::{env, MockedBlockchain}; use near_vm_logic::types::AccountId; - use near_vm_logic::{VMContext, VMConfig}; + use near_vm_logic::{VMConfig, VMContext}; + + /// Objects stored on the trie directly should have identifiers. If identifier is not provided + /// explicitly than `Default` trait would use this index to generate an id. + pub(crate) static mut NEXT_TRIE_OBJECT_INDEX: u64 = 0; + /// Get next id of the object stored on trie. + pub(crate) fn next_trie_id() -> Vec { + unsafe { + let id = NEXT_TRIE_OBJECT_INDEX; + NEXT_TRIE_OBJECT_INDEX += 1; + id.to_le_bytes().to_vec() + } + } fn alice() -> AccountId { "alice.near".to_string() @@ -44,7 +56,7 @@ pub(crate) mod test_env { Default::default(), vec![], storage, - Default::default() + Default::default(), ))); }