From f0d84c36c5309f396967a1ae4151caa1c9f92000 Mon Sep 17 00:00:00 2001 From: "Frank V. Castellucci" Date: Fri, 21 May 2021 13:28:12 -0400 Subject: [PATCH 1/5] Bignum syscalls --- Cargo.lock | 32 +- programs/bpf/Cargo.lock | 1175 ++++--- programs/bpf/Cargo.toml | 1 + programs/bpf/build.rs | 1 + programs/bpf/c/src/bignumber/bignumber.c | 177 + programs/bpf/rust/bignumber/Cargo.toml | 19 + programs/bpf/rust/bignumber/src/lib.rs | 145 + programs/bpf/tests/programs.rs | 31 +- programs/bpf_loader/Cargo.toml | 1 + programs/bpf_loader/src/syscalls.rs | 4082 ++++++++++++++++++---- sdk/bpf/c/inc/solana_bignumber.h | 310 ++ sdk/program/Cargo.toml | 1 + sdk/program/src/bignumber.rs | 826 +++++ sdk/program/src/lib.rs | 1 + sdk/src/feature_set.rs | 4 + sdk/src/process_instruction.rs | 52 + 16 files changed, 5564 insertions(+), 1294 deletions(-) create mode 100644 programs/bpf/c/src/bignumber/bignumber.c create mode 100644 programs/bpf/rust/bignumber/Cargo.toml create mode 100644 programs/bpf/rust/bignumber/src/lib.rs create mode 100644 sdk/bpf/c/inc/solana_bignumber.h create mode 100644 sdk/program/src/bignumber.rs diff --git a/Cargo.lock b/Cargo.lock index 7b1559b5afba2c..bce7a95fc8594a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2669,9 +2669,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg 1.0.0", "num-traits", @@ -2679,9 +2679,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg 1.0.0", ] @@ -2753,15 +2753,15 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.29" +version = "0.10.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd" +checksum = "6d7830286ad6a3973c0f1d9b73738f69c76b739301d0229c4b96501695cbe4c8" dependencies = [ "bitflags", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "foreign-types", - "lazy_static", "libc", + "once_cell", "openssl-sys", ] @@ -2771,15 +2771,25 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +[[package]] +name = "openssl-src" +version = "111.15.0+1.1.1k" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a5f6ae2ac04393b217ea9f700cd04fa9bf3d93fae2872069f3d15d908af70a" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" -version = "0.9.57" +version = "0.9.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990" +checksum = "b6b0d6fb7d80f877617dfcb014e605e2b5ab2fb0afdf27935219bb6bd984cb98" dependencies = [ "autocfg 1.0.0", "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -4328,6 +4338,7 @@ dependencies = [ "log 0.4.11", "num-derive", "num-traits", + "openssl", "rand 0.7.3", "rand_core 0.6.2", "regex", @@ -5241,6 +5252,7 @@ dependencies = [ "log 0.4.11", "num-derive", "num-traits", + "openssl", "rand 0.7.3", "rustc_version 0.4.0", "rustversion", diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index fe4180392f3a71..d89cac8d2caf67 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "Inflector" version = "0.11.4" @@ -14,9 +12,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.12.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" +checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" dependencies = [ "gimli", ] @@ -48,14 +46,14 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "anyhow" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" +checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" [[package]] name = "arrayref" @@ -65,9 +63,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "ascii" @@ -77,9 +75,9 @@ checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" [[package]] name = "assert_matches" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695579f0f2520f3774bb40461e5adb066459d4e0af4d59d20175484fb8e9edf1" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-trait" @@ -87,9 +85,9 @@ version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -100,24 +98,26 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.48" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" +checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282" dependencies = [ "addr2line", - "cfg-if 0.1.10", + "cc", + "cfg-if 1.0.0", "libc", + "miniz_oxide", "object", "rustc-demangle", "serde", @@ -164,9 +164,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake3" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ff35b701f3914bdb8fad3368d822c766ef2858b2583198e41639b936f09d3f" +checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" dependencies = [ "arrayref", "arrayvec", @@ -185,8 +185,8 @@ checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ "block-padding 0.1.5", "byte-tools", - "byteorder 1.3.4", - "generic-array 0.12.3", + "byteorder 1.4.3", + "generic-array 0.12.4", ] [[package]] @@ -216,11 +216,11 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "borsh" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5a26c53ddf60281f18e7a29b20db7ba3db82a9d81b9650bfaa02d646f50d364" +checksum = "09a7111f797cc721407885a323fb071636aee57f750b1a4ddc27397eba168a74" dependencies = [ - "borsh-derive 0.8.1", + "borsh-derive 0.8.2", "hashbrown", ] @@ -236,15 +236,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b637a47728b78a78cd7f4b85bf06d71ef4221840e059a38f048be2422bf673b2" +checksum = "307f3740906bac2c118a8122fe22681232b244f1369273e45f1156b45c43d2dd" dependencies = [ - "borsh-derive-internal 0.8.1", - "borsh-schema-derive-internal 0.8.1", + "borsh-derive-internal 0.8.2", + "borsh-schema-derive-internal 0.8.2", "proc-macro-crate", - "proc-macro2 1.0.24", - "syn 1.0.67", + "proc-macro2 1.0.27", + "syn 1.0.73", ] [[package]] @@ -256,19 +256,19 @@ dependencies = [ "borsh-derive-internal 0.9.0", "borsh-schema-derive-internal 0.9.0", "proc-macro-crate", - "proc-macro2 1.0.24", - "syn 1.0.67", + "proc-macro2 1.0.27", + "syn 1.0.73", ] [[package]] name = "borsh-derive-internal" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d813fa25eb0bed78c36492cff4415f38c760d6de833d255ba9095bd8ebb7d725" +checksum = "d2104c73179359431cc98e016998f2f23bc7a05bc53e79741bcba705f30047bc" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -277,20 +277,20 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e321a130a3ac4b88eb59a6d670bde11eec9721a397b77e0f2079060e2a1b785" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "borsh-schema-derive-internal" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf78ee4a98c8cb9eba1bac3d3e2a1ea3d7673c719ce691e67b5cbafc472d3b7" +checksum = "ae29eb8418fcd46f723f8691a2ac06857d31179d33d2f2d91eb13967de97c728" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -299,9 +299,9 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15151a485164b319cc7a5160fe4316dc469a27993f71b73d7617dc9032ff0fd7" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -318,9 +318,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bumpalo" -version = "3.3.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" +checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" [[package]] name = "bv" @@ -346,9 +346,9 @@ checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" @@ -356,16 +356,16 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ - "byteorder 1.3.4", + "byteorder 1.4.3", "either", "iovec", ] [[package]] name = "bytes" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" @@ -385,9 +385,9 @@ dependencies = [ [[package]] name = "bzip2-sys" -version = "0.1.9+1.0.8" +version = "0.1.11+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad3b39a260062fca31f7b0b12f207e8f2590a67d32ec7d59c20484b07ea7285e" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" dependencies = [ "cc", "libc", @@ -396,9 +396,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" dependencies = [ "jobserver", ] @@ -426,7 +426,7 @@ dependencies = [ "num-traits", "serde", "time", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -469,7 +469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" dependencies = [ "ascii", - "byteorder 1.3.4", + "byteorder 1.4.3", "either", "memchr", "unreachable", @@ -487,15 +487,9 @@ dependencies = [ "regex", "terminal_size", "unicode-width", - "winapi 0.3.8", + "winapi 0.3.9", ] -[[package]] -name = "const_fn" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -520,20 +514,20 @@ checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "cpufeatures" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" +checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -543,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.1", + "crossbeam-utils 0.8.5", ] [[package]] @@ -564,8 +558,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.1", - "crossbeam-utils 0.8.1", + "crossbeam-epoch 0.9.5", + "crossbeam-utils 0.8.5", ] [[package]] @@ -579,21 +573,20 @@ dependencies = [ "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset 0.5.4", + "memoffset 0.5.6", "scopeguard", ] [[package]] name = "crossbeam-epoch" -version = "0.9.1" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ "cfg-if 1.0.0", - "const_fn", - "crossbeam-utils 0.8.1", + "crossbeam-utils 0.8.5", "lazy_static", - "memoffset 0.6.1", + "memoffset 0.6.4", "scopeguard", ] @@ -621,11 +614,10 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "autocfg", "cfg-if 1.0.0", "lazy_static", ] @@ -668,11 +660,11 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "2.1.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" +checksum = "434e1720189a637d44fe464f4df1e6eb900b4835255b14354497c78af37d9bb8" dependencies = [ - "byteorder 1.3.4", + "byteorder 1.4.3", "digest 0.8.1", "rand_core 0.5.1", "subtle", @@ -681,11 +673,11 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" +checksum = "639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3" dependencies = [ - "byteorder 1.3.4", + "byteorder 1.4.3", "digest 0.9.0", "rand_core 0.5.1", "subtle", @@ -714,13 +706,13 @@ dependencies = [ [[package]] name = "derivative" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaed5874effa6cde088c644ddcdcb4ffd1511391c5be4fdd7a5ccd02c7e4a183" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -741,7 +733,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3", + "generic-array 0.12.4", ] [[package]] @@ -780,7 +772,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -791,9 +783,9 @@ checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] name = "ed25519" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf038a7b6fd7ef78ad3348b63f3a17550877b0e28f8d68bcc94894d1412158bc" +checksum = "8d0860415b12243916284c67a9be413e044ee6668247b99ba26d94b2bc06c8f6" dependencies = [ "serde", "signature", @@ -805,7 +797,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek 3.0.0", + "curve25519-dalek 3.1.0", "ed25519", "rand 0.7.3", "serde", @@ -829,21 +821,21 @@ dependencies = [ [[package]] name = "educe" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ed56329d95e524ef98177ad672881bdfe7f22f254eb6ae80deb6fdd2ab20c4" +checksum = "f86b50932a01e7ec5c06160492ab660fb19b6bb2a7878030dd6cd68d21df9d4d" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "either" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "elf" @@ -862,31 +854,31 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.23" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] name = "enum-ordinalize" -version = "3.1.9" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d52ff39419d3e16961ecfb9e32f5042bdaacf9a4cc553d2d688057117bae49b" +checksum = "0b166c9e378360dd5a6666a9604bb4f54ae0cac39023ffbac425e917a2a04fef" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "env_logger" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", "humantime", @@ -911,9 +903,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", "synstructure", ] @@ -931,14 +923,14 @@ checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" [[package]] name = "filetime" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695" +checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "redox_syscall 0.1.56", - "winapi 0.3.8", + "redox_syscall 0.2.9", + "winapi 0.3.9", ] [[package]] @@ -1002,15 +994,15 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.1.29" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" +checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" dependencies = [ "futures-channel", "futures-core", @@ -1023,9 +1015,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" +checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" dependencies = [ "futures-core", "futures-sink", @@ -1033,15 +1025,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" +checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" [[package]] name = "futures-executor" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9" +checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" dependencies = [ "futures-core", "futures-task", @@ -1050,43 +1042,42 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" +checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" [[package]] name = "futures-macro" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" +checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" dependencies = [ + "autocfg", "proc-macro-hack", - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "futures-sink" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6" +checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" [[package]] name = "futures-task" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" -dependencies = [ - "once_cell", -] +checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" [[package]] name = "futures-util" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" +checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" dependencies = [ + "autocfg", "futures-channel", "futures-core", "futures-io", @@ -1094,7 +1085,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.4", + "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1103,9 +1094,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ "typenum", ] @@ -1128,36 +1119,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.1+wasi-snapshot-preview1", + "wasi 0.10.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.21.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" +checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" [[package]] name = "glob" @@ -1167,9 +1158,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "goblin" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c69552f48b18aa6102ce0c82dd9bc9d3f8af5fc0a5797069b1b466b90570e39c" +checksum = "669cdc3826f69a51d3f8fc3f86de81c2378110254f678b8407977736122057a4" dependencies = [ "log", "plain", @@ -1178,9 +1169,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d832b01df74254fe364568d6ddc294443f61cbec82816b60904303af87efae78" +checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726" dependencies = [ "bytes 1.0.1", "fnv", @@ -1190,7 +1181,7 @@ dependencies = [ "http", "indexmap", "slab", - "tokio 1.4.0", + "tokio 1.7.1", "tokio-util", "tracing", ] @@ -1201,7 +1192,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" dependencies = [ - "byteorder 1.3.4", + "byteorder 1.4.3", ] [[package]] @@ -1215,9 +1206,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.13" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] @@ -1282,48 +1273,49 @@ dependencies = [ [[package]] name = "http" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" dependencies = [ - "bytes 0.5.4", + "bytes 1.0.1", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" +checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" dependencies = [ "bytes 1.0.1", "http", + "pin-project-lite", ] [[package]] name = "httparse" -version = "1.3.4" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" [[package]] name = "humantime" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.4" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7" +checksum = "07d6baa1b441335f3ce5098ac421fb6547c46dda735ca1bc6d0153c838f9dd83" dependencies = [ "bytes 1.0.1", "futures-channel", @@ -1335,9 +1327,9 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project", - "socket2", - "tokio 1.4.0", + "pin-project-lite", + "socket2 0.4.0", + "tokio 1.7.1", "tower-service", "tracing", "want", @@ -1353,16 +1345,16 @@ dependencies = [ "hyper", "log", "rustls", - "tokio 1.4.0", + "tokio 1.7.1", "tokio-rustls", "webpki", ] [[package]] name = "idna" -version = "0.2.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -1397,7 +1389,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", ] [[package]] @@ -1420,9 +1412,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" [[package]] name = "itertools" @@ -1444,35 +1436,37 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.49" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821" +checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" dependencies = [ "wasm-bindgen", ] [[package]] name = "jsonrpc-core" -version = "17.0.0" +version = "17.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07569945133257ff557eb37b015497104cea61a2c9edaf126c1cbd6e8332397f" +checksum = "d4467ab6dfa369b69e52bd0692e480c4d117410538526a57a304a0f2250fd95e" dependencies = [ - "futures 0.3.12", + "futures 0.3.15", + "futures-executor", + "futures-util", "log", "serde", "serde_derive", @@ -1517,7 +1511,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" dependencies = [ "cfg-if 1.0.0", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1541,9 +1535,9 @@ dependencies = [ [[package]] name = "libsecp256k1-core" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daaa407ce05dc49849836840fb2542edcadafc4f55e314840cbb5b49359a6919" +checksum = "4ee11012b293ea30093c129173cac4335513064094619f4639a25b310fd33c11" dependencies = [ "crunchy", "digest 0.9.0", @@ -1585,20 +1579,20 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" dependencies = [ "scopeguard", ] [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -1639,18 +1633,18 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ "autocfg", ] [[package]] name = "memoffset" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" dependencies = [ "autocfg", ] @@ -1673,9 +1667,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.22" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" dependencies = [ "cfg-if 0.1.10", "fuchsia-zircon", @@ -1692,15 +1686,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" dependencies = [ "libc", "log", - "miow 0.3.6", + "miow 0.3.7", "ntapi", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1711,7 +1705,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", - "mio 0.6.22", + "mio 0.6.23", ] [[package]] @@ -1728,12 +1722,11 @@ dependencies = [ [[package]] name = "miow" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "socket2", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1762,7 +1755,7 @@ checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1779,18 +1772,18 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "num-bigint" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" +checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" dependencies = [ "autocfg", "num-integer", @@ -1799,20 +1792,20 @@ dependencies = [ [[package]] name = "num-derive" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg", "num-traits", @@ -1820,9 +1813,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] @@ -1854,9 +1847,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -1867,15 +1860,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.19.0" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" +checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +dependencies = [ + "memchr", +] [[package]] name = "once_cell" -version = "1.5.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" dependencies = [ "parking_lot 0.11.1", ] @@ -1894,33 +1890,43 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.32" +version = "0.10.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" +checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885" dependencies = [ "bitflags", "cfg-if 1.0.0", "foreign-types", - "lazy_static", "libc", + "once_cell", "openssl-sys", ] [[package]] name = "openssl-probe" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" + +[[package]] +name = "openssl-src" +version = "111.15.0+1.1.1k" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a5f6ae2ac04393b217ea9f700cd04fa9bf3d93fae2872069f3d15d908af70a" +dependencies = [ + "cc", +] [[package]] name = "openssl-sys" -version = "0.9.60" +version = "0.9.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d" dependencies = [ "autocfg", "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -1932,12 +1938,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91cea1dfd50064e52db033179952d18c770cbc5dfefc8eba45d619357ba3914" dependencies = [ "async-trait", - "futures 0.3.12", + "futures 0.3.15", "js-sys", "lazy_static", "percent-encoding", "pin-project", - "rand 0.8.2", + "rand 0.8.4", "thiserror", ] @@ -1958,9 +1964,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cec33dfceabec83cd0e95a5ce9d20e76ab3a5cbfef59659b8c927f69b93ed8ae" dependencies = [ "Inflector", - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -1991,8 +1997,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", - "lock_api 0.4.2", - "parking_lot_core 0.8.2", + "lock_api 0.4.4", + "parking_lot_core 0.8.3", ] [[package]] @@ -2004,10 +2010,10 @@ dependencies = [ "cfg-if 0.1.10", "cloudabi", "libc", - "redox_syscall 0.1.56", + "redox_syscall 0.1.57", "rustc_version 0.2.3", "smallvec 0.6.14", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2019,23 +2025,23 @@ dependencies = [ "cfg-if 0.1.10", "cloudabi", "libc", - "redox_syscall 0.1.56", + "redox_syscall 0.1.57", "smallvec 1.6.1", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.1.56", + "redox_syscall 0.2.9", "smallvec 1.6.1", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2064,35 +2070,29 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "pin-project-lite" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" - -[[package]] -name = "pin-project-lite" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" +checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" [[package]] name = "pin-utils" @@ -2102,9 +2102,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "plain" @@ -2114,9 +2114,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "ppv-lite86" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro-crate" @@ -2135,9 +2135,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" @@ -2150,11 +2150,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ - "unicode-xid 0.2.0", + "unicode-xid 0.2.2", ] [[package]] @@ -2177,11 +2177,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", ] [[package]] @@ -2190,7 +2190,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -2200,14 +2200,14 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", ] [[package]] @@ -2222,12 +2222,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -2236,16 +2236,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", ] [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.1", + "getrandom 0.2.3", ] [[package]] @@ -2259,11 +2259,11 @@ dependencies = [ [[package]] name = "rand_hc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -2295,22 +2295,22 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.1", + "crossbeam-utils 0.8.5", "lazy_static", "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.4" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" dependencies = [ "bitflags", ] @@ -2321,8 +2321,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.1", - "redox_syscall 0.2.4", + "getrandom 0.2.3", + "redox_syscall 0.2.9", ] [[package]] @@ -2344,18 +2344,18 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remove_dir_all" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "reqwest" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4" +checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22" dependencies = [ "base64 0.13.0", "bytes 1.0.1", @@ -2372,12 +2372,12 @@ dependencies = [ "log", "mime", "percent-encoding", - "pin-project-lite 0.2.4", + "pin-project-lite", "rustls", "serde", "serde_json", "serde_urlencoded", - "tokio 1.4.0", + "tokio 1.7.1", "tokio-rustls", "url", "wasm-bindgen", @@ -2399,7 +2399,7 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2409,14 +2409,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" [[package]] name = "rustc-hash" @@ -2444,9 +2444,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ "base64 0.13.0", "log", @@ -2463,9 +2463,9 @@ checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" [[package]] name = "ryu" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "same-file" @@ -2483,7 +2483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2494,29 +2494,29 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scroll" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" +checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" -version = "0.10.2" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" +checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "sct" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", "untrusted", @@ -2524,9 +2524,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.0.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" +checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" dependencies = [ "bitflags", "core-foundation", @@ -2537,9 +2537,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" +checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284" dependencies = [ "core-foundation-sys", "libc", @@ -2590,9 +2590,9 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -2678,24 +2678,24 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] [[package]] name = "signature" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65211b7b6fc3f14ff9fc7a2011a434e3e6880585bd2e9e9396315ae24cbf7852" +checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" [[package]] name = "slab" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" [[package]] name = "smallvec" @@ -2714,14 +2714,23 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "socket2" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.1.56", - "winapi 0.3.8", + "winapi 0.3.9", +] + +[[package]] +name = "socket2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +dependencies = [ + "libc", + "winapi 0.3.9", ] [[package]] @@ -2752,13 +2761,13 @@ dependencies = [ "bincode", "borsh 0.9.0", "borsh-derive 0.9.0", - "futures 0.3.12", - "mio 0.7.11", + "futures 0.3.15", + "mio 0.7.13", "solana-banks-interface", "solana-program 1.8.0", "solana-sdk", "tarpc", - "tokio 1.4.0", + "tokio 1.7.1", "tokio-serde", ] @@ -2766,7 +2775,7 @@ dependencies = [ name = "solana-banks-interface" version = "1.8.0" dependencies = [ - "mio 0.7.11", + "mio 0.7.13", "serde", "solana-sdk", "tarpc", @@ -2777,15 +2786,15 @@ name = "solana-banks-server" version = "1.8.0" dependencies = [ "bincode", - "futures 0.3.12", + "futures 0.3.15", "log", - "mio 0.7.11", + "mio 0.7.13", "solana-banks-interface", "solana-metrics", "solana-runtime", "solana-sdk", "tarpc", - "tokio 1.4.0", + "tokio 1.7.1", "tokio-serde", "tokio-stream", ] @@ -2795,11 +2804,12 @@ name = "solana-bpf-loader-program" version = "1.8.0" dependencies = [ "bincode", - "byteorder 1.3.4", + "byteorder 1.4.3", "log", "num-derive", "num-traits", - "rand_core 0.6.2", + "openssl", + "rand_core 0.6.3", "regex", "sha3", "solana-measure", @@ -2814,11 +2824,11 @@ name = "solana-bpf-programs" version = "1.8.0" dependencies = [ "bincode", - "byteorder 1.3.4", + "byteorder 1.4.3", "elf", "itertools 0.10.1", "log", - "miow 0.3.6", + "miow 0.3.7", "net2", "solana-account-decoder", "solana-bpf-loader-program", @@ -2854,6 +2864,13 @@ dependencies = [ "solana-program 1.8.0", ] +[[package]] +name = "solana-bpf-rust-bignumber" +version = "1.8.0" +dependencies = [ + "solana-program 1.8.0", +] + [[package]] name = "solana-bpf-rust-call-depth" version = "1.8.0" @@ -2879,7 +2896,7 @@ dependencies = [ name = "solana-bpf-rust-dep-crate" version = "1.8.0" dependencies = [ - "byteorder 1.3.4", + "byteorder 1.4.3", "solana-program 1.8.0", ] @@ -3036,7 +3053,7 @@ dependencies = [ name = "solana-bpf-rust-rand" version = "1.8.0" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", "rand 0.7.3", "solana-program 1.8.0", ] @@ -3183,7 +3200,7 @@ dependencies = [ "solana-version", "solana-vote-program", "thiserror", - "tokio 1.4.0", + "tokio 1.7.1", "tungstenite", "url", ] @@ -3195,7 +3212,7 @@ dependencies = [ "bincode", "chrono", "log", - "rand_core 0.6.2", + "rand_core 0.6.3", "serde", "serde_derive", "solana-sdk", @@ -3208,7 +3225,7 @@ dependencies = [ "backtrace", "bytes 0.4.12", "cc", - "curve25519-dalek 2.1.0", + "curve25519-dalek 2.1.2", "ed25519-dalek", "either", "lazy_static", @@ -3219,9 +3236,9 @@ dependencies = [ "ring", "serde", "syn 0.15.44", - "syn 1.0.67", + "syn 1.0.73", "tokio 0.1.22", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3229,7 +3246,7 @@ name = "solana-faucet" version = "1.8.0" dependencies = [ "bincode", - "byteorder 1.3.4", + "byteorder 1.4.3", "clap", "log", "serde", @@ -3242,14 +3259,14 @@ dependencies = [ "solana-version", "spl-memo", "thiserror", - "tokio 1.4.0", + "tokio 1.7.1", ] [[package]] name = "solana-frozen-abi" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95c481f0f29753f5b2d382628abae98a1dd87b572ddc7cbe5fe55ca62b6f7f07" +checksum = "e8deae875976c64b1cecfc501575ff0185aa3953be29691e83ebab04f94490ac" dependencies = [ "bs58 0.3.1", "bv", @@ -3260,8 +3277,8 @@ dependencies = [ "serde", "serde_derive", "sha2", - "solana-frozen-abi-macro 1.7.1", - "solana-logger 1.7.1", + "solana-frozen-abi-macro 1.7.2", + "solana-logger 1.7.2", "thiserror", ] @@ -3285,31 +3302,31 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2068bcc47160ac9081893439b10a05e4bbe85cc0f6bccb6f1b0815423fbdd0c" +checksum = "4b59337556e8d6240dbc75c793af59accbcbbd93e77a45a346c20fc296b3845d" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", + "proc-macro2 1.0.27", + "quote 1.0.9", "rustc_version 0.2.3", - "syn 1.0.67", + "syn 1.0.73", ] [[package]] name = "solana-frozen-abi-macro" version = "1.8.0" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", + "proc-macro2 1.0.27", + "quote 1.0.9", "rustc_version 0.4.0", - "syn 1.0.67", + "syn 1.0.73", ] [[package]] name = "solana-logger" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ea5932e186629f47859924b3773cfd8bcb4b8796898ac85c1fa0a6a2024e5c6" +checksum = "eb0c0bd132b3efa7b6c561618da1d31ff0688c7f0281545d11199f56ee6ca7cb" dependencies = [ "env_logger", "lazy_static", @@ -3357,28 +3374,28 @@ dependencies = [ "rand 0.7.3", "serde", "serde_derive", - "socket2", + "socket2 0.3.19", "solana-clap-utils", "solana-logger 1.8.0", "solana-sdk", "solana-version", - "tokio 1.4.0", + "tokio 1.7.1", "url", ] [[package]] name = "solana-program" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2df39c63e21c5b58e2012e7675bed5e8dd5100470ffddedcafb78f5a7e3abe" +checksum = "ea60f6b6d29488e780ce5a9cd4f7ce0d83aebe58910ae2f10cee36f69e266f30" dependencies = [ "bincode", "blake3", - "borsh 0.8.1", - "borsh-derive 0.8.1", + "borsh 0.8.2", + "borsh-derive 0.8.2", "bs58 0.3.1", "bv", - "curve25519-dalek 2.1.0", + "curve25519-dalek 2.1.2", "hex", "itertools 0.9.0", "lazy_static", @@ -3393,10 +3410,10 @@ dependencies = [ "serde_derive", "sha2", "sha3", - "solana-frozen-abi 1.7.1", - "solana-frozen-abi-macro 1.7.1", - "solana-logger 1.7.1", - "solana-sdk-macro 1.7.1", + "solana-frozen-abi 1.7.2", + "solana-frozen-abi-macro 1.7.2", + "solana-logger 1.7.2", + "solana-sdk-macro 1.7.2", "thiserror", ] @@ -3410,13 +3427,14 @@ dependencies = [ "borsh-derive 0.9.0", "bs58 0.4.0", "bv", - "curve25519-dalek 2.1.0", + "curve25519-dalek 2.1.2", "hex", "itertools 0.10.1", "lazy_static", "log", "num-derive", "num-traits", + "openssl", "rand 0.7.3", "rustc_version 0.4.0", "rustversion", @@ -3442,7 +3460,7 @@ dependencies = [ "chrono", "chrono-humanize", "log", - "mio 0.7.11", + "mio 0.7.13", "serde", "serde_derive", "solana-banks-client", @@ -3453,7 +3471,7 @@ dependencies = [ "solana-sdk", "solana-vote-program", "thiserror", - "tokio 1.4.0", + "tokio 1.7.1", ] [[package]] @@ -3491,7 +3509,7 @@ dependencies = [ "bincode", "blake3", "bv", - "byteorder 1.3.4", + "byteorder 1.4.3", "bzip2", "crossbeam-channel", "dashmap", @@ -3540,7 +3558,7 @@ dependencies = [ "bincode", "bs58 0.4.0", "bv", - "byteorder 1.3.4", + "byteorder 1.4.3", "chrono", "derivation-path", "digest 0.9.0", @@ -3560,7 +3578,7 @@ dependencies = [ "qstring", "rand 0.7.3", "rand_chacha 0.2.2", - "rand_core 0.6.2", + "rand_core 0.6.3", "rustc_version 0.4.0", "rustversion", "serde", @@ -3581,15 +3599,15 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6473d8fa445520564c84e8803320721404d160ffd876a125326a726541f11534" +checksum = "ea740a2599496175f2d1bd47f54d799c7f2d8c00152a4eb9aed21047cdb30c23" dependencies = [ "bs58 0.3.1", - "proc-macro2 1.0.24", - "quote 1.0.6", + "proc-macro2 1.0.27", + "quote 1.0.9", "rustversion", - "syn 1.0.67", + "syn 1.0.73", ] [[package]] @@ -3597,10 +3615,10 @@ name = "solana-sdk-macro" version = "1.8.0" dependencies = [ "bs58 0.4.0", - "proc-macro2 1.0.24", - "quote 1.0.6", + "proc-macro2 1.0.27", + "quote 1.0.9", "rustversion", - "syn 1.0.67", + "syn 1.0.73", ] [[package]] @@ -3697,7 +3715,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44596a3613a44f76a7f6e5205464a1e78d1529fa19e8eacde0b9e55a6387f50" dependencies = [ - "byteorder 1.3.4", + "byteorder 1.4.3", "combine", "goblin", "hash32", @@ -3722,7 +3740,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4adc47eebe5d2b662cbaaba1843719c28a67e5ec5d0460bc3ca60900a51f74e2" dependencies = [ - "solana-program 1.7.1", + "solana-program 1.7.2", "spl-token", ] @@ -3732,7 +3750,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" dependencies = [ - "solana-program 1.7.1", + "solana-program 1.7.2", ] [[package]] @@ -3745,7 +3763,7 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.7.1", + "solana-program 1.7.2", "thiserror", ] @@ -3769,9 +3787,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "subtle" -version = "2.2.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" +checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "symlink" @@ -3792,25 +3810,25 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.67" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "unicode-xid 0.2.0", + "proc-macro2 1.0.27", + "quote 1.0.9", + "unicode-xid 0.2.2", ] [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", - "unicode-xid 0.2.0", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", + "unicode-xid 0.2.2", ] [[package]] @@ -3832,16 +3850,16 @@ checksum = "82cb992a07637db1bcc0e4511d0c58c3f3a03f509d7c6cc2826f7646deac2032" dependencies = [ "anyhow", "fnv", - "futures 0.3.12", + "futures 0.3.15", "humantime", "opentelemetry", "pin-project", - "rand 0.8.2", + "rand 0.8.4", "serde", "static_assertions", "tarpc-plugins", "thiserror", - "tokio 1.4.0", + "tokio 1.7.1", "tokio-serde", "tokio-util", "tracing", @@ -3854,9 +3872,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea80818e6c75f81d961d7426c1b938cbea6b3a51533b5ee71b61f82166b7ef3d" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -3867,29 +3885,29 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", "libc", - "rand 0.8.2", - "redox_syscall 0.2.4", + "rand 0.8.4", + "redox_syscall 0.2.9", "remove_dir_all", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "termcolor" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd2d183bd3fac5f5fe38ddbeb4dc9aec4a39a9d7d59e7491d900302da01cbe1" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3916,9 +3934,9 @@ version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -3932,12 +3950,13 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "winapi 0.3.8", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", ] [[package]] @@ -3960,9 +3979,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" dependencies = [ "tinyvec_macros", ] @@ -3980,8 +3999,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", - "mio 0.6.22", + "futures 0.1.31", + "mio 0.6.23", "num_cpus", "tokio-codec", "tokio-current-thread", @@ -3999,22 +4018,22 @@ dependencies = [ [[package]] name = "tokio" -version = "1.4.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722" +checksum = "5fb2ed024293bb19f7a5dc54fe83bf86532a44c12a2bb8ba40d64a4509395ca2" dependencies = [ "autocfg", "bytes 1.0.1", "libc", "memchr", - "mio 0.7.11", + "mio 0.7.13", "num_cpus", "once_cell", "parking_lot 0.11.1", - "pin-project-lite 0.2.4", + "pin-project-lite", "signal-hook-registry", "tokio-macros", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4024,7 +4043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.31", "tokio-io", ] @@ -4034,7 +4053,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures 0.1.29", + "futures 0.1.31", "tokio-executor", ] @@ -4045,7 +4064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.31", ] [[package]] @@ -4054,7 +4073,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures 0.1.29", + "futures 0.1.31", "tokio-io", "tokio-threadpool", ] @@ -4066,19 +4085,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.31", "log", ] [[package]] name = "tokio-macros" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" +checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] @@ -4088,10 +4107,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.31", "lazy_static", "log", - "mio 0.6.22", + "mio 0.6.23", "num_cpus", "parking_lot 0.9.0", "slab", @@ -4107,7 +4126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ "rustls", - "tokio 1.4.0", + "tokio 1.7.1", "webpki", ] @@ -4133,8 +4152,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066" dependencies = [ "futures-core", - "pin-project-lite 0.2.4", - "tokio 1.4.0", + "pin-project-lite", + "tokio 1.7.1", ] [[package]] @@ -4144,7 +4163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ "fnv", - "futures 0.1.29", + "futures 0.1.31", ] [[package]] @@ -4154,9 +4173,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.31", "iovec", - "mio 0.6.22", + "mio 0.6.23", "tokio-io", "tokio-reactor", ] @@ -4170,7 +4189,7 @@ dependencies = [ "crossbeam-deque 0.7.3", "crossbeam-queue", "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.31", "lazy_static", "log", "num_cpus", @@ -4185,7 +4204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.31", "slab", "tokio-executor", ] @@ -4197,9 +4216,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.31", "log", - "mio 0.6.22", + "mio 0.6.23", "tokio-codec", "tokio-io", "tokio-reactor", @@ -4207,16 +4226,16 @@ dependencies = [ [[package]] name = "tokio-uds" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.31", "iovec", "libc", "log", - "mio 0.6.22", + "mio 0.6.23", "mio-uds", "tokio-codec", "tokio-io", @@ -4225,17 +4244,17 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.4" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec31e5cc6b46e653cf57762f36f71d5e6386391d88a72fd6db4508f8f676fb29" +checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" dependencies = [ "bytes 1.0.1", "futures-core", "futures-sink", "log", - "pin-project-lite 0.2.4", + "pin-project-lite", "slab", - "tokio 1.4.0", + "tokio 1.7.1", ] [[package]] @@ -4249,19 +4268,19 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.21" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" +checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "log", - "pin-project-lite 0.1.5", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -4272,16 +4291,16 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", ] [[package]] name = "tracing-core" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" dependencies = [ "lazy_static", ] @@ -4311,9 +4330,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" @@ -4322,8 +4341,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" dependencies = [ "base64 0.11.0", - "byteorder 1.3.4", - "bytes 0.5.4", + "byteorder 1.4.3", + "bytes 0.5.6", "http", "httparse", "input_buffer", @@ -4337,24 +4356,24 @@ dependencies = [ [[package]] name = "typenum" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" dependencies = [ "matches", ] [[package]] name = "unicode-normalization" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] @@ -4373,9 +4392,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "unreachable" @@ -4404,9 +4423,9 @@ dependencies = [ [[package]] name = "url" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", "idna", @@ -4416,15 +4435,15 @@ dependencies = [ [[package]] name = "utf-8" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "vcpkg" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vec_map" @@ -4434,9 +4453,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "void" @@ -4446,12 +4465,12 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "walkdir" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", - "winapi 0.3.8", + "winapi 0.3.9", "winapi-util", ] @@ -4473,15 +4492,15 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.1+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.72" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe" +checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4491,24 +4510,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.72" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3" +checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.22" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468" +checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4518,38 +4537,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.72" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b" +checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" dependencies = [ - "quote 1.0.6", + "quote 1.0.9", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.72" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d" +checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.72" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa" +checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" [[package]] name = "web-sys" -version = "0.3.40" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" +checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" dependencies = [ "js-sys", "wasm-bindgen", @@ -4557,9 +4576,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ "ring", "untrusted", @@ -4567,9 +4586,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82015b7e0b8bad8185994674a13a93306bea76cf5a16c5a181382fd3a5ec2376" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ "webpki", ] @@ -4582,9 +4601,9 @@ checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", @@ -4608,7 +4627,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4623,7 +4642,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4656,39 +4675,39 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" +checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.73", "synstructure", ] [[package]] name = "zstd" -version = "0.5.3+zstd.1.4.5" +version = "0.5.4+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8" +checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "2.0.5+zstd.1.4.5" +version = "2.0.6+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055" +checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e" dependencies = [ "libc", "zstd-sys", @@ -4696,9 +4715,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.4.17+zstd.1.4.5" +version = "1.4.18+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b" +checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81" dependencies = [ "cc", "glob", diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index fadbfb9737289d..0fb9f037345480 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -45,6 +45,7 @@ members = [ "rust/128bit", "rust/128bit_dep", "rust/alloc", + "rust/bignumber", "rust/call_depth", "rust/caller_access", "rust/custom_heap", diff --git a/programs/bpf/build.rs b/programs/bpf/build.rs index 8d16b204a76cc9..655e00b814bc56 100644 --- a/programs/bpf/build.rs +++ b/programs/bpf/build.rs @@ -60,6 +60,7 @@ fn main() { let rust_programs = [ "128bit", "alloc", + "bignumber", "call_depth", "caller_access", "custom_heap", diff --git a/programs/bpf/c/src/bignumber/bignumber.c b/programs/bpf/c/src/bignumber/bignumber.c new file mode 100644 index 00000000000000..adb7bcb1189243 --- /dev/null +++ b/programs/bpf/c/src/bignumber/bignumber.c @@ -0,0 +1,177 @@ +/** + * @brief Example C based BPF program that tests the BugNum syscalls + */ +#include +#include + +static const char LONG_DEC_STRING[] = + "1470463693494555670176851280755142329532258274256991544781479988"; +static const char NEG_LONG_DEC_STRING[] = + "-1470463693494555670176851280755142329532258274256991544781479988"; + +void test_constructors() { + sol_log("BigNumber constructors"); + + { + SolBigNumber bn_0 = sol_bignum_from_u32(0); + SolBigNumber bn_u32 = sol_bignum_init(1); + sol_assert(sol_bignum_equal(&bn_0, &bn_u32)); + sol_bignum_deinit(&bn_u32); + sol_bignum_deinit(&bn_0); + } + { + SolBigNumber max_bn_u32 = sol_bignum_from_u32(UINT32_MAX); + uint8_t expected[] = {255, 255, 255, 255}; + sol_assert(!sol_memcmp(max_bn_u32.data_addr, &expected, 4)); + sol_bignum_deinit(&max_bn_u32); + } + { + uint8_t bytes[] = {255, 255, 255, 255, 255, 255, 255, 255}; + SolBigNumber bn = sol_bignum_from_bytes(bytes, SOL_ARRAY_SIZE(bytes)); + sol_assert(!sol_memcmp(bn.data_addr, bytes, 8)); + sol_bignum_deinit(&bn); + } + { + uint8_t *bytes = sol_calloc(1024, 1); + sol_memset(bytes, 255, 1024); + SolBigNumber bn_long = sol_bignum_from_bytes(bytes, 1024); + sol_assert(!sol_memcmp(bn_long.data_addr, bytes, 1024)); + sol_bignum_deinit(&bn_long); + } + { + SolBigNumber bn_from_dec = + sol_bignum_from_dec_str(LONG_DEC_STRING, sol_strlen(LONG_DEC_STRING)); + sol_assert(!bn_from_dec.is_negative); + sol_bignum_deinit(&bn_from_dec); + } + { + SolBigNumber bn_from_dec = sol_bignum_from_dec_str( + NEG_LONG_DEC_STRING, sol_strlen(NEG_LONG_DEC_STRING)); + sol_assert(bn_from_dec.is_negative); + sol_bignum_deinit(&bn_from_dec); + } +} + +void test_basic_maths() { + sol_log("BigNumber Basic Maths"); + + SolBigNumber bn_5 = sol_bignum_from_u32(5); + SolBigNumber bn_258 = sol_bignum_from_u32(258); + + SolBigNumber added = sol_bignum_add(&bn_5, &bn_258); + uint8_t add_expected[] = {1, 7}; + sol_assert(!sol_memcmp(added.data_addr, add_expected, 2)); + sol_bignum_deinit(&added); + + SolBigNumber subed = sol_bignum_sub(&bn_5, &bn_258); + uint8_t sub_expected[] = {253}; + sol_assert(!sol_memcmp(subed.data_addr, sub_expected, 1)); + sol_assert(subed.is_negative); + sol_bignum_deinit(&subed); + + SolBigNumber muled = sol_bignum_mul(&bn_5, &bn_5); + uint8_t mul_expected[] = {25}; + sol_assert(!sol_memcmp(muled.data_addr, mul_expected, 1)); + sol_bignum_deinit(&muled); + + SolBigNumber bn_300 = sol_bignum_from_u32(300); + SolBigNumber bn_10 = sol_bignum_from_u32(10); + SolBigNumber dived = sol_bignum_div(&bn_300, &bn_10); + uint8_t div_expected[] = {30}; + sol_assert(!sol_memcmp(dived.data_addr, div_expected, 1)); + sol_bignum_deinit(&bn_300); + sol_bignum_deinit(&bn_10); + sol_bignum_deinit(&dived); + + sol_bignum_deinit(&bn_258); + sol_bignum_deinit(&bn_5); +} + +void test_complex_maths() { + sol_log("BigNumber Complex Maths"); + { + SolBigNumber bn_arg1 = sol_bignum_from_u32(300); + SolBigNumber sqr_res = sol_bignum_sqr(&bn_arg1); + uint8_t sqr_expected[] = {1, 95, 144}; + sol_assert(!sol_memcmp(sqr_res.data_addr, sqr_expected, 3)); + sol_bignum_deinit(&bn_arg1); + sol_bignum_deinit(&sqr_res); + } + { + SolBigNumber bn_arg1 = sol_bignum_from_u32(8); + SolBigNumber bn_arg2 = sol_bignum_from_u32(2); + SolBigNumber exp_res = sol_bignum_exp(&bn_arg1, &bn_arg2); + uint8_t exp_expected[] = {64}; + sol_assert(!sol_memcmp(exp_res.data_addr, exp_expected, 1)); + sol_bignum_deinit(&bn_arg2); + sol_bignum_deinit(&bn_arg1); + sol_bignum_deinit(&exp_res); + } + { + SolBigNumber bn_arg1 = sol_bignum_from_u32(300); + SolBigNumber bn_arg2 = sol_bignum_from_u32(11); + SolBigNumber mod_sqr = sol_bignum_mod_sqr(&bn_arg1, &bn_arg2); + uint8_t mod_sqr_expected[] = {9}; + sol_assert(!sol_memcmp(mod_sqr.data_addr, mod_sqr_expected, 1)); + sol_bignum_deinit(&bn_arg2); + sol_bignum_deinit(&bn_arg1); + sol_bignum_deinit(&mod_sqr); + } + { + SolBigNumber bn_arg1 = sol_bignum_from_u32(300); + SolBigNumber bn_arg2 = sol_bignum_from_u32(11); + SolBigNumber bn_arg3 = sol_bignum_from_u32(7); + SolBigNumber mod_exp = sol_bignum_mod_exp(&bn_arg1, &bn_arg2, &bn_arg3); + uint8_t mod_exp_expected[] = {6}; + sol_assert(!sol_memcmp(mod_exp.data_addr, mod_exp_expected, 1)); + sol_bignum_deinit(&bn_arg3); + sol_bignum_deinit(&bn_arg2); + sol_bignum_deinit(&bn_arg1); + } + { + SolBigNumber bn_arg1 = sol_bignum_from_u32(300); + SolBigNumber bn_arg2 = sol_bignum_from_u32(11); + SolBigNumber bn_arg3 = sol_bignum_from_u32(7); + SolBigNumber mod_mul = sol_bignum_mod_mul(&bn_arg1, &bn_arg2, &bn_arg3); + uint8_t mod_mul_expected[] = {3}; + sol_assert(!sol_memcmp(mod_mul.data_addr, mod_mul_expected, 1)); + sol_bignum_deinit(&bn_arg3); + sol_bignum_deinit(&bn_arg2); + sol_bignum_deinit(&bn_arg1); + sol_bignum_deinit(&mod_mul); + } + { + SolBigNumber bn_arg1 = sol_bignum_from_u32(415); + SolBigNumber bn_arg2 = sol_bignum_from_u32(7); + SolBigNumber mod_inv = sol_bignum_mod_inv(&bn_arg1, &bn_arg2); + uint8_t mod_inv_expected[] = {4}; + sol_assert(!sol_memcmp(mod_inv.data_addr, mod_inv_expected, 1)); + sol_bignum_deinit(&bn_arg2); + sol_bignum_deinit(&bn_arg1); + sol_bignum_deinit(&mod_inv); + } +} + +void test_output_logging() { + { + SolBigNumber bn = + sol_bignum_from_dec_str(LONG_DEC_STRING, sol_strlen(LONG_DEC_STRING)); + sol_bignum_log(&bn); + } + { + SolBigNumber bn = sol_bignum_from_dec_str(NEG_LONG_DEC_STRING, + sol_strlen(NEG_LONG_DEC_STRING)); + sol_bignum_log(&bn); + } +} + +extern uint64_t entrypoint(const uint8_t *input) { + sol_log("bignum"); + + test_constructors(); + test_basic_maths(); + test_complex_maths(); + test_output_logging(); + + return SUCCESS; +} diff --git a/programs/bpf/rust/bignumber/Cargo.toml b/programs/bpf/rust/bignumber/Cargo.toml new file mode 100644 index 00000000000000..562ea9e2d5b94f --- /dev/null +++ b/programs/bpf/rust/bignumber/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "solana-bpf-rust-bignumber" +version = "1.8.0" +description = "Solana BPF BigNumber test program written in Rust" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +documentation = "https://docs.rs/solana-bpf-rust-bignumber" +edition = "2018" + +[dependencies] +solana-program = { path = "../../../../sdk/program", version = "=1.8.0" } + +[lib] +crate-type = ["cdylib"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/bpf/rust/bignumber/src/lib.rs b/programs/bpf/rust/bignumber/src/lib.rs new file mode 100644 index 00000000000000..1bf24957bbbd00 --- /dev/null +++ b/programs/bpf/rust/bignumber/src/lib.rs @@ -0,0 +1,145 @@ +//! @brief BigNumber Syscall integration test +extern crate solana_program; +use solana_program::{bignumber::BigNumber, custom_panic_default, entrypoint::SUCCESS, msg}; + +const LONG_DEC_STRING: &str = "1470463693494555670176851280755142329532258274256991544781479988"; +const NEG_LONG_DEC_STRING: &str = + "-1470463693494555670176851280755142329532258274256991544781479988"; + +/// BigNumber construction +fn test_constructors() { + msg!("BigNumber constructors"); + let base_bn_0 = BigNumber::new(); + assert_eq!(base_bn_0.size_in_bytes(), 1); + assert_eq!(base_bn_0.to_vec(), vec![0u8]); + let default_0 = BigNumber::default(); + assert_eq!(base_bn_0, default_0); + let new_bn_0 = BigNumber::from_u32(0); + assert_eq!(new_bn_0, default_0); + let max_bn_u32 = BigNumber::from_u32(u32::MAX); + assert_eq!(max_bn_u32.to_vec(), vec![255, 255, 255, 255]); + let slice_vec = vec![255u8, 8]; + let bn_test_slice = BigNumber::from_bytes(&slice_vec); + assert_eq!(bn_test_slice.to_vec(), slice_vec); + let big_slice_vec = vec![255u8; 1024]; + let bn_test_slice = BigNumber::from_bytes(&big_slice_vec); + assert_eq!(bn_test_slice.to_vec(), big_slice_vec); + let bn_from_dec = BigNumber::from_dec_str(LONG_DEC_STRING); + assert!(!bn_from_dec.is_negative()); + let bn_from_dec = BigNumber::from_dec_str(NEG_LONG_DEC_STRING); + assert!(bn_from_dec.is_negative()); +<<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 2961987fa (Bignum syscalls) + // Test endian encoding + let be_bytes_in = u32::to_be_bytes(256); + let bn_bytes_out = BigNumber::from_bytes(&be_bytes_in).to_vec(); + assert_eq!(bn_bytes_out, [1, 0]); +<<<<<<< HEAD +<<<<<<< HEAD +<<<<<<< HEAD + let be_bytes_in: Vec = vec![0, 0, 0, 0, 0, 0, 1, 0]; + let bn_bytes_out = BigNumber::from_bytes(&be_bytes_in).to_vec(); + assert_eq!(bn_bytes_out, [1, 0]); +======= +>>>>>>> aab413c19 (Align files with struct names) +======= + +>>>>>>> 2961987fa (Bignum syscalls) +======= +>>>>>>> 7eee92e63 (Bignum syscalls - fix format issue) +======= + let be_bytes_in: Vec = vec![0, 0, 0, 0, 0, 0, 1, 0]; + let bn_bytes_out = BigNumber::from_bytes(&be_bytes_in).to_vec(); + assert_eq!(bn_bytes_out, [1, 0]); +>>>>>>> 51b0df078 (Bignum encoding length variations) +} + +/// BigNumber simple number and simple maths +fn test_basic_maths() { + msg!("BigNumber Basic Maths"); + let bn_5 = BigNumber::from_u32(5); + let bn_258 = BigNumber::from_u32(258); + let added = bn_5.add(&bn_258); + assert_eq!(added.to_vec(), [1, 7]); + let subed = bn_5.sub(&bn_258); + assert_eq!(subed.to_vec(), vec![253]); + assert!(subed.is_negative()); + let muled = bn_5.mul(&bn_5); + assert_eq!(muled.to_vec(), vec![25]); + let bn_300 = BigNumber::from_u32(300); + let bn_10 = BigNumber::from_u32(10); + let dived = bn_300.div(&bn_10); + assert_eq!(dived.to_vec(), vec![30]); +} + +/// BigNumber bigger numbers and complex maths +fn test_complex_maths() { + msg!("BigNumber Complex Maths"); + let bn_arg1 = BigNumber::from_u32(300); + let sqr_res = bn_arg1.sqr(); + assert_eq!(sqr_res.to_vec(), vec![1, 95, 144]); + let bn_arg2 = BigNumber::from_u32(8); + let bn_arg3 = BigNumber::from_u32(2); + let exp_res = bn_arg2.exp(&bn_arg3); + assert_eq!(exp_res.to_vec(), vec![64]); + let bn_arg1 = BigNumber::from_u32(300); + let bn_arg2 = BigNumber::from_u32(11); + let mod_sqr = bn_arg1.mod_sqr(&bn_arg2); + assert_eq!(mod_sqr.to_vec(), vec![9]); + let bn_arg1 = BigNumber::from_u32(300); + let bn_arg2 = BigNumber::from_u32(11); + let bn_arg3 = BigNumber::from_u32(7); + let mod_exp = bn_arg1.mod_exp(&bn_arg2, &bn_arg3); + assert_eq!(mod_exp.to_vec(), vec![6]); + let mod_mul = bn_arg1.mod_mul(&bn_arg2, &bn_arg3); + assert_eq!(mod_mul.to_vec(), vec![3]); + let bn_arg1 = BigNumber::from_u32(415); + let bn_arg2 = BigNumber::from_u32(7); + let mod_inv = bn_arg1.mod_inv(&bn_arg2); + assert_eq!(mod_inv.to_vec(), vec![4]); +} + +fn test_output_logging() { + let bn_from_dec = BigNumber::from_dec_str(LONG_DEC_STRING); + bn_from_dec.log(); + let bn_from_dec = BigNumber::from_dec_str(NEG_LONG_DEC_STRING); + bn_from_dec.log(); +} + +#[no_mangle] +pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { + msg!("bignum"); + test_constructors(); + test_basic_maths(); + test_complex_maths(); + test_output_logging(); + + SUCCESS +} + +custom_panic_default!(); + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_basic_constructors_pass() { + test_constructors(); + } + #[test] + fn test_simple_maths_pass() { + test_basic_maths(); + } + #[test] + fn test_complex_maths_pass() { + test_complex_maths(); + } + + #[test] + fn test_logging() { + test_output_logging(); + } +} diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 5b8acc15655bd7..c58f0dd6e3462e 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -430,6 +430,15 @@ fn test_program_bpf_sanity() { { programs.extend_from_slice(&[ ("alloc", true), +<<<<<<< HEAD +<<<<<<< HEAD + ("bignumber", true), +======= + ("bignum", true), +>>>>>>> e515f0c31 (Add C bindings and tests) +======= + ("bignumber", true), +>>>>>>> aab413c19 (Align files with struct names) ("bpf_to_bpf", true), ("float", true), ("multiple_static", true), @@ -449,6 +458,7 @@ fn test_program_bpf_sanity() { programs.extend_from_slice(&[ ("solana_bpf_rust_128bit", true), ("solana_bpf_rust_alloc", true), + ("solana_bpf_rust_bignumber", true), ("solana_bpf_rust_custom_heap", true), ("solana_bpf_rust_dep_crate", true), ("solana_bpf_rust_external_spend", false), @@ -1291,10 +1301,23 @@ fn assert_instruction_count() { { programs.extend_from_slice(&[ ("solana_bpf_rust_128bit", 584), - ("solana_bpf_rust_alloc", 7082), - ("solana_bpf_rust_custom_heap", 522), - ("solana_bpf_rust_dep_crate", 2), - ("solana_bpf_rust_external_spend", 504), + ("solana_bpf_rust_alloc", 8906), +<<<<<<< HEAD +<<<<<<< HEAD +<<<<<<< HEAD + ("solana_bpf_rust_bignumber", 10853), +======= + ("solana_bpf_rust_bignumber", 9967), +>>>>>>> aab413c19 (Align files with struct names) +======= + ("solana_bpf_rust_bignumber", 10384), +>>>>>>> 7ba04a7b8 (Bignum - fixed instruction count) +======= + ("solana_bpf_rust_bignumber", 10853), +>>>>>>> 51b0df078 (Bignum encoding length variations) + ("solana_bpf_rust_custom_heap", 539), + ("solana_bpf_rust_dep_crate", 47), + ("solana_bpf_rust_external_spend", 521), ("solana_bpf_rust_iter", 724), ("solana_bpf_rust_many_args", 233), ("solana_bpf_rust_mem", 3119), diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index 6e536002617ee1..17e22411dfacb0 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -18,6 +18,7 @@ byteorder = "1.3.4" log = "0.4.11" num-derive = "0.3" num-traits = "0.2" +openssl = { version = "0.10.32", features = ["vendored"] } rand_core = "0.6.2" sha3 = "0.9.1" solana-measure = { path = "../../measure", version = "=1.8.0" } diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 1b900e9b10e076..65b09557c3e78a 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -1,5 +1,6 @@ use crate::{alloc, BpfError}; use alloc::Alloc; +use openssl::bn::*; use solana_rbpf::{ aligned_memory::AlignedMemory, ebpf::MM_HEAP_START, @@ -13,13 +14,14 @@ use solana_sdk::{ account::{Account, AccountSharedData, ReadableAccount}, account_info::AccountInfo, account_utils::StateMut, + bignumber::FfiBigNumber, blake3, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, clock::Clock, entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS}, epoch_schedule::EpochSchedule, feature_set::{ - blake3_syscall_enabled, cpi_data_cost, demote_sysvar_write_locks, + bignum_syscall_enabled, blake3_syscall_enabled, cpi_data_cost, demote_sysvar_write_locks, enforce_aligned_host_addrs, keccak256_syscall_enabled, memory_ops_syscalls, sysvar_via_syscall, update_data_on_realloc, }, @@ -76,6 +78,40 @@ pub enum SyscallError { TooManyAccounts, #[error("Overlapping copy")] CopyOverlapping, + #[error("BigNumber: Modular exponentiation error {0}")] + BigNumberModExpError(String), + #[error("BigNumber: Bytes would exceed buffer provided")] + BigNumberToBytesError, + #[error("BigNumber: expects {0} args but provided {1}")] + BigNumberArgError(u64, u64), + #[error("BigNumber: add error {0}")] + BigNumberAddError(String), + #[error("BigNumber: sub error {0}")] + BigNumberSubError(String), + #[error("BigNumber: mul error {0}")] + BigNumberMulError(String), + #[error("BigNumber: div error {0}")] + BigNumberDivError(String), + #[error("BigNumber: exp error {0}")] + BigNumberExpError(String), + #[error("BigNumber: sqr error {0}")] + BigNumberSqrError(String), + #[error("BigNumber: mod_sqr error {0}")] + BigNumberModSqrError(String), + #[error("BigNumber: mod_mul error {0}")] + BigNumberModMulError(String), + #[error("BigNumber: mod_inv error {0}")] + BigNumberModInvError(String), + #[error("BigNumber: error in executing operation {0}")] + BigNumberOperationError(String), + #[error("BigNumber: unknow error encountered")] + BigNumberErrorUnknown, + #[error("BigNumber: error in converting decimal string to BigNum")] + BigNumberFromDecStrError, + #[error("BigNumber: size > MAX_BIGNUM_BYTE_SIZE bytes (1 k) error")] + BigNumberSizeError, + #[error("BigNumber: from_slice error {0}")] + BigNumberFromSliceError(String), } impl From for EbpfError { fn from(error: SyscallError) -> Self { @@ -167,6 +203,30 @@ pub fn register_syscalls( // Memory allocator syscall_registry.register_syscall_by_name(b"sol_alloc_free_", SyscallAllocFree::call)?; + if invoke_context.is_feature_active(&bignum_syscall_enabled::id()) { + syscall_registry + .register_syscall_by_name(b"sol_bignum_from_u32_", SyscallBigNumFromU32::call)?; + syscall_registry + .register_syscall_by_name(b"sol_bignum_from_dec_str_", SyscallBigNumFromDecStr::call)?; + syscall_registry + .register_syscall_by_name(b"sol_bignum_mod_exp_", SyscallBigNumModExp::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_log_", SyscallBigNumLog::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_add_", SyscallBigNumAdd::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_sub_", SyscallBigNumSub::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_mul_", SyscallBigNumMul::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_div_", SyscallBigNumDiv::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_exp_", SyscallBigNumExp::call)?; + syscall_registry.register_syscall_by_name(b"sol_bignum_sqr_", SyscallBigNumSqr::call)?; + syscall_registry + .register_syscall_by_name(b"sol_bignum_mod_sqr_", SyscallBigNumModSqr::call)?; + syscall_registry + .register_syscall_by_name(b"sol_bignum_mod_mul_", SyscallBigNumModMul::call)?; + syscall_registry + .register_syscall_by_name(b"sol_bignum_mod_inv_", SyscallBigNumModInv::call)?; + syscall_registry + .register_syscall_by_name(b"sol_bignum_from_bytes_", SyscallBigNumFromBytes::call)?; + } + Ok(syscall_registry) } @@ -331,6 +391,163 @@ pub fn bind_syscall_context_objects<'a>( }), ); + // Bignum + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumFromU32 { + cost: bpf_compute_budget.bignum_from_u32_base_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumFromDecStr { + cost: bpf_compute_budget.bignum_from_dec_str_base_cost, + word_cost: bpf_compute_budget.bignum_from_dec_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumAdd { + cost: bpf_compute_budget.bignum_add_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumSub { + cost: bpf_compute_budget.bignum_sub_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumMul { + cost: bpf_compute_budget.bignum_mul_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumDiv { + cost: bpf_compute_budget.bignum_div_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumExp { + cost: bpf_compute_budget.bignum_exp_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumSqr { + cost: bpf_compute_budget.bignum_sqr_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumModSqr { + cost: bpf_compute_budget.bignum_mod_sqr_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumModMul { + cost: bpf_compute_budget.bignum_mod_mul_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumModInv { + cost: bpf_compute_budget.bignum_mod_inv_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumModExp { + cost: bpf_compute_budget.bignum_mod_exp_base_cost, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumLog { + cost: bpf_compute_budget.bignum_log_cost, + word_cost: bpf_compute_budget.bignum_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + logger: invoke_context.get_logger(), + loader_id, + }), + ); + bind_feature_gated_syscall_context_object!( + vm, + invoke_context.is_feature_active(&bignum_syscall_enabled::id()), + Box::new(SyscallBigNumFromBytes { + cost: bpf_compute_budget.bignum_from_u32_base_cost, + word_cost: bpf_compute_budget.bignum_from_bytes_word_cost, + word_div_cost: bpf_compute_budget.bignum_word_cost_divisor, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + ); + let is_sysvar_via_syscall_active = invoke_context.is_feature_active(&sysvar_via_syscall::id()); let invoke_context = Rc::new(RefCell::new(invoke_context)); @@ -2369,126 +2586,1896 @@ fn call<'a>( Ok(SUCCESS) } -#[cfg(test)] -mod tests { - use super::*; - use solana_rbpf::{ - ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config, - }; - use solana_sdk::{ - bpf_loader, - fee_calculator::FeeCalculator, - hash::hashv, - process_instruction::{MockComputeMeter, MockInvokeContext, MockLogger}, - }; - use std::str::FromStr; - - const DEFAULT_CONFIG: Config = Config { - max_call_depth: 20, - stack_frame_size: 4_096, - enable_instruction_meter: true, - enable_instruction_tracing: false, +/// Bignum data costs calculator +pub const MAX_BIGNUM_BYTE_SIZE: u64 = 1024; +macro_rules! calc_bignum_cost { + ($input_self:expr, $input_size_in_bytes:expr) => { + $input_self.cost + + ($input_self.word_cost as f64 + * ($input_size_in_bytes as f64 / $input_self.word_div_cost as f64).ceil()) + as u64 }; +} - macro_rules! assert_access_violation { - ($result:expr, $va:expr, $len:expr) => { - match $result { - Err(EbpfError::AccessViolation(_, _, va, len, _)) if $va == va && len == len => (), - _ => panic!(), - } - }; +/// Transposes a bn::BigNum into an FfiBignumber array of bytes +fn bignum_to_ffibignumber( + bignum: &BigNum, + bnffi: &mut FfiBigNumber, + loader_id: &Pubkey, + memory_mapping: &MemoryMapping, + result: &mut Result>, +) { + // Get the BigNum vector and size + let big_number_bytes = bignum.to_vec(); + let big_number_len = big_number_bytes.len() as u64; + (*bnffi).is_negative = bignum.is_negative(); + // Fail if result size exceeds 1024 bytes (8192 bits) + if big_number_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()) } + // Fail if we can't support the full array of bytes + else if big_number_len as u64 > bnffi.data_len { + *result = Err(SyscallError::BigNumberArgError(big_number_len, bnffi.data_len).into()) + } else { + // Get the output array pointer + let bn_buffer_out = question_mark!( + translate_slice_mut::(memory_mapping, bnffi.data, bnffi.data_len, loader_id, true), + result + ); + // Zero result + if big_number_len == 0 { + bn_buffer_out[0] = 0u8; + (*bnffi).data_len = 1; + } else if big_number_len == bnffi.data_len { + (*bn_buffer_out).copy_from_slice(&big_number_bytes); + } else { + bn_buffer_out[..big_number_bytes.len()].copy_from_slice(&&big_number_bytes); + (*bnffi).data_len = big_number_len; + } + *result = Ok(SUCCESS) + } +} - #[test] - fn test_translate() { - const START: u64 = 100; - const LENGTH: u64 = 1000; - let data = vec![0u8; LENGTH as usize]; - let addr = data.as_ptr() as u64; - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice(&data, START, 0, false)], - &DEFAULT_CONFIG, - ) - .unwrap(); - - let cases = vec![ - (true, START, 0, addr), - (true, START, 1, addr), - (true, START, LENGTH, addr), - (true, START + 1, LENGTH - 1, addr + 1), - (false, START + 1, LENGTH, 0), - (true, START + LENGTH - 1, 1, addr + LENGTH - 1), - (true, START + LENGTH, 0, addr + LENGTH), - (false, START + LENGTH, 1, 0), - (false, START, LENGTH + 1, 0), - (false, 0, 0, 0), - (false, 0, 1, 0), - (false, START - 1, 0, 0), - (false, START - 1, 1, 0), - (true, START + LENGTH / 2, LENGTH / 2, addr + LENGTH / 2), - ]; - for (ok, start, length, value) in cases { - if ok { - assert_eq!( - translate(&memory_mapping, AccessType::Load, start, length).unwrap(), - value - ) +/// Transposes a FfiBignumber array of bytes to a bn::BigNum +fn ffibignumber_to_bignum(ffi: &FfiBigNumber, ffi_data: &[u8]) -> Result { + let ffi_bn = BigNum::from_slice(ffi_data); + match ffi_bn { + Ok(mut bn) => { + bn.set_negative(ffi.is_negative); + Ok(bn) + } + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + Err(SyscallError::BigNumberOperationError(reason.to_string())) } else { - assert!(translate(&memory_mapping, AccessType::Load, start, length).is_err()) + Err(SyscallError::BigNumberErrorUnknown) } } } +} - #[test] - fn test_translate_type() { - // Pubkey - let pubkey = solana_sdk::pubkey::new_rand(); - let addr = &pubkey as *const _ as u64; - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }], - &DEFAULT_CONFIG, - ) - .unwrap(); - let translated_pubkey = - translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).unwrap(); - assert_eq!(pubkey, *translated_pubkey); - - // Instruction - let instruction = Instruction::new_with_bincode( - solana_sdk::pubkey::new_rand(), - &"foobar", - vec![AccountMeta::new(solana_sdk::pubkey::new_rand(), false)], +/// BIGNUM sol_bignum_from_u32 ingests a u32 and +/// produces an absolute big endian array +struct SyscallBigNumFromU32<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumFromU32<'a> { + fn call( + &mut self, + bn_ffi_out_addr: u64, + u32_val: u64, + _arg3: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + question_mark!( + self.compute_meter.consume(calc_bignum_cost!(self, 4f64)), + result ); - let addr = &instruction as *const _ as u64; - let mut memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 96, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }], - &DEFAULT_CONFIG, - ) - .unwrap(); - let translated_instruction = - translate_type::(&memory_mapping, 96, &bpf_loader::id(), true).unwrap(); - assert_eq!(instruction, *translated_instruction); - memory_mapping.resize_region::(0, 1).unwrap(); - assert!( - translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).is_err() + // Get the output FfiBigNumber structure + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result ); + // Process BigNum call and populate results and + // collect, if any, error from OpenSSL + match BigNum::from_u32(u32_val as u32) { + Ok(bn) => bignum_to_ffibignumber( + &bn, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + } } +} +/// BIGNUM sol_bignum_from_dec_str bounds checks, +/// validates and ingests a decimal string and +/// produces an absoluate big endian array +struct SyscallBigNumFromDecStr<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumFromDecStr<'a> { + fn call( + &mut self, + in_dec_str_addr: u64, + in_dec_str_len: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + question_mark!( + self.compute_meter + .consume(calc_bignum_cost!(self, in_dec_str_len as f64)), + result + ); - #[test] - fn test_translate_slice() { - // zero len + // Get the string and convert to BigNum + let in_dec_raw = question_mark!( + translate_slice::( + memory_mapping, + in_dec_str_addr, + in_dec_str_len, + self.loader_id, + true + ), + result + ); + + let i = match in_dec_raw.iter().position(|byte| *byte == 0) { + Some(i) => i, + None => in_dec_str_len as usize, + }; + let raw_string = match from_utf8(&in_dec_raw[..i]) { + Ok(s) => s, + Err(_) => { + *result = Err(SyscallError::BigNumberToBytesError.into()); + return; + } + }; + + // Get the output FfiBigNumber structure + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + // Handle expected result > MAX_BIGNUM_BYTE_SIZE bytes + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } + // Handle buffer too small or empty strings + else if bn_syscall_result.data_len == 0 || raw_string.is_empty() { + *result = Err(SyscallError::BigNumberToBytesError.into()) + } else { + // Process BigNum call and populate results + match BigNum::from_dec_str(raw_string) { + Ok(bn) => bignum_to_ffibignumber( + &bn, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(_) => *result = Err(SyscallError::BigNumberFromDecStrError.into()), + }; + } + } +} + +/// BIGNUM sol_bignum_from_slice ingests a absolute big endian array for +/// validation and size checking +struct SyscallBigNumFromBytes<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumFromBytes<'a> { + fn call( + &mut self, + in_bytes_addr: u64, + in_bytes_len: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Compute costs + question_mark!( + self.compute_meter + .consume(calc_bignum_cost!(self, in_bytes_len as f64)), + result + ); + + // Get array pointer of bytes to consume + let rhs_data = question_mark!( + translate_slice::( + memory_mapping, + in_bytes_addr, + in_bytes_len, + self.loader_id, + true + ), + result + ); + // Process BigNum call and populate results + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + // Check max length of 1024 bytes + if !(1..=MAX_BIGNUM_BYTE_SIZE).contains(&in_bytes_len) { + *result = Err(SyscallError::BigNumberSizeError.into()) + } else { + match BigNum::from_slice(rhs_data) { + Ok(bn_result) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = + Err(SyscallError::BigNumberFromSliceError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + } + } + } + } +} + +/// BIGNUM sol_bignum_add bounds checks and adds two BigNumber and +/// produces a result. +struct SyscallBigNumAdd<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumAdd<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the data pointer big numbers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.checked_add(&lhs_bn, &rhs_bn) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberAddError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + }; + } + } +} + +/// BIGNUM sol_bignum_sub bounds checks and subtracts two BigNumber and +/// produces a result. +struct SyscallBigNumSub<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumSub<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.checked_sub(&lhs_bn, &rhs_bn) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberSubError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + }; + } + } +} +/// BIGNUM sol_bignum_mul bounds checks and multiplies two BigNumber and +/// produces a result. +struct SyscallBigNumMul<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumMul<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.checked_mul(&lhs_bn, &rhs_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberMulError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + } + } + } + } +} +/// BIGNUM sol_bignum_div bounds checks and divides two BigNumber and +/// produces a result. +struct SyscallBigNumDiv<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumDiv<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.checked_div(&lhs_bn, &rhs_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberDivError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + } + } + } + } +} +/// BIGNUM sol_bignum_sqr bounds checks squares a BigNumber and +/// produces a result. +struct SyscallBigNumSqr<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumSqr<'a> { + fn call( + &mut self, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg3: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter + .consume(calc_bignum_cost!(self, bn_syscall_rhs.data_len as f64)), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get number to sqr ffi + let rhs_data = question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ); + // Convert to BigNum + let rhs_bn = match BigNum::from_slice(rhs_data) { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.sqr(&rhs_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberSqrError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + } + } + } + } +} +/// BIGNUM sol_bignum_exp bounds checks raises a BigNumber by exponent +/// and produces a result. +struct SyscallBigNumExp<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumExp<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.exp(&lhs_bn, &rhs_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberExpError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + } + } + } +} +/// BIGNUM sol_bignum_mod_sqr bounds checks and performs +/// lhs^2 % rhs and produces a result +struct SyscallBigNumModSqr<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumModSqr<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.mod_sqr(&lhs_bn, &rhs_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = + Err(SyscallError::BigNumberModSqrError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + } + } + } + } +} + +/// Calculates a data cost for mod_exp as per https://eips.ethereum.org/EIPS/eip-198 +fn calculate_exp_byte_cost( + base: &BigNum, + exponent: &BigNum, + modulus: &BigNum, +) -> Result { + let zero = match BigNum::from_u32(0) { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + return Err(SyscallError::BigNumberOperationError(reason.to_string())); + } else { + return Err(SyscallError::BigNumberErrorUnknown); + } + } + }; + let exp_bytes_length = exponent.num_bytes() as u32; + let exp_bits_length = exponent.num_bits() as u32; + let base_bytes_length = base.num_bytes() as u32; + // Adjusted length calculation + let adjusted_exp_length = match exp_bytes_length { + 0..=32 if exponent == &zero => 0, + 0..=32 => exp_bits_length - 1, + _ => { + let first_32 = match BigNum::from_slice(&exponent.as_ref().to_vec()[0..31]) { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + return Err(SyscallError::BigNumberOperationError(reason.to_string())); + } else { + return Err(SyscallError::BigNumberErrorUnknown); + } + } + }; + if first_32 == zero { + 8 * (exp_bytes_length - 32) + } else { + 8 * (exp_bytes_length - 32) + ((first_32.num_bits() as u32) - 1) + } + } + } as u64; + // mult_complexity + let mult_compexity_arg = std::cmp::max(base_bytes_length, modulus.num_bytes() as u32) as u64; + let mult_complexity = if mult_compexity_arg <= 64 { + mult_compexity_arg * mult_compexity_arg + } else if mult_compexity_arg <= 1024 { + (((mult_compexity_arg * mult_compexity_arg) / 4) + (96 * mult_compexity_arg)) - 3_072 + } else { + (((mult_compexity_arg * mult_compexity_arg) / 16) + (480 * mult_compexity_arg)) - 199_680 + }; + // Calc data costs and return + Ok( + ((mult_complexity * std::cmp::max(adjusted_exp_length, 1u64)) as f64 / 20f64).floor() + as u64, + ) +} +/// BIGNUM sol_bignum_mod_exp bounds checks and performs +/// lhs^rhs % mod and produces a result +struct SyscallBigNumModExp<'a> { + cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumModExp<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + mod_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the MOD FfiBigNumber value structure + let bn_syscall_mod = question_mark!( + translate_type::(memory_mapping, mod_ffi_in_addr, self.loader_id, true), + result + ); + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let mod_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_mod.data, + bn_syscall_mod.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + // Compute costs + let calc_val = match calculate_exp_byte_cost(&lhs_bn, &rhs_bn, &mod_bn) { + Ok(val) => val, + Err(e) => { + *result = Err(e.into()); + return; + } + }; + question_mark!(self.compute_meter.consume(self.cost + calc_val), result); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_mod.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.mod_exp(&lhs_bn, &rhs_bn, &mod_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(e) => { + if let Some(reason) = e.errors()[0].reason() { + *result = Err(SyscallError::BigNumberModExpError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + } + } + } +} +/// BIGNUM sol_bignum_mod_mul bounds checks and performs +/// lhs*rhs % mod and produces a result +struct SyscallBigNumModMul<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumModMul<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + mod_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the MOD FfiBigNumber value structure + let bn_syscall_mod = question_mark!( + translate_type::(memory_mapping, mod_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len + bn_syscall_mod.data_len) + as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_mod.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let mod_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_mod.data, + bn_syscall_mod.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.mod_mul(&lhs_bn, &rhs_bn, &mod_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(e) => { + if let Some(reason) = e.errors()[0].reason() { + *result = Err(SyscallError::BigNumberModMulError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + } + } + } +} +/// BIGNUM sol_bignum_mod_inv bounds checks and performs +/// inverse(lhs % rhs) and produces a result +struct SyscallBigNumModInv<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumModInv<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + rhs_ffi_in_addr: u64, + bn_ffi_out_addr: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + // Get the RHS FfiBigNumber value structure + let bn_syscall_rhs = question_mark!( + translate_type::(memory_mapping, rhs_ffi_in_addr, self.loader_id, true), + result + ); + // Compute costs + question_mark!( + self.compute_meter.consume(calc_bignum_cost!( + self, + (bn_syscall_lhs.data_len + bn_syscall_rhs.data_len) as f64 + )), + result + ); + // Bounds check on input + if bn_syscall_rhs.data_len > MAX_BIGNUM_BYTE_SIZE + || bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE + { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + let rhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_rhs.data, + bn_syscall_rhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + + // Process BigNum call and populate results + let mut bn_result = match BigNum::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let mut bn_ctx = match BigNumContext::new() { + Ok(bn) => bn, + Err(es) => { + if let Some(reason) = es.errors()[0].reason() { + *result = Err(SyscallError::BigNumberOperationError(reason.to_string()).into()); + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()); + } + return; + } + }; + let bn_syscall_result = question_mark!( + translate_type_mut::( + memory_mapping, + bn_ffi_out_addr, + self.loader_id, + true + ), + result + ); + + if bn_syscall_result.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + } else { + match bn_result.mod_inverse(&lhs_bn, &rhs_bn, &mut bn_ctx) { + Ok(_) => bignum_to_ffibignumber( + &bn_result, + bn_syscall_result, + self.loader_id, + memory_mapping, + result, + ), + Err(e) => { + if let Some(reason) = e.errors()[0].reason() { + *result = Err(SyscallError::BigNumberModInvError(reason.to_string()).into()) + } else { + *result = Err(SyscallError::BigNumberErrorUnknown.into()) + } + } + } + } + } +} +/// Logs a BigNumber to system log +struct SyscallBigNumLog<'a> { + cost: u64, + word_cost: u64, + word_div_cost: u64, + compute_meter: Rc>, + logger: Rc>, + loader_id: &'a Pubkey, +} +impl<'a> SyscallObject for SyscallBigNumLog<'a> { + fn call( + &mut self, + lhs_ffi_in_addr: u64, + _arg2: u64, + _arg3: u64, + _arg4: u64, + _arg5: u64, + memory_mapping: &MemoryMapping, + result: &mut Result>, + ) { + // Get the LHS FfiBigNumber value structure + let bn_syscall_lhs = question_mark!( + translate_type::(memory_mapping, lhs_ffi_in_addr, self.loader_id, true), + result + ); + question_mark!( + self.compute_meter + .consume(calc_bignum_cost!(self, bn_syscall_lhs.data_len as f64)), + result + ); + // Bounds check on input + if bn_syscall_lhs.data_len > MAX_BIGNUM_BYTE_SIZE { + *result = Err(SyscallError::BigNumberSizeError.into()); + return; + } + + // Get the BigNum from data pointers + let lhs_bn = question_mark!( + ffibignumber_to_bignum( + bn_syscall_lhs, + question_mark!( + translate_slice::( + memory_mapping, + bn_syscall_lhs.data, + bn_syscall_lhs.data_len as u64, + self.loader_id, + true + ), + result + ) + ), + result + ); + stable_log::program_log(&self.logger, &lhs_bn.to_string()); + *result = Ok(0); + } +} +#[cfg(test)] +mod tests { + use super::*; + use solana_rbpf::{ + ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config, + }; + use solana_sdk::{ + bpf_loader, + fee_calculator::FeeCalculator, + hash::hashv, + process_instruction::{MockComputeMeter, MockInvokeContext, MockLogger}, + }; + use std::str::FromStr; + + const DEFAULT_CONFIG: Config = Config { + max_call_depth: 20, + stack_frame_size: 4_096, + enable_instruction_meter: true, + enable_instruction_tracing: false, + }; + + const LONG_DEC_STRING: &str = + "1470463693494555670176851280755142329532258274256991544781479988\ + 712408107190720087233560906792937436573943189716784305633216335039\ + 300236370809933808677983409391545753391897467230180786617074456716\ + 591448871466263060696957107957862111484694673874424855359234132302\ + 162208163361387727626078022804936564470716886986414133429438273232\ + 416190048073715996321578752244853524209178212395809614878549824744\ + 227969245726015222693764433413133633359171080169137831743765672068\ + 374040331773668233371864426354886263106537340208256187214278963052\ + 996538599452325797319977413534714912781503130883692806087195354368\ + 8304190675878204079994222"; + + const NEG_LONG_DEC_STRING: &str = + "-1470463693494555670176851280755142329532258274256991544781479988\ + 712408107190720087233560906792937436573943189716784305633216335039\ + 300236370809933808677983409391545753391897467230180786617074456716\ + 591448871466263060696957107957862111484694673874424855359234132302\ + 162208163361387727626078022804936564470716886986414133429438273232\ + 416190048073715996321578752244853524209178212395809614878549824744\ + 227969245726015222693764433413133633359171080169137831743765672068\ + 374040331773668233371864426354886263106537340208256187214278963052\ + 996538599452325797319977413534714912781503130883692806087195354368\ + 8304190675878204079994222"; + + const NOT_A_VALID_DEC_STRING: &str = "ZBikk123A972"; + + macro_rules! assert_access_violation { + ($result:expr, $va:expr, $len:expr) => { + match $result { + Err(EbpfError::AccessViolation(_, _, va, len, _)) if $va == va && len == len => (), + _ => panic!(), + } + }; + } + + #[test] + fn test_translate() { + const START: u64 = 100; + const LENGTH: u64 = 1000; + let data = vec![0u8; LENGTH as usize]; + let addr = data.as_ptr() as u64; + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion::new_from_slice(&data, START, 0, false)], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let cases = vec![ + (true, START, 0, addr), + (true, START, 1, addr), + (true, START, LENGTH, addr), + (true, START + 1, LENGTH - 1, addr + 1), + (false, START + 1, LENGTH, 0), + (true, START + LENGTH - 1, 1, addr + LENGTH - 1), + (true, START + LENGTH, 0, addr + LENGTH), + (false, START + LENGTH, 1, 0), + (false, START, LENGTH + 1, 0), + (false, 0, 0, 0), + (false, 0, 1, 0), + (false, START - 1, 0, 0), + (false, START - 1, 1, 0), + (true, START + LENGTH / 2, LENGTH / 2, addr + LENGTH / 2), + ]; + for (ok, start, length, value) in cases { + if ok { + assert_eq!( + translate(&memory_mapping, AccessType::Load, start, length).unwrap(), + value + ) + } else { + assert!(translate(&memory_mapping, AccessType::Load, start, length).is_err()) + } + } + } + + #[test] + fn test_translate_type() { + // Pubkey + let pubkey = solana_sdk::pubkey::new_rand(); + let addr = &pubkey as *const _ as u64; + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: addr, + vm_addr: 100, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + let translated_pubkey = + translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).unwrap(); + assert_eq!(pubkey, *translated_pubkey); + + // Instruction + let instruction = Instruction::new_with_bincode( + solana_sdk::pubkey::new_rand(), + &"foobar", + vec![AccountMeta::new(solana_sdk::pubkey::new_rand(), false)], + ); + let addr = &instruction as *const _ as u64; + let mut memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: addr, + vm_addr: 96, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + let translated_instruction = + translate_type::(&memory_mapping, 96, &bpf_loader::id(), true).unwrap(); + assert_eq!(instruction, *translated_instruction); + memory_mapping.resize_region::(0, 1).unwrap(); + assert!( + translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).is_err() + ); + } + + #[test] + fn test_translate_slice() { + // zero len let good_data = vec![1u8, 2, 3, 4, 5]; let data: Vec = vec![]; assert_eq!(0x1 as *const u8, data.as_ptr()); @@ -2616,489 +4603,1376 @@ mod tests { } #[test] - fn test_translate_string_and_do() { - let string = "Gaggablaghblagh!"; - let addr = string.as_ptr() as *const _ as u64; + fn test_translate_string_and_do() { + let string = "Gaggablaghblagh!"; + let addr = string.as_ptr() as *const _ as u64; + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: addr, + vm_addr: 100, + len: string.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + assert_eq!( + 42, + translate_string_and_do( + &memory_mapping, + 100, + string.len() as u64, + &bpf_loader::id(), + true, + &mut |string: &str| { + assert_eq!(string, "Gaggablaghblagh!"); + Ok(42) + } + ) + .unwrap() + ); + } + + #[test] + #[should_panic(expected = "UserError(SyscallError(Abort))")] + fn test_syscall_abort() { + let memory_mapping = + MemoryMapping::new::(vec![MemoryRegion::default()], &DEFAULT_CONFIG) + .unwrap(); + let mut result: Result> = Ok(0); + SyscallAbort::call( + &mut SyscallAbort {}, + 0, + 0, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + result.unwrap(); + } + + #[test] + #[should_panic(expected = "UserError(SyscallError(Panic(\"Gaggablaghblagh!\", 42, 84)))")] + fn test_syscall_sol_panic() { + let string = "Gaggablaghblagh!"; + let addr = string.as_ptr() as *const _ as u64; + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: addr, + vm_addr: 100, + len: string.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { + remaining: string.len() as u64 - 1, + })); + let mut syscall_panic = SyscallPanic { + compute_meter, + loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, + }; + let mut result: Result> = Ok(0); + syscall_panic.call( + 100, + string.len() as u64, + 42, + 84, + 0, + &memory_mapping, + &mut result, + ); + assert_eq!( + Err(EbpfError::UserError(BpfError::SyscallError( + SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) + ))), + result + ); + + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { + remaining: string.len() as u64, + })); + let mut syscall_panic = SyscallPanic { + compute_meter, + loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, + }; + let mut result: Result> = Ok(0); + syscall_panic.call( + 100, + string.len() as u64, + 42, + 84, + 0, + &memory_mapping, + &mut result, + ); + result.unwrap(); + } + + #[test] + fn test_syscall_sol_log() { + let string = "Gaggablaghblagh!"; + let addr = string.as_ptr() as *const _ as u64; + + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { remaining: 1000000 })); + let log = Rc::new(RefCell::new(vec![])); + let logger: Rc> = + Rc::new(RefCell::new(MockLogger { log: log.clone() })); + let mut syscall_sol_log = SyscallLog { + compute_meter, + logger, + loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, + }; + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: addr, + vm_addr: 100, + len: string.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let mut result: Result> = Ok(0); + syscall_sol_log.call( + 100, + string.len() as u64, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + result.unwrap(); + assert_eq!(log.borrow().len(), 1); + assert_eq!(log.borrow()[0], "Program log: Gaggablaghblagh!"); + + let mut result: Result> = Ok(0); + syscall_sol_log.call( + 101, // AccessViolation + string.len() as u64, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + assert_access_violation!(result, 101, string.len() as u64); + let mut result: Result> = Ok(0); + syscall_sol_log.call( + 100, + string.len() as u64 * 2, // AccessViolation + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + assert_access_violation!(result, 100, string.len() as u64 * 2); + let mut result: Result> = Ok(0); + syscall_sol_log.call( + 100, + string.len() as u64, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { + remaining: (string.len() as u64 * 2) - 1, + })); + let logger: Rc> = Rc::new(RefCell::new(MockLogger { log })); + let mut syscall_sol_log = SyscallLog { + compute_meter, + logger, + loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, + }; + let mut result: Result> = Ok(0); + syscall_sol_log.call( + 100, + string.len() as u64, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + result.unwrap(); + let mut result: Result> = Ok(0); + syscall_sol_log.call( + 100, + string.len() as u64, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + assert_eq!( + Err(EbpfError::UserError(BpfError::SyscallError( + SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) + ))), + result + ); + } + + #[test] + fn test_syscall_sol_log_u64() { + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { + remaining: std::u64::MAX, + })); + let log = Rc::new(RefCell::new(vec![])); + let logger: Rc> = + Rc::new(RefCell::new(MockLogger { log: log.clone() })); + let mut syscall_sol_log_u64 = SyscallLogU64 { + cost: 0, + compute_meter, + logger, + }; + let memory_mapping = MemoryMapping::new::(vec![], &DEFAULT_CONFIG).unwrap(); + + let mut result: Result> = Ok(0); + syscall_sol_log_u64.call(1, 2, 3, 4, 5, &memory_mapping, &mut result); + result.unwrap(); + + assert_eq!(log.borrow().len(), 1); + assert_eq!(log.borrow()[0], "Program log: 0x1, 0x2, 0x3, 0x4, 0x5"); + } + + #[test] + fn test_syscall_sol_pubkey() { + let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap(); + let addr = &pubkey.as_ref()[0] as *const _ as u64; + + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { remaining: 2 })); + let log = Rc::new(RefCell::new(vec![])); + let logger: Rc> = + Rc::new(RefCell::new(MockLogger { log: log.clone() })); + let mut syscall_sol_pubkey = SyscallLogPubkey { + cost: 1, + compute_meter, + logger, + loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, + }; let memory_mapping = MemoryMapping::new::( vec![MemoryRegion { host_addr: addr, vm_addr: 100, - len: string.len() as u64, + len: 32, vm_gap_shift: 63, is_writable: false, }], &DEFAULT_CONFIG, ) .unwrap(); + + let mut result: Result> = Ok(0); + syscall_sol_pubkey.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); + result.unwrap(); + assert_eq!(log.borrow().len(), 1); assert_eq!( - 42, - translate_string_and_do( - &memory_mapping, - 100, - string.len() as u64, - &bpf_loader::id(), - true, - &mut |string: &str| { - assert_eq!(string, "Gaggablaghblagh!"); - Ok(42) - } - ) - .unwrap() + log.borrow()[0], + "Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN" ); - } - - #[test] - #[should_panic(expected = "UserError(SyscallError(Abort))")] - fn test_syscall_abort() { - let memory_mapping = - MemoryMapping::new::(vec![MemoryRegion::default()], &DEFAULT_CONFIG) - .unwrap(); let mut result: Result> = Ok(0); - SyscallAbort::call( - &mut SyscallAbort {}, - 0, - 0, + syscall_sol_pubkey.call( + 101, // AccessViolation + 32, 0, 0, 0, &memory_mapping, &mut result, ); - result.unwrap(); + assert_access_violation!(result, 101, 32); + let mut result: Result> = Ok(0); + syscall_sol_pubkey.call(100, 32, 0, 0, 0, &memory_mapping, &mut result); + assert_eq!( + Err(EbpfError::UserError(BpfError::SyscallError( + SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) + ))), + result + ); } #[test] - #[should_panic(expected = "UserError(SyscallError(Panic(\"Gaggablaghblagh!\", 42, 84)))")] - fn test_syscall_sol_panic() { - let string = "Gaggablaghblagh!"; - let addr = string.as_ptr() as *const _ as u64; + fn test_syscall_sol_alloc_free() { + // large alloc + { + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], + &DEFAULT_CONFIG, + ) + .unwrap(); + let mut syscall = SyscallAllocFree { + aligned: true, + allocator: BpfAllocator::new(heap, MM_HEAP_START), + }; + let mut result: Result> = Ok(0); + syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_ne!(result.unwrap(), 0); + let mut result: Result> = Ok(0); + syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_eq!(result.unwrap(), 0); + let mut result: Result> = Ok(0); + syscall.call(u64::MAX, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_eq!(result.unwrap(), 0); + } + // many small unaligned allocs + { + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], + &DEFAULT_CONFIG, + ) + .unwrap(); + let mut syscall = SyscallAllocFree { + aligned: false, + allocator: BpfAllocator::new(heap, MM_HEAP_START), + }; + for _ in 0..100 { + let mut result: Result> = Ok(0); + syscall.call(1, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_ne!(result.unwrap(), 0); + } + let mut result: Result> = Ok(0); + syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_eq!(result.unwrap(), 0); + } + // many small aligned allocs + { + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], + &DEFAULT_CONFIG, + ) + .unwrap(); + let mut syscall = SyscallAllocFree { + aligned: true, + allocator: BpfAllocator::new(heap, MM_HEAP_START), + }; + for _ in 0..12 { + let mut result: Result> = Ok(0); + syscall.call(1, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_ne!(result.unwrap(), 0); + } + let mut result: Result> = Ok(0); + syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); + assert_eq!(result.unwrap(), 0); + } + // aligned allocs + + fn check_alignment() { + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], + &DEFAULT_CONFIG, + ) + .unwrap(); + let mut syscall = SyscallAllocFree { + aligned: true, + allocator: BpfAllocator::new(heap, MM_HEAP_START), + }; + let mut result: Result> = Ok(0); + syscall.call( + size_of::() as u64, + 0, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + let address = result.unwrap(); + assert_ne!(address, 0); + assert_eq!((address as *const u8).align_offset(align_of::()), 0); + } + check_alignment::(); + check_alignment::(); + check_alignment::(); + check_alignment::(); + check_alignment::(); + } + + #[test] + fn test_syscall_sha256() { + let bytes1 = "Gaggablaghblagh!"; + let bytes2 = "flurbos"; + + #[allow(dead_code)] + struct MockSlice { + pub addr: u64, + pub len: usize, + } + let mock_slice1 = MockSlice { + addr: 4096, + len: bytes1.len(), + }; + let mock_slice2 = MockSlice { + addr: 8192, + len: bytes2.len(), + }; + let bytes_to_hash = [mock_slice1, mock_slice2]; + let hash_result = [0; HASH_BYTES]; + let ro_len = bytes_to_hash.len() as u64; + let ro_va = 96; + let rw_va = 192; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: string.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion { + host_addr: bytes1.as_ptr() as *const _ as u64, + vm_addr: 4096, + len: bytes1.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bytes2.as_ptr() as *const _ as u64, + vm_addr: 8192, + len: bytes2.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bytes_to_hash.as_ptr() as *const _ as u64, + vm_addr: 96, + len: 32, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: hash_result.as_ptr() as *const _ as u64, + vm_addr: rw_va, + len: HASH_BYTES as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], &DEFAULT_CONFIG, ) .unwrap(); - let compute_meter: Rc> = Rc::new(RefCell::new(MockComputeMeter { - remaining: string.len() as u64 - 1, + remaining: (bytes1.len() + bytes2.len()) as u64, })); - let mut syscall_panic = SyscallPanic { + let mut syscall = SyscallSha256 { + sha256_base_cost: 0, + sha256_byte_cost: 2, compute_meter, - loader_id: &bpf_loader::id(), + loader_id: &bpf_loader_deprecated::id(), enforce_aligned_host_addrs: true, }; + let mut result: Result> = Ok(0); - syscall_panic.call( - 100, - string.len() as u64, - 42, - 84, + syscall.call(ro_va, ro_len, rw_va, 0, 0, &memory_mapping, &mut result); + result.unwrap(); + + let hash_local = hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes(); + assert_eq!(hash_result, hash_local); + let mut result: Result> = Ok(0); + syscall.call( + ro_va - 1, // AccessViolation + ro_len, + rw_va, + 0, + &memory_mapping, + &mut result, + ); + assert_access_violation!(result, ro_va - 1, ro_len); + let mut result: Result> = Ok(0); + syscall.call( + ro_va, + ro_len + 1, // AccessViolation + rw_va, + 0, + &memory_mapping, + &mut result, + ); + assert_access_violation!(result, ro_va - 1, ro_len); + let mut result: Result> = Ok(0); + syscall.call( + ro_va, + ro_len + 1, // AccessViolation + rw_va, + 0, + 0, + &memory_mapping, + &mut result, + ); + assert_access_violation!(result, ro_va, ro_len + 1); + let mut result: Result> = Ok(0); + syscall.call( + ro_va, + ro_len, + rw_va - 1, // AccessViolation + 0, 0, &memory_mapping, &mut result, ); + assert_access_violation!(result, rw_va - 1, HASH_BYTES as u64); + + syscall.call(ro_va, ro_len, rw_va, 0, 0, &memory_mapping, &mut result); assert_eq!( Err(EbpfError::UserError(BpfError::SyscallError( SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) ))), result ); + } - let compute_meter: Rc> = - Rc::new(RefCell::new(MockComputeMeter { - remaining: string.len() as u64, - })); - let mut syscall_panic = SyscallPanic { + #[test] + fn test_syscall_get_sysvar() { + // Test clock sysvar + { + let got_clock = Clock::default(); + let got_clock_va = 2048; + + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: &got_clock as *const _ as u64, + vm_addr: got_clock_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let src_clock = Clock { + slot: 1, + epoch_start_timestamp: 2, + epoch: 3, + leader_schedule_epoch: 4, + unix_timestamp: 5, + }; + let mut invoke_context = MockInvokeContext::new(vec![]); + let mut data = vec![]; + bincode::serialize_into(&mut data, &src_clock).unwrap(); + invoke_context + .sysvars + .push((sysvar::clock::id(), Some(Rc::new(data)))); + + let mut syscall = SyscallGetClockSysvar { + invoke_context: Rc::new(RefCell::new(&mut invoke_context)), + loader_id: &bpf_loader::id(), + }; + let mut result: Result> = Ok(0); + + syscall.call(got_clock_va, 0, 0, 0, 0, &memory_mapping, &mut result); + result.unwrap(); + assert_eq!(got_clock, src_clock); + } + + // Test epoch_schedule sysvar + { + let got_epochschedule = EpochSchedule::default(); + let got_epochschedule_va = 2048; + + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: &got_epochschedule as *const _ as u64, + vm_addr: got_epochschedule_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let src_epochschedule = EpochSchedule { + slots_per_epoch: 1, + leader_schedule_slot_offset: 2, + warmup: false, + first_normal_epoch: 3, + first_normal_slot: 4, + }; + let mut invoke_context = MockInvokeContext::new(vec![]); + let mut data = vec![]; + bincode::serialize_into(&mut data, &src_epochschedule).unwrap(); + invoke_context + .sysvars + .push((sysvar::epoch_schedule::id(), Some(Rc::new(data)))); + + let mut syscall = SyscallGetEpochScheduleSysvar { + invoke_context: Rc::new(RefCell::new(&mut invoke_context)), + loader_id: &bpf_loader::id(), + }; + let mut result: Result> = Ok(0); + + syscall.call( + got_epochschedule_va, + 0, + 0, + 0, + 0, + &memory_mapping, + &mut result, + ); + result.unwrap(); + assert_eq!(got_epochschedule, src_epochschedule); + } + + // Test fees sysvar + { + let got_fees = Fees::default(); + let got_fees_va = 2048; + + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: &got_fees as *const _ as u64, + vm_addr: got_fees_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let src_fees = Fees { + fee_calculator: FeeCalculator { + lamports_per_signature: 1, + }, + }; + let mut invoke_context = MockInvokeContext::new(vec![]); + let mut data = vec![]; + bincode::serialize_into(&mut data, &src_fees).unwrap(); + invoke_context + .sysvars + .push((sysvar::fees::id(), Some(Rc::new(data)))); + + let mut syscall = SyscallGetFeesSysvar { + invoke_context: Rc::new(RefCell::new(&mut invoke_context)), + loader_id: &bpf_loader::id(), + }; + let mut result: Result> = Ok(0); + + syscall.call(got_fees_va, 0, 0, 0, 0, &memory_mapping, &mut result); + result.unwrap(); + assert_eq!(got_fees, src_fees); + } + + // Test rent sysvar + { + let got_rent = Rent::default(); + let got_rent_va = 2048; + + let memory_mapping = MemoryMapping::new::( + vec![MemoryRegion { + host_addr: &got_rent as *const _ as u64, + vm_addr: got_rent_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let src_rent = Rent { + lamports_per_byte_year: 1, + exemption_threshold: 2.0, + burn_percent: 3, + }; + let mut invoke_context = MockInvokeContext::new(vec![]); + let mut data = vec![]; + bincode::serialize_into(&mut data, &src_rent).unwrap(); + invoke_context + .sysvars + .push((sysvar::rent::id(), Some(Rc::new(data)))); + + let mut syscall = SyscallGetRentSysvar { + invoke_context: Rc::new(RefCell::new(&mut invoke_context)), + loader_id: &bpf_loader::id(), + }; + let mut result: Result> = Ok(0); + + syscall.call(got_rent_va, 0, 0, 0, 0, &memory_mapping, &mut result); + result.unwrap(); + assert_eq!(got_rent, src_rent); + } + } + + // Bignum tests + // creates new bignum with u32 value + fn new_u32_bignum(val: u32) -> (Vec, bool) { + let mut my_buffer = Vec::::with_capacity(4); + let bytes_len = 4u64; + let mut sol_out_ffi = FfiBigNumber { + data: 1024u64, + data_len: bytes_len, + is_negative: false, + }; + // let bytes_len_addr = &mut bytes_len as *mut _ as u64; + let memory_mapping = MemoryMapping::new::( + vec![ + MemoryRegion { + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 96, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: my_buffer.as_mut_ptr() as *mut _ as u64, + vm_addr: 1024, + len: bytes_len, + vm_gap_shift: 63, + is_writable: true, + }, + ], + &DEFAULT_CONFIG, + ) + .unwrap(); + + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { remaining: 400 })); + let mut syscall = SyscallBigNumFromU32 { + cost: 100, + word_cost: 6, + word_div_cost: 32, compute_meter, loader_id: &bpf_loader::id(), - enforce_aligned_host_addrs: true, }; let mut result: Result> = Ok(0); - syscall_panic.call( - 100, - string.len() as u64, - 42, - 84, - 0, - &memory_mapping, - &mut result, - ); + syscall.call(96, val as u64, 0, 0, 0, &memory_mapping, &mut result); result.unwrap(); + unsafe { my_buffer.set_len(sol_out_ffi.data_len as usize) }; + (my_buffer, sol_out_ffi.is_negative) } - - #[test] - fn test_syscall_sol_log() { - let string = "Gaggablaghblagh!"; - let addr = string.as_ptr() as *const _ as u64; - - let compute_meter: Rc> = - Rc::new(RefCell::new(MockComputeMeter { remaining: 1000000 })); - let log = Rc::new(RefCell::new(vec![])); - let logger: Rc> = - Rc::new(RefCell::new(MockLogger { log: log.clone() })); - let mut syscall_sol_log = SyscallLog { - compute_meter, - logger, - loader_id: &bpf_loader::id(), - enforce_aligned_host_addrs: true, + // creates new bignum from decimal string + fn new_dec_str_bignum(string: &str) -> Result<(Vec, bool), EbpfError> { + let dec_str_addr = string.as_ptr() as *const _ as u64; + let dec_str_len = string.len(); + // Return Ffi + let mut my_buffer = Vec::::with_capacity(dec_str_len); + let bytes_len = my_buffer.capacity() as u64; + let mut sol_out_ffi = FfiBigNumber { + data: 8196u64, + data_len: bytes_len, + is_negative: false, }; + let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: string.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion { + host_addr: dec_str_addr, + vm_addr: 2048, + len: dec_str_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 96, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: my_buffer.as_mut_ptr() as *mut _ as u64, + vm_addr: 8196, + len: bytes_len, + vm_gap_shift: 63, + is_writable: true, + }, + ], &DEFAULT_CONFIG, ) .unwrap(); + let compute_meter: Rc> = + Rc::new(RefCell::new(MockComputeMeter { remaining: 10_000 })); + let mut syscall = SyscallBigNumFromDecStr { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter, + loader_id: &bpf_loader::id(), + }; let mut result: Result> = Ok(0); - syscall_sol_log.call( - 100, - string.len() as u64, - 0, + syscall.call( + 2048, + dec_str_len as u64, + 96, 0, 0, &memory_mapping, &mut result, ); - result.unwrap(); - assert_eq!(log.borrow().len(), 1); - assert_eq!(log.borrow()[0], "Program log: Gaggablaghblagh!"); + match result { + Ok(_) => { + unsafe { my_buffer.set_len(sol_out_ffi.data_len as usize) }; + Ok((my_buffer, sol_out_ffi.is_negative)) + } + Err(e) => Err(e), + } + } + // creates new bignum with u32 value + fn new_from_slice_bignum(val: &[u8]) -> Result<(Vec, bool), EbpfError> { + let mut my_buffer = Vec::::with_capacity(val.len()); + let bytes_len = val.len(); + let mut sol_out_ffi = FfiBigNumber { + data: 8192u64, + data_len: bytes_len as u64, + is_negative: false, + }; - let mut result: Result> = Ok(0); - syscall_sol_log.call( - 101, // AccessViolation - string.len() as u64, - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, 101, string.len() as u64); - let mut result: Result> = Ok(0); - syscall_sol_log.call( - 100, - string.len() as u64 * 2, // AccessViolation - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, 100, string.len() as u64 * 2); - let mut result: Result> = Ok(0); - syscall_sol_log.call( - 100, - string.len() as u64, - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); + let memory_mapping = MemoryMapping::new::( + vec![ + MemoryRegion { + host_addr: val.as_ptr() as *const _ as u64, + vm_addr: 0, + len: bytes_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 4096, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: my_buffer.as_mut_ptr() as *mut _ as u64, + vm_addr: 8192, + len: bytes_len as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], + &DEFAULT_CONFIG, + ) + .unwrap(); let compute_meter: Rc> = - Rc::new(RefCell::new(MockComputeMeter { - remaining: (string.len() as u64 * 2) - 1, - })); - let logger: Rc> = Rc::new(RefCell::new(MockLogger { log })); - let mut syscall_sol_log = SyscallLog { + Rc::new(RefCell::new(MockComputeMeter { remaining: 400 })); + let mut syscall = SyscallBigNumFromBytes { + cost: 100, + word_cost: 1, + word_div_cost: 32, compute_meter, - logger, loader_id: &bpf_loader::id(), - enforce_aligned_host_addrs: true, }; + let rhs_in_ffi = FfiBigNumber { + data: 2048u64, + data_len: bn2_len as u64, + is_negative: bn2_is_negative, + }; + let mod_in_ffi = FfiBigNumber { + data: 4096u64, + data_len: bn3_len as u64, + is_negative: bn3_is_negative, + }; + let mut result_vec = Vec::::with_capacity(bn1_len * bn3_len); + let mut sol_out_ffi = FfiBigNumber { + data: 5120u64, + data_len: result_vec.capacity() as u64, + is_negative: false, + }; + let memory_mapping = MemoryMapping::new::( + vec![ + MemoryRegion { + host_addr: &lhs_in_ffi as *const _ as u64, + vm_addr: 24, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg1.as_ptr() as *const _ as u64, + vm_addr: 1024, + len: bn1_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &rhs_in_ffi as *const _ as u64, + vm_addr: 48, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg2.as_ptr() as *const _ as u64, + vm_addr: 2048, + len: bn2_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &mod_in_ffi as *const _ as u64, + vm_addr: 72, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg3.as_ptr() as *const _ as u64, + vm_addr: 4096, + len: bn3_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 96, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: result_vec.as_mut_ptr() as *mut _ as u64, + vm_addr: 5120, + len: result_vec.capacity() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], + &DEFAULT_CONFIG, + ) + .unwrap(); let mut result: Result> = Ok(0); - syscall_sol_log.call( - 100, - string.len() as u64, - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); - result.unwrap(); - let mut result: Result> = Ok(0); - syscall_sol_log.call( - 100, - string.len() as u64, + syscall.call( 0, + bytes_len as u64, + 4096, 0, 0, &memory_mapping, &mut result, ); - assert_eq!( - Err(EbpfError::UserError(BpfError::SyscallError( - SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) - ))), - result - ); + match result { + Ok(_) => { + unsafe { my_buffer.set_len(sol_out_ffi.data_len as usize) }; + Ok((my_buffer, sol_out_ffi.is_negative)) + } + Err(e) => Err(e), + } } #[test] - fn test_syscall_sol_log_u64() { - let compute_meter: Rc> = - Rc::new(RefCell::new(MockComputeMeter { - remaining: std::u64::MAX, - })); - let log = Rc::new(RefCell::new(vec![])); - let logger: Rc> = - Rc::new(RefCell::new(MockLogger { log: log.clone() })); - let mut syscall_sol_log_u64 = SyscallLogU64 { - cost: 0, - compute_meter, - logger, + fn test_syscall_bignum_from_u32() { + let (bn_20, is_negative) = new_u32_bignum(20u32); + assert!(!is_negative); + let bn = BigNum::from_u32(20u32).unwrap().to_vec(); + assert_eq!(bn_20, bn); + } + + #[test] + fn test_syscall_bignum_from_dec_str() { + let (bn_long_dec, is_negative) = new_dec_str_bignum(LONG_DEC_STRING).unwrap(); + assert!(!is_negative); + let bns = BigNum::from_dec_str(LONG_DEC_STRING).unwrap(); + let bns_vec = bns.as_ref().to_vec(); + assert_eq!(bn_long_dec, bns_vec); + let (bn_neg_long_dec, is_negative) = new_dec_str_bignum(NEG_LONG_DEC_STRING).unwrap(); + assert!(is_negative); + let bns = BigNum::from_dec_str(NEG_LONG_DEC_STRING).unwrap(); + let bns_vec = bns.as_ref().to_vec(); + assert_eq!(bn_neg_long_dec, bns_vec); + } + + #[test] + fn test_syscall_bignum_from_dec_str_fails() { + assert!(new_dec_str_bignum(NOT_A_VALID_DEC_STRING).is_err()); + assert!(new_dec_str_bignum("").is_err()); + assert!(new_dec_str_bignum(&format!("{}{}", LONG_DEC_STRING, LONG_DEC_STRING)).is_err()); + } + + #[test] + fn test_syscall_bignum_from_slice() { + let (bn_from_slice, is_negative) = + new_from_slice_bignum(&[255, 255, 255, 255, 255, 255, 255, 255]).unwrap(); + assert_eq!(bn_from_slice, [255, 255, 255, 255, 255, 255, 255, 255]); + assert!(!is_negative); + assert!(new_from_slice_bignum(&vec![255u8; 1024]).is_ok()); + } + #[test] + fn test_syscall_bignum_from_slice_fail() { + assert!(new_from_slice_bignum(&vec![255u8; 2048]).is_err()); + assert!(new_from_slice_bignum(&[]).is_err()); + } + + // Wrapper for two argument bignum calls + fn invoke_bignum_two_arg_calls( + lhs: u32, + rhs: u32, + syscall: &mut dyn solana_rbpf::vm::SyscallObject, + ) -> Result<(Vec, bool), EbpfError> { + let (bn_arg1, bn1_is_negative) = new_u32_bignum(lhs); + let (bn_arg2, bn2_is_negative) = new_u32_bignum(rhs); + let bn1_len = bn_arg1.len(); + let bn2_len = bn_arg2.len(); + // Setup Ffi + let lhs_in_ffi = FfiBigNumber { + data: 1024u64, + data_len: bn1_len as u64, + is_negative: bn1_is_negative, + }; + let rhs_in_ffi = FfiBigNumber { + data: 2048u64, + data_len: bn2_len as u64, + is_negative: bn2_is_negative, + }; + let mut result_vec = Vec::::with_capacity(bn1_len + bn2_len); + let mut sol_out_ffi = FfiBigNumber { + data: 4096u64, + data_len: result_vec.capacity() as u64, + is_negative: false, }; - let memory_mapping = MemoryMapping::new::(vec![], &DEFAULT_CONFIG).unwrap(); - let mut result: Result> = Ok(0); - syscall_sol_log_u64.call(1, 2, 3, 4, 5, &memory_mapping, &mut result); - result.unwrap(); + let memory_mapping = MemoryMapping::new::( + vec![ + MemoryRegion { + host_addr: &lhs_in_ffi as *const _ as u64, + vm_addr: 24, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg1.as_ptr() as *const _ as u64, + vm_addr: 1024, + len: bn1_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &rhs_in_ffi as *const _ as u64, + vm_addr: 48, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg2.as_ptr() as *const _ as u64, + vm_addr: 2048, + len: bn2_len as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 72, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: result_vec.as_mut_ptr() as *mut _ as u64, + vm_addr: 4096, + len: result_vec.capacity() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], + &DEFAULT_CONFIG, + ) + .unwrap(); - assert_eq!(log.borrow().len(), 1); - assert_eq!(log.borrow()[0], "Program log: 0x1, 0x2, 0x3, 0x4, 0x5"); + let mut result: Result> = Ok(0); + syscall.call(24, 48, 72, 0, 0, &memory_mapping, &mut result); + match result { + Ok(_) => { + unsafe { result_vec.set_len(sol_out_ffi.data_len as usize) }; + Ok((result_vec, sol_out_ffi.is_negative)) + } + Err(e) => Err(e), + } } - #[test] - fn test_syscall_sol_pubkey() { - let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap(); - let addr = &pubkey.as_ref()[0] as *const _ as u64; - - let compute_meter: Rc> = - Rc::new(RefCell::new(MockComputeMeter { remaining: 2 })); - let log = Rc::new(RefCell::new(vec![])); - let logger: Rc> = - Rc::new(RefCell::new(MockLogger { log: log.clone() })); - let mut syscall_sol_pubkey = SyscallLogPubkey { - cost: 1, - compute_meter, - logger, - loader_id: &bpf_loader::id(), - enforce_aligned_host_addrs: true, + fn invoke_bignum_three_arg_calls( + lhs: u32, + rhs: u32, + mod_arg: u32, + syscall: &mut dyn solana_rbpf::vm::SyscallObject, + ) -> Result<(Vec, bool), EbpfError> { + let (bn_arg1, bn1_is_negative) = new_u32_bignum(lhs); + let (bn_arg2, bn2_is_negative) = new_u32_bignum(rhs); + let (bn_arg3, bn3_is_negative) = new_u32_bignum(mod_arg); + let bn1_len = bn_arg1.len(); + let bn2_len = bn_arg2.len(); + let bn3_len = bn_arg3.len(); + // Setup Ffi + let lhs_in_ffi = FfiBigNumber { + data: 1024u64, + data_len: bn1_len as u64, + is_negative: bn1_is_negative, + }; + let rhs_in_ffi = FfiBigNumber { + data: 2048u64, + data_len: bn2_len as u64, + is_negative: bn2_is_negative, + }; + let mod_in_ffi = FfiBigNumber { + data: 4096u64, + data_len: bn3_len as u64, + is_negative: bn3_is_negative, + }; + let mut result_vec = Vec::::with_capacity(bn1_len * bn3_len); + let mut sol_out_ffi = FfiBigNumber { + data: 5120u64, + data_len: result_vec.capacity() as u64, + is_negative: false, }; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: 32, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion { + host_addr: &lhs_in_ffi as *const _ as u64, + vm_addr: 24, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg1.as_ptr() as *const _ as u64, + vm_addr: 1024, + len: bn1_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &rhs_in_ffi as *const _ as u64, + vm_addr: 48, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg2.as_ptr() as *const _ as u64, + vm_addr: 2048, + len: bn2_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &mod_in_ffi as *const _ as u64, + vm_addr: 72, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: bn_arg3.as_ptr() as *const _ as u64, + vm_addr: 4096, + len: bn3_len as u64, + vm_gap_shift: 63, + is_writable: false, + }, + MemoryRegion { + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 96, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + MemoryRegion { + host_addr: result_vec.as_mut_ptr() as *mut _ as u64, + vm_addr: 5120, + len: result_vec.capacity() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], &DEFAULT_CONFIG, ) .unwrap(); - - let mut result: Result> = Ok(0); - syscall_sol_pubkey.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); - result.unwrap(); - assert_eq!(log.borrow().len(), 1); - assert_eq!( - log.borrow()[0], - "Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN" - ); - let mut result: Result> = Ok(0); - syscall_sol_pubkey.call( - 101, // AccessViolation - 32, - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, 101, 32); let mut result: Result> = Ok(0); - syscall_sol_pubkey.call(100, 32, 0, 0, 0, &memory_mapping, &mut result); - assert_eq!( - Err(EbpfError::UserError(BpfError::SyscallError( - SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) - ))), - result - ); + syscall.call(24, 48, 72, 96, 0, &memory_mapping, &mut result); + match result { + Ok(_) => { + unsafe { result_vec.set_len(sol_out_ffi.data_len as usize) }; + Ok((result_vec, sol_out_ffi.is_negative)) + } + Err(e) => Err(e), + } } #[test] - fn test_syscall_sol_alloc_free() { - // large alloc - { - let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], - &DEFAULT_CONFIG, - ) - .unwrap(); - let mut syscall = SyscallAllocFree { - aligned: true, - allocator: BpfAllocator::new(heap, MM_HEAP_START), - }; - let mut result: Result> = Ok(0); - syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_ne!(result.unwrap(), 0); - let mut result: Result> = Ok(0); - syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_eq!(result.unwrap(), 0); - let mut result: Result> = Ok(0); - syscall.call(u64::MAX, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_eq!(result.unwrap(), 0); - } - // many small unaligned allocs - { - let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], - &DEFAULT_CONFIG, - ) - .unwrap(); - let mut syscall = SyscallAllocFree { - aligned: false, - allocator: BpfAllocator::new(heap, MM_HEAP_START), - }; - for _ in 0..100 { - let mut result: Result> = Ok(0); - syscall.call(1, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_ne!(result.unwrap(), 0); - } - let mut result: Result> = Ok(0); - syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_eq!(result.unwrap(), 0); - } - // many small aligned allocs - { - let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], - &DEFAULT_CONFIG, - ) - .unwrap(); - let mut syscall = SyscallAllocFree { - aligned: true, - allocator: BpfAllocator::new(heap, MM_HEAP_START), - }; - for _ in 0..12 { - let mut result: Result> = Ok(0); - syscall.call(1, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_ne!(result.unwrap(), 0); - } - let mut result: Result> = Ok(0); - syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); - assert_eq!(result.unwrap(), 0); - } - // aligned allocs + fn test_syscall_bignum_simple_math_pass() { + let mut syscall_bn_add = SyscallBigNumAdd { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + let mut syscall_bn_sub = SyscallBigNumSub { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + let mut syscall_bn_mul = SyscallBigNumMul { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + let mut syscall_bn_div = SyscallBigNumDiv { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + assert!(invoke_bignum_two_arg_calls(5, 258, &mut syscall_bn_add).is_ok()); + assert!(invoke_bignum_two_arg_calls(5, 258, &mut syscall_bn_sub).is_ok()); + assert!(invoke_bignum_two_arg_calls(300, 10, &mut syscall_bn_div).is_ok()); + assert!(invoke_bignum_two_arg_calls(5, 5, &mut syscall_bn_mul).is_ok()); + } - fn check_alignment() { - let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], - &DEFAULT_CONFIG, - ) - .unwrap(); - let mut syscall = SyscallAllocFree { - aligned: true, - allocator: BpfAllocator::new(heap, MM_HEAP_START), - }; - let mut result: Result> = Ok(0); - syscall.call( - size_of::() as u64, - 0, - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); - let address = result.unwrap(); - assert_ne!(address, 0); - assert_eq!((address as *const u8).align_offset(align_of::()), 0); - } - check_alignment::(); - check_alignment::(); - check_alignment::(); - check_alignment::(); - check_alignment::(); + #[test] + fn test_syscall_bignum_simple_math_fail() { + let mut syscall_bn_div = SyscallBigNumDiv { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + assert!(invoke_bignum_two_arg_calls(300, 0, &mut syscall_bn_div).is_err()); } #[test] - fn test_syscall_sha256() { - let bytes1 = "Gaggablaghblagh!"; - let bytes2 = "flurbos"; + fn test_syscall_bignum_complex_math() { + let mut syscall_bn_exp = SyscallBigNumExp { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + let mut syscall_bn_mod_sqr = SyscallBigNumModSqr { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + let mut syscall_bn_mod_inv = SyscallBigNumModInv { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + assert!(invoke_bignum_two_arg_calls(8, 2, &mut syscall_bn_exp).is_ok()); + assert!(invoke_bignum_two_arg_calls(11, 7, &mut syscall_bn_mod_sqr).is_ok()); + assert!(invoke_bignum_two_arg_calls(415, 77, &mut syscall_bn_mod_inv).is_ok()); + } - #[allow(dead_code)] - struct MockSlice { - pub addr: u64, - pub len: usize, - } - let mock_slice1 = MockSlice { - addr: 4096, - len: bytes1.len(), + #[test] + fn test_syscall_bignum_complex_math2() { + let mut syscall_bn_mod_exp = SyscallBigNumModExp { + cost: 1, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), + }; + let mut syscall_bn_mod_mul = SyscallBigNumModMul { + cost: 1, + word_cost: 6, + word_div_cost: 32, + compute_meter: Rc::new(RefCell::new(MockComputeMeter { remaining: 200_u64 })), + loader_id: &bpf_loader::id(), }; - let mock_slice2 = MockSlice { - addr: 8192, - len: bytes2.len(), + assert!(invoke_bignum_three_arg_calls(300, 11, 7, &mut syscall_bn_mod_exp).is_ok()); + assert!(invoke_bignum_three_arg_calls(300, 11, 7, &mut syscall_bn_mod_mul).is_ok()); + } + + #[test] + fn test_syscall_bignum_sqr() { + let (bn_arg1, bn1_is_negative) = new_u32_bignum(300); + let bn1_len = bn_arg1.len(); + + // Setup Ffi + let rhs_in_ffi = FfiBigNumber { + data: 1024u64, + data_len: bn1_len as u64, + is_negative: bn1_is_negative, + }; + let mut result_vec = Vec::::with_capacity(bn1_len * 2); + let mut sol_out_ffi = FfiBigNumber { + data: 4096u64, + data_len: result_vec.capacity() as u64, + is_negative: false, }; - let bytes_to_hash = [mock_slice1, mock_slice2]; - let hash_result = [0; HASH_BYTES]; - let ro_len = bytes_to_hash.len() as u64; - let ro_va = 96; - let rw_va = 192; let memory_mapping = MemoryMapping::new::( vec![ MemoryRegion { - host_addr: bytes1.as_ptr() as *const _ as u64, - vm_addr: 4096, - len: bytes1.len() as u64, + host_addr: &rhs_in_ffi as *const _ as u64, + vm_addr: 24, + len: std::mem::size_of::() as u64, vm_gap_shift: 63, is_writable: false, }, MemoryRegion { - host_addr: bytes2.as_ptr() as *const _ as u64, - vm_addr: 8192, - len: bytes2.len() as u64, + host_addr: bn_arg1.as_ptr() as *const _ as u64, + vm_addr: 1024, + len: bn1_len as u64, vm_gap_shift: 63, is_writable: false, }, MemoryRegion { - host_addr: bytes_to_hash.as_ptr() as *const _ as u64, - vm_addr: 96, - len: 32, + host_addr: &mut sol_out_ffi as *mut _ as u64, + vm_addr: 72, + len: std::mem::size_of::() as u64, vm_gap_shift: 63, - is_writable: false, + is_writable: true, }, MemoryRegion { - host_addr: hash_result.as_ptr() as *const _ as u64, - vm_addr: rw_va, - len: HASH_BYTES as u64, + host_addr: result_vec.as_mut_ptr() as *mut _ as u64, + vm_addr: 4096, + len: result_vec.capacity() as u64, vm_gap_shift: 63, is_writable: true, }, @@ -3106,239 +5980,43 @@ mod tests { &DEFAULT_CONFIG, ) .unwrap(); + let compute_meter: Rc> = Rc::new(RefCell::new(MockComputeMeter { - remaining: (bytes1.len() + bytes2.len()) as u64, + remaining: (20 + 20) as u64, })); - let mut syscall = SyscallSha256 { - sha256_base_cost: 0, - sha256_byte_cost: 2, + let mut syscall = SyscallBigNumSqr { + cost: 1, + word_cost: 6, + word_div_cost: 32, compute_meter, - loader_id: &bpf_loader_deprecated::id(), - enforce_aligned_host_addrs: true, + loader_id: &bpf_loader::id(), }; - let mut result: Result> = Ok(0); - syscall.call(ro_va, ro_len, rw_va, 0, 0, &memory_mapping, &mut result); + syscall.call(24, 72, 0, 8, 16, &memory_mapping, &mut result); result.unwrap(); - - let hash_local = hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes(); - assert_eq!(hash_result, hash_local); - let mut result: Result> = Ok(0); - syscall.call( - ro_va - 1, // AccessViolation - ro_len, - rw_va, - 0, - 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, ro_va - 1, ro_len); - let mut result: Result> = Ok(0); - syscall.call( - ro_va, - ro_len + 1, // AccessViolation - rw_va, - 0, - 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, ro_va, ro_len + 1); - let mut result: Result> = Ok(0); - syscall.call( - ro_va, - ro_len, - rw_va - 1, // AccessViolation - 0, - 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, rw_va - 1, HASH_BYTES as u64); - - syscall.call(ro_va, ro_len, rw_va, 0, 0, &memory_mapping, &mut result); - assert_eq!( - Err(EbpfError::UserError(BpfError::SyscallError( - SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded) - ))), - result - ); + unsafe { result_vec.set_len(sol_out_ffi.data_len as usize) }; + assert_eq!(result_vec, vec![1, 95, 144]); } - #[test] - fn test_syscall_get_sysvar() { - // Test clock sysvar - { - let got_clock = Clock::default(); - let got_clock_va = 2048; - - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_clock as *const _ as u64, - vm_addr: got_clock_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], - &DEFAULT_CONFIG, - ) - .unwrap(); - - let src_clock = Clock { - slot: 1, - epoch_start_timestamp: 2, - epoch: 3, - leader_schedule_epoch: 4, - unix_timestamp: 5, - }; - let mut invoke_context = MockInvokeContext::new(vec![]); - let mut data = vec![]; - bincode::serialize_into(&mut data, &src_clock).unwrap(); - invoke_context - .sysvars - .push((sysvar::clock::id(), Some(Rc::new(data)))); - - let mut syscall = SyscallGetClockSysvar { - invoke_context: Rc::new(RefCell::new(&mut invoke_context)), - loader_id: &bpf_loader::id(), - }; - let mut result: Result> = Ok(0); - - syscall.call(got_clock_va, 0, 0, 0, 0, &memory_mapping, &mut result); - result.unwrap(); - assert_eq!(got_clock, src_clock); - } - - // Test epoch_schedule sysvar - { - let got_epochschedule = EpochSchedule::default(); - let got_epochschedule_va = 2048; - - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_epochschedule as *const _ as u64, - vm_addr: got_epochschedule_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], - &DEFAULT_CONFIG, - ) - .unwrap(); - - let src_epochschedule = EpochSchedule { - slots_per_epoch: 1, - leader_schedule_slot_offset: 2, - warmup: false, - first_normal_epoch: 3, - first_normal_slot: 4, - }; - let mut invoke_context = MockInvokeContext::new(vec![]); - let mut data = vec![]; - bincode::serialize_into(&mut data, &src_epochschedule).unwrap(); - invoke_context - .sysvars - .push((sysvar::epoch_schedule::id(), Some(Rc::new(data)))); - - let mut syscall = SyscallGetEpochScheduleSysvar { - invoke_context: Rc::new(RefCell::new(&mut invoke_context)), - loader_id: &bpf_loader::id(), - }; - let mut result: Result> = Ok(0); - - syscall.call( - got_epochschedule_va, - 0, - 0, - 0, - 0, - &memory_mapping, - &mut result, - ); - result.unwrap(); - assert_eq!(got_epochschedule, src_epochschedule); - } - - // Test fees sysvar - { - let got_fees = Fees::default(); - let got_fees_va = 2048; - - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_fees as *const _ as u64, - vm_addr: got_fees_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], - &DEFAULT_CONFIG, - ) - .unwrap(); - - let src_fees = Fees { - fee_calculator: FeeCalculator { - lamports_per_signature: 1, - }, - }; - let mut invoke_context = MockInvokeContext::new(vec![]); - let mut data = vec![]; - bincode::serialize_into(&mut data, &src_fees).unwrap(); - invoke_context - .sysvars - .push((sysvar::fees::id(), Some(Rc::new(data)))); - - let mut syscall = SyscallGetFeesSysvar { - invoke_context: Rc::new(RefCell::new(&mut invoke_context)), - loader_id: &bpf_loader::id(), - }; - let mut result: Result> = Ok(0); - - syscall.call(got_fees_va, 0, 0, 0, 0, &memory_mapping, &mut result); - result.unwrap(); - assert_eq!(got_fees, src_fees); - } - - // Test rent sysvar - { - let got_rent = Rent::default(); - let got_rent_va = 2048; - - let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_rent as *const _ as u64, - vm_addr: got_rent_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], - &DEFAULT_CONFIG, - ) - .unwrap(); - - let src_rent = Rent { - lamports_per_byte_year: 1, - exemption_threshold: 2.0, - burn_percent: 3, - }; - let mut invoke_context = MockInvokeContext::new(vec![]); - let mut data = vec![]; - bincode::serialize_into(&mut data, &src_rent).unwrap(); - invoke_context - .sysvars - .push((sysvar::rent::id(), Some(Rc::new(data)))); + fn test_valid_big_endian() { + let be_bytes_in = u32::to_be_bytes(256); + let bn_bytes_out = BigNum::from_slice(&be_bytes_in).unwrap().to_vec(); + assert_eq!(bn_bytes_out, [1, 0]); +<<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 51b0df078 (Bignum encoding length variations) + let be_bytes_in: Vec = vec![0, 0, 0, 0, 0, 0, 1, 0]; + let bn_bytes_out = BigNum::from_slice(&be_bytes_in).unwrap().to_vec(); + assert_eq!(bn_bytes_out, [1, 0]); + } +======= + } +<<<<<<< HEAD - let mut syscall = SyscallGetRentSysvar { - invoke_context: Rc::new(RefCell::new(&mut invoke_context)), - loader_id: &bpf_loader::id(), - }; - let mut result: Result> = Ok(0); - syscall.call(got_rent_va, 0, 0, 0, 0, &memory_mapping, &mut result); - result.unwrap(); - assert_eq!(got_rent, src_rent); - } - } +>>>>>>> 2961987fa (Bignum syscalls) +======= +>>>>>>> 7a46654ca (Bignum syscalls) } diff --git a/sdk/bpf/c/inc/solana_bignumber.h b/sdk/bpf/c/inc/solana_bignumber.h new file mode 100644 index 00000000000000..1679e559187519 --- /dev/null +++ b/sdk/bpf/c/inc/solana_bignumber.h @@ -0,0 +1,310 @@ +#pragma once +/** + * @brief Solana C-based BPF program BigNumber functions and types + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "solana_sdk.h" + +/** + * Return the maximum of two uint64_t numbers + */ +uint64_t max_u64(uint64_t lhs, uint64_t rhs) { + if (lhs > rhs) { + return lhs; + } else { + return rhs; + } +} + +/** + * BigNumber structure required by tghe BigNum syscalls + */ +typedef struct { + uint64_t + data_len; /** Length of the data, in bytes, pointed to by data_addr */ + uint64_t + is_negative; /** Indicator if number is positive (0) or negative (1) */ + uint8_t *data_addr; /** Pointer to the array of big endian bytes representing + BigNumber value */ +} SolBigNumber; + +/** + * Initialize a SolBigNumber, inclues allocating memory for the data, must call + * `sol_bignum_deinit` to free that memory + */ +static SolBigNumber sol_bignum_init(uint64_t data_len) { + SolBigNumber bn; + bn.is_negative = false; + bn.data_len = data_len; + bn.data_addr = sol_calloc(data_len, 1); + return bn; +} + +/** + * Deinitalize a SolBigNumber, free's the data memory + */ +static void sol_bignum_deinit(SolBigNumber *bn_ptr) { + bn_ptr->is_negative = false; + bn_ptr->data_len = 0; + sol_free(bn_ptr->data_addr); + bn_ptr->data_addr = 0; +} + +/** + * sol_bignum_equal + * + * @param lhs_bn_ptr Address of the lhs SolBigNumber + * @param rhs_bn_ptr Address of the rhs SolBigNumber + */ +static bool sol_bignum_equal(SolBigNumber *lhs_bn_ptr, + SolBigNumber *rhs_bn_ptr) { + if (lhs_bn_ptr->is_negative == rhs_bn_ptr->is_negative) { + if (lhs_bn_ptr->data_len == rhs_bn_ptr->data_len) { + if (!sol_memcmp(lhs_bn_ptr->data_addr, rhs_bn_ptr->data_addr, + lhs_bn_ptr->data_len)) { + return true; + } + } + } + return false; +} + +/** + * sol_bignum_from_u32 + * + * @param val_u32 unsigned 32 bit value to assign to the new object + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_from_u32(const uint64_t val_u32) { + uint64_t sol_bignum_from_u32_(SolBigNumber * out_bn_ptr, + const uint64_t val_u32); + + SolBigNumber bn = sol_bignum_init(4); + sol_bignum_from_u32_(&bn, val_u32); + return bn; +} + +/** + * sol_bignum_from_dec_str + * + * @param in_dec_str_ptr address of decimal string + * @param in_len number of byytes in the decimal string + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_from_dec_str(const char *in_dec_str_ptr, + uint64_t str_len) { + uint64_t sol_bignum_from_dec_str_(const uint64_t *dec_str_ptr, + uint64_t str_len, SolBigNumber *out_bn_ptr); + + SolBigNumber bn = sol_bignum_init(str_len); + sol_bignum_from_dec_str_(in_dec_str_ptr, str_len, &bn); + return bn; +} + +/** + * sol_bignum_from_bytes + * @param bytes_ptr array of bytes + * @param bytes_len length of bytes + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_from_bytes(const uint8_t *bytes_ptr, + uint64_t bytes_len) { + uint64_t sol_bignum_from_bytes_(const uint64_t *bytes_ptr, uint64_t bytes_len, + SolBigNumber *out_bn_ptr); + + SolBigNumber bn = sol_bignum_init(bytes_len); + sol_bignum_from_bytes_(bytes_ptr, bytes_len, &bn); + return bn; +} + +/** + * sol_bignum_add + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_add(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr) { + uint64_t sol_bignum_add_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = + max_u64(in_bn_lhs_ptr->data_len, in_bn_rhs_ptr->data_len) + 1; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_add_(in_bn_lhs_ptr, in_bn_rhs_ptr, &bn); + return bn; +} + +/** + * sol_bignum_sub + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_sub(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr) { + uint64_t sol_bignum_sub_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = + max_u64(in_bn_lhs_ptr->data_len, in_bn_rhs_ptr->data_len) + 1; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_sub_(in_bn_lhs_ptr, in_bn_rhs_ptr, &bn); + return bn; +} +/** + * sol_bignum_mul + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_mul(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr) { + uint64_t sol_bignum_mul_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = + max_u64(in_bn_lhs_ptr->data_len, in_bn_rhs_ptr->data_len) + 1; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_mul_(in_bn_lhs_ptr, in_bn_rhs_ptr, &bn); + return bn; +} +/** + * sol_bignum_div + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_div(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr) { + uint64_t sol_bignum_div_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = + max_u64(in_bn_lhs_ptr->data_len, in_bn_rhs_ptr->data_len) + 1; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_div_(in_bn_lhs_ptr, in_bn_rhs_ptr, &bn); + return bn; +} + +/** + * sol_bignum_sqr + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param out_bn_ptr address of the SolBigNumber result structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_sqr(const SolBigNumber *in_bn_lhs_ptr) { + uint64_t sol_bignum_sqr_(const SolBigNumber *in_bn_lhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = in_bn_lhs_ptr->data_len * 2; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_sqr_(in_bn_lhs_ptr, &bn); + return bn; +} + +/** + * sol_bignum_exp + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_exp(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr) { + uint64_t sol_bignum_exp_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = in_bn_lhs_ptr->data_len + in_bn_rhs_ptr->data_len; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_exp_(in_bn_lhs_ptr, in_bn_rhs_ptr, &bn); + return bn; +} + +/** + * sol_bignum_mod_sqr + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_mod_ptr address of the modulus SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_mod_sqr(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_mod_ptr) { + uint64_t sol_bignum_mod_sqr_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = in_bn_mod_ptr->data_len; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_mod_sqr_(in_bn_lhs_ptr, in_bn_mod_ptr, &bn); + return bn; +} + +/** + * sol_bignum_mod_exp + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @param in_bn_mod_ptr address of the modulus SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_mod_exp(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + const SolBigNumber *in_bn_mod_ptr) { + uint64_t sol_bignum_mod_exp_( + const SolBigNumber *in_bn_lhs_ptr, const SolBigNumber *in_bn_rhs_ptr, + const SolBigNumber *in_bn_mod_ptr, SolBigNumber *out_bn_ptr); + uint64_t out_data_len = in_bn_mod_ptr->data_len; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_mod_exp_(in_bn_lhs_ptr, in_bn_rhs_ptr, in_bn_mod_ptr, &bn); + return bn; +} + +/** + * sol_bignum_mod_mul + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @param in_bn_mod_ptr address of the rhs SolBigNumber structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_mod_mul(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + const SolBigNumber *in_bn_mod_ptr) { + uint64_t sol_bignum_mod_mul_( + const SolBigNumber *in_bn_lhs_ptr, const SolBigNumber *in_bn_rhs_ptr, + const SolBigNumber *in_bn_mod_ptr, SolBigNumber *out_bn_ptr); + uint64_t out_data_len = in_bn_mod_ptr->data_len; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_mod_mul_(in_bn_lhs_ptr, in_bn_rhs_ptr, in_bn_mod_ptr, &bn); + return bn; +} + +/** + * sol_bignum_mod_inv + * @param in_bn_lhs_ptr address of the lhs SolBigNumber structure + * @param in_bn_rhs_ptr address of the rhs SolBigNumber structure + * @param out_bn_ptr address of the SolBigNumber result structure + * @return SolBigNumber result + */ +static SolBigNumber sol_bignum_mod_inv(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_mod_ptr) { + uint64_t sol_bignum_mod_inv_(const SolBigNumber *in_bn_lhs_ptr, + const SolBigNumber *in_bn_rhs_ptr, + SolBigNumber *out_bn_ptr); + uint64_t out_data_len = in_bn_mod_ptr->data_len; + SolBigNumber bn = sol_bignum_init(out_data_len); + sol_bignum_mod_inv_(in_bn_lhs_ptr, in_bn_mod_ptr, &bn); + return bn; +} + +/** Logs a SolBigNumber + * @param in_bn_ptr address of the SolBigNumber to log + */ +static void sol_bignum_log(const SolBigNumber *in_bn_ptr) { + uint64_t sol_bignum_log_(const SolBigNumber *in_bn_ptr); + + sol_bignum_log_(in_bn_ptr); +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk/program/Cargo.toml b/sdk/program/Cargo.toml index fa6e2e353a10e4..5a5748e9b82df6 100644 --- a/sdk/program/Cargo.toml +++ b/sdk/program/Cargo.toml @@ -35,6 +35,7 @@ thiserror = "1.0" [target.'cfg(not(target_arch = "bpf"))'.dependencies] curve25519-dalek = "2.1.0" +openssl = "0.10.32" rand = "0.7.0" solana-logger = { path = "../../logger", version = "=1.8.0" } diff --git a/sdk/program/src/bignumber.rs b/sdk/program/src/bignumber.rs new file mode 100644 index 00000000000000..1b475a0a009b0b --- /dev/null +++ b/sdk/program/src/bignumber.rs @@ -0,0 +1,826 @@ +//! Solana BigNumber +//! +//! Rust-based BigNumber provides safe math for arbitrarily large numbers. +//! Primarily focues on BPF program usage, non-BPF is also supported by +//! backing from the OpenSSL implementation + +#[repr(C)] +#[derive(Debug)] +/// BPF structure for sending/receiving BigNumber data to/from syscalls +pub struct FfiBigNumber { + pub data_len: u64, // Length of bytes of data + pub is_negative: bool, // False (0) or True (1) if data is positive or negative + pub data: u64, // Pointer to the variable length big endian array represneting the value of BigNumber +} + +#[cfg(not(target_arch = "bpf"))] +#[derive(AbiExample, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct BigNumber { + data: openssl::bn::BigNum, // For non-BPF we use OpenSSL +} +#[cfg(target_arch = "bpf")] +#[derive(AbiExample, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct BigNumber { + data: Vec, + is_negative: bool, +} + +impl BigNumber { + /// Returns a BigNumber with initial value of 0 + pub fn new() -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let bn = openssl::bn::BigNum::new().unwrap(); + Self { data: bn } + } + #[cfg(target_arch = "bpf")] + Self { + data: vec![0], + is_negative: false, + } + } + + /// Returns the size, in bytes, of BigNum. Typically used in + /// assessing buffer size needed to fetch the bytes for serialization, etc. + pub fn size_in_bytes(&self) -> usize { + #[cfg(not(target_arch = "bpf"))] + { + self.data.num_bytes() as usize + } + #[cfg(target_arch = "bpf")] + { + self.data.len() + } + } + + /// Returns a big-endian byte vector representation + /// of the absolute value of `self` + pub fn to_vec(&self) -> Vec { + #[cfg(not(target_arch = "bpf"))] + { + if self.data.num_bytes() == 0 { + return vec![0u8]; + } + self.data.to_vec() + } + #[cfg(target_arch = "bpf")] + { + self.data.clone() + } + } + + #[cfg(target_arch = "bpf")] + pub fn as_ref(&self) -> &[u8] { + &self.data + } + + /// Returns a BigNumber with initial value set to a u32 value + pub fn from_u32(u32_val: u32) -> Self { + if u32_val == 0 { + Self::new() + } else { + #[cfg(not(target_arch = "bpf"))] + { + let bn = openssl::bn::BigNum::from_u32(u32_val).unwrap(); + Self { data: bn } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_from_u32_(bn_syscall_result: *mut u64, u32_data: u64) -> u64; + } + let mut data = Vec::::with_capacity(4); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: 4u64, + is_negative: false, + } + }; + unsafe { + sol_bignum_from_u32_( + &mut bn_syscall_result as *mut _ as *mut u64, + u32_val as u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + } + + /// Returns a BigNumber from a decimal string + pub fn from_dec_str(string: &str) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let bn = openssl::bn::BigNum::from_dec_str(string).unwrap(); + Self { data: bn } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_from_dec_str_( + in_dec_str_ptr: *const u64, + in_len: u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + // The output buffer could be sized to 3.32 bits/digit but this would consume compute units + let mut data = Vec::::with_capacity(string.len()); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: string.len() as u64, + is_negative: false, + } + }; + + unsafe { + sol_bignum_from_dec_str_( + string.as_ptr() as *const _ as *const u64, + string.len() as u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Construct a BigNumber from a unsigned absolute big endian array of bytes + pub fn from_bytes(in_data: &[u8]) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + Self { + data: openssl::bn::BigNum::from_slice(in_data).unwrap(), + } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_from_bytes_( + in_bytes_ptr: *const u64, + in_bytes_len: u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let data_size = in_data.len(); + let mut data = Vec::::with_capacity(data_size); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_size as u64, + is_negative: false, + } + }; + unsafe { + sol_bignum_from_bytes_( + in_data.as_ptr() as *const _ as *const u64, + data_size as u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Flag indicating if negative or not + pub fn is_negative(&self) -> bool { + #[cfg(not(target_arch = "bpf"))] + { + self.data.is_negative() + } + #[cfg(target_arch = "bpf")] + { + self.is_negative + } + } + + /// Adds self with another BigNumber and returns + /// a new BigNumber + pub fn add(&self, rhs: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + bn_done.checked_add(&self.data, &rhs.data).unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_add_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: rhs.data.as_ptr() as *const _ as u64, + data_len: rhs.data.len() as u64, + is_negative: rhs.is_negative, + } + }; + let data_len = std::cmp::max(lhs_ffi_in.data_len, rhs_ffi_in.data_len) + 1; + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len, + is_negative: false, + } + }; + unsafe { + sol_bignum_add_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + /// Subtracts BigNumber from self and returns + /// a new BigNumber + pub fn sub(&self, rhs: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + bn_done.checked_sub(&self.data, &rhs.data).unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_sub_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: rhs.data.as_ptr() as *const _ as u64, + data_len: rhs.data.len() as u64, + is_negative: rhs.is_negative, + } + }; + let data_len = std::cmp::max(lhs_ffi_in.data_len, rhs_ffi_in.data_len) + 1; + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len, + is_negative: false, + } + }; + unsafe { + sol_bignum_sub_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Multiplies another BigNumber with self and returns + /// a new BigNumber + pub fn mul(&self, rhs: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done + .checked_mul(&self.data, &rhs.data, &mut ctx) + .unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_mul_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: rhs.data.as_ptr() as *const _ as u64, + data_len: rhs.data.len() as u64, + is_negative: rhs.is_negative, + } + }; + let data_len = std::cmp::max(lhs_ffi_in.data_len, rhs_ffi_in.data_len) + 1; + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len, + is_negative: false, + } + }; + unsafe { + sol_bignum_mul_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Divides self by another and returns + /// a new BigNumber + pub fn div(&self, rhs: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done + .checked_div(&self.data, &rhs.data, &mut ctx) + .unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_div_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: rhs.data.as_ptr() as *const _ as u64, + data_len: rhs.data.len() as u64, + is_negative: rhs.is_negative, + } + }; + let data_len = std::cmp::max(lhs_ffi_in.data_len, rhs_ffi_in.data_len) + 1; + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len, + is_negative: false, + } + }; + unsafe { + sol_bignum_div_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Returns a new BigNumber of self squared + pub fn sqr(&self) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done.sqr(&self.data, &mut ctx).unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_sqr_(lhs_ffi_in_addr: *const u64, bn_syscall_result: *mut u64) + -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let data_len = lhs_ffi_in.data_len * 2; + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len, + is_negative: false, + } + }; + unsafe { + sol_bignum_sqr_( + &lhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Raise self to exponent + pub fn exp(&self, exponent: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done.exp(&self.data, &exponent.data, &mut ctx).unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_exp_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: exponent.data.as_ptr() as *const _ as u64, + data_len: exponent.data.len() as u64, + is_negative: exponent.is_negative, + } + }; + let data_len = lhs_ffi_in.data_len * rhs_ffi_in.data_len; + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len, + is_negative: false, + } + }; + unsafe { + sol_bignum_exp_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + /// Returns self squared % modulus + pub fn mod_sqr(&self, modulus: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done + .mod_sqr(&self.data, &modulus.data, &mut ctx) + .unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_mod_sqr_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: modulus.data.as_ptr() as *const _ as u64, + data_len: modulus.data.len() as u64, + is_negative: modulus.is_negative, + } + }; + let data_len = modulus.data.len(); + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len as u64, + is_negative: false, + } + }; + unsafe { + sol_bignum_mod_sqr_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Compute modular exponentiation (self ^ exponent % modulus) and return the result + pub fn mod_exp(&self, exponent: &BigNumber, modulus: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done + .mod_exp(&self.data, &exponent.data, &modulus.data, &mut ctx) + .unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_mod_exp_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + mod_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: exponent.data.as_ptr() as *const _ as u64, + data_len: exponent.data.len() as u64, + is_negative: exponent.is_negative, + } + }; + let mod_ffi_in = { + FfiBigNumber { + data: modulus.data.as_ptr() as *const _ as u64, + data_len: modulus.data.len() as u64, + is_negative: modulus.is_negative, + } + }; + let data_len = modulus.data.len(); + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len as u64, + is_negative: false, + } + }; + + unsafe { + sol_bignum_mod_exp_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mod_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Mod multiplier (self * multiplier) % modulus + pub fn mod_mul(&self, multiplier: &BigNumber, modulus: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done + .mod_mul(&self.data, &multiplier.data, &modulus.data, &mut ctx) + .unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_mod_mul_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + mod_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: multiplier.data.as_ptr() as *const _ as u64, + data_len: multiplier.data.len() as u64, + is_negative: multiplier.is_negative, + } + }; + let mod_ffi_in = { + FfiBigNumber { + data: modulus.data.as_ptr() as *const _ as u64, + data_len: modulus.data.len() as u64, + is_negative: modulus.is_negative, + } + }; + let data_len = modulus.data.len(); + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len as u64, + is_negative: false, + } + }; + + unsafe { + sol_bignum_mod_mul_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mod_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + /// Finds the inverse of modulus on self + pub fn mod_inv(&self, modulus: &BigNumber) -> Self { + #[cfg(not(target_arch = "bpf"))] + { + let mut bn_done = openssl::bn::BigNum::new().unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + bn_done + .mod_inverse(&self.data, &modulus.data, &mut ctx) + .unwrap(); + Self { data: bn_done } + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_mod_inv_( + lhs_ffi_in_addr: *const u64, + rhs_ffi_in_addr: *const u64, + bn_syscall_result: *mut u64, + ) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + let rhs_ffi_in = { + FfiBigNumber { + data: modulus.data.as_ptr() as *const _ as u64, + data_len: modulus.data.len() as u64, + is_negative: modulus.is_negative, + } + }; + let data_len = modulus.data.len(); + let mut data = Vec::::with_capacity(data_len as usize); + let mut bn_syscall_result = { + FfiBigNumber { + data: data.as_mut_ptr() as *mut _ as u64, + data_len: data_len as u64, + is_negative: false, + } + }; + unsafe { + sol_bignum_mod_inv_( + &lhs_ffi_in as *const _ as *const u64, + &rhs_ffi_in as *const _ as *const u64, + &mut bn_syscall_result as *mut _ as *mut u64, + ); + data.set_len(bn_syscall_result.data_len as usize); + } + Self { + is_negative: bn_syscall_result.is_negative, + data, + } + } + } + + /// Log a `BigNum` from a program to the solana logs + pub fn log(&self) { + #[cfg(not(target_arch = "bpf"))] + { + crate::program_stubs::sol_log(&self.data.to_dec_str().unwrap()); + } + #[cfg(target_arch = "bpf")] + { + extern "C" { + fn sol_bignum_log_(lhs_ffi_in_addr: *const u64) -> u64; + } + let lhs_ffi_in = { + FfiBigNumber { + data: self.data.as_ptr() as *const _ as u64, + data_len: self.data.len() as u64, + is_negative: self.is_negative, + } + }; + unsafe { sol_bignum_log_(&lhs_ffi_in as *const _ as *const u64) }; + } + } +} + +#[cfg(not(target_arch = "bpf"))] +impl Clone for BigNumber { + fn clone(&self) -> Self { + match openssl::bn::BigNum::from_slice(&self.data.to_vec()) { + Ok(bn) => Self { data: bn }, + Err(_) => panic!(), + } + } +} + +impl Default for BigNumber { + fn default() -> Self { + BigNumber::new() + } +} diff --git a/sdk/program/src/lib.rs b/sdk/program/src/lib.rs index bed762359d87a8..438d7c865c4780 100644 --- a/sdk/program/src/lib.rs +++ b/sdk/program/src/lib.rs @@ -6,6 +6,7 @@ extern crate self as solana_program; pub mod account_info; +pub mod bignumber; pub mod blake3; pub mod borsh; pub mod bpf_loader; diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index 82864276fcdca1..3bd9b21f200b51 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -134,6 +134,9 @@ pub mod stake_program_v4 { pub mod memory_ops_syscalls { solana_sdk::declare_id!("ENQi37wsVhTvFz2gUiZAAbqFEWGN2jwFsqdEDTE8A4MU"); } +pub mod bignum_syscall_enabled { + solana_sdk::declare_id!("BM3LiLruWMHeSJpoN1mgEzpxfKs9f7k8FvSMbgNBqN1E"); +} pub mod add_missing_program_error_mappings { solana_sdk::declare_id!("3QEUpjhgPEt92nz3Mqf6pABkHPGCQwSvKtyGMq4SuQyL"); @@ -189,6 +192,7 @@ lazy_static! { (system_transfer_zero_check::id(), "perform all checks for transfers of 0 lamports"), (blake3_syscall_enabled::id(), "blake3 syscall"), (dedupe_config_program_signers::id(), "dedupe config program signers"), + (bignum_syscall_enabled::id(), "bignum syscall"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter() diff --git a/sdk/src/process_instruction.rs b/sdk/src/process_instruction.rs index 5a43398711b996..b452c3b46ac177 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -181,7 +181,42 @@ pub struct BpfComputeBudget { pub cpi_bytes_per_unit: u64, /// Base number of compute units consumed to get a sysvar pub sysvar_base_cost: u64, + /// Base number of compute units consumed to call BigNum new from u32 value + pub bignum_from_u32_base_cost: u64, + /// Base number of compute units consumed to call BigNum new from a decimal string + pub bignum_from_dec_str_base_cost: u64, + /// Incremental number of units consumed to drop/dealloc BigNum (based on bytes) + pub bignum_mod_exp_base_cost: u64, + /// Number of compute units consumed by logging a `BigNum` + pub bignum_log_cost: u64, + /// Number of compute units consumed by BigNum add + pub bignum_add_cost: u64, + /// Number of compute units consumed by BigNum subtract + pub bignum_sub_cost: u64, + /// Number of compute units consumed by BigNum mutliply + pub bignum_mul_cost: u64, + /// Number of compute units consumed by BigNum divide + pub bignum_div_cost: u64, + /// Number of compute units consumed by BigNum exp + pub bignum_exp_cost: u64, + /// Number of compute units consumed by BigNum sqr + pub bignum_sqr_cost: u64, + /// Number of compute units consumed by BigNum mod_sqr + pub bignum_mod_sqr_cost: u64, + /// Number of compute units consumed by BigNum mod_mul + pub bignum_mod_mul_cost: u64, + /// Number of compute units consumed by BigNum mod_inv + pub bignum_mod_inv_cost: u64, + /// Number of compute units consumed for base BigNum data + pub bignum_word_cost: u64, + /// Divsor for number of compute units consumed for base BigNum data + pub bignum_word_cost_divisor: u64, + /// Number of compute units consumed for BigNum data from decimal string + pub bignum_from_dec_word_cost: u64, + /// Number of compute units costing the from_slice operation + pub bignum_from_bytes_word_cost: u64, } + impl Default for BpfComputeBudget { fn default() -> Self { Self::new() @@ -204,6 +239,23 @@ impl BpfComputeBudget { max_cpi_instruction_size: 1280, // IPv6 Min MTU size cpi_bytes_per_unit: 250, // ~50MB at 200,000 units sysvar_base_cost: 100, + bignum_from_u32_base_cost: 100, + bignum_from_dec_str_base_cost: 100, + bignum_mod_exp_base_cost: 100, + bignum_log_cost: 100, + bignum_add_cost: 30, + bignum_sub_cost: 30, + bignum_mul_cost: 60, + bignum_div_cost: 60, + bignum_exp_cost: 60, + bignum_sqr_cost: 30, + bignum_mod_sqr_cost: 60, + bignum_mod_mul_cost: 90, + bignum_mod_inv_cost: 90, + bignum_word_cost: 6, + bignum_word_cost_divisor: 32, + bignum_from_dec_word_cost: 1000, + bignum_from_bytes_word_cost: 4, } } } From 0483ca9e4fbdeb2667420d846935e50a8d4960b9 Mon Sep 17 00:00:00 2001 From: "Frank V. Castellucci" Date: Wed, 23 Jun 2021 06:22:53 -0400 Subject: [PATCH 2/5] Bignum syscalls --- programs/bpf/rust/bignumber/src/lib.rs | 19 ------------------- programs/bpf/tests/programs.rs | 20 -------------------- programs/bpf_loader/src/syscalls.rs | 13 +------------ 3 files changed, 1 insertion(+), 51 deletions(-) diff --git a/programs/bpf/rust/bignumber/src/lib.rs b/programs/bpf/rust/bignumber/src/lib.rs index 1bf24957bbbd00..badcafc2cf112d 100644 --- a/programs/bpf/rust/bignumber/src/lib.rs +++ b/programs/bpf/rust/bignumber/src/lib.rs @@ -28,32 +28,13 @@ fn test_constructors() { assert!(!bn_from_dec.is_negative()); let bn_from_dec = BigNumber::from_dec_str(NEG_LONG_DEC_STRING); assert!(bn_from_dec.is_negative()); -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> 2961987fa (Bignum syscalls) // Test endian encoding let be_bytes_in = u32::to_be_bytes(256); let bn_bytes_out = BigNumber::from_bytes(&be_bytes_in).to_vec(); assert_eq!(bn_bytes_out, [1, 0]); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD let be_bytes_in: Vec = vec![0, 0, 0, 0, 0, 0, 1, 0]; let bn_bytes_out = BigNumber::from_bytes(&be_bytes_in).to_vec(); assert_eq!(bn_bytes_out, [1, 0]); -======= ->>>>>>> aab413c19 (Align files with struct names) -======= - ->>>>>>> 2961987fa (Bignum syscalls) -======= ->>>>>>> 7eee92e63 (Bignum syscalls - fix format issue) -======= - let be_bytes_in: Vec = vec![0, 0, 0, 0, 0, 0, 1, 0]; - let bn_bytes_out = BigNumber::from_bytes(&be_bytes_in).to_vec(); - assert_eq!(bn_bytes_out, [1, 0]); ->>>>>>> 51b0df078 (Bignum encoding length variations) } /// BigNumber simple number and simple maths diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index c58f0dd6e3462e..e1732b5962710f 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -430,15 +430,7 @@ fn test_program_bpf_sanity() { { programs.extend_from_slice(&[ ("alloc", true), -<<<<<<< HEAD -<<<<<<< HEAD ("bignumber", true), -======= - ("bignum", true), ->>>>>>> e515f0c31 (Add C bindings and tests) -======= - ("bignumber", true), ->>>>>>> aab413c19 (Align files with struct names) ("bpf_to_bpf", true), ("float", true), ("multiple_static", true), @@ -1302,19 +1294,7 @@ fn assert_instruction_count() { programs.extend_from_slice(&[ ("solana_bpf_rust_128bit", 584), ("solana_bpf_rust_alloc", 8906), -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - ("solana_bpf_rust_bignumber", 10853), -======= - ("solana_bpf_rust_bignumber", 9967), ->>>>>>> aab413c19 (Align files with struct names) -======= - ("solana_bpf_rust_bignumber", 10384), ->>>>>>> 7ba04a7b8 (Bignum - fixed instruction count) -======= ("solana_bpf_rust_bignumber", 10853), ->>>>>>> 51b0df078 (Bignum encoding length variations) ("solana_bpf_rust_custom_heap", 539), ("solana_bpf_rust_dep_crate", 47), ("solana_bpf_rust_external_spend", 521), diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 65b09557c3e78a..2bc2ea5a2a1f1c 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -6003,20 +6003,9 @@ mod tests { let be_bytes_in = u32::to_be_bytes(256); let bn_bytes_out = BigNum::from_slice(&be_bytes_in).unwrap().to_vec(); assert_eq!(bn_bytes_out, [1, 0]); -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> 51b0df078 (Bignum encoding length variations) + let be_bytes_in: Vec = vec![0, 0, 0, 0, 0, 0, 1, 0]; let bn_bytes_out = BigNum::from_slice(&be_bytes_in).unwrap().to_vec(); assert_eq!(bn_bytes_out, [1, 0]); } -======= - } -<<<<<<< HEAD - - ->>>>>>> 2961987fa (Bignum syscalls) -======= ->>>>>>> 7a46654ca (Bignum syscalls) } From e443f574e992c8cb2a585d2f24a2e36e09e2a94c Mon Sep 17 00:00:00 2001 From: "Frank V. Castellucci" Date: Wed, 23 Jun 2021 06:45:43 -0400 Subject: [PATCH 3/5] Bignum syscalls --- programs/bpf_loader/src/syscalls.rs | 90 +---------------------------- 1 file changed, 2 insertions(+), 88 deletions(-) diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 2bc2ea5a2a1f1c..58f7be2b035f99 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -5117,15 +5117,6 @@ mod tests { ro_len, rw_va, 0, - &memory_mapping, - &mut result, - ); - assert_access_violation!(result, ro_va - 1, ro_len); - let mut result: Result> = Ok(0); - syscall.call( - ro_va, - ro_len + 1, // AccessViolation - rw_va, 0, &memory_mapping, &mut result, @@ -5453,7 +5444,7 @@ mod tests { Err(e) => Err(e), } } - // creates new bignum with u32 value + // creates new bignum from a slice of data fn new_from_slice_bignum(val: &[u8]) -> Result<(Vec, bool), EbpfError> { let mut my_buffer = Vec::::with_capacity(val.len()); let bytes_len = val.len(); @@ -5500,84 +5491,7 @@ mod tests { compute_meter, loader_id: &bpf_loader::id(), }; - let rhs_in_ffi = FfiBigNumber { - data: 2048u64, - data_len: bn2_len as u64, - is_negative: bn2_is_negative, - }; - let mod_in_ffi = FfiBigNumber { - data: 4096u64, - data_len: bn3_len as u64, - is_negative: bn3_is_negative, - }; - let mut result_vec = Vec::::with_capacity(bn1_len * bn3_len); - let mut sol_out_ffi = FfiBigNumber { - data: 5120u64, - data_len: result_vec.capacity() as u64, - is_negative: false, - }; - let memory_mapping = MemoryMapping::new::( - vec![ - MemoryRegion { - host_addr: &lhs_in_ffi as *const _ as u64, - vm_addr: 24, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }, - MemoryRegion { - host_addr: bn_arg1.as_ptr() as *const _ as u64, - vm_addr: 1024, - len: bn1_len as u64, - vm_gap_shift: 63, - is_writable: false, - }, - MemoryRegion { - host_addr: &rhs_in_ffi as *const _ as u64, - vm_addr: 48, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }, - MemoryRegion { - host_addr: bn_arg2.as_ptr() as *const _ as u64, - vm_addr: 2048, - len: bn2_len as u64, - vm_gap_shift: 63, - is_writable: false, - }, - MemoryRegion { - host_addr: &mod_in_ffi as *const _ as u64, - vm_addr: 72, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }, - MemoryRegion { - host_addr: bn_arg3.as_ptr() as *const _ as u64, - vm_addr: 4096, - len: bn3_len as u64, - vm_gap_shift: 63, - is_writable: false, - }, - MemoryRegion { - host_addr: &mut sol_out_ffi as *mut _ as u64, - vm_addr: 96, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }, - MemoryRegion { - host_addr: result_vec.as_mut_ptr() as *mut _ as u64, - vm_addr: 5120, - len: result_vec.capacity() as u64, - vm_gap_shift: 63, - is_writable: true, - }, - ], - &DEFAULT_CONFIG, - ) - .unwrap(); + let mut result: Result> = Ok(0); syscall.call( 0, From 161955f7459d70ac72693774c2342972928c2e58 Mon Sep 17 00:00:00 2001 From: "Frank V. Castellucci" Date: Wed, 23 Jun 2021 06:52:53 -0400 Subject: [PATCH 4/5] Bignum syscalls --- programs/bpf_loader/src/syscalls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 58f7be2b035f99..1b9c77cb4254a9 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -2629,7 +2629,7 @@ fn bignum_to_ffibignumber( } else if big_number_len == bnffi.data_len { (*bn_buffer_out).copy_from_slice(&big_number_bytes); } else { - bn_buffer_out[..big_number_bytes.len()].copy_from_slice(&&big_number_bytes); + bn_buffer_out[..big_number_bytes.len()].copy_from_slice(&big_number_bytes); (*bnffi).data_len = big_number_len; } *result = Ok(SUCCESS) From c731ff2d629f46c50af9f94e7f7431e9692dc343 Mon Sep 17 00:00:00 2001 From: "Frank V. Castellucci" Date: Wed, 23 Jun 2021 08:16:27 -0400 Subject: [PATCH 5/5] Bignum syscalls --- programs/bpf/tests/programs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index e1732b5962710f..06e0f0f16f91c9 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -1293,11 +1293,11 @@ fn assert_instruction_count() { { programs.extend_from_slice(&[ ("solana_bpf_rust_128bit", 584), - ("solana_bpf_rust_alloc", 8906), + ("solana_bpf_rust_alloc", 7082), ("solana_bpf_rust_bignumber", 10853), - ("solana_bpf_rust_custom_heap", 539), + ("solana_bpf_rust_custom_heap", 522), ("solana_bpf_rust_dep_crate", 47), - ("solana_bpf_rust_external_spend", 521), + ("solana_bpf_rust_external_spend", 504), ("solana_bpf_rust_iter", 724), ("solana_bpf_rust_many_args", 233), ("solana_bpf_rust_mem", 3119), @@ -1306,7 +1306,7 @@ fn assert_instruction_count() { ("solana_bpf_rust_param_passing", 46), ("solana_bpf_rust_rand", 481), ("solana_bpf_rust_sanity", 873), - ("solana_bpf_rust_sha", 32295), + ("solana_bpf_rust_sha", 32301), ]); }