From bb0665ba19cec5e8aefc716285e5232cf2cb233e Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 2 Apr 2020 17:48:22 -0600 Subject: [PATCH 01/71] Initial commit --- .gitignore | 2 + Cargo.lock | 3299 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 25 + README.md | 73 + src/arg_parser.rs | 128 ++ src/args.rs | 65 + src/main.rs | 150 +++ 7 files changed, 3742 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/arg_parser.rs create mode 100644 src/args.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000000..e3c0d4bb353841 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +*.csv diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000000000..0e70f7d840abb5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3299 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "ar" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579681b3fecd1e9d6b5ce6969e05f9feb913f296eddaf595be1166a5ca597bc4" +dependencies = [ + "byteorder", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" + +[[package]] +name = "ascii" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" + +[[package]] +name = "assert_matches" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "backtrace" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" +dependencies = [ + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", + "serde", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "base32" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + +[[package]] +name = "bincode" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +dependencies = [ + "byteorder", + "serde", +] + +[[package]] +name = "bit-vec" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" + +[[package]] +name = "bit-vec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2b_simd" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" +dependencies = [ + "arrayref", + "byte-tools 0.2.0", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools 0.3.1", + "byteorder", + "generic-array 0.12.3", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools 0.3.1", +] + +[[package]] +name = "bloom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00ac8e5056d6d65376a3c1aa5c7c34850d6949ace17f0266953a254eb3d6fe8" +dependencies = [ + "bit-vec 0.4.4", +] + +[[package]] +name = "bs58" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" + +[[package]] +name = "bstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "either", + "iovec", +] + +[[package]] +name = "bytes" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" + +[[package]] +name = "cc" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e" +dependencies = [ + "jobserver", + "num_cpus", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "chrono" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +dependencies = [ + "num-integer", + "num-traits 0.2.11", + "serde", + "time", +] + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" +dependencies = [ + "cc", +] + +[[package]] +name = "clicolors-control" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" +dependencies = [ + "atty", + "lazy_static", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi 0.3.8", +] + +[[package]] +name = "combine" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1645a65a99c7c8d345761f4b75a6ffe5be3b3b27a93ee731fccc5050ba6be97c" +dependencies = [ + "ascii", + "byteorder", +] + +[[package]] +name = "console" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6728a28023f207181b193262711102bfbaf47cc9d13bc71d0736607ef8efe88c" +dependencies = [ + "clicolors-control", + "encode_unicode", + "lazy_static", + "libc", + "regex", + "termios", + "unicode-width", + "winapi 0.3.8", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg 1.0.0", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg 1.0.0", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array 0.12.3", + "subtle 1.0.0", +] + +[[package]] +name = "csv" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" +dependencies = [ + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "ct-logs" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" +dependencies = [ + "sct", +] + +[[package]] +name = "curve25519-dalek" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" +dependencies = [ + "byteorder", + "clear_on_drop", + "digest 0.8.1", + "rand_core 0.3.1", + "subtle 2.2.2", +] + +[[package]] +name = "dialoguer" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94616e25d2c04fc97253d145f6ca33ad84a584258dc70c4e621cc79a57f903b6" +dependencies = [ + "console", + "lazy_static", + "tempfile", +] + +[[package]] +name = "digest" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" +dependencies = [ + "generic-array 0.9.0", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.3", +] + +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if", + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +dependencies = [ + "cfg-if", + "libc", + "redox_users", + "winapi 0.3.8", +] + +[[package]] +name = "dtoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" + +[[package]] +name = "ed25519-dalek" +version = "1.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" +dependencies = [ + "clear_on_drop", + "curve25519-dalek", + "failure", + "rand 0.6.5", + "serde", + "sha2 0.8.1", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + +[[package]] +name = "elfkit" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f182eda16a7360c80a2f8638d0726e9d5478173058f1505c42536ca666ecd2" +dependencies = [ + "ar", + "bit-vec 0.5.1", + "bitflags", + "bloom", + "byteorder", + "clap", + "colored", + "enum-primitive-derive", + "env_logger 0.5.13", + "fnv", + "glob", + "indexmap", + "itertools 0.7.11", + "log", + "num-traits 0.2.11", + "pretty_env_logger", + "rayon", + "sha2 0.7.1", + "tempfile", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-primitive-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd" +dependencies = [ + "num-traits 0.1.43", + "quote 0.3.15", + "syn 0.11.11", +] + +[[package]] +name = "env_logger" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "failure" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "synstructure", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "fs_extra" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" + +[[package]] +name = "futures-channel" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" + +[[package]] +name = "futures-io" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" + +[[package]] +name = "futures-macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +dependencies = [ + "proc-macro-hack", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "futures-sink" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-task", + "memchr", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +dependencies = [ + "serde", + "typenum", +] + +[[package]] +name = "gethostname" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" +dependencies = [ + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" + +[[package]] +name = "h2" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42" +dependencies = [ + "bytes 0.5.4", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "log", + "slab", + "tokio 0.2.15", + "tokio-util", +] + +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hermit-abi" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" + +[[package]] +name = "hidapi" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e347988010cd7d98689c553ab3d32f53e62cabb0d876aed16d41a8f9c1760e54" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +dependencies = [ + "crypto-mac", + "digest 0.8.1", +] + +[[package]] +name = "http" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +dependencies = [ + "bytes 0.5.4", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +dependencies = [ + "bytes 0.5.4", + "http", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6081100e960d9d74734659ffc9cc91daf1c0fc7aceb8eaa94ee1a3f5046f2e" +dependencies = [ + "bytes 0.5.4", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "log", + "net2", + "pin-project", + "time", + "tokio 0.2.15", + "tower-service", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac965ea399ec3a25ac7d13b8affd4b8f39325cca00858ddf5eb29b79e6b14b08" +dependencies = [ + "bytes 0.5.4", + "ct-logs", + "futures-util", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio 0.2.15", + "tokio-rustls", + "webpki", +] + +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "indicatif" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a68371cf417889c9d7f98235b7102ea7c54fc59bcbd22f3dea785be9d27e40" +dependencies = [ + "console", + "lazy_static", + "number_prefix", + "regex", +] + +[[package]] +name = "input_buffer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" +dependencies = [ + "bytes 0.5.4", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + +[[package]] +name = "jemalloc-ctl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7" +dependencies = [ + "jemalloc-sys", + "libc", + "paste", +] + +[[package]] +name = "jemalloc-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" +dependencies = [ + "cc", + "fs_extra", + "libc", +] + +[[package]] +name = "jemallocator" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69" +dependencies = [ + "jemalloc-sys", + "libc", +] + +[[package]] +name = "jobserver" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-core" +version = "14.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" +dependencies = [ + "futures", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" + +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi 0.3.8", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" + +[[package]] +name = "lock_api" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +dependencies = [ + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "memoffset" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "mio" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +dependencies = [ + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +dependencies = [ + "iovec", + "libc", + "mio", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "native-tls" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +dependencies = [ + "cfg-if", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "nix" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "void", +] + +[[package]] +name = "num-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +dependencies = [ + "autocfg 1.0.0", + "num-traits 0.2.11", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.11", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "num_cpus" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "number_prefix" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" + +[[package]] +name = "once_cell" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" +dependencies = [ + "parking_lot 0.9.0", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "openssl" +version = "0.10.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" +dependencies = [ + "autocfg 1.0.0", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api", + "parking_lot_core 0.6.2", + "rustc_version", +] + +[[package]] +name = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +dependencies = [ + "lock_api", + "parking_lot_core 0.7.0", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +dependencies = [ + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version", + "smallvec 0.6.13", + "winapi 0.3.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +dependencies = [ + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "smallvec 1.2.0", + "winapi 0.3.8", +] + +[[package]] +name = "paste" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4fb1930692d1b6a9cfabdde3d06ea0a7d186518e2f4d67660d8970e2fa647a" +dependencies = [ + "paste-impl", + "proc-macro-hack", +] + +[[package]] +name = "paste-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a" +dependencies = [ + "proc-macro-hack", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" +dependencies = [ + "byteorder", + "crypto-mac", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + +[[package]] +name = "pretty_env_logger" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed8d1e63042e889b85228620629b51c011d380eed2c7e0015f8a644def280c28" +dependencies = [ + "ansi_term", + "chrono", + "env_logger 0.5.13", + "log", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" + +[[package]] +name = "proc-macro-nested" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +dependencies = [ + "unicode-xid 0.2.0", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +dependencies = [ + "proc-macro2 1.0.10", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.8", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi 0.3.8", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.8", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +dependencies = [ + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "redox_users" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +dependencies = [ + "getrandom", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "regex" +version = "1.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-automata" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +dependencies = [ + "byteorder", +] + +[[package]] +name = "regex-syntax" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" + +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "reqwest" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2" +dependencies = [ + "base64", + "bytes 0.5.4", + "encoding_rs", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "hyper-rustls", + "js-sys", + "lazy_static", + "log", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "rustls", + "serde", + "serde_json", + "serde_urlencoded", + "time", + "tokio 0.2.15", + "tokio-rustls", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" +dependencies = [ + "cc", + "lazy_static", + "libc", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.8", +] + +[[package]] +name = "rpassword" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" +dependencies = [ + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "rust-argon2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" +dependencies = [ + "base64", + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" +dependencies = [ + "openssl-probe", + "rustls", + "schannel", + "security-framework", +] + +[[package]] +name = "ryu" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" + +[[package]] +name = "schannel" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" +dependencies = [ + "lazy_static", + "winapi 0.3.8", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325a073952621257820e7a3469f55ba4726d8b28657e7e36653d1c36dc2c84ae" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "serde_json" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +dependencies = [ + "dtoa", + "itoa", + "serde", + "url", +] + +[[package]] +name = "serde_yaml" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" +dependencies = [ + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", +] + +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" +dependencies = [ + "block-buffer 0.3.3", + "byte-tools 0.2.0", + "digest 0.7.6", + "fake-simd", +] + +[[package]] +name = "sha2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "smallvec" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +dependencies = [ + "maybe-uninit", +] + +[[package]] +name = "smallvec" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" + +[[package]] +name = "socket2" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + +[[package]] +name = "solana-batch" +version = "0.1.0" +dependencies = [ + "clap", + "console", + "csv", + "itertools 0.9.0", + "serde", + "solana-clap-utils", + "solana-cli-config", + "solana-client", + "solana-remote-wallet", + "solana-runtime", + "solana-sdk", + "solana-stake-program", +] + +[[package]] +name = "solana-bpf-loader-program" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6dd534159b364724083ccb459e9d9e37ac63de3f3416d0fd1937809b88d1512" +dependencies = [ + "bincode", + "byteorder", + "libc", + "log", + "num-derive", + "num-traits 0.2.11", + "solana-logger", + "solana-sdk", + "solana_rbpf", + "thiserror", +] + +[[package]] +name = "solana-clap-utils" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cb4120cd8084b703872ae5bdce5b5592f538f9014692e8ae7a4f16ae0f282bc" +dependencies = [ + "chrono", + "clap", + "rpassword", + "solana-remote-wallet", + "solana-sdk", + "thiserror", + "tiny-bip39", + "url", +] + +[[package]] +name = "solana-cli-config" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fd8e6743c01cfd08a4e522a2954e6fcb0ce5970f9fb028adb0413456196d16" +dependencies = [ + "dirs", + "lazy_static", + "serde", + "serde_derive", + "serde_yaml", + "url", +] + +[[package]] +name = "solana-client" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed191106676114e575d93a707c2541c1a3d7fc9b15e4c083b2ee924d50b6574" +dependencies = [ + "bincode", + "bs58", + "indicatif", + "jsonrpc-core", + "log", + "rayon", + "reqwest", + "serde", + "serde_derive", + "serde_json", + "solana-net-utils", + "solana-sdk", + "solana-transaction-status", + "solana-vote-program", + "thiserror", + "tungstenite", + "url", +] + +[[package]] +name = "solana-config-program" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c74e39c5a6bb7734c3a40511de1cd15a7581a514edf1aa570aee0f979a9e17" +dependencies = [ + "bincode", + "chrono", + "log", + "serde", + "serde_derive", + "solana-logger", + "solana-sdk", +] + +[[package]] +name = "solana-crate-features" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb33bafc25208fd7197d43e1c154440345c9f8dcf59ccb153e1c760c8b9ed35" +dependencies = [ + "backtrace", + "bytes 0.4.12", + "cc", + "curve25519-dalek", + "ed25519-dalek", + "either", + "failure", + "lazy_static", + "libc", + "rand_chacha 0.1.1", + "regex-syntax", + "reqwest", + "serde", + "syn 0.15.44", + "syn 1.0.17", + "tokio 0.1.22", + "winapi 0.3.8", +] + +[[package]] +name = "solana-logger" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be2f7313c5c9036d5c48a614cb7eba3a50a2e932c35103d2b2b5b5476cad2d2e" +dependencies = [ + "env_logger 0.7.1", + "lazy_static", + "log", +] + +[[package]] +name = "solana-measure" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f99c4a275b50e89f08d4d7132e4ff03b182f32437ecbf6ac6f286d922ebf1b6" +dependencies = [ + "jemalloc-ctl", + "jemallocator", + "log", + "solana-metrics", + "solana-sdk", +] + +[[package]] +name = "solana-metrics" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016dc8173ee03bb0935d170d1a42b26ad732d628a8b07c3e36a1afb9b827f4de" +dependencies = [ + "env_logger 0.7.1", + "gethostname", + "lazy_static", + "log", + "reqwest", + "solana-sdk", +] + +[[package]] +name = "solana-net-utils" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f47502bdebea17f685d1cbcb7bc744c08cada5482cd322c518d61c4c1f7fc2" +dependencies = [ + "bincode", + "bytes 0.4.12", + "clap", + "log", + "nix", + "rand 0.6.5", + "serde", + "serde_derive", + "socket2", + "solana-clap-utils", + "solana-logger", + "tokio 0.1.22", + "tokio-codec", +] + +[[package]] +name = "solana-rayon-threadlimit" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98abf277ba48d1dd8584c389eb4566b322d028acfc7611b30c5389660ec2abb2" +dependencies = [ + "lazy_static", + "num_cpus", +] + +[[package]] +name = "solana-remote-wallet" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d86eab604d37ee7cafa384295c55e20b3c3fc033fe438befd725a6f3ac24bcd" +dependencies = [ + "base32", + "console", + "dialoguer", + "hidapi", + "log", + "parking_lot 0.10.0", + "semver", + "solana-sdk", + "thiserror", + "url", +] + +[[package]] +name = "solana-runtime" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930a08e8a3097cd060d88003ef99ebad0ae12448a05854570f0f4ceb7c9edd3e" +dependencies = [ + "bincode", + "bv", + "byteorder", + "fnv", + "fs_extra", + "itertools 0.9.0", + "lazy_static", + "libc", + "libloading", + "log", + "memmap", + "num-derive", + "num-traits 0.2.11", + "num_cpus", + "rand 0.6.5", + "rayon", + "serde", + "serde_derive", + "solana-bpf-loader-program", + "solana-logger", + "solana-measure", + "solana-metrics", + "solana-rayon-threadlimit", + "solana-sdk", + "solana-stake-program", + "solana-storage-program", + "solana-vote-program", + "tempfile", + "thiserror", +] + +[[package]] +name = "solana-sdk" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bc7e1e5dda1999fb5894dd9843230fbea77c5748629601c3da29788b6ec071e" +dependencies = [ + "assert_matches", + "bincode", + "bs58", + "bv", + "byteorder", + "chrono", + "ed25519-dalek", + "generic-array 0.13.2", + "hex", + "hmac", + "itertools 0.9.0", + "log", + "memmap", + "num-derive", + "num-traits 0.2.11", + "pbkdf2", + "rand 0.6.5", + "rand_chacha 0.1.1", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.8.1", + "solana-crate-features", + "solana-logger", + "solana-sdk-macro", + "thiserror", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3124b8792d090e99e52e7aa93b25508a5ca2253b3bf2883bd5fef90f395703" +dependencies = [ + "bs58", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "solana-stake-program" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a0afdb46eeacff16098bf11d387d355f11865b9b4300a611775c27b80892f93" +dependencies = [ + "bincode", + "log", + "num-derive", + "num-traits 0.2.11", + "serde", + "serde_derive", + "solana-config-program", + "solana-logger", + "solana-metrics", + "solana-sdk", + "solana-vote-program", + "thiserror", +] + +[[package]] +name = "solana-storage-program" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5422676420bfb243ddb9ce4222ba6609916c9aa5f894c3b407f306d0db310e4e" +dependencies = [ + "bincode", + "log", + "num-derive", + "num-traits 0.2.11", + "rand 0.6.5", + "serde", + "serde_derive", + "solana-logger", + "solana-sdk", +] + +[[package]] +name = "solana-transaction-status" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54f5b8a327ac80c2d020d8396668f8d70602f8dc82a79bd7725ff70fa3811e6" +dependencies = [ + "bincode", + "bs58", + "serde", + "serde_derive", + "solana-sdk", +] + +[[package]] +name = "solana-vote-program" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bdc7e906ced7eb6c0d769081e313ab7adb485b2de77602475aebba38859a5b" +dependencies = [ + "bincode", + "log", + "num-derive", + "num-traits 0.2.11", + "serde", + "serde_derive", + "solana-logger", + "solana-metrics", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana_rbpf" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87d4395203039cac872c125dea2534e6b98ae85e28e3f800872a7571ffa87df8" +dependencies = [ + "byteorder", + "combine", + "elfkit", + "hash32", + "libc", + "log", + "num-traits 0.2.11", + "thiserror", + "time", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" + +[[package]] +name = "subtle" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "unicode-xid 0.2.0", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", +] + +[[package]] +name = "synstructure" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "unicode-xid 0.2.0", +] + +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +dependencies = [ + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.8", +] + +[[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termios" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" +dependencies = [ + "libc", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +dependencies = [ + "libc", + "redox_syscall", + "winapi 0.3.8", +] + +[[package]] +name = "tiny-bip39" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" +dependencies = [ + "failure", + "hmac", + "once_cell", + "pbkdf2", + "rand 0.7.3", + "rustc-hash", + "sha2 0.8.1", + "unicode-normalization", +] + +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +dependencies = [ + "bytes 0.4.12", + "futures", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", +] + +[[package]] +name = "tokio" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619cdb2245c40c42d563089b72e80c5df659513d667a017598439ef7a7b1ffe1" +dependencies = [ + "bytes 0.5.4", + "fnv", + "futures-core", + "iovec", + "lazy_static", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "slab", +] + +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes 0.4.12", + "futures", + "tokio-io", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures", + "tokio-executor", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils", + "futures", +] + +[[package]] +name = "tokio-fs" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +dependencies = [ + "futures", + "tokio-io", + "tokio-threadpool", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes 0.4.12", + "futures", + "log", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils", + "futures", + "lazy_static", + "log", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-rustls" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" +dependencies = [ + "futures-core", + "rustls", + "tokio 0.2.15", + "webpki", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes 0.4.12", + "futures", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "futures", + "lazy_static", + "log", + "num_cpus", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils", + "futures", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +dependencies = [ + "bytes 0.4.12", + "futures", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-uds" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" +dependencies = [ + "bytes 0.4.12", + "futures", + "iovec", + "libc", + "log", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +dependencies = [ + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio 0.2.15", +] + +[[package]] +name = "tower-service" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" + +[[package]] +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" + +[[package]] +name = "tungstenite" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" +dependencies = [ + "base64", + "byteorder", + "bytes 0.5.4", + "http", + "httparse", + "input_buffer", + "log", + "native-tls", + "rand 0.7.3", + "sha-1", + "url", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +dependencies = [ + "smallvec 1.2.0", +] + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "untrusted" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" + +[[package]] +name = "url" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + +[[package]] +name = "vcpkg" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" + +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasm-bindgen" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +dependencies = [ + "cfg-if", + "serde", + "serde_json", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +dependencies = [ + "quote 1.0.3", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" + +[[package]] +name = "web-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" +dependencies = [ + "webpki", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000000000..d0ebe2e80ff2b6 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "solana-batch" +description = "Blockchain, Rebuilt for Scale" +authors = ["Solana Maintainers "] +edition = "2018" +version = "0.1.0" +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" + +[dependencies] +csv = "1.1.3" +clap = "2.33.0" +console = "0.10.0" +itertools = "0.9.0" +serde = { version = "1.0", features = ["derive"] } +solana-clap-utils = "1.1.0" +solana-cli-config = "1.1.0" +solana-client = "1.1.0" +solana-remote-wallet = "1.1.0" +solana-sdk = "1.1.0" +solana-stake-program = "1.1.0" + +[dev-dependencies] +solana-runtime = "1.1.0" diff --git a/README.md b/README.md new file mode 100644 index 00000000000000..b5e0851f82b7be --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +# Reconcile total payments with current payments + +A user may want to make payments to multiple accounts over multiple iterations. +The user will have a spreadsheet listing public keys and expected balances, and +some process for transferring tokens to them, and ensuring that no more than the +expected amount of tokens are sent. The command-line tool here automates that +process. + +## Scrup input + +Clean, group, filter as needed. + +```bash +solana-batch scrub +``` + +Example output: + +```text +recipient,amount +blahblahblah,100 +yayayayayada,42 +nadanadanada,43 +``` + +## Reconcile + +List the differences between a list of expected payments and the record of what +payments have already been made. + +```bash +solana-batch transfer --dryrun +``` + +Example output: + +```text +Recipient Address Amount +blahblahblah 70 +yayayayayada 42 +nadanadanada 43 +``` + + +```bash +solana-batch transfer --from --fee-payer +``` + +Example output: + +```text +Recipient Address Amount Signature +blahblahblah 70 blah +yayayayayada 42 yada +nadanadanada 43 nada +``` + +Example state before: + +```text +recipient,amount,signature +blahblahblah,30,blah,orig +``` + +Example state after: + +```text +recipient,amount,signature +blahblahblah,30,orig +blahblahblah,70,blah +yayayayayada,42,yada +nadanadanada,43,nada +``` diff --git a/src/arg_parser.rs b/src/arg_parser.rs new file mode 100644 index 00000000000000..d05a7888805d90 --- /dev/null +++ b/src/arg_parser.rs @@ -0,0 +1,128 @@ +use crate::args::{Args, Command, ScrubArgs, TransferArgs}; +use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand}; +//use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; +use solana_cli_config::CONFIG_FILE; +use std::ffi::OsString; +use std::process::exit; + +//fn fee_payer_arg<'a, 'b>() -> Arg<'a, 'b> { +// Arg::with_name("fee_payer") +// .long("fee-payer") +// .required(true) +// .takes_value(true) +// .value_name("KEYPAIR") +// .validator(is_valid_signer) +// .help("Fee payer") +//} +// +//fn funding_keypair_arg<'a, 'b>() -> Arg<'a, 'b> { +// Arg::with_name("funding_keypair") +// .required(true) +// .takes_value(true) +// .value_name("FUNDING_KEYPAIR") +// .validator(is_valid_signer) +// .help("Keypair to fund accounts") +//} + +pub(crate) fn get_matches<'a, I, T>(args: I) -> ArgMatches<'a> +where + I: IntoIterator, + T: Into + Clone, +{ + let default_config_file = CONFIG_FILE.as_ref().unwrap(); + App::new("solana-stake-accounts") + .about("about") + .version("version") + .arg( + Arg::with_name("config_file") + .long("config") + .takes_value(true) + .value_name("FILEPATH") + .default_value(default_config_file) + .help("Config file"), + ) + .arg( + Arg::with_name("url") + .long("url") + .global(true) + .takes_value(true) + .value_name("URL") + .help("RPC entrypoint address. i.e. http://devnet.solana.com"), + ) + .subcommand( + SubCommand::with_name("scrub") + .about("Scrub a data file") + .arg( + Arg::with_name("input_csv") + .required(true) + .index(1) + .takes_value(true) + .value_name("FILE") + .help("Input CSV file"), + ), + ) + .subcommand( + SubCommand::with_name("transfer") + .about("Scrub a data file") + .arg( + Arg::with_name("input_csv") + .required(true) + .index(1) + .takes_value(true) + .value_name("FILE") + .help("Scrubbed CSV file"), + ) + .arg( + Arg::with_name("state_csv") + .required(true) + .index(2) + .takes_value(true) + .value_name("FILE") + .help("State CSV file"), + ) + .arg( + Arg::with_name("dry_run") + .long("dry-run") + .help("Do not execute any transfers"), + ), + ) + .get_matches_from(args) +} + +fn parse_scrub_args(matches: &ArgMatches<'_>) -> ScrubArgs { + ScrubArgs { + input_csv: value_t_or_exit!(matches, "input_csv", String), + } +} + +fn parse_transfer_args(matches: &ArgMatches<'_>) -> TransferArgs { + TransferArgs { + input_csv: value_t_or_exit!(matches, "input_csv", String), + state_csv: value_t_or_exit!(matches, "state_csv", String), + dry_run: matches.is_present("dry_run"), + } +} + +pub(crate) fn parse_args(args: I) -> Args +where + I: IntoIterator, + T: Into + Clone, +{ + let matches = get_matches(args); + let config_file = matches.value_of("config_file").unwrap().to_string(); + let url = matches.value_of("url").map(|x| x.to_string()); + + let command = match matches.subcommand() { + ("scrub", Some(matches)) => Command::Scrub(parse_scrub_args(matches)), + ("transfer", Some(matches)) => Command::Transfer(parse_transfer_args(matches)), + _ => { + eprintln!("{}", matches.usage()); + exit(1); + } + }; + Args { + config_file, + url, + command, + } +} diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 00000000000000..4be2d6d59e1a9d --- /dev/null +++ b/src/args.rs @@ -0,0 +1,65 @@ +//use clap::ArgMatches; +//use solana_clap_utils::keypair::{pubkey_from_path, signer_from_path}; +//use solana_remote_wallet::remote_wallet::{maybe_wallet_manager, RemoteWalletManager}; +//use solana_sdk::{pubkey::Pubkey, signature::Signer}; +use std::error::Error; +//use std::sync::Arc; + +pub(crate) struct ScrubArgs { + pub input_csv: String, +} + +pub(crate) struct TransferArgs { + pub input_csv: String, + pub state_csv: String, + pub dry_run: bool, +} + +pub(crate) enum Command { + Scrub(ScrubArgs), + Transfer(TransferArgs), +} + +pub(crate) struct Args { + pub config_file: String, + pub url: Option, + pub command: Command, +} + +//fn resolve_fee_payer( +// wallet_manager: Option<&Arc>, +// key_url: &str, +//) -> Result, Box> { +// let matches = ArgMatches::default(); +// signer_from_path(&matches, key_url, "fee-payer", wallet_manager) +//} +// +//fn resolve_base_pubkey( +// wallet_manager: Option<&Arc>, +// key_url: &str, +//) -> Result> { +// let matches = ArgMatches::default(); +// pubkey_from_path(&matches, key_url, "base pubkey", wallet_manager) +//} + +pub(crate) fn resolve_command(command: &Command) -> Result> { + //let wallet_manager = maybe_wallet_manager()?; + //let wallet_manager = wallet_manager.as_ref(); + //let matches = ArgMatches::default(); + match command { + Command::Scrub(args) => { + let resolved_args = ScrubArgs { + input_csv: args.input_csv.clone(), + }; + Ok(Command::Scrub(resolved_args)) + } + Command::Transfer(args) => { + let resolved_args = TransferArgs { + input_csv: args.input_csv.clone(), + state_csv: args.state_csv.clone(), + dry_run: args.dry_run.clone(), + }; + Ok(Command::Transfer(resolved_args)) + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000000000..75342f11319aa0 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,150 @@ +mod arg_parser; +mod args; + +use crate::arg_parser::parse_args; +use crate::args::{resolve_command, Command, ScrubArgs, TransferArgs}; +use console::style; +use csv::{ReaderBuilder, Trim}; +use itertools::Itertools; +use serde::{Deserialize, Serialize}; +use std::fs; +use std::io; +use std::path::Path; +//use solana_cli_config::Config; +//use solana_client::client_error::ClientError; +//use solana_client::rpc_client::RpcClient; +//use solana_sdk::{ +// message::Message, pubkey::Pubkey, signature::Signature, signers::Signers, +// transaction::Transaction, +//}; +use solana_sdk::signature::Signature; +use std::env; +use std::error::Error; + +#[derive(Deserialize, Debug)] +struct Purchase { + bid_amount_dollars: f64, + primary_address: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct Transfer { + recipient: String, + amount: f64, + signature: Option, +} + +const CLEARING_PRICE: f64 = 0.22; + +fn scrub(purchases: &[Purchase]) -> Vec { + purchases + .iter() + .group_by(|x| &x.primary_address) + .into_iter() + .map(|(pubkey, xs)| { + let dollars: f64 = xs.map(|x| x.bid_amount_dollars).sum(); + Transfer { + recipient: pubkey.clone(), + amount: dollars / CLEARING_PRICE, + signature: None, + } + }) + .collect() +} + +fn process_scrub(args: &ScrubArgs) -> Result<(), csv::Error> { + let mut rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.input_csv)?; + let purchases: Vec = rdr.deserialize().map(|x| x.unwrap()).collect(); + + let mut wtr = csv::Writer::from_writer(io::stdout()); + for transfer in scrub(&purchases) { + wtr.serialize(transfer)?; + } + wtr.flush()?; + Ok(()) +} + +fn find_new_transfers(transfers: &[Transfer], state: &[Transfer]) -> Vec { + let mut needed = vec![]; + for transfer in transfers { + if let Some(prev_transfer) = state.iter().find(|x| x.recipient == transfer.recipient) { + if transfer.amount > prev_transfer.amount { + needed.push(Transfer { + recipient: transfer.recipient.clone(), + amount: transfer.amount - prev_transfer.amount, + signature: None, + }); + } + } else { + needed.push(transfer.clone()); + } + } + needed +} + +fn process_transfer(args: &TransferArgs) -> Result<(), csv::Error> { + let mut rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.input_csv)?; + let transfers: Vec = rdr.deserialize().map(|x| x.unwrap()).collect(); + + let state: Vec = if Path::new(&args.state_csv).exists() { + let mut state_rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.state_csv)?; + state_rdr.deserialize().map(|x| x.unwrap()).collect() + } else { + vec![] + }; + + let needed = find_new_transfers(&transfers, &state); + + println!( + "{}", + style(format!("{:<44} {}", "Recipient", "Amount")).bold() + ); + for transfer in &needed { + println!("{:<44} {}", transfer.recipient, transfer.amount); + } + + if !args.dry_run && !needed.is_empty() { + let state_bak = format!("{}.bak", &args.state_csv); + fs::rename(&args.state_csv, state_bak)?; + let mut wtr = csv::Writer::from_path(&args.state_csv)?; + for transfer in &transfers { + wtr.serialize(transfer)?; + } + wtr.flush()?; + } + + Ok(()) +} + +//fn send_message( +// client: &RpcClient, +// message: Message, +// signers: &S, +//) -> Result { +// let mut transaction = Transaction::new_unsigned(message); +// client.resign_transaction(&mut transaction, signers)?; +// client.send_and_confirm_transaction_with_spinner(&mut transaction, signers) +//} + +fn main() -> Result<(), Box> { + let command_args = parse_args(env::args_os()); + //let config = Config::load(&command_args.config_file)?; + //let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); + //let client = RpcClient::new(json_rpc_url); + + match resolve_command(&command_args.command)? { + Command::Scrub(args) => { + process_scrub(&args)?; + } + Command::Transfer(args) => { + process_transfer(&args)?; + } + } + Ok(()) +} From c8b5e17e337945f11909c31ea1554402ba89fdfb Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 2 Apr 2020 18:24:38 -0600 Subject: [PATCH 02/71] Execute transfers --- src/arg_parser.rs | 47 +++++++++++++++-------------- src/args.rs | 53 ++++++++++++++------------------ src/main.rs | 77 ++++++++++++++++++++++++++++++++--------------- 3 files changed, 100 insertions(+), 77 deletions(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index d05a7888805d90..d62c762a1175f6 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,29 +1,10 @@ use crate::args::{Args, Command, ScrubArgs, TransferArgs}; -use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand}; -//use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; +use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; +use solana_clap_utils::input_validators::is_valid_signer; use solana_cli_config::CONFIG_FILE; use std::ffi::OsString; use std::process::exit; -//fn fee_payer_arg<'a, 'b>() -> Arg<'a, 'b> { -// Arg::with_name("fee_payer") -// .long("fee-payer") -// .required(true) -// .takes_value(true) -// .value_name("KEYPAIR") -// .validator(is_valid_signer) -// .help("Fee payer") -//} -// -//fn funding_keypair_arg<'a, 'b>() -> Arg<'a, 'b> { -// Arg::with_name("funding_keypair") -// .required(true) -// .takes_value(true) -// .value_name("FUNDING_KEYPAIR") -// .validator(is_valid_signer) -// .help("Keypair to fund accounts") -//} - pub(crate) fn get_matches<'a, I, T>(args: I) -> ArgMatches<'a> where I: IntoIterator, @@ -84,6 +65,24 @@ where Arg::with_name("dry_run") .long("dry-run") .help("Do not execute any transfers"), + ) + .arg( + Arg::with_name("sender_keypair") + .long("from") + .required(true) + .takes_value(true) + .value_name("SENDING_KEYPAIR") + .validator(is_valid_signer) + .help("Keypair to fund accounts"), + ) + .arg( + Arg::with_name("fee_payer") + .long("fee-payer") + .required(true) + .takes_value(true) + .value_name("KEYPAIR") + .validator(is_valid_signer) + .help("Fee payer"), ), ) .get_matches_from(args) @@ -95,15 +94,17 @@ fn parse_scrub_args(matches: &ArgMatches<'_>) -> ScrubArgs { } } -fn parse_transfer_args(matches: &ArgMatches<'_>) -> TransferArgs { +fn parse_transfer_args(matches: &ArgMatches<'_>) -> TransferArgs { TransferArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), state_csv: value_t_or_exit!(matches, "state_csv", String), dry_run: matches.is_present("dry_run"), + sender_keypair: value_t!(matches, "sender_keypair", String).ok(), + fee_payer: value_t!(matches, "fee_payer", String).ok(), } } -pub(crate) fn parse_args(args: I) -> Args +pub(crate) fn parse_args(args: I) -> Args where I: IntoIterator, T: Into + Clone, diff --git a/src/args.rs b/src/args.rs index 4be2d6d59e1a9d..81b808b5b0e417 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,51 +1,35 @@ -//use clap::ArgMatches; -//use solana_clap_utils::keypair::{pubkey_from_path, signer_from_path}; -//use solana_remote_wallet::remote_wallet::{maybe_wallet_manager, RemoteWalletManager}; -//use solana_sdk::{pubkey::Pubkey, signature::Signer}; +use clap::ArgMatches; +use solana_clap_utils::keypair::signer_from_path; +use solana_remote_wallet::remote_wallet::maybe_wallet_manager; +use solana_sdk::signature::Signer; use std::error::Error; -//use std::sync::Arc; pub(crate) struct ScrubArgs { pub input_csv: String, } -pub(crate) struct TransferArgs { +pub(crate) struct TransferArgs { pub input_csv: String, pub state_csv: String, pub dry_run: bool, + pub sender_keypair: Option, + pub fee_payer: Option, } -pub(crate) enum Command { +pub(crate) enum Command { Scrub(ScrubArgs), - Transfer(TransferArgs), + Transfer(TransferArgs), } -pub(crate) struct Args { +pub(crate) struct Args { pub config_file: String, pub url: Option, - pub command: Command, + pub command: Command, } -//fn resolve_fee_payer( -// wallet_manager: Option<&Arc>, -// key_url: &str, -//) -> Result, Box> { -// let matches = ArgMatches::default(); -// signer_from_path(&matches, key_url, "fee-payer", wallet_manager) -//} -// -//fn resolve_base_pubkey( -// wallet_manager: Option<&Arc>, -// key_url: &str, -//) -> Result> { -// let matches = ArgMatches::default(); -// pubkey_from_path(&matches, key_url, "base pubkey", wallet_manager) -//} - -pub(crate) fn resolve_command(command: &Command) -> Result> { - //let wallet_manager = maybe_wallet_manager()?; - //let wallet_manager = wallet_manager.as_ref(); - //let matches = ArgMatches::default(); +pub(crate) fn resolve_command( + command: &Command, +) -> Result>, Box> { match command { Command::Scrub(args) => { let resolved_args = ScrubArgs { @@ -54,10 +38,19 @@ pub(crate) fn resolve_command(command: &Command) -> Result { + let wallet_manager = maybe_wallet_manager()?; + let wallet_manager = wallet_manager.as_ref(); + let matches = ArgMatches::default(); let resolved_args = TransferArgs { input_csv: args.input_csv.clone(), state_csv: args.state_csv.clone(), dry_run: args.dry_run.clone(), + sender_keypair: args.sender_keypair.as_ref().map(|key_url| { + signer_from_path(&matches, &key_url, "sender", wallet_manager).unwrap() + }), + fee_payer: args.fee_payer.as_ref().map(|key_url| { + signer_from_path(&matches, &key_url, "fee-payer", wallet_manager).unwrap() + }), }; Ok(Command::Transfer(resolved_args)) } diff --git a/src/main.rs b/src/main.rs index 75342f11319aa0..3dd2c7f0b04329 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,19 +7,22 @@ use console::style; use csv::{ReaderBuilder, Trim}; use itertools::Itertools; use serde::{Deserialize, Serialize}; +use solana_cli_config::Config; +use solana_client::client_error::ClientError; +use solana_client::rpc_client::RpcClient; +use solana_sdk::{ + message::Message, + native_token::sol_to_lamports, + signature::{Signature, Signer}, + signers::Signers, + system_instruction, + transaction::Transaction, +}; +use std::env; +use std::error::Error; use std::fs; use std::io; use std::path::Path; -//use solana_cli_config::Config; -//use solana_client::client_error::ClientError; -//use solana_client::rpc_client::RpcClient; -//use solana_sdk::{ -// message::Message, pubkey::Pubkey, signature::Signature, signers::Signers, -// transaction::Transaction, -//}; -use solana_sdk::signature::Signature; -use std::env; -use std::error::Error; #[derive(Deserialize, Debug)] struct Purchase { @@ -69,6 +72,7 @@ fn process_scrub(args: &ScrubArgs) -> Result<(), csv::Error> { fn find_new_transfers(transfers: &[Transfer], state: &[Transfer]) -> Vec { let mut needed = vec![]; for transfer in transfers { + // TODO: This should be a filter, not a find. if let Some(prev_transfer) = state.iter().find(|x| x.recipient == transfer.recipient) { if transfer.amount > prev_transfer.amount { needed.push(Transfer { @@ -84,7 +88,10 @@ fn find_new_transfers(transfers: &[Transfer], state: &[Transfer]) -> Vec Result<(), csv::Error> { +fn process_transfer( + client: &RpcClient, + args: &TransferArgs>, +) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) .from_path(&args.input_csv)?; @@ -109,7 +116,29 @@ fn process_transfer(args: &TransferArgs) -> Result<(), csv::Error> { println!("{:<44} {}", transfer.recipient, transfer.amount); } + let messages: Vec = needed + .iter() + .map(|transfer| { + let from = args.sender_keypair.as_ref().unwrap().pubkey(); + let to = transfer.recipient.parse().unwrap(); + let lamports = sol_to_lamports(transfer.amount); + let instruction = system_instruction::transfer(&from, &to, lamports); + Message::new(&[instruction]) + }) + .collect(); + + let signers = vec![ + &**args.sender_keypair.as_ref().unwrap(), + &**args.fee_payer.as_ref().unwrap(), + ]; + if !args.dry_run && !needed.is_empty() { + let _signatures: Vec<_> = messages + .into_iter() + .map(|message| send_message(&client, message, &signers).unwrap()) + .collect(); + + // TODO: Add signatures to 'needed' and append it to state_csv. let state_bak = format!("{}.bak", &args.state_csv); fs::rename(&args.state_csv, state_bak)?; let mut wtr = csv::Writer::from_path(&args.state_csv)?; @@ -122,28 +151,28 @@ fn process_transfer(args: &TransferArgs) -> Result<(), csv::Error> { Ok(()) } -//fn send_message( -// client: &RpcClient, -// message: Message, -// signers: &S, -//) -> Result { -// let mut transaction = Transaction::new_unsigned(message); -// client.resign_transaction(&mut transaction, signers)?; -// client.send_and_confirm_transaction_with_spinner(&mut transaction, signers) -//} +fn send_message( + client: &RpcClient, + message: Message, + signers: &S, +) -> Result { + let mut transaction = Transaction::new_unsigned(message); + client.resign_transaction(&mut transaction, signers)?; + client.send_and_confirm_transaction_with_spinner(&mut transaction, signers) +} fn main() -> Result<(), Box> { let command_args = parse_args(env::args_os()); - //let config = Config::load(&command_args.config_file)?; - //let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); - //let client = RpcClient::new(json_rpc_url); + let config = Config::load(&command_args.config_file)?; + let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); + let client = RpcClient::new(json_rpc_url); match resolve_command(&command_args.command)? { Command::Scrub(args) => { process_scrub(&args)?; } Command::Transfer(args) => { - process_transfer(&args)?; + process_transfer(&client, &args)?; } } Ok(()) From 94a17f7b2b2d97384933d4652198f73d19079e5c Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 2 Apr 2020 22:06:16 -0600 Subject: [PATCH 03/71] Refactor for testing --- Cargo.toml | 4 +--- src/arg_parser.rs | 2 -- src/main.rs | 54 +++++++++++++++++++--------------------------- src/thin_client.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 37 deletions(-) create mode 100644 src/thin_client.rs diff --git a/Cargo.toml b/Cargo.toml index d0ebe2e80ff2b6..f41efb4c990820 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,6 @@ solana-clap-utils = "1.1.0" solana-cli-config = "1.1.0" solana-client = "1.1.0" solana-remote-wallet = "1.1.0" +solana-runtime = "1.1.0" solana-sdk = "1.1.0" solana-stake-program = "1.1.0" - -[dev-dependencies] -solana-runtime = "1.1.0" diff --git a/src/arg_parser.rs b/src/arg_parser.rs index d62c762a1175f6..f67c95947e1e81 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -69,7 +69,6 @@ where .arg( Arg::with_name("sender_keypair") .long("from") - .required(true) .takes_value(true) .value_name("SENDING_KEYPAIR") .validator(is_valid_signer) @@ -78,7 +77,6 @@ where .arg( Arg::with_name("fee_payer") .long("fee-payer") - .required(true) .takes_value(true) .value_name("KEYPAIR") .validator(is_valid_signer) diff --git a/src/main.rs b/src/main.rs index 3dd2c7f0b04329..d5d403c85d1569 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,21 @@ mod arg_parser; mod args; +mod thin_client; use crate::arg_parser::parse_args; use crate::args::{resolve_command, Command, ScrubArgs, TransferArgs}; +use crate::thin_client::{NetworkClient, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; use itertools::Itertools; use serde::{Deserialize, Serialize}; use solana_cli_config::Config; -use solana_client::client_error::ClientError; use solana_client::rpc_client::RpcClient; use solana_sdk::{ message::Message, native_token::sol_to_lamports, signature::{Signature, Signer}, - signers::Signers, system_instruction, - transaction::Transaction, }; use std::env; use std::error::Error; @@ -88,8 +87,8 @@ fn find_new_transfers(transfers: &[Transfer], state: &[Transfer]) -> Vec( + client: &ThinClient, args: &TransferArgs>, ) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() @@ -116,26 +115,26 @@ fn process_transfer( println!("{:<44} {}", transfer.recipient, transfer.amount); } - let messages: Vec = needed - .iter() - .map(|transfer| { - let from = args.sender_keypair.as_ref().unwrap().pubkey(); - let to = transfer.recipient.parse().unwrap(); - let lamports = sol_to_lamports(transfer.amount); - let instruction = system_instruction::transfer(&from, &to, lamports); - Message::new(&[instruction]) - }) - .collect(); + if !args.dry_run && !needed.is_empty() { + let messages: Vec = needed + .iter() + .map(|transfer| { + let from = args.sender_keypair.as_ref().unwrap().pubkey(); + let to = transfer.recipient.parse().unwrap(); + let lamports = sol_to_lamports(transfer.amount); + let instruction = system_instruction::transfer(&from, &to, lamports); + Message::new(&[instruction]) + }) + .collect(); - let signers = vec![ - &**args.sender_keypair.as_ref().unwrap(), - &**args.fee_payer.as_ref().unwrap(), - ]; + let signers = vec![ + &**args.sender_keypair.as_ref().unwrap(), + &**args.fee_payer.as_ref().unwrap(), + ]; - if !args.dry_run && !needed.is_empty() { let _signatures: Vec<_> = messages .into_iter() - .map(|message| send_message(&client, message, &signers).unwrap()) + .map(|message| client.send_message(message, &signers).unwrap()) .collect(); // TODO: Add signatures to 'needed' and append it to state_csv. @@ -151,21 +150,12 @@ fn process_transfer( Ok(()) } -fn send_message( - client: &RpcClient, - message: Message, - signers: &S, -) -> Result { - let mut transaction = Transaction::new_unsigned(message); - client.resign_transaction(&mut transaction, signers)?; - client.send_and_confirm_transaction_with_spinner(&mut transaction, signers) -} - fn main() -> Result<(), Box> { let command_args = parse_args(env::args_os()); let config = Config::load(&command_args.config_file)?; let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); - let client = RpcClient::new(json_rpc_url); + let rpc_client = RpcClient::new(json_rpc_url); + let client = ThinClient(rpc_client); match resolve_command(&command_args.command)? { Command::Scrub(args) => { diff --git a/src/thin_client.rs b/src/thin_client.rs new file mode 100644 index 00000000000000..37f0d117a716d1 --- /dev/null +++ b/src/thin_client.rs @@ -0,0 +1,53 @@ +use solana_client::rpc_client::RpcClient; +use solana_runtime::bank_client::BankClient; +use solana_sdk::client::SyncClient; +use solana_sdk::{ + message::Message, signature::Signature, signers::Signers, transaction::Transaction, + transport::TransportError, +}; + +pub trait NetworkClient { + fn send_and_confirm_message( + &self, + message: Message, + signers: &S, + ) -> Result; +} + +impl NetworkClient for RpcClient { + fn send_and_confirm_message( + &self, + message: Message, + signers: &S, + ) -> Result { + let mut transaction = Transaction::new_unsigned(message); + self.resign_transaction(&mut transaction, signers) + .map_err(|e| TransportError::Custom(e.to_string()))?; + let signature = self + .send_and_confirm_transaction_with_spinner(&mut transaction, signers) + .map_err(|e| TransportError::Custom(e.to_string()))?; + Ok(signature) + } +} + +impl NetworkClient for BankClient { + fn send_and_confirm_message( + &self, + message: Message, + signers: &S, + ) -> Result { + self.send_message(signers, message) + } +} + +pub struct ThinClient(pub C); + +impl ThinClient { + pub fn send_message( + &self, + message: Message, + signers: &S, + ) -> Result { + self.0.send_and_confirm_message(message, signers) + } +} From edf81b6490ad664a377db029383234c701712449 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 2 Apr 2020 22:41:31 -0600 Subject: [PATCH 04/71] Cleanup readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b5e0851f82b7be..a5e8af81bb748e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ some process for transferring tokens to them, and ensuring that no more than the expected amount of tokens are sent. The command-line tool here automates that process. -## Scrup input +## Scrub input Clean, group, filter as needed. @@ -35,7 +35,7 @@ solana-batch transfer --dryrun Example output: ```text -Recipient Address Amount +Recipient Amount blahblahblah 70 yayayayayada 42 nadanadanada 43 @@ -49,7 +49,7 @@ solana-batch transfer --from --fee-paye Example output: ```text -Recipient Address Amount Signature +Recipient Amount Signature blahblahblah 70 blah yayayayayada 42 yada nadanadanada 43 nada From e3df5ab4b4e15e94681e49554712c1e61355ed9e Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 06:33:49 -0600 Subject: [PATCH 05/71] Rewrite --- README.md | 30 ++----- src/arg_parser.rs | 48 +++++------ src/args.rs | 31 +++----- src/main.rs | 194 ++++++++++++++++++++++++--------------------- src/thin_client.rs | 10 +++ 5 files changed, 149 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index a5e8af81bb748e..92c299dedbe105 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,17 @@ -# Reconcile total payments with current payments +# Distribute Solana tokens A user may want to make payments to multiple accounts over multiple iterations. -The user will have a spreadsheet listing public keys and expected balances, and +The user will have a spreadsheet listing public keys and token amounts, and some process for transferring tokens to them, and ensuring that no more than the -expected amount of tokens are sent. The command-line tool here automates that -process. +expected amount are sent. The command-line tool here automates that process. -## Scrub input - -Clean, group, filter as needed. - -```bash -solana-batch scrub -``` - -Example output: - -```text -recipient,amount -blahblahblah,100 -yayayayayada,42 -nadanadanada,43 -``` - -## Reconcile +## Distribute tokens List the differences between a list of expected payments and the record of what payments have already been made. ```bash -solana-batch transfer --dryrun +solana-tokens distribute --dollars-per-sol 0.22 --dryrun ``` Example output: @@ -43,7 +25,7 @@ nadanadanada 43 ```bash -solana-batch transfer --from --fee-payer +solana-tokens distribute --from --dollars-per-sol --fee-payer ``` Example output: diff --git a/src/arg_parser.rs b/src/arg_parser.rs index f67c95947e1e81..325a0bbbe4a455 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,4 +1,4 @@ -use crate::args::{Args, Command, ScrubArgs, TransferArgs}; +use crate::args::{Args, Command, DistributeArgs}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_clap_utils::input_validators::is_valid_signer; use solana_cli_config::CONFIG_FILE; @@ -31,35 +31,31 @@ where .help("RPC entrypoint address. i.e. http://devnet.solana.com"), ) .subcommand( - SubCommand::with_name("scrub") - .about("Scrub a data file") + SubCommand::with_name("distribute") + .about("Distribute tokens") .arg( - Arg::with_name("input_csv") + Arg::with_name("allocations_csv") .required(true) .index(1) .takes_value(true) .value_name("FILE") - .help("Input CSV file"), - ), - ) - .subcommand( - SubCommand::with_name("transfer") - .about("Scrub a data file") + .help("Allocations CSV file"), + ) .arg( - Arg::with_name("input_csv") + Arg::with_name("transactions_csv") .required(true) - .index(1) + .index(2) .takes_value(true) .value_name("FILE") - .help("Scrubbed CSV file"), + .help("Transactions CSV file"), ) .arg( - Arg::with_name("state_csv") + Arg::with_name("dollars_per_sol") + .long("dollars-per-sol") .required(true) - .index(2) .takes_value(true) - .value_name("FILE") - .help("State CSV file"), + .value_name("NUMBER") + .help("Dollars per SOL"), ) .arg( Arg::with_name("dry_run") @@ -86,16 +82,11 @@ where .get_matches_from(args) } -fn parse_scrub_args(matches: &ArgMatches<'_>) -> ScrubArgs { - ScrubArgs { - input_csv: value_t_or_exit!(matches, "input_csv", String), - } -} - -fn parse_transfer_args(matches: &ArgMatches<'_>) -> TransferArgs { - TransferArgs { - input_csv: value_t_or_exit!(matches, "input_csv", String), - state_csv: value_t_or_exit!(matches, "state_csv", String), +fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { + DistributeArgs { + allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), + transactions_csv: value_t_or_exit!(matches, "transactions_csv", String), + dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), dry_run: matches.is_present("dry_run"), sender_keypair: value_t!(matches, "sender_keypair", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), @@ -112,8 +103,7 @@ where let url = matches.value_of("url").map(|x| x.to_string()); let command = match matches.subcommand() { - ("scrub", Some(matches)) => Command::Scrub(parse_scrub_args(matches)), - ("transfer", Some(matches)) => Command::Transfer(parse_transfer_args(matches)), + ("distribute", Some(matches)) => Command::Distribute(parse_distribute_args(matches)), _ => { eprintln!("{}", matches.usage()); exit(1); diff --git a/src/args.rs b/src/args.rs index 81b808b5b0e417..5ba4d49079e2cd 100644 --- a/src/args.rs +++ b/src/args.rs @@ -4,21 +4,17 @@ use solana_remote_wallet::remote_wallet::maybe_wallet_manager; use solana_sdk::signature::Signer; use std::error::Error; -pub(crate) struct ScrubArgs { - pub input_csv: String, -} - -pub(crate) struct TransferArgs { - pub input_csv: String, - pub state_csv: String, +pub(crate) struct DistributeArgs { + pub allocations_csv: String, + pub transactions_csv: String, + pub dollars_per_sol: f64, pub dry_run: bool, pub sender_keypair: Option, pub fee_payer: Option, } pub(crate) enum Command { - Scrub(ScrubArgs), - Transfer(TransferArgs), + Distribute(DistributeArgs), } pub(crate) struct Args { @@ -31,19 +27,14 @@ pub(crate) fn resolve_command( command: &Command, ) -> Result>, Box> { match command { - Command::Scrub(args) => { - let resolved_args = ScrubArgs { - input_csv: args.input_csv.clone(), - }; - Ok(Command::Scrub(resolved_args)) - } - Command::Transfer(args) => { + Command::Distribute(args) => { let wallet_manager = maybe_wallet_manager()?; let wallet_manager = wallet_manager.as_ref(); let matches = ArgMatches::default(); - let resolved_args = TransferArgs { - input_csv: args.input_csv.clone(), - state_csv: args.state_csv.clone(), + let resolved_args = DistributeArgs { + allocations_csv: args.allocations_csv.clone(), + transactions_csv: args.transactions_csv.clone(), + dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run.clone(), sender_keypair: args.sender_keypair.as_ref().map(|key_url| { signer_from_path(&matches, &key_url, "sender", wallet_manager).unwrap() @@ -52,7 +43,7 @@ pub(crate) fn resolve_command( signer_from_path(&matches, &key_url, "fee-payer", wallet_manager).unwrap() }), }; - Ok(Command::Transfer(resolved_args)) + Ok(Command::Distribute(resolved_args)) } } } diff --git a/src/main.rs b/src/main.rs index d5d403c85d1569..e002d027ac913d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,10 @@ mod args; mod thin_client; use crate::arg_parser::parse_args; -use crate::args::{resolve_command, Command, ScrubArgs, TransferArgs}; +use crate::args::{resolve_command, Command, DistributeArgs}; use crate::thin_client::{NetworkClient, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; -use itertools::Itertools; use serde::{Deserialize, Serialize}; use solana_cli_config::Config; use solana_client::rpc_client::RpcClient; @@ -20,131 +19,147 @@ use solana_sdk::{ use std::env; use std::error::Error; use std::fs; -use std::io; use std::path::Path; -#[derive(Deserialize, Debug)] -struct Purchase { +#[derive(Deserialize, Debug, Clone)] +struct Bid { bid_amount_dollars: f64, primary_address: String, } +struct Allocation { + recipient: String, + amount: f64, +} + #[derive(Serialize, Deserialize, Debug, Clone)] -struct Transfer { +struct TransactionInfo { recipient: String, amount: f64, - signature: Option, + signature: String, } -const CLEARING_PRICE: f64 = 0.22; +fn apply_previous_transactions( + allocations: &mut Vec, + transaction_infos: &[TransactionInfo], +) { + for transaction_info in transaction_infos { + let mut amount = transaction_info.amount; + for allocation in allocations.iter_mut() { + if allocation.amount >= amount { + allocation.amount -= amount; + break; + } else { + amount -= allocation.amount; + allocation.amount = 0.0; + } + } + } + allocations.retain(|x| x.amount > 0.0); +} -fn scrub(purchases: &[Purchase]) -> Vec { - purchases +fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { + Allocation { + recipient: bid.primary_address.clone(), + amount: bid.bid_amount_dollars / dollars_per_sol, + } +} +fn distribute_tokens( + client: &ThinClient, + allocations: &[Allocation], + args: &DistributeArgs>, +) -> Vec { + let messages: Vec = allocations .iter() - .group_by(|x| &x.primary_address) - .into_iter() - .map(|(pubkey, xs)| { - let dollars: f64 = xs.map(|x| x.bid_amount_dollars).sum(); - Transfer { - recipient: pubkey.clone(), - amount: dollars / CLEARING_PRICE, - signature: None, - } + .map(|allocation| { + let from = args.sender_keypair.as_ref().unwrap().pubkey(); + let to = allocation.recipient.parse().unwrap(); + let lamports = sol_to_lamports(allocation.amount); + let instruction = system_instruction::transfer(&from, &to, lamports); + Message::new(&[instruction]) }) + .collect(); + + let signers = vec![ + &**args.sender_keypair.as_ref().unwrap(), + &**args.fee_payer.as_ref().unwrap(), + ]; + + messages + .into_iter() + .map(|message| client.send_message(message, &signers).unwrap()) .collect() } -fn process_scrub(args: &ScrubArgs) -> Result<(), csv::Error> { - let mut rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.input_csv)?; - let purchases: Vec = rdr.deserialize().map(|x| x.unwrap()).collect(); - - let mut wtr = csv::Writer::from_writer(io::stdout()); - for transfer in scrub(&purchases) { - wtr.serialize(transfer)?; +fn append_transaction_infos( + allocations: &[Allocation], + signatures: &[Signature], + transactions_csv: &str, +) -> Result<(), csv::Error> { + let existed = Path::new(&transactions_csv).exists(); + if existed { + let transactions_bak = format!("{}.bak", &transactions_csv); + fs::copy(&transactions_csv, transactions_bak)?; + } + let file = fs::OpenOptions::new() + .create_new(!existed) + .write(true) + .append(existed) + .open(&transactions_csv)?; + let mut wtr = csv::WriterBuilder::new() + .has_headers(!existed) + .from_writer(file); + + for (i, allocation) in allocations.iter().enumerate() { + let transaction_info = TransactionInfo { + recipient: allocation.recipient.clone(), + amount: allocation.amount, + signature: signatures[i].to_string(), + }; + wtr.serialize(transaction_info)?; } wtr.flush()?; Ok(()) } -fn find_new_transfers(transfers: &[Transfer], state: &[Transfer]) -> Vec { - let mut needed = vec![]; - for transfer in transfers { - // TODO: This should be a filter, not a find. - if let Some(prev_transfer) = state.iter().find(|x| x.recipient == transfer.recipient) { - if transfer.amount > prev_transfer.amount { - needed.push(Transfer { - recipient: transfer.recipient.clone(), - amount: transfer.amount - prev_transfer.amount, - signature: None, - }); - } - } else { - needed.push(transfer.clone()); - } - } - needed -} - -fn process_transfer( +fn process_distribute( client: &ThinClient, - args: &TransferArgs>, + args: &DistributeArgs>, ) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) - .from_path(&args.input_csv)?; - let transfers: Vec = rdr.deserialize().map(|x| x.unwrap()).collect(); + .from_path(&args.allocations_csv)?; + let mut allocations: Vec = rdr + .deserialize() + .map(|bid| create_allocation(&bid.unwrap(), args.dollars_per_sol)) + .collect(); - let state: Vec = if Path::new(&args.state_csv).exists() { + let transaction_infos: Vec = if Path::new(&args.transactions_csv).exists() { let mut state_rdr = ReaderBuilder::new() .trim(Trim::All) - .from_path(&args.state_csv)?; + .from_path(&args.transactions_csv)?; state_rdr.deserialize().map(|x| x.unwrap()).collect() } else { vec![] }; + apply_previous_transactions(&mut allocations, &transaction_infos); - let needed = find_new_transfers(&transfers, &state); + if allocations.is_empty() { + eprintln!("No work to do"); + return Ok(()); + } println!( "{}", style(format!("{:<44} {}", "Recipient", "Amount")).bold() ); - for transfer in &needed { - println!("{:<44} {}", transfer.recipient, transfer.amount); + for allocation in &allocations { + println!("{:<44} {}", allocation.recipient, allocation.amount); } - if !args.dry_run && !needed.is_empty() { - let messages: Vec = needed - .iter() - .map(|transfer| { - let from = args.sender_keypair.as_ref().unwrap().pubkey(); - let to = transfer.recipient.parse().unwrap(); - let lamports = sol_to_lamports(transfer.amount); - let instruction = system_instruction::transfer(&from, &to, lamports); - Message::new(&[instruction]) - }) - .collect(); - - let signers = vec![ - &**args.sender_keypair.as_ref().unwrap(), - &**args.fee_payer.as_ref().unwrap(), - ]; - - let _signatures: Vec<_> = messages - .into_iter() - .map(|message| client.send_message(message, &signers).unwrap()) - .collect(); - - // TODO: Add signatures to 'needed' and append it to state_csv. - let state_bak = format!("{}.bak", &args.state_csv); - fs::rename(&args.state_csv, state_bak)?; - let mut wtr = csv::Writer::from_path(&args.state_csv)?; - for transfer in &transfers { - wtr.serialize(transfer)?; - } - wtr.flush()?; + if !args.dry_run { + let signatures = distribute_tokens(&client, &allocations, &args); + append_transaction_infos(&allocations, &signatures, &args.transactions_csv)?; } Ok(()) @@ -158,11 +173,8 @@ fn main() -> Result<(), Box> { let client = ThinClient(rpc_client); match resolve_command(&command_args.command)? { - Command::Scrub(args) => { - process_scrub(&args)?; - } - Command::Transfer(args) => { - process_transfer(&client, &args)?; + Command::Distribute(args) => { + process_distribute(&client, &args)?; } } Ok(()) diff --git a/src/thin_client.rs b/src/thin_client.rs index 37f0d117a716d1..fb1c9273ca2da3 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -40,6 +40,16 @@ impl NetworkClient for BankClient { } } +impl NetworkClient for () { + fn send_and_confirm_message( + &self, + _message: Message, + _signers: &S, + ) -> Result { + Ok(Signature::default()) + } +} + pub struct ThinClient(pub C); impl ThinClient { From 449826c607a27baacc8c5e86d7a14637532538ac Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 06:37:15 -0600 Subject: [PATCH 06/71] Cleanup --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 92c299dedbe105..b87c78a01b70fc 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ List the differences between a list of expected payments and the record of what payments have already been made. ```bash -solana-tokens distribute --dollars-per-sol 0.22 --dryrun +solana-tokens distribute --dollars-per-sol --dryrun ``` Example output: @@ -25,26 +25,26 @@ nadanadanada 43 ```bash -solana-tokens distribute --from --dollars-per-sol --fee-payer +solana-tokens distribute --from --dollars-per-sol --fee-payer ``` Example output: ```text -Recipient Amount Signature -blahblahblah 70 blah -yayayayayada 42 yada -nadanadanada 43 nada +Recipient Amount +blahblahblah 70 +yayayayayada 42 +nadanadanada 43 ``` -Example state before: +Example transaction log before: ```text recipient,amount,signature blahblahblah,30,blah,orig ``` -Example state after: +Example transaction log after: ```text recipient,amount,signature From 30b14594f1feca380bad64fcbac00f7e27e17934 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 06:41:58 -0600 Subject: [PATCH 07/71] Cleanup --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b87c78a01b70fc..a5c3c83267348b 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ The user will have a spreadsheet listing public keys and token amounts, and some process for transferring tokens to them, and ensuring that no more than the expected amount are sent. The command-line tool here automates that process. -## Distribute tokens +## Calculate what tokens should be sent -List the differences between a list of expected payments and the record of what -payments have already been made. +List the differences between a list of expected distributions and the record of what +transactions have already been sent. ```bash solana-tokens distribute --dollars-per-sol --dryrun @@ -23,6 +23,10 @@ yayayayayada 42 nadanadanada 43 ``` +## Distribute tokens + +Send tokens to the recipients in `` if the distribution is +not already recordered in the transaction log. ```bash solana-tokens distribute --from --dollars-per-sol --fee-payer From d3df3132b2b74bb63ce672c108a068932fe38b57 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 06:45:49 -0600 Subject: [PATCH 08/71] Cleanup client --- src/main.rs | 6 +++--- src/thin_client.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index e002d027ac913d..f734f74dd82272 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod thin_client; use crate::arg_parser::parse_args; use crate::args::{resolve_command, Command, DistributeArgs}; -use crate::thin_client::{NetworkClient, ThinClient}; +use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; use serde::{Deserialize, Serialize}; @@ -64,7 +64,7 @@ fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { amount: bid.bid_amount_dollars / dollars_per_sol, } } -fn distribute_tokens( +fn distribute_tokens( client: &ThinClient, allocations: &[Allocation], args: &DistributeArgs>, @@ -122,7 +122,7 @@ fn append_transaction_infos( Ok(()) } -fn process_distribute( +fn process_distribute( client: &ThinClient, args: &DistributeArgs>, ) -> Result<(), csv::Error> { diff --git a/src/thin_client.rs b/src/thin_client.rs index fb1c9273ca2da3..b840bbdf70e14a 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -6,7 +6,7 @@ use solana_sdk::{ transport::TransportError, }; -pub trait NetworkClient { +pub trait Client { fn send_and_confirm_message( &self, message: Message, @@ -14,7 +14,7 @@ pub trait NetworkClient { ) -> Result; } -impl NetworkClient for RpcClient { +impl Client for RpcClient { fn send_and_confirm_message( &self, message: Message, @@ -30,7 +30,7 @@ impl NetworkClient for RpcClient { } } -impl NetworkClient for BankClient { +impl Client for BankClient { fn send_and_confirm_message( &self, message: Message, @@ -40,7 +40,7 @@ impl NetworkClient for BankClient { } } -impl NetworkClient for () { +impl Client for () { fn send_and_confirm_message( &self, _message: Message, @@ -50,9 +50,9 @@ impl NetworkClient for () { } } -pub struct ThinClient(pub C); +pub struct ThinClient(pub C); -impl ThinClient { +impl ThinClient { pub fn send_message( &self, message: Message, From 7932a48288d7cc219690232f48c66fef7ec98c3e Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 06:55:01 -0600 Subject: [PATCH 09/71] Use a Null Client to move prints closer to where messages are sent --- src/main.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index f734f74dd82272..ef43434330fc6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,6 +72,7 @@ fn distribute_tokens( let messages: Vec = allocations .iter() .map(|allocation| { + println!("{:<44} {}", allocation.recipient, allocation.amount); let from = args.sender_keypair.as_ref().unwrap().pubkey(); let to = allocation.recipient.parse().unwrap(); let lamports = sol_to_lamports(allocation.amount); @@ -153,12 +154,9 @@ fn process_distribute( "{}", style(format!("{:<44} {}", "Recipient", "Amount")).bold() ); - for allocation in &allocations { - println!("{:<44} {}", allocation.recipient, allocation.amount); - } + let signatures = distribute_tokens(&client, &allocations, &args); if !args.dry_run { - let signatures = distribute_tokens(&client, &allocations, &args); append_transaction_infos(&allocations, &signatures, &args.transactions_csv)?; } @@ -168,13 +166,17 @@ fn process_distribute( fn main() -> Result<(), Box> { let command_args = parse_args(env::args_os()); let config = Config::load(&command_args.config_file)?; - let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); - let rpc_client = RpcClient::new(json_rpc_url); - let client = ThinClient(rpc_client); match resolve_command(&command_args.command)? { Command::Distribute(args) => { - process_distribute(&client, &args)?; + let client = if args.dry_run { + let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); + RpcClient::new(json_rpc_url); + } else { + () + }; + let thin_client = ThinClient(client); + process_distribute(&thin_client, &args)?; } } Ok(()) From 6213f14321ced6c91712c6b1cf61b8f532c4a8fa Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 07:00:51 -0600 Subject: [PATCH 10/71] Upgrade Solana --- Cargo.lock | 76 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 14 +++++----- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e70f7d840abb5..1941d2fc3ecf24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2210,9 +2210,9 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6dd534159b364724083ccb459e9d9e37ac63de3f3416d0fd1937809b88d1512" +checksum = "9b11a55221ec8313a1f3e0101461d2f9535d0712a1bcd6754e13974c3c7c8447" dependencies = [ "bincode", "byteorder", @@ -2228,9 +2228,9 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cb4120cd8084b703872ae5bdce5b5592f538f9014692e8ae7a4f16ae0f282bc" +checksum = "2d1e7d83c36a108e81aa83f991e6a53616ace9c026e866f35797df5bc949a977" dependencies = [ "chrono", "clap", @@ -2244,9 +2244,9 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fd8e6743c01cfd08a4e522a2954e6fcb0ce5970f9fb028adb0413456196d16" +checksum = "46bda778268146a2ad2d82b42705f019c50c0a3557a221d64e44c7bc6f844dee" dependencies = [ "dirs", "lazy_static", @@ -2258,9 +2258,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ed191106676114e575d93a707c2541c1a3d7fc9b15e4c083b2ee924d50b6574" +checksum = "70d0b6dd8cd753249fe5ab5f8a81aca74e6f40445e3586d95a4e236200555a6a" dependencies = [ "bincode", "bs58", @@ -2283,9 +2283,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c74e39c5a6bb7734c3a40511de1cd15a7581a514edf1aa570aee0f979a9e17" +checksum = "d3848abb2b3f662aa107df2a3b1c918d01edc57302bd2d1c5c24b279acabdbc9" dependencies = [ "bincode", "chrono", @@ -2298,9 +2298,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb33bafc25208fd7197d43e1c154440345c9f8dcf59ccb153e1c760c8b9ed35" +checksum = "a401b72dcacd535b88d6e3193533c4f7c3b5154a4f2cb7b3d1d1b61932c2cded" dependencies = [ "backtrace", "bytes 0.4.12", @@ -2323,9 +2323,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2f7313c5c9036d5c48a614cb7eba3a50a2e932c35103d2b2b5b5476cad2d2e" +checksum = "b5ba3abed8ca3ab5e5148594452f8d65def958e71ee3aaebbf896ea6fe543c74" dependencies = [ "env_logger 0.7.1", "lazy_static", @@ -2334,9 +2334,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f99c4a275b50e89f08d4d7132e4ff03b182f32437ecbf6ac6f286d922ebf1b6" +checksum = "b3dbf5afbbe452109662eb95159078ec9879313a5ccd57f4bba726768051b9f3" dependencies = [ "jemalloc-ctl", "jemallocator", @@ -2347,9 +2347,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016dc8173ee03bb0935d170d1a42b26ad732d628a8b07c3e36a1afb9b827f4de" +checksum = "5cc4ec5f2eabd26b8ac0bc3c4a3e97a23d7163874f134ac5f98a2506f310775f" dependencies = [ "env_logger 0.7.1", "gethostname", @@ -2361,9 +2361,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f47502bdebea17f685d1cbcb7bc744c08cada5482cd322c518d61c4c1f7fc2" +checksum = "0b8ff34d00ad44fef0309fa4b4772e421fe478c235ee740eaa399f58ae3b93ae" dependencies = [ "bincode", "bytes 0.4.12", @@ -2382,9 +2382,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98abf277ba48d1dd8584c389eb4566b322d028acfc7611b30c5389660ec2abb2" +checksum = "3cb2ae379caa28111b3c6b1ea83f4623d66190f20504ff578c24ce3947afee69" dependencies = [ "lazy_static", "num_cpus", @@ -2392,9 +2392,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d86eab604d37ee7cafa384295c55e20b3c3fc033fe438befd725a6f3ac24bcd" +checksum = "3508f3dd5ddf1fe83663cf3fd5ec47d9b762175669fd868e1c7fcc395c078d11" dependencies = [ "base32", "console", @@ -2410,9 +2410,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930a08e8a3097cd060d88003ef99ebad0ae12448a05854570f0f4ceb7c9edd3e" +checksum = "6c20b96918d9a178c2bea0ce97b2440e7942e626bb6a9dc555e4dc56ff486b0a" dependencies = [ "bincode", "bv", @@ -2447,9 +2447,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bc7e1e5dda1999fb5894dd9843230fbea77c5748629601c3da29788b6ec071e" +checksum = "d8343657849df093cfe3f024da88c46ffec41dbfaa579e25e24057d1b987b8e4" dependencies = [ "assert_matches", "bincode", @@ -2482,9 +2482,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3124b8792d090e99e52e7aa93b25508a5ca2253b3bf2883bd5fef90f395703" +checksum = "2d04c4431d64f1f61df85cdf38c2c0737840d7b061afea6b95d0c9afcd9e1b6d" dependencies = [ "bs58", "proc-macro2 1.0.10", @@ -2494,9 +2494,9 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0afdb46eeacff16098bf11d387d355f11865b9b4300a611775c27b80892f93" +checksum = "5e86a7b234809e2961b51e9959517994610449abf858cb448e9d0e31cafca011" dependencies = [ "bincode", "log", @@ -2514,9 +2514,9 @@ dependencies = [ [[package]] name = "solana-storage-program" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5422676420bfb243ddb9ce4222ba6609916c9aa5f894c3b407f306d0db310e4e" +checksum = "96d9ef9f07f6dfb8be7915f5693767b977449c0d2e7e0ebb9c33c7014c3ea576" dependencies = [ "bincode", "log", @@ -2531,9 +2531,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54f5b8a327ac80c2d020d8396668f8d70602f8dc82a79bd7725ff70fa3811e6" +checksum = "473e8911e1d38e7c432e298e0b385895f502ec1756190b617d43b6adc88784e8" dependencies = [ "bincode", "bs58", @@ -2544,9 +2544,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bdc7e906ced7eb6c0d769081e313ab7adb485b2de77602475aebba38859a5b" +checksum = "142ad2d760e25fb055c0365ae837ee8bcd649d9a956188b14c38f2f365ab4260" dependencies = [ "bincode", "log", diff --git a/Cargo.toml b/Cargo.toml index f41efb4c990820..cb164a011b1b94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,10 @@ clap = "2.33.0" console = "0.10.0" itertools = "0.9.0" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = "1.1.0" -solana-cli-config = "1.1.0" -solana-client = "1.1.0" -solana-remote-wallet = "1.1.0" -solana-runtime = "1.1.0" -solana-sdk = "1.1.0" -solana-stake-program = "1.1.0" +solana-clap-utils = "1.1.1" +solana-cli-config = "1.1.1" +solana-client = "1.1.1" +solana-remote-wallet = "1.1.1" +solana-runtime = "1.1.1" +solana-sdk = "1.1.1" +solana-stake-program = "1.1.1" From c49cdbe8652775012c6d449b0c6f5afc34d72835 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 07:05:34 -0600 Subject: [PATCH 11/71] Move core functionality into its own module --- src/main.rs | 159 ++------------------------------------------------ src/tokens.rs | 155 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 155 deletions(-) create mode 100644 src/tokens.rs diff --git a/src/main.rs b/src/main.rs index ef43434330fc6b..904fdbade3f173 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,167 +1,16 @@ mod arg_parser; mod args; mod thin_client; +mod tokens; use crate::arg_parser::parse_args; -use crate::args::{resolve_command, Command, DistributeArgs}; -use crate::thin_client::{Client, ThinClient}; -use console::style; -use csv::{ReaderBuilder, Trim}; -use serde::{Deserialize, Serialize}; +use crate::args::{resolve_command, Command}; +use crate::thin_client::ThinClient; +use crate::tokens::process_distribute; use solana_cli_config::Config; use solana_client::rpc_client::RpcClient; -use solana_sdk::{ - message::Message, - native_token::sol_to_lamports, - signature::{Signature, Signer}, - system_instruction, -}; use std::env; use std::error::Error; -use std::fs; -use std::path::Path; - -#[derive(Deserialize, Debug, Clone)] -struct Bid { - bid_amount_dollars: f64, - primary_address: String, -} - -struct Allocation { - recipient: String, - amount: f64, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -struct TransactionInfo { - recipient: String, - amount: f64, - signature: String, -} - -fn apply_previous_transactions( - allocations: &mut Vec, - transaction_infos: &[TransactionInfo], -) { - for transaction_info in transaction_infos { - let mut amount = transaction_info.amount; - for allocation in allocations.iter_mut() { - if allocation.amount >= amount { - allocation.amount -= amount; - break; - } else { - amount -= allocation.amount; - allocation.amount = 0.0; - } - } - } - allocations.retain(|x| x.amount > 0.0); -} - -fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { - Allocation { - recipient: bid.primary_address.clone(), - amount: bid.bid_amount_dollars / dollars_per_sol, - } -} -fn distribute_tokens( - client: &ThinClient, - allocations: &[Allocation], - args: &DistributeArgs>, -) -> Vec { - let messages: Vec = allocations - .iter() - .map(|allocation| { - println!("{:<44} {}", allocation.recipient, allocation.amount); - let from = args.sender_keypair.as_ref().unwrap().pubkey(); - let to = allocation.recipient.parse().unwrap(); - let lamports = sol_to_lamports(allocation.amount); - let instruction = system_instruction::transfer(&from, &to, lamports); - Message::new(&[instruction]) - }) - .collect(); - - let signers = vec![ - &**args.sender_keypair.as_ref().unwrap(), - &**args.fee_payer.as_ref().unwrap(), - ]; - - messages - .into_iter() - .map(|message| client.send_message(message, &signers).unwrap()) - .collect() -} - -fn append_transaction_infos( - allocations: &[Allocation], - signatures: &[Signature], - transactions_csv: &str, -) -> Result<(), csv::Error> { - let existed = Path::new(&transactions_csv).exists(); - if existed { - let transactions_bak = format!("{}.bak", &transactions_csv); - fs::copy(&transactions_csv, transactions_bak)?; - } - let file = fs::OpenOptions::new() - .create_new(!existed) - .write(true) - .append(existed) - .open(&transactions_csv)?; - let mut wtr = csv::WriterBuilder::new() - .has_headers(!existed) - .from_writer(file); - - for (i, allocation) in allocations.iter().enumerate() { - let transaction_info = TransactionInfo { - recipient: allocation.recipient.clone(), - amount: allocation.amount, - signature: signatures[i].to_string(), - }; - wtr.serialize(transaction_info)?; - } - wtr.flush()?; - Ok(()) -} - -fn process_distribute( - client: &ThinClient, - args: &DistributeArgs>, -) -> Result<(), csv::Error> { - let mut rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.allocations_csv)?; - let mut allocations: Vec = rdr - .deserialize() - .map(|bid| create_allocation(&bid.unwrap(), args.dollars_per_sol)) - .collect(); - - let transaction_infos: Vec = if Path::new(&args.transactions_csv).exists() { - let mut state_rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.transactions_csv)?; - state_rdr.deserialize().map(|x| x.unwrap()).collect() - } else { - vec![] - }; - apply_previous_transactions(&mut allocations, &transaction_infos); - - if allocations.is_empty() { - eprintln!("No work to do"); - return Ok(()); - } - - println!( - "{}", - style(format!("{:<44} {}", "Recipient", "Amount")).bold() - ); - - let signatures = distribute_tokens(&client, &allocations, &args); - if !args.dry_run { - append_transaction_infos(&allocations, &signatures, &args.transactions_csv)?; - } - - Ok(()) -} fn main() -> Result<(), Box> { let command_args = parse_args(env::args_os()); diff --git a/src/tokens.rs b/src/tokens.rs new file mode 100644 index 00000000000000..8842a358cf11c6 --- /dev/null +++ b/src/tokens.rs @@ -0,0 +1,155 @@ +use crate::args::DistributeArgs; +use crate::thin_client::{Client, ThinClient}; +use console::style; +use csv::{ReaderBuilder, Trim}; +use serde::{Deserialize, Serialize}; +use solana_sdk::{ + message::Message, + native_token::sol_to_lamports, + signature::{Signature, Signer}, + system_instruction, +}; +use std::fs; +use std::path::Path; + +#[derive(Deserialize, Debug, Clone)] +struct Bid { + bid_amount_dollars: f64, + primary_address: String, +} + +struct Allocation { + recipient: String, + amount: f64, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct TransactionInfo { + recipient: String, + amount: f64, + signature: String, +} + +fn apply_previous_transactions( + allocations: &mut Vec, + transaction_infos: &[TransactionInfo], +) { + for transaction_info in transaction_infos { + let mut amount = transaction_info.amount; + for allocation in allocations.iter_mut() { + if allocation.amount >= amount { + allocation.amount -= amount; + break; + } else { + amount -= allocation.amount; + allocation.amount = 0.0; + } + } + } + allocations.retain(|x| x.amount > 0.0); +} + +fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { + Allocation { + recipient: bid.primary_address.clone(), + amount: bid.bid_amount_dollars / dollars_per_sol, + } +} +fn distribute_tokens( + client: &ThinClient, + allocations: &[Allocation], + args: &DistributeArgs>, +) -> Vec { + let messages: Vec = allocations + .iter() + .map(|allocation| { + println!("{:<44} {}", allocation.recipient, allocation.amount); + let from = args.sender_keypair.as_ref().unwrap().pubkey(); + let to = allocation.recipient.parse().unwrap(); + let lamports = sol_to_lamports(allocation.amount); + let instruction = system_instruction::transfer(&from, &to, lamports); + Message::new(&[instruction]) + }) + .collect(); + + let signers = vec![ + &**args.sender_keypair.as_ref().unwrap(), + &**args.fee_payer.as_ref().unwrap(), + ]; + + messages + .into_iter() + .map(|message| client.send_message(message, &signers).unwrap()) + .collect() +} + +fn append_transaction_infos( + allocations: &[Allocation], + signatures: &[Signature], + transactions_csv: &str, +) -> Result<(), csv::Error> { + let existed = Path::new(&transactions_csv).exists(); + if existed { + let transactions_bak = format!("{}.bak", &transactions_csv); + fs::copy(&transactions_csv, transactions_bak)?; + } + let file = fs::OpenOptions::new() + .create_new(!existed) + .write(true) + .append(existed) + .open(&transactions_csv)?; + let mut wtr = csv::WriterBuilder::new() + .has_headers(!existed) + .from_writer(file); + + for (i, allocation) in allocations.iter().enumerate() { + let transaction_info = TransactionInfo { + recipient: allocation.recipient.clone(), + amount: allocation.amount, + signature: signatures[i].to_string(), + }; + wtr.serialize(transaction_info)?; + } + wtr.flush()?; + Ok(()) +} + +pub(crate) fn process_distribute( + client: &ThinClient, + args: &DistributeArgs>, +) -> Result<(), csv::Error> { + let mut rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.allocations_csv)?; + let mut allocations: Vec = rdr + .deserialize() + .map(|bid| create_allocation(&bid.unwrap(), args.dollars_per_sol)) + .collect(); + + let transaction_infos: Vec = if Path::new(&args.transactions_csv).exists() { + let mut state_rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.transactions_csv)?; + state_rdr.deserialize().map(|x| x.unwrap()).collect() + } else { + vec![] + }; + apply_previous_transactions(&mut allocations, &transaction_infos); + + if allocations.is_empty() { + eprintln!("No work to do"); + return Ok(()); + } + + println!( + "{}", + style(format!("{:<44} {}", "Recipient", "Amount")).bold() + ); + + let signatures = distribute_tokens(&client, &allocations, &args); + if !args.dry_run { + append_transaction_infos(&allocations, &signatures, &args.transactions_csv)?; + } + + Ok(()) +} From bc16911444e81382667874aa90d41c1fb8d38fa9 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 07:14:13 -0600 Subject: [PATCH 12/71] Handle transaction errors --- src/tokens.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 8842a358cf11c6..121878cf084bc8 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -8,6 +8,7 @@ use solana_sdk::{ native_token::sol_to_lamports, signature::{Signature, Signer}, system_instruction, + transport::TransportError, }; use std::fs; use std::path::Path; @@ -59,7 +60,7 @@ fn distribute_tokens( client: &ThinClient, allocations: &[Allocation], args: &DistributeArgs>, -) -> Vec { +) -> Vec> { let messages: Vec = allocations .iter() .map(|allocation| { @@ -79,13 +80,13 @@ fn distribute_tokens( messages .into_iter() - .map(|message| client.send_message(message, &signers).unwrap()) + .map(|message| client.send_message(message, &signers)) .collect() } fn append_transaction_infos( allocations: &[Allocation], - signatures: &[Signature], + results: &[Result], transactions_csv: &str, ) -> Result<(), csv::Error> { let existed = Path::new(&transactions_csv).exists(); @@ -103,12 +104,19 @@ fn append_transaction_infos( .from_writer(file); for (i, allocation) in allocations.iter().enumerate() { - let transaction_info = TransactionInfo { - recipient: allocation.recipient.clone(), - amount: allocation.amount, - signature: signatures[i].to_string(), - }; - wtr.serialize(transaction_info)?; + match &results[i] { + Ok(signature) => { + let transaction_info = TransactionInfo { + recipient: allocation.recipient.clone(), + amount: allocation.amount, + signature: signature.to_string(), + }; + wtr.serialize(transaction_info)?; + } + Err(e) => { + eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); + } + } } wtr.flush()?; Ok(()) @@ -146,9 +154,9 @@ pub(crate) fn process_distribute( style(format!("{:<44} {}", "Recipient", "Amount")).bold() ); - let signatures = distribute_tokens(&client, &allocations, &args); + let results = distribute_tokens(&client, &allocations, &args); if !args.dry_run { - append_transaction_infos(&allocations, &signatures, &args.transactions_csv)?; + append_transaction_infos(&allocations, &results, &args.transactions_csv)?; } Ok(()) From 3a7653b2f94869ceac22bf1d9ecfbf5f22a93e1c Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 07:44:05 -0600 Subject: [PATCH 13/71] Merge allocations --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- src/tokens.rs | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1941d2fc3ecf24..0334080d549269 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2197,7 +2197,7 @@ dependencies = [ "clap", "console", "csv", - "itertools 0.9.0", + "indexmap", "serde", "solana-clap-utils", "solana-cli-config", diff --git a/Cargo.toml b/Cargo.toml index cb164a011b1b94..14f1f464bf1260 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "solana-batch" +name = "solana-tokens" description = "Blockchain, Rebuilt for Scale" authors = ["Solana Maintainers "] edition = "2018" @@ -12,7 +12,7 @@ homepage = "https://solana.com/" csv = "1.1.3" clap = "2.33.0" console = "0.10.0" -itertools = "0.9.0" +indexmap = "1.3.2" serde = { version = "1.0", features = ["derive"] } solana-clap-utils = "1.1.1" solana-cli-config = "1.1.1" diff --git a/src/tokens.rs b/src/tokens.rs index 121878cf084bc8..c4b7c8959f6fb3 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -2,6 +2,7 @@ use crate::args::DistributeArgs; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use solana_sdk::{ message::Message, @@ -19,6 +20,7 @@ struct Bid { primary_address: String, } +#[derive(Debug, Clone)] struct Allocation { recipient: String, amount: f64, @@ -31,6 +33,20 @@ struct TransactionInfo { signature: String, } +fn merge_allocations(allocations: &[Allocation]) -> Vec { + let mut allocation_map = IndexMap::new(); + for allocation in allocations { + allocation_map + .entry(&allocation.recipient) + .or_insert(Allocation { + recipient: allocation.recipient.clone(), + amount: 0.0, + }) + .amount += allocation.amount; + } + allocation_map.values().cloned().collect() +} + fn apply_previous_transactions( allocations: &mut Vec, transaction_infos: &[TransactionInfo], @@ -129,7 +145,7 @@ pub(crate) fn process_distribute( let mut rdr = ReaderBuilder::new() .trim(Trim::All) .from_path(&args.allocations_csv)?; - let mut allocations: Vec = rdr + let allocations: Vec = rdr .deserialize() .map(|bid| create_allocation(&bid.unwrap(), args.dollars_per_sol)) .collect(); @@ -142,6 +158,7 @@ pub(crate) fn process_distribute( } else { vec![] }; + let mut allocations = merge_allocations(&allocations); apply_previous_transactions(&mut allocations, &transaction_infos); if allocations.is_empty() { From 984dde83b8be5964850d85f6d2a1121eb6a1b0a7 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 07:51:41 -0600 Subject: [PATCH 14/71] Fixes --- Cargo.lock | 36 ++++++++++++++++++------------------ src/main.rs | 4 ++-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0334080d549269..889675f3b9fcd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2190,24 +2190,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "solana-batch" -version = "0.1.0" -dependencies = [ - "clap", - "console", - "csv", - "indexmap", - "serde", - "solana-clap-utils", - "solana-cli-config", - "solana-client", - "solana-remote-wallet", - "solana-runtime", - "solana-sdk", - "solana-stake-program", -] - [[package]] name = "solana-bpf-loader-program" version = "1.1.1" @@ -2529,6 +2511,24 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-tokens" +version = "0.1.0" +dependencies = [ + "clap", + "console", + "csv", + "indexmap", + "serde", + "solana-clap-utils", + "solana-cli-config", + "solana-client", + "solana-remote-wallet", + "solana-runtime", + "solana-sdk", + "solana-stake-program", +] + [[package]] name = "solana-transaction-status" version = "1.1.1" diff --git a/src/main.rs b/src/main.rs index 904fdbade3f173..5bb4b370680bac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,10 +19,10 @@ fn main() -> Result<(), Box> { match resolve_command(&command_args.command)? { Command::Distribute(args) => { let client = if args.dry_run { + () + } else { let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); RpcClient::new(json_rpc_url); - } else { - () }; let thin_client = ThinClient(client); process_distribute(&thin_client, &args)?; From 74a925df2123edb0a49b95cb08b2e50573a71a7c Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 10:19:03 -0600 Subject: [PATCH 15/71] Cleanup readme --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a5c3c83267348b..ad593936f6345e 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,16 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute --dollars-per-sol --dryrun +solana-tokens distribute --dollars-per-sol --dry-run ``` Example output: ```text -Recipient Amount -blahblahblah 70 -yayayayayada 42 -nadanadanada 43 +`**Recipient**` `**Amount**` +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv 70 +3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM 42 +UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 ``` ## Distribute tokens @@ -29,31 +29,31 @@ Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute --from --dollars-per-sol --fee-payer +solana-tokens distribute --from --dollars-per-sol --fee-payer ``` Example output: ```text -Recipient Amount -blahblahblah 70 -yayayayayada 42 -nadanadanada 43 +`**Recipient**` `**Amount**` +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv 70 +3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM 42 +UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 ``` Example transaction log before: ```text recipient,amount,signature -blahblahblah,30,blah,orig +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,30,orig ``` Example transaction log after: ```text recipient,amount,signature -blahblahblah,30,orig -blahblahblah,70,blah -yayayayayada,42,yada -nadanadanada,43,nada +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,30,1111111111111111111111111111111111111111111111111111111111111111 +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,70,1111111111111111111111111111111111111111111111111111111111111111 +3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM,42,1111111111111111111111111111111111111111111111111111111111111111 +UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k,43,1111111111111111111111111111111111111111111111111111111111111111 ``` From 47a9d98d1635b63cc65684c4079cdcfd7d28b642 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 10:20:00 -0600 Subject: [PATCH 16/71] Fix markdown --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ad593936f6345e..8f7e309f4f4971 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ solana-tokens distribute --dollars-per-sol --dry-run Example output: ```text -`**Recipient**` `**Amount**` +Recipient Amount 6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv 70 3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM 42 UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 @@ -35,7 +35,7 @@ solana-tokens distribute --from --dollars-per-sol Date: Fri, 3 Apr 2020 10:25:10 -0600 Subject: [PATCH 17/71] Add example input --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 8f7e309f4f4971..e886616ccc9f70 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,16 @@ transactions have already been sent. solana-tokens distribute --dollars-per-sol --dry-run ``` +Example allocations.csv: + +```text +primary_address,bid_amount_dollars +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,6.6 +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,15.4 +3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM,9.24 +UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k,9.46 +``` + Example output: ```text From 3f49c37c08ffece99d48f8feb6d16994dd0bfa23 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 15:18:52 -0600 Subject: [PATCH 18/71] Add integration test - currently fails --- Cargo.lock | 1335 +++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 3 + README.md | 61 +- src/arg_parser.rs | 4 +- src/args.rs | 8 +- src/main.rs | 15 +- src/thin_client.rs | 44 +- src/tokens.rs | 101 +++- 8 files changed, 1434 insertions(+), 137 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 889675f3b9fcd9..88893ed4e3d5ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" + [[package]] name = "aho-corasick" version = "0.7.10" @@ -103,6 +109,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + [[package]] name = "base64" version = "0.11.0" @@ -119,6 +144,30 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb26d6a69a335b8cb0e7c7e9775cd5666611dc50a37177c3f2cedcfc040e8c8" +dependencies = [ + "bitflags", + "cexpr", + "cfg-if", + "clang-sys", + "clap", + "env_logger 0.7.1", + "lazy_static", + "lazycell", + "log 0.4.8", + "peeking_take_while", + "proc-macro2 1.0.10", + "quote 1.0.3", + "regex", + "rustc-hash", + "shlex", + "which", +] + [[package]] name = "bit-vec" version = "0.4.4" @@ -257,6 +306,26 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +[[package]] +name = "bzip2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.8+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05305b41c5034ff0e93937ac64133d109b5a2660114ec45e9760bc6816d83038" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "cc" version = "1.0.49" @@ -267,6 +336,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -285,6 +363,17 @@ dependencies = [ "time", ] +[[package]] +name = "clang-sys" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" +dependencies = [ + "glob 0.3.0", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.33.0" @@ -389,6 +478,37 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +[[package]] +name = "core_affinity" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8a03115cc34fb0d7c321dd154a3914b3ca082ccc5c11d91bf7117dbbe7171f" +dependencies = [ + "kernel32-sys", + "libc", + "num_cpus", + "winapi 0.2.8", +] + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +dependencies = [ + "crossbeam-utils", + "maybe-uninit", +] + [[package]] name = "crossbeam-deque" version = "0.7.3" @@ -519,6 +639,15 @@ dependencies = [ "generic-array 0.12.3", ] +[[package]] +name = "dir-diff" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2860407d7d7e2e004bb2128510ad9e8d669e76fa005ccf567977b5d71b8b4a0b" +dependencies = [ + "walkdir", +] + [[package]] name = "dirs" version = "2.0.2" @@ -541,6 +670,29 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "dtoa" version = "0.4.5" @@ -583,10 +735,10 @@ dependencies = [ "enum-primitive-derive", "env_logger 0.5.13", "fnv", - "glob", + "glob 0.2.11", "indexmap", "itertools 0.7.11", - "log", + "log 0.4.8", "num-traits 0.2.11", "pretty_env_logger", "rayon", @@ -628,7 +780,7 @@ checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" dependencies = [ "atty", "humantime", - "log", + "log 0.4.8", "regex", "termcolor", ] @@ -641,7 +793,7 @@ checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", "humantime", - "log", + "log 0.4.8", "regex", "termcolor", ] @@ -674,12 +826,45 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fast-math" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2465292146cdfc2011350fe3b1c616ac83cf0faeedb33463ba1c332ed8948d66" +dependencies = [ + "ieee754", +] + [[package]] name = "feature-probe" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "filetime" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + +[[package]] +name = "flate2" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.6" @@ -750,6 +935,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +dependencies = [ + "futures", + "num_cpus", +] + [[package]] name = "futures-io" version = "0.3.4" @@ -852,6 +1047,43 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "globset" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log 0.4.8", + "regex", +] + +[[package]] +name = "h2" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "fnv", + "futures", + "http 0.1.21", + "indexmap", + "log 0.4.8", + "slab", + "string", + "tokio-io", +] + [[package]] name = "h2" version = "0.2.4" @@ -863,9 +1095,9 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.1", "indexmap", - "log", + "log 0.4.8", "slab", "tokio 0.2.15", "tokio-util", @@ -916,6 +1148,17 @@ dependencies = [ "digest 0.8.1", ] +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +dependencies = [ + "bytes 0.4.12", + "fnv", + "itoa", +] + [[package]] name = "http" version = "0.2.1" @@ -927,6 +1170,18 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +dependencies = [ + "bytes 0.4.12", + "futures", + "http 0.1.21", + "tokio-buf", +] + [[package]] name = "http-body" version = "0.3.1" @@ -934,7 +1189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.4", - "http", + "http 0.2.1", ] [[package]] @@ -952,6 +1207,55 @@ dependencies = [ "quick-error", ] +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64 0.9.3", + "httparse", + "language-tags", + "log 0.3.9", + "mime 0.2.6", + "num_cpus", + "time", + "traitobject", + "typeable", + "unicase 1.4.2", + "url 1.7.2", +] + +[[package]] +name = "hyper" +version = "0.12.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +dependencies = [ + "bytes 0.4.12", + "futures", + "futures-cpupool", + "h2 0.1.26", + "http 0.1.21", + "http-body 0.1.0", + "httparse", + "iovec", + "itoa", + "log 0.4.8", + "net2", + "rustc_version", + "time", + "tokio 0.1.22", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want 0.2.0", +] + [[package]] name = "hyper" version = "0.13.4" @@ -962,18 +1266,18 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.2.4", + "http 0.2.1", + "http-body 0.3.1", "httparse", "itoa", - "log", + "log 0.4.8", "net2", "pin-project", "time", "tokio 0.2.15", "tower-service", - "want", + "want 0.3.0", ] [[package]] @@ -985,8 +1289,8 @@ dependencies = [ "bytes 0.5.4", "ct-logs", "futures-util", - "hyper", - "log", + "hyper 0.13.4", + "log 0.4.8", "rustls", "rustls-native-certs", "tokio 0.2.15", @@ -994,6 +1298,17 @@ dependencies = [ "webpki", ] +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.2.0" @@ -1005,6 +1320,18 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ieee754" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9007da9cacbd3e6343da136e98b0d2df013f553d35bdec8b518f07bea768e19c" + +[[package]] +name = "indexed" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d480125acf340d6a6e59dab69ae19d6fca3a906e1eade277671272cc8f73794b" + [[package]] name = "indexmap" version = "1.3.2" @@ -1118,6 +1445,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpc-client-transports" +version = "14.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a9ae166c4d1f702d297cd76d4b55758ace80272ffc6dbb139fdc1bf810de40b" +dependencies = [ + "failure", + "futures", + "jsonrpc-core", + "jsonrpc-pubsub", + "log 0.4.8", + "serde", + "serde_json", + "tokio 0.1.22", + "url 1.7.2", + "websocket", +] + [[package]] name = "jsonrpc-core" version = "14.0.5" @@ -1125,31 +1470,121 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" dependencies = [ "futures", - "log", + "log 0.4.8", "serde", "serde_derive", "serde_json", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "jsonrpc-core-client" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "080dc110be17701097df238fad3c816d4a478a1899dfbcf8ec8957dd40ec7304" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "jsonrpc-client-transports", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "jsonrpc-derive" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", +] + +[[package]] +name = "jsonrpc-http-server" +version = "14.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816d63997ea45d3634608edbef83ddb35e661f7c0b27b5b72f237e321f0e9807" +dependencies = [ + "hyper 0.12.35", + "jsonrpc-core", + "jsonrpc-server-utils", + "log 0.4.8", + "net2", + "parking_lot 0.10.0", + "unicase 2.6.0", +] + +[[package]] +name = "jsonrpc-pubsub" +version = "14.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" +dependencies = [ + "jsonrpc-core", + "log 0.4.8", + "parking_lot 0.10.0", + "serde", +] + +[[package]] +name = "jsonrpc-server-utils" +version = "14.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" +dependencies = [ + "bytes 0.4.12", + "globset", + "jsonrpc-core", + "lazy_static", + "log 0.4.8", + "tokio 0.1.22", + "tokio-codec", + "unicase 2.6.0", +] + +[[package]] +name = "jsonrpc-ws-server" +version = "14.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94e5773b2ae66e0e02c80775ce6bbba6f15d5bb47c14ec36a36fcf94f8df851" +dependencies = [ + "jsonrpc-core", + "jsonrpc-server-utils", + "log 0.4.8", + "parking_lot 0.10.0", + "slab", + "ws", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ "spin", ] +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" + [[package]] name = "libc" version = "0.2.68" @@ -1166,6 +1601,18 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "librocksdb-sys" +version = "6.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3b727e2dd20ec2fb7ed93f23d9fd5328a0871185485ebdaff007b47d3e27e4" +dependencies = [ + "bindgen", + "cc", + "glob 0.3.0", + "libc", +] + [[package]] name = "linked-hash-map" version = "0.5.2" @@ -1181,6 +1628,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.8", +] + [[package]] name = "log" version = "0.4.8" @@ -1227,6 +1683,15 @@ dependencies = [ "autocfg 1.0.0", ] +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + [[package]] name = "mime" version = "0.3.16" @@ -1239,8 +1704,17 @@ version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ - "mime", - "unicase", + "mime 0.3.16", + "unicase 2.6.0", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" +dependencies = [ + "adler32", ] [[package]] @@ -1255,13 +1729,25 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log", + "log 0.4.8", "miow", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log 0.4.8", + "mio", + "slab", +] + [[package]] name = "mio-uds" version = "0.6.7" @@ -1293,7 +1779,7 @@ checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" dependencies = [ "lazy_static", "libc", - "log", + "log 0.4.8", "openssl", "openssl-probe", "openssl-sys", @@ -1327,6 +1813,27 @@ dependencies = [ "void", ] +[[package]] +name = "nom" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" +dependencies = [ + "memchr", + "version_check 0.9.1", +] + +[[package]] +name = "num-derive" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "num-derive" version = "0.3.0" @@ -1512,6 +2019,18 @@ dependencies = [ "crypto-mac", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1571,7 +2090,16 @@ dependencies = [ "ansi_term", "chrono", "env_logger 0.5.13", - "log", + "log 0.4.8", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" +dependencies = [ + "toml", ] [[package]] @@ -1873,21 +2401,21 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2" dependencies = [ - "base64", + "base64 0.11.0", "bytes 0.5.4", "encoding_rs", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 0.2.1", + "http-body 0.3.1", + "hyper 0.13.4", "hyper-rustls", "js-sys", "lazy_static", - "log", - "mime", + "log 0.4.8", + "mime 0.3.16", "mime_guess", - "percent-encoding", + "percent-encoding 2.1.0", "pin-project-lite", "rustls", "serde", @@ -1896,7 +2424,7 @@ dependencies = [ "time", "tokio 0.2.15", "tokio-rustls", - "url", + "url 2.1.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1919,6 +2447,16 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "rocksdb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12069b106981c6103d3eab7dd1c86751482d0779a520b7c14954c8b586c1e643" +dependencies = [ + "libc", + "librocksdb-sys", +] + [[package]] name = "rpassword" version = "4.0.5" @@ -1935,7 +2473,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" dependencies = [ - "base64", + "base64 0.11.0", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -1968,8 +2506,8 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" dependencies = [ - "base64", - "log", + "base64 0.11.0", + "log 0.4.8", "ring", "sct", "webpki", @@ -1993,6 +2531,21 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.18" @@ -2106,7 +2659,7 @@ dependencies = [ "dtoa", "itoa", "serde", - "url", + "url 2.1.1", ] [[package]] @@ -2133,6 +2686,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" + [[package]] name = "sha2" version = "0.7.1" @@ -2157,6 +2716,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + [[package]] name = "slab" version = "0.4.2" @@ -2190,6 +2755,22 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "solana-archiver-utils" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d977c442df5ddc0394bfce5ec123d4d02f2e2f89529f3348e343e9a8ac1af0e" +dependencies = [ + "log 0.4.8", + "rand 0.6.5", + "solana-chacha", + "solana-chacha-sys", + "solana-ledger", + "solana-logger", + "solana-perf", + "solana-sdk", +] + [[package]] name = "solana-bpf-loader-program" version = "1.1.1" @@ -2199,8 +2780,8 @@ dependencies = [ "bincode", "byteorder", "libc", - "log", - "num-derive", + "log 0.4.8", + "num-derive 0.3.0", "num-traits 0.2.11", "solana-logger", "solana-sdk", @@ -2208,6 +2789,63 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-budget-program" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "720589429e231f12ccb605d6bfc9a155c8992bcac16e627900065c4e4e2272fa" +dependencies = [ + "bincode", + "chrono", + "log 0.4.8", + "num-derive 0.3.0", + "num-traits 0.2.11", + "serde", + "serde_derive", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-chacha" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76dd09ae00d0805c56fce4e79973e5e85947cf69d8f69de709e82d5886e29cb" +dependencies = [ + "log 0.4.8", + "rand 0.6.5", + "rand_chacha 0.1.1", + "solana-chacha-sys", + "solana-ledger", + "solana-logger", + "solana-perf", + "solana-sdk", +] + +[[package]] +name = "solana-chacha-cuda" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab6ab1b5366c7d94a79273dddf818a1e662e827b73ee317b7a8107361a665f8" +dependencies = [ + "log 0.4.8", + "solana-archiver-utils", + "solana-chacha", + "solana-ledger", + "solana-logger", + "solana-perf", + "solana-sdk", +] + +[[package]] +name = "solana-chacha-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2284a0fda7139e027780e97f507b1ff214fe4a578413f7337a8762f73bafcdb" +dependencies = [ + "cc", +] + [[package]] name = "solana-clap-utils" version = "1.1.1" @@ -2221,7 +2859,7 @@ dependencies = [ "solana-sdk", "thiserror", "tiny-bip39", - "url", + "url 2.1.1", ] [[package]] @@ -2235,7 +2873,7 @@ dependencies = [ "serde", "serde_derive", "serde_yaml", - "url", + "url 2.1.1", ] [[package]] @@ -2248,7 +2886,7 @@ dependencies = [ "bs58", "indicatif", "jsonrpc-core", - "log", + "log 0.4.8", "rayon", "reqwest", "serde", @@ -2260,7 +2898,7 @@ dependencies = [ "solana-vote-program", "thiserror", "tungstenite", - "url", + "url 2.1.1", ] [[package]] @@ -2271,11 +2909,76 @@ checksum = "d3848abb2b3f662aa107df2a3b1c918d01edc57302bd2d1c5c24b279acabdbc9" dependencies = [ "bincode", "chrono", - "log", + "log 0.4.8", + "serde", + "serde_derive", + "solana-logger", + "solana-sdk", +] + +[[package]] +name = "solana-core" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5706919c6e60471f38d0dea5b8355980740c0401ccf2ce5910225139b58e318c" +dependencies = [ + "bincode", + "bs58", + "bv", + "byteorder", + "chrono", + "core_affinity", + "crossbeam-channel", + "ed25519-dalek", + "flate2", + "fs_extra", + "indexmap", + "itertools 0.9.0", + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "jsonrpc-http-server", + "jsonrpc-pubsub", + "jsonrpc-ws-server", + "log 0.4.8", + "num-traits 0.2.11", + "num_cpus", + "rand 0.6.5", + "rand_chacha 0.1.1", + "rayon", + "regex", "serde", "serde_derive", + "serde_json", + "solana-budget-program", + "solana-chacha-cuda", + "solana-clap-utils", + "solana-client", + "solana-faucet", + "solana-ledger", "solana-logger", + "solana-measure", + "solana-merkle-tree", + "solana-metrics", + "solana-net-utils", + "solana-perf", + "solana-rayon-threadlimit", + "solana-runtime", "solana-sdk", + "solana-stake-program", + "solana-storage-program", + "solana-streamer", + "solana-sys-tuner", + "solana-transaction-status", + "solana-vote-program", + "solana-vote-signer", + "tempfile", + "thiserror", + "tokio 0.1.22", + "tokio-codec", + "tokio-fs", + "tokio-io", + "trees", ] [[package]] @@ -2304,29 +3007,143 @@ dependencies = [ ] [[package]] -name = "solana-logger" +name = "solana-exchange-program" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ba3abed8ca3ab5e5148594452f8d65def958e71ee3aaebbf896ea6fe543c74" +checksum = "6b9831322edce9493d2ddad4de2e7825f4952c483009f92330ad41d5d1b3bef5" dependencies = [ - "env_logger 0.7.1", - "lazy_static", - "log", -] - -[[package]] -name = "solana-measure" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3dbf5afbbe452109662eb95159078ec9879313a5ccd57f4bba726768051b9f3" + "bincode", + "log 0.4.8", + "num-derive 0.3.0", + "num-traits 0.2.11", + "serde", + "serde_derive", + "solana-logger", + "solana-metrics", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-faucet" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "262652d7ca6a87d12deedb85546c245ea718c50829858675967a289731659ba8" +dependencies = [ + "bincode", + "byteorder", + "bytes 0.4.12", + "clap", + "log 0.4.8", + "serde", + "serde_derive", + "solana-clap-utils", + "solana-logger", + "solana-metrics", + "solana-sdk", + "tokio 0.1.22", + "tokio-codec", +] + +[[package]] +name = "solana-genesis-programs" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb138971f747fd6ac174bc78965957a48d214c4864948fa8c98b0b6806e96da1" +dependencies = [ + "log 0.4.8", + "solana-bpf-loader-program", + "solana-budget-program", + "solana-config-program", + "solana-exchange-program", + "solana-runtime", + "solana-sdk", + "solana-stake-program", + "solana-storage-program", + "solana-vest-program", + "solana-vote-program", +] + +[[package]] +name = "solana-ledger" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac9ced3edf5bfbeef7abe976a08cbad495c80aad44b7c86213c8ab1c2cc9ac3" +dependencies = [ + "bincode", + "byteorder", + "bzip2", + "chrono", + "crossbeam-channel", + "dir-diff", + "ed25519-dalek", + "fs_extra", + "itertools 0.9.0", + "lazy_static", + "libc", + "log 0.4.8", + "num_cpus", + "rand 0.6.5", + "rand_chacha 0.1.1", + "rayon", + "regex", + "rocksdb", + "serde", + "serde_bytes", + "sha2 0.8.1", + "solana-genesis-programs", + "solana-logger", + "solana-measure", + "solana-merkle-tree", + "solana-metrics", + "solana-perf", + "solana-rayon-threadlimit", + "solana-reed-solomon-erasure", + "solana-runtime", + "solana-sdk", + "solana-stake-program", + "solana-transaction-status", + "solana-vote-program", + "symlink", + "tar", + "tempfile", + "thiserror", +] + +[[package]] +name = "solana-logger" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5ba3abed8ca3ab5e5148594452f8d65def958e71ee3aaebbf896ea6fe543c74" +dependencies = [ + "env_logger 0.7.1", + "lazy_static", + "log 0.4.8", +] + +[[package]] +name = "solana-measure" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3dbf5afbbe452109662eb95159078ec9879313a5ccd57f4bba726768051b9f3" dependencies = [ "jemalloc-ctl", "jemallocator", - "log", + "log 0.4.8", "solana-metrics", "solana-sdk", ] +[[package]] +name = "solana-merkle-tree" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636e855d8fc4969e7d87a0bc6b4ce8d3a2c9961e32af12af8665cff826e31f94" +dependencies = [ + "fast-math", + "solana-sdk", +] + [[package]] name = "solana-metrics" version = "1.1.1" @@ -2336,7 +3153,7 @@ dependencies = [ "env_logger 0.7.1", "gethostname", "lazy_static", - "log", + "log 0.4.8", "reqwest", "solana-sdk", ] @@ -2350,7 +3167,7 @@ dependencies = [ "bincode", "bytes 0.4.12", "clap", - "log", + "log 0.4.8", "nix", "rand 0.6.5", "serde", @@ -2362,6 +3179,27 @@ dependencies = [ "tokio-codec", ] +[[package]] +name = "solana-perf" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0e5de2e96f3757c8996a1f57b127e4d7c57b5d233dc1ff8583b73a7f2f765e" +dependencies = [ + "bincode", + "dlopen", + "dlopen_derive", + "lazy_static", + "log 0.4.8", + "rand 0.6.5", + "rayon", + "serde", + "solana-budget-program", + "solana-logger", + "solana-metrics", + "solana-rayon-threadlimit", + "solana-sdk", +] + [[package]] name = "solana-rayon-threadlimit" version = "1.1.1" @@ -2372,6 +3210,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "solana-reed-solomon-erasure" +version = "4.0.1-3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5b3ab3f4dd12af687a7d0d0ee73299cbc06ed3aada42dccac26fe243e73399e" +dependencies = [ + "cc", + "libc", + "smallvec 0.6.13", +] + [[package]] name = "solana-remote-wallet" version = "1.1.1" @@ -2382,12 +3231,12 @@ dependencies = [ "console", "dialoguer", "hidapi", - "log", + "log 0.4.8", "parking_lot 0.10.0", "semver", "solana-sdk", "thiserror", - "url", + "url 2.1.1", ] [[package]] @@ -2405,9 +3254,9 @@ dependencies = [ "lazy_static", "libc", "libloading", - "log", + "log 0.4.8", "memmap", - "num-derive", + "num-derive 0.3.0", "num-traits 0.2.11", "num_cpus", "rand 0.6.5", @@ -2444,9 +3293,9 @@ dependencies = [ "hex", "hmac", "itertools 0.9.0", - "log", + "log 0.4.8", "memmap", - "num-derive", + "num-derive 0.3.0", "num-traits 0.2.11", "pbkdf2", "rand 0.6.5", @@ -2481,8 +3330,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e86a7b234809e2961b51e9959517994610449abf858cb448e9d0e31cafca011" dependencies = [ "bincode", - "log", - "num-derive", + "log 0.4.8", + "num-derive 0.3.0", "num-traits 0.2.11", "serde", "serde_derive", @@ -2501,8 +3350,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d9ef9f07f6dfb8be7915f5693767b977449c0d2e7e0ebb9c33c7014c3ea576" dependencies = [ "bincode", - "log", - "num-derive", + "log 0.4.8", + "num-derive 0.3.0", "num-traits 0.2.11", "rand 0.6.5", "serde", @@ -2511,6 +3360,40 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-streamer" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434523f36a621ac4a5578ebce912e321d1691830dd9b45362dea5c46699a4334" +dependencies = [ + "libc", + "log 0.4.8", + "nix", + "solana-logger", + "solana-measure", + "solana-metrics", + "solana-perf", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-sys-tuner" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b9e38ed20e3cbe4c9560c50d7c64bbb995bccc7819f6f974bbb392de4d0d30b" +dependencies = [ + "clap", + "libc", + "log 0.4.8", + "nix", + "solana-clap-utils", + "solana-logger", + "sysctl", + "unix_socket2", + "users", +] + [[package]] name = "solana-tokens" version = "0.1.0" @@ -2523,10 +3406,13 @@ dependencies = [ "solana-clap-utils", "solana-cli-config", "solana-client", + "solana-core", + "solana-faucet", "solana-remote-wallet", "solana-runtime", "solana-sdk", "solana-stake-program", + "tempfile", ] [[package]] @@ -2542,6 +3428,23 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-vest-program" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973676dfd4c97e50653ed15c1780d588d4299c661f3c55e877e814011ee7cb93" +dependencies = [ + "bincode", + "chrono", + "num-derive 0.2.5", + "num-traits 0.2.11", + "serde", + "serde_derive", + "solana-config-program", + "solana-sdk", + "thiserror", +] + [[package]] name = "solana-vote-program" version = "1.1.1" @@ -2549,8 +3452,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "142ad2d760e25fb055c0365ae837ee8bcd649d9a956188b14c38f2f365ab4260" dependencies = [ "bincode", - "log", - "num-derive", + "log 0.4.8", + "num-derive 0.3.0", "num-traits 0.2.11", "serde", "serde_derive", @@ -2560,6 +3463,23 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-vote-signer" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1085162747e53b3b46fe14f00b4de4527cf640eb242df12a5ad858e2290eed39" +dependencies = [ + "clap", + "jsonrpc-core", + "jsonrpc-derive", + "jsonrpc-http-server", + "log 0.4.8", + "serde_json", + "solana-clap-utils", + "solana-metrics", + "solana-sdk", +] + [[package]] name = "solana_rbpf" version = "0.1.25" @@ -2571,7 +3491,7 @@ dependencies = [ "elfkit", "hash32", "libc", - "log", + "log 0.4.8", "num-traits 0.2.11", "thiserror", "time", @@ -2583,6 +3503,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +dependencies = [ + "bytes 0.4.12", +] + [[package]] name = "strsim" version = "0.8.0" @@ -2601,6 +3530,12 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + [[package]] name = "syn" version = "0.11.11" @@ -2655,6 +3590,31 @@ dependencies = [ "unicode-xid 0.2.0", ] +[[package]] +name = "sysctl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0501f0d0c2aa64b419abff97c209f4b82c4e67caa63e8dc5b222ecc1b574cb5c" +dependencies = [ + "bitflags", + "byteorder", + "failure", + "libc", + "walkdir", +] + +[[package]] +name = "tar" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3196bfbffbba3e57481b6ea32249fbaf590396a52505a2615adbb79d9d826d3" +dependencies = [ + "filetime", + "libc", + "redox_syscall", + "xattr", +] + [[package]] name = "tempfile" version = "3.1.0" @@ -2794,6 +3754,17 @@ dependencies = [ "slab", ] +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +dependencies = [ + "bytes 0.4.12", + "either", + "futures", +] + [[package]] name = "tokio-codec" version = "0.1.2" @@ -2844,7 +3815,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures", - "log", + "log 0.4.8", ] [[package]] @@ -2856,7 +3827,7 @@ dependencies = [ "crossbeam-utils", "futures", "lazy_static", - "log", + "log 0.4.8", "mio", "num_cpus", "parking_lot 0.9.0", @@ -2913,7 +3884,7 @@ dependencies = [ "crossbeam-utils", "futures", "lazy_static", - "log", + "log 0.4.8", "num_cpus", "slab", "tokio-executor", @@ -2931,6 +3902,17 @@ dependencies = [ "tokio-executor", ] +[[package]] +name = "tokio-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +dependencies = [ + "futures", + "native-tls", + "tokio-io", +] + [[package]] name = "tokio-udp" version = "0.1.6" @@ -2939,7 +3921,7 @@ checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", "futures", - "log", + "log 0.4.8", "mio", "tokio-codec", "tokio-io", @@ -2956,7 +3938,7 @@ dependencies = [ "futures", "iovec", "libc", - "log", + "log 0.4.8", "mio", "mio-uds", "tokio-codec", @@ -2973,17 +3955,41 @@ dependencies = [ "bytes 0.5.4", "futures-core", "futures-sink", - "log", + "log 0.4.8", "pin-project-lite", "tokio 0.2.15", ] +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "trees" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa1821e85be4f56cc5bd08bdbc32c0e26d105c90bed9c637992f6c7f747c180" +dependencies = [ + "indexed", +] + [[package]] name = "try-lock" version = "0.2.2" @@ -2996,33 +4002,48 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" dependencies = [ - "base64", + "base64 0.11.0", "byteorder", "bytes 0.5.4", - "http", + "http 0.2.1", "httparse", "input_buffer", - "log", + "log 0.4.8", "native-tls", "rand 0.7.3", "sha-1", - "url", + "url 2.1.1", "utf-8", ] +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + [[package]] name = "typenum" version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check 0.1.5", +] + [[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check", + "version_check 0.9.1", ] [[package]] @@ -3067,21 +4088,50 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +[[package]] +name = "unix_socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b57c6eace16c00eccb98a28e85db3370eab0685bdd5e13831d59e2bcb49a1d8a" +dependencies = [ + "libc", +] + [[package]] name = "untrusted" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna", + "idna 0.2.0", "matches", - "percent-encoding", + "percent-encoding 2.1.0", +] + +[[package]] +name = "users" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72f4267aea0c3ec6d07eaabea6ead7c5ddacfafc5e22bcf8d186706851fb4cf" +dependencies = [ + "libc", ] [[package]] @@ -3102,6 +4152,12 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + [[package]] name = "version_check" version = "0.9.1" @@ -3114,13 +4170,35 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi 0.3.8", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +dependencies = [ + "futures", + "log 0.4.8", + "try-lock", +] + [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log", + "log 0.4.8", "try-lock", ] @@ -3150,7 +4228,7 @@ checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" dependencies = [ "bumpalo", "lazy_static", - "log", + "log 0.4.8", "proc-macro2 1.0.10", "quote 1.0.3", "syn 1.0.17", @@ -3227,6 +4305,56 @@ dependencies = [ "webpki", ] +[[package]] +name = "websocket" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413b37840b9e27b340ce91b319ede10731de8c72f5bc4cb0206ec1ca4ce581d0" +dependencies = [ + "bytes 0.4.12", + "futures", + "hyper 0.10.16", + "native-tls", + "rand 0.6.5", + "tokio-codec", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-tls", + "unicase 1.4.2", + "url 1.7.2", + "websocket-base", +] + +[[package]] +name = "websocket-base" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e3810f0d00c4dccb54c30a4eee815e703232819dec7b007db115791c42aa374" +dependencies = [ + "base64 0.10.1", + "bitflags", + "byteorder", + "bytes 0.4.12", + "futures", + "native-tls", + "rand 0.6.5", + "sha1", + "tokio-codec", + "tokio-io", + "tokio-tcp", + "tokio-tls", +] + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + [[package]] name = "winapi" version = "0.2.8" @@ -3279,6 +4407,24 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "ws" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "httparse", + "log 0.4.8", + "mio", + "mio-extras", + "rand 0.7.3", + "sha-1", + "slab", + "url 2.1.1", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -3289,6 +4435,15 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] + [[package]] name = "yaml-rust" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 14f1f464bf1260..3d2c7024ea0141 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,10 @@ serde = { version = "1.0", features = ["derive"] } solana-clap-utils = "1.1.1" solana-cli-config = "1.1.1" solana-client = "1.1.1" +solana-core = "1.1.1" +solana-faucet = "1.1.1" solana-remote-wallet = "1.1.1" solana-runtime = "1.1.1" solana-sdk = "1.1.1" solana-stake-program = "1.1.1" +tempfile = "3.1.0" diff --git a/README.md b/README.md index e886616ccc9f70..b8bddaf7c16e90 100644 --- a/README.md +++ b/README.md @@ -5,36 +5,28 @@ The user will have a spreadsheet listing public keys and token amounts, and some process for transferring tokens to them, and ensuring that no more than the expected amount are sent. The command-line tool here automates that process. -## Calculate what tokens should be sent - -List the differences between a list of expected distributions and the record of what -transactions have already been sent. +## Distribute tokens -```bash -solana-tokens distribute --dollars-per-sol --dry-run -``` +Send tokens to the recipients in ``. Example allocations.csv: ```text primary_address,bid_amount_dollars 6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,6.6 -6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,15.4 -3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM,9.24 -UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k,9.46 ``` -Example output: +```bash +solana-tokens distribute --from --dollars-per-sol --fee-payer +``` + +Example transaction log before: ```text -Recipient Amount -6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv 70 -3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM 42 -UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 +recipient,amount,signature +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,30,1111111111111111111111111111111111111111111111111111111111111111 ``` -## Distribute tokens - Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. @@ -51,12 +43,6 @@ Recipient Amount UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 ``` -Example transaction log before: - -```text -recipient,amount,signature -6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,30,orig -``` Example transaction log after: @@ -67,3 +53,32 @@ recipient,amount,signature 3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM,42,1111111111111111111111111111111111111111111111111111111111111111 UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k,43,1111111111111111111111111111111111111111111111111111111111111111 ``` + +## Calculate what tokens should be sent + +List the differences between a list of expected distributions and the record of what +transactions have already been sent. + +```bash +solana-tokens distribute --dollars-per-sol --dry-run +``` + +Example allocations.csv: + +```text +primary_address,bid_amount_dollars +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,6.6 +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,15.4 +3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM,9.24 +UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k,9.46 +``` + +Example output: + +```text +Recipient Amount +6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv 70 +3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM 42 +UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 +``` + diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 325a0bbbe4a455..a310aa953fea2d 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -5,7 +5,7 @@ use solana_cli_config::CONFIG_FILE; use std::ffi::OsString; use std::process::exit; -pub(crate) fn get_matches<'a, I, T>(args: I) -> ArgMatches<'a> +fn get_matches<'a, I, T>(args: I) -> ArgMatches<'a> where I: IntoIterator, T: Into + Clone, @@ -93,7 +93,7 @@ fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { } } -pub(crate) fn parse_args(args: I) -> Args +pub fn parse_args(args: I) -> Args where I: IntoIterator, T: Into + Clone, diff --git a/src/args.rs b/src/args.rs index 5ba4d49079e2cd..38a07381636952 100644 --- a/src/args.rs +++ b/src/args.rs @@ -4,7 +4,7 @@ use solana_remote_wallet::remote_wallet::maybe_wallet_manager; use solana_sdk::signature::Signer; use std::error::Error; -pub(crate) struct DistributeArgs { +pub struct DistributeArgs { pub allocations_csv: String, pub transactions_csv: String, pub dollars_per_sol: f64, @@ -13,17 +13,17 @@ pub(crate) struct DistributeArgs { pub fee_payer: Option, } -pub(crate) enum Command { +pub enum Command { Distribute(DistributeArgs), } -pub(crate) struct Args { +pub struct Args { pub config_file: String, pub url: Option, pub command: Command, } -pub(crate) fn resolve_command( +pub fn resolve_command( command: &Command, ) -> Result>, Box> { match command { diff --git a/src/main.rs b/src/main.rs index 5bb4b370680bac..1875e417d89b23 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,11 @@ -mod arg_parser; -mod args; -mod thin_client; -mod tokens; - -use crate::arg_parser::parse_args; -use crate::args::{resolve_command, Command}; -use crate::thin_client::ThinClient; -use crate::tokens::process_distribute; use solana_cli_config::Config; use solana_client::rpc_client::RpcClient; +use solana_tokens::{ + arg_parser::parse_args, + args::{resolve_command, Command}, + thin_client::ThinClient, + tokens::process_distribute, +}; use std::env; use std::error::Error; diff --git a/src/thin_client.rs b/src/thin_client.rs index b840bbdf70e14a..3a3cb5f2452bf0 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -1,8 +1,13 @@ use solana_client::rpc_client::RpcClient; use solana_runtime::bank_client::BankClient; -use solana_sdk::client::SyncClient; use solana_sdk::{ - message::Message, signature::Signature, signers::Signers, transaction::Transaction, + client::SyncClient, + message::Message, + pubkey::Pubkey, + signature::{Signature, Signer}, + signers::Signers, + system_instruction, + transaction::Transaction, transport::TransportError, }; @@ -12,6 +17,8 @@ pub trait Client { message: Message, signers: &S, ) -> Result; + + fn get_balance1(&self, pubkey: &Pubkey) -> Result; } impl Client for RpcClient { @@ -28,6 +35,13 @@ impl Client for RpcClient { .map_err(|e| TransportError::Custom(e.to_string()))?; Ok(signature) } + + fn get_balance1(&self, pubkey: &Pubkey) -> Result { + let balance = self + .get_balance(pubkey) + .map_err(|e| TransportError::Custom(e.to_string()))?; + Ok(balance) + } } impl Client for BankClient { @@ -38,6 +52,10 @@ impl Client for BankClient { ) -> Result { self.send_message(signers, message) } + + fn get_balance1(&self, pubkey: &Pubkey) -> Result { + self.get_balance(pubkey) + } } impl Client for () { @@ -48,10 +66,28 @@ impl Client for () { ) -> Result { Ok(Signature::default()) } + + fn get_balance1(&self, _pubkey: &Pubkey) -> Result { + Ok(0) + } } pub struct ThinClient(pub C); +impl ThinClient { + pub fn transfer( + &self, + lamports: u64, + sender_keypair: &S, + to_pubkey: &Pubkey, + ) -> Result { + let create_instruction = + system_instruction::transfer(&sender_keypair.pubkey(), &to_pubkey, lamports); + let message = Message::new(&[create_instruction]); + self.send_message(message, &[sender_keypair]) + } +} + impl ThinClient { pub fn send_message( &self, @@ -60,4 +96,8 @@ impl ThinClient { ) -> Result { self.0.send_and_confirm_message(message, signers) } + + pub fn get_balance(&self, pubkey: &Pubkey) -> Result { + self.0.get_balance1(pubkey) + } } diff --git a/src/tokens.rs b/src/tokens.rs index c4b7c8959f6fb3..5e442f0781a301 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -14,7 +14,7 @@ use solana_sdk::{ use std::fs; use std::path::Path; -#[derive(Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { bid_amount_dollars: f64, primary_address: String, @@ -72,11 +72,13 @@ fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { amount: bid.bid_amount_dollars / dollars_per_sol, } } + fn distribute_tokens( client: &ThinClient, allocations: &[Allocation], args: &DistributeArgs>, ) -> Vec> { + let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); let messages: Vec = allocations .iter() .map(|allocation| { @@ -85,7 +87,7 @@ fn distribute_tokens( let to = allocation.recipient.parse().unwrap(); let lamports = sol_to_lamports(allocation.amount); let instruction = system_instruction::transfer(&from, &to, lamports); - Message::new(&[instruction]) + Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)) }) .collect(); @@ -100,6 +102,14 @@ fn distribute_tokens( .collect() } +fn read_transaction_infos(path: &str) -> Vec { + let mut rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&path) + .unwrap(); + rdr.deserialize().map(|x| x.unwrap()).collect() +} + fn append_transaction_infos( allocations: &[Allocation], results: &[Result], @@ -138,7 +148,7 @@ fn append_transaction_infos( Ok(()) } -pub(crate) fn process_distribute( +pub fn process_distribute( client: &ThinClient, args: &DistributeArgs>, ) -> Result<(), csv::Error> { @@ -151,10 +161,7 @@ pub(crate) fn process_distribute( .collect(); let transaction_infos: Vec = if Path::new(&args.transactions_csv).exists() { - let mut state_rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.transactions_csv)?; - state_rdr.deserialize().map(|x| x.unwrap()).collect() + read_transaction_infos(&args.transactions_csv) } else { vec![] }; @@ -178,3 +185,83 @@ pub(crate) fn process_distribute( Ok(()) } + +use solana_sdk::{pubkey::Pubkey, signature::Keypair}; +use tempfile::{tempdir, NamedTempFile}; +pub fn test_process_distribute_with_client( + thin_client: &ThinClient, + sender_keypair: Keypair, +) { + let fee_payer = Keypair::new(); + thin_client + .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) + .unwrap(); + + let alice_pubkey = Pubkey::new_rand(); + let bid = Bid { + primary_address: alice_pubkey.to_string(), + bid_amount_dollars: 1000.0, + }; + let allocations_file = NamedTempFile::new().unwrap(); + let allocations_csv = allocations_file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(allocations_file); + wtr.serialize(&bid).unwrap(); + wtr.flush().unwrap(); + + let dir = tempdir().unwrap(); + let transactions_csv = dir + .path() + .join("transactions.csv") + .to_str() + .unwrap() + .to_string(); + + let args: DistributeArgs> = DistributeArgs { + sender_keypair: Some(Box::new(sender_keypair)), + fee_payer: Some(Box::new(fee_payer)), + dry_run: false, + allocations_csv, + transactions_csv: transactions_csv.clone(), + dollars_per_sol: 0.22, + }; + process_distribute(&thin_client, &args).unwrap(); + let transaction_infos = read_transaction_infos(&transactions_csv); + assert_eq!(transaction_infos.len(), 1); + assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + let expected_amount = bid.bid_amount_dollars / args.dollars_per_sol; + assert_eq!(transaction_infos[0].amount, expected_amount); + + assert_eq!( + thin_client.get_balance(&alice_pubkey).unwrap(), + sol_to_lamports(expected_amount), + ); + + // Now, run it again, and check there's no double-spend. + process_distribute(&thin_client, &args).unwrap(); + let transaction_infos = read_transaction_infos(&transactions_csv); + assert_eq!(transaction_infos.len(), 1); + assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + let expected_amount = bid.bid_amount_dollars / args.dollars_per_sol; + assert_eq!(transaction_infos[0].amount, expected_amount); + + assert_eq!( + thin_client.get_balance(&alice_pubkey).unwrap(), + sol_to_lamports(expected_amount), + ); +} + +#[cfg(test)] +mod tests { + use super::*; + use solana_runtime::{bank::Bank, bank_client::BankClient}; + use solana_sdk::genesis_config::create_genesis_config; + + #[test] + fn test_process_distribute() { + let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); + let bank = Bank::new(&genesis_config); + let bank_client = BankClient::new(bank); + let thin_client = ThinClient(bank_client); + test_process_distribute_with_client(&thin_client, sender_keypair); + } +} From 93117f2f34c0e60a20309f45aee3867235997211 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 15:19:28 -0600 Subject: [PATCH 19/71] Add integration test --- tests/tokens.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/tokens.rs diff --git a/tests/tokens.rs b/tests/tokens.rs new file mode 100644 index 00000000000000..653fbb70279955 --- /dev/null +++ b/tests/tokens.rs @@ -0,0 +1,31 @@ +use solana_client::rpc_client::RpcClient; +use solana_core::validator::TestValidator; +use solana_faucet::faucet::{request_airdrop_transaction, run_local_faucet}; +use solana_sdk::{ + native_token::sol_to_lamports, + signature::{Keypair, Signer}, +}; +use solana_tokens::{thin_client::ThinClient, tokens::test_process_distribute_with_client}; +use std::sync::mpsc::channel; + +#[test] +fn test_process_distribute_with_rpc_client() { + let validator = TestValidator::run(); + let (sender, receiver) = channel(); + run_local_faucet(validator.alice, sender, None); + let faucet_addr = receiver.recv().unwrap(); + + let rpc_client = RpcClient::new_socket(validator.leader_data.rpc); + let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash().unwrap(); + let funding_keypair = Keypair::new(); + let lamports = sol_to_lamports(9_000_000.0); + let mut transaction = + request_airdrop_transaction(&faucet_addr, &funding_keypair.pubkey(), lamports, blockhash) + .unwrap(); + rpc_client + .send_and_confirm_transaction_with_spinner(&mut transaction, &[&funding_keypair]) + .unwrap(); + + let thin_client = ThinClient(rpc_client); + test_process_distribute_with_client(&thin_client, funding_keypair); +} From e85e80a003f7f1c7c2baa2ede93432babb8cb2c4 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 15:56:53 -0600 Subject: [PATCH 20/71] Add metrics --- src/tokens.rs | 26 ++++++++++++++++++++++++++ tests/tokens.rs | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/tokens.rs b/src/tokens.rs index 5e442f0781a301..2073d59d2fcc49 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -165,9 +165,35 @@ pub fn process_distribute( } else { vec![] }; + + let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); + println!( + "{} â—Ž{}", + style(format!("{}", "Total in allocations_csv:")).bold(), + starting_total_tokens + ); + let mut allocations = merge_allocations(&allocations); apply_previous_transactions(&mut allocations, &transaction_infos); + let distributed_tokens: f64 = transaction_infos.iter().map(|x| x.amount).sum(); + let undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); + println!( + "{} â—Ž{}", + style(format!("{}", "Distributed:")).bold(), + distributed_tokens + ); + println!( + "{} â—Ž{}", + style(format!("{}", "Undistributed:")).bold(), + undistributed_tokens + ); + println!( + "{} â—Ž{}\n", + style(format!("{}", "Total:")).bold(), + distributed_tokens + undistributed_tokens + ); + if allocations.is_empty() { eprintln!("No work to do"); return Ok(()); diff --git a/tests/tokens.rs b/tests/tokens.rs index 653fbb70279955..b70f57d6c2a7df 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -18,7 +18,7 @@ fn test_process_distribute_with_rpc_client() { let rpc_client = RpcClient::new_socket(validator.leader_data.rpc); let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash().unwrap(); let funding_keypair = Keypair::new(); - let lamports = sol_to_lamports(9_000_000.0); + let lamports = 1_000; let mut transaction = request_airdrop_transaction(&faucet_addr, &funding_keypair.pubkey(), lamports, blockhash) .unwrap(); From 5d80ec0ada8baacfe13522e1167afa2a204f3029 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 16:18:00 -0600 Subject: [PATCH 21/71] Use RpcClient in dry-run, just don't send messages --- src/main.rs | 8 ++------ src/tokens.rs | 8 +++++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1875e417d89b23..0973f26168c1ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,12 +15,8 @@ fn main() -> Result<(), Box> { match resolve_command(&command_args.command)? { Command::Distribute(args) => { - let client = if args.dry_run { - () - } else { - let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); - RpcClient::new(json_rpc_url); - }; + let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); + let client = RpcClient::new(json_rpc_url); let thin_client = ThinClient(client); process_distribute(&thin_client, &args)?; } diff --git a/src/tokens.rs b/src/tokens.rs index 2073d59d2fcc49..d34d261aeb914a 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -98,7 +98,13 @@ fn distribute_tokens( messages .into_iter() - .map(|message| client.send_message(message, &signers)) + .map(|message| { + if args.dry_run { + Ok(Signature::default()) + } else { + client.send_message(message, &signers) + } + }) .collect() } From 0cf5c8c855d6e0a6bbe008c3f9fecc4b2f457c32 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 16:33:42 -0600 Subject: [PATCH 22/71] More metrics --- src/tokens.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index d34d261aeb914a..5c1d1dbe1a188e 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -161,9 +161,17 @@ pub fn process_distribute( let mut rdr = ReaderBuilder::new() .trim(Trim::All) .from_path(&args.allocations_csv)?; - let allocations: Vec = rdr - .deserialize() - .map(|bid| create_allocation(&bid.unwrap(), args.dollars_per_sol)) + let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); + let starting_total_dollars: f64 = bids.iter().map(|x| x.bid_amount_dollars).sum(); + println!( + "{} ${}", + style(format!("{}", "Total in allocations_csv:")).bold(), + starting_total_dollars + ); + + let allocations: Vec = bids + .into_iter() + .map(|bid| create_allocation(&bid, args.dollars_per_sol)) .collect(); let transaction_infos: Vec = if Path::new(&args.transactions_csv).exists() { From 6c9821d9d0df53c02c099b42dc37f40329654227 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 16:57:16 -0600 Subject: [PATCH 23/71] Fix dry run with no keys --- src/tokens.rs | 30 +++++++++++++++++------------- tests/tokens.rs | 6 ++---- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 5c1d1dbe1a188e..7cf0eeca666784 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -78,8 +78,22 @@ fn distribute_tokens( allocations: &[Allocation], args: &DistributeArgs>, ) -> Vec> { - let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); - let messages: Vec = allocations + let fee_payer_pubkey = if args.dry_run { + Pubkey::default() + } else { + args.fee_payer.as_ref().unwrap().pubkey() + }; + + let signers = if args.dry_run { + vec![] + } else { + vec![ + &**args.sender_keypair.as_ref().unwrap(), + &**args.fee_payer.as_ref().unwrap(), + ] + }; + + allocations .iter() .map(|allocation| { println!("{:<44} {}", allocation.recipient, allocation.amount); @@ -87,18 +101,8 @@ fn distribute_tokens( let to = allocation.recipient.parse().unwrap(); let lamports = sol_to_lamports(allocation.amount); let instruction = system_instruction::transfer(&from, &to, lamports); - Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)) - }) - .collect(); + let message = Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)); - let signers = vec![ - &**args.sender_keypair.as_ref().unwrap(), - &**args.fee_payer.as_ref().unwrap(), - ]; - - messages - .into_iter() - .map(|message| { if args.dry_run { Ok(Signature::default()) } else { diff --git a/tests/tokens.rs b/tests/tokens.rs index b70f57d6c2a7df..3c5f96c31f46bc 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,14 +1,12 @@ use solana_client::rpc_client::RpcClient; use solana_core::validator::TestValidator; use solana_faucet::faucet::{request_airdrop_transaction, run_local_faucet}; -use solana_sdk::{ - native_token::sol_to_lamports, - signature::{Keypair, Signer}, -}; +use solana_sdk::signature::{Keypair, Signer}; use solana_tokens::{thin_client::ThinClient, tokens::test_process_distribute_with_client}; use std::sync::mpsc::channel; #[test] +#[ignore] fn test_process_distribute_with_rpc_client() { let validator = TestValidator::run(); let (sender, receiver) = channel(); From 0b421b0e37b6fdff22605f6fd8dd15fd4fed22ad Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 17:17:44 -0600 Subject: [PATCH 24/71] Only require one approval if fee-payer is the sender keypair --- src/tokens.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 7cf0eeca666784..00bfa6cb071474 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -87,10 +87,11 @@ fn distribute_tokens( let signers = if args.dry_run { vec![] } else { - vec![ - &**args.sender_keypair.as_ref().unwrap(), - &**args.fee_payer.as_ref().unwrap(), - ] + let mut signers = vec![&**args.sender_keypair.as_ref().unwrap()]; + if args.sender_keypair != args.fee_payer { + signers.push(&**args.fee_payer.as_ref().unwrap()); + } + signers }; allocations @@ -106,7 +107,11 @@ fn distribute_tokens( if args.dry_run { Ok(Signature::default()) } else { - client.send_message(message, &signers) + let result = client.send_message(message, &signers); + if let Ok(signature) = result { + println!("{:?}", signature); + } + result } }) .collect() From 7ce73764760ef1dc697f2b933137ea399dc0ef2a Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 20:20:50 -0600 Subject: [PATCH 25/71] Fix bugs * Don't create the transaction log if nothing to put into it; otherwise the next innvocation won't add the header * Apply previous transactions to allocations with matching recipients --- Cargo.toml | 2 +- src/tokens.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3d2c7024ea0141..f0f989dcc781ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "solana-tokens" description = "Blockchain, Rebuilt for Scale" authors = ["Solana Maintainers "] edition = "2018" -version = "0.1.0" +version = "0.1.1" repository = "https://github.com/solana-labs/solana" license = "Apache-2.0" homepage = "https://solana.com/" diff --git a/src/tokens.rs b/src/tokens.rs index 00bfa6cb071474..18a16be6c1d6ac 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -54,6 +54,9 @@ fn apply_previous_transactions( for transaction_info in transaction_infos { let mut amount = transaction_info.amount; for allocation in allocations.iter_mut() { + if allocation.recipient != transaction_info.recipient { + continue; + } if allocation.amount >= amount { allocation.amount -= amount; break; @@ -130,6 +133,14 @@ fn append_transaction_infos( results: &[Result], transactions_csv: &str, ) -> Result<(), csv::Error> { + if results.iter().all(|x| x.is_err()) { + for (i, allocation) in allocations.iter().enumerate() { + let e = results[i].as_ref().unwrap_err(); + eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); + } + return Ok(()); + } + let existed = Path::new(&transactions_csv).exists(); if existed { let transactions_bak = format!("{}.bak", &transactions_csv); @@ -313,4 +324,51 @@ mod tests { let thin_client = ThinClient(bank_client); test_process_distribute_with_client(&thin_client, sender_keypair); } + + #[test] + fn test_apply_previous_transactions() { + let mut allocations = vec![ + Allocation { + recipient: "a".to_string(), + amount: 1.0, + }, + Allocation { + recipient: "b".to_string(), + amount: 1.0, + }, + ]; + let transaction_infos = vec![TransactionInfo { + recipient: "b".to_string(), + amount: 1.0, + signature: "".to_string(), + }]; + apply_previous_transactions(&mut allocations, &transaction_infos); + assert_eq!(allocations.len(), 1); + + // Ensure that we applied the transaction to the allocation with + // a matching recipient address (to "b", not "a"). + assert_eq!(allocations[0].recipient, "a"); + } + + #[test] + fn test_append_transaction_infos_all_errors() { + let allocations = vec![Allocation { + recipient: "a".to_string(), + amount: 1.0, + }]; + let results = vec![Err(TransportError::Custom("".to_string()))]; + let dir = tempdir().unwrap(); + let transactions_csv = dir + .path() + .join("transactions.csv") + .to_str() + .unwrap() + .to_string(); + append_transaction_infos(&allocations, &results, &transactions_csv).unwrap(); + assert!(!Path::new(&transactions_csv).exists()); + + let results = vec![Ok(Signature::default())]; + append_transaction_infos(&allocations, &results, &transactions_csv).unwrap(); + assert!(Path::new(&transactions_csv).exists()); + } } From 6a5639952674a45a1538c3ede8f74fb7e88a05fb Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 20:59:14 -0600 Subject: [PATCH 26/71] Bail out of any account already has a balance --- Cargo.lock | 2 +- src/thin_client.rs | 2 ++ src/tokens.rs | 26 ++++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88893ed4e3d5ef..9075c1756d771b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3396,7 +3396,7 @@ dependencies = [ [[package]] name = "solana-tokens" -version = "0.1.0" +version = "0.1.1" dependencies = [ "clap", "console", diff --git a/src/thin_client.rs b/src/thin_client.rs index 3a3cb5f2452bf0..a9c5edcea50002 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -30,6 +30,8 @@ impl Client for RpcClient { let mut transaction = Transaction::new_unsigned(message); self.resign_transaction(&mut transaction, signers) .map_err(|e| TransportError::Custom(e.to_string()))?; + let initial_signature = transaction.signatures[0]; + println!("Sending transaction with signature {}", initial_signature); let signature = self .send_and_confirm_transaction_with_spinner(&mut transaction, signers) .map_err(|e| TransportError::Custom(e.to_string()))?; diff --git a/src/tokens.rs b/src/tokens.rs index 18a16be6c1d6ac..644ad29a52d92d 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -6,13 +6,14 @@ use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use solana_sdk::{ message::Message, - native_token::sol_to_lamports, + native_token::{lamports_to_sol, sol_to_lamports}, signature::{Signature, Signer}, system_instruction, transport::TransportError, }; use std::fs; use std::path::Path; +use std::process; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -112,7 +113,7 @@ fn distribute_tokens( } else { let result = client.send_message(message, &signers); if let Ok(signature) = result { - println!("{:?}", signature); + println!("Finalized transaction with signature {}", signature); } result } @@ -233,6 +234,27 @@ pub fn process_distribute( return Ok(()); } + // Sanity check: the recipient should not have tokens yet. If they do, it + // is probably because: + // 1. The signature couldn't be found in a previous run, though the transaction was + // successful. If so, manually add a row to the transaction log. + // 2. The recipient already has tokens. If so, update this code to include a `--force` flag. + // 3. The recipient correctly got tokens in a previous run, and then later registered the same + // address for another bid. If so, update this code to check for that case. + for allocation in &allocations { + let address = allocation.recipient.parse().unwrap(); + let balance = client.get_balance(&address).unwrap(); + if balance != 0 { + eprintln!( + "Error: Non-zero balance {}, refusing to send {} to {}", + lamports_to_sol(balance), + allocation.amount, + allocation.recipient, + ); + process::exit(1); + } + } + println!( "{}", style(format!("{:<44} {}", "Recipient", "Amount")).bold() From 00cc299a463475b053aed8288f1cbbdf79c08f54 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 3 Apr 2020 21:14:08 -0600 Subject: [PATCH 27/71] Polish --- src/tokens.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 644ad29a52d92d..7a2ef1b011d2e6 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -183,13 +183,6 @@ pub fn process_distribute( .trim(Trim::All) .from_path(&args.allocations_csv)?; let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); - let starting_total_dollars: f64 = bids.iter().map(|x| x.bid_amount_dollars).sum(); - println!( - "{} ${}", - style(format!("{}", "Total in allocations_csv:")).bold(), - starting_total_dollars - ); - let allocations: Vec = bids .into_iter() .map(|bid| create_allocation(&bid, args.dollars_per_sol)) @@ -203,9 +196,10 @@ pub fn process_distribute( let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( - "{} â—Ž{}", + "{} â—Ž{} (${})", style(format!("{}", "Total in allocations_csv:")).bold(), - starting_total_tokens + starting_total_tokens, + starting_total_tokens * args.dollars_per_sol, ); let mut allocations = merge_allocations(&allocations); @@ -214,19 +208,22 @@ pub fn process_distribute( let distributed_tokens: f64 = transaction_infos.iter().map(|x| x.amount).sum(); let undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( - "{} â—Ž{}", + "{} â—Ž{} (${})", style(format!("{}", "Distributed:")).bold(), - distributed_tokens + distributed_tokens, + distributed_tokens * args.dollars_per_sol, ); println!( - "{} â—Ž{}", + "{} â—Ž{} (${})", style(format!("{}", "Undistributed:")).bold(), - undistributed_tokens + undistributed_tokens, + undistributed_tokens * args.dollars_per_sol, ); println!( - "{} â—Ž{}\n", + "{} â—Ž{} (${})\n", style(format!("{}", "Total:")).bold(), - distributed_tokens + undistributed_tokens + distributed_tokens + undistributed_tokens, + (distributed_tokens + undistributed_tokens) * args.dollars_per_sol, ); if allocations.is_empty() { From 490206003e69a0c62b05f43791cbbf191e1bb7dc Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 4 Apr 2020 14:06:13 -0600 Subject: [PATCH 28/71] Add new 'balances' command --- src/arg_parser.rs | 30 +++++++++++++++++++++++++++++- src/args.rs | 15 +++++++++++---- src/main.rs | 15 +++++++++------ src/tokens.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index a310aa953fea2d..cffc31598c7126 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,4 +1,4 @@ -use crate::args::{Args, Command, DistributeArgs}; +use crate::args::{Args, BalancesArgs, Command, DistributeArgs}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_clap_utils::input_validators::is_valid_signer; use solana_cli_config::CONFIG_FILE; @@ -79,6 +79,26 @@ where .help("Fee payer"), ), ) + .subcommand( + SubCommand::with_name("balances") + .about("Balance of each account") + .arg( + Arg::with_name("allocations_csv") + .required(true) + .index(1) + .takes_value(true) + .value_name("FILE") + .help("Allocations CSV file"), + ) + .arg( + Arg::with_name("dollars_per_sol") + .long("dollars-per-sol") + .required(true) + .takes_value(true) + .value_name("NUMBER") + .help("Dollars per SOL"), + ), + ) .get_matches_from(args) } @@ -93,6 +113,13 @@ fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { } } +fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { + BalancesArgs { + allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), + dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), + } +} + pub fn parse_args(args: I) -> Args where I: IntoIterator, @@ -104,6 +131,7 @@ where let command = match matches.subcommand() { ("distribute", Some(matches)) => Command::Distribute(parse_distribute_args(matches)), + ("balances", Some(matches)) => Command::Balances(parse_balances_args(matches)), _ => { eprintln!("{}", matches.usage()); exit(1); diff --git a/src/args.rs b/src/args.rs index 38a07381636952..8d01e004b8d403 100644 --- a/src/args.rs +++ b/src/args.rs @@ -13,8 +13,14 @@ pub struct DistributeArgs { pub fee_payer: Option, } +pub struct BalancesArgs { + pub allocations_csv: String, + pub dollars_per_sol: f64, +} + pub enum Command { Distribute(DistributeArgs), + Balances(BalancesArgs), } pub struct Args { @@ -24,7 +30,7 @@ pub struct Args { } pub fn resolve_command( - command: &Command, + command: Command, ) -> Result>, Box> { match command { Command::Distribute(args) => { @@ -32,10 +38,10 @@ pub fn resolve_command( let wallet_manager = wallet_manager.as_ref(); let matches = ArgMatches::default(); let resolved_args = DistributeArgs { - allocations_csv: args.allocations_csv.clone(), - transactions_csv: args.transactions_csv.clone(), + allocations_csv: args.allocations_csv, + transactions_csv: args.transactions_csv, dollars_per_sol: args.dollars_per_sol, - dry_run: args.dry_run.clone(), + dry_run: args.dry_run, sender_keypair: args.sender_keypair.as_ref().map(|key_url| { signer_from_path(&matches, &key_url, "sender", wallet_manager).unwrap() }), @@ -45,5 +51,6 @@ pub fn resolve_command( }; Ok(Command::Distribute(resolved_args)) } + Command::Balances(args) => Ok(Command::Balances(args)), } } diff --git a/src/main.rs b/src/main.rs index 0973f26168c1ba..c7ee0d1a969574 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use solana_tokens::{ arg_parser::parse_args, args::{resolve_command, Command}, thin_client::ThinClient, - tokens::process_distribute, + tokens, }; use std::env; use std::error::Error; @@ -12,13 +12,16 @@ use std::error::Error; fn main() -> Result<(), Box> { let command_args = parse_args(env::args_os()); let config = Config::load(&command_args.config_file)?; + let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); + let client = RpcClient::new(json_rpc_url); + let thin_client = ThinClient(client); - match resolve_command(&command_args.command)? { + match resolve_command(command_args.command)? { Command::Distribute(args) => { - let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); - let client = RpcClient::new(json_rpc_url); - let thin_client = ThinClient(client); - process_distribute(&thin_client, &args)?; + tokens::process_distribute(&thin_client, &args)?; + } + Command::Balances(args) => { + tokens::process_balances(&thin_client, &args)?; } } Ok(()) diff --git a/src/tokens.rs b/src/tokens.rs index 7a2ef1b011d2e6..dc78d175492226 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,4 +1,4 @@ -use crate::args::DistributeArgs; +use crate::args::{BalancesArgs, DistributeArgs}; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; @@ -265,6 +265,45 @@ pub fn process_distribute( Ok(()) } +pub fn process_balances( + client: &ThinClient, + args: &BalancesArgs, +) -> Result<(), csv::Error> { + let mut rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.allocations_csv)?; + let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); + let allocations: Vec = bids + .into_iter() + .map(|bid| create_allocation(&bid, args.dollars_per_sol)) + .collect(); + let allocations = merge_allocations(&allocations); + + println!( + "{}", + style(format!( + "{:<44} {:>24} {:>24} {:>24}", + "Recipient", "Expected Balance", "Actual Balance", "Difference" + )) + .bold() + ); + + for allocation in &allocations { + let address = allocation.recipient.parse().unwrap(); + let expected = lamports_to_sol(sol_to_lamports(allocation.amount)); + let actual = lamports_to_sol(client.get_balance(&address).unwrap()); + println!( + "{:<44} {:>24} {:>24} {:>24.9}", + allocation.recipient, + expected, + actual, + actual - expected + ); + } + + Ok(()) +} + use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; pub fn test_process_distribute_with_client( From b5cd54cf7be5bd750e02adf388e221f3fdcd8c1d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 4 Apr 2020 14:36:23 -0600 Subject: [PATCH 29/71] 9 decimal places --- src/tokens.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens.rs b/src/tokens.rs index dc78d175492226..211fa4da7dad8d 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -293,7 +293,7 @@ pub fn process_balances( let expected = lamports_to_sol(sol_to_lamports(allocation.amount)); let actual = lamports_to_sol(client.get_balance(&address).unwrap()); println!( - "{:<44} {:>24} {:>24} {:>24.9}", + "{:<44} {:>24.9} {:>24.9} {:>24.9}", allocation.recipient, expected, actual, From b4fb233558bc54416a7c950764adbab6808e6d5b Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 4 Apr 2020 15:05:31 -0600 Subject: [PATCH 30/71] Add missing file --- src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/lib.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000000000..8a5ab44ea2c842 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +pub mod arg_parser; +pub mod args; +pub mod thin_client; +pub mod tokens; From 6bf5f7c113521a8d585a4499df84db1332573917 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 4 Apr 2020 15:14:01 -0600 Subject: [PATCH 31/71] Better dry-run; keypair options now optional --- src/tokens.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 211fa4da7dad8d..f9bcf85287532e 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -82,12 +82,6 @@ fn distribute_tokens( allocations: &[Allocation], args: &DistributeArgs>, ) -> Vec> { - let fee_payer_pubkey = if args.dry_run { - Pubkey::default() - } else { - args.fee_payer.as_ref().unwrap().pubkey() - }; - let signers = if args.dry_run { vec![] } else { @@ -101,22 +95,22 @@ fn distribute_tokens( allocations .iter() .map(|allocation| { - println!("{:<44} {}", allocation.recipient, allocation.amount); + println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); + if args.dry_run { + return Ok(Signature::default()); + } + let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); let from = args.sender_keypair.as_ref().unwrap().pubkey(); let to = allocation.recipient.parse().unwrap(); let lamports = sol_to_lamports(allocation.amount); let instruction = system_instruction::transfer(&from, &to, lamports); let message = Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)); - if args.dry_run { - Ok(Signature::default()) - } else { - let result = client.send_message(message, &signers); - if let Ok(signature) = result { - println!("Finalized transaction with signature {}", signature); - } - result + let result = client.send_message(message, &signers); + if let Ok(signature) = result { + println!("Finalized transaction with signature {}", signature); } + result }) .collect() } @@ -254,7 +248,11 @@ pub fn process_distribute( println!( "{}", - style(format!("{:<44} {}", "Recipient", "Amount")).bold() + style(format!( + "{:<44} {:>24}", + "Recipient", "Expected Balance (â—Ž)" + )) + .bold() ); let results = distribute_tokens(&client, &allocations, &args); @@ -283,7 +281,7 @@ pub fn process_balances( "{}", style(format!( "{:<44} {:>24} {:>24} {:>24}", - "Recipient", "Expected Balance", "Actual Balance", "Difference" + "Recipient", "Expected Balance (â—Ž)", "Actual Balance (â—Ž)", "Difference (â—Ž)" )) .bold() ); From 0c6da710fc4dca987f0dfb7e1019702f813b840d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 7 Apr 2020 10:49:02 -0600 Subject: [PATCH 32/71] Change field name from 'bid' to 'accepted' Also, tolerate precision change from 2 decimal places to 4 --- src/tokens.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index f9bcf85287532e..2aa969d4b70618 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -17,7 +17,7 @@ use std::process; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { - bid_amount_dollars: f64, + accepted_amount_dollars: f64, primary_address: String, } @@ -67,13 +67,13 @@ fn apply_previous_transactions( } } } - allocations.retain(|x| x.amount > 0.0); + allocations.retain(|x| x.amount > 0.5); } fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { Allocation { recipient: bid.primary_address.clone(), - amount: bid.bid_amount_dollars / dollars_per_sol, + amount: bid.accepted_amount_dollars / dollars_per_sol, } } @@ -316,7 +316,7 @@ pub fn test_process_distribute_with_client( let alice_pubkey = Pubkey::new_rand(); let bid = Bid { primary_address: alice_pubkey.to_string(), - bid_amount_dollars: 1000.0, + accepted_amount_dollars: 1000.0, }; let allocations_file = NamedTempFile::new().unwrap(); let allocations_csv = allocations_file.path().to_str().unwrap().to_string(); @@ -344,7 +344,7 @@ pub fn test_process_distribute_with_client( let transaction_infos = read_transaction_infos(&transactions_csv); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = bid.bid_amount_dollars / args.dollars_per_sol; + let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol; assert_eq!(transaction_infos[0].amount, expected_amount); assert_eq!( @@ -357,7 +357,7 @@ pub fn test_process_distribute_with_client( let transaction_infos = read_transaction_infos(&transactions_csv); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = bid.bid_amount_dollars / args.dollars_per_sol; + let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol; assert_eq!(transaction_infos[0].amount, expected_amount); assert_eq!( From 4373f2016ffb5433b00e3f77fd52e66e1af47e14 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 22 Apr 2020 17:08:34 -0600 Subject: [PATCH 33/71] Write to transaction log immediately --- src/tokens.rs | 100 +++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 71 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 2aa969d4b70618..312081be49c009 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -9,7 +9,6 @@ use solana_sdk::{ native_token::{lamports_to_sol, sol_to_lamports}, signature::{Signature, Signer}, system_instruction, - transport::TransportError, }; use std::fs; use std::path::Path; @@ -81,7 +80,7 @@ fn distribute_tokens( client: &ThinClient, allocations: &[Allocation], args: &DistributeArgs>, -) -> Vec> { +) -> Result<(), csv::Error> { let signers = if args.dry_run { vec![] } else { @@ -92,27 +91,32 @@ fn distribute_tokens( signers }; - allocations - .iter() - .map(|allocation| { - println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); - if args.dry_run { - return Ok(Signature::default()); - } + for allocation in allocations { + println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); + let result = if args.dry_run { + Ok(Signature::default()) + } else { let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); let from = args.sender_keypair.as_ref().unwrap().pubkey(); let to = allocation.recipient.parse().unwrap(); let lamports = sol_to_lamports(allocation.amount); let instruction = system_instruction::transfer(&from, &to, lamports); let message = Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)); - - let result = client.send_message(message, &signers); - if let Ok(signature) = result { + client.send_message(message, &signers) + }; + match result { + Ok(signature) => { println!("Finalized transaction with signature {}", signature); + if !args.dry_run { + append_transaction_info(&allocation, &signature, &args.transactions_csv)?; + } + } + Err(e) => { + eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); } - result - }) - .collect() + }; + } + Ok(()) } fn read_transaction_infos(path: &str) -> Vec { @@ -123,24 +127,12 @@ fn read_transaction_infos(path: &str) -> Vec { rdr.deserialize().map(|x| x.unwrap()).collect() } -fn append_transaction_infos( - allocations: &[Allocation], - results: &[Result], +fn append_transaction_info( + allocation: &Allocation, + signature: &Signature, transactions_csv: &str, ) -> Result<(), csv::Error> { - if results.iter().all(|x| x.is_err()) { - for (i, allocation) in allocations.iter().enumerate() { - let e = results[i].as_ref().unwrap_err(); - eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); - } - return Ok(()); - } - let existed = Path::new(&transactions_csv).exists(); - if existed { - let transactions_bak = format!("{}.bak", &transactions_csv); - fs::copy(&transactions_csv, transactions_bak)?; - } let file = fs::OpenOptions::new() .create_new(!existed) .write(true) @@ -150,21 +142,12 @@ fn append_transaction_infos( .has_headers(!existed) .from_writer(file); - for (i, allocation) in allocations.iter().enumerate() { - match &results[i] { - Ok(signature) => { - let transaction_info = TransactionInfo { - recipient: allocation.recipient.clone(), - amount: allocation.amount, - signature: signature.to_string(), - }; - wtr.serialize(transaction_info)?; - } - Err(e) => { - eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); - } - } - } + let transaction_info = TransactionInfo { + recipient: allocation.recipient.clone(), + amount: allocation.amount, + signature: signature.to_string(), + }; + wtr.serialize(transaction_info)?; wtr.flush()?; Ok(()) } @@ -255,10 +238,7 @@ pub fn process_distribute( .bold() ); - let results = distribute_tokens(&client, &allocations, &args); - if !args.dry_run { - append_transaction_infos(&allocations, &results, &args.transactions_csv)?; - } + distribute_tokens(&client, &allocations, &args)?; Ok(()) } @@ -405,26 +385,4 @@ mod tests { // a matching recipient address (to "b", not "a"). assert_eq!(allocations[0].recipient, "a"); } - - #[test] - fn test_append_transaction_infos_all_errors() { - let allocations = vec![Allocation { - recipient: "a".to_string(), - amount: 1.0, - }]; - let results = vec![Err(TransportError::Custom("".to_string()))]; - let dir = tempdir().unwrap(); - let transactions_csv = dir - .path() - .join("transactions.csv") - .to_str() - .unwrap() - .to_string(); - append_transaction_infos(&allocations, &results, &transactions_csv).unwrap(); - assert!(!Path::new(&transactions_csv).exists()); - - let results = vec![Ok(Signature::default())]; - append_transaction_infos(&allocations, &results, &transactions_csv).unwrap(); - assert!(Path::new(&transactions_csv).exists()); - } } From eee2a6792b175fa4c7b231a3e1db772d8ab23c72 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 22 Apr 2020 17:14:59 -0600 Subject: [PATCH 34/71] Rename allocations_csv to bids_csv So that we can bypass bids_csv with an allocations CSV file --- src/arg_parser.rs | 20 ++++++++++---------- src/args.rs | 6 +++--- src/tokens.rs | 12 ++++++------ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index cffc31598c7126..1b1fa8bef07f75 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -34,20 +34,20 @@ where SubCommand::with_name("distribute") .about("Distribute tokens") .arg( - Arg::with_name("allocations_csv") + Arg::with_name("transactions_csv") .required(true) .index(1) .takes_value(true) .value_name("FILE") - .help("Allocations CSV file"), + .help("Transactions CSV file"), ) .arg( - Arg::with_name("transactions_csv") + Arg::with_name("bids_csv") + .long("bids-csv") .required(true) - .index(2) .takes_value(true) .value_name("FILE") - .help("Transactions CSV file"), + .help("Bids CSV file"), ) .arg( Arg::with_name("dollars_per_sol") @@ -83,12 +83,12 @@ where SubCommand::with_name("balances") .about("Balance of each account") .arg( - Arg::with_name("allocations_csv") + Arg::with_name("bids_csv") + .long("bids-csv") .required(true) - .index(1) .takes_value(true) .value_name("FILE") - .help("Allocations CSV file"), + .help("Bids CSV file"), ) .arg( Arg::with_name("dollars_per_sol") @@ -104,7 +104,7 @@ where fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { DistributeArgs { - allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), + bids_csv: value_t_or_exit!(matches, "bids_csv", String), transactions_csv: value_t_or_exit!(matches, "transactions_csv", String), dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), dry_run: matches.is_present("dry_run"), @@ -115,7 +115,7 @@ fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { BalancesArgs { - allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), + bids_csv: value_t_or_exit!(matches, "bids_csv", String), dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), } } diff --git a/src/args.rs b/src/args.rs index 8d01e004b8d403..cd2f5c37e26bb0 100644 --- a/src/args.rs +++ b/src/args.rs @@ -5,7 +5,7 @@ use solana_sdk::signature::Signer; use std::error::Error; pub struct DistributeArgs { - pub allocations_csv: String, + pub bids_csv: String, pub transactions_csv: String, pub dollars_per_sol: f64, pub dry_run: bool, @@ -14,7 +14,7 @@ pub struct DistributeArgs { } pub struct BalancesArgs { - pub allocations_csv: String, + pub bids_csv: String, pub dollars_per_sol: f64, } @@ -38,7 +38,7 @@ pub fn resolve_command( let wallet_manager = wallet_manager.as_ref(); let matches = ArgMatches::default(); let resolved_args = DistributeArgs { - allocations_csv: args.allocations_csv, + bids_csv: args.bids_csv, transactions_csv: args.transactions_csv, dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run, diff --git a/src/tokens.rs b/src/tokens.rs index 312081be49c009..85aac21f9cf7bc 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -158,7 +158,7 @@ pub fn process_distribute( ) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) - .from_path(&args.allocations_csv)?; + .from_path(&args.bids_csv)?; let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); let allocations: Vec = bids .into_iter() @@ -249,7 +249,7 @@ pub fn process_balances( ) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) - .from_path(&args.allocations_csv)?; + .from_path(&args.bids_csv)?; let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); let allocations: Vec = bids .into_iter() @@ -298,9 +298,9 @@ pub fn test_process_distribute_with_client( primary_address: alice_pubkey.to_string(), accepted_amount_dollars: 1000.0, }; - let allocations_file = NamedTempFile::new().unwrap(); - let allocations_csv = allocations_file.path().to_str().unwrap().to_string(); - let mut wtr = csv::WriterBuilder::new().from_writer(allocations_file); + let bids_file = NamedTempFile::new().unwrap(); + let bids_csv = bids_file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(bids_file); wtr.serialize(&bid).unwrap(); wtr.flush().unwrap(); @@ -316,7 +316,7 @@ pub fn test_process_distribute_with_client( sender_keypair: Some(Box::new(sender_keypair)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, - allocations_csv, + bids_csv, transactions_csv: transactions_csv.clone(), dollars_per_sol: 0.22, }; From b929084b49d781bd8821eb34fde513de513a1a99 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 23 Apr 2020 15:29:17 -0600 Subject: [PATCH 35/71] Upgrade Solana --- Cargo.lock | 141 +++++++++++++++++++++++----------------------- Cargo.toml | 17 +++--- src/arg_parser.rs | 2 +- src/args.rs | 7 +-- 4 files changed, 82 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9075c1756d771b..280c8025f25d70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2757,9 +2757,9 @@ dependencies = [ [[package]] name = "solana-archiver-utils" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d977c442df5ddc0394bfce5ec123d4d02f2e2f89529f3348e343e9a8ac1af0e" +checksum = "ad60209b2812ca2149b3d50fdd04193c444b3d50a4ecd5c79bf3ada68ba73590" dependencies = [ "log 0.4.8", "rand 0.6.5", @@ -2773,9 +2773,9 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b11a55221ec8313a1f3e0101461d2f9535d0712a1bcd6754e13974c3c7c8447" +checksum = "a05d411d070424b475478b2586a26d1b3da53effc08066675756700cd6123a25" dependencies = [ "bincode", "byteorder", @@ -2791,9 +2791,9 @@ dependencies = [ [[package]] name = "solana-budget-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720589429e231f12ccb605d6bfc9a155c8992bcac16e627900065c4e4e2272fa" +checksum = "5e5326ff7b6a03e36597025259b34bc903034aa489dd40041a4a73a45ba9e653" dependencies = [ "bincode", "chrono", @@ -2808,9 +2808,9 @@ dependencies = [ [[package]] name = "solana-chacha" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76dd09ae00d0805c56fce4e79973e5e85947cf69d8f69de709e82d5886e29cb" +checksum = "97db655a19596404a5bdf685b1495187f8c14205652d2d5ae5da89bbe0a59369" dependencies = [ "log 0.4.8", "rand 0.6.5", @@ -2824,9 +2824,9 @@ dependencies = [ [[package]] name = "solana-chacha-cuda" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab6ab1b5366c7d94a79273dddf818a1e662e827b73ee317b7a8107361a665f8" +checksum = "54fc6713552e19bf56333fe592f84749123c221c31d2684366447de7d5e8adc2" dependencies = [ "log 0.4.8", "solana-archiver-utils", @@ -2839,18 +2839,18 @@ dependencies = [ [[package]] name = "solana-chacha-sys" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2284a0fda7139e027780e97f507b1ff214fe4a578413f7337a8762f73bafcdb" +checksum = "898910294e5b152fdca397eee45c70f2d01c42757b47dedd302811fe1ebc9d0f" dependencies = [ "cc", ] [[package]] name = "solana-clap-utils" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1e7d83c36a108e81aa83f991e6a53616ace9c026e866f35797df5bc949a977" +checksum = "121c14abffc40c06a8fe8227429488eac65da416f739c2e5f7c9e0014f4f7e60" dependencies = [ "chrono", "clap", @@ -2864,9 +2864,9 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bda778268146a2ad2d82b42705f019c50c0a3557a221d64e44c7bc6f844dee" +checksum = "72e00089763a5d11da50cf63fa9bfe96cefa402e895dc6988a3a998ae1d477ac" dependencies = [ "dirs", "lazy_static", @@ -2878,9 +2878,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d0b6dd8cd753249fe5ab5f8a81aca74e6f40445e3586d95a4e236200555a6a" +checksum = "2ccb3a57d0880bec3d8ffae8c8c67509641c91731aec4f3014c3d7a68a253d66" dependencies = [ "bincode", "bs58", @@ -2903,9 +2903,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3848abb2b3f662aa107df2a3b1c918d01edc57302bd2d1c5c24b279acabdbc9" +checksum = "415b93f33c8ab74d1d0400cd7eb63b03c49ed3b46b5484d2945d0eeb4e5fa979" dependencies = [ "bincode", "chrono", @@ -2918,9 +2918,9 @@ dependencies = [ [[package]] name = "solana-core" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5706919c6e60471f38d0dea5b8355980740c0401ccf2ce5910225139b58e318c" +checksum = "087bdfed47de6e88d5875f85b278d7f62358a39e54d97d627b032f1184059a31" dependencies = [ "bincode", "bs58", @@ -2983,9 +2983,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a401b72dcacd535b88d6e3193533c4f7c3b5154a4f2cb7b3d1d1b61932c2cded" +checksum = "514ce92cd079728eee61b0e27dea56c168a24b3026b38db365febd3b660320a9" dependencies = [ "backtrace", "bytes 0.4.12", @@ -3008,9 +3008,9 @@ dependencies = [ [[package]] name = "solana-exchange-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9831322edce9493d2ddad4de2e7825f4952c483009f92330ad41d5d1b3bef5" +checksum = "5d48b97514d0403b2d7efb45458ece9eef6ee826d2871b4709c7202901f9a05b" dependencies = [ "bincode", "log 0.4.8", @@ -3026,9 +3026,9 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262652d7ca6a87d12deedb85546c245ea718c50829858675967a289731659ba8" +checksum = "bdc63cd2a5cba11a2bd00f869b8469bc4089d3235dd7cedd5dddbf20579f2e6e" dependencies = [ "bincode", "byteorder", @@ -3047,9 +3047,9 @@ dependencies = [ [[package]] name = "solana-genesis-programs" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb138971f747fd6ac174bc78965957a48d214c4864948fa8c98b0b6806e96da1" +checksum = "5c4c270b902aa2b9cd0a8c92db5617bf9128ba6db1c30de57145c8ef7ca62ab2" dependencies = [ "log 0.4.8", "solana-bpf-loader-program", @@ -3066,9 +3066,9 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac9ced3edf5bfbeef7abe976a08cbad495c80aad44b7c86213c8ab1c2cc9ac3" +checksum = "83a24f1498404be3c271f525614d19a60ac3a0ef510b500c7271d050c0091980" dependencies = [ "bincode", "byteorder", @@ -3112,9 +3112,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ba3abed8ca3ab5e5148594452f8d65def958e71ee3aaebbf896ea6fe543c74" +checksum = "6200704d6a5c23a74753050c855aae6697f6ff0d1a3a7dce6381b7fb80580a96" dependencies = [ "env_logger 0.7.1", "lazy_static", @@ -3123,9 +3123,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3dbf5afbbe452109662eb95159078ec9879313a5ccd57f4bba726768051b9f3" +checksum = "66b5d7cdbde4d22c7af68a9c9fc71ae9013585f0e2d7d64f3361480ef9053511" dependencies = [ "jemalloc-ctl", "jemallocator", @@ -3136,9 +3136,9 @@ dependencies = [ [[package]] name = "solana-merkle-tree" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636e855d8fc4969e7d87a0bc6b4ce8d3a2c9961e32af12af8665cff826e31f94" +checksum = "cc163a7b9691a12e2c8af6fdbd7ec606d2eae5b2e0c5df5c57e7085589b60b91" dependencies = [ "fast-math", "solana-sdk", @@ -3146,9 +3146,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc4ec5f2eabd26b8ac0bc3c4a3e97a23d7163874f134ac5f98a2506f310775f" +checksum = "fb8f220cf0d9252e9635979bc3665a8b0f3a5f49fc1e9ea2989e9cfaa1e87c5b" dependencies = [ "env_logger 0.7.1", "gethostname", @@ -3160,9 +3160,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8ff34d00ad44fef0309fa4b4772e421fe478c235ee740eaa399f58ae3b93ae" +checksum = "6eb496f1a802fc3d294847108829d1968c900c46d1acdf97c95a96e67fafc42b" dependencies = [ "bincode", "bytes 0.4.12", @@ -3181,9 +3181,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0e5de2e96f3757c8996a1f57b127e4d7c57b5d233dc1ff8583b73a7f2f765e" +checksum = "6a54de5f5154a20bed1a0c4f0522c096613b5f2f2170fe00f36e236cbb0c8c57" dependencies = [ "bincode", "dlopen", @@ -3202,9 +3202,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb2ae379caa28111b3c6b1ea83f4623d66190f20504ff578c24ce3947afee69" +checksum = "63256b0e360fe073e939a44b318a3e31110c00d9a159d83b50da2116310206a8" dependencies = [ "lazy_static", "num_cpus", @@ -3223,9 +3223,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3508f3dd5ddf1fe83663cf3fd5ec47d9b762175669fd868e1c7fcc395c078d11" +checksum = "2c3e75db1347abb88d27f6fc59cbb408428435cae65f808ec00b40fbaa075301" dependencies = [ "base32", "console", @@ -3241,9 +3241,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c20b96918d9a178c2bea0ce97b2440e7942e626bb6a9dc555e4dc56ff486b0a" +checksum = "7c18561821e669100cb2e147ada66bbca6e5ad55e6b1e93e9c52ebb6206f5c28" dependencies = [ "bincode", "bv", @@ -3278,9 +3278,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8343657849df093cfe3f024da88c46ffec41dbfaa579e25e24057d1b987b8e4" +checksum = "d4c4674e5e7b809af748909ea99c3572de3761536fa8e7136d2c31eeaf314a35" dependencies = [ "assert_matches", "bincode", @@ -3313,9 +3313,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d04c4431d64f1f61df85cdf38c2c0737840d7b061afea6b95d0c9afcd9e1b6d" +checksum = "d64f6e9420c2cfae6b29661e83e2024518d3fe3f5adb94aa3999c4549d5fa089" dependencies = [ "bs58", "proc-macro2 1.0.10", @@ -3325,9 +3325,9 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e86a7b234809e2961b51e9959517994610449abf858cb448e9d0e31cafca011" +checksum = "ff08836c28e2276872bb233b4ce19e22e181fb70fadc193ddf8729d4dfda58ec" dependencies = [ "bincode", "log 0.4.8", @@ -3345,9 +3345,9 @@ dependencies = [ [[package]] name = "solana-storage-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d9ef9f07f6dfb8be7915f5693767b977449c0d2e7e0ebb9c33c7014c3ea576" +checksum = "cab1129490c250b68c09b25883a8f36dcc41c4d26b17d451939c4196058c309a" dependencies = [ "bincode", "log 0.4.8", @@ -3362,9 +3362,9 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434523f36a621ac4a5578ebce912e321d1691830dd9b45362dea5c46699a4334" +checksum = "956be6b872c531f62a0f7c4792b36098fe6011abc28089ae262f30e7c6e417e4" dependencies = [ "libc", "log 0.4.8", @@ -3379,9 +3379,9 @@ dependencies = [ [[package]] name = "solana-sys-tuner" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9e38ed20e3cbe4c9560c50d7c64bbb995bccc7819f6f974bbb392de4d0d30b" +checksum = "366836f9f47126609c78ec7110793466b825ab92d1ef4bb33107524209a6f2f7" dependencies = [ "clap", "libc", @@ -3411,15 +3411,14 @@ dependencies = [ "solana-remote-wallet", "solana-runtime", "solana-sdk", - "solana-stake-program", "tempfile", ] [[package]] name = "solana-transaction-status" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473e8911e1d38e7c432e298e0b385895f502ec1756190b617d43b6adc88784e8" +checksum = "2300c6cd4d7f400ba164a0f1578988ef04753665a134d1560adc0bb55bd8ef1c" dependencies = [ "bincode", "bs58", @@ -3430,9 +3429,9 @@ dependencies = [ [[package]] name = "solana-vest-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973676dfd4c97e50653ed15c1780d588d4299c661f3c55e877e814011ee7cb93" +checksum = "7ed2272e4a789af86f0cd032f71f4ccde67ce33137bf30a10ac061d2c146414e" dependencies = [ "bincode", "chrono", @@ -3447,9 +3446,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142ad2d760e25fb055c0365ae837ee8bcd649d9a956188b14c38f2f365ab4260" +checksum = "fe7987567350c099538e5555c7dea30718f6d40324ab97be3fe32b561c907f22" dependencies = [ "bincode", "log 0.4.8", @@ -3465,9 +3464,9 @@ dependencies = [ [[package]] name = "solana-vote-signer" -version = "1.1.1" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1085162747e53b3b46fe14f00b4de4527cf640eb242df12a5ad858e2290eed39" +checksum = "d86ff7b8cf7a519b15a05aa808b2da75adf87030e65bc970cd1bed4c2634b427" dependencies = [ "clap", "jsonrpc-core", diff --git a/Cargo.toml b/Cargo.toml index f0f989dcc781ee..efce748bd71692 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,12 @@ clap = "2.33.0" console = "0.10.0" indexmap = "1.3.2" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = "1.1.1" -solana-cli-config = "1.1.1" -solana-client = "1.1.1" -solana-core = "1.1.1" -solana-faucet = "1.1.1" -solana-remote-wallet = "1.1.1" -solana-runtime = "1.1.1" -solana-sdk = "1.1.1" -solana-stake-program = "1.1.1" +solana-clap-utils = "1.1.6" +solana-cli-config = "1.1.6" +solana-client = "1.1.6" +solana-core = "1.1.6" +solana-faucet = "1.1.6" +solana-remote-wallet = "1.1.6" +solana-runtime = "1.1.6" +solana-sdk = "1.1.6" tempfile = "3.1.0" diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 1b1fa8bef07f75..c03a0fc6ba6afc 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -11,7 +11,7 @@ where T: Into + Clone, { let default_config_file = CONFIG_FILE.as_ref().unwrap(); - App::new("solana-stake-accounts") + App::new("solana-tokens") .about("about") .version("version") .arg( diff --git a/src/args.rs b/src/args.rs index cd2f5c37e26bb0..dd96833558ef53 100644 --- a/src/args.rs +++ b/src/args.rs @@ -34,8 +34,7 @@ pub fn resolve_command( ) -> Result>, Box> { match command { Command::Distribute(args) => { - let wallet_manager = maybe_wallet_manager()?; - let wallet_manager = wallet_manager.as_ref(); + let mut wallet_manager = maybe_wallet_manager()?; let matches = ArgMatches::default(); let resolved_args = DistributeArgs { bids_csv: args.bids_csv, @@ -43,10 +42,10 @@ pub fn resolve_command( dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run, sender_keypair: args.sender_keypair.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "sender", wallet_manager).unwrap() + signer_from_path(&matches, &key_url, "sender", &mut wallet_manager).unwrap() }), fee_payer: args.fee_payer.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "fee-payer", wallet_manager).unwrap() + signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() }), }; Ok(Command::Distribute(resolved_args)) From 24dc72c2690ce6dcfc9dab60dd36387b3728f8f7 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 24 Apr 2020 15:44:55 -0600 Subject: [PATCH 36/71] Remove faucet from integration test --- Cargo.lock | 392 ++++++++++++++++++++++++------------------------ Cargo.toml | 17 ++- tests/tokens.rs | 31 ++-- 3 files changed, 222 insertions(+), 218 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 280c8025f25d70..a3328a8f277eb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,9 +95,9 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" +checksum = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7" dependencies = [ "cc", "libc", @@ -161,7 +161,7 @@ dependencies = [ "log 0.4.8", "peeking_take_while", "proc-macro2 1.0.10", - "quote 1.0.3", + "quote 1.0.1", "regex", "rustc-hash", "shlex", @@ -239,9 +239,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "bstr" @@ -815,8 +815,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", "synstructure", ] @@ -959,8 +959,8 @@ checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] @@ -1099,7 +1099,7 @@ dependencies = [ "indexmap", "log 0.4.8", "slab", - "tokio 0.2.15", + "tokio 0.2.18", "tokio-util", ] @@ -1114,9 +1114,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" dependencies = [ "libc", ] @@ -1258,9 +1258,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6081100e960d9d74734659ffc9cc91daf1c0fc7aceb8eaa94ee1a3f5046f2e" +checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" dependencies = [ "bytes 0.5.4", "futures-channel", @@ -1275,7 +1275,7 @@ dependencies = [ "net2", "pin-project", "time", - "tokio 0.2.15", + "tokio 0.2.18", "tower-service", "want 0.3.0", ] @@ -1289,11 +1289,11 @@ dependencies = [ "bytes 0.5.4", "ct-logs", "futures-util", - "hyper 0.13.4", + "hyper 0.13.5", "log 0.4.8", "rustls", "rustls-native-certs", - "tokio 0.2.15", + "tokio 0.2.18", "tokio-rustls", "webpki", ] @@ -1447,9 +1447,9 @@ dependencies = [ [[package]] name = "jsonrpc-client-transports" -version = "14.0.5" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a9ae166c4d1f702d297cd76d4b55758ace80272ffc6dbb139fdc1bf810de40b" +checksum = "2307a7e78cf969759e390a8a2151ea12e783849a45bb00aa871b468ba58ea79e" dependencies = [ "failure", "futures", @@ -1465,9 +1465,9 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "14.0.5" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" +checksum = "25525f6002338fb4debb5167a89a0b47f727a5a48418417545ad3429758b7fec" dependencies = [ "futures", "log 0.4.8", @@ -1478,57 +1478,57 @@ dependencies = [ [[package]] name = "jsonrpc-core-client" -version = "14.0.5" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080dc110be17701097df238fad3c816d4a478a1899dfbcf8ec8957dd40ec7304" +checksum = "87f9382e831a6d630c658df103aac3f971da096deb57c136ea2b760d3b4e3f9f" dependencies = [ "jsonrpc-client-transports", ] [[package]] name = "jsonrpc-derive" -version = "14.0.5" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" +checksum = "d386855ea963193689078018f46f9f39e06acda14c10d396e153cfd728fc690c" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] name = "jsonrpc-http-server" -version = "14.0.6" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816d63997ea45d3634608edbef83ddb35e661f7c0b27b5b72f237e321f0e9807" +checksum = "d52860f0549694aa4abb12766856f56952ab46d3fb9f0815131b2db3d9cc2f29" dependencies = [ "hyper 0.12.35", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.8", "net2", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "unicase 2.6.0", ] [[package]] name = "jsonrpc-pubsub" -version = "14.0.6" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" +checksum = "c4ca5e391d6c6a2261d4adca029f427fe63ea546ad6cef2957c654c08495ec16" dependencies = [ "jsonrpc-core", "log 0.4.8", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "serde", ] [[package]] name = "jsonrpc-server-utils" -version = "14.0.5" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" +checksum = "1f06add502b48351e05dd95814835327fb115e4e9f834ca42fd522d3b769d4d2" dependencies = [ "bytes 0.4.12", "globset", @@ -1542,14 +1542,14 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" -version = "14.0.6" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94e5773b2ae66e0e02c80775ce6bbba6f15d5bb47c14ec36a36fcf94f8df851" +checksum = "017a7dd5083d9ed62c5e1dd3e317975c33c3115dac5447f4480fe05a8c354754" dependencies = [ "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.8", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "slab", "ws", ] @@ -1587,9 +1587,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" [[package]] name = "libloading" @@ -1603,9 +1603,9 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "6.6.4" +version = "6.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3b727e2dd20ec2fb7ed93f23d9fd5328a0871185485ebdaff007b47d3e27e4" +checksum = "883213ae3d09bfc3d104aefe94b25ebb183b6f4d3a515b23b14817e1f4854005" dependencies = [ "bindgen", "cc", @@ -1621,9 +1621,9 @@ checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" [[package]] name = "lock_api" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ "scopeguard", ] @@ -1841,8 +1841,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] @@ -1875,9 +1875,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", "libc", @@ -1906,9 +1906,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openssl" -version = "0.10.28" +version = "0.10.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" +checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd" dependencies = [ "bitflags", "cfg-if", @@ -1926,9 +1926,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.54" +version = "0.9.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" +checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8" dependencies = [ "autocfg 1.0.0", "cc", @@ -1950,12 +1950,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ "lock_api", - "parking_lot_core 0.7.0", + "parking_lot_core 0.7.2", ] [[package]] @@ -1975,15 +1975,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if", "cloudabi", "libc", "redox_syscall", - "smallvec 1.2.0", + "smallvec 1.4.0", "winapi 0.3.8", ] @@ -2005,8 +2005,8 @@ checksum = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] @@ -2039,22 +2039,22 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" +checksum = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" +checksum = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] @@ -2065,9 +2065,9 @@ checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" [[package]] name = "pin-utils" -version = "0.1.0-alpha.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" @@ -2155,9 +2155,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "49d77c41ca8767f2f41394c11a4eebccab83da25e7cc035387a3125f02be90a3" dependencies = [ "proc-macro2 1.0.10", ] @@ -2361,9 +2361,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.6" +version = "1.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" dependencies = [ "aho-corasick", "memchr", @@ -2408,7 +2408,7 @@ dependencies = [ "futures-util", "http 0.2.1", "http-body 0.3.1", - "hyper 0.13.4", + "hyper 0.13.5", "hyper-rustls", "js-sys", "lazy_static", @@ -2422,7 +2422,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "time", - "tokio 0.2.15", + "tokio 0.2.18", "tokio-rustls", "url 2.1.1", "wasm-bindgen", @@ -2449,9 +2449,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12069b106981c6103d3eab7dd1c86751482d0779a520b7c14954c8b586c1e643" +checksum = "61aa17a99a2413cd71c1106691bf59dad7de0cd5099127f90e9d99c429c40d4a" dependencies = [ "libc", "librocksdb-sys", @@ -2527,9 +2527,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "safemem" @@ -2574,9 +2574,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a" +checksum = "3f331b9025654145cd425b9ded0caf8f5ae0df80d418b326e2dc1c3dc5eb0620" dependencies = [ "bitflags", "core-foundation", @@ -2587,9 +2587,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f" +checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" dependencies = [ "core-foundation-sys", "libc", @@ -2612,9 +2612,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" dependencies = [ "serde_derive", ] @@ -2630,20 +2630,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] name = "serde_json" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" +checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" dependencies = [ "itoa", "ryu", @@ -2739,9 +2739,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" [[package]] name = "socket2" @@ -2757,9 +2757,9 @@ dependencies = [ [[package]] name = "solana-archiver-utils" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad60209b2812ca2149b3d50fdd04193c444b3d50a4ecd5c79bf3ada68ba73590" +checksum = "8614e23e38c2ac9b42200c22d5799abc8798e388fa239dd615596f9f92fb5eed" dependencies = [ "log 0.4.8", "rand 0.6.5", @@ -2773,9 +2773,9 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a05d411d070424b475478b2586a26d1b3da53effc08066675756700cd6123a25" +checksum = "695e1483e34fc138fe14c559d1357895a2b1d4afd922558f35a542e5af6a71c4" dependencies = [ "bincode", "byteorder", @@ -2791,9 +2791,9 @@ dependencies = [ [[package]] name = "solana-budget-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5326ff7b6a03e36597025259b34bc903034aa489dd40041a4a73a45ba9e653" +checksum = "15300fc7920ebcfdc77e3f88f3dc67c3df5697262fdf87bf9d2164aed902524e" dependencies = [ "bincode", "chrono", @@ -2808,9 +2808,9 @@ dependencies = [ [[package]] name = "solana-chacha" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97db655a19596404a5bdf685b1495187f8c14205652d2d5ae5da89bbe0a59369" +checksum = "785bf40d375afa52d2e49448d0e7661ef672efbb37043cee441bf9deec28a2b8" dependencies = [ "log 0.4.8", "rand 0.6.5", @@ -2824,9 +2824,9 @@ dependencies = [ [[package]] name = "solana-chacha-cuda" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54fc6713552e19bf56333fe592f84749123c221c31d2684366447de7d5e8adc2" +checksum = "f89ca4d1e8ef7e18b5f37c79ec8756b2b563ba40769c629c91eac44851e59c4e" dependencies = [ "log 0.4.8", "solana-archiver-utils", @@ -2839,18 +2839,18 @@ dependencies = [ [[package]] name = "solana-chacha-sys" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "898910294e5b152fdca397eee45c70f2d01c42757b47dedd302811fe1ebc9d0f" +checksum = "81320359331b5723bf73ca7ac6829d7fc8b52a37c8b90b9229e0baee99cce8ac" dependencies = [ "cc", ] [[package]] name = "solana-clap-utils" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c14abffc40c06a8fe8227429488eac65da416f739c2e5f7c9e0014f4f7e60" +checksum = "fbb8c1d8db18694aed03e1113eaa0a4eb8cf1aec3f06bfcd500ec427e69ec1c8" dependencies = [ "chrono", "clap", @@ -2864,9 +2864,9 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e00089763a5d11da50cf63fa9bfe96cefa402e895dc6988a3a998ae1d477ac" +checksum = "0aad29a487182b63ebf9871311f8aed60c05bc89b69a708f76f520b343d1f26b" dependencies = [ "dirs", "lazy_static", @@ -2878,9 +2878,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ccb3a57d0880bec3d8ffae8c8c67509641c91731aec4f3014c3d7a68a253d66" +checksum = "64eb5118ef1eeb25d4354ef13ca3937c7b34b248bcc4d53a975fa1c43c72ae6c" dependencies = [ "bincode", "bs58", @@ -2903,9 +2903,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415b93f33c8ab74d1d0400cd7eb63b03c49ed3b46b5484d2945d0eeb4e5fa979" +checksum = "d7b80f1fe61944b3d5390353df5eb366d99f92265bfcb6bf79b5dc2989012513" dependencies = [ "bincode", "chrono", @@ -2918,9 +2918,9 @@ dependencies = [ [[package]] name = "solana-core" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "087bdfed47de6e88d5875f85b278d7f62358a39e54d97d627b032f1184059a31" +checksum = "a2cef4443f588c75f775a86030a50ddc7bb774470fc93867c46ddb032f1a232f" dependencies = [ "bincode", "bs58", @@ -2983,9 +2983,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514ce92cd079728eee61b0e27dea56c168a24b3026b38db365febd3b660320a9" +checksum = "d8b9e89b0ad8df5063b9000ed75f839693d3f02baca6ca5136400ab18025bd23" dependencies = [ "backtrace", "bytes 0.4.12", @@ -3001,16 +3001,16 @@ dependencies = [ "reqwest", "serde", "syn 0.15.44", - "syn 1.0.17", + "syn 1.0.18", "tokio 0.1.22", "winapi 0.3.8", ] [[package]] name = "solana-exchange-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d48b97514d0403b2d7efb45458ece9eef6ee826d2871b4709c7202901f9a05b" +checksum = "491628e7dcb1a8701789118f532fabd6d5579811ee6a182f02e436ad12f12c20" dependencies = [ "bincode", "log 0.4.8", @@ -3026,9 +3026,9 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc63cd2a5cba11a2bd00f869b8469bc4089d3235dd7cedd5dddbf20579f2e6e" +checksum = "7a3f8e6c81e216482afae755abce1b6e8c50ee3b507db75687cd7eab037500a2" dependencies = [ "bincode", "byteorder", @@ -3047,9 +3047,9 @@ dependencies = [ [[package]] name = "solana-genesis-programs" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4c270b902aa2b9cd0a8c92db5617bf9128ba6db1c30de57145c8ef7ca62ab2" +checksum = "9ec01560e00e8e821c3cfd59b71143f2d2f0ef81cb7620bb16071353acf54f6a" dependencies = [ "log 0.4.8", "solana-bpf-loader-program", @@ -3066,9 +3066,9 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a24f1498404be3c271f525614d19a60ac3a0ef510b500c7271d050c0091980" +checksum = "9f8ebe46808a2df835f75b7cd2c92185f95e17a05b00c258fc5eabded93578bb" dependencies = [ "bincode", "byteorder", @@ -3112,9 +3112,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6200704d6a5c23a74753050c855aae6697f6ff0d1a3a7dce6381b7fb80580a96" +checksum = "89d558b778b5411818dbfbb2d63b4cffcec07a0c5a8801a7e42e815709811218" dependencies = [ "env_logger 0.7.1", "lazy_static", @@ -3123,9 +3123,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b5d7cdbde4d22c7af68a9c9fc71ae9013585f0e2d7d64f3361480ef9053511" +checksum = "a3d7009a43913b522b4b16c1dcca3797b160602c67bbbc8ad7ff8cbc78689ba1" dependencies = [ "jemalloc-ctl", "jemallocator", @@ -3136,9 +3136,9 @@ dependencies = [ [[package]] name = "solana-merkle-tree" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc163a7b9691a12e2c8af6fdbd7ec606d2eae5b2e0c5df5c57e7085589b60b91" +checksum = "4771aadf2895c017180ef9c7ab78d97c45e5d4dd73a7ce555ec66abebf85824e" dependencies = [ "fast-math", "solana-sdk", @@ -3146,9 +3146,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8f220cf0d9252e9635979bc3665a8b0f3a5f49fc1e9ea2989e9cfaa1e87c5b" +checksum = "20f4e692a2697519f42a78de3d4ac0e8da32ca64d13bf5ee0ca517a6ca714f24" dependencies = [ "env_logger 0.7.1", "gethostname", @@ -3160,9 +3160,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb496f1a802fc3d294847108829d1968c900c46d1acdf97c95a96e67fafc42b" +checksum = "2fdae65c5491476db7658b9089996e3336b7a91b149655d86e68b8bb2abc3560" dependencies = [ "bincode", "bytes 0.4.12", @@ -3181,9 +3181,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a54de5f5154a20bed1a0c4f0522c096613b5f2f2170fe00f36e236cbb0c8c57" +checksum = "246ff8024900c1fe8e0087730da533577bee0669a85d4dd702bdb74b0b6347ad" dependencies = [ "bincode", "dlopen", @@ -3202,9 +3202,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63256b0e360fe073e939a44b318a3e31110c00d9a159d83b50da2116310206a8" +checksum = "7a4475517aed6b0631a98347a12a3a7f9cfbe5a16194739645c31f9af392d89d" dependencies = [ "lazy_static", "num_cpus", @@ -3223,16 +3223,16 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3e75db1347abb88d27f6fc59cbb408428435cae65f808ec00b40fbaa075301" +checksum = "87f476c2b7b0b70721a4284747694543c7df8742fc4c3f5e1f79760966647f40" dependencies = [ "base32", "console", "dialoguer", "hidapi", "log 0.4.8", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "semver", "solana-sdk", "thiserror", @@ -3241,9 +3241,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18561821e669100cb2e147ada66bbca6e5ad55e6b1e93e9c52ebb6206f5c28" +checksum = "582dfaf264f8abafe7105844dc4b0d717bcd3fac2c049db22afcd7b4bdcbcf32" dependencies = [ "bincode", "bv", @@ -3278,9 +3278,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c4674e5e7b809af748909ea99c3572de3761536fa8e7136d2c31eeaf314a35" +checksum = "20aba22d0c5fd1e23cf074ae38c794d3dd955d0c98845bb30a5bf8c3009eb899" dependencies = [ "assert_matches", "bincode", @@ -3313,21 +3313,21 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64f6e9420c2cfae6b29661e83e2024518d3fe3f5adb94aa3999c4549d5fa089" +checksum = "8eb5d141bc2b9a114eddcdcf7ba2e7e3be29f32e4108d2bdb8a7e7e6c34ccc39" dependencies = [ "bs58", "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] name = "solana-stake-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08836c28e2276872bb233b4ce19e22e181fb70fadc193ddf8729d4dfda58ec" +checksum = "f60c74e77a83da31af36a07c057bc701ed57f5faedb2e7f5da2723823338aeb7" dependencies = [ "bincode", "log 0.4.8", @@ -3345,9 +3345,9 @@ dependencies = [ [[package]] name = "solana-storage-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab1129490c250b68c09b25883a8f36dcc41c4d26b17d451939c4196058c309a" +checksum = "eb6428be56e6e3ba2ae4e6b477d10a0a83b6ff993fe0ef83434e11108e5bd64b" dependencies = [ "bincode", "log 0.4.8", @@ -3362,9 +3362,9 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956be6b872c531f62a0f7c4792b36098fe6011abc28089ae262f30e7c6e417e4" +checksum = "5d8a25bbee675fa03bbe71fe690f80c50dcae63635ae8cc55fda77d91fde8ce8" dependencies = [ "libc", "log 0.4.8", @@ -3379,9 +3379,9 @@ dependencies = [ [[package]] name = "solana-sys-tuner" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366836f9f47126609c78ec7110793466b825ab92d1ef4bb33107524209a6f2f7" +checksum = "add85cc6ffeea2ed9d7e97d18e2dd96ae7d1c81e5f0b51e028487794b6d15c74" dependencies = [ "clap", "libc", @@ -3407,7 +3407,6 @@ dependencies = [ "solana-cli-config", "solana-client", "solana-core", - "solana-faucet", "solana-remote-wallet", "solana-runtime", "solana-sdk", @@ -3416,9 +3415,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2300c6cd4d7f400ba164a0f1578988ef04753665a134d1560adc0bb55bd8ef1c" +checksum = "dc11a90e2e3a0028e67041ed27f3943721d315898efd6321bd4cd70c39810dad" dependencies = [ "bincode", "bs58", @@ -3429,9 +3428,9 @@ dependencies = [ [[package]] name = "solana-vest-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ed2272e4a789af86f0cd032f71f4ccde67ce33137bf30a10ac061d2c146414e" +checksum = "843a9d05f464e1b4e66848129981e63d59e492bb20d7f974a53a16bf5a2cec58" dependencies = [ "bincode", "chrono", @@ -3446,9 +3445,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7987567350c099538e5555c7dea30718f6d40324ab97be3fe32b561c907f22" +checksum = "0fafad19ed179c3397c3e474f60297beab9517559afd67ae2379e5436f08f8ec" dependencies = [ "bincode", "log 0.4.8", @@ -3464,9 +3463,9 @@ dependencies = [ [[package]] name = "solana-vote-signer" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86ff7b8cf7a519b15a05aa808b2da75adf87030e65bc970cd1bed4c2634b427" +checksum = "b846102aeb160d98f1b6bac2782fab282ad8281cda0abc90393c92b4df6c37da" dependencies = [ "clap", "jsonrpc-core", @@ -3559,12 +3558,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", + "quote 1.0.1", "unicode-xid 0.2.0", ] @@ -3584,8 +3583,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", "unicode-xid 0.2.0", ] @@ -3639,9 +3638,9 @@ dependencies = [ [[package]] name = "termios" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" +checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2" dependencies = [ "libc", ] @@ -3657,22 +3656,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae" +checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd" +checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", ] [[package]] @@ -3686,12 +3685,11 @@ dependencies = [ [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall", "winapi 0.3.8", ] @@ -3737,9 +3735,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "619cdb2245c40c42d563089b72e80c5df659513d667a017598439ef7a7b1ffe1" +checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713" dependencies = [ "bytes 0.5.4", "fnv", @@ -3844,7 +3842,7 @@ checksum = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" dependencies = [ "futures-core", "rustls", - "tokio 0.2.15", + "tokio 0.2.18", "webpki", ] @@ -3956,7 +3954,7 @@ dependencies = [ "futures-sink", "log 0.4.8", "pin-project-lite", - "tokio 0.2.15", + "tokio 0.2.18", ] [[package]] @@ -4023,9 +4021,9 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicase" @@ -4060,7 +4058,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0", + "smallvec 1.4.0", ] [[package]] @@ -4229,8 +4227,8 @@ dependencies = [ "lazy_static", "log 0.4.8", "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", "wasm-bindgen-shared", ] @@ -4252,7 +4250,7 @@ version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" dependencies = [ - "quote 1.0.3", + "quote 1.0.1", "wasm-bindgen-macro-support", ] @@ -4263,8 +4261,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" dependencies = [ "proc-macro2 1.0.10", - "quote 1.0.3", - "syn 1.0.17", + "quote 1.0.1", + "syn 1.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4384,9 +4382,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi 0.3.8", ] diff --git a/Cargo.toml b/Cargo.toml index efce748bd71692..dbf3689bd1810c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,12 +14,13 @@ clap = "2.33.0" console = "0.10.0" indexmap = "1.3.2" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = "1.1.6" -solana-cli-config = "1.1.6" -solana-client = "1.1.6" -solana-core = "1.1.6" -solana-faucet = "1.1.6" -solana-remote-wallet = "1.1.6" -solana-runtime = "1.1.6" -solana-sdk = "1.1.6" +solana-clap-utils = "1.1.7" +solana-cli-config = "1.1.7" +solana-client = "1.1.7" +solana-remote-wallet = "1.1.7" +solana-runtime = "1.1.7" +solana-sdk = "1.1.7" tempfile = "3.1.0" + +[dev-dependencies] +solana-core = "1.1.7" diff --git a/tests/tokens.rs b/tests/tokens.rs index 3c5f96c31f46bc..8c9ab3dce41a99 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,29 +1,34 @@ use solana_client::rpc_client::RpcClient; use solana_core::validator::TestValidator; -use solana_faucet::faucet::{request_airdrop_transaction, run_local_faucet}; -use solana_sdk::signature::{Keypair, Signer}; +use solana_sdk::{ + signature::{Keypair, Signer}, + system_instruction, + transaction::Transaction, +}; use solana_tokens::{thin_client::ThinClient, tokens::test_process_distribute_with_client}; -use std::sync::mpsc::channel; +use std::fs::remove_dir_all; #[test] #[ignore] fn test_process_distribute_with_rpc_client() { let validator = TestValidator::run(); - let (sender, receiver) = channel(); - run_local_faucet(validator.alice, sender, None); - let faucet_addr = receiver.recv().unwrap(); - let rpc_client = RpcClient::new_socket(validator.leader_data.rpc); + + let bob = Keypair::new(); + let instruction = system_instruction::transfer(&validator.alice.pubkey(), &bob.pubkey(), 1); let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash().unwrap(); - let funding_keypair = Keypair::new(); - let lamports = 1_000; + let signers = vec![&validator.alice]; + let mut transaction = - request_airdrop_transaction(&faucet_addr, &funding_keypair.pubkey(), lamports, blockhash) - .unwrap(); + Transaction::new_signed_instructions(&signers, vec![instruction], blockhash); rpc_client - .send_and_confirm_transaction_with_spinner(&mut transaction, &[&funding_keypair]) + .send_and_confirm_transaction_with_spinner(&mut transaction, &signers) .unwrap(); + assert_ne!(rpc_client.get_balance(&bob.pubkey()).unwrap(), 0); let thin_client = ThinClient(rpc_client); - test_process_distribute_with_client(&thin_client, funding_keypair); + test_process_distribute_with_client(&thin_client, bob); + + validator.server.close().unwrap(); + remove_dir_all(validator.ledger_path).unwrap(); } From 29dbb532f913036177df9ecee48ff39e8a0dbe58 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 27 Apr 2020 14:53:55 -0600 Subject: [PATCH 37/71] Cleaner integration test Won't work until this lands and is released: https://github.com/solana-labs/solana/pull/9717 --- src/tokens.rs | 9 +++------ tests/tokens.rs | 31 ++++++++----------------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 85aac21f9cf7bc..97504b3e4368c4 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -284,10 +284,8 @@ pub fn process_balances( use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; -pub fn test_process_distribute_with_client( - thin_client: &ThinClient, - sender_keypair: Keypair, -) { +pub fn test_process_distribute_with_client(client: C, sender_keypair: Keypair) { + let thin_client = ThinClient(client); let fee_payer = Keypair::new(); thin_client .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) @@ -357,8 +355,7 @@ mod tests { let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let bank = Bank::new(&genesis_config); let bank_client = BankClient::new(bank); - let thin_client = ThinClient(bank_client); - test_process_distribute_with_client(&thin_client, sender_keypair); + test_process_distribute_with_client(bank_client, sender_keypair); } #[test] diff --git a/tests/tokens.rs b/tests/tokens.rs index 8c9ab3dce41a99..7a669a3944f18d 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,33 +1,18 @@ use solana_client::rpc_client::RpcClient; -use solana_core::validator::TestValidator; -use solana_sdk::{ - signature::{Keypair, Signer}, - system_instruction, - transaction::Transaction, -}; -use solana_tokens::{thin_client::ThinClient, tokens::test_process_distribute_with_client}; +use solana_core::validator::{TestValidator, TestValidatorOptions}; +use solana_sdk::native_token::sol_to_lamports; +use solana_tokens::tokens::test_process_distribute_with_client; use std::fs::remove_dir_all; #[test] #[ignore] fn test_process_distribute_with_rpc_client() { - let validator = TestValidator::run(); + let validator = TestValidator::run_with_options(TestValidatorOptions { + mint_lamports: sol_to_lamports(9_000_000.0), + ..TestValidatorOptions::default() + }); let rpc_client = RpcClient::new_socket(validator.leader_data.rpc); - - let bob = Keypair::new(); - let instruction = system_instruction::transfer(&validator.alice.pubkey(), &bob.pubkey(), 1); - let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash().unwrap(); - let signers = vec![&validator.alice]; - - let mut transaction = - Transaction::new_signed_instructions(&signers, vec![instruction], blockhash); - rpc_client - .send_and_confirm_transaction_with_spinner(&mut transaction, &signers) - .unwrap(); - assert_ne!(rpc_client.get_balance(&bob.pubkey()).unwrap(), 0); - - let thin_client = ThinClient(rpc_client); - test_process_distribute_with_client(&thin_client, bob); + test_process_distribute_with_client(rpc_client, validator.alice); validator.server.close().unwrap(); remove_dir_all(validator.ledger_path).unwrap(); From 3830038786deae0c44bf54a735cbd4c831bfb291 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 27 Apr 2020 14:56:23 -0600 Subject: [PATCH 38/71] Update README --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b8bddaf7c16e90..ad98da5327b116 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ expected amount are sent. The command-line tool here automates that process. ## Distribute tokens -Send tokens to the recipients in ``. +Send tokens to the recipients in ``. -Example allocations.csv: +Example bids.csv: ```text primary_address,bid_amount_dollars @@ -17,7 +17,7 @@ primary_address,bid_amount_dollars ``` ```bash -solana-tokens distribute --from --dollars-per-sol --fee-payer +solana-tokens distribute --from --dollars-per-sol --bids-csv --fee-payer ``` Example transaction log before: @@ -27,11 +27,11 @@ recipient,amount,signature 6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,30,1111111111111111111111111111111111111111111111111111111111111111 ``` -Send tokens to the recipients in `` if the distribution is +Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute --from --dollars-per-sol --fee-payer +solana-tokens distribute --from --dollars-per-sol --bids-csv --fee-payer ``` Example output: @@ -60,10 +60,10 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute --dollars-per-sol --dry-run +solana-tokens distribute --dollars-per-sol --dry-run --bids-csv ``` -Example allocations.csv: +Example bids.csv: ```text primary_address,bid_amount_dollars From 4b445521b0b317906b3c71fc03b6beab35eb03af Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 27 Apr 2020 15:12:31 -0600 Subject: [PATCH 39/71] Add TravicCI script to build and test (#1) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000000..22761ba7ee19a9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1 @@ +language: rust From 2148fb34e86b053b955a6f8d2cbd9b4dd7a8a4cd Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 29 Apr 2020 15:51:11 -0600 Subject: [PATCH 40/71] Add distribute-stake command (#2) --- .travis.yml | 6 + Cargo.lock | 361 +++++++++++++++++++++++++--------------------- Cargo.toml | 17 ++- src/arg_parser.rs | 79 +++++++++- src/args.rs | 58 +++++++- src/main.rs | 3 + src/tokens.rs | 291 ++++++++++++++++++++++++++++++++----- 7 files changed, 602 insertions(+), 213 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22761ba7ee19a9..cba263c127543c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,7 @@ language: rust +addons: + apt: + packages: + - pkg-config + - libudev-dev + update: true diff --git a/Cargo.lock b/Cargo.lock index a3328a8f277eb4..a414897811af97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -371,7 +371,7 @@ checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" dependencies = [ "glob 0.3.0", "libc", - "libloading", + "libloading 0.5.2", ] [[package]] @@ -442,20 +442,38 @@ dependencies = [ [[package]] name = "console" -version = "0.10.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6728a28023f207181b193262711102bfbaf47cc9d13bc71d0736607ef8efe88c" +checksum = "2586208b33573b7f76ccfbe5adb076394c88deaf81b84d7213969805b0a952a7" dependencies = [ "clicolors-control", "encode_unicode", "lazy_static", "libc", "regex", + "terminal_size", "termios", "unicode-width", "winapi 0.3.8", ] +[[package]] +name = "console" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea0f3e2e8d7dba335e913b97f9e1992c86c4399d54f8be1d31c8727d0652064" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "termios", + "unicode-width", + "winapi 0.3.8", + "winapi-util", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -599,24 +617,24 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "1.2.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" +checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" dependencies = [ "byteorder", - "clear_on_drop", "digest 0.8.1", - "rand_core 0.3.1", + "rand_core 0.5.1", "subtle 2.2.2", + "zeroize", ] [[package]] name = "dialoguer" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94616e25d2c04fc97253d145f6ca33ad84a584258dc70c4e621cc79a57f903b6" +checksum = "d8b5eb0fce3c4f955b8d8d864b131fb8863959138da962026c106ba7a2e3bf7a" dependencies = [ - "console", + "console 0.10.3", "lazy_static", "tempfile", ] @@ -701,14 +719,13 @@ checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" [[package]] name = "ed25519-dalek" -version = "1.0.0-pre.1" +version = "1.0.0-pre.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" +checksum = "978710b352437433c97b2bff193f2fb1dfd58a093f863dd95e225a19baa599a2" dependencies = [ "clear_on_drop", "curve25519-dalek", - "failure", - "rand 0.6.5", + "rand 0.7.3", "serde", "sha2 0.8.1", ] @@ -1012,9 +1029,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.13.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +checksum = "6d2664c2cf08049036f31015b04c6ac3671379a1d86f52ed2416893f16022deb" dependencies = [ "serde", "typenum", @@ -1347,7 +1364,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a68371cf417889c9d7f98235b7102ea7c54fc59bcbd22f3dea785be9d27e40" dependencies = [ - "console", + "console 0.11.2", "lazy_static", "number_prefix", "regex", @@ -1601,6 +1618,15 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "libloading" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c4f51b790f5bdb65acb4cc94bb81d7b2ee60348a5431ac1467d390b017600b0" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "librocksdb-sys" version = "6.7.4" @@ -2359,6 +2385,17 @@ dependencies = [ "rust-argon2", ] +[[package]] +name = "reed-solomon-erasure" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a415a013dd7c5d4221382329a5a3482566da675737494935cbbbcdec04662f9d" +dependencies = [ + "cc", + "libc", + "smallvec 1.4.0", +] + [[package]] name = "regex" version = "1.3.7" @@ -2757,12 +2794,11 @@ dependencies = [ [[package]] name = "solana-archiver-utils" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8614e23e38c2ac9b42200c22d5799abc8798e388fa239dd615596f9f92fb5eed" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "log 0.4.8", - "rand 0.6.5", + "rand 0.7.3", "solana-chacha", "solana-chacha-sys", "solana-ledger", @@ -2773,17 +2809,17 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695e1483e34fc138fe14c559d1357895a2b1d4afd922558f35a542e5af6a71c4" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "byteorder", - "libc", + "jemalloc-sys", "log 0.4.8", "num-derive 0.3.0", "num-traits 0.2.11", "solana-logger", + "solana-runtime", "solana-sdk", "solana_rbpf", "thiserror", @@ -2791,9 +2827,8 @@ dependencies = [ [[package]] name = "solana-budget-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15300fc7920ebcfdc77e3f88f3dc67c3df5697262fdf87bf9d2164aed902524e" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "chrono", @@ -2808,13 +2843,12 @@ dependencies = [ [[package]] name = "solana-chacha" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785bf40d375afa52d2e49448d0e7661ef672efbb37043cee441bf9deec28a2b8" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "log 0.4.8", - "rand 0.6.5", - "rand_chacha 0.1.1", + "rand 0.7.3", + "rand_chacha 0.2.2", "solana-chacha-sys", "solana-ledger", "solana-logger", @@ -2824,9 +2858,8 @@ dependencies = [ [[package]] name = "solana-chacha-cuda" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89ca4d1e8ef7e18b5f37c79ec8756b2b563ba40769c629c91eac44851e59c4e" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "log 0.4.8", "solana-archiver-utils", @@ -2839,18 +2872,16 @@ dependencies = [ [[package]] name = "solana-chacha-sys" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81320359331b5723bf73ca7ac6829d7fc8b52a37c8b90b9229e0baee99cce8ac" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "cc", ] [[package]] name = "solana-clap-utils" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb8c1d8db18694aed03e1113eaa0a4eb8cf1aec3f06bfcd500ec427e69ec1c8" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "chrono", "clap", @@ -2864,9 +2895,8 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aad29a487182b63ebf9871311f8aed60c05bc89b69a708f76f520b343d1f26b" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "dirs", "lazy_static", @@ -2878,9 +2908,8 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64eb5118ef1eeb25d4354ef13ca3937c7b34b248bcc4d53a975fa1c43c72ae6c" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "bs58", @@ -2903,24 +2932,21 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b80f1fe61944b3d5390353df5eb366d99f92265bfcb6bf79b5dc2989012513" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "chrono", "log 0.4.8", "serde", "serde_derive", - "solana-logger", "solana-sdk", ] [[package]] name = "solana-core" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2cef4443f588c75f775a86030a50ddc7bb774470fc93867c46ddb032f1a232f" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "bs58", @@ -2943,13 +2969,14 @@ dependencies = [ "log 0.4.8", "num-traits 0.2.11", "num_cpus", - "rand 0.6.5", - "rand_chacha 0.1.1", + "rand 0.7.3", + "rand_chacha 0.2.2", "rayon", "regex", "serde", "serde_derive", "serde_json", + "solana-bpf-loader-program", "solana-budget-program", "solana-chacha-cuda", "solana-clap-utils", @@ -2983,9 +3010,8 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b9e89b0ad8df5063b9000ed75f839693d3f02baca6ca5136400ab18025bd23" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "backtrace", "bytes 0.4.12", @@ -2996,7 +3022,7 @@ dependencies = [ "failure", "lazy_static", "libc", - "rand_chacha 0.1.1", + "rand_chacha 0.2.2", "regex-syntax", "reqwest", "serde", @@ -3008,9 +3034,8 @@ dependencies = [ [[package]] name = "solana-exchange-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491628e7dcb1a8701789118f532fabd6d5579811ee6a182f02e436ad12f12c20" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "log 0.4.8", @@ -3026,9 +3051,8 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3f8e6c81e216482afae755abce1b6e8c50ee3b507db75687cd7eab037500a2" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "byteorder", @@ -3047,28 +3071,23 @@ dependencies = [ [[package]] name = "solana-genesis-programs" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec01560e00e8e821c3cfd59b71143f2d2f0ef81cb7620bb16071353acf54f6a" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "log 0.4.8", "solana-bpf-loader-program", "solana-budget-program", - "solana-config-program", "solana-exchange-program", "solana-runtime", "solana-sdk", - "solana-stake-program", "solana-storage-program", "solana-vest-program", - "solana-vote-program", ] [[package]] name = "solana-ledger" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f8ebe46808a2df835f75b7cd2c92185f95e17a05b00c258fc5eabded93578bb" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "byteorder", @@ -3077,15 +3096,17 @@ dependencies = [ "crossbeam-channel", "dir-diff", "ed25519-dalek", + "flate2", "fs_extra", "itertools 0.9.0", "lazy_static", "libc", "log 0.4.8", "num_cpus", - "rand 0.6.5", - "rand_chacha 0.1.1", + "rand 0.7.3", + "rand_chacha 0.2.2", "rayon", + "reed-solomon-erasure", "regex", "rocksdb", "serde", @@ -3098,7 +3119,6 @@ dependencies = [ "solana-metrics", "solana-perf", "solana-rayon-threadlimit", - "solana-reed-solomon-erasure", "solana-runtime", "solana-sdk", "solana-stake-program", @@ -3108,13 +3128,13 @@ dependencies = [ "tar", "tempfile", "thiserror", + "zstd", ] [[package]] name = "solana-logger" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d558b778b5411818dbfbb2d63b4cffcec07a0c5a8801a7e42e815709811218" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "env_logger 0.7.1", "lazy_static", @@ -3123,9 +3143,8 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d7009a43913b522b4b16c1dcca3797b160602c67bbbc8ad7ff8cbc78689ba1" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "jemalloc-ctl", "jemallocator", @@ -3136,9 +3155,8 @@ dependencies = [ [[package]] name = "solana-merkle-tree" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4771aadf2895c017180ef9c7ab78d97c45e5d4dd73a7ce555ec66abebf85824e" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "fast-math", "solana-sdk", @@ -3146,9 +3164,8 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f4e692a2697519f42a78de3d4ac0e8da32ca64d13bf5ee0ca517a6ca714f24" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "env_logger 0.7.1", "gethostname", @@ -3160,16 +3177,15 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fdae65c5491476db7658b9089996e3336b7a91b149655d86e68b8bb2abc3560" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "bytes 0.4.12", "clap", "log 0.4.8", "nix", - "rand 0.6.5", + "rand 0.7.3", "serde", "serde_derive", "socket2", @@ -3181,16 +3197,15 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246ff8024900c1fe8e0087730da533577bee0669a85d4dd702bdb74b0b6347ad" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "dlopen", "dlopen_derive", "lazy_static", "log 0.4.8", - "rand 0.6.5", + "rand 0.7.3", "rayon", "serde", "solana-budget-program", @@ -3202,33 +3217,20 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4475517aed6b0631a98347a12a3a7f9cfbe5a16194739645c31f9af392d89d" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "lazy_static", "num_cpus", ] -[[package]] -name = "solana-reed-solomon-erasure" -version = "4.0.1-3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5b3ab3f4dd12af687a7d0d0ee73299cbc06ed3aada42dccac26fe243e73399e" -dependencies = [ - "cc", - "libc", - "smallvec 0.6.13", -] - [[package]] name = "solana-remote-wallet" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f476c2b7b0b70721a4284747694543c7df8742fc4c3f5e1f79760966647f40" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "base32", - "console", + "console 0.10.3", "dialoguer", "hidapi", "log 0.4.8", @@ -3241,9 +3243,8 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "582dfaf264f8abafe7105844dc4b0d717bcd3fac2c049db22afcd7b4bdcbcf32" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "bv", @@ -3253,17 +3254,17 @@ dependencies = [ "itertools 0.9.0", "lazy_static", "libc", - "libloading", + "libloading 0.6.1", "log 0.4.8", "memmap", "num-derive 0.3.0", "num-traits 0.2.11", "num_cpus", - "rand 0.6.5", + "rand 0.7.3", "rayon", "serde", "serde_derive", - "solana-bpf-loader-program", + "solana-config-program", "solana-logger", "solana-measure", "solana-metrics", @@ -3278,9 +3279,8 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20aba22d0c5fd1e23cf074ae38c794d3dd955d0c98845bb30a5bf8c3009eb899" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "assert_matches", "bincode", @@ -3289,7 +3289,7 @@ dependencies = [ "byteorder", "chrono", "ed25519-dalek", - "generic-array 0.13.2", + "generic-array 0.14.1", "hex", "hmac", "itertools 0.9.0", @@ -3298,8 +3298,8 @@ dependencies = [ "num-derive 0.3.0", "num-traits 0.2.11", "pbkdf2", - "rand 0.6.5", - "rand_chacha 0.1.1", + "rand 0.7.3", + "rand_chacha 0.2.2", "serde", "serde_bytes", "serde_derive", @@ -3313,9 +3313,8 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb5d141bc2b9a114eddcdcf7ba2e7e3be29f32e4108d2bdb8a7e7e6c34ccc39" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bs58", "proc-macro2 1.0.10", @@ -3325,9 +3324,8 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60c74e77a83da31af36a07c057bc701ed57f5faedb2e7f5da2723823338aeb7" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "log 0.4.8", @@ -3336,7 +3334,6 @@ dependencies = [ "serde", "serde_derive", "solana-config-program", - "solana-logger", "solana-metrics", "solana-sdk", "solana-vote-program", @@ -3345,15 +3342,14 @@ dependencies = [ [[package]] name = "solana-storage-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb6428be56e6e3ba2ae4e6b477d10a0a83b6ff993fe0ef83434e11108e5bd64b" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "log 0.4.8", "num-derive 0.3.0", "num-traits 0.2.11", - "rand 0.6.5", + "rand 0.7.3", "serde", "serde_derive", "solana-logger", @@ -3362,9 +3358,8 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8a25bbee675fa03bbe71fe690f80c50dcae63635ae8cc55fda77d91fde8ce8" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "libc", "log 0.4.8", @@ -3379,9 +3374,8 @@ dependencies = [ [[package]] name = "solana-sys-tuner" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add85cc6ffeea2ed9d7e97d18e2dd96ae7d1c81e5f0b51e028487794b6d15c74" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "clap", "libc", @@ -3399,7 +3393,7 @@ name = "solana-tokens" version = "0.1.1" dependencies = [ "clap", - "console", + "console 0.10.3", "csv", "indexmap", "serde", @@ -3410,14 +3404,14 @@ dependencies = [ "solana-remote-wallet", "solana-runtime", "solana-sdk", + "solana-stake-program", "tempfile", ] [[package]] name = "solana-transaction-status" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc11a90e2e3a0028e67041ed27f3943721d315898efd6321bd4cd70c39810dad" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "bs58", @@ -3428,9 +3422,8 @@ dependencies = [ [[package]] name = "solana-vest-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843a9d05f464e1b4e66848129981e63d59e492bb20d7f974a53a16bf5a2cec58" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "chrono", @@ -3445,9 +3438,8 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafad19ed179c3397c3e474f60297beab9517559afd67ae2379e5436f08f8ec" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "bincode", "log 0.4.8", @@ -3455,7 +3447,6 @@ dependencies = [ "num-traits 0.2.11", "serde", "serde_derive", - "solana-logger", "solana-metrics", "solana-sdk", "thiserror", @@ -3463,9 +3454,8 @@ dependencies = [ [[package]] name = "solana-vote-signer" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b846102aeb160d98f1b6bac2782fab282ad8281cda0abc90393c92b4df6c37da" +version = "1.2.0" +source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" dependencies = [ "clap", "jsonrpc-core", @@ -3636,6 +3626,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8038f95fc7a6f351163f4b964af631bd26c9e828f7db085f2a84aca56f70d13b" +dependencies = [ + "libc", + "winapi 0.3.8", +] + [[package]] name = "termios" version = "0.3.2" @@ -4124,11 +4124,12 @@ dependencies = [ [[package]] name = "users" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c72f4267aea0c3ec6d07eaabea6ead7c5ddacfafc5e22bcf8d186706851fb4cf" +checksum = "aa4227e95324a443c9fcb06e03d4d85e91aabe9a5a02aa818688b6918b6af486" dependencies = [ "libc", + "log 0.4.8", ] [[package]] @@ -4449,3 +4450,39 @@ checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zeroize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" + +[[package]] +name = "zstd" +version = "0.5.1+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5d978b793ae64375b80baf652919b148f6a496ac8802922d9999f5a553194f" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "2.0.3+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee25eac9753cfedd48133fa1736cbd23b774e253d89badbeac7d12b23848d3f" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.4.15+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89719b034dc22d240d5b407fb0a3fe6d29952c181cff9a9f95c0bd40b4f8f7d8" +dependencies = [ + "cc", + "glob 0.3.0", + "libc", +] diff --git a/Cargo.toml b/Cargo.toml index dbf3689bd1810c..36ac4653654670 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,16 +11,17 @@ homepage = "https://solana.com/" [dependencies] csv = "1.1.3" clap = "2.33.0" -console = "0.10.0" +console = "0.10.3" indexmap = "1.3.2" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = "1.1.7" -solana-cli-config = "1.1.7" -solana-client = "1.1.7" -solana-remote-wallet = "1.1.7" -solana-runtime = "1.1.7" -solana-sdk = "1.1.7" +solana-clap-utils = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-cli-config = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-client = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-remote-wallet = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-runtime = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-sdk = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-stake-program = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} tempfile = "3.1.0" [dev-dependencies] -solana-core = "1.1.7" +solana-core = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} diff --git a/src/arg_parser.rs b/src/arg_parser.rs index c03a0fc6ba6afc..833ebf5df83d80 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,6 +1,6 @@ -use crate::args::{Args, BalancesArgs, Command, DistributeArgs}; +use crate::args::{Args, BalancesArgs, Command, DistributeArgs, DistributeStakeArgs}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; -use solana_clap_utils::input_validators::is_valid_signer; +use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; use solana_cli_config::CONFIG_FILE; use std::ffi::OsString; use std::process::exit; @@ -79,6 +79,64 @@ where .help("Fee payer"), ), ) + .subcommand( + SubCommand::with_name("distribute-stake") + .about("Distribute stake accounts") + .arg( + Arg::with_name("transactions_csv") + .required(true) + .index(1) + .takes_value(true) + .value_name("FILE") + .help("Transactions CSV file"), + ) + .arg( + Arg::with_name("allocations_csv") + .long("allocations-csv") + .required(true) + .takes_value(true) + .value_name("FILE") + .help("Allocations CSV file"), + ) + .arg( + Arg::with_name("dry_run") + .long("dry-run") + .help("Do not execute any transfers"), + ) + .arg( + Arg::with_name("stake_account_address") + .required(true) + .long("stake-account-address") + .takes_value(true) + .value_name("ACCOUNT_ADDRESS") + .validator(is_valid_pubkey) + .help("Stake Account Address"), + ) + .arg( + Arg::with_name("stake_authority") + .long("stake-authority") + .takes_value(true) + .value_name("KEYPAIR") + .validator(is_valid_signer) + .help("Stake Authority Keypair"), + ) + .arg( + Arg::with_name("withdraw_authority") + .long("withdraw-authority") + .takes_value(true) + .value_name("KEYPAIR") + .validator(is_valid_signer) + .help("Withdraw Authority Keypair"), + ) + .arg( + Arg::with_name("fee_payer") + .long("fee-payer") + .takes_value(true) + .value_name("KEYPAIR") + .validator(is_valid_signer) + .help("Fee payer"), + ), + ) .subcommand( SubCommand::with_name("balances") .about("Balance of each account") @@ -113,6 +171,18 @@ fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { } } +fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs { + DistributeStakeArgs { + allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), + transactions_csv: value_t_or_exit!(matches, "transactions_csv", String), + dry_run: matches.is_present("dry_run"), + stake_account_address: value_t_or_exit!(matches, "stake_account_address", String), + stake_authority: value_t!(matches, "stake_authority", String).ok(), + withdraw_authority: value_t!(matches, "withdraw_authority", String).ok(), + fee_payer: value_t!(matches, "fee_payer", String).ok(), + } +} + fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { BalancesArgs { bids_csv: value_t_or_exit!(matches, "bids_csv", String), @@ -120,7 +190,7 @@ fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { } } -pub fn parse_args(args: I) -> Args +pub fn parse_args(args: I) -> Args where I: IntoIterator, T: Into + Clone, @@ -131,6 +201,9 @@ where let command = match matches.subcommand() { ("distribute", Some(matches)) => Command::Distribute(parse_distribute_args(matches)), + ("distribute-stake", Some(matches)) => { + Command::DistributeStake(parse_distribute_stake_args(matches)) + } ("balances", Some(matches)) => Command::Balances(parse_balances_args(matches)), _ => { eprintln!("{}", matches.usage()); diff --git a/src/args.rs b/src/args.rs index dd96833558ef53..ca9d4c7bd4a12c 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,7 +1,7 @@ use clap::ArgMatches; -use solana_clap_utils::keypair::signer_from_path; +use solana_clap_utils::keypair::{pubkey_from_path, signer_from_path}; use solana_remote_wallet::remote_wallet::maybe_wallet_manager; -use solana_sdk::signature::Signer; +use solana_sdk::{pubkey::Pubkey, signature::Signer}; use std::error::Error; pub struct DistributeArgs { @@ -13,25 +13,36 @@ pub struct DistributeArgs { pub fee_payer: Option, } +pub struct DistributeStakeArgs { + pub allocations_csv: String, + pub transactions_csv: String, + pub dry_run: bool, + pub stake_account_address: P, + pub stake_authority: Option, + pub withdraw_authority: Option, + pub fee_payer: Option, +} + pub struct BalancesArgs { pub bids_csv: String, pub dollars_per_sol: f64, } -pub enum Command { +pub enum Command { Distribute(DistributeArgs), + DistributeStake(DistributeStakeArgs), Balances(BalancesArgs), } -pub struct Args { +pub struct Args { pub config_file: String, pub url: Option, - pub command: Command, + pub command: Command, } pub fn resolve_command( - command: Command, -) -> Result>, Box> { + command: Command, +) -> Result>, Box> { match command { Command::Distribute(args) => { let mut wallet_manager = maybe_wallet_manager()?; @@ -50,6 +61,39 @@ pub fn resolve_command( }; Ok(Command::Distribute(resolved_args)) } + Command::DistributeStake(args) => { + let mut wallet_manager = maybe_wallet_manager()?; + let matches = ArgMatches::default(); + let resolved_args = DistributeStakeArgs { + allocations_csv: args.allocations_csv, + transactions_csv: args.transactions_csv, + dry_run: args.dry_run, + stake_account_address: pubkey_from_path( + &matches, + &args.stake_account_address, + "stake account address", + &mut wallet_manager, + ) + .unwrap(), + stake_authority: args.stake_authority.as_ref().map(|key_url| { + signer_from_path(&matches, &key_url, "stake authority", &mut wallet_manager) + .unwrap() + }), + withdraw_authority: args.withdraw_authority.as_ref().map(|key_url| { + signer_from_path( + &matches, + &key_url, + "withdraw authority", + &mut wallet_manager, + ) + .unwrap() + }), + fee_payer: args.fee_payer.as_ref().map(|key_url| { + signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() + }), + }; + Ok(Command::DistributeStake(resolved_args)) + } Command::Balances(args) => Ok(Command::Balances(args)), } } diff --git a/src/main.rs b/src/main.rs index c7ee0d1a969574..f0f1ef27184890 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,9 @@ fn main() -> Result<(), Box> { Command::Distribute(args) => { tokens::process_distribute(&thin_client, &args)?; } + Command::DistributeStake(args) => { + tokens::process_distribute_stake(&thin_client, &args)?; + } Command::Balances(args) => { tokens::process_balances(&thin_client, &args)?; } diff --git a/src/tokens.rs b/src/tokens.rs index 97504b3e4368c4..4730ad3c2c9afe 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,4 +1,4 @@ -use crate::args::{BalancesArgs, DistributeArgs}; +use crate::args::{BalancesArgs, DistributeArgs, DistributeStakeArgs}; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; @@ -10,6 +10,10 @@ use solana_sdk::{ signature::{Signature, Signer}, system_instruction, }; +use solana_stake_program::{ + stake_instruction, + stake_state::{Authorized, Lockup, StakeAuthorize}, +}; use std::fs; use std::path::Path; use std::process; @@ -20,7 +24,7 @@ struct Bid { primary_address: String, } -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] struct Allocation { recipient: String, amount: f64, @@ -31,6 +35,7 @@ struct TransactionInfo { recipient: String, amount: f64, signature: String, + new_stake_account_address: String, } fn merge_allocations(allocations: &[Allocation]) -> Vec { @@ -108,7 +113,89 @@ fn distribute_tokens( Ok(signature) => { println!("Finalized transaction with signature {}", signature); if !args.dry_run { - append_transaction_info(&allocation, &signature, &args.transactions_csv)?; + append_transaction_info(&allocation, &signature, None, &args.transactions_csv)?; + } + } + Err(e) => { + eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); + } + }; + } + Ok(()) +} + +fn distribute_stake( + client: &ThinClient, + allocations: &[Allocation], + args: &DistributeStakeArgs>, +) -> Result<(), csv::Error> { + let new_stake_account_keypair = Keypair::new(); + let new_stake_account_address = new_stake_account_keypair.pubkey(); + let signers = if args.dry_run { + vec![] + } else { + vec![ + &**args.fee_payer.as_ref().unwrap(), + &**args.stake_authority.as_ref().unwrap(), + &**args.withdraw_authority.as_ref().unwrap(), + &new_stake_account_keypair, + ] + }; + + for allocation in allocations { + println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); + let result = if args.dry_run { + Ok(Signature::default()) + } else { + let system_sol = 1.0; + let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); + let stake_authority = args.stake_authority.as_ref().unwrap().pubkey(); + let withdraw_authority = args.withdraw_authority.as_ref().unwrap().pubkey(); + + let mut instructions = stake_instruction::split( + &args.stake_account_address, + &stake_authority, + sol_to_lamports(allocation.amount - system_sol), + &new_stake_account_address, + ); + + let recipient = allocation.recipient.parse().unwrap(); + + // Make the recipient the new stake authority + instructions.push(stake_instruction::authorize( + &new_stake_account_address, + &stake_authority, + &recipient, + StakeAuthorize::Staker, + )); + + // Make the recipient the new withdraw authority + instructions.push(stake_instruction::authorize( + &new_stake_account_address, + &withdraw_authority, + &recipient, + StakeAuthorize::Withdrawer, + )); + + instructions.push(system_instruction::transfer( + &fee_payer_pubkey, // Should this be a sender keypair? + &recipient, + sol_to_lamports(system_sol), + )); + + let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); + client.send_message(message, &signers) + }; + match result { + Ok(signature) => { + println!("Finalized transaction with signature {}", signature); + if !args.dry_run { + append_transaction_info( + &allocation, + &signature, + Some(&new_stake_account_address), + &args.transactions_csv, + )?; } } Err(e) => { @@ -130,6 +217,7 @@ fn read_transaction_infos(path: &str) -> Vec { fn append_transaction_info( allocation: &Allocation, signature: &Signature, + new_stake_account_address: Option<&Pubkey>, transactions_csv: &str, ) -> Result<(), csv::Error> { let existed = Path::new(&transactions_csv).exists(); @@ -146,6 +234,9 @@ fn append_transaction_info( recipient: allocation.recipient.clone(), amount: allocation.amount, signature: signature.to_string(), + new_stake_account_address: new_stake_account_address + .map(|pubkey| pubkey.to_string()) + .unwrap_or("".to_string()), }; wtr.serialize(transaction_info)?; wtr.flush()?; @@ -160,17 +251,11 @@ pub fn process_distribute( .trim(Trim::All) .from_path(&args.bids_csv)?; let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); - let allocations: Vec = bids + let mut allocations: Vec = bids .into_iter() .map(|bid| create_allocation(&bid, args.dollars_per_sol)) .collect(); - let transaction_infos: Vec = if Path::new(&args.transactions_csv).exists() { - read_transaction_infos(&args.transactions_csv) - } else { - vec![] - }; - let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( "{} â—Ž{} (${})", @@ -179,29 +264,13 @@ pub fn process_distribute( starting_total_tokens * args.dollars_per_sol, ); - let mut allocations = merge_allocations(&allocations); - apply_previous_transactions(&mut allocations, &transaction_infos); + let transaction_infos = if Path::new(&args.transactions_csv).exists() { + read_transaction_infos(&args.transactions_csv) + } else { + vec![] + }; - let distributed_tokens: f64 = transaction_infos.iter().map(|x| x.amount).sum(); - let undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); - println!( - "{} â—Ž{} (${})", - style(format!("{}", "Distributed:")).bold(), - distributed_tokens, - distributed_tokens * args.dollars_per_sol, - ); - println!( - "{} â—Ž{} (${})", - style(format!("{}", "Undistributed:")).bold(), - undistributed_tokens, - undistributed_tokens * args.dollars_per_sol, - ); - println!( - "{} â—Ž{} (${})\n", - style(format!("{}", "Total:")).bold(), - distributed_tokens + undistributed_tokens, - (distributed_tokens + undistributed_tokens) * args.dollars_per_sol, - ); + apply_previous_transactions(&mut allocations, &transaction_infos); if allocations.is_empty() { eprintln!("No work to do"); @@ -238,7 +307,59 @@ pub fn process_distribute( .bold() ); - distribute_tokens(&client, &allocations, &args)?; + let distributed_tokens: f64 = transaction_infos.iter().map(|x| x.amount).sum(); + let undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); + println!( + "{} â—Ž{} (${})", + style(format!("{}", "Distributed:")).bold(), + distributed_tokens, + distributed_tokens * args.dollars_per_sol, + ); + println!( + "{} â—Ž{} (${})", + style(format!("{}", "Undistributed:")).bold(), + undistributed_tokens, + undistributed_tokens * args.dollars_per_sol, + ); + println!( + "{} â—Ž{} (${})\n", + style(format!("{}", "Total:")).bold(), + distributed_tokens + undistributed_tokens, + (distributed_tokens + undistributed_tokens) * args.dollars_per_sol, + ); + + distribute_tokens(client, &allocations, args)?; + + Ok(()) +} + +pub fn process_distribute_stake( + client: &ThinClient, + args: &DistributeStakeArgs>, +) -> Result<(), csv::Error> { + let mut rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.allocations_csv)?; + let allocations: Vec = rdr + .deserialize() + .map(|allocation| allocation.unwrap()) + .collect(); + + let transaction_infos = if Path::new(&args.transactions_csv).exists() { + read_transaction_infos(&args.transactions_csv) + } else { + vec![] + }; + + let mut allocations = merge_allocations(&allocations); + apply_previous_transactions(&mut allocations, &transaction_infos); + + if allocations.is_empty() { + eprintln!("No work to do"); + return Ok(()); + } + + distribute_stake(client, &allocations, args)?; Ok(()) } @@ -344,6 +465,101 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: ); } +pub fn test_process_distribute_stake_with_client(client: C, sender_keypair: Keypair) { + let thin_client = ThinClient(client); + let fee_payer = Keypair::new(); + thin_client + .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) + .unwrap(); + + // TODO: Create a stake account with lockups + let stake_account_keypair = Keypair::new(); + let stake_account_address = stake_account_keypair.pubkey(); + let stake_authority = Keypair::new(); + let withdraw_authority = Keypair::new(); + + let authorized = Authorized { + staker: stake_authority.pubkey(), + withdrawer: withdraw_authority.pubkey(), + }; + let lockup = Lockup::default(); + let instructions = stake_instruction::create_account( + &sender_keypair.pubkey(), + &stake_account_address, + &authorized, + &lockup, + sol_to_lamports(3000.0), + ); + let message = Message::new(&instructions); + let signers = [&sender_keypair, &stake_account_keypair]; + thin_client.send_message(message, &signers).unwrap(); + + let alice_pubkey = Pubkey::new_rand(); + let allocation = Allocation { + recipient: alice_pubkey.to_string(), + amount: 1000.0, + }; + let allocations_file = NamedTempFile::new().unwrap(); + let allocations_csv = allocations_file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(allocations_file); + wtr.serialize(&allocation).unwrap(); + wtr.flush().unwrap(); + + let dir = tempdir().unwrap(); + let transactions_csv = dir + .path() + .join("transactions.csv") + .to_str() + .unwrap() + .to_string(); + + let args: DistributeStakeArgs> = DistributeStakeArgs { + stake_account_address, + stake_authority: Some(Box::new(stake_authority)), + withdraw_authority: Some(Box::new(withdraw_authority)), + fee_payer: Some(Box::new(fee_payer)), + dry_run: false, + allocations_csv, + transactions_csv: transactions_csv.clone(), + }; + process_distribute_stake(&thin_client, &args).unwrap(); + let transaction_infos = read_transaction_infos(&transactions_csv); + assert_eq!(transaction_infos.len(), 1); + assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + let expected_amount = allocation.amount; + assert_eq!(transaction_infos[0].amount, expected_amount); + + assert_eq!( + thin_client.get_balance(&alice_pubkey).unwrap(), + sol_to_lamports(1.0), + ); + let new_stake_account_address = transaction_infos[0] + .new_stake_account_address + .parse() + .unwrap(); + assert_eq!( + thin_client.get_balance(&new_stake_account_address).unwrap(), + sol_to_lamports(expected_amount - 1.0), + ); + + // Now, run it again, and check there's no double-spend. + process_distribute_stake(&thin_client, &args).unwrap(); + let transaction_infos = read_transaction_infos(&transactions_csv); + assert_eq!(transaction_infos.len(), 1); + assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + let expected_amount = allocation.amount; + assert_eq!(transaction_infos[0].amount, expected_amount); + + assert_eq!( + thin_client.get_balance(&alice_pubkey).unwrap(), + sol_to_lamports(1.0), + ); + assert_eq!( + thin_client.get_balance(&new_stake_account_address).unwrap(), + sol_to_lamports(expected_amount - 1.0), + ); +} + #[cfg(test)] mod tests { use super::*; @@ -358,6 +574,14 @@ mod tests { test_process_distribute_with_client(bank_client, sender_keypair); } + #[test] + fn test_process_distribute_stake() { + let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); + let bank = Bank::new(&genesis_config); + let bank_client = BankClient::new(bank); + test_process_distribute_stake_with_client(bank_client, sender_keypair); + } + #[test] fn test_apply_previous_transactions() { let mut allocations = vec![ @@ -374,6 +598,7 @@ mod tests { recipient: "b".to_string(), amount: 1.0, signature: "".to_string(), + new_stake_account_address: "".to_string(), }]; apply_previous_transactions(&mut allocations, &transaction_infos); assert_eq!(allocations.len(), 1); From d65b3beae671bc987b9d64731b51416d291f7efe Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 29 Apr 2020 16:47:49 -0600 Subject: [PATCH 41/71] Distribute -> DistributeTokens (#3) --- README.md | 6 +++--- src/arg_parser.rs | 10 ++++++---- src/args.rs | 10 +++++----- src/main.rs | 4 ++-- src/tokens.rs | 14 +++++++------- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index ad98da5327b116..7e162be74ed4dd 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ primary_address,bid_amount_dollars ``` ```bash -solana-tokens distribute --from --dollars-per-sol --bids-csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --bids-csv --fee-payer ``` Example transaction log before: @@ -31,7 +31,7 @@ Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute --from --dollars-per-sol --bids-csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --bids-csv --fee-payer ``` Example output: @@ -60,7 +60,7 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute --dollars-per-sol --dry-run --bids-csv +solana-tokens distribute-tokens --dollars-per-sol --dry-run --bids-csv ``` Example bids.csv: diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 833ebf5df83d80..378ad231c47e0b 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,4 +1,4 @@ -use crate::args::{Args, BalancesArgs, Command, DistributeArgs, DistributeStakeArgs}; +use crate::args::{Args, BalancesArgs, Command, DistributeStakeArgs, DistributeTokensArgs}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; use solana_cli_config::CONFIG_FILE; @@ -160,8 +160,8 @@ where .get_matches_from(args) } -fn parse_distribute_args(matches: &ArgMatches<'_>) -> DistributeArgs { - DistributeArgs { +fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { + DistributeTokensArgs { bids_csv: value_t_or_exit!(matches, "bids_csv", String), transactions_csv: value_t_or_exit!(matches, "transactions_csv", String), dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), @@ -200,7 +200,9 @@ where let url = matches.value_of("url").map(|x| x.to_string()); let command = match matches.subcommand() { - ("distribute", Some(matches)) => Command::Distribute(parse_distribute_args(matches)), + ("distribute-tokens", Some(matches)) => { + Command::DistributeTokens(parse_distribute_tokens_args(matches)) + } ("distribute-stake", Some(matches)) => { Command::DistributeStake(parse_distribute_stake_args(matches)) } diff --git a/src/args.rs b/src/args.rs index ca9d4c7bd4a12c..106cbd8239b1be 100644 --- a/src/args.rs +++ b/src/args.rs @@ -4,7 +4,7 @@ use solana_remote_wallet::remote_wallet::maybe_wallet_manager; use solana_sdk::{pubkey::Pubkey, signature::Signer}; use std::error::Error; -pub struct DistributeArgs { +pub struct DistributeTokensArgs { pub bids_csv: String, pub transactions_csv: String, pub dollars_per_sol: f64, @@ -29,7 +29,7 @@ pub struct BalancesArgs { } pub enum Command { - Distribute(DistributeArgs), + DistributeTokens(DistributeTokensArgs), DistributeStake(DistributeStakeArgs), Balances(BalancesArgs), } @@ -44,10 +44,10 @@ pub fn resolve_command( command: Command, ) -> Result>, Box> { match command { - Command::Distribute(args) => { + Command::DistributeTokens(args) => { let mut wallet_manager = maybe_wallet_manager()?; let matches = ArgMatches::default(); - let resolved_args = DistributeArgs { + let resolved_args = DistributeTokensArgs { bids_csv: args.bids_csv, transactions_csv: args.transactions_csv, dollars_per_sol: args.dollars_per_sol, @@ -59,7 +59,7 @@ pub fn resolve_command( signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() }), }; - Ok(Command::Distribute(resolved_args)) + Ok(Command::DistributeTokens(resolved_args)) } Command::DistributeStake(args) => { let mut wallet_manager = maybe_wallet_manager()?; diff --git a/src/main.rs b/src/main.rs index f0f1ef27184890..6a44419a1d14ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,8 +17,8 @@ fn main() -> Result<(), Box> { let thin_client = ThinClient(client); match resolve_command(command_args.command)? { - Command::Distribute(args) => { - tokens::process_distribute(&thin_client, &args)?; + Command::DistributeTokens(args) => { + tokens::process_distribute_tokens(&thin_client, &args)?; } Command::DistributeStake(args) => { tokens::process_distribute_stake(&thin_client, &args)?; diff --git a/src/tokens.rs b/src/tokens.rs index 4730ad3c2c9afe..072b7b5c6c2104 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,4 +1,4 @@ -use crate::args::{BalancesArgs, DistributeArgs, DistributeStakeArgs}; +use crate::args::{BalancesArgs, DistributeStakeArgs, DistributeTokensArgs}; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; @@ -84,7 +84,7 @@ fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { fn distribute_tokens( client: &ThinClient, allocations: &[Allocation], - args: &DistributeArgs>, + args: &DistributeTokensArgs>, ) -> Result<(), csv::Error> { let signers = if args.dry_run { vec![] @@ -243,9 +243,9 @@ fn append_transaction_info( Ok(()) } -pub fn process_distribute( +pub fn process_distribute_tokens( client: &ThinClient, - args: &DistributeArgs>, + args: &DistributeTokensArgs>, ) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) @@ -431,7 +431,7 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: .unwrap() .to_string(); - let args: DistributeArgs> = DistributeArgs { + let args: DistributeTokensArgs> = DistributeTokensArgs { sender_keypair: Some(Box::new(sender_keypair)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, @@ -439,7 +439,7 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: transactions_csv: transactions_csv.clone(), dollars_per_sol: 0.22, }; - process_distribute(&thin_client, &args).unwrap(); + process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&transactions_csv); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); @@ -452,7 +452,7 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: ); // Now, run it again, and check there's no double-spend. - process_distribute(&thin_client, &args).unwrap(); + process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&transactions_csv); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); From d51871bb26f3be8a46012359e92e8e87bcf9a7db Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 29 Apr 2020 17:15:37 -0600 Subject: [PATCH 42/71] Cache cargo deps (#4) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cba263c127543c..da1d173f0abd7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: rust +cache: cargo addons: apt: packages: From 09b5e0cceeb166ab823d093e5c62280e4735a343 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 2 May 2020 18:02:34 -0600 Subject: [PATCH 43/71] Add docs (#5) --- README.md | 20 +++++++++++++++++++- src/tokens.rs | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e162be74ed4dd..b2449e3aadb1fe 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ recipient,amount,signature UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k,43,1111111111111111111111111111111111111111111111111111111111111111 ``` -## Calculate what tokens should be sent +### Calculate what tokens should be sent List the differences between a list of expected distributions and the record of what transactions have already been sent. @@ -82,3 +82,21 @@ Recipient Amount UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 ``` +## Distribute stake accounts + +Distributing tokens via stake accounts works similarly to how tokens are distributed. The +big difference is that new stake accounts are split from existing ones. By splitting, +the new accounts inherit any lockup or custodian settings of the original. + +```bash +solana-tokens distribute-stake --stake-account-address \ + --allocations-csv \ + \ + --stake-authority --withdraw-authority --fee-payer +``` + +Currently, this will subtract 1 SOL from each allocation and store it the +recipient address. That SOL can be used to pay transaction fees on staking +operations such as delegating stake. The rest of the allocation is put in +a stake account. The new stake account address is output in the transaction +log. diff --git a/src/tokens.rs b/src/tokens.rs index 072b7b5c6c2104..091fc63c703859 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -184,6 +184,7 @@ fn distribute_stake( )); let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); + println!("Creating stake account {}", new_stake_account_address); client.send_message(message, &signers) }; match result { From 9bb847326bdf07b345303cf46741cfe5cf6157e0 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 2 May 2020 18:44:21 -0600 Subject: [PATCH 44/71] Switch to latest Solana 1.1 release (#7) --- Cargo.lock | 259 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 16 ++-- 2 files changed, 134 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a414897811af97..eda743bfedb95c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -371,7 +371,7 @@ checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" dependencies = [ "glob 0.3.0", "libc", - "libloading 0.5.2", + "libloading", ] [[package]] @@ -1029,9 +1029,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2664c2cf08049036f31015b04c6ac3671379a1d86f52ed2416893f16022deb" +checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" dependencies = [ "serde", "typenum", @@ -1618,15 +1618,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "libloading" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c4f51b790f5bdb65acb4cc94bb81d7b2ee60348a5431ac1467d390b017600b0" -dependencies = [ - "winapi 0.3.8", -] - [[package]] name = "librocksdb-sys" version = "6.7.4" @@ -2385,17 +2376,6 @@ dependencies = [ "rust-argon2", ] -[[package]] -name = "reed-solomon-erasure" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a415a013dd7c5d4221382329a5a3482566da675737494935cbbbcdec04662f9d" -dependencies = [ - "cc", - "libc", - "smallvec 1.4.0", -] - [[package]] name = "regex" version = "1.3.7" @@ -2794,8 +2774,9 @@ dependencies = [ [[package]] name = "solana-archiver-utils" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5748b097187cf8c1a65c8fa9eda38e639d39ce5e10b7366d85010ceae1b43f6" dependencies = [ "log 0.4.8", "rand 0.7.3", @@ -2809,17 +2790,17 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b8061b765425f87cb1e1f215700d0e8d432ec71e2bd37f61012cb04157203d" dependencies = [ "bincode", "byteorder", - "jemalloc-sys", + "libc", "log 0.4.8", "num-derive 0.3.0", "num-traits 0.2.11", "solana-logger", - "solana-runtime", "solana-sdk", "solana_rbpf", "thiserror", @@ -2827,8 +2808,9 @@ dependencies = [ [[package]] name = "solana-budget-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17dac9b180aef6ea82ba0b0a9b333183dd2d1c1c5f7d76e77ab365675d2b749" dependencies = [ "bincode", "chrono", @@ -2843,8 +2825,9 @@ dependencies = [ [[package]] name = "solana-chacha" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d827dcd3c0c2002bf709999d70a39cb1b467185d536d65f2f4ceb2ece845c04" dependencies = [ "log 0.4.8", "rand 0.7.3", @@ -2858,8 +2841,9 @@ dependencies = [ [[package]] name = "solana-chacha-cuda" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a433202f0bf5d14845a609f77c6ac483d446fe13766c73ab82e6ff2b853f9d" dependencies = [ "log 0.4.8", "solana-archiver-utils", @@ -2872,16 +2856,18 @@ dependencies = [ [[package]] name = "solana-chacha-sys" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bcb5f621da93619d5ec06354d9b59c9a1a87ac77452c3f5b9dd37637152a4d8" dependencies = [ "cc", ] [[package]] name = "solana-clap-utils" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49c6e49808c95de975b8591aa84a7f1dad102200b2624d713f2c64cdf131a83c" dependencies = [ "chrono", "clap", @@ -2895,8 +2881,9 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "493ec5bd9c44ae33594a5ef568179a38d6d378c538bc652d93eecd959cfc49b8" dependencies = [ "dirs", "lazy_static", @@ -2908,8 +2895,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e43d60394d9238d865c94409784fb0984b28948682164ff3c8abca131014885" dependencies = [ "bincode", "bs58", @@ -2932,8 +2920,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fd83a1a37bf1496c9154e6d10d4a103b82ea7a0cba6029809342249c02624" dependencies = [ "bincode", "chrono", @@ -2945,8 +2934,9 @@ dependencies = [ [[package]] name = "solana-core" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2037d4dc846e077b26798c5a67da9a9e20ead0d9ad2c34c2d773b02f46e54f" dependencies = [ "bincode", "bs58", @@ -3010,8 +3000,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4951745150b3973be869860b3239bcb85d6da45abf314106e136187dbaa88d90" dependencies = [ "backtrace", "bytes 0.4.12", @@ -3034,8 +3025,9 @@ dependencies = [ [[package]] name = "solana-exchange-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f53b8f6cdcb53c68ac962e5d34a53ab54734fcd757516fd2ccf30dafeba47a" dependencies = [ "bincode", "log 0.4.8", @@ -3051,8 +3043,9 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e621d9ab601163293f58a94197ac0b0907260de7b1566412cbc1a4ae1ebbec13" dependencies = [ "bincode", "byteorder", @@ -3071,8 +3064,9 @@ dependencies = [ [[package]] name = "solana-genesis-programs" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1dd6ff73fd0b8d850cd79be1187431eb0dc15bccdccda81ab1a419cf8c1f" dependencies = [ "log 0.4.8", "solana-bpf-loader-program", @@ -3086,8 +3080,9 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39d1328915a36e3df2b60fa77fc29c0d0fa0d868de22cc7b2ce834765b6192f" dependencies = [ "bincode", "byteorder", @@ -3096,7 +3091,6 @@ dependencies = [ "crossbeam-channel", "dir-diff", "ed25519-dalek", - "flate2", "fs_extra", "itertools 0.9.0", "lazy_static", @@ -3106,7 +3100,6 @@ dependencies = [ "rand 0.7.3", "rand_chacha 0.2.2", "rayon", - "reed-solomon-erasure", "regex", "rocksdb", "serde", @@ -3119,6 +3112,7 @@ dependencies = [ "solana-metrics", "solana-perf", "solana-rayon-threadlimit", + "solana-reed-solomon-erasure", "solana-runtime", "solana-sdk", "solana-stake-program", @@ -3128,13 +3122,13 @@ dependencies = [ "tar", "tempfile", "thiserror", - "zstd", ] [[package]] name = "solana-logger" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b97fb29457995ca16c4ef6dd11c65062315e5860ef4fa23f8130b2a625b810a" dependencies = [ "env_logger 0.7.1", "lazy_static", @@ -3143,8 +3137,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac46fed54a2375b09780e0e52ff9087316c280f419ca4f5c6d4240be77686e5e" dependencies = [ "jemalloc-ctl", "jemallocator", @@ -3155,8 +3150,9 @@ dependencies = [ [[package]] name = "solana-merkle-tree" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b403bd97961442f49d0f87c4988357f54c47509cc91c0273ef0224b8f432d20" dependencies = [ "fast-math", "solana-sdk", @@ -3164,8 +3160,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25081118a3cd87b4851dbb02a3bac60a51c1a6e7ff28b44f824a7462a8f4638b" dependencies = [ "env_logger 0.7.1", "gethostname", @@ -3177,8 +3174,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98c3a0479966688f4258a3faa4ea92ba68f4591b33c323887308bcef28c10a9f" dependencies = [ "bincode", "bytes 0.4.12", @@ -3197,8 +3195,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48882ec893bee13106146643071aefdd06d2aef614cd531d6b235389ffcd9f95" dependencies = [ "bincode", "dlopen", @@ -3217,17 +3216,30 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b14ba7745207ff9a9319f11b14c220d45cc241bb82aa91fe4741f45f334c2a63" dependencies = [ "lazy_static", "num_cpus", ] +[[package]] +name = "solana-reed-solomon-erasure" +version = "4.0.1-3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5b3ab3f4dd12af687a7d0d0ee73299cbc06ed3aada42dccac26fe243e73399e" +dependencies = [ + "cc", + "libc", + "smallvec 0.6.13", +] + [[package]] name = "solana-remote-wallet" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f64f9065b9dd9c587025017340fb6a10a13f386c2d0586736632e245ed7dae2" dependencies = [ "base32", "console 0.10.3", @@ -3243,8 +3255,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add26829dc669ce66702d74d2f170d3e55d45741c3b1802b8a319b8d564ef958" dependencies = [ "bincode", "bv", @@ -3254,7 +3267,7 @@ dependencies = [ "itertools 0.9.0", "lazy_static", "libc", - "libloading 0.6.1", + "libloading", "log 0.4.8", "memmap", "num-derive 0.3.0", @@ -3264,6 +3277,7 @@ dependencies = [ "rayon", "serde", "serde_derive", + "solana-bpf-loader-program", "solana-config-program", "solana-logger", "solana-measure", @@ -3279,8 +3293,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea460e467f49d70df645fa489779900b7e25ea9c29a309f4c0f571707145c1e" dependencies = [ "assert_matches", "bincode", @@ -3289,7 +3304,7 @@ dependencies = [ "byteorder", "chrono", "ed25519-dalek", - "generic-array 0.14.1", + "generic-array 0.13.2", "hex", "hmac", "itertools 0.9.0", @@ -3313,8 +3328,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1699e81c4366590818c3bcd2c05af17de45b5e25f340f3032405d4fa89e163" dependencies = [ "bs58", "proc-macro2 1.0.10", @@ -3324,8 +3340,9 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2027a28f776996d57a41d6543b33a69fb0e3acd578b72de32d29b2d43fc32534" dependencies = [ "bincode", "log 0.4.8", @@ -3342,8 +3359,9 @@ dependencies = [ [[package]] name = "solana-storage-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917418b7a035fa85b8100f89e59c5e95c60f6e3464e72d717707e89417394ca6" dependencies = [ "bincode", "log 0.4.8", @@ -3358,8 +3376,9 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8037ebde07a2fbf5c879edde60efbc1f0164141f6625efcfb13d96a9d4b84b98" dependencies = [ "libc", "log 0.4.8", @@ -3374,8 +3393,9 @@ dependencies = [ [[package]] name = "solana-sys-tuner" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e654f861cc2ab9a3c8efe95127c3c4b7ca534bccf35fc16a5cbd41c4bbbac25" dependencies = [ "clap", "libc", @@ -3410,8 +3430,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2660c083007606866edf1964bc63a0ff068eece70a65dfd2f599c93aa2bad0e5" dependencies = [ "bincode", "bs58", @@ -3422,8 +3443,9 @@ dependencies = [ [[package]] name = "solana-vest-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f00039e44edfa4a3e9a0c1e801b9d3dbe4285bd7c85ab14edaefd344b128ee4" dependencies = [ "bincode", "chrono", @@ -3438,8 +3460,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b4a37623715633f3925ff8b34047624beabc08320f5478fde7d7313f342e131" dependencies = [ "bincode", "log 0.4.8", @@ -3454,8 +3477,9 @@ dependencies = [ [[package]] name = "solana-vote-signer" -version = "1.2.0" -source = "git+https://github.com/solana-labs/solana?rev=efb4988d108fa2f52c35d671a177d3b18db6c495#efb4988d108fa2f52c35d671a177d3b18db6c495" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "858b129a70106ab764bc780fee19a6bb60913deb54d82c8a56eee8eb4eff8320" dependencies = [ "clap", "jsonrpc-core", @@ -4124,12 +4148,11 @@ dependencies = [ [[package]] name = "users" -version = "0.10.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4227e95324a443c9fcb06e03d4d85e91aabe9a5a02aa818688b6918b6af486" +checksum = "c72f4267aea0c3ec6d07eaabea6ead7c5ddacfafc5e22bcf8d186706851fb4cf" dependencies = [ "libc", - "log 0.4.8", ] [[package]] @@ -4456,33 +4479,3 @@ name = "zeroize" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" - -[[package]] -name = "zstd" -version = "0.5.1+zstd.1.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5d978b793ae64375b80baf652919b148f6a496ac8802922d9999f5a553194f" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "2.0.3+zstd.1.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee25eac9753cfedd48133fa1736cbd23b774e253d89badbeac7d12b23848d3f" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "1.4.15+zstd.1.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89719b034dc22d240d5b407fb0a3fe6d29952c181cff9a9f95c0bd40b4f8f7d8" -dependencies = [ - "cc", - "glob 0.3.0", - "libc", -] diff --git a/Cargo.toml b/Cargo.toml index 36ac4653654670..27afb716176ef9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,14 +14,14 @@ clap = "2.33.0" console = "0.10.3" indexmap = "1.3.2" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} -solana-cli-config = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} -solana-client = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} -solana-remote-wallet = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} -solana-runtime = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} -solana-sdk = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} -solana-stake-program = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-clap-utils = "1.1.8" +solana-cli-config = "1.1.8" +solana-client = "1.1.8" +solana-remote-wallet = "1.1.8" +solana-runtime = "1.1.8" +solana-sdk = "1.1.8" +solana-stake-program = "1.1.8" tempfile = "3.1.0" [dev-dependencies] -solana-core = {git = "https://github.com/solana-labs/solana", rev = "efb4988d108fa2f52c35d671a177d3b18db6c495"} +solana-core = "1.1.8" From 07d961776dffafc80056cb6b1aa946408f790da0 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Mon, 4 May 2020 12:27:23 -0600 Subject: [PATCH 45/71] distribute -> distribute-tokens (#9) --- src/arg_parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 378ad231c47e0b..0c83f57aa5cfc2 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -31,7 +31,7 @@ where .help("RPC entrypoint address. i.e. http://devnet.solana.com"), ) .subcommand( - SubCommand::with_name("distribute") + SubCommand::with_name("distribute-tokens") .about("Distribute tokens") .arg( Arg::with_name("transactions_csv") From ac7dd4176483c14b27bad2dbc9ffb8aff9c7f1f0 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 4 May 2020 13:46:48 -0600 Subject: [PATCH 46/71] Switch from CSV to a pickledb database (#8) * Switch from CSV to a pickledb database * Allow PickleDb errors to bubble up * Dedup * Hoist db * Add finalized field to TransactionInfo * Don't allow RPC client to resign transactions * Remove dead code * Use transport::Result * Record unconfirmed transaction * Fix: separate stake account per allocation * Catch transport errors * Panic if we attempt to replay a transaction that hasn't been finalized * Attempt to fix CI PickleDb isn't calling flush() or close() after writing to files. No issue on MacOS, but looks racy in CI. * Revert "Attempt to fix CI" This reverts commit 1632394f636c54402b3578120e8817dd1660e19b. * Poll for signature before returning --- Cargo.lock | 31 +++++++++ Cargo.toml | 2 + src/arg_parser.rs | 12 ++-- src/args.rs | 8 +-- src/thin_client.rs | 97 ++++++++++++--------------- src/tokens.rs | 160 +++++++++++++++++++++++++-------------------- 6 files changed, 176 insertions(+), 134 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eda743bfedb95c..ec63fa88fb4499 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1120,6 +1120,12 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "half" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36b5f248235f45773d4944f555f83ea61fe07b18b561ccf99d7483d7381e54d" + [[package]] name = "hash32" version = "0.1.1" @@ -2054,6 +2060,19 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pickledb" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9161694d67f6c5163519d42be942ae36bbdb55f439460144f105bc4f9f7d1d61" +dependencies = [ + "bincode", + "serde", + "serde_cbor", + "serde_json", + "serde_yaml", +] + [[package]] name = "pin-project" version = "0.4.9" @@ -2645,6 +2664,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.106" @@ -3416,6 +3445,7 @@ dependencies = [ "console 0.10.3", "csv", "indexmap", + "pickledb", "serde", "solana-clap-utils", "solana-cli-config", @@ -3426,6 +3456,7 @@ dependencies = [ "solana-sdk", "solana-stake-program", "tempfile", + "thiserror", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 27afb716176ef9..9657c00623b66d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ csv = "1.1.3" clap = "2.33.0" console = "0.10.3" indexmap = "1.3.2" +pickledb = "0.4.1" serde = { version = "1.0", features = ["derive"] } solana-clap-utils = "1.1.8" solana-cli-config = "1.1.8" @@ -22,6 +23,7 @@ solana-runtime = "1.1.8" solana-sdk = "1.1.8" solana-stake-program = "1.1.8" tempfile = "3.1.0" +thiserror = "1.0" [dev-dependencies] solana-core = "1.1.8" diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 0c83f57aa5cfc2..47808c8abe70db 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -34,12 +34,12 @@ where SubCommand::with_name("distribute-tokens") .about("Distribute tokens") .arg( - Arg::with_name("transactions_csv") + Arg::with_name("transactions_db") .required(true) .index(1) .takes_value(true) .value_name("FILE") - .help("Transactions CSV file"), + .help("Transactions database file"), ) .arg( Arg::with_name("bids_csv") @@ -83,12 +83,12 @@ where SubCommand::with_name("distribute-stake") .about("Distribute stake accounts") .arg( - Arg::with_name("transactions_csv") + Arg::with_name("transactions_db") .required(true) .index(1) .takes_value(true) .value_name("FILE") - .help("Transactions CSV file"), + .help("Transactions database file"), ) .arg( Arg::with_name("allocations_csv") @@ -163,7 +163,7 @@ where fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { DistributeTokensArgs { bids_csv: value_t_or_exit!(matches, "bids_csv", String), - transactions_csv: value_t_or_exit!(matches, "transactions_csv", String), + transactions_db: value_t_or_exit!(matches, "transactions_db", String), dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), dry_run: matches.is_present("dry_run"), sender_keypair: value_t!(matches, "sender_keypair", String).ok(), @@ -174,7 +174,7 @@ fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArg fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs { DistributeStakeArgs { allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), - transactions_csv: value_t_or_exit!(matches, "transactions_csv", String), + transactions_db: value_t_or_exit!(matches, "transactions_db", String), dry_run: matches.is_present("dry_run"), stake_account_address: value_t_or_exit!(matches, "stake_account_address", String), stake_authority: value_t!(matches, "stake_authority", String).ok(), diff --git a/src/args.rs b/src/args.rs index 106cbd8239b1be..3e1d21055fdd1e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -6,7 +6,7 @@ use std::error::Error; pub struct DistributeTokensArgs { pub bids_csv: String, - pub transactions_csv: String, + pub transactions_db: String, pub dollars_per_sol: f64, pub dry_run: bool, pub sender_keypair: Option, @@ -15,7 +15,7 @@ pub struct DistributeTokensArgs { pub struct DistributeStakeArgs { pub allocations_csv: String, - pub transactions_csv: String, + pub transactions_db: String, pub dry_run: bool, pub stake_account_address: P, pub stake_authority: Option, @@ -49,7 +49,7 @@ pub fn resolve_command( let matches = ArgMatches::default(); let resolved_args = DistributeTokensArgs { bids_csv: args.bids_csv, - transactions_csv: args.transactions_csv, + transactions_db: args.transactions_db, dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run, sender_keypair: args.sender_keypair.as_ref().map(|key_url| { @@ -66,7 +66,7 @@ pub fn resolve_command( let matches = ArgMatches::default(); let resolved_args = DistributeStakeArgs { allocations_csv: args.allocations_csv, - transactions_csv: args.transactions_csv, + transactions_db: args.transactions_db, dry_run: args.dry_run, stake_account_address: pubkey_from_path( &matches, diff --git a/src/thin_client.rs b/src/thin_client.rs index a9c5edcea50002..fc19e3b0031035 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -1,105 +1,94 @@ use solana_client::rpc_client::RpcClient; use solana_runtime::bank_client::BankClient; use solana_sdk::{ - client::SyncClient, + client::{AsyncClient, SyncClient}, + fee_calculator::FeeCalculator, + hash::Hash, message::Message, pubkey::Pubkey, - signature::{Signature, Signer}, + signature::{Keypair, Signature, Signer}, signers::Signers, system_instruction, transaction::Transaction, - transport::TransportError, + transport::{Result, TransportError}, }; pub trait Client { - fn send_and_confirm_message( - &self, - message: Message, - signers: &S, - ) -> Result; - - fn get_balance1(&self, pubkey: &Pubkey) -> Result; + fn send_and_confirm_transaction1(&self, transaction: Transaction) -> Result; + fn get_balance1(&self, pubkey: &Pubkey) -> Result; + fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)>; } impl Client for RpcClient { - fn send_and_confirm_message( - &self, - message: Message, - signers: &S, - ) -> Result { - let mut transaction = Transaction::new_unsigned(message); - self.resign_transaction(&mut transaction, signers) - .map_err(|e| TransportError::Custom(e.to_string()))?; - let initial_signature = transaction.signatures[0]; - println!("Sending transaction with signature {}", initial_signature); - let signature = self - .send_and_confirm_transaction_with_spinner(&mut transaction, signers) - .map_err(|e| TransportError::Custom(e.to_string()))?; - Ok(signature) + fn send_and_confirm_transaction1(&self, mut transaction: Transaction) -> Result { + let signers: Vec<&Keypair> = vec![]; // Don't allow resigning + self.send_and_confirm_transaction_with_spinner(&mut transaction, &signers) + .map_err(|e| TransportError::Custom(e.to_string())) } - fn get_balance1(&self, pubkey: &Pubkey) -> Result { + fn get_balance1(&self, pubkey: &Pubkey) -> Result { let balance = self .get_balance(pubkey) .map_err(|e| TransportError::Custom(e.to_string()))?; Ok(balance) } + + fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)> { + let blockhash = self + .get_recent_blockhash() + .map_err(|e| TransportError::Custom(e.to_string()))?; + Ok(blockhash) + } } impl Client for BankClient { - fn send_and_confirm_message( - &self, - message: Message, - signers: &S, - ) -> Result { - self.send_message(signers, message) + fn send_and_confirm_transaction1(&self, transaction: Transaction) -> Result { + let signature = self.async_send_transaction(transaction)?; + self.poll_for_signature(&signature)?; + Ok(signature) } - fn get_balance1(&self, pubkey: &Pubkey) -> Result { + fn get_balance1(&self, pubkey: &Pubkey) -> Result { self.get_balance(pubkey) } -} -impl Client for () { - fn send_and_confirm_message( - &self, - _message: Message, - _signers: &S, - ) -> Result { - Ok(Signature::default()) - } - - fn get_balance1(&self, _pubkey: &Pubkey) -> Result { - Ok(0) + fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)> { + self.get_recent_blockhash() } } pub struct ThinClient(pub C); impl ThinClient { + pub fn send_transaction(&self, transaction: Transaction) -> Result { + self.0.send_and_confirm_transaction1(transaction) + } + + pub fn send_message(&self, message: Message, signers: &S) -> Result { + let (blockhash, _fee_caluclator) = self.0.get_recent_blockhash_and_fees()?; + let transaction = Transaction::new(signers, message, blockhash); + let signature = transaction.signatures[0]; + self.send_transaction(transaction)?; + Ok(signature) + } + pub fn transfer( &self, lamports: u64, sender_keypair: &S, to_pubkey: &Pubkey, - ) -> Result { + ) -> Result { let create_instruction = system_instruction::transfer(&sender_keypair.pubkey(), &to_pubkey, lamports); let message = Message::new(&[create_instruction]); self.send_message(message, &[sender_keypair]) } -} -impl ThinClient { - pub fn send_message( - &self, - message: Message, - signers: &S, - ) -> Result { - self.0.send_and_confirm_message(message, signers) + pub fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)> { + self.0.get_recent_blockhash_and_fees() } - pub fn get_balance(&self, pubkey: &Pubkey) -> Result { + pub fn get_balance(&self, pubkey: &Pubkey) -> Result { self.0.get_balance1(pubkey) } } diff --git a/src/tokens.rs b/src/tokens.rs index 091fc63c703859..6bccd3375c700d 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -3,18 +3,20 @@ use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; use indexmap::IndexMap; +use pickledb::{PickleDb, PickleDbDumpPolicy}; use serde::{Deserialize, Serialize}; use solana_sdk::{ message::Message, native_token::{lamports_to_sol, sol_to_lamports}, signature::{Signature, Signer}, system_instruction, + transaction::Transaction, + transport::TransportError, }; use solana_stake_program::{ stake_instruction, stake_state::{Authorized, Lockup, StakeAuthorize}, }; -use std::fs; use std::path::Path; use std::process; @@ -34,8 +36,18 @@ struct Allocation { struct TransactionInfo { recipient: String, amount: f64, - signature: String, new_stake_account_address: String, + finalized: bool, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("CSV error")] + CsvError(#[from] csv::Error), + #[error("PickleDb error")] + PickleDbError(#[from] pickledb::error::Error), + #[error("Transport error")] + TransportError(#[from] TransportError), } fn merge_allocations(allocations: &[Allocation]) -> Vec { @@ -57,6 +69,9 @@ fn apply_previous_transactions( transaction_infos: &[TransactionInfo], ) { for transaction_info in transaction_infos { + if !transaction_info.finalized { + panic!("Attempt to apply an unconfirmed transaction. Please confirm the trarnsaction has been finalized or that its blockhash has expired."); + } let mut amount = transaction_info.amount; for allocation in allocations.iter_mut() { if allocation.recipient != transaction_info.recipient { @@ -83,9 +98,10 @@ fn create_allocation(bid: &Bid, dollars_per_sol: f64) -> Allocation { fn distribute_tokens( client: &ThinClient, + db: &mut PickleDb, allocations: &[Allocation], args: &DistributeTokensArgs>, -) -> Result<(), csv::Error> { +) -> Result<(), Error> { let signers = if args.dry_run { vec![] } else { @@ -107,13 +123,17 @@ fn distribute_tokens( let lamports = sol_to_lamports(allocation.amount); let instruction = system_instruction::transfer(&from, &to, lamports); let message = Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)); - client.send_message(message, &signers) + let (blockhash, _fee_caluclator) = client.get_recent_blockhash_and_fees()?; + let transaction = Transaction::new(&signers, message, blockhash); + let signature = transaction.signatures[0]; + set_transaction_info(db, &allocation, &signature, None, false)?; + client.send_transaction(transaction) }; match result { Ok(signature) => { println!("Finalized transaction with signature {}", signature); if !args.dry_run { - append_transaction_info(&allocation, &signature, None, &args.transactions_csv)?; + set_transaction_info(db, &allocation, &signature, None, true)?; } } Err(e) => { @@ -126,23 +146,24 @@ fn distribute_tokens( fn distribute_stake( client: &ThinClient, + db: &mut PickleDb, allocations: &[Allocation], args: &DistributeStakeArgs>, -) -> Result<(), csv::Error> { - let new_stake_account_keypair = Keypair::new(); - let new_stake_account_address = new_stake_account_keypair.pubkey(); - let signers = if args.dry_run { - vec![] - } else { - vec![ - &**args.fee_payer.as_ref().unwrap(), - &**args.stake_authority.as_ref().unwrap(), - &**args.withdraw_authority.as_ref().unwrap(), - &new_stake_account_keypair, - ] - }; - +) -> Result<(), Error> { for allocation in allocations { + let new_stake_account_keypair = Keypair::new(); + let new_stake_account_address = new_stake_account_keypair.pubkey(); + let signers = if args.dry_run { + vec![] + } else { + vec![ + &**args.fee_payer.as_ref().unwrap(), + &**args.stake_authority.as_ref().unwrap(), + &**args.withdraw_authority.as_ref().unwrap(), + &new_stake_account_keypair, + ] + }; + println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); let result = if args.dry_run { Ok(Signature::default()) @@ -184,18 +205,28 @@ fn distribute_stake( )); let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); - println!("Creating stake account {}", new_stake_account_address); - client.send_message(message, &signers) + let (blockhash, _fee_caluclator) = client.get_recent_blockhash_and_fees()?; + let transaction = Transaction::new(&signers, message, blockhash); + let signature = transaction.signatures[0]; + set_transaction_info( + db, + &allocation, + &signature, + Some(&new_stake_account_address), + false, + )?; + client.send_transaction(transaction) }; match result { Ok(signature) => { println!("Finalized transaction with signature {}", signature); if !args.dry_run { - append_transaction_info( + set_transaction_info( + db, &allocation, &signature, Some(&new_stake_account_address), - &args.transactions_csv, + true, )?; } } @@ -207,47 +238,44 @@ fn distribute_stake( Ok(()) } -fn read_transaction_infos(path: &str) -> Vec { - let mut rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&path) - .unwrap(); - rdr.deserialize().map(|x| x.unwrap()).collect() +fn open_db(path: &str) -> Result { + let policy = PickleDbDumpPolicy::AutoDump; + if Path::new(path).exists() { + PickleDb::load_yaml(path, policy) + } else { + Ok(PickleDb::new_yaml(path, policy)) + } +} + +fn read_transaction_infos(db: &PickleDb) -> Vec { + db.iter() + .map(|kv| kv.get_value::().unwrap()) + .collect() } -fn append_transaction_info( +fn set_transaction_info( + db: &mut PickleDb, allocation: &Allocation, signature: &Signature, new_stake_account_address: Option<&Pubkey>, - transactions_csv: &str, -) -> Result<(), csv::Error> { - let existed = Path::new(&transactions_csv).exists(); - let file = fs::OpenOptions::new() - .create_new(!existed) - .write(true) - .append(existed) - .open(&transactions_csv)?; - let mut wtr = csv::WriterBuilder::new() - .has_headers(!existed) - .from_writer(file); - + finalized: bool, +) -> Result<(), pickledb::error::Error> { let transaction_info = TransactionInfo { recipient: allocation.recipient.clone(), amount: allocation.amount, - signature: signature.to_string(), new_stake_account_address: new_stake_account_address .map(|pubkey| pubkey.to_string()) .unwrap_or("".to_string()), + finalized, }; - wtr.serialize(transaction_info)?; - wtr.flush()?; + db.set(&signature.to_string(), &transaction_info)?; Ok(()) } pub fn process_distribute_tokens( client: &ThinClient, args: &DistributeTokensArgs>, -) -> Result<(), csv::Error> { +) -> Result<(), Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) .from_path(&args.bids_csv)?; @@ -265,12 +293,8 @@ pub fn process_distribute_tokens( starting_total_tokens * args.dollars_per_sol, ); - let transaction_infos = if Path::new(&args.transactions_csv).exists() { - read_transaction_infos(&args.transactions_csv) - } else { - vec![] - }; - + let mut db = open_db(&args.transactions_db)?; + let transaction_infos = read_transaction_infos(&db); apply_previous_transactions(&mut allocations, &transaction_infos); if allocations.is_empty() { @@ -329,7 +353,7 @@ pub fn process_distribute_tokens( (distributed_tokens + undistributed_tokens) * args.dollars_per_sol, ); - distribute_tokens(client, &allocations, args)?; + distribute_tokens(client, &mut db, &allocations, args)?; Ok(()) } @@ -337,7 +361,7 @@ pub fn process_distribute_tokens( pub fn process_distribute_stake( client: &ThinClient, args: &DistributeStakeArgs>, -) -> Result<(), csv::Error> { +) -> Result<(), Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) .from_path(&args.allocations_csv)?; @@ -346,12 +370,8 @@ pub fn process_distribute_stake( .map(|allocation| allocation.unwrap()) .collect(); - let transaction_infos = if Path::new(&args.transactions_csv).exists() { - read_transaction_infos(&args.transactions_csv) - } else { - vec![] - }; - + let mut db = open_db(&args.transactions_db)?; + let transaction_infos = read_transaction_infos(&db); let mut allocations = merge_allocations(&allocations); apply_previous_transactions(&mut allocations, &transaction_infos); @@ -360,7 +380,7 @@ pub fn process_distribute_stake( return Ok(()); } - distribute_stake(client, &allocations, args)?; + distribute_stake(client, &mut db, &allocations, args)?; Ok(()) } @@ -425,7 +445,7 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: wtr.flush().unwrap(); let dir = tempdir().unwrap(); - let transactions_csv = dir + let transactions_db = dir .path() .join("transactions.csv") .to_str() @@ -437,11 +457,11 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: fee_payer: Some(Box::new(fee_payer)), dry_run: false, bids_csv, - transactions_csv: transactions_csv.clone(), + transactions_db: transactions_db.clone(), dollars_per_sol: 0.22, }; process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&transactions_csv); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol; @@ -454,7 +474,7 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&transactions_csv); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol; @@ -507,7 +527,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke wtr.flush().unwrap(); let dir = tempdir().unwrap(); - let transactions_csv = dir + let transactions_db = dir .path() .join("transactions.csv") .to_str() @@ -521,10 +541,10 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke fee_payer: Some(Box::new(fee_payer)), dry_run: false, allocations_csv, - transactions_csv: transactions_csv.clone(), + transactions_db: transactions_db.clone(), }; process_distribute_stake(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&transactions_csv); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); let expected_amount = allocation.amount; @@ -545,7 +565,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke // Now, run it again, and check there's no double-spend. process_distribute_stake(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&transactions_csv); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); let expected_amount = allocation.amount; @@ -598,8 +618,8 @@ mod tests { let transaction_infos = vec![TransactionInfo { recipient: "b".to_string(), amount: 1.0, - signature: "".to_string(), new_stake_account_address: "".to_string(), + finalized: true, }]; apply_previous_transactions(&mut allocations, &transaction_infos); assert_eq!(allocations.len(), 1); From 3f7542454703e75d548ca6746182e5cf1df17360 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Mon, 4 May 2020 22:52:04 -0600 Subject: [PATCH 47/71] Add --sol-for-fees option for stake distributions --- src/arg_parser.rs | 9 +++++++++ src/args.rs | 2 ++ src/tokens.rs | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 47808c8abe70db..96ebe02d1b6807 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -112,6 +112,14 @@ where .validator(is_valid_pubkey) .help("Stake Account Address"), ) + .arg( + Arg::with_name("sol_for_fees") + .default_value("1.0") + .long("sol-for-fees") + .takes_value(true) + .value_name("SOL_AMOUNT") + .help("Amount of SOL to put in system account to pay for fees"), + ) .arg( Arg::with_name("stake_authority") .long("stake-authority") @@ -177,6 +185,7 @@ fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs< transactions_db: value_t_or_exit!(matches, "transactions_db", String), dry_run: matches.is_present("dry_run"), stake_account_address: value_t_or_exit!(matches, "stake_account_address", String), + sol_for_fees: value_t_or_exit!(matches, "sol_for_fees", f64), stake_authority: value_t!(matches, "stake_authority", String).ok(), withdraw_authority: value_t!(matches, "withdraw_authority", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), diff --git a/src/args.rs b/src/args.rs index 3e1d21055fdd1e..f918535e0f519e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -17,6 +17,7 @@ pub struct DistributeStakeArgs { pub allocations_csv: String, pub transactions_db: String, pub dry_run: bool, + pub sol_for_fees: f64, pub stake_account_address: P, pub stake_authority: Option, pub withdraw_authority: Option, @@ -75,6 +76,7 @@ pub fn resolve_command( &mut wallet_manager, ) .unwrap(), + sol_for_fees: args.sol_for_fees, stake_authority: args.stake_authority.as_ref().map(|key_url| { signer_from_path(&matches, &key_url, "stake authority", &mut wallet_manager) .unwrap() diff --git a/src/tokens.rs b/src/tokens.rs index 6bccd3375c700d..ab9462481408ba 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -168,7 +168,7 @@ fn distribute_stake( let result = if args.dry_run { Ok(Signature::default()) } else { - let system_sol = 1.0; + let system_sol = args.sol_for_fees; let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); let stake_authority = args.stake_authority.as_ref().unwrap().pubkey(); let withdraw_authority = args.withdraw_authority.as_ref().unwrap().pubkey(); @@ -540,6 +540,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke withdraw_authority: Some(Box::new(withdraw_authority)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, + sol_for_fees: 1.0, allocations_csv, transactions_db: transactions_db.clone(), }; From 0c36708f46abe158217d6ef9a740d9d95d1d06a6 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 5 May 2020 15:30:20 -0600 Subject: [PATCH 48/71] Add --allocations-csv option (#14) * Add allocations-csv option * Add tests or GTFO * Apply review feedback * apply feedback * Add read_allocations function --- README.md | 6 +- src/arg_parser.rs | 24 +++++--- src/args.rs | 10 +-- src/tokens.rs | 154 ++++++++++++++++++++++++++++++++++++++-------- tests/tokens.rs | 4 +- 5 files changed, 155 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index b2449e3aadb1fe..9c956382b853e1 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ primary_address,bid_amount_dollars ``` ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --bids-csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --input_csv --fee-payer ``` Example transaction log before: @@ -31,7 +31,7 @@ Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --bids-csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --input_csv --fee-payer ``` Example output: @@ -60,7 +60,7 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute-tokens --dollars-per-sol --dry-run --bids-csv +solana-tokens distribute-tokens --dollars-per-sol --dry-run --input_csv ``` Example bids.csv: diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 96ebe02d1b6807..47f382b73fea19 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -42,12 +42,17 @@ where .help("Transactions database file"), ) .arg( - Arg::with_name("bids_csv") - .long("bids-csv") + Arg::with_name("from_bids") + .long("from-bids") + .help("Input CSV contains bids in dollars, not allocations in SOL"), + ) + .arg( + Arg::with_name("input_csv") + .long("input_csv") .required(true) .takes_value(true) .value_name("FILE") - .help("Bids CSV file"), + .help("Input CSV file"), ) .arg( Arg::with_name("dollars_per_sol") @@ -55,7 +60,7 @@ where .required(true) .takes_value(true) .value_name("NUMBER") - .help("Dollars per SOL"), + .help("Dollars per SOL, if input CSV contains bids") ) .arg( Arg::with_name("dry_run") @@ -149,8 +154,8 @@ where SubCommand::with_name("balances") .about("Balance of each account") .arg( - Arg::with_name("bids_csv") - .long("bids-csv") + Arg::with_name("input_csv") + .long("input_csv") .required(true) .takes_value(true) .value_name("FILE") @@ -170,9 +175,10 @@ where fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { DistributeTokensArgs { - bids_csv: value_t_or_exit!(matches, "bids_csv", String), + input_csv: value_t_or_exit!(matches, "input_csv", String), + from_bids: matches.is_present("from_bids"), transactions_db: value_t_or_exit!(matches, "transactions_db", String), - dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), + dollars_per_sol: value_t!(matches, "dollars_per_sol", f64).ok(), dry_run: matches.is_present("dry_run"), sender_keypair: value_t!(matches, "sender_keypair", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), @@ -194,7 +200,7 @@ fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs< fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { BalancesArgs { - bids_csv: value_t_or_exit!(matches, "bids_csv", String), + input_csv: value_t_or_exit!(matches, "input_csv", String), dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), } } diff --git a/src/args.rs b/src/args.rs index f918535e0f519e..ea913681cd595c 100644 --- a/src/args.rs +++ b/src/args.rs @@ -5,9 +5,10 @@ use solana_sdk::{pubkey::Pubkey, signature::Signer}; use std::error::Error; pub struct DistributeTokensArgs { - pub bids_csv: String, + pub input_csv: String, + pub from_bids: bool, pub transactions_db: String, - pub dollars_per_sol: f64, + pub dollars_per_sol: Option, pub dry_run: bool, pub sender_keypair: Option, pub fee_payer: Option, @@ -25,7 +26,7 @@ pub struct DistributeStakeArgs { } pub struct BalancesArgs { - pub bids_csv: String, + pub input_csv: String, pub dollars_per_sol: f64, } @@ -49,7 +50,8 @@ pub fn resolve_command( let mut wallet_manager = maybe_wallet_manager()?; let matches = ArgMatches::default(); let resolved_args = DistributeTokensArgs { - bids_csv: args.bids_csv, + input_csv: args.input_csv, + from_bids: args.from_bids, transactions_db: args.transactions_db, dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run, diff --git a/src/tokens.rs b/src/tokens.rs index ab9462481408ba..7ad7a8c3336894 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -272,26 +272,42 @@ fn set_transaction_info( Ok(()) } +fn read_allocations( + args: &DistributeTokensArgs> +) -> Vec { + let rdr = ReaderBuilder::new() + .trim(Trim::All) + .from_path(&args.input_csv); + if args.from_bids { + let bids: Vec = rdr.unwrap().deserialize().map(|bid| bid.unwrap()).collect(); + bids + .into_iter() + .map(|bid| create_allocation(&bid, args.dollars_per_sol.unwrap())) + .collect() + } else { + rdr.unwrap().deserialize().map(|entry| entry.unwrap()).collect() + } +} + pub fn process_distribute_tokens( client: &ThinClient, args: &DistributeTokensArgs>, ) -> Result<(), Error> { - let mut rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.bids_csv)?; - let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); - let mut allocations: Vec = bids - .into_iter() - .map(|bid| create_allocation(&bid, args.dollars_per_sol)) - .collect(); + let mut allocations: Vec = read_allocations(&args); let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( - "{} â—Ž{} (${})", + "{} â—Ž{}", style(format!("{}", "Total in allocations_csv:")).bold(), starting_total_tokens, - starting_total_tokens * args.dollars_per_sol, ); + if let Some(dollars_per_sol) = args.dollars_per_sol { + println!( + "{} ${}", + style(format!("{}", "Total in allocations_csv:")).bold(), + starting_total_tokens * dollars_per_sol, + ); + } let mut db = open_db(&args.transactions_db)?; let transaction_infos = read_transaction_infos(&db); @@ -335,23 +351,41 @@ pub fn process_distribute_tokens( let distributed_tokens: f64 = transaction_infos.iter().map(|x| x.amount).sum(); let undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( - "{} â—Ž{} (${})", + "{} â—Ž{}", style(format!("{}", "Distributed:")).bold(), distributed_tokens, - distributed_tokens * args.dollars_per_sol, ); + if let Some(dollars_per_sol) = args.dollars_per_sol { + println!( + "{} ${}", + style(format!("{}", "Distributed:")).bold(), + distributed_tokens * dollars_per_sol, + ); + } println!( - "{} â—Ž{} (${})", + "{} â—Ž{}", style(format!("{}", "Undistributed:")).bold(), undistributed_tokens, - undistributed_tokens * args.dollars_per_sol, ); + if let Some(dollars_per_sol) = args.dollars_per_sol { + println!( + "{} ${}", + style(format!("{}", "Undistributed:")).bold(), + undistributed_tokens * dollars_per_sol, + ); + } println!( - "{} â—Ž{} (${})\n", + "{} â—Ž{}", style(format!("{}", "Total:")).bold(), distributed_tokens + undistributed_tokens, - (distributed_tokens + undistributed_tokens) * args.dollars_per_sol, ); + if let Some(dollars_per_sol) = args.dollars_per_sol { + println!( + "{} ${}", + style(format!("{}", "Total:")).bold(), + (distributed_tokens + undistributed_tokens) * dollars_per_sol, + ); + } distribute_tokens(client, &mut db, &allocations, args)?; @@ -391,7 +425,7 @@ pub fn process_balances( ) -> Result<(), csv::Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) - .from_path(&args.bids_csv)?; + .from_path(&args.input_csv)?; let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); let allocations: Vec = bids .into_iter() @@ -426,7 +460,7 @@ pub fn process_balances( use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; -pub fn test_process_distribute_with_client(client: C, sender_keypair: Keypair) { +pub fn test_process_distribute_bids_with_client(client: C, sender_keypair: Keypair) { let thin_client = ThinClient(client); let fee_payer = Keypair::new(); thin_client @@ -439,7 +473,7 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: accepted_amount_dollars: 1000.0, }; let bids_file = NamedTempFile::new().unwrap(); - let bids_csv = bids_file.path().to_str().unwrap().to_string(); + let input_csv = bids_file.path().to_str().unwrap().to_string(); let mut wtr = csv::WriterBuilder::new().from_writer(bids_file); wtr.serialize(&bid).unwrap(); wtr.flush().unwrap(); @@ -456,15 +490,16 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: sender_keypair: Some(Box::new(sender_keypair)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, - bids_csv, + from_bids: true, + input_csv, transactions_db: transactions_db.clone(), - dollars_per_sol: 0.22, + dollars_per_sol: Some(0.22), }; process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol; + let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol.unwrap(); assert_eq!(transaction_infos[0].amount, expected_amount); assert_eq!( @@ -477,7 +512,68 @@ pub fn test_process_distribute_with_client(client: C, sender_keypair: let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol; + let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol.unwrap(); + assert_eq!(transaction_infos[0].amount, expected_amount); + + assert_eq!( + thin_client.get_balance(&alice_pubkey).unwrap(), + sol_to_lamports(expected_amount), + ); +} + +pub fn test_process_distribute_allocations_with_client(client: C, sender_keypair: Keypair) { + let thin_client = ThinClient(client); + let fee_payer = Keypair::new(); + thin_client + .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) + .unwrap(); + + let alice_pubkey = Pubkey::new_rand(); + let allocation = Allocation { + recipient: alice_pubkey.to_string(), + amount: 1000.0, + }; + let allocations_file = NamedTempFile::new().unwrap(); + let input_csv = allocations_file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(allocations_file); + wtr.serialize(&allocation).unwrap(); + wtr.flush().unwrap(); + + let dir = tempdir().unwrap(); + let transactions_db = dir + .path() + .join("transactions.csv") + .to_str() + .unwrap() + .to_string(); + + let args: DistributeTokensArgs> = DistributeTokensArgs { + sender_keypair: Some(Box::new(sender_keypair)), + fee_payer: Some(Box::new(fee_payer)), + dry_run: false, + input_csv, + from_bids: false, + transactions_db: transactions_db.clone(), + dollars_per_sol: None, + }; + process_distribute_tokens(&thin_client, &args).unwrap(); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + assert_eq!(transaction_infos.len(), 1); + assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + let expected_amount = allocation.amount; + assert_eq!(transaction_infos[0].amount, expected_amount); + + assert_eq!( + thin_client.get_balance(&alice_pubkey).unwrap(), + sol_to_lamports(expected_amount), + ); + + // Now, run it again, and check there's no double-spend. + process_distribute_tokens(&thin_client, &args).unwrap(); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + assert_eq!(transaction_infos.len(), 1); + assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + let expected_amount = allocation.amount; assert_eq!(transaction_infos[0].amount, expected_amount); assert_eq!( @@ -589,11 +685,19 @@ mod tests { use solana_sdk::genesis_config::create_genesis_config; #[test] - fn test_process_distribute() { + fn test_process_distribute_bids() { + let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); + let bank = Bank::new(&genesis_config); + let bank_client = BankClient::new(bank); + test_process_distribute_bids_with_client(bank_client, sender_keypair); + } + + #[test] + fn test_process_distribute_allocations() { let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let bank = Bank::new(&genesis_config); let bank_client = BankClient::new(bank); - test_process_distribute_with_client(bank_client, sender_keypair); + test_process_distribute_allocations_with_client(bank_client, sender_keypair); } #[test] diff --git a/tests/tokens.rs b/tests/tokens.rs index 7a669a3944f18d..c2c3fd255fbb65 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,7 +1,7 @@ use solana_client::rpc_client::RpcClient; use solana_core::validator::{TestValidator, TestValidatorOptions}; use solana_sdk::native_token::sol_to_lamports; -use solana_tokens::tokens::test_process_distribute_with_client; +use solana_tokens::tokens::test_process_distribute_bids_with_client; use std::fs::remove_dir_all; #[test] @@ -12,7 +12,7 @@ fn test_process_distribute_with_rpc_client() { ..TestValidatorOptions::default() }); let rpc_client = RpcClient::new_socket(validator.leader_data.rpc); - test_process_distribute_with_client(rpc_client, validator.alice); + test_process_distribute_bids_with_client(rpc_client, validator.alice); validator.server.close().unwrap(); remove_dir_all(validator.ledger_path).unwrap(); From e766d888362648e21ec5c479ef1701853dc26fbb Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 5 May 2020 16:17:21 -0600 Subject: [PATCH 49/71] Update arg_parser.rs --- src/arg_parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 47f382b73fea19..6aaee6b0ce5220 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -48,7 +48,7 @@ where ) .arg( Arg::with_name("input_csv") - .long("input_csv") + .long("input-csv") .required(true) .takes_value(true) .value_name("FILE") From a737e9e4bf5d36c7172ee1c1eff1191aaf11a94b Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 5 May 2020 17:08:33 -0600 Subject: [PATCH 50/71] Fix balances command (#17) * Fix balances command * Fix readme --- README.md | 6 +++--- src/arg_parser.rs | 13 +++++++++---- src/args.rs | 3 ++- src/tokens.rs | 38 +++++++++++++++++++------------------- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 9c956382b853e1..1450edeaef8e2a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ primary_address,bid_amount_dollars ``` ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --input_csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --input-csv --fee-payer ``` Example transaction log before: @@ -31,7 +31,7 @@ Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --input_csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --input-csv --fee-payer ``` Example output: @@ -60,7 +60,7 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute-tokens --dollars-per-sol --dry-run --input_csv +solana-tokens distribute-tokens --dollars-per-sol --dry-run --input-csv ``` Example bids.csv: diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 6aaee6b0ce5220..35933c6a8ee157 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -60,7 +60,7 @@ where .required(true) .takes_value(true) .value_name("NUMBER") - .help("Dollars per SOL, if input CSV contains bids") + .help("Dollars per SOL, if input CSV contains bids"), ) .arg( Arg::with_name("dry_run") @@ -155,16 +155,20 @@ where .about("Balance of each account") .arg( Arg::with_name("input_csv") - .long("input_csv") + .long("input-csv") .required(true) .takes_value(true) .value_name("FILE") .help("Bids CSV file"), ) + .arg( + Arg::with_name("from_bids") + .long("from-bids") + .help("Input CSV contains bids in dollars, not allocations in SOL"), + ) .arg( Arg::with_name("dollars_per_sol") .long("dollars-per-sol") - .required(true) .takes_value(true) .value_name("NUMBER") .help("Dollars per SOL"), @@ -201,7 +205,8 @@ fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs< fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { BalancesArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), - dollars_per_sol: value_t_or_exit!(matches, "dollars_per_sol", f64), + from_bids: matches.is_present("from_bids"), + dollars_per_sol: value_t!(matches, "dollars_per_sol", f64).ok(), } } diff --git a/src/args.rs b/src/args.rs index ea913681cd595c..60814eca11ba59 100644 --- a/src/args.rs +++ b/src/args.rs @@ -27,7 +27,8 @@ pub struct DistributeStakeArgs { pub struct BalancesArgs { pub input_csv: String, - pub dollars_per_sol: f64, + pub from_bids: bool, + pub dollars_per_sol: Option, } pub enum Command { diff --git a/src/tokens.rs b/src/tokens.rs index 7ad7a8c3336894..87a5a3bd5c0fbe 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -273,19 +273,21 @@ fn set_transaction_info( } fn read_allocations( - args: &DistributeTokensArgs> + input_csv: &str, + from_bids: bool, + dollars_per_sol: Option, ) -> Vec { - let rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.input_csv); - if args.from_bids { + let rdr = ReaderBuilder::new().trim(Trim::All).from_path(input_csv); + if from_bids { let bids: Vec = rdr.unwrap().deserialize().map(|bid| bid.unwrap()).collect(); - bids - .into_iter() - .map(|bid| create_allocation(&bid, args.dollars_per_sol.unwrap())) + bids.into_iter() + .map(|bid| create_allocation(&bid, dollars_per_sol.unwrap())) .collect() } else { - rdr.unwrap().deserialize().map(|entry| entry.unwrap()).collect() + rdr.unwrap() + .deserialize() + .map(|entry| entry.unwrap()) + .collect() } } @@ -293,7 +295,8 @@ pub fn process_distribute_tokens( client: &ThinClient, args: &DistributeTokensArgs>, ) -> Result<(), Error> { - let mut allocations: Vec = read_allocations(&args); + let mut allocations: Vec = + read_allocations(&args.input_csv, args.from_bids, args.dollars_per_sol); let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( @@ -423,14 +426,8 @@ pub fn process_balances( client: &ThinClient, args: &BalancesArgs, ) -> Result<(), csv::Error> { - let mut rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.input_csv)?; - let bids: Vec = rdr.deserialize().map(|bid| bid.unwrap()).collect(); - let allocations: Vec = bids - .into_iter() - .map(|bid| create_allocation(&bid, args.dollars_per_sol)) - .collect(); + let allocations: Vec = + read_allocations(&args.input_csv, args.from_bids, args.dollars_per_sol); let allocations = merge_allocations(&allocations); println!( @@ -521,7 +518,10 @@ pub fn test_process_distribute_bids_with_client(client: C, sender_key ); } -pub fn test_process_distribute_allocations_with_client(client: C, sender_keypair: Keypair) { +pub fn test_process_distribute_allocations_with_client( + client: C, + sender_keypair: Keypair, +) { let thin_client = ThinClient(client); let fee_payer = Keypair::new(); thin_client From ee8e5ac26b3a211c1d6c1571b38e2c6fae44e0a8 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 5 May 2020 17:36:09 -0600 Subject: [PATCH 51/71] Add --force to transfer to non-empty accounts (#18) --- src/arg_parser.rs | 6 ++++++ src/args.rs | 2 ++ src/tokens.rs | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 35933c6a8ee157..cf28645be6345c 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -82,6 +82,11 @@ where .value_name("KEYPAIR") .validator(is_valid_signer) .help("Fee payer"), + ) + .arg( + Arg::with_name("force") + .long("force") + .help("Do not block transfers is recipients have a non-zero balance"), ), ) .subcommand( @@ -186,6 +191,7 @@ fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArg dry_run: matches.is_present("dry_run"), sender_keypair: value_t!(matches, "sender_keypair", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), + force: matches.is_present("force"), } } diff --git a/src/args.rs b/src/args.rs index 60814eca11ba59..793c80097811de 100644 --- a/src/args.rs +++ b/src/args.rs @@ -12,6 +12,7 @@ pub struct DistributeTokensArgs { pub dry_run: bool, pub sender_keypair: Option, pub fee_payer: Option, + pub force: bool, } pub struct DistributeStakeArgs { @@ -62,6 +63,7 @@ pub fn resolve_command( fee_payer: args.fee_payer.as_ref().map(|key_url| { signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() }), + force: args.force, }; Ok(Command::DistributeTokens(resolved_args)) } diff --git a/src/tokens.rs b/src/tokens.rs index 87a5a3bd5c0fbe..464f9c08b9496d 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -331,7 +331,7 @@ pub fn process_distribute_tokens( for allocation in &allocations { let address = allocation.recipient.parse().unwrap(); let balance = client.get_balance(&address).unwrap(); - if balance != 0 { + if !args.force && balance != 0 { eprintln!( "Error: Non-zero balance {}, refusing to send {} to {}", lamports_to_sol(balance), @@ -491,6 +491,7 @@ pub fn test_process_distribute_bids_with_client(client: C, sender_key input_csv, transactions_db: transactions_db.clone(), dollars_per_sol: Some(0.22), + force: false, }; process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); @@ -555,6 +556,7 @@ pub fn test_process_distribute_allocations_with_client( from_bids: false, transactions_db: transactions_db.clone(), dollars_per_sol: None, + force: false, }; process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); From fdb5f569f30f3cd25f37cbf303c19890528472b9 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 6 May 2020 17:18:47 -0600 Subject: [PATCH 52/71] Add --no-wait (#16) * Add ThinClient methods to implement --no-wait * Plumb --no-wait through No tests yet * Check transaction status on startup * Easier to test * Wait until transaction is finalized before checking if it failed with an error It's possible that a minority fork thinks it failed. * Add unit tests * Remove dead code and rustfmt * Don't flush database to file if doing a dry-run --- Cargo.lock | 1 + Cargo.toml | 1 + src/arg_parser.rs | 12 ++ src/args.rs | 4 + src/thin_client.rs | 93 ++++++++++--- src/tokens.rs | 322 ++++++++++++++++++++++++++++++++++++++------- 6 files changed, 363 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec63fa88fb4499..c5cd670eb22099 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3455,6 +3455,7 @@ dependencies = [ "solana-runtime", "solana-sdk", "solana-stake-program", + "solana-transaction-status", "tempfile", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 9657c00623b66d..3011a7e6847f7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ solana-remote-wallet = "1.1.8" solana-runtime = "1.1.8" solana-sdk = "1.1.8" solana-stake-program = "1.1.8" +solana-transaction-status = "1.1.8" tempfile = "3.1.0" thiserror = "1.0" diff --git a/src/arg_parser.rs b/src/arg_parser.rs index cf28645be6345c..aab7126ce2b515 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -67,6 +67,11 @@ where .long("dry-run") .help("Do not execute any transfers"), ) + .arg( + Arg::with_name("no_wait") + .long("no-wait") + .help("Don't wait for transaction confirmations"), + ) .arg( Arg::with_name("sender_keypair") .long("from") @@ -113,6 +118,11 @@ where .long("dry-run") .help("Do not execute any transfers"), ) + .arg( + Arg::with_name("no_wait") + .long("no-wait") + .help("Don't wait for transaction confirmations"), + ) .arg( Arg::with_name("stake_account_address") .required(true) @@ -189,6 +199,7 @@ fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArg transactions_db: value_t_or_exit!(matches, "transactions_db", String), dollars_per_sol: value_t!(matches, "dollars_per_sol", f64).ok(), dry_run: matches.is_present("dry_run"), + no_wait: matches.is_present("no_wait"), sender_keypair: value_t!(matches, "sender_keypair", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), force: matches.is_present("force"), @@ -200,6 +211,7 @@ fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs< allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), transactions_db: value_t_or_exit!(matches, "transactions_db", String), dry_run: matches.is_present("dry_run"), + no_wait: matches.is_present("no_wait"), stake_account_address: value_t_or_exit!(matches, "stake_account_address", String), sol_for_fees: value_t_or_exit!(matches, "sol_for_fees", f64), stake_authority: value_t!(matches, "stake_authority", String).ok(), diff --git a/src/args.rs b/src/args.rs index 793c80097811de..cb85aab85c504d 100644 --- a/src/args.rs +++ b/src/args.rs @@ -10,6 +10,7 @@ pub struct DistributeTokensArgs { pub transactions_db: String, pub dollars_per_sol: Option, pub dry_run: bool, + pub no_wait: bool, pub sender_keypair: Option, pub fee_payer: Option, pub force: bool, @@ -19,6 +20,7 @@ pub struct DistributeStakeArgs { pub allocations_csv: String, pub transactions_db: String, pub dry_run: bool, + pub no_wait: bool, pub sol_for_fees: f64, pub stake_account_address: P, pub stake_authority: Option, @@ -57,6 +59,7 @@ pub fn resolve_command( transactions_db: args.transactions_db, dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run, + no_wait: args.no_wait, sender_keypair: args.sender_keypair.as_ref().map(|key_url| { signer_from_path(&matches, &key_url, "sender", &mut wallet_manager).unwrap() }), @@ -74,6 +77,7 @@ pub fn resolve_command( allocations_csv: args.allocations_csv, transactions_db: args.transactions_db, dry_run: args.dry_run, + no_wait: args.no_wait, stake_account_address: pubkey_from_path( &matches, &args.stake_account_address, diff --git a/src/thin_client.rs b/src/thin_client.rs index fc19e3b0031035..dc66ccc45b9624 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -6,53 +6,95 @@ use solana_sdk::{ hash::Hash, message::Message, pubkey::Pubkey, - signature::{Keypair, Signature, Signer}, + signature::{Signature, Signer}, signers::Signers, system_instruction, transaction::Transaction, transport::{Result, TransportError}, }; +use solana_transaction_status::TransactionStatus; pub trait Client { + fn async_send_transaction1(&self, transaction: Transaction) -> Result; + + // TODO: Work to delete this fn send_and_confirm_transaction1(&self, transaction: Transaction) -> Result; + + fn get_signature_statuses1( + &self, + signatures: &[Signature], + ) -> Result>>; fn get_balance1(&self, pubkey: &Pubkey) -> Result; - fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)>; + fn get_recent_blockhash1(&self) -> Result<(Hash, FeeCalculator)>; } impl Client for RpcClient { + fn async_send_transaction1(&self, transaction: Transaction) -> Result { + self.send_transaction(&transaction) + .map_err(|e| TransportError::Custom(e.to_string())) + } + fn send_and_confirm_transaction1(&self, mut transaction: Transaction) -> Result { - let signers: Vec<&Keypair> = vec![]; // Don't allow resigning + let signers: Vec<&dyn Signer> = vec![]; // Don't allow resigning self.send_and_confirm_transaction_with_spinner(&mut transaction, &signers) .map_err(|e| TransportError::Custom(e.to_string())) } + fn get_signature_statuses1( + &self, + signatures: &[Signature], + ) -> Result>> { + self.get_signature_statuses(signatures) + .map(|response| response.value) + .map_err(|e| TransportError::Custom(e.to_string())) + } + fn get_balance1(&self, pubkey: &Pubkey) -> Result { - let balance = self - .get_balance(pubkey) - .map_err(|e| TransportError::Custom(e.to_string()))?; - Ok(balance) + self.get_balance(pubkey) + .map_err(|e| TransportError::Custom(e.to_string())) } - fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)> { - let blockhash = self - .get_recent_blockhash() - .map_err(|e| TransportError::Custom(e.to_string()))?; - Ok(blockhash) + fn get_recent_blockhash1(&self) -> Result<(Hash, FeeCalculator)> { + self.get_recent_blockhash() + .map_err(|e| TransportError::Custom(e.to_string())) } } impl Client for BankClient { + fn async_send_transaction1(&self, transaction: Transaction) -> Result { + self.async_send_transaction(transaction) + } + fn send_and_confirm_transaction1(&self, transaction: Transaction) -> Result { - let signature = self.async_send_transaction(transaction)?; + let signature = self.async_send_transaction1(transaction)?; self.poll_for_signature(&signature)?; Ok(signature) } + fn get_signature_statuses1( + &self, + signatures: &[Signature], + ) -> Result>> { + signatures + .iter() + .map(|signature| { + self.get_signature_status(signature).map(|opt| { + opt.map(|status| TransactionStatus { + slot: 0, + confirmations: None, + status, + err: None, + }) + }) + }) + .collect() + } + fn get_balance1(&self, pubkey: &Pubkey) -> Result { self.get_balance(pubkey) } - fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)> { + fn get_recent_blockhash1(&self) -> Result<(Hash, FeeCalculator)> { self.get_recent_blockhash() } } @@ -60,16 +102,27 @@ impl Client for BankClient { pub struct ThinClient(pub C); impl ThinClient { + pub fn async_send_transaction(&self, transaction: Transaction) -> Result { + self.0.async_send_transaction1(transaction) + } + + pub fn get_signature_statuses( + &self, + signatures: &[Signature], + ) -> Result>> { + self.0.get_signature_statuses1(signatures) + } + pub fn send_transaction(&self, transaction: Transaction) -> Result { + // TODO: implement this in terms of ThinClient methods and then remove + // send_and_confirm_transaction1 from from the Client trait. self.0.send_and_confirm_transaction1(transaction) } pub fn send_message(&self, message: Message, signers: &S) -> Result { - let (blockhash, _fee_caluclator) = self.0.get_recent_blockhash_and_fees()?; + let (blockhash, _fee_caluclator) = self.get_recent_blockhash()?; let transaction = Transaction::new(signers, message, blockhash); - let signature = transaction.signatures[0]; - self.send_transaction(transaction)?; - Ok(signature) + self.send_transaction(transaction) } pub fn transfer( @@ -84,8 +137,8 @@ impl ThinClient { self.send_message(message, &[sender_keypair]) } - pub fn get_recent_blockhash_and_fees(&self) -> Result<(Hash, FeeCalculator)> { - self.0.get_recent_blockhash_and_fees() + pub fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> { + self.0.get_recent_blockhash1() } pub fn get_balance(&self, pubkey: &Pubkey) -> Result { diff --git a/src/tokens.rs b/src/tokens.rs index 464f9c08b9496d..bf392100b54d18 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -17,6 +17,7 @@ use solana_stake_program::{ stake_instruction, stake_state::{Authorized, Lockup, StakeAuthorize}, }; +use solana_transaction_status::TransactionStatus; use std::path::Path; use std::process; @@ -32,7 +33,7 @@ struct Allocation { amount: f64, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] struct TransactionInfo { recipient: String, amount: f64, @@ -123,16 +124,20 @@ fn distribute_tokens( let lamports = sol_to_lamports(allocation.amount); let instruction = system_instruction::transfer(&from, &to, lamports); let message = Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)); - let (blockhash, _fee_caluclator) = client.get_recent_blockhash_and_fees()?; + let (blockhash, _fee_caluclator) = client.get_recent_blockhash()?; let transaction = Transaction::new(&signers, message, blockhash); let signature = transaction.signatures[0]; set_transaction_info(db, &allocation, &signature, None, false)?; - client.send_transaction(transaction) + if args.no_wait { + client.async_send_transaction(transaction) + } else { + client.send_transaction(transaction) + } }; match result { Ok(signature) => { println!("Finalized transaction with signature {}", signature); - if !args.dry_run { + if !args.no_wait { set_transaction_info(db, &allocation, &signature, None, true)?; } } @@ -205,7 +210,7 @@ fn distribute_stake( )); let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); - let (blockhash, _fee_caluclator) = client.get_recent_blockhash_and_fees()?; + let (blockhash, _fee_caluclator) = client.get_recent_blockhash()?; let transaction = Transaction::new(&signers, message, blockhash); let signature = transaction.signatures[0]; set_transaction_info( @@ -215,12 +220,16 @@ fn distribute_stake( Some(&new_stake_account_address), false, )?; - client.send_transaction(transaction) + if args.no_wait { + client.async_send_transaction(transaction) + } else { + client.send_transaction(transaction) + } }; match result { Ok(signature) => { println!("Finalized transaction with signature {}", signature); - if !args.dry_run { + if !args.no_wait { set_transaction_info( db, &allocation, @@ -238,8 +247,12 @@ fn distribute_stake( Ok(()) } -fn open_db(path: &str) -> Result { - let policy = PickleDbDumpPolicy::AutoDump; +fn open_db(path: &str, dry_run: bool) -> Result { + let policy = if dry_run { + PickleDbDumpPolicy::NeverDump + } else { + PickleDbDumpPolicy::AutoDump + }; if Path::new(path).exists() { PickleDb::load_yaml(path, policy) } else { @@ -247,6 +260,17 @@ fn open_db(path: &str) -> Result { } } +fn read_transaction_data(db: &PickleDb) -> Vec<(Signature, TransactionInfo)> { + db.iter() + .map(|kv| { + ( + kv.get_key().parse().unwrap(), + kv.get_value::().unwrap(), + ) + }) + .collect() +} + fn read_transaction_infos(db: &PickleDb) -> Vec { db.iter() .map(|kv| kv.get_value::().unwrap()) @@ -265,7 +289,7 @@ fn set_transaction_info( amount: allocation.amount, new_stake_account_address: new_stake_account_address .map(|pubkey| pubkey.to_string()) - .unwrap_or("".to_string()), + .unwrap_or_else(|| "".to_string()), finalized, }; db.set(&signature.to_string(), &transaction_info)?; @@ -301,18 +325,24 @@ pub fn process_distribute_tokens( let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( "{} â—Ž{}", - style(format!("{}", "Total in allocations_csv:")).bold(), + style("Total in allocations_csv:").bold(), starting_total_tokens, ); if let Some(dollars_per_sol) = args.dollars_per_sol { println!( "{} ${}", - style(format!("{}", "Total in allocations_csv:")).bold(), + style("Total in allocations_csv:").bold(), starting_total_tokens * dollars_per_sol, ); } - let mut db = open_db(&args.transactions_db)?; + let mut db = open_db(&args.transactions_db, args.dry_run)?; + let still_finalizing = update_finalized_transactions(client, &mut db)?; + if still_finalizing { + eprintln!("Still finalizing transactions. Try again in 10 seconds"); + process::exit(1); + } + let transaction_infos = read_transaction_infos(&db); apply_previous_transactions(&mut allocations, &transaction_infos); @@ -353,39 +383,35 @@ pub fn process_distribute_tokens( let distributed_tokens: f64 = transaction_infos.iter().map(|x| x.amount).sum(); let undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); - println!( - "{} â—Ž{}", - style(format!("{}", "Distributed:")).bold(), - distributed_tokens, - ); + println!("{} â—Ž{}", style("Distributed:").bold(), distributed_tokens,); if let Some(dollars_per_sol) = args.dollars_per_sol { println!( "{} ${}", - style(format!("{}", "Distributed:")).bold(), + style("Distributed:").bold(), distributed_tokens * dollars_per_sol, ); } println!( "{} â—Ž{}", - style(format!("{}", "Undistributed:")).bold(), + style("Undistributed:").bold(), undistributed_tokens, ); if let Some(dollars_per_sol) = args.dollars_per_sol { println!( "{} ${}", - style(format!("{}", "Undistributed:")).bold(), + style("Undistributed:").bold(), undistributed_tokens * dollars_per_sol, ); } println!( "{} â—Ž{}", - style(format!("{}", "Total:")).bold(), + style("Total:").bold(), distributed_tokens + undistributed_tokens, ); if let Some(dollars_per_sol) = args.dollars_per_sol { println!( "{} ${}", - style(format!("{}", "Total:")).bold(), + style("Total:").bold(), (distributed_tokens + undistributed_tokens) * dollars_per_sol, ); } @@ -395,6 +421,77 @@ pub fn process_distribute_tokens( Ok(()) } +// Set the finalized bit in the database if the transaction is rooted. +// Remove the TransactionInfo from the database if the transaction failed. +// Return true if still waiting to finalize. +fn update_finalized_transaction( + db: &mut PickleDb, + signature: &Signature, + opt_transaction_status: Option, +) -> Result { + if opt_transaction_status.is_none() { + eprintln!( + "Signature not found {}. If its blockhash is expired, remove it from the database", + signature + ); + + // Return true because the transaction might still be in flight and get accepted onto + // the ledger. + return Ok(true); + } + let transaction_status = opt_transaction_status.unwrap(); + + if transaction_status.confirmations.is_some() { + // The transaction was found but is not yet finalized. + return Ok(true); + } + + if let Err(e) = &transaction_status.status { + // The transaction was finalized, but execution failed. Drop it. + eprintln!( + "Error in transaction with signature {}: {}", + signature, + e.to_string() + ); + eprintln!("Discarding transaction record"); + db.rem(&signature.to_string())?; + return Ok(false); + } + + // Transaction is rooted. Set finalized in the database. + let mut transaction_info = db.get::(&signature.to_string()).unwrap(); + transaction_info.finalized = true; + db.set(&signature.to_string(), &transaction_info)?; + Ok(false) +} + +// Update the finalized bit on any transactions that are now rooted +fn update_finalized_transactions( + client: &ThinClient, + db: &mut PickleDb, +) -> Result { + let transaction_data = read_transaction_data(db); + let unconfirmed_signatures: Vec<_> = transaction_data + .iter() + .filter_map(|(signature, info)| { + if info.finalized { + None + } else { + Some(*signature) + } + }) + .collect(); + let transaction_statuses = client.get_signature_statuses(&unconfirmed_signatures)?; + let mut still_finalizing = false; + for (signature, opt_transaction_status) in unconfirmed_signatures + .into_iter() + .zip(transaction_statuses.into_iter()) + { + still_finalizing |= update_finalized_transaction(db, &signature, opt_transaction_status)?; + } + Ok(still_finalizing) +} + pub fn process_distribute_stake( client: &ThinClient, args: &DistributeStakeArgs>, @@ -407,9 +504,15 @@ pub fn process_distribute_stake( .map(|allocation| allocation.unwrap()) .collect(); - let mut db = open_db(&args.transactions_db)?; - let transaction_infos = read_transaction_infos(&db); + let mut db = open_db(&args.transactions_db, args.dry_run)?; + let still_finalizing = update_finalized_transactions(client, &mut db)?; + if still_finalizing { + eprintln!("Still finalizing transactions. Try again in 10 seconds"); + process::exit(1); + } + let mut allocations = merge_allocations(&allocations); + let transaction_infos = read_transaction_infos(&db); apply_previous_transactions(&mut allocations, &transaction_infos); if allocations.is_empty() { @@ -487,6 +590,7 @@ pub fn test_process_distribute_bids_with_client(client: C, sender_key sender_keypair: Some(Box::new(sender_keypair)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, + no_wait: false, from_bids: true, input_csv, transactions_db: transactions_db.clone(), @@ -494,28 +598,36 @@ pub fn test_process_distribute_bids_with_client(client: C, sender_key force: false, }; process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol.unwrap(); - assert_eq!(transaction_infos[0].amount, expected_amount); + let expected_amount = + sol_to_lamports(bid.accepted_amount_dollars / args.dollars_per_sol.unwrap()); + assert_eq!( + sol_to_lamports(transaction_infos[0].amount), + expected_amount + ); assert_eq!( thin_client.get_balance(&alice_pubkey).unwrap(), - sol_to_lamports(expected_amount), + expected_amount, ); // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = bid.accepted_amount_dollars / args.dollars_per_sol.unwrap(); - assert_eq!(transaction_infos[0].amount, expected_amount); + let expected_amount = + sol_to_lamports(bid.accepted_amount_dollars / args.dollars_per_sol.unwrap()); + assert_eq!( + sol_to_lamports(transaction_infos[0].amount), + expected_amount + ); assert_eq!( thin_client.get_balance(&alice_pubkey).unwrap(), - sol_to_lamports(expected_amount), + expected_amount, ); } @@ -552,6 +664,7 @@ pub fn test_process_distribute_allocations_with_client( sender_keypair: Some(Box::new(sender_keypair)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, + no_wait: false, input_csv, from_bids: false, transactions_db: transactions_db.clone(), @@ -559,28 +672,34 @@ pub fn test_process_distribute_allocations_with_client( force: false, }; process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = allocation.amount; - assert_eq!(transaction_infos[0].amount, expected_amount); + let expected_amount = sol_to_lamports(allocation.amount); + assert_eq!( + sol_to_lamports(transaction_infos[0].amount), + expected_amount + ); assert_eq!( thin_client.get_balance(&alice_pubkey).unwrap(), - sol_to_lamports(expected_amount), + expected_amount, ); // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = allocation.amount; - assert_eq!(transaction_infos[0].amount, expected_amount); + let expected_amount = sol_to_lamports(allocation.amount); + assert_eq!( + sol_to_lamports(transaction_infos[0].amount), + expected_amount + ); assert_eq!( thin_client.get_balance(&alice_pubkey).unwrap(), - sol_to_lamports(expected_amount), + expected_amount, ); } @@ -638,16 +757,20 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke withdraw_authority: Some(Box::new(withdraw_authority)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, + no_wait: false, sol_for_fees: 1.0, allocations_csv, transactions_db: transactions_db.clone(), }; process_distribute_stake(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = allocation.amount; - assert_eq!(transaction_infos[0].amount, expected_amount); + let expected_amount = sol_to_lamports(allocation.amount); + assert_eq!( + sol_to_lamports(transaction_infos[0].amount), + expected_amount + ); assert_eq!( thin_client.get_balance(&alice_pubkey).unwrap(), @@ -659,16 +782,19 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke .unwrap(); assert_eq!( thin_client.get_balance(&new_stake_account_address).unwrap(), - sol_to_lamports(expected_amount - 1.0), + expected_amount - sol_to_lamports(1.0), ); // Now, run it again, and check there's no double-spend. process_distribute_stake(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = allocation.amount; - assert_eq!(transaction_infos[0].amount, expected_amount); + let expected_amount = sol_to_lamports(allocation.amount); + assert_eq!( + sol_to_lamports(transaction_infos[0].amount), + expected_amount + ); assert_eq!( thin_client.get_balance(&alice_pubkey).unwrap(), @@ -676,7 +802,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke ); assert_eq!( thin_client.get_balance(&new_stake_account_address).unwrap(), - sol_to_lamports(expected_amount - 1.0), + expected_amount - sol_to_lamports(1.0), ); } @@ -684,7 +810,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke mod tests { use super::*; use solana_runtime::{bank::Bank, bank_client::BankClient}; - use solana_sdk::genesis_config::create_genesis_config; + use solana_sdk::{genesis_config::create_genesis_config, transaction::TransactionError}; #[test] fn test_process_distribute_bids() { @@ -735,4 +861,100 @@ mod tests { // a matching recipient address (to "b", not "a"). assert_eq!(allocations[0].recipient, "a"); } + + #[test] + fn test_update_finalized_transaction_not_landed() { + // Keep waiting for a transaction that hasn't landed yet. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + assert_eq!( + update_finalized_transaction(&mut db, &signature, None).unwrap(), + true + ); + + // Unchanged + assert_eq!( + db.get::(&signature.to_string()).unwrap(), + transaction_info + ); + } + + #[test] + fn test_update_finalized_transaction_confirming() { + // Keep waiting for a transaction that is still being confirmed. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + let transaction_status = TransactionStatus { + slot: 0, + confirmations: Some(1), + status: Ok(()), + err: None, + }; + assert_eq!( + update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), + true + ); + + // Unchanged + assert_eq!( + db.get::(&signature.to_string()).unwrap(), + transaction_info + ); + } + + #[test] + fn test_update_finalized_transaction_failed() { + // Don't wait if the transaction failed to execute. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + let status = Err(TransactionError::AccountNotFound); + let transaction_status = TransactionStatus { + slot: 0, + confirmations: None, + status, + err: None, + }; + assert_eq!( + update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), + false + ); + + // Ensure TransactionInfo has been purged. + assert_eq!(db.get::(&signature.to_string()), None); + } + + #[test] + fn test_update_finalized_transaction_finalized() { + // Don't wait once the transaction has been finalized. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let mut transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + let transaction_status = TransactionStatus { + slot: 0, + confirmations: None, + status: Ok(()), + err: None, + }; + assert_eq!( + update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), + false + ); + + transaction_info.finalized = true; + assert_eq!( + db.get::(&signature.to_string()).unwrap(), + transaction_info + ); + } } From 6885f1a4a8de44909e50995f22a47142216c8783 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 6 May 2020 23:14:32 -0600 Subject: [PATCH 53/71] Continue when transactions not yet finalized (#20) If those transactions are dropped, the next run will execute them. --- src/tokens.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index bf392100b54d18..4343a65070ef6b 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -70,9 +70,6 @@ fn apply_previous_transactions( transaction_infos: &[TransactionInfo], ) { for transaction_info in transaction_infos { - if !transaction_info.finalized { - panic!("Attempt to apply an unconfirmed transaction. Please confirm the trarnsaction has been finalized or that its blockhash has expired."); - } let mut amount = transaction_info.amount; for allocation in allocations.iter_mut() { if allocation.recipient != transaction_info.recipient { @@ -339,8 +336,7 @@ pub fn process_distribute_tokens( let mut db = open_db(&args.transactions_db, args.dry_run)?; let still_finalizing = update_finalized_transactions(client, &mut db)?; if still_finalizing { - eprintln!("Still finalizing transactions. Try again in 10 seconds"); - process::exit(1); + eprintln!("warning: some transactions not yet finalized"); } let transaction_infos = read_transaction_infos(&db); @@ -507,8 +503,7 @@ pub fn process_distribute_stake( let mut db = open_db(&args.transactions_db, args.dry_run)?; let still_finalizing = update_finalized_transactions(client, &mut db)?; if still_finalizing { - eprintln!("Still finalizing transactions. Try again in 10 seconds"); - process::exit(1); + eprintln!("warning: some transactions not yet finalized"); } let mut allocations = merge_allocations(&allocations); From 6dafeb510425809257ea784620844c711b3afc33 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 7 May 2020 02:20:50 -0600 Subject: [PATCH 54/71] Return the number of confirmations (#21) --- src/tokens.rs | 74 +++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 4343a65070ef6b..71166d76b01563 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -18,8 +18,7 @@ use solana_stake_program::{ stake_state::{Authorized, Lockup, StakeAuthorize}, }; use solana_transaction_status::TransactionStatus; -use std::path::Path; -use std::process; +use std::{path::Path, process, cmp}; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -315,7 +314,7 @@ fn read_allocations( pub fn process_distribute_tokens( client: &ThinClient, args: &DistributeTokensArgs>, -) -> Result<(), Error> { +) -> Result, Error> { let mut allocations: Vec = read_allocations(&args.input_csv, args.from_bids, args.dollars_per_sol); @@ -334,9 +333,9 @@ pub fn process_distribute_tokens( } let mut db = open_db(&args.transactions_db, args.dry_run)?; - let still_finalizing = update_finalized_transactions(client, &mut db)?; - if still_finalizing { - eprintln!("warning: some transactions not yet finalized"); + let confirmations = update_finalized_transactions(client, &mut db)?; + if confirmations.is_some() { + eprintln!("warning: unfinalized transactions"); } let transaction_infos = read_transaction_infos(&db); @@ -344,7 +343,7 @@ pub fn process_distribute_tokens( if allocations.is_empty() { eprintln!("No work to do"); - return Ok(()); + return Ok(confirmations); } // Sanity check: the recipient should not have tokens yet. If they do, it @@ -414,17 +413,18 @@ pub fn process_distribute_tokens( distribute_tokens(client, &mut db, &allocations, args)?; - Ok(()) + let confirmations = update_finalized_transactions(client, &mut db)?; + Ok(confirmations) } // Set the finalized bit in the database if the transaction is rooted. // Remove the TransactionInfo from the database if the transaction failed. -// Return true if still waiting to finalize. +// Return the number of confirmations on the transaction or None if finalized. fn update_finalized_transaction( db: &mut PickleDb, signature: &Signature, opt_transaction_status: Option, -) -> Result { +) -> Result, pickledb::error::Error> { if opt_transaction_status.is_none() { eprintln!( "Signature not found {}. If its blockhash is expired, remove it from the database", @@ -433,13 +433,13 @@ fn update_finalized_transaction( // Return true because the transaction might still be in flight and get accepted onto // the ledger. - return Ok(true); + return Ok(Some(0)); } let transaction_status = opt_transaction_status.unwrap(); - if transaction_status.confirmations.is_some() { + if let Some(confirmations) = transaction_status.confirmations { // The transaction was found but is not yet finalized. - return Ok(true); + return Ok(Some(confirmations)); } if let Err(e) = &transaction_status.status { @@ -451,21 +451,22 @@ fn update_finalized_transaction( ); eprintln!("Discarding transaction record"); db.rem(&signature.to_string())?; - return Ok(false); + return Ok(None); } // Transaction is rooted. Set finalized in the database. let mut transaction_info = db.get::(&signature.to_string()).unwrap(); transaction_info.finalized = true; db.set(&signature.to_string(), &transaction_info)?; - Ok(false) + Ok(None) } // Update the finalized bit on any transactions that are now rooted +// Return the lowest number of confirmations on the unfinalized transactions or None if all are finalized. fn update_finalized_transactions( client: &ThinClient, db: &mut PickleDb, -) -> Result { +) -> Result, Error> { let transaction_data = read_transaction_data(db); let unconfirmed_signatures: Vec<_> = transaction_data .iter() @@ -478,20 +479,22 @@ fn update_finalized_transactions( }) .collect(); let transaction_statuses = client.get_signature_statuses(&unconfirmed_signatures)?; - let mut still_finalizing = false; + let mut confirmations = None; for (signature, opt_transaction_status) in unconfirmed_signatures .into_iter() .zip(transaction_statuses.into_iter()) { - still_finalizing |= update_finalized_transaction(db, &signature, opt_transaction_status)?; + if let Some(confs) = update_finalized_transaction(db, &signature, opt_transaction_status)? { + confirmations = Some(cmp::min(confs, confirmations.unwrap_or(usize::MAX))); + } } - Ok(still_finalizing) + Ok(confirmations) } pub fn process_distribute_stake( client: &ThinClient, args: &DistributeStakeArgs>, -) -> Result<(), Error> { +) -> Result, Error> { let mut rdr = ReaderBuilder::new() .trim(Trim::All) .from_path(&args.allocations_csv)?; @@ -501,9 +504,9 @@ pub fn process_distribute_stake( .collect(); let mut db = open_db(&args.transactions_db, args.dry_run)?; - let still_finalizing = update_finalized_transactions(client, &mut db)?; - if still_finalizing { - eprintln!("warning: some transactions not yet finalized"); + let confirmations = update_finalized_transactions(client, &mut db)?; + if confirmations.is_some() { + eprintln!("warning: unfinalized transactions"); } let mut allocations = merge_allocations(&allocations); @@ -512,12 +515,13 @@ pub fn process_distribute_stake( if allocations.is_empty() { eprintln!("No work to do"); - return Ok(()); + return Ok(confirmations); } distribute_stake(client, &mut db, &allocations, args)?; - Ok(()) + let confirmations = update_finalized_transactions(client, &mut db)?; + Ok(confirmations) } pub fn process_balances( @@ -609,7 +613,9 @@ pub fn test_process_distribute_bids_with_client(client: C, sender_key ); // Now, run it again, and check there's no double-spend. - process_distribute_tokens(&thin_client, &args).unwrap(); + let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); + assert_eq!(confirmations, None); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); @@ -666,7 +672,9 @@ pub fn test_process_distribute_allocations_with_client( dollars_per_sol: None, force: false, }; - process_distribute_tokens(&thin_client, &args).unwrap(); + let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); + assert_eq!(confirmations, None); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); @@ -757,7 +765,9 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke allocations_csv, transactions_db: transactions_db.clone(), }; - process_distribute_stake(&thin_client, &args).unwrap(); + let confirmations = process_distribute_stake(&thin_client, &args).unwrap(); + assert_eq!(confirmations, None); + let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); @@ -867,7 +877,7 @@ mod tests { db.set(&signature.to_string(), &transaction_info).unwrap(); assert_eq!( update_finalized_transaction(&mut db, &signature, None).unwrap(), - true + Some(0) ); // Unchanged @@ -893,7 +903,7 @@ mod tests { }; assert_eq!( update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), - true + Some(1) ); // Unchanged @@ -920,7 +930,7 @@ mod tests { }; assert_eq!( update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), - false + None ); // Ensure TransactionInfo has been purged. @@ -943,7 +953,7 @@ mod tests { }; assert_eq!( update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), - false + None ); transaction_info.finalized = true; From 5258447aeef259d9cb20b128e73c69227d0a7b0e Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 7 May 2020 03:38:32 -0600 Subject: [PATCH 55/71] Add read_allocations() unit-test (#22) Delete the copy-pasted top-level test. Fixes #19 --- src/tokens.rs | 135 ++++++++++++++++-------------------------------- tests/tokens.rs | 4 +- 2 files changed, 47 insertions(+), 92 deletions(-) diff --git a/src/tokens.rs b/src/tokens.rs index 71166d76b01563..c9729c07c426e4 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -18,7 +18,7 @@ use solana_stake_program::{ stake_state::{Authorized, Lockup, StakeAuthorize}, }; use solana_transaction_status::TransactionStatus; -use std::{path::Path, process, cmp}; +use std::{cmp, path::Path, process}; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -26,7 +26,7 @@ struct Bid { primary_address: String, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] struct Allocation { recipient: String, amount: f64, @@ -559,83 +559,7 @@ pub fn process_balances( use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; -pub fn test_process_distribute_bids_with_client(client: C, sender_keypair: Keypair) { - let thin_client = ThinClient(client); - let fee_payer = Keypair::new(); - thin_client - .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) - .unwrap(); - - let alice_pubkey = Pubkey::new_rand(); - let bid = Bid { - primary_address: alice_pubkey.to_string(), - accepted_amount_dollars: 1000.0, - }; - let bids_file = NamedTempFile::new().unwrap(); - let input_csv = bids_file.path().to_str().unwrap().to_string(); - let mut wtr = csv::WriterBuilder::new().from_writer(bids_file); - wtr.serialize(&bid).unwrap(); - wtr.flush().unwrap(); - - let dir = tempdir().unwrap(); - let transactions_db = dir - .path() - .join("transactions.csv") - .to_str() - .unwrap() - .to_string(); - - let args: DistributeTokensArgs> = DistributeTokensArgs { - sender_keypair: Some(Box::new(sender_keypair)), - fee_payer: Some(Box::new(fee_payer)), - dry_run: false, - no_wait: false, - from_bids: true, - input_csv, - transactions_db: transactions_db.clone(), - dollars_per_sol: Some(0.22), - force: false, - }; - process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); - assert_eq!(transaction_infos.len(), 1); - assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = - sol_to_lamports(bid.accepted_amount_dollars / args.dollars_per_sol.unwrap()); - assert_eq!( - sol_to_lamports(transaction_infos[0].amount), - expected_amount - ); - - assert_eq!( - thin_client.get_balance(&alice_pubkey).unwrap(), - expected_amount, - ); - - // Now, run it again, and check there's no double-spend. - let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); - assert_eq!(confirmations, None); - - let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); - assert_eq!(transaction_infos.len(), 1); - assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); - let expected_amount = - sol_to_lamports(bid.accepted_amount_dollars / args.dollars_per_sol.unwrap()); - assert_eq!( - sol_to_lamports(transaction_infos[0].amount), - expected_amount - ); - - assert_eq!( - thin_client.get_balance(&alice_pubkey).unwrap(), - expected_amount, - ); -} - -pub fn test_process_distribute_allocations_with_client( - client: C, - sender_keypair: Keypair, -) { +pub fn test_process_distribute_tokens_with_client(client: C, sender_keypair: Keypair) { let thin_client = ThinClient(client); let fee_payer = Keypair::new(); thin_client @@ -656,7 +580,7 @@ pub fn test_process_distribute_allocations_with_client( let dir = tempdir().unwrap(); let transactions_db = dir .path() - .join("transactions.csv") + .join("transactions.db") .to_str() .unwrap() .to_string(); @@ -749,7 +673,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke let dir = tempdir().unwrap(); let transactions_db = dir .path() - .join("transactions.csv") + .join("transactions.db") .to_str() .unwrap() .to_string(); @@ -818,27 +742,58 @@ mod tests { use solana_sdk::{genesis_config::create_genesis_config, transaction::TransactionError}; #[test] - fn test_process_distribute_bids() { + fn test_process_distribute_tokens() { let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let bank = Bank::new(&genesis_config); let bank_client = BankClient::new(bank); - test_process_distribute_bids_with_client(bank_client, sender_keypair); + test_process_distribute_tokens_with_client(bank_client, sender_keypair); } #[test] - fn test_process_distribute_allocations() { + fn test_process_distribute_stake() { let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let bank = Bank::new(&genesis_config); let bank_client = BankClient::new(bank); - test_process_distribute_allocations_with_client(bank_client, sender_keypair); + test_process_distribute_stake_with_client(bank_client, sender_keypair); } #[test] - fn test_process_distribute_stake() { - let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); - let bank = Bank::new(&genesis_config); - let bank_client = BankClient::new(bank); - test_process_distribute_stake_with_client(bank_client, sender_keypair); + fn test_read_allocations() { + let alice_pubkey = Pubkey::new_rand(); + let allocation = Allocation { + recipient: alice_pubkey.to_string(), + amount: 42.0, + }; + let file = NamedTempFile::new().unwrap(); + let input_csv = file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(file); + wtr.serialize(&allocation).unwrap(); + wtr.flush().unwrap(); + + assert_eq!(read_allocations(&input_csv, false, None), vec![allocation]); + } + + #[test] + fn test_read_allocations_from_bids() { + let alice_pubkey = Pubkey::new_rand(); + let bid = Bid { + primary_address: alice_pubkey.to_string(), + accepted_amount_dollars: 42.0, + }; + let file = NamedTempFile::new().unwrap(); + let input_csv = file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(file); + wtr.serialize(&bid).unwrap(); + wtr.flush().unwrap(); + + let allocation = Allocation { + recipient: bid.primary_address, + amount: 84.0, + }; + assert_eq!( + read_allocations(&input_csv, true, Some(0.5)), + vec![allocation] + ); } #[test] diff --git a/tests/tokens.rs b/tests/tokens.rs index c2c3fd255fbb65..8ca40725556851 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,7 +1,7 @@ use solana_client::rpc_client::RpcClient; use solana_core::validator::{TestValidator, TestValidatorOptions}; use solana_sdk::native_token::sol_to_lamports; -use solana_tokens::tokens::test_process_distribute_bids_with_client; +use solana_tokens::tokens::test_process_distribute_tokens_with_client; use std::fs::remove_dir_all; #[test] @@ -12,7 +12,7 @@ fn test_process_distribute_with_rpc_client() { ..TestValidatorOptions::default() }); let rpc_client = RpcClient::new_socket(validator.leader_data.rpc); - test_process_distribute_bids_with_client(rpc_client, validator.alice); + test_process_distribute_tokens_with_client(rpc_client, validator.alice); validator.server.close().unwrap(); remove_dir_all(validator.ledger_path).unwrap(); From 6f288be4c9f3636ea4c2982b18bfbdfda689167a Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 7 May 2020 09:28:17 -0600 Subject: [PATCH 56/71] Add a CSV printer (#23) --- .vscode/launch.json | 83 +++++++++++++++++++++++++++++++++++++++++++++ src/arg_parser.rs | 32 ++++++++++++++++- src/args.rs | 7 ++++ src/main.rs | 3 ++ src/tokens.rs | 58 +++++++++++++++++++++++++++++-- 5 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000000000..b740a4ee4e3905 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,83 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in library 'solana-tokens'", + "cargo": { + "args": [ + "test", + "--no-run", + "--lib", + "--package=solana-tokens" + ], + "filter": { + "name": "solana-tokens", + "kind": "lib" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'solana-tokens'", + "cargo": { + "args": [ + "build", + "--bin=solana-tokens", + "--package=solana-tokens" + ], + "filter": { + "name": "solana-tokens", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'solana-tokens'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=solana-tokens", + "--package=solana-tokens" + ], + "filter": { + "name": "solana-tokens", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug integration test 'tokens'", + "cargo": { + "args": [ + "test", + "--no-run", + "--test=tokens", + "--package=solana-tokens" + ], + "filter": { + "name": "tokens", + "kind": "test" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/src/arg_parser.rs b/src/arg_parser.rs index aab7126ce2b515..6d379d9975f06d 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,4 +1,6 @@ -use crate::args::{Args, BalancesArgs, Command, DistributeStakeArgs, DistributeTokensArgs}; +use crate::args::{ + Args, BalancesArgs, Command, DistributeStakeArgs, DistributeTokensArgs, PrintDbArgs, +}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; use solana_cli_config::CONFIG_FILE; @@ -189,6 +191,26 @@ where .help("Dollars per SOL"), ), ) + .subcommand( + SubCommand::with_name("print-database") + .about("Print the database to a CSV file") + .arg( + Arg::with_name("transactions_db") + .required(true) + .index(1) + .takes_value(true) + .value_name("FILE") + .help("Transactions database file"), + ) + .arg( + Arg::with_name("output_path") + .long("output-path") + .required(true) + .takes_value(true) + .value_name("FILE") + .help("Output file"), + ), + ) .get_matches_from(args) } @@ -228,6 +250,13 @@ fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { } } +fn parse_print_db_args(matches: &ArgMatches<'_>) -> PrintDbArgs { + PrintDbArgs { + transactions_db: value_t_or_exit!(matches, "transactions_db", String), + output_path: value_t_or_exit!(matches, "output_path", String), + } +} + pub fn parse_args(args: I) -> Args where I: IntoIterator, @@ -245,6 +274,7 @@ where Command::DistributeStake(parse_distribute_stake_args(matches)) } ("balances", Some(matches)) => Command::Balances(parse_balances_args(matches)), + ("print-database", Some(matches)) => Command::PrintDb(parse_print_db_args(matches)), _ => { eprintln!("{}", matches.usage()); exit(1); diff --git a/src/args.rs b/src/args.rs index cb85aab85c504d..f025269cc78237 100644 --- a/src/args.rs +++ b/src/args.rs @@ -34,10 +34,16 @@ pub struct BalancesArgs { pub dollars_per_sol: Option, } +pub struct PrintDbArgs { + pub transactions_db: String, + pub output_path: String, +} + pub enum Command { DistributeTokens(DistributeTokensArgs), DistributeStake(DistributeStakeArgs), Balances(BalancesArgs), + PrintDb(PrintDbArgs), } pub struct Args { @@ -106,5 +112,6 @@ pub fn resolve_command( Ok(Command::DistributeStake(resolved_args)) } Command::Balances(args) => Ok(Command::Balances(args)), + Command::PrintDb(args) => Ok(Command::PrintDb(args)), } } diff --git a/src/main.rs b/src/main.rs index 6a44419a1d14ec..3afbc78e48bc00 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,9 @@ fn main() -> Result<(), Box> { Command::Balances(args) => { tokens::process_balances(&thin_client, &args)?; } + Command::PrintDb(args) => { + tokens::process_print_db(&args)?; + } } Ok(()) } diff --git a/src/tokens.rs b/src/tokens.rs index c9729c07c426e4..ea8ef722ca2221 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,4 +1,4 @@ -use crate::args::{BalancesArgs, DistributeStakeArgs, DistributeTokensArgs}; +use crate::args::{BalancesArgs, DistributeStakeArgs, DistributeTokensArgs, PrintDbArgs}; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; @@ -18,7 +18,7 @@ use solana_stake_program::{ stake_state::{Authorized, Lockup, StakeAuthorize}, }; use solana_transaction_status::TransactionStatus; -use std::{cmp, path::Path, process}; +use std::{cmp, io, path::Path, process}; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -40,8 +40,19 @@ struct TransactionInfo { finalized: bool, } +#[derive(Serialize, Deserialize, Debug, Default, PartialEq)] +struct SignedTransactionInfo { + recipient: String, + amount: f64, + new_stake_account_address: String, + finalized: bool, + signature: String, +} + #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("I/O error")] + IoError(#[from] io::Error), #[error("CSV error")] CsvError(#[from] csv::Error), #[error("PickleDb error")] @@ -256,6 +267,21 @@ fn open_db(path: &str, dry_run: bool) -> Result>(db: &PickleDb, path: &P) -> Result<(), io::Error> { + let mut wtr = csv::WriterBuilder::new().from_path(path).unwrap(); + for (signature, info) in read_transaction_data(db) { + let signed_info = SignedTransactionInfo { + recipient: info.recipient, + amount: info.amount, + new_stake_account_address: info.new_stake_account_address, + finalized: info.finalized, + signature: signature.to_string(), + }; + wtr.serialize(&signed_info)?; + } + wtr.flush() +} + fn read_transaction_data(db: &PickleDb) -> Vec<(Signature, TransactionInfo)> { db.iter() .map(|kv| { @@ -557,6 +583,12 @@ pub fn process_balances( Ok(()) } +pub fn process_print_db(args: &PrintDbArgs) -> Result<(), Error> { + let db = open_db(&args.transactions_db, true)?; + print_db(&db, &args.output_path)?; + Ok(()) +} + use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; pub fn test_process_distribute_tokens_with_client(client: C, sender_keypair: Keypair) { @@ -917,4 +949,26 @@ mod tests { transaction_info ); } + + #[test] + fn test_print_db() { + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + + let csv_file = NamedTempFile::new().unwrap(); + print_db(&db, &csv_file).unwrap(); + + let mut rdr = ReaderBuilder::new().trim(Trim::All).from_reader(csv_file); + let signed_infos: Vec = + rdr.deserialize().map(|entry| entry.unwrap()).collect(); + + let signed_info = SignedTransactionInfo { + signature: Signature::default().to_string(), + ..SignedTransactionInfo::default() + }; + assert_eq!(signed_infos, vec![signed_info]); + } } From 426ec4ffcfd2533ed3c1e8919d323faafb3035f9 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 7 May 2020 09:50:39 -0600 Subject: [PATCH 57/71] Remove all the copypasta (#24) * Move resolve_distribute_stake_args into its own function * Add stake args to token args * Unify option names * Move Command::DistributeStake into DistributeTokens * Remove process_distribute_stake * Only unique signers * Use sender keypair to fund new fee-payer accounts * Unify distribute_tokens and distribute_stake --- Cargo.lock | 1 + Cargo.toml | 1 + src/arg_parser.rs | 40 ++++++--- src/args.rs | 80 +++++++---------- src/main.rs | 3 - src/tokens.rs | 224 +++++++++++++++++----------------------------- 6 files changed, 146 insertions(+), 203 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5cd670eb22099..6dedb8be7d285f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3445,6 +3445,7 @@ dependencies = [ "console 0.10.3", "csv", "indexmap", + "itertools 0.9.0", "pickledb", "serde", "solana-clap-utils", diff --git a/Cargo.toml b/Cargo.toml index 3011a7e6847f7b..6de42d696eafe5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ csv = "1.1.3" clap = "2.33.0" console = "0.10.3" indexmap = "1.3.2" +itertools = "0.9.0" pickledb = "0.4.1" serde = { version = "1.0", features = ["derive"] } solana-clap-utils = "1.1.8" diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 6d379d9975f06d..93ea438466aed5 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,6 +1,4 @@ -use crate::args::{ - Args, BalancesArgs, Command, DistributeStakeArgs, DistributeTokensArgs, PrintDbArgs, -}; +use crate::args::{Args, BalancesArgs, Command, DistributeTokensArgs, PrintDbArgs, StakeArgs}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; use solana_cli_config::CONFIG_FILE; @@ -108,8 +106,8 @@ where .help("Transactions database file"), ) .arg( - Arg::with_name("allocations_csv") - .long("allocations-csv") + Arg::with_name("input_csv") + .long("input-csv") .required(true) .takes_value(true) .value_name("FILE") @@ -125,6 +123,14 @@ where .long("no-wait") .help("Don't wait for transaction confirmations"), ) + .arg( + Arg::with_name("sender_keypair") + .long("from") + .takes_value(true) + .value_name("SENDING_KEYPAIR") + .validator(is_valid_signer) + .help("Keypair to fund accounts"), + ) .arg( Arg::with_name("stake_account_address") .required(true) @@ -214,7 +220,7 @@ where .get_matches_from(args) } -fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { +fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { DistributeTokensArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), from_bids: matches.is_present("from_bids"), @@ -225,20 +231,28 @@ fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArg sender_keypair: value_t!(matches, "sender_keypair", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), force: matches.is_present("force"), + stake_args: None, } } -fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeStakeArgs { - DistributeStakeArgs { - allocations_csv: value_t_or_exit!(matches, "allocations_csv", String), - transactions_db: value_t_or_exit!(matches, "transactions_db", String), - dry_run: matches.is_present("dry_run"), - no_wait: matches.is_present("no_wait"), +fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { + let stake_args = StakeArgs { stake_account_address: value_t_or_exit!(matches, "stake_account_address", String), sol_for_fees: value_t_or_exit!(matches, "sol_for_fees", f64), stake_authority: value_t!(matches, "stake_authority", String).ok(), withdraw_authority: value_t!(matches, "withdraw_authority", String).ok(), + }; + DistributeTokensArgs { + input_csv: value_t_or_exit!(matches, "input_csv", String), + from_bids: false, + transactions_db: value_t_or_exit!(matches, "transactions_db", String), + dollars_per_sol: None, + dry_run: matches.is_present("dry_run"), + no_wait: matches.is_present("no_wait"), + sender_keypair: value_t!(matches, "sender_keypair", String).ok(), fee_payer: value_t!(matches, "fee_payer", String).ok(), + force: false, + stake_args: Some(stake_args), } } @@ -271,7 +285,7 @@ where Command::DistributeTokens(parse_distribute_tokens_args(matches)) } ("distribute-stake", Some(matches)) => { - Command::DistributeStake(parse_distribute_stake_args(matches)) + Command::DistributeTokens(parse_distribute_stake_args(matches)) } ("balances", Some(matches)) => Command::Balances(parse_balances_args(matches)), ("print-database", Some(matches)) => Command::PrintDb(parse_print_db_args(matches)), diff --git a/src/args.rs b/src/args.rs index f025269cc78237..7b69e6edc8fbe6 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,10 +1,10 @@ use clap::ArgMatches; use solana_clap_utils::keypair::{pubkey_from_path, signer_from_path}; -use solana_remote_wallet::remote_wallet::maybe_wallet_manager; +use solana_remote_wallet::remote_wallet::{maybe_wallet_manager, RemoteWalletManager}; use solana_sdk::{pubkey::Pubkey, signature::Signer}; -use std::error::Error; +use std::{error::Error, sync::Arc}; -pub struct DistributeTokensArgs { +pub struct DistributeTokensArgs { pub input_csv: String, pub from_bids: bool, pub transactions_db: String, @@ -14,18 +14,14 @@ pub struct DistributeTokensArgs { pub sender_keypair: Option, pub fee_payer: Option, pub force: bool, + pub stake_args: Option>, } -pub struct DistributeStakeArgs { - pub allocations_csv: String, - pub transactions_db: String, - pub dry_run: bool, - pub no_wait: bool, +pub struct StakeArgs { pub sol_for_fees: f64, pub stake_account_address: P, pub stake_authority: Option, pub withdraw_authority: Option, - pub fee_payer: Option, } pub struct BalancesArgs { @@ -40,8 +36,7 @@ pub struct PrintDbArgs { } pub enum Command { - DistributeTokens(DistributeTokensArgs), - DistributeStake(DistributeStakeArgs), + DistributeTokens(DistributeTokensArgs), Balances(BalancesArgs), PrintDb(PrintDbArgs), } @@ -52,6 +47,30 @@ pub struct Args { pub command: Command, } +pub fn resolve_stake_args( + wallet_manager: &mut Option>, + args: StakeArgs, +) -> Result>, Box> { + let matches = ArgMatches::default(); + let resolved_args = StakeArgs { + stake_account_address: pubkey_from_path( + &matches, + &args.stake_account_address, + "stake account address", + wallet_manager, + ) + .unwrap(), + sol_for_fees: args.sol_for_fees, + stake_authority: args.stake_authority.as_ref().map(|key_url| { + signer_from_path(&matches, &key_url, "stake authority", wallet_manager).unwrap() + }), + withdraw_authority: args.withdraw_authority.as_ref().map(|key_url| { + signer_from_path(&matches, &key_url, "withdraw authority", wallet_manager).unwrap() + }), + }; + Ok(resolved_args) +} + pub fn resolve_command( command: Command, ) -> Result>, Box> { @@ -59,6 +78,9 @@ pub fn resolve_command( Command::DistributeTokens(args) => { let mut wallet_manager = maybe_wallet_manager()?; let matches = ArgMatches::default(); + let resolved_stake_args = args + .stake_args + .map(|args| resolve_stake_args(&mut wallet_manager, args)); let resolved_args = DistributeTokensArgs { input_csv: args.input_csv, from_bids: args.from_bids, @@ -73,44 +95,10 @@ pub fn resolve_command( signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() }), force: args.force, + stake_args: resolved_stake_args.map_or(Ok(None), |r| r.map(Some))?, }; Ok(Command::DistributeTokens(resolved_args)) } - Command::DistributeStake(args) => { - let mut wallet_manager = maybe_wallet_manager()?; - let matches = ArgMatches::default(); - let resolved_args = DistributeStakeArgs { - allocations_csv: args.allocations_csv, - transactions_db: args.transactions_db, - dry_run: args.dry_run, - no_wait: args.no_wait, - stake_account_address: pubkey_from_path( - &matches, - &args.stake_account_address, - "stake account address", - &mut wallet_manager, - ) - .unwrap(), - sol_for_fees: args.sol_for_fees, - stake_authority: args.stake_authority.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "stake authority", &mut wallet_manager) - .unwrap() - }), - withdraw_authority: args.withdraw_authority.as_ref().map(|key_url| { - signer_from_path( - &matches, - &key_url, - "withdraw authority", - &mut wallet_manager, - ) - .unwrap() - }), - fee_payer: args.fee_payer.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() - }), - }; - Ok(Command::DistributeStake(resolved_args)) - } Command::Balances(args) => Ok(Command::Balances(args)), Command::PrintDb(args) => Ok(Command::PrintDb(args)), } diff --git a/src/main.rs b/src/main.rs index 3afbc78e48bc00..9eea518f52b194 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,9 +20,6 @@ fn main() -> Result<(), Box> { Command::DistributeTokens(args) => { tokens::process_distribute_tokens(&thin_client, &args)?; } - Command::DistributeStake(args) => { - tokens::process_distribute_stake(&thin_client, &args)?; - } Command::Balances(args) => { tokens::process_balances(&thin_client, &args)?; } diff --git a/src/tokens.rs b/src/tokens.rs index ea8ef722ca2221..bbfe5d39d57b19 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,8 +1,9 @@ -use crate::args::{BalancesArgs, DistributeStakeArgs, DistributeTokensArgs, PrintDbArgs}; +use crate::args::{BalancesArgs, DistributeTokensArgs, PrintDbArgs, StakeArgs}; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; use indexmap::IndexMap; +use itertools::Itertools; use pickledb::{PickleDb, PickleDbDumpPolicy}; use serde::{Deserialize, Serialize}; use solana_sdk::{ @@ -61,6 +62,10 @@ pub enum Error { TransportError(#[from] TransportError), } +fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> { + signers.into_iter().unique_by(|s| s.pubkey()).collect_vec() +} + fn merge_allocations(allocations: &[Allocation]) -> Vec { let mut allocation_map = IndexMap::new(); for allocation in allocations { @@ -108,59 +113,7 @@ fn distribute_tokens( client: &ThinClient, db: &mut PickleDb, allocations: &[Allocation], - args: &DistributeTokensArgs>, -) -> Result<(), Error> { - let signers = if args.dry_run { - vec![] - } else { - let mut signers = vec![&**args.sender_keypair.as_ref().unwrap()]; - if args.sender_keypair != args.fee_payer { - signers.push(&**args.fee_payer.as_ref().unwrap()); - } - signers - }; - - for allocation in allocations { - println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); - let result = if args.dry_run { - Ok(Signature::default()) - } else { - let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); - let from = args.sender_keypair.as_ref().unwrap().pubkey(); - let to = allocation.recipient.parse().unwrap(); - let lamports = sol_to_lamports(allocation.amount); - let instruction = system_instruction::transfer(&from, &to, lamports); - let message = Message::new_with_payer(&[instruction], Some(&fee_payer_pubkey)); - let (blockhash, _fee_caluclator) = client.get_recent_blockhash()?; - let transaction = Transaction::new(&signers, message, blockhash); - let signature = transaction.signatures[0]; - set_transaction_info(db, &allocation, &signature, None, false)?; - if args.no_wait { - client.async_send_transaction(transaction) - } else { - client.send_transaction(transaction) - } - }; - match result { - Ok(signature) => { - println!("Finalized transaction with signature {}", signature); - if !args.no_wait { - set_transaction_info(db, &allocation, &signature, None, true)?; - } - } - Err(e) => { - eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); - } - }; - } - Ok(()) -} - -fn distribute_stake( - client: &ThinClient, - db: &mut PickleDb, - allocations: &[Allocation], - args: &DistributeStakeArgs>, + args: &DistributeTokensArgs>, ) -> Result<(), Error> { for allocation in allocations { let new_stake_account_keypair = Keypair::new(); @@ -168,54 +121,69 @@ fn distribute_stake( let signers = if args.dry_run { vec![] } else { - vec![ + let mut signers = vec![ &**args.fee_payer.as_ref().unwrap(), - &**args.stake_authority.as_ref().unwrap(), - &**args.withdraw_authority.as_ref().unwrap(), - &new_stake_account_keypair, - ] + &**args.sender_keypair.as_ref().unwrap(), + ]; + if let Some(stake_args) = &args.stake_args { + signers.push(&**stake_args.stake_authority.as_ref().unwrap()); + signers.push(&**stake_args.withdraw_authority.as_ref().unwrap()); + signers.push(&new_stake_account_keypair); + } + unique_signers(signers) }; println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); let result = if args.dry_run { Ok(Signature::default()) } else { - let system_sol = args.sol_for_fees; - let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); - let stake_authority = args.stake_authority.as_ref().unwrap().pubkey(); - let withdraw_authority = args.withdraw_authority.as_ref().unwrap().pubkey(); - - let mut instructions = stake_instruction::split( - &args.stake_account_address, - &stake_authority, - sol_to_lamports(allocation.amount - system_sol), - &new_stake_account_address, - ); - - let recipient = allocation.recipient.parse().unwrap(); - - // Make the recipient the new stake authority - instructions.push(stake_instruction::authorize( - &new_stake_account_address, - &stake_authority, - &recipient, - StakeAuthorize::Staker, - )); - - // Make the recipient the new withdraw authority - instructions.push(stake_instruction::authorize( - &new_stake_account_address, - &withdraw_authority, - &recipient, - StakeAuthorize::Withdrawer, - )); - - instructions.push(system_instruction::transfer( - &fee_payer_pubkey, // Should this be a sender keypair? - &recipient, - sol_to_lamports(system_sol), - )); + let instructions = if let Some(stake_args) = &args.stake_args { + let sol_for_fees = stake_args.sol_for_fees; + let sender_pubkey = args.sender_keypair.as_ref().unwrap().pubkey(); + let stake_authority = stake_args.stake_authority.as_ref().unwrap().pubkey(); + let withdraw_authority = stake_args.withdraw_authority.as_ref().unwrap().pubkey(); + + let mut instructions = stake_instruction::split( + &stake_args.stake_account_address, + &stake_authority, + sol_to_lamports(allocation.amount - sol_for_fees), + &new_stake_account_address, + ); + + let recipient = allocation.recipient.parse().unwrap(); + + // Make the recipient the new stake authority + instructions.push(stake_instruction::authorize( + &new_stake_account_address, + &stake_authority, + &recipient, + StakeAuthorize::Staker, + )); + + // Make the recipient the new withdraw authority + instructions.push(stake_instruction::authorize( + &new_stake_account_address, + &withdraw_authority, + &recipient, + StakeAuthorize::Withdrawer, + )); + + instructions.push(system_instruction::transfer( + &sender_pubkey, + &recipient, + sol_to_lamports(sol_for_fees), + )); + + instructions + } else { + let from = args.sender_keypair.as_ref().unwrap().pubkey(); + let to = allocation.recipient.parse().unwrap(); + let lamports = sol_to_lamports(allocation.amount); + let instruction = system_instruction::transfer(&from, &to, lamports); + vec![instruction] + }; + let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); let (blockhash, _fee_caluclator) = client.get_recent_blockhash()?; let transaction = Transaction::new(&signers, message, blockhash); @@ -339,7 +307,7 @@ fn read_allocations( pub fn process_distribute_tokens( client: &ThinClient, - args: &DistributeTokensArgs>, + args: &DistributeTokensArgs>, ) -> Result, Error> { let mut allocations: Vec = read_allocations(&args.input_csv, args.from_bids, args.dollars_per_sol); @@ -347,13 +315,13 @@ pub fn process_distribute_tokens( let starting_total_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); println!( "{} â—Ž{}", - style("Total in allocations_csv:").bold(), + style("Total in input_csv:").bold(), starting_total_tokens, ); if let Some(dollars_per_sol) = args.dollars_per_sol { println!( "{} ${}", - style("Total in allocations_csv:").bold(), + style("Total in input_csv:").bold(), starting_total_tokens * dollars_per_sol, ); } @@ -382,7 +350,7 @@ pub fn process_distribute_tokens( for allocation in &allocations { let address = allocation.recipient.parse().unwrap(); let balance = client.get_balance(&address).unwrap(); - if !args.force && balance != 0 { + if args.stake_args.is_none() && !args.force && balance != 0 { eprintln!( "Error: Non-zero balance {}, refusing to send {} to {}", lamports_to_sol(balance), @@ -517,39 +485,6 @@ fn update_finalized_transactions( Ok(confirmations) } -pub fn process_distribute_stake( - client: &ThinClient, - args: &DistributeStakeArgs>, -) -> Result, Error> { - let mut rdr = ReaderBuilder::new() - .trim(Trim::All) - .from_path(&args.allocations_csv)?; - let allocations: Vec = rdr - .deserialize() - .map(|allocation| allocation.unwrap()) - .collect(); - - let mut db = open_db(&args.transactions_db, args.dry_run)?; - let confirmations = update_finalized_transactions(client, &mut db)?; - if confirmations.is_some() { - eprintln!("warning: unfinalized transactions"); - } - - let mut allocations = merge_allocations(&allocations); - let transaction_infos = read_transaction_infos(&db); - apply_previous_transactions(&mut allocations, &transaction_infos); - - if allocations.is_empty() { - eprintln!("No work to do"); - return Ok(confirmations); - } - - distribute_stake(client, &mut db, &allocations, args)?; - - let confirmations = update_finalized_transactions(client, &mut db)?; - Ok(confirmations) -} - pub fn process_balances( client: &ThinClient, args: &BalancesArgs, @@ -617,7 +552,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k .unwrap() .to_string(); - let args: DistributeTokensArgs> = DistributeTokensArgs { + let args: DistributeTokensArgs> = DistributeTokensArgs { sender_keypair: Some(Box::new(sender_keypair)), fee_payer: Some(Box::new(fee_payer)), dry_run: false, @@ -627,6 +562,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k transactions_db: transactions_db.clone(), dollars_per_sol: None, force: false, + stake_args: None, }; let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); assert_eq!(confirmations, None); @@ -669,7 +605,6 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) .unwrap(); - // TODO: Create a stake account with lockups let stake_account_keypair = Keypair::new(); let stake_account_address = stake_account_keypair.pubkey(); let stake_authority = Keypair::new(); @@ -696,9 +631,9 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke recipient: alice_pubkey.to_string(), amount: 1000.0, }; - let allocations_file = NamedTempFile::new().unwrap(); - let allocations_csv = allocations_file.path().to_str().unwrap().to_string(); - let mut wtr = csv::WriterBuilder::new().from_writer(allocations_file); + let file = NamedTempFile::new().unwrap(); + let input_csv = file.path().to_str().unwrap().to_string(); + let mut wtr = csv::WriterBuilder::new().from_writer(file); wtr.serialize(&allocation).unwrap(); wtr.flush().unwrap(); @@ -710,18 +645,25 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke .unwrap() .to_string(); - let args: DistributeStakeArgs> = DistributeStakeArgs { + let stake_args: StakeArgs> = StakeArgs { stake_account_address, stake_authority: Some(Box::new(stake_authority)), withdraw_authority: Some(Box::new(withdraw_authority)), + sol_for_fees: 1.0, + }; + let args: DistributeTokensArgs> = DistributeTokensArgs { fee_payer: Some(Box::new(fee_payer)), dry_run: false, no_wait: false, - sol_for_fees: 1.0, - allocations_csv, + input_csv, transactions_db: transactions_db.clone(), + stake_args: Some(stake_args), + force: false, + from_bids: false, + sender_keypair: Some(Box::new(sender_keypair)), + dollars_per_sol: None, }; - let confirmations = process_distribute_stake(&thin_client, &args).unwrap(); + let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); assert_eq!(confirmations, None); let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); @@ -747,7 +689,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke ); // Now, run it again, and check there's no double-spend. - process_distribute_stake(&thin_client, &args).unwrap(); + process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); From 6007905185a0c86ecdc501e39e774af4054697ac Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 8 May 2020 08:41:08 -0600 Subject: [PATCH 58/71] Rename print-database command to transaction-log (#25) --- src/arg_parser.rs | 14 +++++++++----- src/args.rs | 6 +++--- src/main.rs | 4 ++-- src/tokens.rs | 12 ++++++------ 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 93ea438466aed5..34541c87e74357 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -1,4 +1,6 @@ -use crate::args::{Args, BalancesArgs, Command, DistributeTokensArgs, PrintDbArgs, StakeArgs}; +use crate::args::{ + Args, BalancesArgs, Command, DistributeTokensArgs, StakeArgs, TransactionLogArgs, +}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_clap_utils::input_validators::{is_valid_pubkey, is_valid_signer}; use solana_cli_config::CONFIG_FILE; @@ -198,7 +200,7 @@ where ), ) .subcommand( - SubCommand::with_name("print-database") + SubCommand::with_name("transaction-log") .about("Print the database to a CSV file") .arg( Arg::with_name("transactions_db") @@ -264,8 +266,8 @@ fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { } } -fn parse_print_db_args(matches: &ArgMatches<'_>) -> PrintDbArgs { - PrintDbArgs { +fn parse_transaction_log_args(matches: &ArgMatches<'_>) -> TransactionLogArgs { + TransactionLogArgs { transactions_db: value_t_or_exit!(matches, "transactions_db", String), output_path: value_t_or_exit!(matches, "output_path", String), } @@ -288,7 +290,9 @@ where Command::DistributeTokens(parse_distribute_stake_args(matches)) } ("balances", Some(matches)) => Command::Balances(parse_balances_args(matches)), - ("print-database", Some(matches)) => Command::PrintDb(parse_print_db_args(matches)), + ("transaction-log", Some(matches)) => { + Command::TransactionLog(parse_transaction_log_args(matches)) + } _ => { eprintln!("{}", matches.usage()); exit(1); diff --git a/src/args.rs b/src/args.rs index 7b69e6edc8fbe6..a771c57031f331 100644 --- a/src/args.rs +++ b/src/args.rs @@ -30,7 +30,7 @@ pub struct BalancesArgs { pub dollars_per_sol: Option, } -pub struct PrintDbArgs { +pub struct TransactionLogArgs { pub transactions_db: String, pub output_path: String, } @@ -38,7 +38,7 @@ pub struct PrintDbArgs { pub enum Command { DistributeTokens(DistributeTokensArgs), Balances(BalancesArgs), - PrintDb(PrintDbArgs), + TransactionLog(TransactionLogArgs), } pub struct Args { @@ -100,6 +100,6 @@ pub fn resolve_command( Ok(Command::DistributeTokens(resolved_args)) } Command::Balances(args) => Ok(Command::Balances(args)), - Command::PrintDb(args) => Ok(Command::PrintDb(args)), + Command::TransactionLog(args) => Ok(Command::TransactionLog(args)), } } diff --git a/src/main.rs b/src/main.rs index 9eea518f52b194..79f7c25add4ccf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,8 +23,8 @@ fn main() -> Result<(), Box> { Command::Balances(args) => { tokens::process_balances(&thin_client, &args)?; } - Command::PrintDb(args) => { - tokens::process_print_db(&args)?; + Command::TransactionLog(args) => { + tokens::process_transaction_log(&args)?; } } Ok(()) diff --git a/src/tokens.rs b/src/tokens.rs index bbfe5d39d57b19..5ecda89b8c51d3 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,4 +1,4 @@ -use crate::args::{BalancesArgs, DistributeTokensArgs, PrintDbArgs, StakeArgs}; +use crate::args::{BalancesArgs, DistributeTokensArgs, StakeArgs, TransactionLogArgs}; use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; @@ -235,7 +235,7 @@ fn open_db(path: &str, dry_run: bool) -> Result>(db: &PickleDb, path: &P) -> Result<(), io::Error> { +pub fn write_transaction_log>(db: &PickleDb, path: &P) -> Result<(), io::Error> { let mut wtr = csv::WriterBuilder::new().from_path(path).unwrap(); for (signature, info) in read_transaction_data(db) { let signed_info = SignedTransactionInfo { @@ -518,9 +518,9 @@ pub fn process_balances( Ok(()) } -pub fn process_print_db(args: &PrintDbArgs) -> Result<(), Error> { +pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> { let db = open_db(&args.transactions_db, true)?; - print_db(&db, &args.output_path)?; + write_transaction_log(&db, &args.output_path)?; Ok(()) } @@ -893,7 +893,7 @@ mod tests { } #[test] - fn test_print_db() { + fn test_write_transaction_log() { let mut db = PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); let signature = Signature::default(); @@ -901,7 +901,7 @@ mod tests { db.set(&signature.to_string(), &transaction_info).unwrap(); let csv_file = NamedTempFile::new().unwrap(); - print_db(&db, &csv_file).unwrap(); + write_transaction_log(&db, &csv_file).unwrap(); let mut rdr = ReaderBuilder::new().trim(Trim::All).from_reader(csv_file); let signed_infos: Vec = From a29ae506671897bea575b860d58893c2a2a24dbd Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 8 May 2020 09:51:33 -0600 Subject: [PATCH 59/71] Send all transactions as quickly as possible, then wait (#26) * Send all transactions as quickly as possible, then wait * Exit when finalized or blockhashes have expired * Don't need blockhash in the CSV output * Better types CSV library was choking on Pubkey as a type. PickleDb doesn't have that problem. * Resend if blockhash has not expired * Attempt to fix CI --- .travis.yml | 1 - Cargo.lock | 1 + Cargo.toml | 1 + src/thin_client.rs | 28 +++++ src/tokens.rs | 284 ++++++++++++++++++++++++++++++--------------- tests/tokens.rs | 1 - 6 files changed, 221 insertions(+), 95 deletions(-) diff --git a/.travis.yml b/.travis.yml index da1d173f0abd7f..cba263c127543c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: rust -cache: cargo addons: apt: packages: diff --git a/Cargo.lock b/Cargo.lock index 6dedb8be7d285f..c6344c84f9d5de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3445,6 +3445,7 @@ dependencies = [ "console 0.10.3", "csv", "indexmap", + "indicatif", "itertools 0.9.0", "pickledb", "serde", diff --git a/Cargo.toml b/Cargo.toml index 6de42d696eafe5..bef3e726642708 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ csv = "1.1.3" clap = "2.33.0" console = "0.10.3" indexmap = "1.3.2" +indicatif = "0.14.0" itertools = "0.9.0" pickledb = "0.4.1" serde = { version = "1.0", features = ["derive"] } diff --git a/src/thin_client.rs b/src/thin_client.rs index dc66ccc45b9624..8b9a28a495f02b 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -1,6 +1,7 @@ use solana_client::rpc_client::RpcClient; use solana_runtime::bank_client::BankClient; use solana_sdk::{ + account::Account, client::{AsyncClient, SyncClient}, fee_calculator::FeeCalculator, hash::Hash, @@ -9,6 +10,10 @@ use solana_sdk::{ signature::{Signature, Signer}, signers::Signers, system_instruction, + sysvar::{ + recent_blockhashes::{self, RecentBlockhashes}, + Sysvar, + }, transaction::Transaction, transport::{Result, TransportError}, }; @@ -26,6 +31,7 @@ pub trait Client { ) -> Result>>; fn get_balance1(&self, pubkey: &Pubkey) -> Result; fn get_recent_blockhash1(&self) -> Result<(Hash, FeeCalculator)>; + fn get_account1(&self, pubkey: &Pubkey) -> Result>; } impl Client for RpcClient { @@ -58,6 +64,12 @@ impl Client for RpcClient { self.get_recent_blockhash() .map_err(|e| TransportError::Custom(e.to_string())) } + + fn get_account1(&self, pubkey: &Pubkey) -> Result> { + self.get_account(pubkey) + .map(Some) + .map_err(|e| TransportError::Custom(e.to_string())) + } } impl Client for BankClient { @@ -97,6 +109,10 @@ impl Client for BankClient { fn get_recent_blockhash1(&self) -> Result<(Hash, FeeCalculator)> { self.get_recent_blockhash() } + + fn get_account1(&self, pubkey: &Pubkey) -> Result> { + self.get_account(pubkey) + } } pub struct ThinClient(pub C); @@ -144,4 +160,16 @@ impl ThinClient { pub fn get_balance(&self, pubkey: &Pubkey) -> Result { self.0.get_balance1(pubkey) } + + pub fn get_account(&self, pubkey: &Pubkey) -> Result> { + self.0.get_account1(pubkey) + } + + pub fn get_recent_blockhashes(&self) -> Result> { + let opt_blockhashes_account = self.get_account(&recent_blockhashes::id())?; + let blockhashes_account = opt_blockhashes_account.unwrap(); + let recent_blockhashes = RecentBlockhashes::from_account(&blockhashes_account).unwrap(); + let hashes = recent_blockhashes.iter().map(|x| x.blockhash).collect(); + Ok(hashes) + } } diff --git a/src/tokens.rs b/src/tokens.rs index 5ecda89b8c51d3..89987b1cd62ba3 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -3,10 +3,12 @@ use crate::thin_client::{Client, ThinClient}; use console::style; use csv::{ReaderBuilder, Trim}; use indexmap::IndexMap; +use indicatif::{ProgressBar, ProgressStyle}; use itertools::Itertools; use pickledb::{PickleDb, PickleDbDumpPolicy}; use serde::{Deserialize, Serialize}; use solana_sdk::{ + hash::Hash, message::Message, native_token::{lamports_to_sol, sol_to_lamports}, signature::{Signature, Signer}, @@ -19,7 +21,7 @@ use solana_stake_program::{ stake_state::{Authorized, Lockup, StakeAuthorize}, }; use solana_transaction_status::TransactionStatus; -use std::{cmp, io, path::Path, process}; +use std::{cmp, io, path::Path, process, thread::sleep, time::Duration}; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -33,12 +35,27 @@ struct Allocation { amount: f64, } -#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] struct TransactionInfo { - recipient: String, + recipient: Pubkey, amount: f64, - new_stake_account_address: String, + new_stake_account_address: Option, finalized: bool, + transaction: Transaction, +} + +impl Default for TransactionInfo { + fn default() -> Self { + let mut transaction = Transaction::new_unsigned_instructions(vec![]); + transaction.signatures.push(Signature::default()); + Self { + recipient: Pubkey::default(), + amount: 0.0, + new_stake_account_address: None, + finalized: false, + transaction, + } + } } #[derive(Serialize, Deserialize, Debug, Default, PartialEq)] @@ -60,6 +77,8 @@ pub enum Error { PickleDbError(#[from] pickledb::error::Error), #[error("Transport error")] TransportError(#[from] TransportError), + #[error("Signature not found")] + SignatureNotFound, } fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> { @@ -87,7 +106,7 @@ fn apply_previous_transactions( for transaction_info in transaction_infos { let mut amount = transaction_info.amount; for allocation in allocations.iter_mut() { - if allocation.recipient != transaction_info.recipient { + if allocation.recipient != transaction_info.recipient.to_string() { continue; } if allocation.amount >= amount { @@ -187,37 +206,19 @@ fn distribute_tokens( let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); let (blockhash, _fee_caluclator) = client.get_recent_blockhash()?; let transaction = Transaction::new(&signers, message, blockhash); - let signature = transaction.signatures[0]; set_transaction_info( db, &allocation, - &signature, + &transaction, Some(&new_stake_account_address), false, )?; - if args.no_wait { - client.async_send_transaction(transaction) - } else { - client.send_transaction(transaction) - } - }; - match result { - Ok(signature) => { - println!("Finalized transaction with signature {}", signature); - if !args.no_wait { - set_transaction_info( - db, - &allocation, - &signature, - Some(&new_stake_account_address), - true, - )?; - } - } - Err(e) => { - eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); - } + + client.async_send_transaction(transaction) }; + if let Err(e) = result { + eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); + } } Ok(()) } @@ -237,30 +238,22 @@ fn open_db(path: &str, dry_run: bool) -> Result>(db: &PickleDb, path: &P) -> Result<(), io::Error> { let mut wtr = csv::WriterBuilder::new().from_path(path).unwrap(); - for (signature, info) in read_transaction_data(db) { + for info in read_transaction_infos(db) { let signed_info = SignedTransactionInfo { - recipient: info.recipient, + recipient: info.recipient.to_string(), amount: info.amount, - new_stake_account_address: info.new_stake_account_address, + new_stake_account_address: info + .new_stake_account_address + .map(|x| x.to_string()) + .unwrap_or_else(|| "".to_string()), finalized: info.finalized, - signature: signature.to_string(), + signature: info.transaction.signatures[0].to_string(), }; wtr.serialize(&signed_info)?; } wtr.flush() } -fn read_transaction_data(db: &PickleDb) -> Vec<(Signature, TransactionInfo)> { - db.iter() - .map(|kv| { - ( - kv.get_key().parse().unwrap(), - kv.get_value::().unwrap(), - ) - }) - .collect() -} - fn read_transaction_infos(db: &PickleDb) -> Vec { db.iter() .map(|kv| kv.get_value::().unwrap()) @@ -270,18 +263,18 @@ fn read_transaction_infos(db: &PickleDb) -> Vec { fn set_transaction_info( db: &mut PickleDb, allocation: &Allocation, - signature: &Signature, + transaction: &Transaction, new_stake_account_address: Option<&Pubkey>, finalized: bool, ) -> Result<(), pickledb::error::Error> { let transaction_info = TransactionInfo { - recipient: allocation.recipient.clone(), + recipient: allocation.recipient.parse().unwrap(), amount: allocation.amount, - new_stake_account_address: new_stake_account_address - .map(|pubkey| pubkey.to_string()) - .unwrap_or_else(|| "".to_string()), + new_stake_account_address: new_stake_account_address.cloned(), finalized, + transaction: transaction.clone(), }; + let signature = transaction.signatures[0]; db.set(&signature.to_string(), &transaction_info)?; Ok(()) } @@ -305,6 +298,14 @@ fn read_allocations( } } +fn new_spinner_progress_bar() -> ProgressBar { + let progress_bar = ProgressBar::new(42); + progress_bar + .set_style(ProgressStyle::default_spinner().template("{spinner:.green} {wide_msg}")); + progress_bar.enable_steady_tick(100); + progress_bar +} + pub fn process_distribute_tokens( client: &ThinClient, args: &DistributeTokensArgs>, @@ -327,10 +328,9 @@ pub fn process_distribute_tokens( } let mut db = open_db(&args.transactions_db, args.dry_run)?; - let confirmations = update_finalized_transactions(client, &mut db)?; - if confirmations.is_some() { - eprintln!("warning: unfinalized transactions"); - } + + // Start by finalizing any transactions from the previous run. + let confirmations = finalize_transactions(client, &mut db, args.dry_run, args.no_wait)?; let transaction_infos = read_transaction_infos(&db); apply_previous_transactions(&mut allocations, &transaction_infos); @@ -407,8 +407,45 @@ pub fn process_distribute_tokens( distribute_tokens(client, &mut db, &allocations, args)?; - let confirmations = update_finalized_transactions(client, &mut db)?; - Ok(confirmations) + finalize_transactions(client, &mut db, args.dry_run, args.no_wait) +} + +fn finalize_transactions( + client: &ThinClient, + db: &mut PickleDb, + dry_run: bool, + no_wait: bool, +) -> Result, Error> { + let (mut opt_confirmations, mut unconfirmed_transactions) = + update_finalized_transactions(client, db)?; + + if no_wait { + return Ok(opt_confirmations); + } + + let progress_bar = new_spinner_progress_bar(); + + while opt_confirmations.is_some() || !unconfirmed_transactions.is_empty() { + let confirmations = opt_confirmations.unwrap(); + progress_bar.set_message(&format!( + "[{}/{}] Finalizing transactions", + confirmations, 32, + )); + + if !dry_run { + for transaction in unconfirmed_transactions { + client.async_send_transaction(transaction)?; + } + } + + // Sleep for about 1 slot + sleep(Duration::from_millis(500)); + let (opt_conf, unconfirmed) = update_finalized_transactions(client, db)?; + opt_confirmations = opt_conf; + unconfirmed_transactions = unconfirmed; + } + + Ok(opt_confirmations) } // Set the finalized bit in the database if the transaction is rooted. @@ -418,16 +455,19 @@ fn update_finalized_transaction( db: &mut PickleDb, signature: &Signature, opt_transaction_status: Option, -) -> Result, pickledb::error::Error> { + blockhash: &Hash, + recent_blockhashes: &[Hash], +) -> Result, Error> { if opt_transaction_status.is_none() { - eprintln!( - "Signature not found {}. If its blockhash is expired, remove it from the database", - signature - ); + if !recent_blockhashes.contains(blockhash) { + eprintln!("Signature not found {} and blockhash expired", signature); + println!("Discarding transaction record"); + db.rem(&signature.to_string())?; + return Ok(None); + } - // Return true because the transaction might still be in flight and get accepted onto - // the ledger. - return Ok(Some(0)); + // Return an error to signal the option resend the transaction. + return Err(Error::SignatureNotFound); } let transaction_status = opt_transaction_status.unwrap(); @@ -457,32 +497,54 @@ fn update_finalized_transaction( // Update the finalized bit on any transactions that are now rooted // Return the lowest number of confirmations on the unfinalized transactions or None if all are finalized. +// Also return the unconfirmed transactions with valid blockhashes. fn update_finalized_transactions( client: &ThinClient, db: &mut PickleDb, -) -> Result, Error> { - let transaction_data = read_transaction_data(db); - let unconfirmed_signatures: Vec<_> = transaction_data +) -> Result<(Option, Vec), Error> { + let transaction_infos = read_transaction_infos(db); + let unconfirmed_transactions: Vec<_> = transaction_infos .iter() - .filter_map(|(signature, info)| { + .filter_map(|info| { if info.finalized { None } else { - Some(*signature) + Some(&info.transaction) } }) .collect(); + let unconfirmed_signatures = unconfirmed_transactions + .iter() + .map(|tx| tx.signatures[0]) + .collect_vec(); let transaction_statuses = client.get_signature_statuses(&unconfirmed_signatures)?; + let recent_blockhashes = client.get_recent_blockhashes()?; + let mut confirmations = None; - for (signature, opt_transaction_status) in unconfirmed_signatures + let mut mia_transactions = vec![]; + for (transaction, opt_transaction_status) in unconfirmed_transactions .into_iter() .zip(transaction_statuses.into_iter()) { - if let Some(confs) = update_finalized_transaction(db, &signature, opt_transaction_status)? { - confirmations = Some(cmp::min(confs, confirmations.unwrap_or(usize::MAX))); + match update_finalized_transaction( + db, + &transaction.signatures[0], + opt_transaction_status, + &transaction.message.recent_blockhash, + &recent_blockhashes, + ) { + Ok(Some(confs)) => { + confirmations = Some(cmp::min(confs, confirmations.unwrap_or(usize::MAX))); + } + Err(Error::SignatureNotFound) => { + mia_transactions.push(transaction.clone()); + } + result => { + result?; + } } } - Ok(confirmations) + Ok((confirmations, mia_transactions)) } pub fn process_balances( @@ -569,7 +631,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); - assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); assert_eq!( sol_to_lamports(transaction_infos[0].amount), @@ -585,7 +647,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); - assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); assert_eq!( sol_to_lamports(transaction_infos[0].amount), @@ -668,7 +730,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); - assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); assert_eq!( sol_to_lamports(transaction_infos[0].amount), @@ -679,10 +741,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke thin_client.get_balance(&alice_pubkey).unwrap(), sol_to_lamports(1.0), ); - let new_stake_account_address = transaction_infos[0] - .new_stake_account_address - .parse() - .unwrap(); + let new_stake_account_address = transaction_infos[0].new_stake_account_address.unwrap(); assert_eq!( thin_client.get_balance(&new_stake_account_address).unwrap(), expected_amount - sol_to_lamports(1.0), @@ -692,7 +751,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke process_distribute_tokens(&thin_client, &args).unwrap(); let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); - assert_eq!(transaction_infos[0].recipient, alice_pubkey.to_string()); + assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); assert_eq!( sol_to_lamports(transaction_infos[0].amount), @@ -772,28 +831,31 @@ mod tests { #[test] fn test_apply_previous_transactions() { + let alice = Pubkey::new_rand(); + let bob = Pubkey::new_rand(); let mut allocations = vec![ Allocation { - recipient: "a".to_string(), + recipient: alice.to_string(), amount: 1.0, }, Allocation { - recipient: "b".to_string(), + recipient: bob.to_string(), amount: 1.0, }, ]; let transaction_infos = vec![TransactionInfo { - recipient: "b".to_string(), + recipient: bob, amount: 1.0, - new_stake_account_address: "".to_string(), + new_stake_account_address: None, finalized: true, + transaction: Transaction::new_unsigned_instructions(vec![]), }]; apply_previous_transactions(&mut allocations, &transaction_infos); assert_eq!(allocations.len(), 1); // Ensure that we applied the transaction to the allocation with - // a matching recipient address (to "b", not "a"). - assert_eq!(allocations[0].recipient, "a"); + // a matching recipient address (to bob, not alice). + assert_eq!(allocations[0].recipient, alice.to_string()); } #[test] @@ -802,18 +864,29 @@ mod tests { let mut db = PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); let signature = Signature::default(); + let blockhash = Hash::default(); let transaction_info = TransactionInfo::default(); db.set(&signature.to_string(), &transaction_info).unwrap(); - assert_eq!( - update_finalized_transaction(&mut db, &signature, None).unwrap(), - Some(0) - ); + assert!(matches!( + update_finalized_transaction(&mut db, &signature, None, &blockhash, &[blockhash]) + .unwrap_err(), + Error::SignatureNotFound + )); // Unchanged assert_eq!( db.get::(&signature.to_string()).unwrap(), transaction_info ); + + // Same as before, but now with an expired blockhash + assert_eq!( + update_finalized_transaction(&mut db, &signature, None, &blockhash, &[]).unwrap(), + None + ); + + // Ensure TransactionInfo has been purged. + assert_eq!(db.get::(&signature.to_string()), None); } #[test] @@ -822,6 +895,7 @@ mod tests { let mut db = PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); let signature = Signature::default(); + let blockhash = Hash::default(); let transaction_info = TransactionInfo::default(); db.set(&signature.to_string(), &transaction_info).unwrap(); let transaction_status = TransactionStatus { @@ -831,7 +905,14 @@ mod tests { err: None, }; assert_eq!( - update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), + update_finalized_transaction( + &mut db, + &signature, + Some(transaction_status), + &blockhash, + &[blockhash] + ) + .unwrap(), Some(1) ); @@ -848,6 +929,7 @@ mod tests { let mut db = PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); let signature = Signature::default(); + let blockhash = Hash::default(); let transaction_info = TransactionInfo::default(); db.set(&signature.to_string(), &transaction_info).unwrap(); let status = Err(TransactionError::AccountNotFound); @@ -858,7 +940,14 @@ mod tests { err: None, }; assert_eq!( - update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), + update_finalized_transaction( + &mut db, + &signature, + Some(transaction_status), + &blockhash, + &[blockhash] + ) + .unwrap(), None ); @@ -872,6 +961,7 @@ mod tests { let mut db = PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); let signature = Signature::default(); + let blockhash = Hash::default(); let mut transaction_info = TransactionInfo::default(); db.set(&signature.to_string(), &transaction_info).unwrap(); let transaction_status = TransactionStatus { @@ -881,7 +971,14 @@ mod tests { err: None, }; assert_eq!( - update_finalized_transaction(&mut db, &signature, Some(transaction_status)).unwrap(), + update_finalized_transaction( + &mut db, + &signature, + Some(transaction_status), + &blockhash, + &[blockhash] + ) + .unwrap(), None ); @@ -908,6 +1005,7 @@ mod tests { rdr.deserialize().map(|entry| entry.unwrap()).collect(); let signed_info = SignedTransactionInfo { + recipient: Pubkey::default().to_string(), signature: Signature::default().to_string(), ..SignedTransactionInfo::default() }; diff --git a/tests/tokens.rs b/tests/tokens.rs index 8ca40725556851..b23c38cc3567b6 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -5,7 +5,6 @@ use solana_tokens::tokens::test_process_distribute_tokens_with_client; use std::fs::remove_dir_all; #[test] -#[ignore] fn test_process_distribute_with_rpc_client() { let validator = TestValidator::run_with_options(TestValidatorOptions { mint_lamports: sol_to_lamports(9_000_000.0), From 5f9d678690e03c80a66124bee8e24817daaeda7a Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 8 May 2020 10:26:45 -0600 Subject: [PATCH 60/71] Move log to stderr --- src/tokens.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens.rs b/src/tokens.rs index 89987b1cd62ba3..6f29d151663cd3 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -461,7 +461,7 @@ fn update_finalized_transaction( if opt_transaction_status.is_none() { if !recent_blockhashes.contains(blockhash) { eprintln!("Signature not found {} and blockhash expired", signature); - println!("Discarding transaction record"); + eprintln!("Discarding transaction record"); db.rem(&signature.to_string())?; return Ok(None); } From d3a9058fecc425ebef980ba9e5ccd953d96fb4b3 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 8 May 2020 15:43:30 -0600 Subject: [PATCH 61/71] Add constructor, tuck away client (#30) * Add constructor, tuck away client * Fix unwrap() caught by CI --- src/main.rs | 2 +- src/thin_client.rs | 6 +++++- src/tokens.rs | 15 ++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 79f7c25add4ccf..e495107c4eb01b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ fn main() -> Result<(), Box> { let config = Config::load(&command_args.config_file)?; let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); let client = RpcClient::new(json_rpc_url); - let thin_client = ThinClient(client); + let thin_client = ThinClient::new(client); match resolve_command(command_args.command)? { Command::DistributeTokens(args) => { diff --git a/src/thin_client.rs b/src/thin_client.rs index 8b9a28a495f02b..291801c7ca9fd0 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -115,9 +115,13 @@ impl Client for BankClient { } } -pub struct ThinClient(pub C); +pub struct ThinClient(C); impl ThinClient { + pub fn new(client: C) -> Self { + Self(client) + } + pub fn async_send_transaction(&self, transaction: Transaction) -> Result { self.0.async_send_transaction1(transaction) } diff --git a/src/tokens.rs b/src/tokens.rs index 6f29d151663cd3..e20459f1e860c7 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -426,11 +426,12 @@ fn finalize_transactions( let progress_bar = new_spinner_progress_bar(); while opt_confirmations.is_some() || !unconfirmed_transactions.is_empty() { - let confirmations = opt_confirmations.unwrap(); - progress_bar.set_message(&format!( - "[{}/{}] Finalizing transactions", - confirmations, 32, - )); + if let Some(confirmations) = opt_confirmations { + progress_bar.set_message(&format!( + "[{}/{}] Finalizing transactions", + confirmations, 32, + )); + } if !dry_run { for transaction in unconfirmed_transactions { @@ -589,7 +590,7 @@ pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> { use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; pub fn test_process_distribute_tokens_with_client(client: C, sender_keypair: Keypair) { - let thin_client = ThinClient(client); + let thin_client = ThinClient::new(client); let fee_payer = Keypair::new(); thin_client .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) @@ -661,7 +662,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k } pub fn test_process_distribute_stake_with_client(client: C, sender_keypair: Keypair) { - let thin_client = ThinClient(client); + let thin_client = ThinClient::new(client); let fee_payer = Keypair::new(); thin_client .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) From 256c4095da1606ccc9e87c509a93cf8f5a91c1fd Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sun, 10 May 2020 11:38:17 -0600 Subject: [PATCH 62/71] Fix optional option flagged as required --- src/arg_parser.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 34541c87e74357..d74d55f6354f93 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -59,7 +59,6 @@ where .arg( Arg::with_name("dollars_per_sol") .long("dollars-per-sol") - .required(true) .takes_value(true) .value_name("NUMBER") .help("Dollars per SOL, if input CSV contains bids"), From 041565d1c638d1c78cebc2fe16380892a9a23ede Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 11 May 2020 18:06:13 -0600 Subject: [PATCH 63/71] Bunch of cleanup (#31) * Remove untested --no-wait feature * Make --transactions-db an option, not an arg So that in the future, we can make it optional * Remove more untested features Too many false positives in that santity check. Use --dry-run instead. * Add dry-run mode to ThinClient * Cleaner dry-run * Make key parameters required Just don't use them in --dry-run * Add option to write the transaction log --dry-run doesn't write to the database. Use this option if you want a copy of the transaction log before the final run. * Revert --transaction-log addition Implement #27 first * Fix CI * Update readme * Fix CI in copypasta --- README.md | 10 +- src/arg_parser.rs | 59 ++++------ src/args.rs | 58 ++++++---- src/main.rs | 3 +- src/thin_client.rs | 69 ++++++------ src/tokens.rs | 262 +++++++++++++++++++-------------------------- 6 files changed, 205 insertions(+), 256 deletions(-) diff --git a/README.md b/README.md index 1450edeaef8e2a..1dd3af9a0ced75 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ primary_address,bid_amount_dollars ``` ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --input-csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --from-bids --input-csv --transaction-db --fee-payer ``` Example transaction log before: @@ -31,7 +31,7 @@ Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --input-csv --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --from-bids --input-csv --transaction-db --fee-payer ``` Example output: @@ -60,7 +60,7 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute-tokens --dollars-per-sol --dry-run --input-csv +solana-tokens distribute-tokens --dollars-per-sol --dry-run --from-bids --input-csv --transaction-db ``` Example bids.csv: @@ -90,8 +90,8 @@ the new accounts inherit any lockup or custodian settings of the original. ```bash solana-tokens distribute-stake --stake-account-address \ - --allocations-csv \ - \ + --input-csv \ + --transaction-db \ --stake-authority --withdraw-authority --fee-payer ``` diff --git a/src/arg_parser.rs b/src/arg_parser.rs index d74d55f6354f93..3ecaff543cab7c 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -36,12 +36,12 @@ where SubCommand::with_name("distribute-tokens") .about("Distribute tokens") .arg( - Arg::with_name("transactions_db") + Arg::with_name("transaction_db") + .long("transaction-db") .required(true) - .index(1) .takes_value(true) .value_name("FILE") - .help("Transactions database file"), + .help("Transaction database file"), ) .arg( Arg::with_name("from_bids") @@ -68,14 +68,10 @@ where .long("dry-run") .help("Do not execute any transfers"), ) - .arg( - Arg::with_name("no_wait") - .long("no-wait") - .help("Don't wait for transaction confirmations"), - ) .arg( Arg::with_name("sender_keypair") .long("from") + .required(true) .takes_value(true) .value_name("SENDING_KEYPAIR") .validator(is_valid_signer) @@ -84,27 +80,23 @@ where .arg( Arg::with_name("fee_payer") .long("fee-payer") + .required(true) .takes_value(true) .value_name("KEYPAIR") .validator(is_valid_signer) .help("Fee payer"), - ) - .arg( - Arg::with_name("force") - .long("force") - .help("Do not block transfers is recipients have a non-zero balance"), ), ) .subcommand( SubCommand::with_name("distribute-stake") .about("Distribute stake accounts") .arg( - Arg::with_name("transactions_db") + Arg::with_name("transaction_db") + .long("transaction-db") .required(true) - .index(1) .takes_value(true) .value_name("FILE") - .help("Transactions database file"), + .help("Transaction database file"), ) .arg( Arg::with_name("input_csv") @@ -119,14 +111,10 @@ where .long("dry-run") .help("Do not execute any transfers"), ) - .arg( - Arg::with_name("no_wait") - .long("no-wait") - .help("Don't wait for transaction confirmations"), - ) .arg( Arg::with_name("sender_keypair") .long("from") + .required(true) .takes_value(true) .value_name("SENDING_KEYPAIR") .validator(is_valid_signer) @@ -152,6 +140,7 @@ where .arg( Arg::with_name("stake_authority") .long("stake-authority") + .required(true) .takes_value(true) .value_name("KEYPAIR") .validator(is_valid_signer) @@ -160,6 +149,7 @@ where .arg( Arg::with_name("withdraw_authority") .long("withdraw-authority") + .required(true) .takes_value(true) .value_name("KEYPAIR") .validator(is_valid_signer) @@ -168,6 +158,7 @@ where .arg( Arg::with_name("fee_payer") .long("fee-payer") + .required(true) .takes_value(true) .value_name("KEYPAIR") .validator(is_valid_signer) @@ -202,9 +193,9 @@ where SubCommand::with_name("transaction-log") .about("Print the database to a CSV file") .arg( - Arg::with_name("transactions_db") + Arg::with_name("transaction_db") + .long("transaction-db") .required(true) - .index(1) .takes_value(true) .value_name("FILE") .help("Transactions database file"), @@ -225,13 +216,11 @@ fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArg DistributeTokensArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), from_bids: matches.is_present("from_bids"), - transactions_db: value_t_or_exit!(matches, "transactions_db", String), + transaction_db: value_t_or_exit!(matches, "transaction_db", String), dollars_per_sol: value_t!(matches, "dollars_per_sol", f64).ok(), dry_run: matches.is_present("dry_run"), - no_wait: matches.is_present("no_wait"), - sender_keypair: value_t!(matches, "sender_keypair", String).ok(), - fee_payer: value_t!(matches, "fee_payer", String).ok(), - force: matches.is_present("force"), + sender_keypair: value_t_or_exit!(matches, "sender_keypair", String), + fee_payer: value_t_or_exit!(matches, "fee_payer", String), stake_args: None, } } @@ -240,19 +229,17 @@ fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs let stake_args = StakeArgs { stake_account_address: value_t_or_exit!(matches, "stake_account_address", String), sol_for_fees: value_t_or_exit!(matches, "sol_for_fees", f64), - stake_authority: value_t!(matches, "stake_authority", String).ok(), - withdraw_authority: value_t!(matches, "withdraw_authority", String).ok(), + stake_authority: value_t_or_exit!(matches, "stake_authority", String), + withdraw_authority: value_t_or_exit!(matches, "withdraw_authority", String), }; DistributeTokensArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), from_bids: false, - transactions_db: value_t_or_exit!(matches, "transactions_db", String), + transaction_db: value_t_or_exit!(matches, "transaction_db", String), dollars_per_sol: None, dry_run: matches.is_present("dry_run"), - no_wait: matches.is_present("no_wait"), - sender_keypair: value_t!(matches, "sender_keypair", String).ok(), - fee_payer: value_t!(matches, "fee_payer", String).ok(), - force: false, + sender_keypair: value_t_or_exit!(matches, "sender_keypair", String), + fee_payer: value_t_or_exit!(matches, "fee_payer", String), stake_args: Some(stake_args), } } @@ -267,7 +254,7 @@ fn parse_balances_args(matches: &ArgMatches<'_>) -> BalancesArgs { fn parse_transaction_log_args(matches: &ArgMatches<'_>) -> TransactionLogArgs { TransactionLogArgs { - transactions_db: value_t_or_exit!(matches, "transactions_db", String), + transaction_db: value_t_or_exit!(matches, "transaction_db", String), output_path: value_t_or_exit!(matches, "output_path", String), } } diff --git a/src/args.rs b/src/args.rs index a771c57031f331..0eed6946388d8e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -7,21 +7,19 @@ use std::{error::Error, sync::Arc}; pub struct DistributeTokensArgs { pub input_csv: String, pub from_bids: bool, - pub transactions_db: String, + pub transaction_db: String, pub dollars_per_sol: Option, pub dry_run: bool, - pub no_wait: bool, - pub sender_keypair: Option, - pub fee_payer: Option, - pub force: bool, + pub sender_keypair: K, + pub fee_payer: K, pub stake_args: Option>, } pub struct StakeArgs { pub sol_for_fees: f64, pub stake_account_address: P, - pub stake_authority: Option, - pub withdraw_authority: Option, + pub stake_authority: K, + pub withdraw_authority: K, } pub struct BalancesArgs { @@ -31,7 +29,7 @@ pub struct BalancesArgs { } pub struct TransactionLogArgs { - pub transactions_db: String, + pub transaction_db: String, pub output_path: String, } @@ -61,12 +59,20 @@ pub fn resolve_stake_args( ) .unwrap(), sol_for_fees: args.sol_for_fees, - stake_authority: args.stake_authority.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "stake authority", wallet_manager).unwrap() - }), - withdraw_authority: args.withdraw_authority.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "withdraw authority", wallet_manager).unwrap() - }), + stake_authority: signer_from_path( + &matches, + &args.stake_authority, + "stake authority", + wallet_manager, + ) + .unwrap(), + withdraw_authority: signer_from_path( + &matches, + &args.withdraw_authority, + "withdraw authority", + wallet_manager, + ) + .unwrap(), }; Ok(resolved_args) } @@ -84,17 +90,23 @@ pub fn resolve_command( let resolved_args = DistributeTokensArgs { input_csv: args.input_csv, from_bids: args.from_bids, - transactions_db: args.transactions_db, + transaction_db: args.transaction_db, dollars_per_sol: args.dollars_per_sol, dry_run: args.dry_run, - no_wait: args.no_wait, - sender_keypair: args.sender_keypair.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "sender", &mut wallet_manager).unwrap() - }), - fee_payer: args.fee_payer.as_ref().map(|key_url| { - signer_from_path(&matches, &key_url, "fee-payer", &mut wallet_manager).unwrap() - }), - force: args.force, + sender_keypair: signer_from_path( + &matches, + &args.sender_keypair, + "sender", + &mut wallet_manager, + ) + .unwrap(), + fee_payer: signer_from_path( + &matches, + &args.fee_payer, + "fee-payer", + &mut wallet_manager, + ) + .unwrap(), stake_args: resolved_stake_args.map_or(Ok(None), |r| r.map(Some))?, }; Ok(Command::DistributeTokens(resolved_args)) diff --git a/src/main.rs b/src/main.rs index e495107c4eb01b..a2e9b63663a67c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,13 +14,14 @@ fn main() -> Result<(), Box> { let config = Config::load(&command_args.config_file)?; let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); let client = RpcClient::new(json_rpc_url); - let thin_client = ThinClient::new(client); match resolve_command(command_args.command)? { Command::DistributeTokens(args) => { + let thin_client = ThinClient::new(client, args.dry_run); tokens::process_distribute_tokens(&thin_client, &args)?; } Command::Balances(args) => { + let thin_client = ThinClient::new(client, false); tokens::process_balances(&thin_client, &args)?; } Command::TransactionLog(args) => { diff --git a/src/thin_client.rs b/src/thin_client.rs index 291801c7ca9fd0..5b11889f7016ed 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -20,11 +20,7 @@ use solana_sdk::{ use solana_transaction_status::TransactionStatus; pub trait Client { - fn async_send_transaction1(&self, transaction: Transaction) -> Result; - - // TODO: Work to delete this - fn send_and_confirm_transaction1(&self, transaction: Transaction) -> Result; - + fn send_transaction1(&self, transaction: Transaction) -> Result; fn get_signature_statuses1( &self, signatures: &[Signature], @@ -35,17 +31,11 @@ pub trait Client { } impl Client for RpcClient { - fn async_send_transaction1(&self, transaction: Transaction) -> Result { + fn send_transaction1(&self, transaction: Transaction) -> Result { self.send_transaction(&transaction) .map_err(|e| TransportError::Custom(e.to_string())) } - fn send_and_confirm_transaction1(&self, mut transaction: Transaction) -> Result { - let signers: Vec<&dyn Signer> = vec![]; // Don't allow resigning - self.send_and_confirm_transaction_with_spinner(&mut transaction, &signers) - .map_err(|e| TransportError::Custom(e.to_string())) - } - fn get_signature_statuses1( &self, signatures: &[Signature], @@ -73,16 +63,10 @@ impl Client for RpcClient { } impl Client for BankClient { - fn async_send_transaction1(&self, transaction: Transaction) -> Result { + fn send_transaction1(&self, transaction: Transaction) -> Result { self.async_send_transaction(transaction) } - fn send_and_confirm_transaction1(&self, transaction: Transaction) -> Result { - let signature = self.async_send_transaction1(transaction)?; - self.poll_for_signature(&signature)?; - Ok(signature) - } - fn get_signature_statuses1( &self, signatures: &[Signature], @@ -115,34 +99,45 @@ impl Client for BankClient { } } -pub struct ThinClient(C); +pub struct ThinClient { + client: C, + dry_run: bool, +} impl ThinClient { - pub fn new(client: C) -> Self { - Self(client) + pub fn new(client: C, dry_run: bool) -> Self { + Self { client, dry_run } + } + + pub fn send_transaction(&self, transaction: Transaction) -> Result { + if self.dry_run { + return Ok(Signature::default()); + } + self.client.send_transaction1(transaction) } - pub fn async_send_transaction(&self, transaction: Transaction) -> Result { - self.0.async_send_transaction1(transaction) + pub fn poll_for_confirmation(&self, signature: &Signature) -> Result<()> { + while self.get_signature_statuses(&[*signature])?[0].is_none() { + std::thread::sleep(std::time::Duration::from_millis(500)); + } + Ok(()) } pub fn get_signature_statuses( &self, signatures: &[Signature], ) -> Result>> { - self.0.get_signature_statuses1(signatures) - } - - pub fn send_transaction(&self, transaction: Transaction) -> Result { - // TODO: implement this in terms of ThinClient methods and then remove - // send_and_confirm_transaction1 from from the Client trait. - self.0.send_and_confirm_transaction1(transaction) + self.client.get_signature_statuses1(signatures) } - pub fn send_message(&self, message: Message, signers: &S) -> Result { + pub fn send_message(&self, message: Message, signers: &S) -> Result { + if self.dry_run { + return Ok(Transaction::new_unsigned(message)); + } let (blockhash, _fee_caluclator) = self.get_recent_blockhash()?; let transaction = Transaction::new(signers, message, blockhash); - self.send_transaction(transaction) + self.send_transaction(transaction.clone())?; + Ok(transaction) } pub fn transfer( @@ -150,7 +145,7 @@ impl ThinClient { lamports: u64, sender_keypair: &S, to_pubkey: &Pubkey, - ) -> Result { + ) -> Result { let create_instruction = system_instruction::transfer(&sender_keypair.pubkey(), &to_pubkey, lamports); let message = Message::new(&[create_instruction]); @@ -158,15 +153,15 @@ impl ThinClient { } pub fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> { - self.0.get_recent_blockhash1() + self.client.get_recent_blockhash1() } pub fn get_balance(&self, pubkey: &Pubkey) -> Result { - self.0.get_balance1(pubkey) + self.client.get_balance1(pubkey) } pub fn get_account(&self, pubkey: &Pubkey) -> Result> { - self.0.get_account1(pubkey) + self.client.get_account1(pubkey) } pub fn get_recent_blockhashes(&self) -> Result> { diff --git a/src/tokens.rs b/src/tokens.rs index e20459f1e860c7..4d5242a2251672 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -21,7 +21,7 @@ use solana_stake_program::{ stake_state::{Authorized, Lockup, StakeAuthorize}, }; use solana_transaction_status::TransactionStatus; -use std::{cmp, io, path::Path, process, thread::sleep, time::Duration}; +use std::{cmp, io, path::Path, thread::sleep, time::Duration}; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -137,88 +137,78 @@ fn distribute_tokens( for allocation in allocations { let new_stake_account_keypair = Keypair::new(); let new_stake_account_address = new_stake_account_keypair.pubkey(); - let signers = if args.dry_run { - vec![] - } else { - let mut signers = vec![ - &**args.fee_payer.as_ref().unwrap(), - &**args.sender_keypair.as_ref().unwrap(), - ]; - if let Some(stake_args) = &args.stake_args { - signers.push(&**stake_args.stake_authority.as_ref().unwrap()); - signers.push(&**stake_args.withdraw_authority.as_ref().unwrap()); - signers.push(&new_stake_account_keypair); - } - unique_signers(signers) - }; + + let mut signers = vec![&*args.fee_payer, &*args.sender_keypair]; + if let Some(stake_args) = &args.stake_args { + signers.push(&*stake_args.stake_authority); + signers.push(&*stake_args.withdraw_authority); + signers.push(&new_stake_account_keypair); + } + let signers = unique_signers(signers); println!("{:<44} {:>24.9}", allocation.recipient, allocation.amount); - let result = if args.dry_run { - Ok(Signature::default()) + let instructions = if let Some(stake_args) = &args.stake_args { + let sol_for_fees = stake_args.sol_for_fees; + let sender_pubkey = args.sender_keypair.pubkey(); + let stake_authority = stake_args.stake_authority.pubkey(); + let withdraw_authority = stake_args.withdraw_authority.pubkey(); + + let mut instructions = stake_instruction::split( + &stake_args.stake_account_address, + &stake_authority, + sol_to_lamports(allocation.amount - sol_for_fees), + &new_stake_account_address, + ); + + let recipient = allocation.recipient.parse().unwrap(); + + // Make the recipient the new stake authority + instructions.push(stake_instruction::authorize( + &new_stake_account_address, + &stake_authority, + &recipient, + StakeAuthorize::Staker, + )); + + // Make the recipient the new withdraw authority + instructions.push(stake_instruction::authorize( + &new_stake_account_address, + &withdraw_authority, + &recipient, + StakeAuthorize::Withdrawer, + )); + + instructions.push(system_instruction::transfer( + &sender_pubkey, + &recipient, + sol_to_lamports(sol_for_fees), + )); + + instructions } else { - let instructions = if let Some(stake_args) = &args.stake_args { - let sol_for_fees = stake_args.sol_for_fees; - let sender_pubkey = args.sender_keypair.as_ref().unwrap().pubkey(); - let stake_authority = stake_args.stake_authority.as_ref().unwrap().pubkey(); - let withdraw_authority = stake_args.withdraw_authority.as_ref().unwrap().pubkey(); - - let mut instructions = stake_instruction::split( - &stake_args.stake_account_address, - &stake_authority, - sol_to_lamports(allocation.amount - sol_for_fees), - &new_stake_account_address, - ); - - let recipient = allocation.recipient.parse().unwrap(); - - // Make the recipient the new stake authority - instructions.push(stake_instruction::authorize( - &new_stake_account_address, - &stake_authority, - &recipient, - StakeAuthorize::Staker, - )); - - // Make the recipient the new withdraw authority - instructions.push(stake_instruction::authorize( - &new_stake_account_address, - &withdraw_authority, - &recipient, - StakeAuthorize::Withdrawer, - )); - - instructions.push(system_instruction::transfer( - &sender_pubkey, - &recipient, - sol_to_lamports(sol_for_fees), - )); - - instructions - } else { - let from = args.sender_keypair.as_ref().unwrap().pubkey(); - let to = allocation.recipient.parse().unwrap(); - let lamports = sol_to_lamports(allocation.amount); - let instruction = system_instruction::transfer(&from, &to, lamports); - vec![instruction] - }; - - let fee_payer_pubkey = args.fee_payer.as_ref().unwrap().pubkey(); - let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); - let (blockhash, _fee_caluclator) = client.get_recent_blockhash()?; - let transaction = Transaction::new(&signers, message, blockhash); - set_transaction_info( - db, - &allocation, - &transaction, - Some(&new_stake_account_address), - false, - )?; - - client.async_send_transaction(transaction) + let from = args.sender_keypair.pubkey(); + let to = allocation.recipient.parse().unwrap(); + let lamports = sol_to_lamports(allocation.amount); + let instruction = system_instruction::transfer(&from, &to, lamports); + vec![instruction] + }; + + let fee_payer_pubkey = args.fee_payer.pubkey(); + let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); + match client.send_message(message, &signers) { + Ok(transaction) => { + set_transaction_info( + db, + &allocation, + &transaction, + Some(&new_stake_account_address), + false, + )?; + } + Err(e) => { + eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); + } }; - if let Err(e) = result { - eprintln!("Error sending tokens to {}: {}", allocation.recipient, e); - } } Ok(()) } @@ -327,10 +317,10 @@ pub fn process_distribute_tokens( ); } - let mut db = open_db(&args.transactions_db, args.dry_run)?; + let mut db = open_db(&args.transaction_db, args.dry_run)?; // Start by finalizing any transactions from the previous run. - let confirmations = finalize_transactions(client, &mut db, args.dry_run, args.no_wait)?; + let confirmations = finalize_transactions(client, &mut db)?; let transaction_infos = read_transaction_infos(&db); apply_previous_transactions(&mut allocations, &transaction_infos); @@ -340,27 +330,6 @@ pub fn process_distribute_tokens( return Ok(confirmations); } - // Sanity check: the recipient should not have tokens yet. If they do, it - // is probably because: - // 1. The signature couldn't be found in a previous run, though the transaction was - // successful. If so, manually add a row to the transaction log. - // 2. The recipient already has tokens. If so, update this code to include a `--force` flag. - // 3. The recipient correctly got tokens in a previous run, and then later registered the same - // address for another bid. If so, update this code to check for that case. - for allocation in &allocations { - let address = allocation.recipient.parse().unwrap(); - let balance = client.get_balance(&address).unwrap(); - if args.stake_args.is_none() && !args.force && balance != 0 { - eprintln!( - "Error: Non-zero balance {}, refusing to send {} to {}", - lamports_to_sol(balance), - allocation.amount, - allocation.recipient, - ); - process::exit(1); - } - } - println!( "{}", style(format!( @@ -407,25 +376,19 @@ pub fn process_distribute_tokens( distribute_tokens(client, &mut db, &allocations, args)?; - finalize_transactions(client, &mut db, args.dry_run, args.no_wait) + let opt_confirmations = finalize_transactions(client, &mut db)?; + Ok(opt_confirmations) } fn finalize_transactions( client: &ThinClient, db: &mut PickleDb, - dry_run: bool, - no_wait: bool, ) -> Result, Error> { - let (mut opt_confirmations, mut unconfirmed_transactions) = - update_finalized_transactions(client, db)?; - - if no_wait { - return Ok(opt_confirmations); - } + let mut opt_confirmations = update_finalized_transactions(client, db)?; let progress_bar = new_spinner_progress_bar(); - while opt_confirmations.is_some() || !unconfirmed_transactions.is_empty() { + while opt_confirmations.is_some() { if let Some(confirmations) = opt_confirmations { progress_bar.set_message(&format!( "[{}/{}] Finalizing transactions", @@ -433,17 +396,10 @@ fn finalize_transactions( )); } - if !dry_run { - for transaction in unconfirmed_transactions { - client.async_send_transaction(transaction)?; - } - } - // Sleep for about 1 slot sleep(Duration::from_millis(500)); - let (opt_conf, unconfirmed) = update_finalized_transactions(client, db)?; + let opt_conf = update_finalized_transactions(client, db)?; opt_confirmations = opt_conf; - unconfirmed_transactions = unconfirmed; } Ok(opt_confirmations) @@ -467,8 +423,8 @@ fn update_finalized_transaction( return Ok(None); } - // Return an error to signal the option resend the transaction. - return Err(Error::SignatureNotFound); + // Return zero to signal the transaction may still be in flight. + return Ok(Some(0)); } let transaction_status = opt_transaction_status.unwrap(); @@ -498,11 +454,10 @@ fn update_finalized_transaction( // Update the finalized bit on any transactions that are now rooted // Return the lowest number of confirmations on the unfinalized transactions or None if all are finalized. -// Also return the unconfirmed transactions with valid blockhashes. fn update_finalized_transactions( client: &ThinClient, db: &mut PickleDb, -) -> Result<(Option, Vec), Error> { +) -> Result, Error> { let transaction_infos = read_transaction_infos(db); let unconfirmed_transactions: Vec<_> = transaction_infos .iter() @@ -517,12 +472,12 @@ fn update_finalized_transactions( let unconfirmed_signatures = unconfirmed_transactions .iter() .map(|tx| tx.signatures[0]) + .filter(|sig| *sig != Signature::default()) // Filter out dry-run signatures .collect_vec(); let transaction_statuses = client.get_signature_statuses(&unconfirmed_signatures)?; let recent_blockhashes = client.get_recent_blockhashes()?; let mut confirmations = None; - let mut mia_transactions = vec![]; for (transaction, opt_transaction_status) in unconfirmed_transactions .into_iter() .zip(transaction_statuses.into_iter()) @@ -537,15 +492,12 @@ fn update_finalized_transactions( Ok(Some(confs)) => { confirmations = Some(cmp::min(confs, confirmations.unwrap_or(usize::MAX))); } - Err(Error::SignatureNotFound) => { - mia_transactions.push(transaction.clone()); - } result => { result?; } } } - Ok((confirmations, mia_transactions)) + Ok(confirmations) } pub fn process_balances( @@ -582,7 +534,7 @@ pub fn process_balances( } pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> { - let db = open_db(&args.transactions_db, true)?; + let db = open_db(&args.transaction_db, true)?; write_transaction_log(&db, &args.output_path)?; Ok(()) } @@ -590,11 +542,14 @@ pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> { use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use tempfile::{tempdir, NamedTempFile}; pub fn test_process_distribute_tokens_with_client(client: C, sender_keypair: Keypair) { - let thin_client = ThinClient::new(client); + let thin_client = ThinClient::new(client, false); let fee_payer = Keypair::new(); - thin_client + let transaction = thin_client .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) .unwrap(); + thin_client + .poll_for_confirmation(&transaction.signatures[0]) + .unwrap(); let alice_pubkey = Pubkey::new_rand(); let allocation = Allocation { @@ -608,7 +563,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k wtr.flush().unwrap(); let dir = tempdir().unwrap(); - let transactions_db = dir + let transaction_db = dir .path() .join("transactions.db") .to_str() @@ -616,21 +571,19 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k .to_string(); let args: DistributeTokensArgs> = DistributeTokensArgs { - sender_keypair: Some(Box::new(sender_keypair)), - fee_payer: Some(Box::new(fee_payer)), + sender_keypair: Box::new(sender_keypair), + fee_payer: Box::new(fee_payer), dry_run: false, - no_wait: false, input_csv, from_bids: false, - transactions_db: transactions_db.clone(), + transaction_db: transaction_db.clone(), dollars_per_sol: None, - force: false, stake_args: None, }; let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); assert_eq!(confirmations, None); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -646,7 +599,7 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -662,11 +615,14 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k } pub fn test_process_distribute_stake_with_client(client: C, sender_keypair: Keypair) { - let thin_client = ThinClient::new(client); + let thin_client = ThinClient::new(client, false); let fee_payer = Keypair::new(); - thin_client + let transaction = thin_client .transfer(sol_to_lamports(1.0), &sender_keypair, &fee_payer.pubkey()) .unwrap(); + thin_client + .poll_for_confirmation(&transaction.signatures[0]) + .unwrap(); let stake_account_keypair = Keypair::new(); let stake_account_address = stake_account_keypair.pubkey(); @@ -701,7 +657,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke wtr.flush().unwrap(); let dir = tempdir().unwrap(); - let transactions_db = dir + let transaction_db = dir .path() .join("transactions.db") .to_str() @@ -710,26 +666,24 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke let stake_args: StakeArgs> = StakeArgs { stake_account_address, - stake_authority: Some(Box::new(stake_authority)), - withdraw_authority: Some(Box::new(withdraw_authority)), + stake_authority: Box::new(stake_authority), + withdraw_authority: Box::new(withdraw_authority), sol_for_fees: 1.0, }; let args: DistributeTokensArgs> = DistributeTokensArgs { - fee_payer: Some(Box::new(fee_payer)), + fee_payer: Box::new(fee_payer), dry_run: false, - no_wait: false, input_csv, - transactions_db: transactions_db.clone(), + transaction_db: transaction_db.clone(), stake_args: Some(stake_args), - force: false, from_bids: false, - sender_keypair: Some(Box::new(sender_keypair)), + sender_keypair: Box::new(sender_keypair), dollars_per_sol: None, }; let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); assert_eq!(confirmations, None); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -750,7 +704,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transactions_db, true).unwrap()); + let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -870,8 +824,8 @@ mod tests { db.set(&signature.to_string(), &transaction_info).unwrap(); assert!(matches!( update_finalized_transaction(&mut db, &signature, None, &blockhash, &[blockhash]) - .unwrap_err(), - Error::SignatureNotFound + .unwrap(), + Some(0) )); // Unchanged From 0ee429e9c73de75b5c1c0cf77eb283dc7d0aa760 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 13:58:51 -0600 Subject: [PATCH 64/71] Sort transaction log by finalized date (#33) --- Cargo.lock | 1 + Cargo.toml | 3 +- src/tokens.rs | 81 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c6344c84f9d5de..787561018bbfd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3441,6 +3441,7 @@ dependencies = [ name = "solana-tokens" version = "0.1.1" dependencies = [ + "chrono", "clap", "console 0.10.3", "csv", diff --git a/Cargo.toml b/Cargo.toml index bef3e726642708..b0b463b404bcac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,9 +9,10 @@ license = "Apache-2.0" homepage = "https://solana.com/" [dependencies] -csv = "1.1.3" +chrono = { version = "0.4", features = ["serde"] } clap = "2.33.0" console = "0.10.3" +csv = "1.1.3" indexmap = "1.3.2" indicatif = "0.14.0" itertools = "0.9.0" diff --git a/src/tokens.rs b/src/tokens.rs index 4d5242a2251672..195884cf6352d4 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,5 +1,6 @@ use crate::args::{BalancesArgs, DistributeTokensArgs, StakeArgs, TransactionLogArgs}; use crate::thin_client::{Client, ThinClient}; +use chrono::prelude::*; use console::style; use csv::{ReaderBuilder, Trim}; use indexmap::IndexMap; @@ -21,7 +22,13 @@ use solana_stake_program::{ stake_state::{Authorized, Lockup, StakeAuthorize}, }; use solana_transaction_status::TransactionStatus; -use std::{cmp, io, path::Path, thread::sleep, time::Duration}; +use std::{ + cmp::{self, Ordering}, + io, + path::Path, + thread::sleep, + time::Duration, +}; #[derive(Serialize, Deserialize, Debug, Clone)] struct Bid { @@ -40,7 +47,7 @@ struct TransactionInfo { recipient: Pubkey, amount: f64, new_stake_account_address: Option, - finalized: bool, + finalized_date: Option>, transaction: Transaction, } @@ -52,7 +59,7 @@ impl Default for TransactionInfo { recipient: Pubkey::default(), amount: 0.0, new_stake_account_address: None, - finalized: false, + finalized_date: None, transaction, } } @@ -63,7 +70,7 @@ struct SignedTransactionInfo { recipient: String, amount: f64, new_stake_account_address: String, - finalized: bool, + finalized_date: Option>, signature: String, } @@ -226,9 +233,24 @@ fn open_db(path: &str, dry_run: bool) -> Result Ordering { + let ordering = match (a.finalized_date, b.finalized_date) { + (Some(a), Some(b)) => a.cmp(&b), + (None, Some(_)) => Ordering::Greater, + (Some(_), None) => Ordering::Less, // Future finalized date will be greater + _ => Ordering::Equal, + }; + if ordering == Ordering::Equal { + return a.recipient.to_string().cmp(&b.recipient.to_string()); + } + ordering +} + pub fn write_transaction_log>(db: &PickleDb, path: &P) -> Result<(), io::Error> { let mut wtr = csv::WriterBuilder::new().from_path(path).unwrap(); - for info in read_transaction_infos(db) { + let mut transaction_infos = read_transaction_infos(db); + transaction_infos.sort_by(compare_transaction_infos); + for info in transaction_infos { let signed_info = SignedTransactionInfo { recipient: info.recipient.to_string(), amount: info.amount, @@ -236,7 +258,7 @@ pub fn write_transaction_log>(db: &PickleDb, path: &P) -> Result< .new_stake_account_address .map(|x| x.to_string()) .unwrap_or_else(|| "".to_string()), - finalized: info.finalized, + finalized_date: info.finalized_date, signature: info.transaction.signatures[0].to_string(), }; wtr.serialize(&signed_info)?; @@ -257,11 +279,12 @@ fn set_transaction_info( new_stake_account_address: Option<&Pubkey>, finalized: bool, ) -> Result<(), pickledb::error::Error> { + let finalized_date = if finalized { Some(Utc::now()) } else { None }; let transaction_info = TransactionInfo { recipient: allocation.recipient.parse().unwrap(), amount: allocation.amount, new_stake_account_address: new_stake_account_address.cloned(), - finalized, + finalized_date, transaction: transaction.clone(), }; let signature = transaction.signatures[0]; @@ -447,7 +470,7 @@ fn update_finalized_transaction( // Transaction is rooted. Set finalized in the database. let mut transaction_info = db.get::(&signature.to_string()).unwrap(); - transaction_info.finalized = true; + transaction_info.finalized_date = Some(Utc::now()); db.set(&signature.to_string(), &transaction_info)?; Ok(None) } @@ -462,7 +485,7 @@ fn update_finalized_transactions( let unconfirmed_transactions: Vec<_> = transaction_infos .iter() .filter_map(|info| { - if info.finalized { + if info.finalized_date.is_some() { None } else { Some(&info.transaction) @@ -802,7 +825,7 @@ mod tests { recipient: bob, amount: 1.0, new_stake_account_address: None, - finalized: true, + finalized_date: Some(Utc::now()), transaction: Transaction::new_unsigned_instructions(vec![]), }]; apply_previous_transactions(&mut allocations, &transaction_infos); @@ -917,7 +940,7 @@ mod tests { PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); let signature = Signature::default(); let blockhash = Hash::default(); - let mut transaction_info = TransactionInfo::default(); + let transaction_info = TransactionInfo::default(); db.set(&signature.to_string(), &transaction_info).unwrap(); let transaction_status = TransactionStatus { slot: 0, @@ -937,11 +960,37 @@ mod tests { None ); - transaction_info.finalized = true; - assert_eq!( - db.get::(&signature.to_string()).unwrap(), - transaction_info - ); + assert!(db + .get::(&signature.to_string()) + .unwrap() + .finalized_date + .is_some()); + } + + #[test] + fn test_sort_transaction_infos_finalized_first() { + let info0 = TransactionInfo { + finalized_date: Some(Utc.ymd(2014, 7, 8).and_hms(9, 10, 11)), + ..TransactionInfo::default() + }; + let info1 = TransactionInfo { + finalized_date: Some(Utc.ymd(2014, 7, 8).and_hms(9, 10, 42)), + ..TransactionInfo::default() + }; + let info2 = TransactionInfo::default(); + let info3 = TransactionInfo { + recipient: Pubkey::new_rand(), + ..TransactionInfo::default() + }; + + // Sorted first by date + assert_eq!(compare_transaction_infos(&info0, &info1), Ordering::Less); + + // Finalized transactions should be before unfinalized ones + assert_eq!(compare_transaction_infos(&info1, &info2), Ordering::Less); + + // Then sorted by recipient + assert_eq!(compare_transaction_infos(&info2, &info3), Ordering::Less); } #[test] From 8d35db17e474e33f8753fd46bbdb9997aca4f1f6 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 16:06:04 -0600 Subject: [PATCH 65/71] Make --transaction-db option implicit (#34) --- Cargo.lock | 1 + Cargo.toml | 1 + README.md | 11 +++++++---- src/arg_parser.rs | 47 ++++++++++++++++++++++++++++++----------------- src/main.rs | 14 +++++++++++++- src/tokens.rs | 17 +++++++++++------ 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 787561018bbfd7..47e6c63af63890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3445,6 +3445,7 @@ dependencies = [ "clap", "console 0.10.3", "csv", + "dirs", "indexmap", "indicatif", "itertools 0.9.0", diff --git a/Cargo.toml b/Cargo.toml index b0b463b404bcac..4324c0275a0485 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ chrono = { version = "0.4", features = ["serde"] } clap = "2.33.0" console = "0.10.3" csv = "1.1.3" +dirs = "2.0.2" indexmap = "1.3.2" indicatif = "0.14.0" itertools = "0.9.0" diff --git a/README.md b/README.md index 1dd3af9a0ced75..940183dfd71819 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ primary_address,bid_amount_dollars ``` ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --from-bids --input-csv --transaction-db --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --from-bids --input-csv --fee-payer ``` Example transaction log before: @@ -31,7 +31,7 @@ Send tokens to the recipients in `` if the distribution is not already recordered in the transaction log. ```bash -solana-tokens distribute-tokens --from --dollars-per-sol --from-bids --input-csv --transaction-db --fee-payer +solana-tokens distribute-tokens --from --dollars-per-sol --from-bids --input-csv --fee-payer ``` Example output: @@ -46,6 +46,10 @@ UKUcTXgbeTYh65RaVV5gSf6xBHevqHvAXMo3e8Q6np8k 43 Example transaction log after: +```bash +solana-tokens transaction-log --output-path transactions.csv +``` + ```text recipient,amount,signature 6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv,30,1111111111111111111111111111111111111111111111111111111111111111 @@ -60,7 +64,7 @@ List the differences between a list of expected distributions and the record of transactions have already been sent. ```bash -solana-tokens distribute-tokens --dollars-per-sol --dry-run --from-bids --input-csv --transaction-db +solana-tokens distribute-tokens --dollars-per-sol --dry-run --from-bids --input-csv ``` Example bids.csv: @@ -91,7 +95,6 @@ the new accounts inherit any lockup or custodian settings of the original. ```bash solana-tokens distribute-stake --stake-account-address \ --input-csv \ - --transaction-db \ --stake-authority --withdraw-authority --fee-payer ``` diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 3ecaff543cab7c..96e38e208ed58a 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -36,12 +36,11 @@ where SubCommand::with_name("distribute-tokens") .about("Distribute tokens") .arg( - Arg::with_name("transaction_db") - .long("transaction-db") - .required(true) + Arg::with_name("campaign_name") + .long("campaign-name") .takes_value(true) - .value_name("FILE") - .help("Transaction database file"), + .value_name("NAME") + .help("Campaign name for storing transaction data"), ) .arg( Arg::with_name("from_bids") @@ -91,12 +90,11 @@ where SubCommand::with_name("distribute-stake") .about("Distribute stake accounts") .arg( - Arg::with_name("transaction_db") - .long("transaction-db") - .required(true) + Arg::with_name("campaign_name") + .long("campaign-name") .takes_value(true) - .value_name("FILE") - .help("Transaction database file"), + .value_name("NAME") + .help("Campaign name for storing transaction data"), ) .arg( Arg::with_name("input_csv") @@ -193,12 +191,11 @@ where SubCommand::with_name("transaction-log") .about("Print the database to a CSV file") .arg( - Arg::with_name("transaction_db") - .long("transaction-db") - .required(true) + Arg::with_name("campaign_name") + .long("campaign-name") .takes_value(true) - .value_name("FILE") - .help("Transactions database file"), + .value_name("NAME") + .help("Campaign name for storing transaction data"), ) .arg( Arg::with_name("output_path") @@ -212,11 +209,27 @@ where .get_matches_from(args) } +fn create_db_path(campaign_name: Option) -> String { + let (prefix, hyphen) = if let Some(name) = campaign_name { + (name, "-") + } else { + ("".to_string(), "") + }; + let path = dirs::home_dir().unwrap(); + let filename = format!("{}{}transactions.db", prefix, hyphen); + path.join(".config") + .join("solana-tokens") + .join(filename) + .to_str() + .unwrap() + .to_string() +} + fn parse_distribute_tokens_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs { DistributeTokensArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), from_bids: matches.is_present("from_bids"), - transaction_db: value_t_or_exit!(matches, "transaction_db", String), + transaction_db: create_db_path(value_t!(matches, "campaign_name", String).ok()), dollars_per_sol: value_t!(matches, "dollars_per_sol", f64).ok(), dry_run: matches.is_present("dry_run"), sender_keypair: value_t_or_exit!(matches, "sender_keypair", String), @@ -235,7 +248,7 @@ fn parse_distribute_stake_args(matches: &ArgMatches<'_>) -> DistributeTokensArgs DistributeTokensArgs { input_csv: value_t_or_exit!(matches, "input_csv", String), from_bids: false, - transaction_db: value_t_or_exit!(matches, "transaction_db", String), + transaction_db: create_db_path(value_t!(matches, "campaign_name", String).ok()), dollars_per_sol: None, dry_run: matches.is_present("dry_run"), sender_keypair: value_t_or_exit!(matches, "sender_keypair", String), diff --git a/src/main.rs b/src/main.rs index a2e9b63663a67c..379ae648211313 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use solana_cli_config::Config; +use solana_cli_config::CONFIG_FILE; use solana_client::rpc_client::RpcClient; use solana_tokens::{ arg_parser::parse_args, @@ -8,10 +9,21 @@ use solana_tokens::{ }; use std::env; use std::error::Error; +use std::path::Path; +use std::process; fn main() -> Result<(), Box> { let command_args = parse_args(env::args_os()); - let config = Config::load(&command_args.config_file)?; + let config = if Path::new(&command_args.config_file).exists() { + Config::load(&command_args.config_file)? + } else { + let default_config_file = CONFIG_FILE.as_ref().unwrap(); + if command_args.config_file != *default_config_file { + eprintln!("Error: config file not found"); + process::exit(1); + } + Config::default() + }; let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); let client = RpcClient::new(json_rpc_url); diff --git a/src/tokens.rs b/src/tokens.rs index 195884cf6352d4..634d728ba5c5c6 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -24,7 +24,7 @@ use solana_stake_program::{ use solana_transaction_status::TransactionStatus; use std::{ cmp::{self, Ordering}, - io, + fs, io, path::Path, thread::sleep, time::Duration, @@ -220,17 +220,22 @@ fn distribute_tokens( Ok(()) } -fn open_db(path: &str, dry_run: bool) -> Result { +fn open_db(path: &str, dry_run: bool) -> Result { let policy = if dry_run { PickleDbDumpPolicy::NeverDump } else { PickleDbDumpPolicy::AutoDump }; - if Path::new(path).exists() { - PickleDb::load_yaml(path, policy) + let path = Path::new(path); + let db = if path.exists() { + PickleDb::load_yaml(path, policy)? } else { - Ok(PickleDb::new_yaml(path, policy)) - } + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + PickleDb::new_yaml(path, policy) + }; + Ok(db) } fn compare_transaction_infos(a: &TransactionInfo, b: &TransactionInfo) -> Ordering { From 282c9f371d5ef3f136c20b709911559b3ce14a77 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 17:03:22 -0600 Subject: [PATCH 66/71] Move db functionality into its own module (#35) * Move db functionality into its own module * Rename tokens module to commands * Version bump * Upgrade Solana --- Cargo.lock | 474 +++++++++++-------------------- Cargo.toml | 20 +- src/{tokens.rs => commands.rs} | 381 ++----------------------- src/db.rs | 351 +++++++++++++++++++++++ src/lib.rs | 3 +- src/main.rs | 8 +- tests/{tokens.rs => commands.rs} | 2 +- 7 files changed, 550 insertions(+), 689 deletions(-) rename src/{tokens.rs => commands.rs} (63%) create mode 100644 src/db.rs rename tests/{tokens.rs => commands.rs} (90%) diff --git a/Cargo.lock b/Cargo.lock index 47e6c63af63890..8eff663b749914 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,15 +24,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "ar" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579681b3fecd1e9d6b5ce6969e05f9feb913f296eddaf595be1166a5ca597bc4" -dependencies = [ - "byteorder", -] - [[package]] name = "arrayref" version = "0.3.6" @@ -155,7 +146,7 @@ dependencies = [ "cfg-if", "clang-sys", "clap", - "env_logger 0.7.1", + "env_logger", "lazy_static", "lazycell", "log 0.4.8", @@ -168,18 +159,6 @@ dependencies = [ "which", ] -[[package]] -name = "bit-vec" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" - -[[package]] -name = "bit-vec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" - [[package]] name = "bitflags" version = "1.2.1" @@ -197,16 +176,6 @@ dependencies = [ "constant_time_eq", ] -[[package]] -name = "block-buffer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -dependencies = [ - "arrayref", - "byte-tools 0.2.0", -] - [[package]] name = "block-buffer" version = "0.7.3" @@ -214,7 +183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ "block-padding", - "byte-tools 0.3.1", + "byte-tools", "byteorder", "generic-array 0.12.3", ] @@ -225,16 +194,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ - "byte-tools 0.3.1", -] - -[[package]] -name = "bloom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00ac8e5056d6d65376a3c1aa5c7c34850d6949ace17f0266953a254eb3d6fe8" -dependencies = [ - "bit-vec 0.4.4", + "byte-tools", ] [[package]] @@ -271,12 +231,6 @@ dependencies = [ "serde", ] -[[package]] -name = "byte-tools" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" - [[package]] name = "byte-tools" version = "0.3.1" @@ -358,7 +312,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" dependencies = [ "num-integer", - "num-traits 0.2.11", + "num-traits", "serde", "time", ] @@ -369,7 +323,7 @@ version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" dependencies = [ - "glob 0.3.0", + "glob", "libc", "libloading", ] @@ -419,17 +373,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "colored" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" -dependencies = [ - "atty", - "lazy_static", - "winapi 0.3.8", -] - [[package]] name = "combine" version = "2.5.2" @@ -622,7 +565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" dependencies = [ "byteorder", - "digest 0.8.1", + "digest", "rand_core 0.5.1", "subtle 2.2.2", "zeroize", @@ -639,15 +582,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "digest" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -dependencies = [ - "generic-array 0.9.0", -] - [[package]] name = "digest" version = "0.8.1" @@ -727,7 +661,7 @@ dependencies = [ "curve25519-dalek", "rand 0.7.3", "serde", - "sha2 0.8.1", + "sha2", ] [[package]] @@ -736,33 +670,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -[[package]] -name = "elfkit" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f182eda16a7360c80a2f8638d0726e9d5478173058f1505c42536ca666ecd2" -dependencies = [ - "ar", - "bit-vec 0.5.1", - "bitflags", - "bloom", - "byteorder", - "clap", - "colored", - "enum-primitive-derive", - "env_logger 0.5.13", - "fnv", - "glob 0.2.11", - "indexmap", - "itertools 0.7.11", - "log 0.4.8", - "num-traits 0.2.11", - "pretty_env_logger", - "rayon", - "sha2 0.7.1", - "tempfile", -] - [[package]] name = "encode_unicode" version = "0.3.6" @@ -778,30 +685,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "enum-primitive-derive" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd" -dependencies = [ - "num-traits 0.1.43", - "quote 0.3.15", - "syn 0.11.11", -] - -[[package]] -name = "env_logger" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -dependencies = [ - "atty", - "humantime", - "log 0.4.8", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.7.1" @@ -1009,15 +892,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.12.3" @@ -1058,12 +932,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" - [[package]] name = "glob" version = "0.3.0" @@ -1083,6 +951,17 @@ dependencies = [ "regex", ] +[[package]] +name = "goblin" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884" +dependencies = [ + "log 0.4.8", + "plain", + "scroll", +] + [[package]] name = "h2" version = "0.1.26" @@ -1168,7 +1047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" dependencies = [ "crypto-mac", - "digest 0.8.1", + "digest", ] [[package]] @@ -1394,15 +1273,6 @@ dependencies = [ "libc", ] -[[package]] -name = "itertools" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.9.0" @@ -1632,7 +1502,7 @@ checksum = "883213ae3d09bfc3d104aefe94b25ebb183b6f4d3a515b23b14817e1f4854005" dependencies = [ "bindgen", "cc", - "glob 0.3.0", + "glob", "libc", ] @@ -1875,16 +1745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" dependencies = [ "autocfg 1.0.0", - "num-traits 0.2.11", -] - -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.11", + "num-traits", ] [[package]] @@ -2112,22 +1973,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] -name = "ppv-lite86" -version = "0.2.6" +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] -name = "pretty_env_logger" -version = "0.2.5" +name = "ppv-lite86" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed8d1e63042e889b85228620629b51c011d380eed2c7e0015f8a644def280c28" -dependencies = [ - "ansi_term", - "chrono", - "env_logger 0.5.13", - "log 0.4.8", -] +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "proc-macro-crate" @@ -2174,12 +2029,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" - [[package]] name = "quote" version = "0.6.13" @@ -2598,6 +2447,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scroll" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.1", + "syn 1.0.18", +] + [[package]] name = "sct" version = "0.6.0" @@ -2726,8 +2595,8 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", + "block-buffer", + "digest", "fake-simd", "opaque-debug", ] @@ -2738,26 +2607,14 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -[[package]] -name = "sha2" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" -dependencies = [ - "block-buffer 0.3.3", - "byte-tools 0.2.0", - "digest 0.7.6", - "fake-simd", -] - [[package]] name = "sha2" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", + "block-buffer", + "digest", "fake-simd", "opaque-debug", ] @@ -2803,9 +2660,9 @@ dependencies = [ [[package]] name = "solana-archiver-utils" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5748b097187cf8c1a65c8fa9eda38e639d39ce5e10b7366d85010ceae1b43f6" +checksum = "af16337f68249126755ed915faa3be8a43484703ad28d904d256c47c801d1835" dependencies = [ "log 0.4.8", "rand 0.7.3", @@ -2819,16 +2676,16 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b8061b765425f87cb1e1f215700d0e8d432ec71e2bd37f61012cb04157203d" +checksum = "5065a3c4ff081a43fd716b2d98431920cbd0fc5bec254d1dbfa46c9acea248bd" dependencies = [ "bincode", "byteorder", "libc", "log 0.4.8", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "solana-logger", "solana-sdk", "solana_rbpf", @@ -2837,15 +2694,15 @@ dependencies = [ [[package]] name = "solana-budget-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17dac9b180aef6ea82ba0b0a9b333183dd2d1c1c5f7d76e77ab365675d2b749" +checksum = "b5bf766c14fcef01ef47a113e51861955adbf4ac7e4c174161f170ef3a7010b0" dependencies = [ "bincode", "chrono", "log 0.4.8", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "serde", "serde_derive", "solana-sdk", @@ -2854,9 +2711,9 @@ dependencies = [ [[package]] name = "solana-chacha" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d827dcd3c0c2002bf709999d70a39cb1b467185d536d65f2f4ceb2ece845c04" +checksum = "765b4d45c4399c779a3b480e9b7d620eb36b765f878d0bb49cb125f53430efcb" dependencies = [ "log 0.4.8", "rand 0.7.3", @@ -2870,9 +2727,9 @@ dependencies = [ [[package]] name = "solana-chacha-cuda" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a433202f0bf5d14845a609f77c6ac483d446fe13766c73ab82e6ff2b853f9d" +checksum = "3721a9c794c662527144293cf18b4174063c798a59d1b7637d52959819898de2" dependencies = [ "log 0.4.8", "solana-archiver-utils", @@ -2885,18 +2742,18 @@ dependencies = [ [[package]] name = "solana-chacha-sys" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bcb5f621da93619d5ec06354d9b59c9a1a87ac77452c3f5b9dd37637152a4d8" +checksum = "9deae46160e7df6d0330e402917187298690d0fa9cba7236b27962d43cb82fa9" dependencies = [ "cc", ] [[package]] name = "solana-clap-utils" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c6e49808c95de975b8591aa84a7f1dad102200b2624d713f2c64cdf131a83c" +checksum = "4347a772749876a4d2e52132e786765e2d69d5e5a3f55868ad0418775222c265" dependencies = [ "chrono", "clap", @@ -2910,9 +2767,9 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "493ec5bd9c44ae33594a5ef568179a38d6d378c538bc652d93eecd959cfc49b8" +checksum = "b37d4bf33d9d7f5a4cc94cbc27cea45366e64a771b0688df5018072df6eabe1a" dependencies = [ "dirs", "lazy_static", @@ -2924,9 +2781,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e43d60394d9238d865c94409784fb0984b28948682164ff3c8abca131014885" +checksum = "a0ef535a3634219bc22397da24c1bf65d596e9169c085cefcd8f7cef14406d57" dependencies = [ "bincode", "bs58", @@ -2949,9 +2806,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fd83a1a37bf1496c9154e6d10d4a103b82ea7a0cba6029809342249c02624" +checksum = "d11c4846b9ac4db511cac9d63d03bfd4926a1eb19e1a8a7b66cf4574ad28721b" dependencies = [ "bincode", "chrono", @@ -2963,9 +2820,9 @@ dependencies = [ [[package]] name = "solana-core" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2037d4dc846e077b26798c5a67da9a9e20ead0d9ad2c34c2d773b02f46e54f" +checksum = "487f8eec5f526f53679b9c2ee41cda57fdc50ec0096fc2673970e747b5b0c055" dependencies = [ "bincode", "bs58", @@ -2978,7 +2835,7 @@ dependencies = [ "flate2", "fs_extra", "indexmap", - "itertools 0.9.0", + "itertools", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -2986,7 +2843,7 @@ dependencies = [ "jsonrpc-pubsub", "jsonrpc-ws-server", "log 0.4.8", - "num-traits 0.2.11", + "num-traits", "num_cpus", "rand 0.7.3", "rand_chacha 0.2.2", @@ -3016,6 +2873,7 @@ dependencies = [ "solana-streamer", "solana-sys-tuner", "solana-transaction-status", + "solana-version", "solana-vote-program", "solana-vote-signer", "tempfile", @@ -3029,9 +2887,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4951745150b3973be869860b3239bcb85d6da45abf314106e136187dbaa88d90" +checksum = "d2343b3f37b45e7d1183ad21a0feeac0ac216ee065f5df81e1709af5145653d3" dependencies = [ "backtrace", "bytes 0.4.12", @@ -3054,14 +2912,14 @@ dependencies = [ [[package]] name = "solana-exchange-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f53b8f6cdcb53c68ac962e5d34a53ab54734fcd757516fd2ccf30dafeba47a" +checksum = "df1627dd1764c0d274b3281827a75b575253f79ed58aa8ed65f9e52548c42c5e" dependencies = [ "bincode", "log 0.4.8", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "serde", "serde_derive", "solana-logger", @@ -3072,9 +2930,9 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e621d9ab601163293f58a94197ac0b0907260de7b1566412cbc1a4ae1ebbec13" +checksum = "ad1158994709fc61eff8b26cdf69fbedb11f3e82f0271e6fa23523e18e84d727" dependencies = [ "bincode", "byteorder", @@ -3093,9 +2951,9 @@ dependencies = [ [[package]] name = "solana-genesis-programs" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1dd6ff73fd0b8d850cd79be1187431eb0dc15bccdccda81ab1a419cf8c1f" +checksum = "187f4468de794aa4f4ca267b0113bad9db4d049a63cc00c31eac8ef6b7c2a61c" dependencies = [ "log 0.4.8", "solana-bpf-loader-program", @@ -3109,9 +2967,9 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39d1328915a36e3df2b60fa77fc29c0d0fa0d868de22cc7b2ce834765b6192f" +checksum = "9b49bb91c0d53c60a759f2c2eb2403228622cd7e49fdc3cf42213605b3473ead" dependencies = [ "bincode", "byteorder", @@ -3121,7 +2979,7 @@ dependencies = [ "dir-diff", "ed25519-dalek", "fs_extra", - "itertools 0.9.0", + "itertools", "lazy_static", "libc", "log 0.4.8", @@ -3133,7 +2991,7 @@ dependencies = [ "rocksdb", "serde", "serde_bytes", - "sha2 0.8.1", + "sha2", "solana-genesis-programs", "solana-logger", "solana-measure", @@ -3155,20 +3013,20 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b97fb29457995ca16c4ef6dd11c65062315e5860ef4fa23f8130b2a625b810a" +checksum = "c4b26cb13817ba92e36a05c792f2f4e551b1c7e5cb17744da47677dc653cee4e" dependencies = [ - "env_logger 0.7.1", + "env_logger", "lazy_static", "log 0.4.8", ] [[package]] name = "solana-measure" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac46fed54a2375b09780e0e52ff9087316c280f419ca4f5c6d4240be77686e5e" +checksum = "c4c2bf2a8a742192b50c05d5066fffaf9a802f254ec235ccb1d622e82f40ea92" dependencies = [ "jemalloc-ctl", "jemallocator", @@ -3179,9 +3037,9 @@ dependencies = [ [[package]] name = "solana-merkle-tree" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b403bd97961442f49d0f87c4988357f54c47509cc91c0273ef0224b8f432d20" +checksum = "e2f450d84d4a879b7a4000f5a6c6220cc32e021bd63d2563ef0d8eb514758782" dependencies = [ "fast-math", "solana-sdk", @@ -3189,11 +3047,11 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25081118a3cd87b4851dbb02a3bac60a51c1a6e7ff28b44f824a7462a8f4638b" +checksum = "f11f79a745e16128f6afff361037184afcc7a693eba25ccf4a632f7df26d8e24" dependencies = [ - "env_logger 0.7.1", + "env_logger", "gethostname", "lazy_static", "log 0.4.8", @@ -3203,9 +3061,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c3a0479966688f4258a3faa4ea92ba68f4591b33c323887308bcef28c10a9f" +checksum = "2597713f8619f02d2574d8e3e41bb5a4c39abfb3c466777a79c91fdb0f017815" dependencies = [ "bincode", "bytes 0.4.12", @@ -3224,9 +3082,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48882ec893bee13106146643071aefdd06d2aef614cd531d6b235389ffcd9f95" +checksum = "9b210d1ce14719194a0e7a71221c5a52569e878ad1fe863020d2717244342c40" dependencies = [ "bincode", "dlopen", @@ -3245,9 +3103,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b14ba7745207ff9a9319f11b14c220d45cc241bb82aa91fe4741f45f334c2a63" +checksum = "efa6a81840be99cba2285dca3c8320fc0845daf7fe02effc4f44e42eff51b334" dependencies = [ "lazy_static", "num_cpus", @@ -3266,9 +3124,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f64f9065b9dd9c587025017340fb6a10a13f386c2d0586736632e245ed7dae2" +checksum = "1281efae0e72833a45c4cd8eefaed2578a715a537b8ea6386cf99f730afb5e4f" dependencies = [ "base32", "console 0.10.3", @@ -3284,23 +3142,23 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add26829dc669ce66702d74d2f170d3e55d45741c3b1802b8a319b8d564ef958" +checksum = "bcbb9a560caefe24636c54437f2d882ef8d46dec73e44d2ea69b1b007f36b3a2" dependencies = [ "bincode", "bv", "byteorder", "fnv", "fs_extra", - "itertools 0.9.0", + "itertools", "lazy_static", "libc", "libloading", "log 0.4.8", "memmap", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "num_cpus", "rand 0.7.3", "rayon", @@ -3322,9 +3180,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea460e467f49d70df645fa489779900b7e25ea9c29a309f4c0f571707145c1e" +checksum = "860fd85a4e481e2f79bdf73418cbe9cc1e8281a828bb8dc16be18da881675ca2" dependencies = [ "assert_matches", "bincode", @@ -3336,11 +3194,11 @@ dependencies = [ "generic-array 0.13.2", "hex", "hmac", - "itertools 0.9.0", + "itertools", "log 0.4.8", "memmap", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "pbkdf2", "rand 0.7.3", "rand_chacha 0.2.2", @@ -3348,7 +3206,7 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.8.1", + "sha2", "solana-crate-features", "solana-logger", "solana-sdk-macro", @@ -3357,9 +3215,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1699e81c4366590818c3bcd2c05af17de45b5e25f340f3032405d4fa89e163" +checksum = "6a7dc08359c1db017aff7663cfc899305e50c6fb9d99ec8a17c7b5fc9398baab" dependencies = [ "bs58", "proc-macro2 1.0.10", @@ -3369,14 +3227,14 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2027a28f776996d57a41d6543b33a69fb0e3acd578b72de32d29b2d43fc32534" +checksum = "f6f59076b27386284822a25e97ed5a21cc9e8ccb8ddc1b9cc13076f803b0c3c0" dependencies = [ "bincode", "log 0.4.8", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "serde", "serde_derive", "solana-config-program", @@ -3388,14 +3246,14 @@ dependencies = [ [[package]] name = "solana-storage-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917418b7a035fa85b8100f89e59c5e95c60f6e3464e72d717707e89417394ca6" +checksum = "1a6793775b57efc9e7925e3f640d47d1526402704687976ce09d00ae2a2f4f6c" dependencies = [ "bincode", "log 0.4.8", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "rand 0.7.3", "serde", "serde_derive", @@ -3405,9 +3263,9 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8037ebde07a2fbf5c879edde60efbc1f0164141f6625efcfb13d96a9d4b84b98" +checksum = "6ca0feb653d6e2f7e7f89487e79b15c5b257f7e89ed1325f24f517d1a86f8049" dependencies = [ "libc", "log 0.4.8", @@ -3422,9 +3280,9 @@ dependencies = [ [[package]] name = "solana-sys-tuner" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e654f861cc2ab9a3c8efe95127c3c4b7ca534bccf35fc16a5cbd41c4bbbac25" +checksum = "60d8299687d5ebc21b91a84b0255c36cbfa9b0de26c2088684317d21e0d4e6c7" dependencies = [ "clap", "libc", @@ -3439,7 +3297,7 @@ dependencies = [ [[package]] name = "solana-tokens" -version = "0.1.1" +version = "0.1.3" dependencies = [ "chrono", "clap", @@ -3448,7 +3306,7 @@ dependencies = [ "dirs", "indexmap", "indicatif", - "itertools 0.9.0", + "itertools", "pickledb", "serde", "solana-clap-utils", @@ -3466,9 +3324,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2660c083007606866edf1964bc63a0ff068eece70a65dfd2f599c93aa2bad0e5" +checksum = "8bbaa0428020e55c8fa79ad53a7f836e45dcb855dc1c7614287fe3d92e6c8017" dependencies = [ "bincode", "bs58", @@ -3477,16 +3335,27 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-version" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a658f1a9c1308fc05245b42a7fddf18208ec80d892bc84a087200cd024581" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk", +] + [[package]] name = "solana-vest-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f00039e44edfa4a3e9a0c1e801b9d3dbe4285bd7c85ab14edaefd344b128ee4" +checksum = "67ea744b51f354c09f277888a8398d0382a07cf00a6ecbf3b47779e380cfb462" dependencies = [ "bincode", "chrono", "num-derive 0.2.5", - "num-traits 0.2.11", + "num-traits", "serde", "serde_derive", "solana-config-program", @@ -3496,14 +3365,14 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b4a37623715633f3925ff8b34047624beabc08320f5478fde7d7313f342e131" +checksum = "0d63f784f6b03528ede5911fe577878625b1172a7a6b39cd5f9d27c7c8afd604" dependencies = [ "bincode", "log 0.4.8", "num-derive 0.3.0", - "num-traits 0.2.11", + "num-traits", "serde", "serde_derive", "solana-metrics", @@ -3513,9 +3382,9 @@ dependencies = [ [[package]] name = "solana-vote-signer" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "858b129a70106ab764bc780fee19a6bb60913deb54d82c8a56eee8eb4eff8320" +checksum = "ab52fbedb798628414f66b8f65e52912038f436c49b722c43a3d5d40afd031fd" dependencies = [ "clap", "jsonrpc-core", @@ -3530,17 +3399,18 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.1.25" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87d4395203039cac872c125dea2534e6b98ae85e28e3f800872a7571ffa87df8" +checksum = "e7baa2550500e75413f031f239fe0c4da2d477ae1b1ff7cb671eba483f963d91" dependencies = [ "byteorder", "combine", - "elfkit", + "goblin", "hash32", "libc", "log 0.4.8", - "num-traits 0.2.11", + "rand 0.7.3", + "scroll", "thiserror", "time", ] @@ -3584,17 +3454,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" -[[package]] -name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -dependencies = [ - "quote 0.3.15", - "synom", - "unicode-xid 0.0.4", -] - [[package]] name = "syn" version = "0.15.44" @@ -3617,15 +3476,6 @@ dependencies = [ "unicode-xid 0.2.0", ] -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -dependencies = [ - "unicode-xid 0.0.4", -] - [[package]] name = "synstructure" version = "0.12.3" @@ -3765,7 +3615,7 @@ dependencies = [ "pbkdf2", "rand 0.7.3", "rustc-hash", - "sha2 0.8.1", + "sha2", "unicode-normalization", ] @@ -4127,12 +3977,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" - [[package]] name = "unicode-xid" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 4324c0275a0485..0d092f424b2baa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "solana-tokens" description = "Blockchain, Rebuilt for Scale" authors = ["Solana Maintainers "] edition = "2018" -version = "0.1.1" +version = "0.1.3" repository = "https://github.com/solana-labs/solana" license = "Apache-2.0" homepage = "https://solana.com/" @@ -19,16 +19,16 @@ indicatif = "0.14.0" itertools = "0.9.0" pickledb = "0.4.1" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = "1.1.8" -solana-cli-config = "1.1.8" -solana-client = "1.1.8" -solana-remote-wallet = "1.1.8" -solana-runtime = "1.1.8" -solana-sdk = "1.1.8" -solana-stake-program = "1.1.8" -solana-transaction-status = "1.1.8" +solana-clap-utils = "1.1.12" +solana-cli-config = "1.1.12" +solana-client = "1.1.12" +solana-remote-wallet = "1.1.12" +solana-runtime = "1.1.12" +solana-sdk = "1.1.12" +solana-stake-program = "1.1.12" +solana-transaction-status = "1.1.12" tempfile = "3.1.0" thiserror = "1.0" [dev-dependencies] -solana-core = "1.1.8" +solana-core = "1.1.12" diff --git a/src/tokens.rs b/src/commands.rs similarity index 63% rename from src/tokens.rs rename to src/commands.rs index 634d728ba5c5c6..5517ab5887e211 100644 --- a/src/tokens.rs +++ b/src/commands.rs @@ -1,31 +1,27 @@ use crate::args::{BalancesArgs, DistributeTokensArgs, StakeArgs, TransactionLogArgs}; +use crate::db::{self, TransactionInfo}; use crate::thin_client::{Client, ThinClient}; -use chrono::prelude::*; use console::style; use csv::{ReaderBuilder, Trim}; use indexmap::IndexMap; use indicatif::{ProgressBar, ProgressStyle}; use itertools::Itertools; -use pickledb::{PickleDb, PickleDbDumpPolicy}; +use pickledb::PickleDb; use serde::{Deserialize, Serialize}; use solana_sdk::{ - hash::Hash, message::Message, native_token::{lamports_to_sol, sol_to_lamports}, signature::{Signature, Signer}, system_instruction, - transaction::Transaction, transport::TransportError, }; use solana_stake_program::{ stake_instruction, stake_state::{Authorized, Lockup, StakeAuthorize}, }; -use solana_transaction_status::TransactionStatus; use std::{ - cmp::{self, Ordering}, - fs, io, - path::Path, + cmp::{self}, + io, thread::sleep, time::Duration, }; @@ -42,38 +38,6 @@ struct Allocation { amount: f64, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] -struct TransactionInfo { - recipient: Pubkey, - amount: f64, - new_stake_account_address: Option, - finalized_date: Option>, - transaction: Transaction, -} - -impl Default for TransactionInfo { - fn default() -> Self { - let mut transaction = Transaction::new_unsigned_instructions(vec![]); - transaction.signatures.push(Signature::default()); - Self { - recipient: Pubkey::default(), - amount: 0.0, - new_stake_account_address: None, - finalized_date: None, - transaction, - } - } -} - -#[derive(Serialize, Deserialize, Debug, Default, PartialEq)] -struct SignedTransactionInfo { - recipient: String, - amount: f64, - new_stake_account_address: String, - finalized_date: Option>, - signature: String, -} - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("I/O error")] @@ -204,9 +168,10 @@ fn distribute_tokens( let message = Message::new_with_payer(&instructions, Some(&fee_payer_pubkey)); match client.send_message(message, &signers) { Ok(transaction) => { - set_transaction_info( + db::set_transaction_info( db, - &allocation, + &allocation.recipient.parse().unwrap(), + allocation.amount, &transaction, Some(&new_stake_account_address), false, @@ -220,83 +185,6 @@ fn distribute_tokens( Ok(()) } -fn open_db(path: &str, dry_run: bool) -> Result { - let policy = if dry_run { - PickleDbDumpPolicy::NeverDump - } else { - PickleDbDumpPolicy::AutoDump - }; - let path = Path::new(path); - let db = if path.exists() { - PickleDb::load_yaml(path, policy)? - } else { - if let Some(parent) = path.parent() { - fs::create_dir_all(parent)?; - } - PickleDb::new_yaml(path, policy) - }; - Ok(db) -} - -fn compare_transaction_infos(a: &TransactionInfo, b: &TransactionInfo) -> Ordering { - let ordering = match (a.finalized_date, b.finalized_date) { - (Some(a), Some(b)) => a.cmp(&b), - (None, Some(_)) => Ordering::Greater, - (Some(_), None) => Ordering::Less, // Future finalized date will be greater - _ => Ordering::Equal, - }; - if ordering == Ordering::Equal { - return a.recipient.to_string().cmp(&b.recipient.to_string()); - } - ordering -} - -pub fn write_transaction_log>(db: &PickleDb, path: &P) -> Result<(), io::Error> { - let mut wtr = csv::WriterBuilder::new().from_path(path).unwrap(); - let mut transaction_infos = read_transaction_infos(db); - transaction_infos.sort_by(compare_transaction_infos); - for info in transaction_infos { - let signed_info = SignedTransactionInfo { - recipient: info.recipient.to_string(), - amount: info.amount, - new_stake_account_address: info - .new_stake_account_address - .map(|x| x.to_string()) - .unwrap_or_else(|| "".to_string()), - finalized_date: info.finalized_date, - signature: info.transaction.signatures[0].to_string(), - }; - wtr.serialize(&signed_info)?; - } - wtr.flush() -} - -fn read_transaction_infos(db: &PickleDb) -> Vec { - db.iter() - .map(|kv| kv.get_value::().unwrap()) - .collect() -} - -fn set_transaction_info( - db: &mut PickleDb, - allocation: &Allocation, - transaction: &Transaction, - new_stake_account_address: Option<&Pubkey>, - finalized: bool, -) -> Result<(), pickledb::error::Error> { - let finalized_date = if finalized { Some(Utc::now()) } else { None }; - let transaction_info = TransactionInfo { - recipient: allocation.recipient.parse().unwrap(), - amount: allocation.amount, - new_stake_account_address: new_stake_account_address.cloned(), - finalized_date, - transaction: transaction.clone(), - }; - let signature = transaction.signatures[0]; - db.set(&signature.to_string(), &transaction_info)?; - Ok(()) -} - fn read_allocations( input_csv: &str, from_bids: bool, @@ -345,12 +233,12 @@ pub fn process_distribute_tokens( ); } - let mut db = open_db(&args.transaction_db, args.dry_run)?; + let mut db = db::open_db(&args.transaction_db, args.dry_run)?; // Start by finalizing any transactions from the previous run. let confirmations = finalize_transactions(client, &mut db)?; - let transaction_infos = read_transaction_infos(&db); + let transaction_infos = db::read_transaction_infos(&db); apply_previous_transactions(&mut allocations, &transaction_infos); if allocations.is_empty() { @@ -433,60 +321,13 @@ fn finalize_transactions( Ok(opt_confirmations) } -// Set the finalized bit in the database if the transaction is rooted. -// Remove the TransactionInfo from the database if the transaction failed. -// Return the number of confirmations on the transaction or None if finalized. -fn update_finalized_transaction( - db: &mut PickleDb, - signature: &Signature, - opt_transaction_status: Option, - blockhash: &Hash, - recent_blockhashes: &[Hash], -) -> Result, Error> { - if opt_transaction_status.is_none() { - if !recent_blockhashes.contains(blockhash) { - eprintln!("Signature not found {} and blockhash expired", signature); - eprintln!("Discarding transaction record"); - db.rem(&signature.to_string())?; - return Ok(None); - } - - // Return zero to signal the transaction may still be in flight. - return Ok(Some(0)); - } - let transaction_status = opt_transaction_status.unwrap(); - - if let Some(confirmations) = transaction_status.confirmations { - // The transaction was found but is not yet finalized. - return Ok(Some(confirmations)); - } - - if let Err(e) = &transaction_status.status { - // The transaction was finalized, but execution failed. Drop it. - eprintln!( - "Error in transaction with signature {}: {}", - signature, - e.to_string() - ); - eprintln!("Discarding transaction record"); - db.rem(&signature.to_string())?; - return Ok(None); - } - - // Transaction is rooted. Set finalized in the database. - let mut transaction_info = db.get::(&signature.to_string()).unwrap(); - transaction_info.finalized_date = Some(Utc::now()); - db.set(&signature.to_string(), &transaction_info)?; - Ok(None) -} - // Update the finalized bit on any transactions that are now rooted // Return the lowest number of confirmations on the unfinalized transactions or None if all are finalized. fn update_finalized_transactions( client: &ThinClient, db: &mut PickleDb, ) -> Result, Error> { - let transaction_infos = read_transaction_infos(db); + let transaction_infos = db::read_transaction_infos(db); let unconfirmed_transactions: Vec<_> = transaction_infos .iter() .filter_map(|info| { @@ -510,7 +351,7 @@ fn update_finalized_transactions( .into_iter() .zip(transaction_statuses.into_iter()) { - match update_finalized_transaction( + match db::update_finalized_transaction( db, &transaction.signatures[0], opt_transaction_status, @@ -562,8 +403,8 @@ pub fn process_balances( } pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> { - let db = open_db(&args.transaction_db, true)?; - write_transaction_log(&db, &args.output_path)?; + let db = db::open_db(&args.transaction_db, true)?; + db::write_transaction_log(&db, &args.output_path)?; Ok(()) } @@ -611,7 +452,8 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); assert_eq!(confirmations, None); - let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); + let transaction_infos = + db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -627,7 +469,8 @@ pub fn test_process_distribute_tokens_with_client(client: C, sender_k // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); + let transaction_infos = + db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -711,7 +554,8 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke let confirmations = process_distribute_tokens(&thin_client, &args).unwrap(); assert_eq!(confirmations, None); - let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); + let transaction_infos = + db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -732,7 +576,8 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke // Now, run it again, and check there's no double-spend. process_distribute_tokens(&thin_client, &args).unwrap(); - let transaction_infos = read_transaction_infos(&open_db(&transaction_db, true).unwrap()); + let transaction_infos = + db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap()); assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos[0].recipient, alice_pubkey); let expected_amount = sol_to_lamports(allocation.amount); @@ -755,7 +600,7 @@ pub fn test_process_distribute_stake_with_client(client: C, sender_ke mod tests { use super::*; use solana_runtime::{bank::Bank, bank_client::BankClient}; - use solana_sdk::{genesis_config::create_genesis_config, transaction::TransactionError}; + use solana_sdk::{genesis_config::create_genesis_config, transaction::Transaction}; #[test] fn test_process_distribute_tokens() { @@ -830,7 +675,7 @@ mod tests { recipient: bob, amount: 1.0, new_stake_account_address: None, - finalized_date: Some(Utc::now()), + finalized_date: None, transaction: Transaction::new_unsigned_instructions(vec![]), }]; apply_previous_transactions(&mut allocations, &transaction_infos); @@ -840,184 +685,4 @@ mod tests { // a matching recipient address (to bob, not alice). assert_eq!(allocations[0].recipient, alice.to_string()); } - - #[test] - fn test_update_finalized_transaction_not_landed() { - // Keep waiting for a transaction that hasn't landed yet. - let mut db = - PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); - let signature = Signature::default(); - let blockhash = Hash::default(); - let transaction_info = TransactionInfo::default(); - db.set(&signature.to_string(), &transaction_info).unwrap(); - assert!(matches!( - update_finalized_transaction(&mut db, &signature, None, &blockhash, &[blockhash]) - .unwrap(), - Some(0) - )); - - // Unchanged - assert_eq!( - db.get::(&signature.to_string()).unwrap(), - transaction_info - ); - - // Same as before, but now with an expired blockhash - assert_eq!( - update_finalized_transaction(&mut db, &signature, None, &blockhash, &[]).unwrap(), - None - ); - - // Ensure TransactionInfo has been purged. - assert_eq!(db.get::(&signature.to_string()), None); - } - - #[test] - fn test_update_finalized_transaction_confirming() { - // Keep waiting for a transaction that is still being confirmed. - let mut db = - PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); - let signature = Signature::default(); - let blockhash = Hash::default(); - let transaction_info = TransactionInfo::default(); - db.set(&signature.to_string(), &transaction_info).unwrap(); - let transaction_status = TransactionStatus { - slot: 0, - confirmations: Some(1), - status: Ok(()), - err: None, - }; - assert_eq!( - update_finalized_transaction( - &mut db, - &signature, - Some(transaction_status), - &blockhash, - &[blockhash] - ) - .unwrap(), - Some(1) - ); - - // Unchanged - assert_eq!( - db.get::(&signature.to_string()).unwrap(), - transaction_info - ); - } - - #[test] - fn test_update_finalized_transaction_failed() { - // Don't wait if the transaction failed to execute. - let mut db = - PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); - let signature = Signature::default(); - let blockhash = Hash::default(); - let transaction_info = TransactionInfo::default(); - db.set(&signature.to_string(), &transaction_info).unwrap(); - let status = Err(TransactionError::AccountNotFound); - let transaction_status = TransactionStatus { - slot: 0, - confirmations: None, - status, - err: None, - }; - assert_eq!( - update_finalized_transaction( - &mut db, - &signature, - Some(transaction_status), - &blockhash, - &[blockhash] - ) - .unwrap(), - None - ); - - // Ensure TransactionInfo has been purged. - assert_eq!(db.get::(&signature.to_string()), None); - } - - #[test] - fn test_update_finalized_transaction_finalized() { - // Don't wait once the transaction has been finalized. - let mut db = - PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); - let signature = Signature::default(); - let blockhash = Hash::default(); - let transaction_info = TransactionInfo::default(); - db.set(&signature.to_string(), &transaction_info).unwrap(); - let transaction_status = TransactionStatus { - slot: 0, - confirmations: None, - status: Ok(()), - err: None, - }; - assert_eq!( - update_finalized_transaction( - &mut db, - &signature, - Some(transaction_status), - &blockhash, - &[blockhash] - ) - .unwrap(), - None - ); - - assert!(db - .get::(&signature.to_string()) - .unwrap() - .finalized_date - .is_some()); - } - - #[test] - fn test_sort_transaction_infos_finalized_first() { - let info0 = TransactionInfo { - finalized_date: Some(Utc.ymd(2014, 7, 8).and_hms(9, 10, 11)), - ..TransactionInfo::default() - }; - let info1 = TransactionInfo { - finalized_date: Some(Utc.ymd(2014, 7, 8).and_hms(9, 10, 42)), - ..TransactionInfo::default() - }; - let info2 = TransactionInfo::default(); - let info3 = TransactionInfo { - recipient: Pubkey::new_rand(), - ..TransactionInfo::default() - }; - - // Sorted first by date - assert_eq!(compare_transaction_infos(&info0, &info1), Ordering::Less); - - // Finalized transactions should be before unfinalized ones - assert_eq!(compare_transaction_infos(&info1, &info2), Ordering::Less); - - // Then sorted by recipient - assert_eq!(compare_transaction_infos(&info2, &info3), Ordering::Less); - } - - #[test] - fn test_write_transaction_log() { - let mut db = - PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); - let signature = Signature::default(); - let transaction_info = TransactionInfo::default(); - db.set(&signature.to_string(), &transaction_info).unwrap(); - - let csv_file = NamedTempFile::new().unwrap(); - write_transaction_log(&db, &csv_file).unwrap(); - - let mut rdr = ReaderBuilder::new().trim(Trim::All).from_reader(csv_file); - let signed_infos: Vec = - rdr.deserialize().map(|entry| entry.unwrap()).collect(); - - let signed_info = SignedTransactionInfo { - recipient: Pubkey::default().to_string(), - signature: Signature::default().to_string(), - ..SignedTransactionInfo::default() - }; - assert_eq!(signed_infos, vec![signed_info]); - } } diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 00000000000000..442f888927a8c9 --- /dev/null +++ b/src/db.rs @@ -0,0 +1,351 @@ +use chrono::prelude::*; +use pickledb::{error::Error, PickleDb, PickleDbDumpPolicy}; +use serde::{Deserialize, Serialize}; +use solana_sdk::{hash::Hash, pubkey::Pubkey, signature::Signature, transaction::Transaction}; +use solana_transaction_status::TransactionStatus; +use std::{cmp::Ordering, fs, io, path::Path}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub struct TransactionInfo { + pub recipient: Pubkey, + pub amount: f64, + pub new_stake_account_address: Option, + pub finalized_date: Option>, + pub transaction: Transaction, +} + +#[derive(Serialize, Deserialize, Debug, Default, PartialEq)] +struct SignedTransactionInfo { + recipient: String, + amount: f64, + new_stake_account_address: String, + finalized_date: Option>, + signature: String, +} + +impl Default for TransactionInfo { + fn default() -> Self { + let mut transaction = Transaction::new_unsigned_instructions(vec![]); + transaction.signatures.push(Signature::default()); + Self { + recipient: Pubkey::default(), + amount: 0.0, + new_stake_account_address: None, + finalized_date: None, + transaction, + } + } +} + +pub fn open_db(path: &str, dry_run: bool) -> Result { + let policy = if dry_run { + PickleDbDumpPolicy::NeverDump + } else { + PickleDbDumpPolicy::AutoDump + }; + let path = Path::new(path); + let db = if path.exists() { + PickleDb::load_yaml(path, policy)? + } else { + if let Some(parent) = path.parent() { + fs::create_dir_all(parent).unwrap(); + } + PickleDb::new_yaml(path, policy) + }; + Ok(db) +} + +pub fn compare_transaction_infos(a: &TransactionInfo, b: &TransactionInfo) -> Ordering { + let ordering = match (a.finalized_date, b.finalized_date) { + (Some(a), Some(b)) => a.cmp(&b), + (None, Some(_)) => Ordering::Greater, + (Some(_), None) => Ordering::Less, // Future finalized date will be greater + _ => Ordering::Equal, + }; + if ordering == Ordering::Equal { + return a.recipient.to_string().cmp(&b.recipient.to_string()); + } + ordering +} + +pub fn write_transaction_log>(db: &PickleDb, path: &P) -> Result<(), io::Error> { + let mut wtr = csv::WriterBuilder::new().from_path(path).unwrap(); + let mut transaction_infos = read_transaction_infos(db); + transaction_infos.sort_by(compare_transaction_infos); + for info in transaction_infos { + let signed_info = SignedTransactionInfo { + recipient: info.recipient.to_string(), + amount: info.amount, + new_stake_account_address: info + .new_stake_account_address + .map(|x| x.to_string()) + .unwrap_or_else(|| "".to_string()), + finalized_date: info.finalized_date, + signature: info.transaction.signatures[0].to_string(), + }; + wtr.serialize(&signed_info)?; + } + wtr.flush() +} + +pub fn read_transaction_infos(db: &PickleDb) -> Vec { + db.iter() + .map(|kv| kv.get_value::().unwrap()) + .collect() +} + +pub fn set_transaction_info( + db: &mut PickleDb, + recipient: &Pubkey, + amount: f64, + transaction: &Transaction, + new_stake_account_address: Option<&Pubkey>, + finalized: bool, +) -> Result<(), Error> { + let finalized_date = if finalized { Some(Utc::now()) } else { None }; + let transaction_info = TransactionInfo { + recipient: *recipient, + amount, + new_stake_account_address: new_stake_account_address.cloned(), + finalized_date, + transaction: transaction.clone(), + }; + let signature = transaction.signatures[0]; + db.set(&signature.to_string(), &transaction_info)?; + Ok(()) +} + +// Set the finalized bit in the database if the transaction is rooted. +// Remove the TransactionInfo from the database if the transaction failed. +// Return the number of confirmations on the transaction or None if finalized. +pub fn update_finalized_transaction( + db: &mut PickleDb, + signature: &Signature, + opt_transaction_status: Option, + blockhash: &Hash, + recent_blockhashes: &[Hash], +) -> Result, Error> { + if opt_transaction_status.is_none() { + if !recent_blockhashes.contains(blockhash) { + eprintln!("Signature not found {} and blockhash expired", signature); + eprintln!("Discarding transaction record"); + db.rem(&signature.to_string())?; + return Ok(None); + } + + // Return zero to signal the transaction may still be in flight. + return Ok(Some(0)); + } + let transaction_status = opt_transaction_status.unwrap(); + + if let Some(confirmations) = transaction_status.confirmations { + // The transaction was found but is not yet finalized. + return Ok(Some(confirmations)); + } + + if let Err(e) = &transaction_status.status { + // The transaction was finalized, but execution failed. Drop it. + eprintln!( + "Error in transaction with signature {}: {}", + signature, + e.to_string() + ); + eprintln!("Discarding transaction record"); + db.rem(&signature.to_string())?; + return Ok(None); + } + + // Transaction is rooted. Set finalized in the database. + let mut transaction_info = db.get::(&signature.to_string()).unwrap(); + transaction_info.finalized_date = Some(Utc::now()); + db.set(&signature.to_string(), &transaction_info)?; + Ok(None) +} + +#[cfg(test)] +mod tests { + use super::*; + use csv::{ReaderBuilder, Trim}; + use solana_sdk::transaction::TransactionError; + use tempfile::NamedTempFile; + + #[test] + fn test_sort_transaction_infos_finalized_first() { + let info0 = TransactionInfo { + finalized_date: Some(Utc.ymd(2014, 7, 8).and_hms(9, 10, 11)), + ..TransactionInfo::default() + }; + let info1 = TransactionInfo { + finalized_date: Some(Utc.ymd(2014, 7, 8).and_hms(9, 10, 42)), + ..TransactionInfo::default() + }; + let info2 = TransactionInfo::default(); + let info3 = TransactionInfo { + recipient: Pubkey::new_rand(), + ..TransactionInfo::default() + }; + + // Sorted first by date + assert_eq!(compare_transaction_infos(&info0, &info1), Ordering::Less); + + // Finalized transactions should be before unfinalized ones + assert_eq!(compare_transaction_infos(&info1, &info2), Ordering::Less); + + // Then sorted by recipient + assert_eq!(compare_transaction_infos(&info2, &info3), Ordering::Less); + } + + #[test] + fn test_write_transaction_log() { + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + + let csv_file = NamedTempFile::new().unwrap(); + write_transaction_log(&db, &csv_file).unwrap(); + + let mut rdr = ReaderBuilder::new().trim(Trim::All).from_reader(csv_file); + let signed_infos: Vec = + rdr.deserialize().map(|entry| entry.unwrap()).collect(); + + let signed_info = SignedTransactionInfo { + recipient: Pubkey::default().to_string(), + signature: Signature::default().to_string(), + ..SignedTransactionInfo::default() + }; + assert_eq!(signed_infos, vec![signed_info]); + } + + #[test] + fn test_update_finalized_transaction_not_landed() { + // Keep waiting for a transaction that hasn't landed yet. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let blockhash = Hash::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + assert!(matches!( + update_finalized_transaction(&mut db, &signature, None, &blockhash, &[blockhash]) + .unwrap(), + Some(0) + )); + + // Unchanged + assert_eq!( + db.get::(&signature.to_string()).unwrap(), + transaction_info + ); + + // Same as before, but now with an expired blockhash + assert_eq!( + update_finalized_transaction(&mut db, &signature, None, &blockhash, &[]).unwrap(), + None + ); + + // Ensure TransactionInfo has been purged. + assert_eq!(db.get::(&signature.to_string()), None); + } + + #[test] + fn test_update_finalized_transaction_confirming() { + // Keep waiting for a transaction that is still being confirmed. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let blockhash = Hash::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + let transaction_status = TransactionStatus { + slot: 0, + confirmations: Some(1), + status: Ok(()), + err: None, + }; + assert_eq!( + update_finalized_transaction( + &mut db, + &signature, + Some(transaction_status), + &blockhash, + &[blockhash] + ) + .unwrap(), + Some(1) + ); + + // Unchanged + assert_eq!( + db.get::(&signature.to_string()).unwrap(), + transaction_info + ); + } + + #[test] + fn test_update_finalized_transaction_failed() { + // Don't wait if the transaction failed to execute. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let blockhash = Hash::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + let status = Err(TransactionError::AccountNotFound); + let transaction_status = TransactionStatus { + slot: 0, + confirmations: None, + status, + err: None, + }; + assert_eq!( + update_finalized_transaction( + &mut db, + &signature, + Some(transaction_status), + &blockhash, + &[blockhash] + ) + .unwrap(), + None + ); + + // Ensure TransactionInfo has been purged. + assert_eq!(db.get::(&signature.to_string()), None); + } + + #[test] + fn test_update_finalized_transaction_finalized() { + // Don't wait once the transaction has been finalized. + let mut db = + PickleDb::new_yaml(NamedTempFile::new().unwrap(), PickleDbDumpPolicy::NeverDump); + let signature = Signature::default(); + let blockhash = Hash::default(); + let transaction_info = TransactionInfo::default(); + db.set(&signature.to_string(), &transaction_info).unwrap(); + let transaction_status = TransactionStatus { + slot: 0, + confirmations: None, + status: Ok(()), + err: None, + }; + assert_eq!( + update_finalized_transaction( + &mut db, + &signature, + Some(transaction_status), + &blockhash, + &[blockhash] + ) + .unwrap(), + None + ); + + assert!(db + .get::(&signature.to_string()) + .unwrap() + .finalized_date + .is_some()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 8a5ab44ea2c842..f955230c8ceb81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod arg_parser; pub mod args; +pub mod commands; +mod db; pub mod thin_client; -pub mod tokens; diff --git a/src/main.rs b/src/main.rs index 379ae648211313..3ea9db57ddc8c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,8 +4,8 @@ use solana_client::rpc_client::RpcClient; use solana_tokens::{ arg_parser::parse_args, args::{resolve_command, Command}, + commands, thin_client::ThinClient, - tokens, }; use std::env; use std::error::Error; @@ -30,14 +30,14 @@ fn main() -> Result<(), Box> { match resolve_command(command_args.command)? { Command::DistributeTokens(args) => { let thin_client = ThinClient::new(client, args.dry_run); - tokens::process_distribute_tokens(&thin_client, &args)?; + commands::process_distribute_tokens(&thin_client, &args)?; } Command::Balances(args) => { let thin_client = ThinClient::new(client, false); - tokens::process_balances(&thin_client, &args)?; + commands::process_balances(&thin_client, &args)?; } Command::TransactionLog(args) => { - tokens::process_transaction_log(&args)?; + commands::process_transaction_log(&args)?; } } Ok(()) diff --git a/tests/tokens.rs b/tests/commands.rs similarity index 90% rename from tests/tokens.rs rename to tests/commands.rs index b23c38cc3567b6..3bdab39c4420dd 100644 --- a/tests/tokens.rs +++ b/tests/commands.rs @@ -1,7 +1,7 @@ use solana_client::rpc_client::RpcClient; use solana_core::validator::{TestValidator, TestValidatorOptions}; use solana_sdk::native_token::sol_to_lamports; -use solana_tokens::tokens::test_process_distribute_tokens_with_client; +use solana_tokens::commands::test_process_distribute_tokens_with_client; use std::fs::remove_dir_all; #[test] From ca5faf4d626234b1c45613769190d7468933d77d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 17:18:27 -0600 Subject: [PATCH 67/71] Add solana-tokens to build --- Cargo.lock | 56 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + tokens/Cargo.toml | 20 +++++++-------- tokens/src/commands.rs | 2 +- tokens/src/db.rs | 2 +- 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2829294b6e4e5..d5529b423e98eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1358,6 +1358,12 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "half" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" + [[package]] name = "hash32" version = "0.1.1" @@ -2572,6 +2578,19 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pickledb" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9161694d67f6c5163519d42be942ae36bbdb55f439460144f105bc4f9f7d1d61" +dependencies = [ + "bincode", + "serde", + "serde_cbor", + "serde_json", + "serde_yaml", +] + [[package]] name = "pin-project" version = "0.4.9" @@ -3427,6 +3446,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.110" @@ -4826,6 +4855,33 @@ dependencies = [ "users", ] +[[package]] +name = "solana-tokens" +version = "1.2.0" +dependencies = [ + "chrono", + "clap", + "console 0.10.3", + "csv", + "dirs 2.0.2", + "indexmap", + "indicatif", + "itertools 0.9.0", + "pickledb", + "serde", + "solana-clap-utils", + "solana-cli-config", + "solana-client", + "solana-core", + "solana-remote-wallet", + "solana-runtime", + "solana-sdk", + "solana-stake-program", + "solana-transaction-status", + "tempfile", + "thiserror", +] + [[package]] name = "solana-transaction-status" version = "1.2.0" diff --git a/Cargo.toml b/Cargo.toml index ee3147b4a8e573..61389a8afb95af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ members = [ "stake-accounts", "stake-monitor", "sys-tuner", + "tokens", "transaction-status", "upload-perf", "net-utils", diff --git a/tokens/Cargo.toml b/tokens/Cargo.toml index 0d092f424b2baa..1cbbc4a4c3f85d 100644 --- a/tokens/Cargo.toml +++ b/tokens/Cargo.toml @@ -3,7 +3,7 @@ name = "solana-tokens" description = "Blockchain, Rebuilt for Scale" authors = ["Solana Maintainers "] edition = "2018" -version = "0.1.3" +version = "1.2.0" repository = "https://github.com/solana-labs/solana" license = "Apache-2.0" homepage = "https://solana.com/" @@ -19,16 +19,16 @@ indicatif = "0.14.0" itertools = "0.9.0" pickledb = "0.4.1" serde = { version = "1.0", features = ["derive"] } -solana-clap-utils = "1.1.12" -solana-cli-config = "1.1.12" -solana-client = "1.1.12" -solana-remote-wallet = "1.1.12" -solana-runtime = "1.1.12" -solana-sdk = "1.1.12" -solana-stake-program = "1.1.12" -solana-transaction-status = "1.1.12" +solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } +solana-cli-config = { path = "../cli-config", version = "1.2.0" } +solana-client = { path = "../client", version = "1.2.0" } +solana-remote-wallet = { path = "../remote-wallet", version = "1.2.0" } +solana-runtime = { path = "../runtime", version = "1.2.0" } +solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-stake-program = { path = "../programs/stake", version = "1.2.0" } +solana-transaction-status = { path = "../transaction-status", version = "1.2.0" } tempfile = "3.1.0" thiserror = "1.0" [dev-dependencies] -solana-core = "1.1.12" +solana-core = { path = "../core", version = "1.2.0" } diff --git a/tokens/src/commands.rs b/tokens/src/commands.rs index 5517ab5887e211..efae68bdeb27ca 100644 --- a/tokens/src/commands.rs +++ b/tokens/src/commands.rs @@ -676,7 +676,7 @@ mod tests { amount: 1.0, new_stake_account_address: None, finalized_date: None, - transaction: Transaction::new_unsigned_instructions(vec![]), + transaction: Transaction::new_unsigned_instructions(&[]), }]; apply_previous_transactions(&mut allocations, &transaction_infos); assert_eq!(allocations.len(), 1); diff --git a/tokens/src/db.rs b/tokens/src/db.rs index 442f888927a8c9..66f96a8423bb2c 100644 --- a/tokens/src/db.rs +++ b/tokens/src/db.rs @@ -25,7 +25,7 @@ struct SignedTransactionInfo { impl Default for TransactionInfo { fn default() -> Self { - let mut transaction = Transaction::new_unsigned_instructions(vec![]); + let mut transaction = Transaction::new_unsigned_instructions(&[]); transaction.signatures.push(Signature::default()); Self { recipient: Pubkey::default(), From b9d27e67d2ce0ce9806d11a7587609018897adaf Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 17:27:34 -0600 Subject: [PATCH 68/71] Remove Cargo.lock --- tokens/Cargo.lock | 4361 --------------------------------------------- 1 file changed, 4361 deletions(-) delete mode 100644 tokens/Cargo.lock diff --git a/tokens/Cargo.lock b/tokens/Cargo.lock deleted file mode 100644 index 8eff663b749914..00000000000000 --- a/tokens/Cargo.lock +++ /dev/null @@ -1,4361 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "adler32" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" - -[[package]] -name = "aho-corasick" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi 0.3.8", -] - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - -[[package]] -name = "ascii" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" - -[[package]] -name = "assert_matches" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - -[[package]] -name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" - -[[package]] -name = "backtrace" -version = "0.3.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" -dependencies = [ - "backtrace-sys", - "cfg-if", - "libc", - "rustc-demangle", - "serde", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "base32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" - -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - -[[package]] -name = "bincode" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" -dependencies = [ - "byteorder", - "serde", -] - -[[package]] -name = "bindgen" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb26d6a69a335b8cb0e7c7e9775cd5666611dc50a37177c3f2cedcfc040e8c8" -dependencies = [ - "bitflags", - "cexpr", - "cfg-if", - "clang-sys", - "clap", - "env_logger", - "lazy_static", - "lazycell", - "log 0.4.8", - "peeking_take_while", - "proc-macro2 1.0.10", - "quote 1.0.1", - "regex", - "rustc-hash", - "shlex", - "which", -] - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "blake2b_simd" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.3", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "bs58" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" - -[[package]] -name = "bstr" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" - -[[package]] -name = "bv" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" -dependencies = [ - "feature-probe", - "serde", -] - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "either", - "iovec", -] - -[[package]] -name = "bytes" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" - -[[package]] -name = "bzip2" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.8+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05305b41c5034ff0e93937ac64133d109b5a2660114ec45e9760bc6816d83038" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "cc" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e" -dependencies = [ - "jobserver", - "num_cpus", -] - -[[package]] -name = "cexpr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "chrono" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" -dependencies = [ - "num-integer", - "num-traits", - "serde", - "time", -] - -[[package]] -name = "clang-sys" -version = "0.29.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "2.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "clear_on_drop" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" -dependencies = [ - "cc", -] - -[[package]] -name = "clicolors-control" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" -dependencies = [ - "atty", - "lazy_static", - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - -[[package]] -name = "combine" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1645a65a99c7c8d345761f4b75a6ffe5be3b3b27a93ee731fccc5050ba6be97c" -dependencies = [ - "ascii", - "byteorder", -] - -[[package]] -name = "console" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586208b33573b7f76ccfbe5adb076394c88deaf81b84d7213969805b0a952a7" -dependencies = [ - "clicolors-control", - "encode_unicode", - "lazy_static", - "libc", - "regex", - "terminal_size", - "termios", - "unicode-width", - "winapi 0.3.8", -] - -[[package]] -name = "console" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0f3e2e8d7dba335e913b97f9e1992c86c4399d54f8be1d31c8727d0652064" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "regex", - "terminal_size", - "termios", - "unicode-width", - "winapi 0.3.8", - "winapi-util", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - -[[package]] -name = "core_affinity" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8a03115cc34fb0d7c321dd154a3914b3ca082ccc5c11d91bf7117dbbe7171f" -dependencies = [ - "kernel32-sys", - "libc", - "num_cpus", - "winapi 0.2.8", -] - -[[package]] -name = "crc32fast" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" -dependencies = [ - "crossbeam-utils", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg 1.0.0", - "cfg-if", - "crossbeam-utils", - "lazy_static", - "maybe-uninit", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg 1.0.0", - "cfg-if", - "lazy_static", -] - -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -dependencies = [ - "generic-array 0.12.3", - "subtle 1.0.0", -] - -[[package]] -name = "csv" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" -dependencies = [ - "bstr", - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "ct-logs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" -dependencies = [ - "sct", -] - -[[package]] -name = "curve25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "subtle 2.2.2", - "zeroize", -] - -[[package]] -name = "dialoguer" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b5eb0fce3c4f955b8d8d864b131fb8863959138da962026c106ba7a2e3bf7a" -dependencies = [ - "console 0.10.3", - "lazy_static", - "tempfile", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.3", -] - -[[package]] -name = "dir-diff" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2860407d7d7e2e004bb2128510ad9e8d669e76fa005ccf567977b5d71b8b4a0b" -dependencies = [ - "walkdir", -] - -[[package]] -name = "dirs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -dependencies = [ - "cfg-if", - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -dependencies = [ - "cfg-if", - "libc", - "redox_users", - "winapi 0.3.8", -] - -[[package]] -name = "dlopen" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" -dependencies = [ - "dlopen_derive", - "lazy_static", - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "dlopen_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" -dependencies = [ - "libc", - "quote 0.6.13", - "syn 0.15.44", -] - -[[package]] -name = "dtoa" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" - -[[package]] -name = "ed25519-dalek" -version = "1.0.0-pre.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978710b352437433c97b2bff193f2fb1dfd58a093f863dd95e225a19baa599a2" -dependencies = [ - "clear_on_drop", - "curve25519-dalek", - "rand 0.7.3", - "serde", - "sha2", -] - -[[package]] -name = "either" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime", - "log 0.4.8", - "regex", - "termcolor", -] - -[[package]] -name = "failure" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", - "synstructure", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "fast-math" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2465292146cdfc2011350fe3b1c616ac83cf0faeedb33463ba1c332ed8948d66" -dependencies = [ - "ieee754", -] - -[[package]] -name = "feature-probe" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" - -[[package]] -name = "filetime" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi 0.3.8", -] - -[[package]] -name = "flate2" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" -dependencies = [ - "cfg-if", - "crc32fast", - "libc", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "fs_extra" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" - -[[package]] -name = "futures-channel" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" - -[[package]] -name = "futures-macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "futures-sink" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" - -[[package]] -name = "futures-task" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" - -[[package]] -name = "futures-util" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" -dependencies = [ - "futures-core", - "futures-io", - "futures-macro", - "futures-task", - "memchr", - "pin-utils", - "proc-macro-hack", - "proc-macro-nested", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" -dependencies = [ - "serde", - "typenum", -] - -[[package]] -name = "gethostname" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "getrandom" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "globset" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log 0.4.8", - "regex", -] - -[[package]] -name = "goblin" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884" -dependencies = [ - "log 0.4.8", - "plain", - "scroll", -] - -[[package]] -name = "h2" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "fnv", - "futures", - "http 0.1.21", - "indexmap", - "log 0.4.8", - "slab", - "string", - "tokio-io", -] - -[[package]] -name = "h2" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42" -dependencies = [ - "bytes 0.5.4", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.1", - "indexmap", - "log 0.4.8", - "slab", - "tokio 0.2.18", - "tokio-util", -] - -[[package]] -name = "half" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36b5f248235f45773d4944f555f83ea61fe07b18b561ccf99d7483d7381e54d" - -[[package]] -name = "hash32" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hermit-abi" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" - -[[package]] -name = "hidapi" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e347988010cd7d98689c553ab3d32f53e62cabb0d876aed16d41a8f9c1760e54" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "hmac" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -dependencies = [ - "bytes 0.4.12", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" -dependencies = [ - "bytes 0.5.4", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -dependencies = [ - "bytes 0.4.12", - "futures", - "http 0.1.21", - "tokio-buf", -] - -[[package]] -name = "http-body" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" -dependencies = [ - "bytes 0.5.4", - "http 0.2.1", -] - -[[package]] -name = "httparse" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" - -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime 0.2.6", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase 1.4.2", - "url 1.7.2", -] - -[[package]] -name = "hyper" -version = "0.12.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -dependencies = [ - "bytes 0.4.12", - "futures", - "futures-cpupool", - "h2 0.1.26", - "http 0.1.21", - "http-body 0.1.0", - "httparse", - "iovec", - "itoa", - "log 0.4.8", - "net2", - "rustc_version", - "time", - "tokio 0.1.22", - "tokio-buf", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "want 0.2.0", -] - -[[package]] -name = "hyper" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" -dependencies = [ - "bytes 0.5.4", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.2.4", - "http 0.2.1", - "http-body 0.3.1", - "httparse", - "itoa", - "log 0.4.8", - "net2", - "pin-project", - "time", - "tokio 0.2.18", - "tower-service", - "want 0.3.0", -] - -[[package]] -name = "hyper-rustls" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac965ea399ec3a25ac7d13b8affd4b8f39325cca00858ddf5eb29b79e6b14b08" -dependencies = [ - "bytes 0.5.4", - "ct-logs", - "futures-util", - "hyper 0.13.5", - "log 0.4.8", - "rustls", - "rustls-native-certs", - "tokio 0.2.18", - "tokio-rustls", - "webpki", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "ieee754" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9007da9cacbd3e6343da136e98b0d2df013f553d35bdec8b518f07bea768e19c" - -[[package]] -name = "indexed" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d480125acf340d6a6e59dab69ae19d6fca3a906e1eade277671272cc8f73794b" - -[[package]] -name = "indexmap" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" -dependencies = [ - "autocfg 1.0.0", -] - -[[package]] -name = "indicatif" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a68371cf417889c9d7f98235b7102ea7c54fc59bcbd22f3dea785be9d27e40" -dependencies = [ - "console 0.11.2", - "lazy_static", - "number_prefix", - "regex", -] - -[[package]] -name = "input_buffer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" -dependencies = [ - "bytes 0.5.4", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" - -[[package]] -name = "jemalloc-ctl" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7" -dependencies = [ - "jemalloc-sys", - "libc", - "paste", -] - -[[package]] -name = "jemalloc-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" -dependencies = [ - "cc", - "fs_extra", - "libc", -] - -[[package]] -name = "jemallocator" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69" -dependencies = [ - "jemalloc-sys", - "libc", -] - -[[package]] -name = "jobserver" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonrpc-client-transports" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2307a7e78cf969759e390a8a2151ea12e783849a45bb00aa871b468ba58ea79e" -dependencies = [ - "failure", - "futures", - "jsonrpc-core", - "jsonrpc-pubsub", - "log 0.4.8", - "serde", - "serde_json", - "tokio 0.1.22", - "url 1.7.2", - "websocket", -] - -[[package]] -name = "jsonrpc-core" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25525f6002338fb4debb5167a89a0b47f727a5a48418417545ad3429758b7fec" -dependencies = [ - "futures", - "log 0.4.8", - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "jsonrpc-core-client" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f9382e831a6d630c658df103aac3f971da096deb57c136ea2b760d3b4e3f9f" -dependencies = [ - "jsonrpc-client-transports", -] - -[[package]] -name = "jsonrpc-derive" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d386855ea963193689078018f46f9f39e06acda14c10d396e153cfd728fc690c" -dependencies = [ - "proc-macro-crate", - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "jsonrpc-http-server" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52860f0549694aa4abb12766856f56952ab46d3fb9f0815131b2db3d9cc2f29" -dependencies = [ - "hyper 0.12.35", - "jsonrpc-core", - "jsonrpc-server-utils", - "log 0.4.8", - "net2", - "parking_lot 0.10.2", - "unicase 2.6.0", -] - -[[package]] -name = "jsonrpc-pubsub" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ca5e391d6c6a2261d4adca029f427fe63ea546ad6cef2957c654c08495ec16" -dependencies = [ - "jsonrpc-core", - "log 0.4.8", - "parking_lot 0.10.2", - "serde", -] - -[[package]] -name = "jsonrpc-server-utils" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f06add502b48351e05dd95814835327fb115e4e9f834ca42fd522d3b769d4d2" -dependencies = [ - "bytes 0.4.12", - "globset", - "jsonrpc-core", - "lazy_static", - "log 0.4.8", - "tokio 0.1.22", - "tokio-codec", - "unicase 2.6.0", -] - -[[package]] -name = "jsonrpc-ws-server" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017a7dd5083d9ed62c5e1dd3e317975c33c3115dac5447f4480fe05a8c354754" -dependencies = [ - "jsonrpc-core", - "jsonrpc-server-utils", - "log 0.4.8", - "parking_lot 0.10.2", - "slab", - "ws", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] - -[[package]] -name = "lazycell" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" - -[[package]] -name = "libc" -version = "0.2.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" - -[[package]] -name = "libloading" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" -dependencies = [ - "cc", - "winapi 0.3.8", -] - -[[package]] -name = "librocksdb-sys" -version = "6.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883213ae3d09bfc3d104aefe94b25ebb183b6f4d3a515b23b14817e1f4854005" -dependencies = [ - "bindgen", - "cc", - "glob", - "libc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" - -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.8", -] - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "memoffset" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" -dependencies = [ - "autocfg 1.0.0", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "mime_guess" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" -dependencies = [ - "mime 0.3.16", - "unicase 2.6.0", -] - -[[package]] -name = "miniz_oxide" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" -dependencies = [ - "adler32", -] - -[[package]] -name = "mio" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" -dependencies = [ - "cfg-if", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log 0.4.8", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log 0.4.8", - "mio", - "slab", -] - -[[package]] -name = "mio-uds" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -dependencies = [ - "iovec", - "libc", - "mio", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "native-tls" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" -dependencies = [ - "lazy_static", - "libc", - "log 0.4.8", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "net2" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -dependencies = [ - "cfg-if", - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "nix" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" -dependencies = [ - "bitflags", - "cc", - "cfg-if", - "libc", - "void", -] - -[[package]] -name = "nom" -version = "5.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" -dependencies = [ - "memchr", - "version_check 0.9.1", -] - -[[package]] -name = "num-derive" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", -] - -[[package]] -name = "num-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "num-integer" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -dependencies = [ - "autocfg 1.0.0", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -dependencies = [ - "autocfg 1.0.0", -] - -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "number_prefix" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" - -[[package]] -name = "once_cell" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" -dependencies = [ - "parking_lot 0.9.0", -] - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "openssl" -version = "0.10.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "lazy_static", - "libc", - "openssl-sys", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" - -[[package]] -name = "openssl-sys" -version = "0.9.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8" -dependencies = [ - "autocfg 1.0.0", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api", - "parking_lot_core 0.6.2", - "rustc_version", -] - -[[package]] -name = "parking_lot" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api", - "parking_lot_core 0.7.2", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if", - "cloudabi", - "libc", - "redox_syscall", - "rustc_version", - "smallvec 0.6.13", - "winapi 0.3.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -dependencies = [ - "cfg-if", - "cloudabi", - "libc", - "redox_syscall", - "smallvec 1.4.0", - "winapi 0.3.8", -] - -[[package]] -name = "paste" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4fb1930692d1b6a9cfabdde3d06ea0a7d186518e2f4d67660d8970e2fa647a" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "pbkdf2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -dependencies = [ - "byteorder", - "crypto-mac", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pickledb" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9161694d67f6c5163519d42be942ae36bbdb55f439460144f105bc4f9f7d1d61" -dependencies = [ - "bincode", - "serde", - "serde_cbor", - "serde_json", - "serde_yaml", -] - -[[package]] -name = "pin-project" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" - -[[package]] -name = "proc-macro-crate" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" - -[[package]] -name = "proc-macro-nested" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] - -[[package]] -name = "proc-macro2" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" -dependencies = [ - "unicode-xid 0.2.0", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - -[[package]] -name = "quote" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d77c41ca8767f2f41394c11a4eebccab83da25e7cc035387a3125f02be90a3" -dependencies = [ - "proc-macro2 1.0.10", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.7", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi 0.3.8", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi 0.3.8", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi 0.3.8", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rayon" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" -dependencies = [ - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - -[[package]] -name = "redox_users" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" -dependencies = [ - "getrandom", - "redox_syscall", - "rust-argon2", -] - -[[package]] -name = "regex" -version = "1.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-automata" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -dependencies = [ - "byteorder", -] - -[[package]] -name = "regex-syntax" -version = "0.6.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" - -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -dependencies = [ - "winapi 0.3.8", -] - -[[package]] -name = "reqwest" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2" -dependencies = [ - "base64 0.11.0", - "bytes 0.5.4", - "encoding_rs", - "futures-core", - "futures-util", - "http 0.2.1", - "http-body 0.3.1", - "hyper 0.13.5", - "hyper-rustls", - "js-sys", - "lazy_static", - "log 0.4.8", - "mime 0.3.16", - "mime_guess", - "percent-encoding 2.1.0", - "pin-project-lite", - "rustls", - "serde", - "serde_json", - "serde_urlencoded", - "time", - "tokio 0.2.18", - "tokio-rustls", - "url 2.1.1", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "ring" -version = "0.16.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" -dependencies = [ - "cc", - "lazy_static", - "libc", - "spin", - "untrusted", - "web-sys", - "winapi 0.3.8", -] - -[[package]] -name = "rocksdb" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61aa17a99a2413cd71c1106691bf59dad7de0cd5099127f90e9d99c429c40d4a" -dependencies = [ - "libc", - "librocksdb-sys", -] - -[[package]] -name = "rpassword" -version = "4.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "rust-argon2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" -dependencies = [ - "base64 0.11.0", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "rustls" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" -dependencies = [ - "base64 0.11.0", - "log 0.4.8", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls-native-certs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" -dependencies = [ - "openssl-probe", - "rustls", - "schannel", - "security-framework", -] - -[[package]] -name = "ryu" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" -dependencies = [ - "lazy_static", - "winapi 0.3.8", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scroll" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "sct" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "security-framework" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f331b9025654145cd425b9ded0caf8f5ae0df80d418b326e2dc1c3dc5eb0620" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a073952621257820e7a3469f55ba4726d8b28657e7e36653d1c36dc2c84ae" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_cbor" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "serde_json" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" -dependencies = [ - "dtoa", - "itoa", - "serde", - "url 2.1.1", -] - -[[package]] -name = "serde_yaml" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" -dependencies = [ - "dtoa", - "linked-hash-map", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", -] - -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" - -[[package]] -name = "sha2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" -dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", -] - -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" - -[[package]] -name = "smallvec" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -dependencies = [ - "maybe-uninit", -] - -[[package]] -name = "smallvec" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" - -[[package]] -name = "socket2" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi 0.3.8", -] - -[[package]] -name = "solana-archiver-utils" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af16337f68249126755ed915faa3be8a43484703ad28d904d256c47c801d1835" -dependencies = [ - "log 0.4.8", - "rand 0.7.3", - "solana-chacha", - "solana-chacha-sys", - "solana-ledger", - "solana-logger", - "solana-perf", - "solana-sdk", -] - -[[package]] -name = "solana-bpf-loader-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065a3c4ff081a43fd716b2d98431920cbd0fc5bec254d1dbfa46c9acea248bd" -dependencies = [ - "bincode", - "byteorder", - "libc", - "log 0.4.8", - "num-derive 0.3.0", - "num-traits", - "solana-logger", - "solana-sdk", - "solana_rbpf", - "thiserror", -] - -[[package]] -name = "solana-budget-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bf766c14fcef01ef47a113e51861955adbf4ac7e4c174161f170ef3a7010b0" -dependencies = [ - "bincode", - "chrono", - "log 0.4.8", - "num-derive 0.3.0", - "num-traits", - "serde", - "serde_derive", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-chacha" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765b4d45c4399c779a3b480e9b7d620eb36b765f878d0bb49cb125f53430efcb" -dependencies = [ - "log 0.4.8", - "rand 0.7.3", - "rand_chacha 0.2.2", - "solana-chacha-sys", - "solana-ledger", - "solana-logger", - "solana-perf", - "solana-sdk", -] - -[[package]] -name = "solana-chacha-cuda" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3721a9c794c662527144293cf18b4174063c798a59d1b7637d52959819898de2" -dependencies = [ - "log 0.4.8", - "solana-archiver-utils", - "solana-chacha", - "solana-ledger", - "solana-logger", - "solana-perf", - "solana-sdk", -] - -[[package]] -name = "solana-chacha-sys" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9deae46160e7df6d0330e402917187298690d0fa9cba7236b27962d43cb82fa9" -dependencies = [ - "cc", -] - -[[package]] -name = "solana-clap-utils" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4347a772749876a4d2e52132e786765e2d69d5e5a3f55868ad0418775222c265" -dependencies = [ - "chrono", - "clap", - "rpassword", - "solana-remote-wallet", - "solana-sdk", - "thiserror", - "tiny-bip39", - "url 2.1.1", -] - -[[package]] -name = "solana-cli-config" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37d4bf33d9d7f5a4cc94cbc27cea45366e64a771b0688df5018072df6eabe1a" -dependencies = [ - "dirs", - "lazy_static", - "serde", - "serde_derive", - "serde_yaml", - "url 2.1.1", -] - -[[package]] -name = "solana-client" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ef535a3634219bc22397da24c1bf65d596e9169c085cefcd8f7cef14406d57" -dependencies = [ - "bincode", - "bs58", - "indicatif", - "jsonrpc-core", - "log 0.4.8", - "rayon", - "reqwest", - "serde", - "serde_derive", - "serde_json", - "solana-net-utils", - "solana-sdk", - "solana-transaction-status", - "solana-vote-program", - "thiserror", - "tungstenite", - "url 2.1.1", -] - -[[package]] -name = "solana-config-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11c4846b9ac4db511cac9d63d03bfd4926a1eb19e1a8a7b66cf4574ad28721b" -dependencies = [ - "bincode", - "chrono", - "log 0.4.8", - "serde", - "serde_derive", - "solana-sdk", -] - -[[package]] -name = "solana-core" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487f8eec5f526f53679b9c2ee41cda57fdc50ec0096fc2673970e747b5b0c055" -dependencies = [ - "bincode", - "bs58", - "bv", - "byteorder", - "chrono", - "core_affinity", - "crossbeam-channel", - "ed25519-dalek", - "flate2", - "fs_extra", - "indexmap", - "itertools", - "jsonrpc-core", - "jsonrpc-core-client", - "jsonrpc-derive", - "jsonrpc-http-server", - "jsonrpc-pubsub", - "jsonrpc-ws-server", - "log 0.4.8", - "num-traits", - "num_cpus", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "solana-bpf-loader-program", - "solana-budget-program", - "solana-chacha-cuda", - "solana-clap-utils", - "solana-client", - "solana-faucet", - "solana-ledger", - "solana-logger", - "solana-measure", - "solana-merkle-tree", - "solana-metrics", - "solana-net-utils", - "solana-perf", - "solana-rayon-threadlimit", - "solana-runtime", - "solana-sdk", - "solana-stake-program", - "solana-storage-program", - "solana-streamer", - "solana-sys-tuner", - "solana-transaction-status", - "solana-version", - "solana-vote-program", - "solana-vote-signer", - "tempfile", - "thiserror", - "tokio 0.1.22", - "tokio-codec", - "tokio-fs", - "tokio-io", - "trees", -] - -[[package]] -name = "solana-crate-features" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2343b3f37b45e7d1183ad21a0feeac0ac216ee065f5df81e1709af5145653d3" -dependencies = [ - "backtrace", - "bytes 0.4.12", - "cc", - "curve25519-dalek", - "ed25519-dalek", - "either", - "failure", - "lazy_static", - "libc", - "rand_chacha 0.2.2", - "regex-syntax", - "reqwest", - "serde", - "syn 0.15.44", - "syn 1.0.18", - "tokio 0.1.22", - "winapi 0.3.8", -] - -[[package]] -name = "solana-exchange-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1627dd1764c0d274b3281827a75b575253f79ed58aa8ed65f9e52548c42c5e" -dependencies = [ - "bincode", - "log 0.4.8", - "num-derive 0.3.0", - "num-traits", - "serde", - "serde_derive", - "solana-logger", - "solana-metrics", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-faucet" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1158994709fc61eff8b26cdf69fbedb11f3e82f0271e6fa23523e18e84d727" -dependencies = [ - "bincode", - "byteorder", - "bytes 0.4.12", - "clap", - "log 0.4.8", - "serde", - "serde_derive", - "solana-clap-utils", - "solana-logger", - "solana-metrics", - "solana-sdk", - "tokio 0.1.22", - "tokio-codec", -] - -[[package]] -name = "solana-genesis-programs" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187f4468de794aa4f4ca267b0113bad9db4d049a63cc00c31eac8ef6b7c2a61c" -dependencies = [ - "log 0.4.8", - "solana-bpf-loader-program", - "solana-budget-program", - "solana-exchange-program", - "solana-runtime", - "solana-sdk", - "solana-storage-program", - "solana-vest-program", -] - -[[package]] -name = "solana-ledger" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b49bb91c0d53c60a759f2c2eb2403228622cd7e49fdc3cf42213605b3473ead" -dependencies = [ - "bincode", - "byteorder", - "bzip2", - "chrono", - "crossbeam-channel", - "dir-diff", - "ed25519-dalek", - "fs_extra", - "itertools", - "lazy_static", - "libc", - "log 0.4.8", - "num_cpus", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rayon", - "regex", - "rocksdb", - "serde", - "serde_bytes", - "sha2", - "solana-genesis-programs", - "solana-logger", - "solana-measure", - "solana-merkle-tree", - "solana-metrics", - "solana-perf", - "solana-rayon-threadlimit", - "solana-reed-solomon-erasure", - "solana-runtime", - "solana-sdk", - "solana-stake-program", - "solana-transaction-status", - "solana-vote-program", - "symlink", - "tar", - "tempfile", - "thiserror", -] - -[[package]] -name = "solana-logger" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4b26cb13817ba92e36a05c792f2f4e551b1c7e5cb17744da47677dc653cee4e" -dependencies = [ - "env_logger", - "lazy_static", - "log 0.4.8", -] - -[[package]] -name = "solana-measure" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4c2bf2a8a742192b50c05d5066fffaf9a802f254ec235ccb1d622e82f40ea92" -dependencies = [ - "jemalloc-ctl", - "jemallocator", - "log 0.4.8", - "solana-metrics", - "solana-sdk", -] - -[[package]] -name = "solana-merkle-tree" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f450d84d4a879b7a4000f5a6c6220cc32e021bd63d2563ef0d8eb514758782" -dependencies = [ - "fast-math", - "solana-sdk", -] - -[[package]] -name = "solana-metrics" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11f79a745e16128f6afff361037184afcc7a693eba25ccf4a632f7df26d8e24" -dependencies = [ - "env_logger", - "gethostname", - "lazy_static", - "log 0.4.8", - "reqwest", - "solana-sdk", -] - -[[package]] -name = "solana-net-utils" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2597713f8619f02d2574d8e3e41bb5a4c39abfb3c466777a79c91fdb0f017815" -dependencies = [ - "bincode", - "bytes 0.4.12", - "clap", - "log 0.4.8", - "nix", - "rand 0.7.3", - "serde", - "serde_derive", - "socket2", - "solana-clap-utils", - "solana-logger", - "tokio 0.1.22", - "tokio-codec", -] - -[[package]] -name = "solana-perf" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b210d1ce14719194a0e7a71221c5a52569e878ad1fe863020d2717244342c40" -dependencies = [ - "bincode", - "dlopen", - "dlopen_derive", - "lazy_static", - "log 0.4.8", - "rand 0.7.3", - "rayon", - "serde", - "solana-budget-program", - "solana-logger", - "solana-metrics", - "solana-rayon-threadlimit", - "solana-sdk", -] - -[[package]] -name = "solana-rayon-threadlimit" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa6a81840be99cba2285dca3c8320fc0845daf7fe02effc4f44e42eff51b334" -dependencies = [ - "lazy_static", - "num_cpus", -] - -[[package]] -name = "solana-reed-solomon-erasure" -version = "4.0.1-3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5b3ab3f4dd12af687a7d0d0ee73299cbc06ed3aada42dccac26fe243e73399e" -dependencies = [ - "cc", - "libc", - "smallvec 0.6.13", -] - -[[package]] -name = "solana-remote-wallet" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1281efae0e72833a45c4cd8eefaed2578a715a537b8ea6386cf99f730afb5e4f" -dependencies = [ - "base32", - "console 0.10.3", - "dialoguer", - "hidapi", - "log 0.4.8", - "parking_lot 0.10.2", - "semver", - "solana-sdk", - "thiserror", - "url 2.1.1", -] - -[[package]] -name = "solana-runtime" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbb9a560caefe24636c54437f2d882ef8d46dec73e44d2ea69b1b007f36b3a2" -dependencies = [ - "bincode", - "bv", - "byteorder", - "fnv", - "fs_extra", - "itertools", - "lazy_static", - "libc", - "libloading", - "log 0.4.8", - "memmap", - "num-derive 0.3.0", - "num-traits", - "num_cpus", - "rand 0.7.3", - "rayon", - "serde", - "serde_derive", - "solana-bpf-loader-program", - "solana-config-program", - "solana-logger", - "solana-measure", - "solana-metrics", - "solana-rayon-threadlimit", - "solana-sdk", - "solana-stake-program", - "solana-storage-program", - "solana-vote-program", - "tempfile", - "thiserror", -] - -[[package]] -name = "solana-sdk" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "860fd85a4e481e2f79bdf73418cbe9cc1e8281a828bb8dc16be18da881675ca2" -dependencies = [ - "assert_matches", - "bincode", - "bs58", - "bv", - "byteorder", - "chrono", - "ed25519-dalek", - "generic-array 0.13.2", - "hex", - "hmac", - "itertools", - "log 0.4.8", - "memmap", - "num-derive 0.3.0", - "num-traits", - "pbkdf2", - "rand 0.7.3", - "rand_chacha 0.2.2", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "sha2", - "solana-crate-features", - "solana-logger", - "solana-sdk-macro", - "thiserror", -] - -[[package]] -name = "solana-sdk-macro" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7dc08359c1db017aff7663cfc899305e50c6fb9d99ec8a17c7b5fc9398baab" -dependencies = [ - "bs58", - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "solana-stake-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f59076b27386284822a25e97ed5a21cc9e8ccb8ddc1b9cc13076f803b0c3c0" -dependencies = [ - "bincode", - "log 0.4.8", - "num-derive 0.3.0", - "num-traits", - "serde", - "serde_derive", - "solana-config-program", - "solana-metrics", - "solana-sdk", - "solana-vote-program", - "thiserror", -] - -[[package]] -name = "solana-storage-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a6793775b57efc9e7925e3f640d47d1526402704687976ce09d00ae2a2f4f6c" -dependencies = [ - "bincode", - "log 0.4.8", - "num-derive 0.3.0", - "num-traits", - "rand 0.7.3", - "serde", - "serde_derive", - "solana-logger", - "solana-sdk", -] - -[[package]] -name = "solana-streamer" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca0feb653d6e2f7e7f89487e79b15c5b257f7e89ed1325f24f517d1a86f8049" -dependencies = [ - "libc", - "log 0.4.8", - "nix", - "solana-logger", - "solana-measure", - "solana-metrics", - "solana-perf", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-sys-tuner" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d8299687d5ebc21b91a84b0255c36cbfa9b0de26c2088684317d21e0d4e6c7" -dependencies = [ - "clap", - "libc", - "log 0.4.8", - "nix", - "solana-clap-utils", - "solana-logger", - "sysctl", - "unix_socket2", - "users", -] - -[[package]] -name = "solana-tokens" -version = "0.1.3" -dependencies = [ - "chrono", - "clap", - "console 0.10.3", - "csv", - "dirs", - "indexmap", - "indicatif", - "itertools", - "pickledb", - "serde", - "solana-clap-utils", - "solana-cli-config", - "solana-client", - "solana-core", - "solana-remote-wallet", - "solana-runtime", - "solana-sdk", - "solana-stake-program", - "solana-transaction-status", - "tempfile", - "thiserror", -] - -[[package]] -name = "solana-transaction-status" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbaa0428020e55c8fa79ad53a7f836e45dcb855dc1c7614287fe3d92e6c8017" -dependencies = [ - "bincode", - "bs58", - "serde", - "serde_derive", - "solana-sdk", -] - -[[package]] -name = "solana-version" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a658f1a9c1308fc05245b42a7fddf18208ec80d892bc84a087200cd024581" -dependencies = [ - "serde", - "serde_derive", - "solana-sdk", -] - -[[package]] -name = "solana-vest-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ea744b51f354c09f277888a8398d0382a07cf00a6ecbf3b47779e380cfb462" -dependencies = [ - "bincode", - "chrono", - "num-derive 0.2.5", - "num-traits", - "serde", - "serde_derive", - "solana-config-program", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-vote-program" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d63f784f6b03528ede5911fe577878625b1172a7a6b39cd5f9d27c7c8afd604" -dependencies = [ - "bincode", - "log 0.4.8", - "num-derive 0.3.0", - "num-traits", - "serde", - "serde_derive", - "solana-metrics", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-vote-signer" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab52fbedb798628414f66b8f65e52912038f436c49b722c43a3d5d40afd031fd" -dependencies = [ - "clap", - "jsonrpc-core", - "jsonrpc-derive", - "jsonrpc-http-server", - "log 0.4.8", - "serde_json", - "solana-clap-utils", - "solana-metrics", - "solana-sdk", -] - -[[package]] -name = "solana_rbpf" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7baa2550500e75413f031f239fe0c4da2d477ae1b1ff7cb671eba483f963d91" -dependencies = [ - "byteorder", - "combine", - "goblin", - "hash32", - "libc", - "log 0.4.8", - "rand 0.7.3", - "scroll", - "thiserror", - "time", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "string" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -dependencies = [ - "bytes 0.4.12", -] - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - -[[package]] -name = "subtle" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" - -[[package]] -name = "symlink" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - -[[package]] -name = "syn" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "unicode-xid 0.2.0", -] - -[[package]] -name = "synstructure" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", - "unicode-xid 0.2.0", -] - -[[package]] -name = "sysctl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0501f0d0c2aa64b419abff97c209f4b82c4e67caa63e8dc5b222ecc1b574cb5c" -dependencies = [ - "bitflags", - "byteorder", - "failure", - "libc", - "walkdir", -] - -[[package]] -name = "tar" -version = "0.4.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3196bfbffbba3e57481b6ea32249fbaf590396a52505a2615adbb79d9d826d3" -dependencies = [ - "filetime", - "libc", - "redox_syscall", - "xattr", -] - -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -dependencies = [ - "cfg-if", - "libc", - "rand 0.7.3", - "redox_syscall", - "remove_dir_all", - "winapi 0.3.8", -] - -[[package]] -name = "termcolor" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "terminal_size" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8038f95fc7a6f351163f4b964af631bd26c9e828f7db085f2a84aca56f70d13b" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "termios" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2" -dependencies = [ - "libc", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", -] - -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "tiny-bip39" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" -dependencies = [ - "failure", - "hmac", - "once_cell", - "pbkdf2", - "rand 0.7.3", - "rustc-hash", - "sha2", - "unicode-normalization", -] - -[[package]] -name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures", - "mio", - "num_cpus", - "tokio-codec", - "tokio-current-thread", - "tokio-executor", - "tokio-fs", - "tokio-io", - "tokio-reactor", - "tokio-sync", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "tokio-udp", - "tokio-uds", -] - -[[package]] -name = "tokio" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713" -dependencies = [ - "bytes 0.5.4", - "fnv", - "futures-core", - "iovec", - "lazy_static", - "memchr", - "mio", - "num_cpus", - "pin-project-lite", - "slab", -] - -[[package]] -name = "tokio-buf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -dependencies = [ - "bytes 0.4.12", - "either", - "futures", -] - -[[package]] -name = "tokio-codec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -dependencies = [ - "bytes 0.4.12", - "futures", - "tokio-io", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -dependencies = [ - "futures", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils", - "futures", -] - -[[package]] -name = "tokio-fs" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -dependencies = [ - "futures", - "tokio-io", - "tokio-threadpool", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures", - "log 0.4.8", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils", - "futures", - "lazy_static", - "log 0.4.8", - "mio", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", -] - -[[package]] -name = "tokio-rustls" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" -dependencies = [ - "futures-core", - "rustls", - "tokio 0.2.18", - "webpki", -] - -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures", - "iovec", - "mio", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils", - "futures", - "lazy_static", - "log 0.4.8", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils", - "futures", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-tls" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -dependencies = [ - "futures", - "native-tls", - "tokio-io", -] - -[[package]] -name = "tokio-udp" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -dependencies = [ - "bytes 0.4.12", - "futures", - "log 0.4.8", - "mio", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-uds" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" -dependencies = [ - "bytes 0.4.12", - "futures", - "iovec", - "libc", - "log 0.4.8", - "mio", - "mio-uds", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -dependencies = [ - "bytes 0.5.4", - "futures-core", - "futures-sink", - "log 0.4.8", - "pin-project-lite", - "tokio 0.2.18", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -dependencies = [ - "serde", -] - -[[package]] -name = "tower-service" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - -[[package]] -name = "trees" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa1821e85be4f56cc5bd08bdbc32c0e26d105c90bed9c637992f6c7f747c180" -dependencies = [ - "indexed", -] - -[[package]] -name = "try-lock" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" - -[[package]] -name = "tungstenite" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" -dependencies = [ - "base64 0.11.0", - "byteorder", - "bytes 0.5.4", - "http 0.2.1", - "httparse", - "input_buffer", - "log 0.4.8", - "native-tls", - "rand 0.7.3", - "sha-1", - "url 2.1.1", - "utf-8", -] - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check 0.9.1", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -dependencies = [ - "smallvec 1.4.0", -] - -[[package]] -name = "unicode-width" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" - -[[package]] -name = "unix_socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57c6eace16c00eccb98a28e85db3370eab0685bdd5e13831d59e2bcb49a1d8a" -dependencies = [ - "libc", -] - -[[package]] -name = "untrusted" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - -[[package]] -name = "url" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -dependencies = [ - "idna 0.2.0", - "matches", - "percent-encoding 2.1.0", -] - -[[package]] -name = "users" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c72f4267aea0c3ec6d07eaabea6ead7c5ddacfafc5e22bcf8d186706851fb4cf" -dependencies = [ - "libc", -] - -[[package]] -name = "utf-8" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" - -[[package]] -name = "vcpkg" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" - -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - -[[package]] -name = "version_check" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "walkdir" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -dependencies = [ - "same-file", - "winapi 0.3.8", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -dependencies = [ - "futures", - "log 0.4.8", - "try-lock", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log 0.4.8", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasm-bindgen" -version = "0.2.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" -dependencies = [ - "cfg-if", - "serde", - "serde_json", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" -dependencies = [ - "bumpalo", - "lazy_static", - "log 0.4.8", - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" -dependencies = [ - "quote 1.0.1", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" -dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.1", - "syn 1.0.18", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" - -[[package]] -name = "web-sys" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" -dependencies = [ - "webpki", -] - -[[package]] -name = "websocket" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413b37840b9e27b340ce91b319ede10731de8c72f5bc4cb0206ec1ca4ce581d0" -dependencies = [ - "bytes 0.4.12", - "futures", - "hyper 0.10.16", - "native-tls", - "rand 0.6.5", - "tokio-codec", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-tls", - "unicase 1.4.2", - "url 1.7.2", - "websocket-base", -] - -[[package]] -name = "websocket-base" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3810f0d00c4dccb54c30a4eee815e703232819dec7b007db115791c42aa374" -dependencies = [ - "base64 0.10.1", - "bitflags", - "byteorder", - "bytes 0.4.12", - "futures", - "native-tls", - "rand 0.6.5", - "sha1", - "tokio-codec", - "tokio-io", - "tokio-tcp", - "tokio-tls", -] - -[[package]] -name = "which" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" -dependencies = [ - "libc", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.8", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "winreg" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -dependencies = [ - "winapi 0.3.8", -] - -[[package]] -name = "ws" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "httparse", - "log 0.4.8", - "mio", - "mio-extras", - "rand 0.7.3", - "sha-1", - "slab", - "url 2.1.1", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "xattr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -dependencies = [ - "libc", -] - -[[package]] -name = "yaml-rust" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "zeroize" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" From 07bcaac3df7424f72a61648b5dd293406d226f3d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 17:28:20 -0600 Subject: [PATCH 69/71] Remove vscode file --- tokens/.vscode/launch.json | 83 -------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 tokens/.vscode/launch.json diff --git a/tokens/.vscode/launch.json b/tokens/.vscode/launch.json deleted file mode 100644 index b740a4ee4e3905..00000000000000 --- a/tokens/.vscode/launch.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug unit tests in library 'solana-tokens'", - "cargo": { - "args": [ - "test", - "--no-run", - "--lib", - "--package=solana-tokens" - ], - "filter": { - "name": "solana-tokens", - "kind": "lib" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug executable 'solana-tokens'", - "cargo": { - "args": [ - "build", - "--bin=solana-tokens", - "--package=solana-tokens" - ], - "filter": { - "name": "solana-tokens", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug unit tests in executable 'solana-tokens'", - "cargo": { - "args": [ - "test", - "--no-run", - "--bin=solana-tokens", - "--package=solana-tokens" - ], - "filter": { - "name": "solana-tokens", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug integration test 'tokens'", - "cargo": { - "args": [ - "test", - "--no-run", - "--test=tokens", - "--package=solana-tokens" - ], - "filter": { - "name": "tokens", - "kind": "test" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - } - ] -} \ No newline at end of file From 89118411c26082e25dea69a2f758533f6c9eef96 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 17:28:52 -0600 Subject: [PATCH 70/71] Remove TravisCI build script --- tokens/.travis.yml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 tokens/.travis.yml diff --git a/tokens/.travis.yml b/tokens/.travis.yml deleted file mode 100644 index cba263c127543c..00000000000000 --- a/tokens/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: rust -addons: - apt: - packages: - - pkg-config - - libudev-dev - update: true From 7f0e1266890dceb9f3182251af3638339e700a70 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 12 May 2020 20:38:20 -0600 Subject: [PATCH 71/71] Install solana-tokens --- scripts/cargo-install-all.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/cargo-install-all.sh b/scripts/cargo-install-all.sh index 02fb81f7a40fc3..9ce5115963ce6a 100755 --- a/scripts/cargo-install-all.sh +++ b/scripts/cargo-install-all.sh @@ -67,6 +67,7 @@ if [[ $CI_OS_NAME = windows ]]; then solana-install-init solana-keygen solana-stake-accounts + solana-tokens ) else ./fetch-perf-libs.sh @@ -100,6 +101,7 @@ else solana-stake-accounts solana-stake-monitor solana-sys-tuner + solana-tokens solana-validator solana-watchtower )