diff --git a/sdk/rust/Cargo.lock b/sdk/rust/Cargo.lock index 409935d77..901dc0d67 100644 --- a/sdk/rust/Cargo.lock +++ b/sdk/rust/Cargo.lock @@ -2,85 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.6", - "once_cell", - "version_check", -] - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - -[[package]] -name = "blake3" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", - "digest 0.10.3", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -91,437 +12,36 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array", -] - [[package]] name = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" -[[package]] -name = "borsh" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" -dependencies = [ - "borsh-derive", - "hashbrown", -] - -[[package]] -name = "borsh-derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate", - "proc-macro2", - "syn", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bstr" -version = "0.2.17" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd" dependencies = [ - "lazy_static", "memchr", + "once_cell", "regex-automata", -] - -[[package]] -name = "bumpalo" -version = "3.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "bv" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" -dependencies = [ - "feature-probe", "serde", ] -[[package]] -name = "bytemuck" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "console_log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" -dependencies = [ - "log", - "web-sys", -] - -[[package]] -name = "const-oid" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "cosmwasm-crypto" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec9bdd1f4da5fc0d085251b0322661c5aaf773ab299e3e205fb18130b7f6ba3" -dependencies = [ - "digest 0.9.0", - "ed25519-zebra", - "k256", - "rand_core 0.5.1", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac17a14b4ab09a5d89b5301218067acca33d9311376e5c34c9877f09e562395" -dependencies = [ - "syn", -] - -[[package]] -name = "cosmwasm-std" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47306c113f4d964c35a74a87ceb8ccfb5811e9810a9dc427101148b5b9134ca" -dependencies = [ - "base64 0.13.0", - "cosmwasm-crypto", - "cosmwasm-derive", - "schemars", - "serde", - "serde-json-wasm", - "thiserror", - "uint", -] - -[[package]] -name = "cosmwasm-storage" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e3472d8e0e7155c5f4d89674ad47adede4b1491ad14f4141610e1522028a6a7" -dependencies = [ - "cosmwasm-std", - "serde", -] - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "once_cell", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" -dependencies = [ - "cfg-if", - "once_cell", -] - [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-bigint" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" -dependencies = [ - "generic-array", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cw-storage-plus" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e867b9972b83b32e00e878dfbff48299ba26618dabeb19b9c56fae176dc225" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw0" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c497f885a40918a02df7d938c81809965fa05cfc21b3dc591e9950237b5de0a9" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d48454f96494aa1018556cd457977375cc8c57ef3e5c767cfa2ea5ec24b0258" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - -[[package]] -name = "cw20" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a11a2adbd52258f5b4ed5323f62bc6e559f2cefbe52ef0e58290016fde5bb083" -dependencies = [ - "cosmwasm-std", - "cw0", - "schemars", - "serde", -] - -[[package]] -name = "cw20-base" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3791e0f6b4a0a82b86541d48dcc67c2d607da8e5691a91b40b2c06ddf09c52" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "cw0", - "cw2", - "cw20", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw20-legacy" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d27b11827323369993519abb494f3ae9b6aac4d716d058bea5e181b9b0074b7" -dependencies = [ - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus", - "cw0", - "cw2", - "cw20", - "cw20-base", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw20-wrapped" -version = "0.1.0" -dependencies = [ - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus", - "cw2", - "cw20", - "cw20-legacy", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "der" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e98c534e9c8a0483aa01d6f6913bc063de254311bd267c9cf535e9b70e15b2" -dependencies = [ - "const-oid", -] - [[package]] name = "digest" version = "0.9.0" @@ -531,87 +51,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", - "crypto-common", - "subtle", -] - -[[package]] -name = "dyn-clone" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" - -[[package]] -name = "ecdsa" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" -dependencies = [ - "der", - "elliptic-curve", - "hmac 0.11.0", - "signature", -] - -[[package]] -name = "ed25519-zebra" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" -dependencies = [ - "curve25519-dalek", - "hex", - "rand_core 0.5.1", - "serde", - "sha2 0.9.9", - "thiserror", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "elliptic-curve" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" -dependencies = [ - "crypto-bigint", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "feature-probe" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" - -[[package]] -name = "ff" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" -dependencies = [ - "rand_core 0.6.3", - "subtle", -] - [[package]] name = "fixed-hash" version = "0.7.0" @@ -623,265 +62,37 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ - "serde", "typenum", "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "group" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" -dependencies = [ - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac 0.11.1", - "digest 0.9.0", -] - -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] - -[[package]] -name = "im" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" -dependencies = [ - "bitmaps", - "rand_core 0.6.3", - "rand_xoshiro", - "rayon", - "serde", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "js-sys" -version = "0.3.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "k256" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sha2 0.9.9", -] +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.122" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" - -[[package]] -name = "libsecp256k1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" -dependencies = [ - "arrayref", - "base64 0.12.3", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand", - "serde", - "sha2 0.9.9", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "lock_api" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" -dependencies = [ - "cfg-if", -] +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "memmap2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "minimal-lexical" @@ -899,41 +110,11 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "once_cell" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "opaque-debug" @@ -941,45 +122,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "pkcs8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - [[package]] name = "primitive-types" version = "0.9.1" @@ -990,232 +132,53 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.6", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.3", -] - -[[package]] -name = "rayon" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" -dependencies = [ - "bitflags", -] - [[package]] name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -[[package]] -name = "rocksalt" -version = "0.1.0" -dependencies = [ - "byteorder", - "proc-macro2", - "quote", - "sha3 0.9.1", - "solana-program", - "syn", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[package]] -name = "schemars" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" - [[package]] name = "serde" -version = "1.0.136" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-json-wasm" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449" -dependencies = [ - "serde", -] - [[package]] name = "serde_bytes" -version = "0.11.5" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -1223,10 +186,10 @@ dependencies = [ ] [[package]] -name = "serde_derive_internals" -version = "0.26.0" +name = "serde_repr" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ "proc-macro2", "quote", @@ -1234,38 +197,14 @@ dependencies = [ ] [[package]] -name = "serde_json" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +name = "serde_wormhole" +version = "0.1.0" dependencies = [ "itoa", - "ryu", "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.3", + "serde_bytes", + "serde_repr", + "thiserror", ] [[package]] @@ -1274,209 +213,49 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", + "block-buffer", + "digest", "keccak", "opaque-debug", ] -[[package]] -name = "sha3" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaedf34ed289ea47c2b741bb72e5357a209512d67bcd4bda44359e5bf0470f56" -dependencies = [ - "digest 0.10.3", - "keccak", -] - -[[package]] -name = "signature" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4" -dependencies = [ - "digest 0.9.0", - "rand_core 0.6.3", -] - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", -] - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "solana-frozen-abi" -version = "1.10.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2b153f8eb8c4d22f2b739d3d31bac4122ca17376869cb717bf3a45200ea63" -dependencies = [ - "bs58", - "bv", - "generic-array", - "im", - "lazy_static", - "log", - "memmap2", - "rustc_version", - "serde", - "serde_bytes", - "serde_derive", - "sha2 0.10.5", - "solana-frozen-abi-macro", - "thiserror", -] - -[[package]] -name = "solana-frozen-abi-macro" -version = "1.10.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cd23aad847403a28dd1452611490b5e8f040470ed251882cca0492c5e566280" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn", -] - -[[package]] -name = "solana-program" -version = "1.10.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37be82a1fe85b24aa036153650053fd9628489c07c834b6b2dc027c4052bdbe5" -dependencies = [ - "base64 0.13.0", - "bincode", - "bitflags", - "blake3", - "borsh", - "borsh-derive", - "bs58", - "bv", - "bytemuck", - "console_error_panic_hook", - "console_log", - "curve25519-dalek", - "getrandom 0.1.16", - "itertools", - "js-sys", - "lazy_static", - "libsecp256k1", - "log", - "num-derive", - "num-traits", - "parking_lot", - "rand", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "sha2 0.10.5", - "sha3 0.10.4", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-sdk-macro", - "thiserror", - "wasm-bindgen", -] - -[[package]] -name = "solana-sdk-macro" -version = "1.10.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "275c52edaaaa86ce649a226c03f75579d570c01880a43ee1de77a973994754ce" -dependencies = [ - "bs58", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - -[[package]] -name = "solitaire" -version = "0.1.0" -dependencies = [ - "borsh", - "byteorder", - "rocksalt", - "sha3 0.9.1", - "solana-program", -] - -[[package]] -name = "spki" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" -dependencies = [ - "der", -] - [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - [[package]] name = "syn" -version = "1.0.91" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - [[package]] name = "typenum" version = "1.15.0" @@ -1485,9 +264,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "uint" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" +checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" dependencies = [ "byteorder", "crunchy", @@ -1496,10 +275,10 @@ dependencies = [ ] [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "unicode-ident" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "version_check" @@ -1507,158 +286,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" - -[[package]] -name = "web-sys" -version = "0.3.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "wormhole-bridge-solana" -version = "0.1.0" -dependencies = [ - "borsh", - "byteorder", - "primitive-types", - "serde", - "sha3 0.9.1", - "solana-program", - "solitaire", -] - -[[package]] -name = "wormhole-bridge-terra" -version = "0.1.0" -dependencies = [ - "cosmwasm-std", - "cosmwasm-storage", - "cw20", - "cw20-base", - "cw20-wrapped", - "generic-array", - "getrandom 0.2.6", - "hex", - "k256", - "lazy_static", - "schemars", - "serde", - "sha3 0.9.1", - "thiserror", -] - [[package]] name = "wormhole-core" version = "0.1.0" @@ -1668,30 +295,5 @@ dependencies = [ "hex", "nom", "primitive-types", - "sha3 0.9.1", + "sha3", ] - -[[package]] -name = "wormhole-sdk" -version = "0.1.0" -dependencies = [ - "borsh", - "byteorder", - "cosmwasm-std", - "cosmwasm-storage", - "hex", - "nom", - "primitive-types", - "schemars", - "serde", - "solana-program", - "wormhole-bridge-solana", - "wormhole-bridge-terra", - "wormhole-core", -] - -[[package]] -name = "zeroize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml index 101870222..5ee98fe83 100644 --- a/sdk/rust/Cargo.toml +++ b/sdk/rust/Cargo.toml @@ -1,9 +1,12 @@ [workspace] members = [ - "core", - "sdk" + "core/", + "serde_wormhole", ] [profile.release] opt-level = 3 lto = "thin" + +[patch.crates-io] +serde_wormhole = { path = "serde_wormhole" } diff --git a/sdk/rust/serde_wormhole/Cargo.toml b/sdk/rust/serde_wormhole/Cargo.toml new file mode 100644 index 000000000..e739f12fb --- /dev/null +++ b/sdk/rust/serde_wormhole/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "serde_wormhole" +version = "0.1.0" +edition = "2021" +description = "Serde data format for VAA payloads" + +[dependencies] +itoa = "1.0.1" +serde = { version = "1.0.103", default-features = false } +thiserror = "1.0" + +[dev-dependencies] +serde = { version = "1.0.103", default-features = false, features = ["alloc", "derive"] } +serde_bytes = "0.11.5" +serde_repr = "0.1.7" \ No newline at end of file diff --git a/sdk/rust/serde_wormhole/src/de.rs b/sdk/rust/serde_wormhole/src/de.rs new file mode 100644 index 000000000..6410713ce --- /dev/null +++ b/sdk/rust/serde_wormhole/src/de.rs @@ -0,0 +1,910 @@ +use std::{convert::TryFrom, mem::size_of}; + +use serde::de::{ + self, DeserializeSeed, EnumAccess, Error as DeError, IntoDeserializer, MapAccess, SeqAccess, + Unexpected, VariantAccess, Visitor, +}; + +use crate::error::Error; + +/// A struct that deserializes the VAA payload wire format into rust values. +pub struct Deserializer<'de> { + input: &'de [u8], +} + +impl<'de> Deserializer<'de> { + /// Construct a new instance of `Deserializer` from `input`. + pub fn new(input: &'de [u8]) -> Self { + Self { input } + } + + /// Should be called once the value has been fully deserialized. Returns any data left in the + /// input buffer after deserialization. + pub fn end(self) -> &'de [u8] { + self.input + } +} + +// This has to be a macro because `::from_be_bytes` is not a trait function so there is no +// trait bound that we can use in a generic function. +macro_rules! deserialize_be_number { + ($self:ident, $ty:ty) => {{ + const LEN: usize = size_of::<$ty>(); + if $self.input.len() < LEN { + return Err(Error::Eof); + } + + let (data, rem) = $self.input.split_at(LEN); + let mut buf = [0u8; LEN]; + buf.copy_from_slice(data); + $self.input = rem; + + <$ty>::from_be_bytes(buf) + }}; +} + +impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { + type Error = Error; + + fn deserialize_any(self, _: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::DeserializeAnyNotSupported) + } + + fn deserialize_ignored_any(self, _: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::DeserializeAnyNotSupported) + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let v = deserialize_be_number!(self, u8); + match v { + 0 => visitor.visit_bool(false), + 1 => visitor.visit_bool(true), + v => Err(Error::invalid_value( + Unexpected::Unsigned(v.into()), + &"a 0 or 1", + )), + } + } + + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i8(deserialize_be_number!(self, i8)) + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i16(deserialize_be_number!(self, i16)) + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i32(deserialize_be_number!(self, i32)) + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i64(deserialize_be_number!(self, i64)) + } + + fn deserialize_i128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i128(deserialize_be_number!(self, i128)) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u8(deserialize_be_number!(self, u8)) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u16(deserialize_be_number!(self, u16)) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u32(deserialize_be_number!(self, u32)) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u64(deserialize_be_number!(self, u64)) + } + + fn deserialize_u128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u128(deserialize_be_number!(self, u128)) + } + + fn deserialize_f32(self, _: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::Unsupported) + } + + fn deserialize_f64(self, _: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::Unsupported) + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let v = deserialize_be_number!(self, u32); + char::try_from(v) + .map_err(|_| Error::invalid_value(Unexpected::Unsigned(v.into()), &"a `char`")) + .and_then(|v| visitor.visit_char(v)) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = usize::from(deserialize_be_number!(self, u8)); + + if self.input.len() < len { + return Err(Error::Eof); + } + + let (data, rem) = self.input.split_at(len); + self.input = rem; + + std::str::from_utf8(data) + .map_err(|_| Error::invalid_value(Unexpected::Bytes(data), &"a UTF-8 string")) + .and_then(|s| visitor.visit_borrowed_str(s)) + } + + #[inline] + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = usize::from(deserialize_be_number!(self, u8)); + + if self.input.len() < len { + return Err(Error::Eof); + } + + let (data, rem) = self.input.split_at(len); + self.input = rem; + + visitor.visit_borrowed_bytes(data) + } + + #[inline] + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_bytes(visitor) + } + + #[inline] + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // There are no optional values in this data format. + visitor.visit_some(self) + } + + #[inline] + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_unit() + } + + #[inline] + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_unit() + } + + #[inline] + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = usize::from(deserialize_be_number!(self, u8)); + visitor.visit_seq(BoundedSequence::new(self, len)) + } + + #[inline] + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_seq(BoundedSequence::new(self, len)) + } + + #[inline] + fn deserialize_tuple_struct( + self, + _name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_seq(BoundedSequence::new(self, len)) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = usize::from(deserialize_be_number!(self, u8)); + visitor.visit_map(BoundedSequence::new(self, len)) + } + + #[inline] + fn deserialize_struct( + self, + _name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_seq(BoundedSequence::new(self, fields.len())) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let variant = deserialize_be_number!(self, u8); + visitor.visit_enum(Enum { de: self, variant }) + } + + fn deserialize_identifier(self, _: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::Unsupported) + } +} + +impl<'de, 'a> VariantAccess<'de> for &'a mut Deserializer<'de> { + type Error = Error; + + #[inline] + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + #[inline] + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + seed.deserialize(self) + } + + #[inline] + fn tuple_variant(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_seq(BoundedSequence::new(self, len)) + } + + #[inline] + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_seq(BoundedSequence::new(self, fields.len())) + } +} + +struct BoundedSequence<'de, 'a> { + de: &'a mut Deserializer<'de>, + count: usize, +} + +impl<'de, 'a> BoundedSequence<'de, 'a> { + fn new(de: &'a mut Deserializer<'de>, count: usize) -> Self { + Self { de, count } + } +} + +impl<'de, 'a> SeqAccess<'de> for BoundedSequence<'de, 'a> { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + if self.count == 0 { + return Ok(None); + } + + self.count -= 1; + seed.deserialize(&mut *self.de).map(Some) + } + + #[inline] + fn size_hint(&self) -> Option { + Some(self.count) + } +} + +impl<'de, 'a> MapAccess<'de> for BoundedSequence<'de, 'a> { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: DeserializeSeed<'de>, + { + if self.count == 0 { + return Ok(None); + } + + self.count -= 1; + seed.deserialize(&mut *self.de).map(Some) + } + + #[inline] + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, + { + seed.deserialize(&mut *self.de) + } + + #[inline] + fn size_hint(&self) -> Option { + Some(self.count) + } +} + +/// Tells serde which enum variant it should deserialize. Enums are encoded in the byte stream as a +/// `u8` followed by the data for the variant but unfortunately, serde doesn't currently support +/// integer tags (see https://github.com/serde-rs/serde/issues/745). Instead we format the integer +/// into its string representation and have serde use that to determine the enum variant. This +/// requires using `#[serde(rename = "")]` on all enum variants. +/// +/// # Examples +/// +/// ``` +/// use std::borrow::Cow; +/// +/// use serde::{Deserialize, Serialize}; +/// +/// #[derive(Serialize, Deserialize)] +/// enum TestEnum<'a> { +/// #[serde(rename = "19")] +/// Unit, +/// #[serde(rename = "235")] +/// NewType(u64), +/// #[serde(rename = "179")] +/// Tuple(u32, u64, Vec), +/// #[serde(rename = "97")] +/// Struct { +/// #[serde(borrow, with = "serde_bytes")] +/// data: Cow<'a, [u8]>, +/// footer: u32, +/// }, +/// } +/// # +/// # assert!(matches!(serde_wormhole::from_slice(&[19]).unwrap(), TestEnum::Unit)); +/// ``` +struct Enum<'de, 'a> { + de: &'a mut Deserializer<'de>, + variant: u8, +} + +impl<'de, 'a> EnumAccess<'de> for Enum<'de, 'a> { + type Error = Error; + type Variant = &'a mut Deserializer<'de>; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>, + { + let mut buf = itoa::Buffer::new(); + seed.deserialize(buf.format(self.variant).into_deserializer()) + .map(|v| (v, self.de)) + } +} + +#[cfg(test)] +mod tests { + use std::{ + borrow::Cow, + collections::BTreeMap, + io::{Cursor, Write}, + iter::FromIterator, + mem::size_of, + }; + + use serde::{Deserialize, Serialize}; + + use crate::{from_slice, Error}; + + #[test] + fn empty_input() { + let e = from_slice::(&[]).expect_err("empty buffer deserialized"); + assert!(matches!(e, Error::Eof)) + } + + #[test] + fn trailing_data() { + macro_rules! check { + ($buf:ident, $ty:ty) => { + let e = from_slice::<$ty>(&$buf) + .expect_err("deserialized with trailing data"); + assert!(matches!(e, Error::TrailingData)); + }; + ($buf:ident, $($ty:ty),*) => { + $( + check!($buf, $ty); + )* + }; + } + let buf = 0x9ab0_8c9f_8462_2f63u64.to_be_bytes(); + check!(buf, i8, i16, i32, u8, u16, u32); + } + + #[test] + fn bool() { + let v: bool = from_slice(&[0u8]).unwrap(); + assert!(!v); + + let v: bool = from_slice(&[1u8]).unwrap(); + assert!(v); + + for v in 2..=u8::MAX { + from_slice::(&[v]).unwrap_err(); + } + } + + #[test] + fn integers() { + macro_rules! check { + ($v:ident, $ty:ty) => { + // Casting an integer from a larger width to a smaller width will truncate the + // upper bits. + let expected = $v as $ty; + let buf = expected.to_be_bytes(); + + let actual: $ty = from_slice(&buf).expect("failed to deserialize integer"); + assert_eq!(expected, actual); + }; + ($v:ident, $($ty:ty),*) => { + $( + check!($v, $ty); + )* + }; + } + + // Value randomly generated from `dd if=/dev/urandom | xxd -p -l 16`. + let v = 0x84f2_e24f_2e8a_734e_5a5f_def6_c597_f232u128; + check!(v, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128); + } + + #[test] + fn char() { + let chars = ['\u{0065}', '\u{0301}']; + let mut buf = [0u8; size_of::() * 2]; + let mut cursor = Cursor::new(&mut buf[..]); + for c in chars { + cursor.write_all(&u32::from(c).to_be_bytes()).unwrap(); + } + + let (c1, c2): (char, char) = from_slice(&buf).unwrap(); + let mut actual = String::new(); + actual.push(c1); + actual.push(c2); + assert_eq!("é", actual); + } + + #[test] + fn invalid_chars() { + for c in 0xd800u32..0xe000 { + from_slice::(&c.to_be_bytes()).expect_err("deserialized invalid char"); + } + + // Spot check a few values in the higher range. + let invalid = [ + 0xa17c509eu32, + 0xb4ee4bc8u32, + 0x46055273u32, + 0x3d3bb5fbu32, + 0xeb82fddcu32, + 0xe2777604u32, + 0xe597554fu32, + 0x12aa069fu32, + ]; + for c in invalid { + from_slice::(&c.to_be_bytes()).expect_err("deserialized invalid char"); + } + } + + #[test] + fn char_array() { + let expected = "Löwe 老虎 Léopard"; + let mut buf = [0u8; size_of::() * 15]; + let mut cursor = Cursor::new(&mut buf[..]); + for c in expected.chars().map(u32::from) { + cursor.write_all(&c.to_be_bytes()).unwrap(); + } + + let actual = from_slice::<[char; 15]>(&buf) + .map(String::from_iter) + .unwrap(); + + assert_eq!(expected, actual); + } + + #[test] + fn strings() { + let expected = "Löwe 老虎 Léopard"; + let buf = IntoIterator::into_iter([expected.len() as u8]) + .chain(expected.as_bytes().iter().copied()) + .collect::>(); + + let actual = from_slice::(&buf).unwrap(); + assert_eq!(expected, actual); + + let actual = from_slice::<&str>(&buf).unwrap(); + assert_eq!(expected, actual); + + let actual = from_slice::<&str>(&[0]).unwrap(); + assert!(actual.is_empty()); + } + + #[test] + fn maps() { + let buf = [ + 0x04, 0x78, 0x26, 0x20, 0x90, 0x48, 0x96, 0xd4, 0x18, 0x8b, 0xce, 0x62, 0xcd, 0x87, + 0x7a, 0x36, 0x1a, 0x4c, 0x5e, 0x4f, 0x65, 0x84, 0x76, 0xb3, 0x9c, 0x7e, 0xb3, 0xfa, + 0x99, 0x29, 0xf2, 0x8b, 0x7f, + ]; + + let expected = BTreeMap::from([ + (0x78262090u32, 0x4896d418u32), + (0x8bce62cd, 0x877a361a), + (0x4c5e4f65, 0x8476b39c), + (0x7eb3fa99, 0x29f28b7f), + ]); + + let actual = from_slice(&buf).unwrap(); + assert_eq!(expected, actual); + + let actual = from_slice::>(&[0]).unwrap(); + assert!(actual.is_empty()); + } + + #[test] + fn empty_bytes() { + let buf = [0x0]; + let actual: Vec = from_slice(&buf).unwrap(); + assert!(actual.is_empty()); + + let actual: &[u8] = from_slice(&buf).unwrap(); + assert!(actual.is_empty()); + } + + #[test] + fn bytes() { + let buf = [ + 0x40, 0xc7, 0xe7, 0x8f, 0x91, 0x47, 0x32, 0xe0, 0x54, 0x4e, 0xde, 0x94, 0x27, 0xf4, + 0xa9, 0x95, 0xd5, 0x96, 0xbe, 0x38, 0xd4, 0xa8, 0xca, 0xdd, 0x2e, 0xec, 0x95, 0x8d, + 0xb3, 0x1a, 0xa3, 0x8a, 0x3b, 0xc2, 0xdb, 0x54, 0xac, 0x23, 0x85, 0xa7, 0xe8, 0x88, + 0x39, 0xcb, 0xa4, 0x83, 0xde, 0xc4, 0x33, 0x83, 0x10, 0xba, 0x39, 0x55, 0x63, 0x67, + 0xd9, 0x08, 0x19, 0xe2, 0x42, 0xf6, 0xc9, 0x5c, 0xe2, + ]; + let expected = &buf[1..]; + + let actual: Vec = from_slice(&buf).unwrap(); + assert_eq!(expected, actual); + + let actual: &[u8] = from_slice(&buf).unwrap(); + assert_eq!(expected, actual); + } + + #[test] + fn max_bytes() { + let buf = [ + 0xff, 0x8a, 0xa0, 0x62, 0x4b, 0xf8, 0x5c, 0x2f, 0x71, 0x8b, 0xa2, 0xe4, 0x80, 0xbf, + 0xb0, 0x15, 0xe0, 0xa3, 0x7c, 0xd3, 0x81, 0x56, 0x0d, 0x25, 0x13, 0x63, 0x23, 0xa1, + 0x0f, 0x84, 0x7f, 0x3e, 0xed, 0x3a, 0xe1, 0xe2, 0x8e, 0x20, 0x33, 0x42, 0x83, 0x89, + 0xa9, 0x0d, 0xe6, 0x58, 0xa5, 0xb4, 0x64, 0x60, 0x0f, 0x8f, 0xdf, 0x51, 0xd1, 0x00, + 0x9d, 0x4b, 0x6e, 0x42, 0x04, 0x8b, 0xa2, 0xc8, 0x14, 0xed, 0x4f, 0x46, 0x64, 0xf5, + 0xfd, 0xa6, 0xb2, 0x85, 0x63, 0x60, 0xa6, 0xb7, 0xd8, 0xed, 0x1a, 0xfd, 0x3f, 0x99, + 0x6b, 0x3c, 0x85, 0xfe, 0x09, 0x04, 0xab, 0x9f, 0x56, 0xfa, 0x9f, 0x80, 0xd5, 0x93, + 0x94, 0xa3, 0xc6, 0x62, 0xa8, 0x0e, 0x2d, 0xaa, 0x82, 0x94, 0xf9, 0x38, 0xf1, 0x58, + 0x9e, 0x4c, 0x3e, 0x00, 0x64, 0x67, 0xda, 0x9e, 0x8b, 0x5c, 0xb1, 0xaa, 0xa8, 0x85, + 0x43, 0xfd, 0x1a, 0xf2, 0xd8, 0xa7, 0xa7, 0x31, 0x55, 0x73, 0x91, 0x19, 0x5e, 0x43, + 0xe3, 0xc0, 0xfb, 0xd0, 0xc6, 0xa8, 0x72, 0x43, 0x33, 0x2f, 0x69, 0x5c, 0x64, 0x92, + 0xc7, 0x17, 0xb2, 0x30, 0x7a, 0xc1, 0x0a, 0x0d, 0x30, 0xbb, 0x94, 0xcb, 0x5c, 0x49, + 0x88, 0xe0, 0xb4, 0x0b, 0x4e, 0xab, 0xd7, 0x8e, 0x2d, 0x82, 0x55, 0x33, 0xb1, 0x00, + 0xa6, 0x89, 0x32, 0x59, 0x86, 0xde, 0xd7, 0x13, 0xea, 0x35, 0x0a, 0xa0, 0x50, 0x89, + 0x95, 0xe7, 0xaf, 0xaa, 0x6a, 0x4e, 0x22, 0xb4, 0x7f, 0x2e, 0x49, 0x9d, 0x67, 0x3a, + 0x95, 0x99, 0x75, 0x0a, 0x6b, 0x4d, 0x3e, 0x9d, 0x03, 0x1e, 0xfd, 0x82, 0xda, 0x02, + 0x3e, 0x18, 0xe4, 0x26, 0xdf, 0xb0, 0x1d, 0x49, 0xce, 0x6c, 0xf8, 0xbc, 0xbe, 0x82, + 0x27, 0x0e, 0x66, 0xa1, 0xc1, 0x85, 0xe2, 0xe1, 0x03, 0x83, 0xa4, 0x82, 0xf7, 0xd0, + 0x66, 0x12, 0x8b, 0xc4, + ]; + let expected = &buf[1..]; + + let actual: Vec = from_slice(&buf).unwrap(); + assert_eq!(expected, actual); + + let actual: &[u8] = from_slice(&buf).unwrap(); + assert_eq!(expected, actual); + } + + #[test] + fn tagged_enums() { + #[derive(Serialize, Deserialize)] + enum TestEnum<'a> { + #[serde(rename = "19")] + Unit, + #[serde(rename = "235")] + NewType(u64), + #[serde(rename = "179")] + Tuple(u32, u64, Vec), + #[serde(rename = "97")] + Struct { + #[serde(borrow, with = "serde_bytes")] + data: Cow<'a, [u8]>, + footer: u32, + }, + } + + assert!(matches!(from_slice(&[19]).unwrap(), TestEnum::Unit)); + + let buf = [235, 0xa7, 0xc5, 0x31, 0x9c, 0x8d, 0x87, 0x48, 0xd2]; + if let TestEnum::NewType(v) = from_slice(&buf).unwrap() { + assert_eq!(v, 0xa7c5319c8d8748d2); + } else { + panic!(); + } + + let buf = [ + 179, 0x60, 0xfb, 0x4d, 0x0d, 0xc4, 0x98, 0x40, 0x65, 0xf5, 0xdb, 0xbf, 0x3c, 0x05, + 0xa9, 0xca, 0xb9, 0xe7, 0x96, 0x3b, 0x74, 0xfa, 0x82, 0xb2, + ]; + if let TestEnum::Tuple(a, b, c) = from_slice(&buf).unwrap() { + assert_eq!(a, 0x60fb4d0d); + assert_eq!(b, 0xc4984065f5dbbf3c); + assert_eq!(c, &[0xa9ca, 0xb9e7, 0x963b, 0x74fa, 0x82b2]); + } else { + panic!(); + } + + let buf = [ + 97, 0x0b, 0xc2, 0xfd, 0xd6, 0xa1, 0xed, 0x8a, 0x12, 0x46, 0xd4, 0x20, 0xaf, 0xcc, 0x88, + 0x8c, 0xd2, + ]; + if let TestEnum::Struct { data, footer } = from_slice(&buf).unwrap() { + assert_eq!( + &*data, + &[0xc2, 0xfd, 0xd6, 0xa1, 0xed, 0x8a, 0x12, 0x46, 0xd4, 0x20, 0xaf] + ); + assert_eq!(footer, 0xcc888cd2); + } else { + panic!(); + } + } + + #[test] + fn unknown_enum_variant() { + #[derive(Debug, Serialize, Deserialize)] + enum Unknown { + #[serde(rename = "7")] + Foo, + } + + from_slice::(&[1]).expect_err("Deserialized unknown enum variant"); + } + + #[test] + fn complex_struct() { + #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] + struct Address<'a> { + #[serde(borrow, with = "serde_bytes")] + bytes: Cow<'a, [u8]>, + } + + #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] + struct Info<'a> { + #[serde(borrow)] + addrs: Vec>, + expiration: u64, + } + + #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] + struct Upgrade<'a> { + index: u32, + #[serde(borrow)] + info: Info<'a>, + } + + let expected = Upgrade { + index: 7, + info: Info { + addrs: vec![ + Address { + bytes: Cow::Owned(vec![ + 0x4f, 0x58, 0x50, 0x9e, 0xb6, 0x8b, 0x9d, 0x19, 0x9e, 0x00, 0x92, 0x5e, + 0xcb, 0x0f, 0xfd, 0x53, 0x80, 0x06, 0xfe, 0xc3, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0xb6, 0x7c, 0xd5, 0xef, 0x88, 0x00, 0xa7, 0xbc, 0xba, 0x2e, 0xfb, 0x91, + 0x09, 0x33, 0xee, 0x51, 0xdd, 0x02, 0x24, 0x35, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x2b, 0x05, 0x87, 0x83, 0x8a, 0x2a, 0xe9, 0xc4, 0x0e, 0x54, 0x28, 0x11, + 0xc2, 0x99, 0x33, 0xa8, 0x65, 0xd4, 0x6c, 0x3d, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x08, 0xd2, 0xb5, 0x03, 0x64, 0xb5, 0x27, 0x7f, 0xf0, 0xaf, 0x90, 0x6d, + 0x03, 0x10, 0x21, 0xb3, 0x20, 0xdd, 0xfb, 0xda, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0xec, 0xc9, 0x7d, 0x9d, 0x6c, 0x68, 0x4e, 0x43, 0x6e, 0x39, 0x51, 0xe0, + 0xa8, 0x6f, 0x49, 0xf1, 0xf4, 0xd3, 0xdb, 0x2a, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x11, 0xed, 0x25, 0xe6, 0x6b, 0xed, 0x56, 0x25, 0x87, 0xb4, 0x1c, 0x94, + 0x9c, 0x81, 0xcf, 0x2c, 0x34, 0xb8, 0x5e, 0xc3, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x3d, 0x82, 0xcb, 0x29, 0xe8, 0xa7, 0x34, 0x37, 0x3a, 0x46, 0x07, 0xa4, + 0xf2, 0xb3, 0x94, 0xb0, 0x73, 0xed, 0x86, 0x3b, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x99, 0xa4, 0xb5, 0x89, 0x01, 0x59, 0x18, 0x01, 0x08, 0x53, 0xcf, 0x17, + 0x21, 0x14, 0x65, 0xcf, 0x05, 0x7f, 0xaa, 0x5d, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0xcc, 0x38, 0x3b, 0x85, 0xde, 0xc2, 0x59, 0xe6, 0x22, 0xee, 0xa4, 0xea, + 0x83, 0x72, 0x08, 0x7e, 0xdf, 0xea, 0xe1, 0xc3, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x7a, 0xd9, 0x4d, 0x53, 0x9c, 0xc2, 0xff, 0xe3, 0x1d, 0xd6, 0x60, 0x78, + 0x31, 0xb3, 0x2f, 0x76, 0x12, 0xb7, 0xc7, 0xaf, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x10, 0x88, 0xf6, 0x6f, 0x1d, 0x27, 0x2d, 0xad, 0x5b, 0x48, 0xca, 0xaf, + 0xba, 0x63, 0x99, 0xbe, 0x23, 0x3b, 0xd5, 0xca, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0x49, 0x91, 0xa9, 0x0f, 0x47, 0xcd, 0xfe, 0xdb, 0xd6, 0xfb, 0xb3, 0xe9, + 0xa4, 0xc2, 0xc2, 0x15, 0xb3, 0xe7, 0xe5, 0xb6, + ]), + }, + Address { + bytes: Cow::Owned(vec![ + 0xdd, 0xe3, 0x77, 0xb0, 0xc3, 0x1b, 0x56, 0x2c, 0x90, 0x67, 0x88, 0xc6, + 0xc5, 0xa5, 0xd8, 0xb8, 0xee, 0xc3, 0xa0, 0x87, + ]), + }, + ], + expiration: 0x90e4_9c5d_cb20_0792, + }, + }; + let buf = [ + 0x00, 0x00, 0x00, 0x07, 0x0d, 0x14, 0x4f, 0x58, 0x50, 0x9e, 0xb6, 0x8b, 0x9d, 0x19, + 0x9e, 0x00, 0x92, 0x5e, 0xcb, 0x0f, 0xfd, 0x53, 0x80, 0x06, 0xfe, 0xc3, 0x14, 0xb6, + 0x7c, 0xd5, 0xef, 0x88, 0x00, 0xa7, 0xbc, 0xba, 0x2e, 0xfb, 0x91, 0x09, 0x33, 0xee, + 0x51, 0xdd, 0x02, 0x24, 0x35, 0x14, 0x2b, 0x05, 0x87, 0x83, 0x8a, 0x2a, 0xe9, 0xc4, + 0x0e, 0x54, 0x28, 0x11, 0xc2, 0x99, 0x33, 0xa8, 0x65, 0xd4, 0x6c, 0x3d, 0x14, 0x08, + 0xd2, 0xb5, 0x03, 0x64, 0xb5, 0x27, 0x7f, 0xf0, 0xaf, 0x90, 0x6d, 0x03, 0x10, 0x21, + 0xb3, 0x20, 0xdd, 0xfb, 0xda, 0x14, 0xec, 0xc9, 0x7d, 0x9d, 0x6c, 0x68, 0x4e, 0x43, + 0x6e, 0x39, 0x51, 0xe0, 0xa8, 0x6f, 0x49, 0xf1, 0xf4, 0xd3, 0xdb, 0x2a, 0x14, 0x11, + 0xed, 0x25, 0xe6, 0x6b, 0xed, 0x56, 0x25, 0x87, 0xb4, 0x1c, 0x94, 0x9c, 0x81, 0xcf, + 0x2c, 0x34, 0xb8, 0x5e, 0xc3, 0x14, 0x3d, 0x82, 0xcb, 0x29, 0xe8, 0xa7, 0x34, 0x37, + 0x3a, 0x46, 0x07, 0xa4, 0xf2, 0xb3, 0x94, 0xb0, 0x73, 0xed, 0x86, 0x3b, 0x14, 0x99, + 0xa4, 0xb5, 0x89, 0x01, 0x59, 0x18, 0x01, 0x08, 0x53, 0xcf, 0x17, 0x21, 0x14, 0x65, + 0xcf, 0x05, 0x7f, 0xaa, 0x5d, 0x14, 0xcc, 0x38, 0x3b, 0x85, 0xde, 0xc2, 0x59, 0xe6, + 0x22, 0xee, 0xa4, 0xea, 0x83, 0x72, 0x08, 0x7e, 0xdf, 0xea, 0xe1, 0xc3, 0x14, 0x7a, + 0xd9, 0x4d, 0x53, 0x9c, 0xc2, 0xff, 0xe3, 0x1d, 0xd6, 0x60, 0x78, 0x31, 0xb3, 0x2f, + 0x76, 0x12, 0xb7, 0xc7, 0xaf, 0x14, 0x10, 0x88, 0xf6, 0x6f, 0x1d, 0x27, 0x2d, 0xad, + 0x5b, 0x48, 0xca, 0xaf, 0xba, 0x63, 0x99, 0xbe, 0x23, 0x3b, 0xd5, 0xca, 0x14, 0x49, + 0x91, 0xa9, 0x0f, 0x47, 0xcd, 0xfe, 0xdb, 0xd6, 0xfb, 0xb3, 0xe9, 0xa4, 0xc2, 0xc2, + 0x15, 0xb3, 0xe7, 0xe5, 0xb6, 0x14, 0xdd, 0xe3, 0x77, 0xb0, 0xc3, 0x1b, 0x56, 0x2c, + 0x90, 0x67, 0x88, 0xc6, 0xc5, 0xa5, 0xd8, 0xb8, 0xee, 0xc3, 0xa0, 0x87, 0x90, 0xe4, + 0x9c, 0x5d, 0xcb, 0x20, 0x07, 0x92, + ]; + + let actual = from_slice(&buf).unwrap(); + assert_eq!(expected, actual); + } +} diff --git a/sdk/rust/serde_wormhole/src/error.rs b/sdk/rust/serde_wormhole/src/error.rs new file mode 100644 index 000000000..de7f3275a --- /dev/null +++ b/sdk/rust/serde_wormhole/src/error.rs @@ -0,0 +1,38 @@ +use std::{fmt::Display, io, num::ParseIntError}; + +use serde::{de, ser}; +use thiserror::Error as ThisError; + +#[derive(Debug, ThisError)] +pub enum Error { + #[error("{0}")] + Message(Box), + #[error("{0}")] + Io(#[from] io::Error), + #[error("unexpected end of input")] + Eof, + #[error("`deserialize_any` is not supported")] + DeserializeAnyNotSupported, + #[error("trailing data in input buffer")] + TrailingData, + #[error("this type is not supported")] + Unsupported, + #[error("sequence is too large ({0} elements), max supported length = 255")] + SequenceTooLarge(usize), + #[error("enum variant {0}::{1} cannot be parsed as a `u8`: {2}")] + EnumVariant(&'static str, &'static str, ParseIntError), + #[error("sequence length must be known before serialization")] + UnknownSequenceLength, +} + +impl de::Error for Error { + fn custom(msg: T) -> Error { + Error::Message(msg.to_string().into_boxed_str()) + } +} + +impl ser::Error for Error { + fn custom(msg: T) -> Error { + Error::Message(msg.to_string().into_boxed_str()) + } +} diff --git a/sdk/rust/serde_wormhole/src/lib.rs b/sdk/rust/serde_wormhole/src/lib.rs new file mode 100644 index 000000000..0f0f73559 --- /dev/null +++ b/sdk/rust/serde_wormhole/src/lib.rs @@ -0,0 +1,426 @@ +//! Serialize and deserialize rust values from the VAA payload wire format. +//! +//! As of this writing (June, 2022) there is no proper specification for the VAA payload wire +//! format so this implementation has mostly been reverse engineered from the existing messages. +//! While the rest of this document talks about how various types are represented on the wire this +//! should be seen as an explanation of how things are implemented *in this crate* and not as +//! official documentation. In cases where the serialization of a payload produced by this crate +//! differs from the one use by the wormhole contracts, the serialization used by the actual +//! contract is considered the canonical serialization. +//! +//! Unless you want to interact with existing wormhole VAA payloads, this crate is probably not what +//! you are looking for. If you are simply using the wormhole bridge to send your own payloads then +//! using a schema with auto-generated code (like protobufs or flatbuffers) is probably a better +//! choice. +//! +//! ## Wire format +//! +//! The VAA payload wire format is not a self-describing format (unlike json and toml). Therefore it +//! is necessary to know the type that needs to be produced before deserializing a byte stream. +//! +//! The wire format currently supports the following primitive types: +//! +//! ### `bool` +//! +//! Encoded as a single byte where a value of 0 indicates false and 1 indicates true. All other +//! values are invalid. +//! +//! ### Integers +//! +//! `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, and `u128` are all supported and +//! encoded as full-width big-endian integers, i.e., `i16` is 2 bytes, `u64` is 8 bytes, etc. +//! +//! ### `char` +//! +//! Encoded as a big-endian `u32`, with the additional restriction that it must be a valid [`Unicode +//! Scalar Value`](https://www.unicode.org/glossary/#unicode_scalar_value). +//! +//! ### Sequences +//! +//! Variable length heterogeneous sequences are encoded as a single byte length followed by the +//! concatenation of the serialized form of each element in the sequence. Note that this means that +//! sequences cannot have more than 255 elements. Additionally, during serialization the length must +//! be known ahead of time. +//! +//! ### Byte arrays - `&[u8]`, `Vec`, and `Cow<'a, [u8]>` +//! +//! Byte arrays are treated as a subset of variable-length sequences and are encoded as a single +//! byte length followed by that many bytes of data. Again, since the length of the byte array has +//! to fit in a single byte it cannot be longer than 255 bytes. +//! +//! ### `&str`, `String` +//! +//! String types are encoded the same way as `&[u8]`, with the additional restriction that the byte +//! array must be valid UTF-8. +//! +//! ### Tuples +//! +//! Tuples are heterogenous sequences where the length is fixed and known ahead of time. In this +//! case the length is not encoded on the wire and the serialization of each element in the tuple is +//! concatenated to produce the final value. +//! +//! ### `Option` +//! +//! The wire format does not support optional values. Options are always deserialized as `Some(T)` +//! while trying to serialize an `Option::None` will result in an error. +//! +//! ### Structs +//! +//! Structs are represented the same way as tuples and the wire format for a struct is identical to +//! the wire format for a tuple with the same fields in the same order. The only exception is unit +//! structs (structs with no fields), which are not represented in the wire format at all. +//! +//! ### `[T; N]` +//! +//! Arrays are treated as tuples with homogenous fields and have the same wire format. +//! +//! ### Enums +//! +//! Enums are encoded as a single byte identifying the variant followed by the serialization of the +//! variant. +//! +//! * Unit variants - No additional data is encoded. +//! * Newtype variants - Encoded using the serialization of the inner type. +//! * Tuple variants - Encoded as a regular tuple. +//! * Struct variants - Encoded as a regular struct. +//! +//! Since the enum variant is encoded as a single byte rather than the name of the variant itself, +//! it is necessary to use `#[serde(rename = "")]` on each enum variant to ensure +//! that they can be serialized and deserialized properly. +//! +//! #### Examples +//! +//! ``` +//! use std::borrow::Cow; +//! +//! use serde::{Deserialize, Serialize}; +//! +//! #[derive(Serialize, Deserialize)] +//! enum TestEnum<'a> { +//! #[serde(rename = "19")] +//! Unit, +//! #[serde(rename = "235")] +//! NewType(u64), +//! #[serde(rename = "179")] +//! Tuple(u32, u64, Vec), +//! #[serde(rename = "97")] +//! Struct { +//! #[serde(borrow, with = "serde_bytes")] +//! data: Cow<'a, [u8]>, +//! footer: u32, +//! }, +//! } +//! +//! assert!(matches!(serde_wormhole::from_slice(&[19]).unwrap(), TestEnum::Unit)); +//! ``` +//! +//! ### Map types +//! +//! Map types are encoded as a sequence of `(key, value)` tuples. The encoding for a `Vec<(K, V)>` +//! is identical to that of a `BTreeMap`. During serialiazation, the number of elements in the +//! map must be known ahead of time. Like other sequences, the maximum number of elements in the map +//! is 255. + +use std::io::{Read, Write}; + +use serde::{de::DeserializeOwned, Deserialize, Serialize}; + +mod de; +mod error; +mod ser; + +pub use error::Error; + +/// Deserialize an instance of type `T` from the provided reader. +pub fn from_reader(mut r: R) -> Result { + // We can do something smarter here by making the deserializer generic over the reader (see + // serde_json::Deserializer) but for now this is probably good enough. + let mut buf = Vec::with_capacity(128); + r.read_to_end(&mut buf)?; + + from_slice(&buf) +} + +/// Like `from_reader` but also returns any trailing data in the input buffer after +/// deserialization. +pub fn from_reader_with_payload( + mut r: R, +) -> Result<(T, Vec), Error> { + // We can do something smarter here by making the deserializer generic over the reader (see + // serde_json::Deserializer) but for now this is probably good enough. + let mut buf = Vec::with_capacity(128); + r.read_to_end(&mut buf)?; + + from_slice_with_payload(&buf).map(|(v, p)| (v, p.to_vec())) +} + +/// Deserialize an instance of type `T` from a byte slice. +pub fn from_slice<'a, T: Deserialize<'a>>(buf: &'a [u8]) -> Result { + let mut deserializer = de::Deserializer::new(buf); + + let v = T::deserialize(&mut deserializer)?; + + if deserializer.end().is_empty() { + Ok(v) + } else { + Err(Error::TrailingData) + } +} + +/// Like `from_slice` but also returns any trailing data in the input buffer after deserialization. +pub fn from_slice_with_payload<'a, T: Deserialize<'a>>( + buf: &'a [u8], +) -> Result<(T, &'a [u8]), Error> { + let mut deserializer = de::Deserializer::new(buf); + + T::deserialize(&mut deserializer).map(|v| (v, deserializer.end())) +} + +/// Serialize `T` into a byte vector. +pub fn to_vec(val: &T) -> Result, Error> { + let mut buf = Vec::with_capacity(128); + + to_writer(&mut buf, val)?; + Ok(buf) +} + +/// Serialize `T` into the provided writer. +pub fn to_writer(w: W, val: &T) -> Result<(), Error> { + let mut serializer = ser::Serializer::new(w); + val.serialize(&mut serializer) +} + +#[cfg(test)] +mod tests { + use core::panic; + use std::{borrow::Cow, collections::BTreeMap}; + + use super::*; + + use serde::{Deserialize, Serialize}; + use serde_repr::{Deserialize_repr, Serialize_repr}; + + mod serde_array { + use std::{fmt, mem::MaybeUninit}; + + use serde::{ + de::{Error, SeqAccess, Visitor}, + ser::SerializeTuple, + Deserializer, Serializer, + }; + + pub fn serialize( + value: &[u8; N], + serializer: S, + ) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_tuple(N)?; + for v in value { + seq.serialize_element(v)?; + } + + seq.end() + } + + struct ArrayVisitor; + impl<'de, const N: usize> Visitor<'de> for ArrayVisitor { + type Value = [u8; N]; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "an array of length {}", N) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + // TODO: Replace with `MaybeUninit::uninit_array()` once that's stabilized. + let mut buf = MaybeUninit::<[u8; N]>::uninit(); + let ptr = buf.as_mut_ptr() as *mut u8; + let mut pos = 0; + + while pos < N { + let v = seq + .next_element() + .and_then(|v| v.ok_or_else(|| Error::invalid_length(pos, &self)))?; + + // Safety: The resulting pointer is within the bounds of the allocation because + // we know that `pos < N`. + unsafe { ptr.add(pos).write(v) }; + + pos += 1; + } + + if pos == N { + // Safety: We've initialized all the bytes in `buf`. + Ok(unsafe { buf.assume_init() }) + } else { + Err(Error::invalid_length(pos, &self)) + } + } + } + + pub fn deserialize<'de, const N: usize, D>(deserializer: D) -> Result<[u8; N], D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_tuple(N, ArrayVisitor) + } + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Header { + version: u8, + guardian_set_index: u32, + } + + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] + struct Signature { + index: u8, + #[serde(with = "serde_array")] + signature: [u8; 65], + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Vaa<'s> { + header: Header, + #[serde(borrow)] + signatures: Cow<'s, [Signature]>, + timestamp: u32, // Seconds since UNIX epoch + nonce: u32, + emitter_chain: u16, + emitter_address: [u8; 32], + sequence: u64, + consistency_level: u8, + map: BTreeMap, + payload: GovernancePacket, + } + + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] + struct GuardianAddress<'a> { + #[serde(borrow, with = "serde_bytes")] + bytes: Cow<'a, [u8]>, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct GuardianSetInfo<'a> { + #[serde(borrow)] + addresses: Cow<'a, [GuardianAddress<'a>]>, + expiration_time: u64, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct ContractUpgrade { + new_contract: u64, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct GuardianSetUpgrade<'a> { + new_guardian_set_index: u32, + #[serde(borrow)] + new_guardian_set: GuardianSetInfo<'a>, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct SetFee { + high: u128, + low: u128, + } + + #[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Eq)] + #[repr(u8)] + enum Action { + ContractUpgrade = 1, + GuardianSetUpgrade = 2, + SetFee = 3, + } + + #[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Eq)] + #[repr(u16)] + enum Chain { + Unset = 0, + Solana = 1, + Ethereum = 2, + Terra = 3, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct GovernancePacket { + module: [u8; 32], + action: Action, + chain: Chain, + } + + #[test] + fn end_to_end() { + let vaa = Vaa { + header: Header { + version: 3, + guardian_set_index: 0x97a5_6966, + }, + signatures: Cow::Borrowed(&[ + Signature { + index: 0x13, + signature: [ + 0x23, 0x35, 0xf3, 0xc2, 0x2c, 0xd2, 0x43, 0xf4, 0xcd, 0xe4, 0x7a, 0xa9, + 0xdd, 0x99, 0x35, 0xbc, 0x20, 0x8f, 0x9c, 0x2d, 0x2e, 0xa4, 0x8e, 0xe0, + 0x85, 0x89, 0x33, 0x65, 0x0b, 0x8c, 0x6c, 0x14, 0xd9, 0x6b, 0x41, 0xe8, + 0x4b, 0xc7, 0xef, 0xae, 0x75, 0x3d, 0x9f, 0x1a, 0x36, 0x4c, 0x09, 0x62, + 0x59, 0x92, 0xca, 0x29, 0xcc, 0x2c, 0xb1, 0x9b, 0xc6, 0x8e, 0xff, 0xf1, + 0x29, 0xae, 0x21, 0xe9, 0x17, + ], + }, + Signature { + index: 0xb2, + signature: [ + 0xa1, 0x45, 0x54, 0x14, 0xd5, 0x3a, 0x4f, 0xb0, 0xf1, 0xf4, 0xf6, 0xf5, + 0x6b, 0x17, 0xc2, 0x52, 0x19, 0xe8, 0x68, 0x54, 0x73, 0x39, 0xde, 0xd2, + 0xef, 0x5c, 0xca, 0xca, 0x0f, 0x42, 0x0d, 0x3c, 0x71, 0x64, 0x50, 0xc0, + 0x2f, 0xf3, 0xf8, 0x70, 0xee, 0x52, 0xa8, 0x4a, 0xfb, 0x2a, 0x62, 0x4d, + 0xeb, 0xc8, 0x1e, 0xa3, 0x38, 0x07, 0x78, 0x67, 0x7f, 0x4b, 0x96, 0xa0, + 0x54, 0xc0, 0x66, 0x7d, 0xe7, + ], + }, + ]), + timestamp: 0x2db5_98b3, + nonce: 0x0861_20c4, + emitter_chain: 0x247b, + emitter_address: [ + 0x8b, 0xc0, 0x03, 0x0d, 0xe2, 0x50, 0x96, 0xcc, 0x48, 0xa8, 0xe7, 0xd7, 0x17, 0x05, + 0x6f, 0x9c, 0xe8, 0xe8, 0x0c, 0x12, 0x0d, 0x05, 0x02, 0xed, 0x4c, 0xc9, 0x51, 0xb4, + 0x9c, 0xe3, 0xc7, 0x94, + ], + sequence: 0xcc2b_6c34_eda9_89c1, + consistency_level: 0x0d, + map: BTreeMap::from([(0x35845d1a, 0x25ff53af), (0x543596f3, 0x58373435)]), + payload: GovernancePacket { + module: [ + 0x50, 0x06, 0x58, 0xff, 0xff, 0xae, 0x1a, 0xdd, 0x07, 0xbc, 0xcf, 0x34, 0x10, + 0x6c, 0xa3, 0xbb, 0x14, 0x40, 0x25, 0xe1, 0x8f, 0x1a, 0xa0, 0x39, 0x7b, 0x12, + 0x5a, 0x03, 0x58, 0x6f, 0xe1, 0x88, + ], + action: Action::ContractUpgrade, + chain: Chain::Solana, + }, + }; + let payload = &[0x3d, 0xab, 0x45, 0xaf, 0x7a, 0x6e, 0x9f, 0x7b]; + + let mut buf = to_vec(&vaa).unwrap(); + buf.extend_from_slice(payload); + + let (actual, governance_payload) = from_slice_with_payload(&buf).unwrap(); + + assert_eq!(vaa, actual); + + match actual.payload.action { + Action::ContractUpgrade => { + let expected = 0x3dab_45af_7a6e_9f7b; + let msg: ContractUpgrade = from_slice(governance_payload).unwrap(); + assert_eq!(expected, msg.new_contract); + } + _ => panic!("Unexpected action: {:?}", actual.payload.action), + } + } +} diff --git a/sdk/rust/serde_wormhole/src/ser.rs b/sdk/rust/serde_wormhole/src/ser.rs new file mode 100644 index 000000000..d6984c077 --- /dev/null +++ b/sdk/rust/serde_wormhole/src/ser.rs @@ -0,0 +1,712 @@ +use std::{convert::TryFrom, fmt::Display, io::Write}; + +use serde::{ser, Serialize}; + +use crate::Error; + +/// A struct that serializes a rust value into the VAA payload wire format. +pub struct Serializer { + writer: W, +} + +impl Serializer { + pub fn new(writer: W) -> Self { + Self { writer } + } +} + +impl<'a, W: Write> ser::Serializer for &'a mut Serializer { + type Ok = (); + type Error = Error; + + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + #[inline] + fn serialize_bool(self, v: bool) -> Result { + if v { + self.writer.write_all(&[1]).map_err(Error::from) + } else { + self.writer.write_all(&[0]).map_err(Error::from) + } + } + + #[inline] + fn serialize_i8(self, v: i8) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_i16(self, v: i16) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_i32(self, v: i32) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_i64(self, v: i64) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_i128(self, v: i128) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_u8(self, v: u8) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_u16(self, v: u16) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_u32(self, v: u32) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_u64(self, v: u64) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_u128(self, v: u128) -> Result { + self.writer.write_all(&v.to_be_bytes()).map_err(Error::from) + } + + #[inline] + fn serialize_f32(self, _v: f32) -> Result { + Err(Error::Unsupported) + } + + #[inline] + fn serialize_f64(self, _v: f64) -> Result { + Err(Error::Unsupported) + } + + #[inline] + fn serialize_char(self, v: char) -> Result { + self.serialize_u32(v.into()) + } + + #[inline] + fn serialize_str(self, v: &str) -> Result { + self.serialize_bytes(v.as_bytes()) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + let len = u8::try_from(v.len()).map_err(|_| Error::SequenceTooLarge(v.len()))?; + + self.writer.write_all(&[len])?; + self.writer.write_all(v).map_err(Error::from) + } + + #[inline] + fn serialize_none(self) -> Result { + Err(Error::Unsupported) + } + + #[inline] + fn serialize_some(self, value: &T) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + #[inline] + fn serialize_unit(self) -> Result { + Ok(()) + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + let v: u8 = variant + .parse() + .map_err(|e| Error::EnumVariant(name, variant, e))?; + + self.writer.write_all(&[v]).map_err(Error::from) + } + + #[inline] + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + let v: u8 = variant + .parse() + .map_err(|e| Error::EnumVariant(name, variant, e))?; + + self.writer.write_all(&[v])?; + value.serialize(self) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + let v: u8 = variant + .parse() + .map_err(|e| Error::EnumVariant(name, variant, e))?; + + self.writer.write_all(&[v])?; + Ok(self) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + let v: u8 = variant + .parse() + .map_err(|e| Error::EnumVariant(name, variant, e))?; + + self.writer.write_all(&[v])?; + Ok(self) + } + + fn serialize_seq(self, len: Option) -> Result { + let len = len + .ok_or(Error::UnknownSequenceLength) + .and_then(|v| u8::try_from(v).map_err(|_| Error::SequenceTooLarge(v)))?; + + self.writer.write_all(&[len])?; + Ok(self) + } + + #[inline] + fn serialize_tuple(self, _len: usize) -> Result { + Ok(self) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(self) + } + + fn serialize_map(self, len: Option) -> Result { + let len = len + .ok_or(Error::UnknownSequenceLength) + .and_then(|v| u8::try_from(v).map_err(|_| Error::SequenceTooLarge(v)))?; + + self.writer.write_all(&[len])?; + Ok(self) + } + + #[inline] + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(self) + } + + #[inline] + fn collect_str(self, value: &T) -> Result + where + T: Display, + { + self.serialize_str(&value.to_string()) + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +impl<'a, W: Write> ser::SerializeSeq for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, W: Write> ser::SerializeTuple for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, W: Write> ser::SerializeTupleStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, W: Write> ser::SerializeTupleVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, W: Write> ser::SerializeStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field( + &mut self, + _key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, W: Write> ser::SerializeStructVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field( + &mut self, + _key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, W: Write> ser::SerializeMap for &'a mut Serializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + key.serialize(&mut **self) + } + + #[inline] + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(&mut **self) + } + + fn serialize_entry( + &mut self, + key: &K, + value: &V, + ) -> Result<(), Self::Error> + where + K: Serialize, + V: Serialize, + { + self.serialize_key(key)?; + self.serialize_value(value) + } + + #[inline] + fn end(self) -> Result { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::{borrow::Cow, collections::BTreeMap}; + + use serde::{Deserialize, Serialize}; + + use crate::{to_vec, to_writer, Error}; + + #[test] + fn empty_buffer() { + to_writer(&mut [][..], &0xcc1a_7e0e_31f4_eae4u64) + .expect_err("serialized data to empty buffer"); + } + + #[test] + fn bool() { + assert_eq!(to_vec(&true).unwrap(), &[1]); + assert_eq!(to_vec(&false).unwrap(), &[0]); + } + + #[test] + fn integers() { + macro_rules! check { + ($v:ident, $ty:ty) => { + // Casting an integer from a larger width to a smaller width will truncate the + // upper bits. + let v = $v as $ty; + let expected = v.to_be_bytes(); + + let actual = to_vec(&v).expect("failed to serialize integer"); + assert_eq!(actual, &expected); + }; + ($v:ident, $($ty:ty),*) => { + $( + check!($v, $ty); + )* + }; + } + + // Value randomly generated from `dd if=/dev/urandom | xxd -p -l 16`. + let v = 0x46b1_265e_2f09_2e98_15c5_4c28_5c53_986cu128; + check!(v, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128); + } + + #[test] + fn strings() { + let buf = "Löwe 老虎 Léopard"; + + let expected = IntoIterator::into_iter([buf.len() as u8]) + .chain(buf.as_bytes().iter().copied()) + .collect::>(); + let actual = to_vec(buf).unwrap(); + assert_eq!(expected, actual); + + let actual = to_vec(&buf.to_string()).unwrap(); + assert_eq!(expected, actual); + + let actual = to_vec(&"").unwrap(); + assert_eq!(&[0], &*actual); + } + + #[test] + fn maps() { + let m = BTreeMap::from([ + (0xb74909e6u32, 0xe3a9db9cu32), + (0x383c5309u32, 0x5c6b2d54u32), + ]); + + let expected = [ + 0x02, 0x38, 0x3c, 0x53, 0x09, 0x5c, 0x6b, 0x2d, 0x54, 0xb7, 0x49, 0x09, 0xe6, 0xe3, + 0xa9, 0xdb, 0x9c, + ]; + let actual = to_vec(&m).unwrap(); + assert_eq!(actual, expected); + + let actual = to_vec(&BTreeMap::::new()).unwrap(); + assert_eq!(actual, [0]); + } + + #[test] + fn empty_bytes() { + let expected = [0x0]; + let actual = to_vec::>(&vec![]).unwrap(); + assert_eq!(actual, &expected); + + let actual = to_vec::<[u16]>(&[]).unwrap(); + assert_eq!(actual, &expected); + } + + #[test] + fn bytes() { + let expected = [ + 0x40, 0xff, 0x17, 0xc6, 0x15, 0xa4, 0x7c, 0x3c, 0x8c, 0xf3, 0x8b, 0x9f, 0x88, 0x31, + 0xc4, 0x46, 0x07, 0xcb, 0xe9, 0x2d, 0xc4, 0x59, 0xaf, 0x34, 0x5a, 0x32, 0x66, 0x8c, + 0x05, 0xc9, 0x3d, 0xab, 0x4f, 0xd2, 0x8a, 0xb6, 0x2e, 0x68, 0x58, 0x45, 0xef, 0x56, + 0x27, 0x1a, 0xb6, 0xe0, 0x17, 0x47, 0xf3, 0xb8, 0x5d, 0xbd, 0x1b, 0x92, 0xd9, 0xdd, + 0xe2, 0x99, 0x04, 0xbb, 0x67, 0xf7, 0x9f, 0xe1, 0xe1, + ]; + + let actual = to_vec(&expected[1..].to_vec()).unwrap(); + assert_eq!(actual, expected); + + let actual = to_vec(&expected[1..]).unwrap(); + assert_eq!(actual, expected); + } + + #[test] + fn max_bytes() { + let expected = [ + 0xff, 0x79, 0xce, 0xa2, 0x42, 0xd5, 0x8d, 0x0a, 0xaf, 0xa1, 0x72, 0x01, 0x92, 0xfc, + 0x23, 0x4f, 0x80, 0x56, 0x9d, 0xff, 0x9d, 0x44, 0x30, 0xe3, 0x22, 0xb6, 0xd5, 0x11, + 0xdd, 0xbe, 0x68, 0x6b, 0x34, 0x53, 0x5a, 0x97, 0x1b, 0x22, 0x96, 0x6c, 0xd5, 0xc6, + 0x08, 0x2a, 0xf0, 0x1b, 0x74, 0x22, 0xe8, 0xdf, 0xcd, 0xad, 0xa0, 0x75, 0x43, 0x84, + 0xf5, 0x43, 0x66, 0x38, 0x42, 0x66, 0xbb, 0xa1, 0x10, 0x54, 0x6a, 0x00, 0x4c, 0x9c, + 0x0d, 0x53, 0xed, 0x72, 0xc7, 0x6c, 0x9c, 0x86, 0x75, 0xbe, 0x7d, 0xf3, 0x54, 0x70, + 0x25, 0xda, 0x96, 0x9b, 0xc8, 0x6e, 0xc5, 0xc1, 0x56, 0xcf, 0x5a, 0x8d, 0xe1, 0x12, + 0x8d, 0xd7, 0x06, 0x33, 0xc5, 0x25, 0xf2, 0x31, 0xa2, 0x42, 0x3b, 0xc8, 0x30, 0xc9, + 0x1e, 0x51, 0xa5, 0x6a, 0x52, 0x0d, 0x6c, 0xbb, 0xc7, 0xde, 0x44, 0x8e, 0xe0, 0x80, + 0x00, 0xcf, 0x4b, 0xf1, 0x5e, 0xff, 0x68, 0x9d, 0xb5, 0x13, 0xad, 0x71, 0x6a, 0x94, + 0x0d, 0x68, 0x37, 0x7f, 0x68, 0x47, 0xf6, 0x03, 0xc5, 0x08, 0xf2, 0x47, 0x90, 0x7d, + 0x29, 0xd8, 0xeb, 0x7d, 0xc2, 0xbb, 0xaa, 0xea, 0x0b, 0x1a, 0x73, 0x44, 0xd1, 0x35, + 0x42, 0x79, 0xd8, 0x2b, 0x99, 0xbb, 0x75, 0xb7, 0xad, 0x54, 0xd3, 0xbb, 0x7b, 0xa3, + 0x4d, 0x3a, 0xea, 0x74, 0xbe, 0x82, 0x40, 0xac, 0x63, 0x6e, 0x03, 0x38, 0x3c, 0x57, + 0xa2, 0x02, 0x8b, 0x6c, 0xc9, 0x32, 0x9f, 0x6a, 0x35, 0x8f, 0x2d, 0x4e, 0x4d, 0xc6, + 0x2b, 0x51, 0x08, 0x02, 0x35, 0x03, 0x45, 0xa1, 0x13, 0x0a, 0xad, 0x3c, 0x53, 0x90, + 0x18, 0xe1, 0x89, 0xf2, 0xeb, 0xf1, 0x57, 0x2d, 0x32, 0xc1, 0x1a, 0x46, 0x8d, 0x72, + 0xe4, 0x39, 0xbb, 0x75, 0xda, 0x85, 0xec, 0x8d, 0x98, 0x31, 0xf2, 0xfb, 0x20, 0x9a, + 0x4e, 0x9c, 0xe6, 0x8c, + ]; + + let actual = to_vec(&expected[1..].to_vec()).unwrap(); + assert_eq!(actual, expected); + + let actual = to_vec(&expected[1..]).unwrap(); + assert_eq!(actual, expected); + } + + #[test] + fn data_too_large() { + let e = + to_vec(&vec![0u16; 300]).expect_err("serialized sequence with more than 255 entries"); + assert!(matches!(e, Error::SequenceTooLarge(300))); + } + + #[test] + fn tagged_enums() { + #[derive(Serialize, Deserialize)] + enum TestEnum<'a> { + #[serde(rename = "19")] + Unit, + #[serde(rename = "235")] + NewType(u64), + #[serde(rename = "179")] + Tuple(u32, u64, Vec), + #[serde(rename = "97")] + Struct { + #[serde(borrow, with = "serde_bytes")] + data: Cow<'a, [u8]>, + footer: u32, + }, + } + + assert_eq!(to_vec(&TestEnum::Unit).unwrap(), &[19]); + + let expected = [235, 0xa7, 0xc5, 0x31, 0x9c, 0x8d, 0x87, 0x48, 0xd2]; + assert_eq!( + to_vec(&TestEnum::NewType(0xa7c5319c8d8748d2)).unwrap(), + &expected + ); + + let expected = [ + 179, 0x60, 0xfb, 0x4d, 0x0d, 0xc4, 0x98, 0x40, 0x65, 0xf5, 0xdb, 0xbf, 0x3c, 0x05, + 0xa9, 0xca, 0xb9, 0xe7, 0x96, 0x3b, 0x74, 0xfa, 0x82, 0xb2, + ]; + let value = TestEnum::Tuple( + 0x60fb4d0d, + 0xc4984065f5dbbf3c, + vec![0xa9ca, 0xb9e7, 0x963b, 0x74fa, 0x82b2], + ); + assert_eq!(to_vec(&value).unwrap(), &expected); + + let expected = [ + 97, 0x0b, 0xc2, 0xfd, 0xd6, 0xa1, 0xed, 0x8a, 0x12, 0x46, 0xd4, 0x20, 0xaf, 0xcc, 0x88, + 0x8c, 0xd2, + ]; + let value = TestEnum::Struct { + data: Cow::Owned(vec![ + 0xc2, 0xfd, 0xd6, 0xa1, 0xed, 0x8a, 0x12, 0x46, 0xd4, 0x20, 0xaf, + ]), + footer: 0xcc888cd2, + }; + assert_eq!(to_vec(&value).unwrap(), &expected); + } + + #[test] + fn complex_struct() { + #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] + struct Address<'a> { + #[serde(borrow, with = "serde_bytes")] + bytes: Cow<'a, [u8]>, + } + + #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] + struct Info<'a> { + #[serde(borrow)] + addrs: Vec>, + expiration: u64, + } + + #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] + struct Upgrade<'a> { + index: u32, + #[serde(borrow)] + info: Info<'a>, + } + + let expected = [ + 0x00, 0x00, 0x00, 0x07, 0x0d, 0x14, 0x4f, 0x58, 0x50, 0x9e, 0xb6, 0x8b, 0x9d, 0x19, + 0x9e, 0x00, 0x92, 0x5e, 0xcb, 0x0f, 0xfd, 0x53, 0x80, 0x06, 0xfe, 0xc3, 0x14, 0xb6, + 0x7c, 0xd5, 0xef, 0x88, 0x00, 0xa7, 0xbc, 0xba, 0x2e, 0xfb, 0x91, 0x09, 0x33, 0xee, + 0x51, 0xdd, 0x02, 0x24, 0x35, 0x14, 0x2b, 0x05, 0x87, 0x83, 0x8a, 0x2a, 0xe9, 0xc4, + 0x0e, 0x54, 0x28, 0x11, 0xc2, 0x99, 0x33, 0xa8, 0x65, 0xd4, 0x6c, 0x3d, 0x14, 0x08, + 0xd2, 0xb5, 0x03, 0x64, 0xb5, 0x27, 0x7f, 0xf0, 0xaf, 0x90, 0x6d, 0x03, 0x10, 0x21, + 0xb3, 0x20, 0xdd, 0xfb, 0xda, 0x14, 0xec, 0xc9, 0x7d, 0x9d, 0x6c, 0x68, 0x4e, 0x43, + 0x6e, 0x39, 0x51, 0xe0, 0xa8, 0x6f, 0x49, 0xf1, 0xf4, 0xd3, 0xdb, 0x2a, 0x14, 0x11, + 0xed, 0x25, 0xe6, 0x6b, 0xed, 0x56, 0x25, 0x87, 0xb4, 0x1c, 0x94, 0x9c, 0x81, 0xcf, + 0x2c, 0x34, 0xb8, 0x5e, 0xc3, 0x14, 0x3d, 0x82, 0xcb, 0x29, 0xe8, 0xa7, 0x34, 0x37, + 0x3a, 0x46, 0x07, 0xa4, 0xf2, 0xb3, 0x94, 0xb0, 0x73, 0xed, 0x86, 0x3b, 0x14, 0x99, + 0xa4, 0xb5, 0x89, 0x01, 0x59, 0x18, 0x01, 0x08, 0x53, 0xcf, 0x17, 0x21, 0x14, 0x65, + 0xcf, 0x05, 0x7f, 0xaa, 0x5d, 0x14, 0xcc, 0x38, 0x3b, 0x85, 0xde, 0xc2, 0x59, 0xe6, + 0x22, 0xee, 0xa4, 0xea, 0x83, 0x72, 0x08, 0x7e, 0xdf, 0xea, 0xe1, 0xc3, 0x14, 0x7a, + 0xd9, 0x4d, 0x53, 0x9c, 0xc2, 0xff, 0xe3, 0x1d, 0xd6, 0x60, 0x78, 0x31, 0xb3, 0x2f, + 0x76, 0x12, 0xb7, 0xc7, 0xaf, 0x14, 0x10, 0x88, 0xf6, 0x6f, 0x1d, 0x27, 0x2d, 0xad, + 0x5b, 0x48, 0xca, 0xaf, 0xba, 0x63, 0x99, 0xbe, 0x23, 0x3b, 0xd5, 0xca, 0x14, 0x49, + 0x91, 0xa9, 0x0f, 0x47, 0xcd, 0xfe, 0xdb, 0xd6, 0xfb, 0xb3, 0xe9, 0xa4, 0xc2, 0xc2, + 0x15, 0xb3, 0xe7, 0xe5, 0xb6, 0x14, 0xdd, 0xe3, 0x77, 0xb0, 0xc3, 0x1b, 0x56, 0x2c, + 0x90, 0x67, 0x88, 0xc6, 0xc5, 0xa5, 0xd8, 0xb8, 0xee, 0xc3, 0xa0, 0x87, 0x90, 0xe4, + 0x9c, 0x5d, 0xcb, 0x20, 0x07, 0x92, + ]; + let value = Upgrade { + index: 7, + info: Info { + addrs: vec![ + Address { + bytes: Cow::Borrowed(&expected[6..26]), + }, + Address { + bytes: Cow::Borrowed(&expected[27..47]), + }, + Address { + bytes: Cow::Borrowed(&expected[48..68]), + }, + Address { + bytes: Cow::Borrowed(&expected[69..89]), + }, + Address { + bytes: Cow::Borrowed(&expected[90..110]), + }, + Address { + bytes: Cow::Borrowed(&expected[111..131]), + }, + Address { + bytes: Cow::Borrowed(&expected[132..152]), + }, + Address { + bytes: Cow::Borrowed(&expected[153..173]), + }, + Address { + bytes: Cow::Borrowed(&expected[174..194]), + }, + Address { + bytes: Cow::Borrowed(&expected[195..215]), + }, + Address { + bytes: Cow::Borrowed(&expected[216..236]), + }, + Address { + bytes: Cow::Borrowed(&expected[237..257]), + }, + Address { + bytes: Cow::Borrowed(&expected[258..278]), + }, + ], + expiration: 0x90e4_9c5d_cb20_0792, + }, + }; + + let actual = to_vec(&value).unwrap(); + assert_eq!(actual, expected); + } +}