Node scaffold (#16)

This commit is contained in:
Armani Ferrante 2020-10-08 11:32:23 -07:00 committed by GitHub
parent 50693e0a4c
commit e65766dd00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 1178 additions and 47 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
bin/
bin/*
dex/target
crank/target
.idea*

480
Cargo.lock generated
View File

@ -204,6 +204,15 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
[[package]]
name = "bstr"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"
dependencies = [
"memchr",
]
[[package]]
name = "buf_redux"
version = "0.8.4"
@ -809,6 +818,7 @@ checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -831,6 +841,27 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
[[package]]
name = "futures-cpupool"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
dependencies = [
"futures 0.1.29",
"num_cpus",
]
[[package]]
name = "futures-executor"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.5"
@ -870,6 +901,8 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
dependencies = [
"futures 0.1.29",
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
@ -930,6 +963,37 @@ version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
[[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",
"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 0.1.29",
"http 0.1.21",
"indexmap",
"log",
"slab",
"string",
"tokio-io",
]
[[package]]
name = "h2"
version = "0.2.6"
@ -941,7 +1005,7 @@ dependencies = [
"futures-core",
"futures-sink",
"futures-util",
"http",
"http 0.2.1",
"indexmap",
"slab",
"tokio 0.2.22",
@ -965,7 +1029,7 @@ dependencies = [
"bitflags",
"bytes 0.5.6",
"headers-core",
"http",
"http 0.2.1",
"mime",
"sha-1 0.8.2",
"time",
@ -977,7 +1041,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
dependencies = [
"http",
"http 0.2.1",
]
[[package]]
@ -1025,6 +1089,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"
@ -1036,6 +1111,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 0.1.29",
"http 0.1.21",
"tokio-buf",
]
[[package]]
name = "http-body"
version = "0.3.1"
@ -1043,7 +1130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
dependencies = [
"bytes 0.5.6",
"http",
"http 0.2.1",
]
[[package]]
@ -1061,6 +1148,36 @@ dependencies = [
"quick-error",
]
[[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 0.1.29",
"futures-cpupool",
"h2 0.1.26",
"http 0.1.21",
"http-body 0.1.0",
"httparse",
"iovec",
"itoa",
"log",
"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.7"
@ -1071,9 +1188,9 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"h2 0.2.6",
"http 0.2.1",
"http-body 0.3.1",
"httparse",
"itoa",
"pin-project",
@ -1082,7 +1199,7 @@ dependencies = [
"tokio 0.2.22",
"tower-service",
"tracing",
"want",
"want 0.3.0",
]
[[package]]
@ -1093,7 +1210,7 @@ checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6"
dependencies = [
"bytes 0.5.6",
"futures-util",
"hyper",
"hyper 0.13.7",
"log",
"rustls",
"tokio 0.2.22",
@ -1101,6 +1218,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"
@ -1197,6 +1325,22 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "jsonrpc-client-transports"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f7b1cdf66312002e15682a24430728bd13036c641163c016bc53fb686a7c2d"
dependencies = [
"failure",
"futures 0.1.29",
"jsonrpc-core 15.0.0",
"jsonrpc-pubsub",
"log",
"serde",
"serde_json",
"url 1.7.2",
]
[[package]]
name = "jsonrpc-core"
version = "14.2.0"
@ -1210,6 +1354,84 @@ dependencies = [
"serde_json",
]
[[package]]
name = "jsonrpc-core"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b12567a31d48588a65b6cf870081e6ba1d7b2ae353977cb9820d512e69c70"
dependencies = [
"futures 0.1.29",
"log",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "jsonrpc-core-client"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d175ca0cf77439b5495612bf216c650807d252d665b4b70ab2eebd895a88fac1"
dependencies = [
"jsonrpc-client-transports",
]
[[package]]
name = "jsonrpc-derive"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2cc6ea7f785232d9ca8786a44e9fa698f92149dcdc1acc4aa1fc69c4993d79e"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.21",
"quote 1.0.7",
"syn 1.0.40",
]
[[package]]
name = "jsonrpc-http-server"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9996b26c0c7a59626d0ed6c5ec8bf06218e62ce1474bd2849f9b9fd38a0158c0"
dependencies = [
"hyper 0.12.35",
"jsonrpc-core 15.0.0",
"jsonrpc-server-utils",
"log",
"net2",
"parking_lot 0.10.2",
"unicase",
]
[[package]]
name = "jsonrpc-pubsub"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f389c5cd1f3db258a99296892c21047e21ae73ff4c0e2d39650ea86fe994b4c7"
dependencies = [
"jsonrpc-core 15.0.0",
"log",
"parking_lot 0.10.2",
"rand 0.7.3",
"serde",
]
[[package]]
name = "jsonrpc-server-utils"
version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c623e1895d0d9110cb0ea7736cfff13191ff52335ad33b21bd5c775ea98b27af"
dependencies = [
"bytes 0.4.12",
"globset",
"jsonrpc-core 15.0.0",
"lazy_static",
"log",
"tokio 0.1.22",
"tokio-codec",
"unicase",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@ -1687,6 +1909,12 @@ dependencies = [
"crypto-mac",
]
[[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"
@ -2055,7 +2283,7 @@ dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
"thread_local 1.0.1",
]
[[package]]
@ -2084,9 +2312,9 @@ dependencies = [
"encoding_rs",
"futures-core",
"futures-util",
"http",
"http-body",
"hyper",
"http 0.2.1",
"http-body 0.3.1",
"hyper 0.13.7",
"hyper-rustls",
"ipnet",
"js-sys",
@ -2094,7 +2322,7 @@ dependencies = [
"log",
"mime",
"mime_guess",
"percent-encoding",
"percent-encoding 2.1.0",
"pin-project-lite",
"rustls",
"serde",
@ -2102,7 +2330,7 @@ dependencies = [
"serde_urlencoded",
"tokio 0.2.22",
"tokio-rustls",
"url",
"url 2.1.1",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
@ -2335,7 +2563,7 @@ dependencies = [
"dtoa",
"itoa",
"serde",
"url",
"url 2.1.1",
]
[[package]]
@ -2360,6 +2588,94 @@ dependencies = [
"solana-client-gen",
]
[[package]]
name = "serum-node"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 3.0.0-beta.2",
"crossbeam",
"futures 0.3.5",
"serum-common",
"serum-node-context",
"serum-node-crank",
"serum-node-json-rpc",
"serum-node-logging",
"serum-node-registry",
"tokio 0.2.22",
]
[[package]]
name = "serum-node-context"
version = "0.1.0"
dependencies = [
"clap 3.0.0-beta.2",
"serum-common",
]
[[package]]
name = "serum-node-crank"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 3.0.0-beta.2",
"crank",
"crossbeam",
"futures 0.3.5",
"serde",
"serum-node-context",
"serum-node-logging",
"solana-sdk",
"tokio 0.2.22",
]
[[package]]
name = "serum-node-json-rpc"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 3.0.0-beta.2",
"futures 0.3.5",
"jsonrpc-core 15.0.0",
"jsonrpc-core-client",
"jsonrpc-derive",
"jsonrpc-http-server",
"num_enum",
"serum-node-crank",
"serum-node-logging",
"serum-node-registry",
"thiserror",
"tokio 0.2.22",
]
[[package]]
name = "serum-node-logging"
version = "0.1.0"
dependencies = [
"clap 3.0.0-beta.2",
"lazy_static",
"slog 2.5.2",
"slog-async",
"slog-json",
"slog-stream",
"slog-term",
]
[[package]]
name = "serum-node-registry"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 3.0.0-beta.2",
"crossbeam",
"futures 0.3.5",
"serde",
"serum-node-context",
"serum-node-logging",
"solana-sdk",
"tokio 0.2.22",
]
[[package]]
name = "serum-registry"
version = "0.1.0"
@ -2473,6 +2789,12 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "slog"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07aa15818e194222ef5b814aec86d47da20d93360c068b2c5f5ef64d9347fbdf"
[[package]]
name = "slog"
version = "2.5.2"
@ -2486,9 +2808,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b3336ce47ce2f96673499fc07eb85e3472727b9a7a2959964b002c2ce8fbbb"
dependencies = [
"crossbeam-channel",
"slog",
"slog 2.5.2",
"take_mut",
"thread_local",
"thread_local 1.0.1",
]
[[package]]
name = "slog-extra"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "511581f4dd1dc90e4eca99b60be8a692d9c975e8757558aa774f16007d27492a"
dependencies = [
"slog 1.7.1",
"thread_local 0.3.6",
]
[[package]]
name = "slog-json"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a"
dependencies = [
"chrono",
"serde",
"serde_json",
"slog 2.5.2",
]
[[package]]
@ -2498,7 +2842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae939ed7d169eed9699f4f5cd440f046f5dc5dfc27c19e3cd311619594c175e0"
dependencies = [
"regex",
"slog",
"slog 2.5.2",
]
[[package]]
@ -2509,7 +2853,7 @@ checksum = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6"
dependencies = [
"arc-swap",
"lazy_static",
"slog",
"slog 2.5.2",
]
[[package]]
@ -2520,10 +2864,21 @@ checksum = "be4d87903baf655da2d82bc3ac3f7ef43868c58bf712b3a661fda72009304c23"
dependencies = [
"crossbeam",
"log",
"slog",
"slog 2.5.2",
"slog-scope",
]
[[package]]
name = "slog-stream"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fac4af71007ddb7338f771e059a46051f18d1454d8ac556f234a0573e719daa"
dependencies = [
"slog 1.7.1",
"slog-extra",
"thread_local 0.3.6",
]
[[package]]
name = "slog-term"
version = "2.6.0"
@ -2532,9 +2887,9 @@ checksum = "bab1d807cf71129b05ce36914e1dbb6fbfbdecaf686301cb457f4fa967f9f5b6"
dependencies = [
"atty",
"chrono",
"slog",
"slog 2.5.2",
"term",
"thread_local",
"thread_local 1.0.1",
]
[[package]]
@ -2547,7 +2902,7 @@ dependencies = [
"libflate",
"regex",
"serde",
"slog",
"slog 2.5.2",
"slog-async",
"slog-kvfilter",
"slog-scope",
@ -2619,7 +2974,7 @@ dependencies = [
"solana-sdk",
"thiserror",
"tiny-bip39",
"url",
"url 2.1.1",
]
[[package]]
@ -2631,7 +2986,7 @@ dependencies = [
"bincode",
"bs58",
"indicatif",
"jsonrpc-core",
"jsonrpc-core 14.2.0",
"log",
"rayon",
"reqwest",
@ -2645,7 +3000,7 @@ dependencies = [
"solana-vote-program",
"thiserror",
"tungstenite 0.10.1",
"url",
"url 2.1.1",
]
[[package]]
@ -2746,7 +3101,7 @@ dependencies = [
"solana-version",
"tokio 0.1.22",
"tokio-codec",
"url",
"url 2.1.1",
]
[[package]]
@ -2766,7 +3121,7 @@ dependencies = [
"semver",
"solana-sdk",
"thiserror",
"url",
"url 2.1.1",
]
[[package]]
@ -2949,6 +3304,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[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"
@ -3103,6 +3467,15 @@ dependencies = [
"syn 1.0.40",
]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
dependencies = [
"lazy_static",
]
[[package]]
name = "thread_local"
version = "1.0.1"
@ -3202,6 +3575,17 @@ dependencies = [
"winapi 0.3.9",
]
[[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 0.1.29",
]
[[package]]
name = "tokio-codec"
version = "0.1.2"
@ -3489,14 +3873,14 @@ dependencies = [
"base64 0.11.0",
"byteorder",
"bytes 0.5.6",
"http",
"http 0.2.1",
"httparse",
"input_buffer",
"log",
"native-tls",
"rand 0.7.3",
"sha-1 0.8.2",
"url",
"url 2.1.1",
"utf-8",
]
@ -3509,13 +3893,13 @@ dependencies = [
"base64 0.12.3",
"byteorder",
"bytes 0.5.6",
"http",
"http 0.2.1",
"httparse",
"input_buffer",
"log",
"rand 0.7.3",
"sha-1 0.9.1",
"url",
"url 2.1.1",
"utf-8",
]
@ -3591,15 +3975,26 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[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]]
@ -3638,6 +4033,17 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "want"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
dependencies = [
"futures 0.1.29",
"log",
"try-lock",
]
[[package]]
name = "want"
version = "0.3.0"
@ -3657,8 +4063,8 @@ dependencies = [
"bytes 0.5.6",
"futures 0.3.5",
"headers",
"http",
"hyper",
"http 0.2.1",
"hyper 0.13.7",
"log",
"mime",
"mime_guess",

View File

@ -6,9 +6,16 @@ members = [
"crank",
"safe",
"registry",
"node",
"node/json-rpc",
"node/logging",
"node/crank",
"node/registry",
"node/context",
]
exclude = [
"dex",
"registry/program",
"rewards/constant",
"safe/program",
]

View File

@ -3,7 +3,7 @@ use std::str::FromStr;
pub mod rpc;
#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum Cluster {
Testnet,
Mainnet,

View File

@ -3,7 +3,9 @@ name = "crank"
version = "0.2.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "crank"
path = "src/bin/main.rs"
[dependencies]
serum_dex = { path = "../dex", features = ["client"] }

8
crank/src/bin/main.rs Normal file
View File

@ -0,0 +1,8 @@
use anyhow::Result;
use clap::Clap;
use crank::Opts;
fn main() -> Result<()> {
let opts = Opts::parse();
crank::start(opts)
}

View File

@ -59,15 +59,15 @@ fn read_keypair_file(s: &str) -> Result<Keypair> {
}
#[derive(Clap, Debug)]
struct Opts {
pub struct Opts {
#[clap(default_value = "mainnet")]
cluster: Cluster,
pub cluster: Cluster,
#[clap(subcommand)]
command: Command,
pub command: Command,
}
#[derive(Clap, Debug)]
enum Command {
pub enum Command {
Genesis {
#[clap(long, short)]
payer: String,
@ -198,9 +198,7 @@ impl Opts {
}
}
fn main() -> Result<()> {
let opts = Opts::parse();
pub fn start(opts: Opts) -> Result<()> {
let client = opts.client();
match opts.command {

29
node/Cargo.toml Normal file
View File

@ -0,0 +1,29 @@
[package]
name = "serum-node"
version = "0.1.0"
description = "Serum Node"
repository = "https://github.com/project-serum/serum-dex"
edition = "2018"
[[bin]]
name = "serum-node"
path = "src/bin/main.rs"
[features]
trace = ["serum-node-logging/trace"]
default = []
strict = []
rpc = []
[dependencies]
serum-common = { path = "../common" }
serum-node-json-rpc = { path = "./json-rpc" }
serum-node-logging = { path = "./logging" }
serum-node-crank = { path = "./crank" }
serum-node-registry = { path = "./registry" }
serum-node-context = { path = "./context" }
tokio = { version = "0.2.22", features = ["sync"] }
futures = "0.3"
anyhow = "1.0.32"
crossbeam = "0.7.3"
clap = "3.0.0-beta.1"

10
node/context/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "serum-node-context"
version = "0.1.0"
description = "Serum Node Context"
repository = "https://github.com/project-serum/serum-dex"
edition = "2018"
[dependencies]
serum-common = { path = "../../common" }
clap = "3.0.0-beta.1"

13
node/context/src/lib.rs Normal file
View File

@ -0,0 +1,13 @@
use clap::Clap;
use serum_common::client::Cluster;
#[derive(Clone, Debug, Clap)]
pub struct Context {
/// Solana cluster to communicate with.
#[clap(long, default_value = "localnet")]
pub cluster: Cluster,
/// Path to the node's wallet [optional].
#[clap(long)]
pub wallet: Option<String>,
}

18
node/crank/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "serum-node-crank"
version = "0.1.0"
description = "Serum Node Crank"
repository = "https://github.com/project-serum/serum-dex"
edition = "2018"
[dependencies]
serum-node-logging = { path = "../logging" }
serum-node-context = { path = "../context" }
crank = { path = "../../crank", version = "0.2" }
solana-sdk = "1.3.9"
tokio = "0.2.22"
futures = "0.3"
anyhow = "1.0.32"
serde = { version = "1.0", features = ["derive"] }
crossbeam = "0.7.3"
clap = "3.0.0-beta.1"

11
node/crank/src/api.rs Normal file
View File

@ -0,0 +1,11 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
pub fn health() -> Result<HealthResponse> {
Ok(HealthResponse { ok: true })
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HealthResponse {
pub ok: bool,
}

View File

@ -0,0 +1,47 @@
use crate::api::{self, HealthResponse};
use anyhow::Result;
use crossbeam::sync::WaitGroup;
use futures::channel::{mpsc, oneshot};
use futures::future;
use futures::StreamExt;
use serde::{Deserialize, Serialize};
use serum_node_logging::{error, info};
pub async fn dispatch(rpc_recv: Receiver, start_wg: WaitGroup) {
let logger = serum_node_logging::get_logger("crank");
info!(logger, "Starting crank api dispatch");
drop(start_wg);
rpc_recv
.for_each(
move |(req, resp_ch): (Request, oneshot::Sender<Result<Response>>)| {
info!(logger, "Dispatch request {:?}", req);
let resp = {
match req {
Request::Health => api::health().map(|r| Response::Health(r)),
}
};
if let Err(e) = resp_ch.send(resp) {
error!(logger, "Unable to send api response: {:?}", e);
}
future::ready(())
},
)
.await;
}
pub type Sender = mpsc::Sender<(Request, oneshot::Sender<Result<Response>>)>;
pub type Receiver = mpsc::Receiver<(Request, oneshot::Sender<Result<Response>>)>;
#[derive(Debug)]
pub enum Request {
Health,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum Response {
Health(HealthResponse),
}

37
node/crank/src/lib.rs Normal file
View File

@ -0,0 +1,37 @@
extern crate crank as serum_crank;
use anyhow::Result;
use crossbeam::sync::WaitGroup;
use serum_node_context::Context;
use tokio::runtime::{Builder, Runtime};
mod api;
mod dispatch;
// Re-export.
pub use api::HealthResponse;
pub use dispatch::*;
pub use serum_crank::Command;
pub struct StartRequest {
pub rpc: Receiver,
pub start_wg: WaitGroup,
}
pub fn start(req: StartRequest) -> Runtime {
let runtime = Builder::new()
.thread_name("crank")
.threaded_scheduler()
.enable_all()
.build()
.expect("Failed to start crank runtime.");
runtime.handle().spawn(dispatch(req.rpc, req.start_wg));
runtime
}
pub fn run_cmd(ctx: &Context, cmd: Command) -> Result<()> {
serum_crank::start(serum_crank::Opts {
cluster: ctx.cluster.clone(),
command: cmd,
})
}

21
node/json-rpc/Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "serum-node-json-rpc"
version = "0.1.0"
description = "Serum Node JSON RPC"
repository = "https://github.com/project-serum/serum-dex"
edition = "2018"
[dependencies]
serum-node-logging = { path = "../logging" }
serum-node-crank = { path = "../crank" }
serum-node-registry = { path = "../registry" }
jsonrpc-core = "15.0.0"
jsonrpc-derive = "15.0.0"
jsonrpc-http-server = "15.0.0"
jsonrpc-core-client = "15.0.0"
tokio = "0.2.22"
futures = { version = "0.3", features = ["compat"] }
anyhow = "1.0.32"
num_enum = "0.5.0"
thiserror = "1.0.20"
clap = "3.0.0-beta.1"

View File

@ -0,0 +1,109 @@
use crate::handlers::api_trait;
use crate::handlers::FutureResult;
use futures::channel::oneshot;
use futures::future::TryFutureExt;
use jsonrpc_core::Error as RpcError;
use serum_node_crank::{
HealthResponse as CrankHealthResponse, Request as CrankRequest, Response as CrankResponse,
};
use serum_node_logging::{trace, Logger};
use serum_node_registry::{
HealthResponse as RegistryHealthResponse, Request as RegistryRequest,
Response as RegistryResponse,
};
use std::convert::Into;
pub struct Api {
logger: Logger,
crank: serum_node_crank::Sender,
registry: serum_node_registry::Sender,
}
impl Api {
pub fn new(
logger: Logger,
crank: serum_node_crank::Sender,
registry: serum_node_registry::Sender,
) -> Self {
Self {
logger,
crank,
registry,
}
}
}
impl api_trait::Api for Api {
fn crank_health(&self) -> FutureResult<CrankHealthResponse> {
trace!(self.logger, "serum_startCrank");
// Send request to the crank.
let fut = {
let mut crank = self.crank.clone();
async move {
let (tx, rx) = oneshot::channel();
crank
.try_send((CrankRequest::Health, tx))
.map_err(Into::into)
.map_err(jsonrpc_error)?;
let resp = rx
.await
.map_err(Into::into)
.map_err(jsonrpc_error)?
.map_err(jsonrpc_error)?;
match resp {
CrankResponse::Health(r) => Ok(r),
}
}
};
// Convert to pre-async/await future.
let rpc_fut = Box::pin(fut).compat();
// Response.
Box::new(rpc_fut)
}
fn registry_health(&self) -> FutureResult<RegistryHealthResponse> {
trace!(self.logger, "serum_createEntity");
// Send request to the registry.
let fut = {
let mut registry = self.registry.clone();
async move {
let (tx, rx) = oneshot::channel();
registry
.try_send((RegistryRequest::Health, tx))
.map_err(Into::into)
.map_err(jsonrpc_error)?;
let resp = rx
.await
.map_err(Into::into)
.map_err(jsonrpc_error)?
.map_err(jsonrpc_error)?;
match resp {
RegistryResponse::Health(r) => Ok(r),
}
}
};
// Convert to pre-async/await future.
let rpc_fut = Box::pin(fut).compat();
// Response.
Box::new(rpc_fut)
}
}
/// Constructs a JSON-RPC error from a string message, with error code -32603.
pub fn jsonrpc_error(err: anyhow::Error) -> RpcError {
RpcError {
code: jsonrpc_core::ErrorCode::InternalError,
message: format!("{}", err),
data: None,
}
}

View File

@ -0,0 +1,14 @@
use crate::handlers::FutureResult;
use jsonrpc_derive::rpc;
use serum_node_crank::HealthResponse as CrankHealthResponse;
use serum_node_registry::HealthResponse as RegistryHealthResponse;
/// Api defines the JSON-RPC interface. Handlers must implement this trait.
#[rpc]
pub trait Api {
#[rpc(name = "serum_crankHealth")]
fn crank_health(&self) -> FutureResult<CrankHealthResponse>;
#[rpc(name = "serum_registryHealth")]
fn registry_health(&self) -> FutureResult<RegistryHealthResponse>;
}

View File

@ -0,0 +1,19 @@
use api::Api;
use api_trait::Api as ApiTrait;
use serum_node_logging::Logger;
mod api;
pub(crate) mod api_trait;
pub type FutureResult<T> =
Box<dyn jsonrpc_core::futures::Future<Item = T, Error = jsonrpc_core::Error> + Send>;
pub fn build(
logger: Logger,
crank: serum_node_crank::Sender,
registry: serum_node_registry::Sender,
) -> jsonrpc_core::IoHandler {
let mut io = jsonrpc_core::IoHandler::new();
io.extend_with(Api::new(logger, crank, registry).to_delegate());
io
}

41
node/json-rpc/src/lib.rs Normal file
View File

@ -0,0 +1,41 @@
use clap::Clap;
use jsonrpc_http_server::{Server, ServerBuilder};
use serum_node_logging::info;
mod handlers;
pub struct StartRequest {
pub cfg: Config,
pub crank: serum_node_crank::Sender,
pub registry: serum_node_registry::Sender,
}
#[derive(Debug, Clap)]
pub struct Config {
/// HTTP port for the JSON RPC server.
#[clap(long = "json.http.port", default_value = "8080")]
pub http_port: u16,
/// Number of threads for the JSON RPC server.
#[clap(long = "json.http.threads", default_value = "3")]
pub http_threads: u16,
}
pub fn start(req: StartRequest) -> JsonRpc {
let url = format!("127.0.0.1:{}", req.cfg.http_port);
let logger = serum_node_logging::get_logger("json-rpc");
info!(logger, "Starting JSON-RPC server at {}", url);
let handlers = handlers::build(logger, req.crank, req.registry);
let _server = ServerBuilder::new(handlers)
.threads(req.cfg.http_threads as usize)
.start_http(&url.parse().unwrap())
.unwrap();
JsonRpc { _server }
}
pub struct JsonRpc {
_server: Server,
}

19
node/logging/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "serum-node-logging"
version = "0.1.0"
description = "Serum Node Logging"
repository = "https://github.com/project-serum/serum-dex"
edition = "2018"
[features]
trace = ["slog/max_level_trace", "slog/release_max_level_warn"]
default = []
[dependencies]
slog = "2.5.2"
slog-term = "2"
slog-json = "2.3.0"
slog-async = "2"
slog-stream = "1.2.1"
lazy_static = "1.4.0"
clap = "3.0.0-beta.1"

62
node/logging/src/lib.rs Normal file
View File

@ -0,0 +1,62 @@
use clap::Clap;
use lazy_static::lazy_static;
use slog::{self, Drain};
use std::sync::Mutex;
pub use slog::{debug, error, info, trace, warn};
lazy_static! {
static ref LOGGER: Mutex<Option<slog::Logger>> = Mutex::new(None);
}
#[derive(Debug, Clap)]
pub struct Config {
/// Log level.
#[clap(long = "log.level", default_value = "info")]
pub level: String,
/// Log format.
#[clap(long = "log.format", default_value = "pretty")]
pub format: String,
}
pub type Logger = slog::Logger;
/// Start initializes the logger.
pub fn start(cfg: Config) {
let format_drain = match cfg.format.as_str() {
"json" => {
let drain = slog_json::Json::default(std::io::stderr()).fuse();
slog_async::Async::default(drain)
}
_ => {
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::FullFormat::new(decorator).build().fuse();
slog_async::Async::default(drain)
}
};
let level_drain = {
let level = match cfg.level.as_str() {
"trace" => slog::Level::Trace,
"debug" => slog::Level::Debug,
"info" => slog::Level::Info,
"warning" => slog::Level::Warning,
"error" => slog::Level::Error,
_ => slog::Level::Info,
};
slog::LevelFilter::new(format_drain, level).fuse()
};
LOGGER
.lock()
.unwrap()
.get_or_insert(slog::Logger::root(level_drain, slog::o!()));
}
/// `start` must be called before `get_logger`.
pub fn get_logger(module: &'static str) -> slog::Logger {
LOGGER
.lock()
.unwrap()
.as_ref()
.unwrap()
.new(slog::o!("module" => module))
}

17
node/registry/Cargo.toml Normal file
View File

@ -0,0 +1,17 @@
[package]
name = "serum-node-registry"
version = "0.1.0"
description = "Serum Node Registry"
repository = "https://github.com/project-serum/serum-dex"
edition = "2018"
[dependencies]
serum-node-logging = { path = "../logging" }
serum-node-context = { path = "../context" }
tokio = "0.2.22"
futures = "0.3"
anyhow = "1.0.32"
serde = { version = "1.0", features = ["derive"] }
solana-sdk = { version = "=1.3.9", default-features = false }
crossbeam = "0.7.3"
clap = "3.0.0-beta.1"

11
node/registry/src/api.rs Normal file
View File

@ -0,0 +1,11 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
pub fn health() -> Result<HealthResponse> {
Ok(HealthResponse { ok: true })
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HealthResponse {
pub ok: bool,
}

View File

@ -0,0 +1,47 @@
use crate::api::{self, HealthResponse};
use anyhow::Result;
use crossbeam::sync::WaitGroup;
use futures::channel::{mpsc, oneshot};
use futures::future;
use futures::StreamExt;
use serde::{Deserialize, Serialize};
use serum_node_logging::{error, info};
pub(crate) async fn dispatch(rpc_recv: Receiver, start_wg: WaitGroup) {
let logger = serum_node_logging::get_logger("registry");
info!(logger, "Starting registry api dispatch");
drop(start_wg);
rpc_recv
.for_each(
move |(req, resp_chan): (Request, oneshot::Sender<Result<Response>>)| {
info!(logger, "Dispatch request {:?}", req);
let resp = {
match req {
Request::Health => api::health().map(|r| Response::Health(r)),
}
};
if let Err(e) = resp_chan.send(resp) {
error!(logger, "Unable to send api response: {:?}", e);
}
future::ready(())
},
)
.await;
}
pub type Sender = mpsc::Sender<(Request, oneshot::Sender<Result<Response>>)>;
pub type Receiver = mpsc::Receiver<(Request, oneshot::Sender<Result<Response>>)>;
#[derive(Debug)]
pub enum Request {
Health,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum Response {
Health(HealthResponse),
}

42
node/registry/src/lib.rs Normal file
View File

@ -0,0 +1,42 @@
//! serum-node-registry defines the internal registry node service.
use anyhow::Result;
use clap::Clap;
use crossbeam::sync::WaitGroup;
use serum_node_context::Context;
use solana_sdk::pubkey::Pubkey;
use tokio::runtime::{Builder, Runtime};
mod api;
mod dispatch;
pub use api::HealthResponse;
pub use dispatch::*;
#[derive(Debug, Clap)]
pub struct Command {
/// Program id of the deployed on-chain registry
#[clap(long = "program-id")]
pub program_id: Option<Pubkey>,
}
pub struct StartRequest {
pub rpc: Receiver,
pub start_wg: WaitGroup,
}
pub fn start(req: StartRequest) -> Runtime {
let runtime = Builder::new()
.thread_name("registry")
.threaded_scheduler()
.enable_all()
.build()
.expect("Failed to start registry runtime.");
runtime.handle().spawn(dispatch(req.rpc, req.start_wg));
runtime
}
pub fn run_cmd(_ctx: &Context, _cmd: Command) -> Result<()> {
// todo
Ok(())
}

8
node/src/bin/main.rs Normal file
View File

@ -0,0 +1,8 @@
use clap::Clap;
use serum_node::Config;
fn main() {
let cfg = Config::parse();
let handle = serum_node::start(cfg);
handle.park();
}

135
node/src/lib.rs Normal file
View File

@ -0,0 +1,135 @@
#![cfg_attr(feature = "strict", deny(warnings))]
use anyhow::Result;
use clap::Clap;
use crossbeam::sync::WaitGroup;
use futures::channel::mpsc;
use serum_node_context::Context;
use serum_node_logging::info;
use serum_node_logging::{error, trace};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::runtime::Runtime;
/// start is the entrypoint to running a node.
pub fn start(cfg: Config) -> Handle {
// Start logging.
serum_node_logging::start(cfg.logging);
let logger = serum_node_logging::get_logger("node");
// Start the services, if needed.
let _services = {
if !cfg.json {
None
} else {
info!(logger, "Node starting 🚀");
// Channels to relay requests from the RPC server to internal services.
let crank_chan_size = 4;
let (crank_sender, crank_receiver) = mpsc::channel(crank_chan_size);
let registry_chan_size = 1024;
let (registry_sender, registry_receiver) = mpsc::channel(registry_chan_size);
// Start JSON-RPC server.
let _json_rpc = serum_node_json_rpc::start(serum_node_json_rpc::StartRequest {
cfg: cfg.json_rpc,
crank: crank_sender,
registry: registry_sender,
});
info!(logger, "Starting internal api services");
// WaitGroup to block thread until all async services are ready.
let start_wg = WaitGroup::new();
// Start crank service.
let _crank = serum_node_crank::start(serum_node_crank::StartRequest {
rpc: crank_receiver,
start_wg: start_wg.clone(),
});
// Start registry service.
let _registry = serum_node_registry::start(serum_node_registry::StartRequest {
rpc: registry_receiver,
start_wg: start_wg.clone(),
});
start_wg.wait();
info!(logger, "Service setup complete");
Some(Services {
_json_rpc,
_crank,
_registry,
})
}
};
// Run the command, if given.
if let Some(cmd) = cfg.cmd {
trace!(logger, "Executing command: {:?}", cmd);
if let Err(e) = run_cmd(&cfg.context, cmd) {
error!(logger, "Command failed with error: {}", e.to_string());
std::process::exit(1);
}
}
Handle { _services }
}
fn run_cmd(ctx: &Context, cmd: Command) -> Result<()> {
match cmd {
Command::Crank(crank_cmd) => serum_node_crank::run_cmd(ctx, crank_cmd),
Command::Registry(reg_cmd) => serum_node_registry::run_cmd(ctx, reg_cmd),
}
}
#[derive(Debug, Clap)]
#[clap(name = "serum-node", about = "A Serum node")]
pub struct Config {
#[clap(flatten)]
pub logging: serum_node_logging::Config,
#[clap(flatten)]
pub json_rpc: serum_node_json_rpc::Config,
/// Enables the JSON RPC server if set. Defaults to off.
#[clap(long)]
pub json: bool,
#[clap(flatten)]
pub context: Context,
#[clap(subcommand)]
pub cmd: Option<Command>,
}
#[derive(Debug, Clap)]
pub enum Command {
/// Runs the crank client utility
Crank(serum_node_crank::Command),
/// Communicates with a Serum registry.
Registry(serum_node_registry::Command),
}
pub struct Handle {
_services: Option<Services>,
}
struct Services {
_json_rpc: serum_node_json_rpc::JsonRpc,
_crank: Runtime,
_registry: Runtime,
}
impl Handle {
pub fn park(&self) {
if self._services.is_some() {
let term = Arc::new(AtomicBool::new(false));
while !term.load(Ordering::Acquire) {
std::thread::park();
}
}
}
}