diff --git a/Cargo.lock b/Cargo.lock index 7c53cc712..3e398ad8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,24 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "aho-corasick" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -53,6 +71,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + [[package]] name = "bellman" version = "0.6.0" @@ -164,9 +188,20 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "chrono" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" +dependencies = [ + "num-integer", + "num-traits", + "time", +] [[package]] name = "constant_time_eq" @@ -181,11 +216,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" dependencies = [ "cfg-if", - "crossbeam-channel", + "crossbeam-channel 0.3.9", "crossbeam-deque", "crossbeam-epoch", "crossbeam-queue", - "crossbeam-utils", + "crossbeam-utils 0.6.6", ] [[package]] @@ -194,7 +229,17 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.6.6", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6" +dependencies = [ + "cfg-if", + "crossbeam-utils 0.7.2", ] [[package]] @@ -204,7 +249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" dependencies = [ "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-utils 0.6.6", ] [[package]] @@ -215,7 +260,7 @@ checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ "arrayvec", "cfg-if", - "crossbeam-utils", + "crossbeam-utils 0.6.6", "lazy_static", "memoffset", "scopeguard", @@ -227,7 +272,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.6.6", ] [[package]] @@ -240,6 +285,17 @@ dependencies = [ "lazy_static", ] +[[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 = "crunchy" version = "0.1.6" @@ -418,9 +474,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701" [[package]] name = "librustzcash" @@ -435,6 +491,10 @@ dependencies = [ "libc", "pairing", "rand_core", + "tracing", + "tracing-appender", + "tracing-core", + "tracing-subscriber", "zcash_history", "zcash_primitives", "zcash_proofs", @@ -449,6 +509,21 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + [[package]] name = "memoffset" version = "0.5.1" @@ -470,7 +545,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" dependencies = [ - "autocfg", + "autocfg 0.1.6", "num-integer", "num-traits", ] @@ -481,7 +556,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" dependencies = [ - "autocfg", + "autocfg 0.1.6", "num-traits", ] @@ -491,7 +566,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" dependencies = [ - "autocfg", + "autocfg 0.1.6", ] [[package]] @@ -595,6 +670,34 @@ dependencies = [ "rand_core", ] +[[package]] +name = "regex" +version = "1.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +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", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" + [[package]] name = "rustc_version" version = "0.2.3" @@ -657,6 +760,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sharded-slab" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e" +dependencies = [ + "lazy_static", +] + [[package]] name = "subtle" version = "2.2.3" @@ -694,6 +806,82 @@ dependencies = [ "syn", ] +[[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", +] + +[[package]] +name = "tracing" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178" +dependencies = [ + "cfg-if", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-appender" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aa52d56cc0d79ab604e8a022a1cebc4de33cf09dc9933c94353bea2e00d6e88" +dependencies = [ + "chrono", + "crossbeam-channel 0.4.3", + "tracing-subscriber", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "tracing-core", +] + [[package]] name = "typenum" version = "1.11.2" diff --git a/Cargo.toml b/Cargo.toml index 16b8615c9..ddb7e4d69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,19 @@ libc = "0.2" pairing = "0.16" lazy_static = "1" rand_core = "0.5.1" +tracing = "0.1" +tracing-core = "0.1" +tracing-appender = "0.1" zcash_history = "0.2" zcash_primitives = "0.2" zcash_proofs = "0.2" ed25519-zebra = "2.0.0" +[dependencies.tracing-subscriber] +version = "0.2" +default-features = false +features = ["ansi", "chrono", "env-filter"] + [profile.release] lto = true panic = 'abort' diff --git a/depends/packages/crate_aho_corasick.mk b/depends/packages/crate_aho_corasick.mk new file mode 100644 index 000000000..03cbc8996 --- /dev/null +++ b/depends/packages/crate_aho_corasick.mk @@ -0,0 +1,15 @@ +package=crate_aho_corasick +$(package)_crate_name=aho-corasick +$(package)_version=0.7.13 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_ansi_term.mk b/depends/packages/crate_ansi_term.mk new file mode 100644 index 000000000..9b7f48e55 --- /dev/null +++ b/depends/packages/crate_ansi_term.mk @@ -0,0 +1,15 @@ +package=crate_ansi_term +$(package)_crate_name=ansi_term +$(package)_version=0.12.1 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_autocfg.mk b/depends/packages/crate_autocfg.mk index 1b36846ed..9e9adf7fa 100644 --- a/depends/packages/crate_autocfg.mk +++ b/depends/packages/crate_autocfg.mk @@ -1,9 +1,9 @@ package=crate_autocfg $(package)_crate_name=autocfg -$(package)_version=0.1.6 +$(package)_version=1.0.0 $(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) $(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate -$(package)_sha256_hash=b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875 +$(package)_sha256_hash=f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d $(package)_crate_versioned_name=$($(package)_crate_name) define $(package)_preprocess_cmds diff --git a/depends/packages/crate_autocfg_0.1.mk b/depends/packages/crate_autocfg_0.1.mk new file mode 100644 index 000000000..21468f57e --- /dev/null +++ b/depends/packages/crate_autocfg_0.1.mk @@ -0,0 +1,15 @@ +package=crate_autocfg +$(package)_crate_name=autocfg +$(package)_version=0.1.6 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875 +$(package)_crate_versioned_name=$($(package)_crate_name)-$($(package)_version) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_cfg_if.mk b/depends/packages/crate_cfg_if.mk index af67660f9..895a979ee 100644 --- a/depends/packages/crate_cfg_if.mk +++ b/depends/packages/crate_cfg_if.mk @@ -1,9 +1,9 @@ package=crate_cfg_if $(package)_crate_name=cfg-if -$(package)_version=0.1.9 +$(package)_version=0.1.10 $(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) $(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate -$(package)_sha256_hash=b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33 +$(package)_sha256_hash=4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822 $(package)_crate_versioned_name=$($(package)_crate_name) define $(package)_preprocess_cmds diff --git a/depends/packages/crate_chrono.mk b/depends/packages/crate_chrono.mk new file mode 100644 index 000000000..2437f11b3 --- /dev/null +++ b/depends/packages/crate_chrono.mk @@ -0,0 +1,15 @@ +package=crate_chrono +$(package)_crate_name=chrono +$(package)_version=0.4.13 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_crossbeam_channel.mk b/depends/packages/crate_crossbeam_channel.mk index 618268f41..06184ba25 100644 --- a/depends/packages/crate_crossbeam_channel.mk +++ b/depends/packages/crate_crossbeam_channel.mk @@ -1,9 +1,9 @@ package=crate_crossbeam_channel $(package)_crate_name=crossbeam-channel -$(package)_version=0.3.9 +$(package)_version=0.4.3 $(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) $(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate -$(package)_sha256_hash=c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa +$(package)_sha256_hash=09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6 $(package)_crate_versioned_name=$($(package)_crate_name) define $(package)_preprocess_cmds diff --git a/depends/packages/crate_crossbeam_channel_0.3.mk b/depends/packages/crate_crossbeam_channel_0.3.mk new file mode 100644 index 000000000..125425027 --- /dev/null +++ b/depends/packages/crate_crossbeam_channel_0.3.mk @@ -0,0 +1,15 @@ +package=crate_crossbeam_channel +$(package)_crate_name=crossbeam-channel +$(package)_version=0.3.9 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa +$(package)_crate_versioned_name=$($(package)_crate_name)-$($(package)_version) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_crossbeam_utils.mk b/depends/packages/crate_crossbeam_utils.mk index eabfa26c4..5aa4efdf4 100644 --- a/depends/packages/crate_crossbeam_utils.mk +++ b/depends/packages/crate_crossbeam_utils.mk @@ -1,9 +1,9 @@ package=crate_crossbeam_utils $(package)_crate_name=crossbeam-utils -$(package)_version=0.6.6 +$(package)_version=0.7.2 $(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) $(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate -$(package)_sha256_hash=04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6 +$(package)_sha256_hash=c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8 $(package)_crate_versioned_name=$($(package)_crate_name) define $(package)_preprocess_cmds diff --git a/depends/packages/crate_crossbeam_utils_0.6.mk b/depends/packages/crate_crossbeam_utils_0.6.mk new file mode 100644 index 000000000..3e8365856 --- /dev/null +++ b/depends/packages/crate_crossbeam_utils_0.6.mk @@ -0,0 +1,15 @@ +package=crate_crossbeam_utils +$(package)_crate_name=crossbeam-utils +$(package)_version=0.6.6 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6 +$(package)_crate_versioned_name=$($(package)_crate_name)-$($(package)_version) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_libc.mk b/depends/packages/crate_libc.mk index a8752b964..774e8ce00 100644 --- a/depends/packages/crate_libc.mk +++ b/depends/packages/crate_libc.mk @@ -1,9 +1,9 @@ package=crate_libc $(package)_crate_name=libc -$(package)_version=0.2.62 +$(package)_version=0.2.72 $(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) $(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate -$(package)_sha256_hash=34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba +$(package)_sha256_hash=a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701 $(package)_crate_versioned_name=$($(package)_crate_name) define $(package)_preprocess_cmds diff --git a/depends/packages/crate_matchers.mk b/depends/packages/crate_matchers.mk new file mode 100644 index 000000000..61f968fcc --- /dev/null +++ b/depends/packages/crate_matchers.mk @@ -0,0 +1,15 @@ +package=crate_matchers +$(package)_crate_name=matchers +$(package)_version=0.0.1 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_memchr.mk b/depends/packages/crate_memchr.mk new file mode 100644 index 000000000..8d318f5d6 --- /dev/null +++ b/depends/packages/crate_memchr.mk @@ -0,0 +1,15 @@ +package=crate_memchr +$(package)_crate_name=memchr +$(package)_version=2.3.3 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_regex.mk b/depends/packages/crate_regex.mk new file mode 100644 index 000000000..e801eae51 --- /dev/null +++ b/depends/packages/crate_regex.mk @@ -0,0 +1,15 @@ +package=crate_regex +$(package)_crate_name=regex +$(package)_version=1.3.9 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_regex_automata.mk b/depends/packages/crate_regex_automata.mk new file mode 100644 index 000000000..3a577b18b --- /dev/null +++ b/depends/packages/crate_regex_automata.mk @@ -0,0 +1,15 @@ +package=crate_regex_automata +$(package)_crate_name=regex-automata +$(package)_version=0.1.9 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_regex_syntax.mk b/depends/packages/crate_regex_syntax.mk new file mode 100644 index 000000000..afa390e00 --- /dev/null +++ b/depends/packages/crate_regex_syntax.mk @@ -0,0 +1,15 @@ +package=crate_regex_syntax +$(package)_crate_name=regex-syntax +$(package)_version=0.6.18 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_sharded_slab.mk b/depends/packages/crate_sharded_slab.mk new file mode 100644 index 000000000..65f1aaf4a --- /dev/null +++ b/depends/packages/crate_sharded_slab.mk @@ -0,0 +1,15 @@ +package=crate_sharded_slab +$(package)_crate_name=sharded-slab +$(package)_version=0.0.9 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_thread_local.mk b/depends/packages/crate_thread_local.mk new file mode 100644 index 000000000..9a164f0e4 --- /dev/null +++ b/depends/packages/crate_thread_local.mk @@ -0,0 +1,15 @@ +package=crate_thread_local +$(package)_crate_name=thread_local +$(package)_version=1.0.1 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_time.mk b/depends/packages/crate_time.mk new file mode 100644 index 000000000..e003d68ab --- /dev/null +++ b/depends/packages/crate_time.mk @@ -0,0 +1,15 @@ +package=crate_time +$(package)_crate_name=time +$(package)_version=0.1.43 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_tracing.mk b/depends/packages/crate_tracing.mk new file mode 100644 index 000000000..efe15f9a7 --- /dev/null +++ b/depends/packages/crate_tracing.mk @@ -0,0 +1,15 @@ +package=crate_tracing +$(package)_crate_name=tracing +$(package)_version=0.1.18 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_tracing_appender.mk b/depends/packages/crate_tracing_appender.mk new file mode 100644 index 000000000..90d60aad6 --- /dev/null +++ b/depends/packages/crate_tracing_appender.mk @@ -0,0 +1,15 @@ +package=crate_tracing_appender +$(package)_crate_name=tracing-appender +$(package)_version=0.1.1 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=7aa52d56cc0d79ab604e8a022a1cebc4de33cf09dc9933c94353bea2e00d6e88 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_tracing_attributes.mk b/depends/packages/crate_tracing_attributes.mk new file mode 100644 index 000000000..1f18e81ba --- /dev/null +++ b/depends/packages/crate_tracing_attributes.mk @@ -0,0 +1,15 @@ +package=crate_tracing_attributes +$(package)_crate_name=tracing-attributes +$(package)_version=0.1.9 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_tracing_core.mk b/depends/packages/crate_tracing_core.mk new file mode 100644 index 000000000..4aee3472e --- /dev/null +++ b/depends/packages/crate_tracing_core.mk @@ -0,0 +1,15 @@ +package=crate_tracing_core +$(package)_crate_name=tracing-core +$(package)_version=0.1.13 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9 +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/crate_tracing_subscriber.mk b/depends/packages/crate_tracing_subscriber.mk new file mode 100644 index 000000000..ac68653a2 --- /dev/null +++ b/depends/packages/crate_tracing_subscriber.mk @@ -0,0 +1,15 @@ +package=crate_tracing_subscriber +$(package)_crate_name=tracing-subscriber +$(package)_version=0.2.10 +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 9e43d2de0..e1fb4d66d 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -2,8 +2,11 @@ rust_crates := \ crate_aes \ crate_aesni \ crate_aes_soft \ + crate_aho_corasick \ + crate_ansi_term \ crate_arrayref \ crate_arrayvec \ + crate_autocfg_0.1 \ crate_autocfg \ crate_bellman \ crate_bigint \ @@ -17,11 +20,14 @@ rust_crates := \ crate_byteorder \ crate_c2_chacha \ crate_cfg_if \ + crate_chrono \ crate_constant_time_eq \ + crate_crossbeam_channel_0.3 \ crate_crossbeam_channel \ crate_crossbeam_deque \ crate_crossbeam_epoch \ crate_crossbeam_queue \ + crate_crossbeam_utils_0.6 \ crate_crossbeam_utils \ crate_crossbeam \ crate_crunchy \ @@ -45,6 +51,8 @@ rust_crates := \ crate_lazy_static \ crate_libc \ crate_log \ + crate_matchers \ + crate_memchr \ crate_memoffset \ crate_nodrop \ crate_num_bigint \ @@ -61,6 +69,9 @@ rust_crates := \ crate_rand_hc \ crate_rand_xorshift \ crate_rand \ + crate_regex_automata \ + crate_regex_syntax \ + crate_regex \ crate_rustc_version \ crate_scopeguard \ crate_semver_parser \ @@ -68,10 +79,18 @@ rust_crates := \ crate_serde \ crate_serde_derive \ crate_sha2 \ + crate_sharded_slab \ crate_subtle \ crate_syn \ + crate_time \ crate_thiserror \ crate_thiserror_impl \ + crate_thread_local \ + crate_tracing_appender \ + crate_tracing_attributes \ + crate_tracing_core \ + crate_tracing_subscriber \ + crate_tracing \ crate_typenum \ crate_unicode_xid \ crate_wasi \ diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b51..d20ba239d 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,27 @@ release-notes at release time) Notable changes =============== +New logging system +------------------ + +The `zcashd` logging system is now powered by the Rust `tracing` crate. This +has two main benefits: + +- `tracing` supports the concept of "spans", which represent periods of time + with a beginning and end. These enable logging additional information about + temporality and causality of events. (Regular log lines, which represent + moments in time, are called `events` in `tracing`.) +- Spans and events are structured, and can record typed data in addition to text + messages. This structure can then be filtered dynamically. + +The existing `-debug=target` config flags are mapped to `tracing` log filters, +and will continue to correctly enable additional logging when starting `zcashd`. +A new `setlogfilter` RPC method has been introduced that enables reconfiguring +the log filter at runtime. See `zcash-cli help setlogfilter` for its syntax. + +As a minor note, `zcashd` no longer reopens the `debug.log` file on `SIGHUP`. +This behaviour was originally introduced in upstream Bitcoin Core to support log +rotation using external tools. `tracing` supports log rotation internally (which +is currently disabled), as well as a variety of interesting backends (such as +`journald` and OpenTelemetry integration); we are investigating how these might +be exposed in future releases. diff --git a/qa/zcash/postponed-updates.txt b/qa/zcash/postponed-updates.txt index 0def0da32..c6c08492c 100644 --- a/qa/zcash/postponed-updates.txt +++ b/qa/zcash/postponed-updates.txt @@ -57,8 +57,8 @@ crate_arrayvec 0.4.12 2020-10-01 crate_arrayvec 0.5.0 2020-10-01 crate_arrayvec 0.5.1 2020-10-01 crate_arrayref 0.3.6 2020-10-01 -crate_autocfg 0.1.7 2020-10-01 -crate_autocfg 1.0.0 2020-10-01 +crate_autocfg_0.1 0.1.7 2020-10-01 +crate_autocfg_0.1 1.0.0 2020-10-01 crate_bigint 4.4.2 2020-10-01 crate_bigint 4.4.3 2020-10-01 crate_blake2b_simd 0.5.9 2020-10-01 @@ -85,17 +85,17 @@ crate_crunchy 0.2.2 2020-10-01 crate_constant_time_eq 0.1.5 2020-10-01 crate_crossbeam 0.7.3 2020-10-01 crate_digest 0.9.0 2020-10-01 -crate_crossbeam_channel 0.4.0 2020-10-01 -crate_crossbeam_channel 0.4.1 2020-10-01 -crate_crossbeam_channel 0.4.2 2020-10-01 +crate_crossbeam_channel_0.3 0.4.0 2020-10-01 +crate_crossbeam_channel_0.3 0.4.1 2020-10-01 +crate_crossbeam_channel_0.3 0.4.2 2020-10-01 crate_crossbeam_deque 0.7.2 2020-10-01 crate_crossbeam_deque 0.7.3 2020-10-01 crate_crossbeam_epoch 0.8.0 2020-10-01 crate_crossbeam_epoch 0.8.1 2020-10-01 crate_crossbeam_epoch 0.8.2 2020-10-01 -crate_crossbeam_utils 0.7.0 2020-10-01 -crate_crossbeam_utils 0.7.1 2020-10-01 -crate_crossbeam_utils 0.7.2 2020-10-01 +crate_crossbeam_utils_0.6 0.7.0 2020-10-01 +crate_crossbeam_utils_0.6 0.7.1 2020-10-01 +crate_crossbeam_utils_0.6 0.7.2 2020-10-01 crate_crossbeam_queue 0.2.0 2020-10-01 crate_crossbeam_queue 0.2.1 2020-10-01 crate_crossbeam_queue 0.2.2 2020-10-01 @@ -246,3 +246,23 @@ crate_winapi 0.3.9 2020-10-01 rust 1.45.0 2020-10-01 rust 1.45.1 2020-10-01 rust 1.45.2 2020-10-01 + +# The chrono crate depends on "time ^0.1.43", and is highly unlikely to +# upgrade to v0.2: https://github.com/chronotope/chrono/issues/400 +crate_time 0.2.0 2021-02-01 +crate_time 0.2.1 2021-02-01 +crate_time 0.2.2 2021-02-01 +crate_time 0.2.3 2021-02-01 +crate_time 0.2.4 2021-02-01 +crate_time 0.2.5 2021-02-01 +crate_time 0.2.6 2021-02-01 +crate_time 0.2.7 2021-02-01 +crate_time 0.2.8 2021-02-01 +crate_time 0.2.9 2021-02-01 +crate_time 0.2.10 2021-02-01 +crate_time 0.2.11 2021-02-01 +crate_time 0.2.12 2021-02-01 +crate_time 0.2.13 2021-02-01 +crate_time 0.2.14 2021-02-01 +crate_time 0.2.15 2021-02-01 +crate_time 0.2.16 2021-02-01 diff --git a/qa/zcash/updatecheck.py b/qa/zcash/updatecheck.py index e449a5329..8a8ec8902 100755 --- a/qa/zcash/updatecheck.py +++ b/qa/zcash/updatecheck.py @@ -97,23 +97,28 @@ def get_dependency_list(): # Rust crates (filename portion: depends/packages/crate_.mk). crates = [ - "aes", "aesni", "aes_soft", "arrayvec", "bellman", "arrayref", - "autocfg", "bigint", "blake2b_simd", "blake2s_simd", "bit_vec", + "aes", "aesni", "aes_soft", "aho_corasick", "ansi_term", + "arrayvec", "arrayref", "autocfg", "autocfg_0.1", + "bellman", "bigint", "blake2b_simd", "blake2s_simd", "bit_vec", "block_cipher_trait", "byteorder", "byte_tools", "block_buffer", - "block_padding", "c2_chacha", "cfg_if", "crunchy", + "block_padding", "c2_chacha", "cfg_if", "chrono", "crunchy", "curve25519_dalek", "constant_time_eq", "crossbeam", "digest", "fpe", + "crossbeam_channel_0.3", "crossbeam_utils_0.6", "crossbeam_channel", "crossbeam_deque", "crossbeam_epoch", "crossbeam_utils", "crossbeam_queue", "crypto_api", "crypto_api_chachapoly", "directories", "ed25519_zebra", "fake_simd", "ff", "ff_derive", "getrandom", "hex", "hex2", "log", "futures_cpupool", "futures", "generic_array", "group", - "lazy_static", "libc", "nodrop", "num_bigint", "memoffset", + "lazy_static", "libc", "matchers", "memchr", "memoffset", "nodrop", "num_bigint", "ppv_lite86", "proc_macro2", "quote", "num_cpus", "num_integer", "num_traits", "opaque_debug", "pairing", "rand", "typenum", "rand_chacha", "rand_core", "rand_hc", "rand_xorshift", + "regex", "regex_automata", "regex_syntax", "rustc_version", "scopeguard", "semver", "semver_parser", "serde", - "serde_derive", "sha2", "subtle", "syn", "thiserror", - "thiserror_impl", "unicode_xid", "wasi", + "serde_derive", "sha2", "sharded_slab", "subtle", "syn", "thiserror", + "thiserror_impl", "thread_local", "time", "tracing", "tracing_appender", + "tracing_attributes", "tracing_core", "tracing_subscriber", + "unicode_xid", "wasi", "winapi_i686_pc_windows_gnu", "winapi", "winapi_x86_64_pc_windows_gnu", "zcash_history", "zcash_primitives", "zcash_proofs", "zeroize" @@ -122,6 +127,9 @@ def get_dependency_list(): # Sometimes we need multiple versions of a crate, in which case there can't # be a direct mapping between the filename portion and the crate name. crate_name_exceptions = { + "autocfg_0.1": "autocfg", + "crossbeam_channel_0.3": "crossbeam_channel", + "crossbeam_utils_0.6": "crossbeam_utils", "hex2": "hex" } @@ -284,7 +292,7 @@ class DependsVersionGetter: self.name = name def current_version(self): - mk_file_path = os.path.join(SOURCE_ROOT, "depends", "packages", safe(self.name) + ".mk") + mk_file_path = os.path.join(SOURCE_ROOT, "depends", "packages", safe_depends(self.name) + ".mk") mk_file = open(mk_file_path, 'r').read() regexp_whitelist = [ @@ -361,6 +369,12 @@ def safe(string): else: raise RuntimeError("Potentially-dangerous string encountered.") +def safe_depends(string): + if re.match('^[a-zA-Z0-9._-]*$', string): + return string + else: + raise RuntimeError("Potentially-dangerous string encountered.") + def print_row(name, status, current_version, known_versions): COL_FMT_LARGE = "{:<35}" COL_FMT_SMALL = "{:<18}" diff --git a/src/Makefile.am b/src/Makefile.am index d2a30bd6c..35a657f5d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) +BITCOIN_CONFIG_INCLUDES += -I$(srcdir)/rust/include BITCOIN_INCLUDES += -I$(srcdir)/rust/include BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += -I$(srcdir)/univalue/include diff --git a/src/init.cpp b/src/init.cpp index a52205233..317216ae4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -71,6 +71,8 @@ using namespace std; extern void ThreadSendAlert(); +TracingHandle* pTracingHandle = nullptr; + bool fFeeEstimatesInitialized = false; static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; @@ -259,6 +261,9 @@ void Shutdown() globalVerifyHandle.reset(); ECC_Stop(); LogPrintf("%s: done\n", __func__); + if (pTracingHandle) { + tracing_free(pTracingHandle); + } } /** @@ -800,6 +805,23 @@ void InitLogging() fLogTimestamps = GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS); + // Set up the initial filtering directive from the -debug flags. + std::string initialFilter = LogConfigFilter(); + + if (fPrintToConsole) { + pTracingHandle = tracing_init(nullptr, 0, initialFilter.c_str(), fLogTimestamps); + } else { + boost::filesystem::path pathDebug = GetDebugLogPath(); + const boost::filesystem::path::string_type& pathDebugStr = pathDebug.native(); + static_assert(sizeof(boost::filesystem::path::value_type) == sizeof(codeunit), + "native path has unexpected code unit size"); + pTracingHandle = tracing_init( + reinterpret_cast(pathDebugStr.c_str()), + pathDebugStr.length(), + initialFilter.c_str(), + fLogTimestamps); + } + LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); } @@ -1144,12 +1166,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // if (GetBoolArg("-shrinkdebugfile", !fDebug)) // ShrinkDebugFile(); - if (fPrintToDebugLog) { - if (!OpenDebugLog()) { - return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string())); - } - } - LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); diff --git a/src/init.h b/src/init.h index 8e96ff9d6..552d402ad 100644 --- a/src/init.h +++ b/src/init.h @@ -8,6 +8,8 @@ #include +#include + class CScheduler; class CWallet; @@ -16,6 +18,8 @@ namespace boost class thread_group; } // namespace boost +extern TracingHandle* pTracingHandle; + void StartShutdown(); bool ShutdownRequested(); /** Interrupt threads */ diff --git a/src/main.cpp b/src/main.cpp index 7ee9f6e2b..206f81c1d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4321,6 +4321,9 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp) { + auto span = TracingSpan("info", "main", "ProcessNewBlock"); + auto spanGuard = span.Enter(); + // Preliminary checks auto verifier = ProofVerifier::Disabled(); bool checked = CheckBlock(*pblock, state, chainparams, verifier); diff --git a/src/net.cpp b/src/net.cpp index 42afd7b60..067678c6b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -994,6 +994,8 @@ void ThreadSocketHandler() if (pnode->fDisconnect || (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty())) { + auto spanGuard = pnode->span.Enter(); + // remove from vNodes vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); @@ -1152,6 +1154,8 @@ void ThreadSocketHandler() { boost::this_thread::interruption_point(); + auto spanGuard = pnode->span.Enter(); + // // Receive // @@ -1557,6 +1561,8 @@ void ThreadMessageHandler() if (pnode->fDisconnect) continue; + auto spanGuard = pnode->span.Enter(); + // Receive messages { TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); @@ -1890,6 +1896,7 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss) if(!pnode->fRelayTxes) continue; LOCK(pnode->cs_filter); + auto spanGuard = pnode->span.Enter(); if (pnode->pfilter) { if (pnode->pfilter->IsRelevantAndUpdate(tx)) @@ -2101,6 +2108,8 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nPingUsecTime = 0; fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); + span = TracingSpan("info", "net", "CNode"); + auto spanGuard = span.Enter(); { LOCK(cs_nLastNodeId); diff --git a/src/net.h b/src/net.h index 7fd4320b7..b8392e083 100644 --- a/src/net.h +++ b/src/net.h @@ -30,6 +30,8 @@ #include #include +#include + class CAddrMan; class CBlockIndex; class CScheduler; @@ -297,6 +299,8 @@ public: CBloomFilter* pfilter; int nRefCount; NodeId id; + + tracing::Span span; protected: // Denial-of-service detection/prevention diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index bd4273bd4..077e68768 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -28,6 +28,8 @@ #include #include // for to_upper() +#include + using namespace RPCServer; using namespace std; @@ -239,6 +241,42 @@ UniValue help(const UniValue& params, bool fHelp) } +UniValue setlogfilter(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() > 1) { + throw runtime_error( + "setlogfilter \"directives\"\n" + "\nSets the filter to be used for selecting events to log.\n" + "\nA filter is a comma-separated list of directives.\n" + "The syntax for each directive is:\n" + "\n target[span{field=value}]=level\n" + "\nThe default filter, derived from the -debug=target flags, is:\n" + + strprintf("\n %s", LogConfigFilter()) + "\n" + "\nPassing a valid filter here will replace the existing filter.\n" + "Passing an empty string will reset the filter to the default.\n" + "\nArguments:\n" + "1. newFilterDirectives (string, required) The new log filter.\n" + "\nExamples:\n" + + HelpExampleCli("setlogfilter", "\"main=info,rpc=info\"") + + HelpExampleRpc("setlogfilter", "\"main=info,rpc=info\"") + ); + } + + auto newFilter = params[0].getValStr(); + if (newFilter.empty()) { + newFilter = LogConfigFilter(); + } + + if (pTracingHandle) { + if (!tracing_reload(pTracingHandle, newFilter.c_str())) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Filter reload failed; check logs"); + } + } + + return NullUniValue; +} + + UniValue stop(const UniValue& params, bool fHelp) { // Accept the deprecated and ignored 'detach' boolean argument @@ -260,6 +298,7 @@ static const CRPCCommand vRPCCommands[] = // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ { "control", "help", &help, true }, + { "control", "setlogfilter", &setlogfilter, true }, { "control", "stop", &stop, true }, }; diff --git a/src/rust/include/librustzcash.h b/src/rust/include/librustzcash.h index 0dd261cbe..6f972a9ab 100644 --- a/src/rust/include/librustzcash.h +++ b/src/rust/include/librustzcash.h @@ -1,6 +1,9 @@ #ifndef LIBRUSTZCASH_INCLUDE_H_ #define LIBRUSTZCASH_INCLUDE_H_ +#include "rust/types.h" + +#include #include #ifndef __cplusplus @@ -29,11 +32,6 @@ static_assert(alignof(HistoryEntry) == 1, "HistoryEntry struct alignment is not #ifdef __cplusplus extern "C" { -#endif -#ifdef WIN32 - typedef uint16_t codeunit; -#else - typedef uint8_t codeunit; #endif void librustzcash_to_scalar(const unsigned char *input, unsigned char *result); diff --git a/src/rust/include/rust/types.h b/src/rust/include/rust/types.h new file mode 100644 index 000000000..63c5a1d52 --- /dev/null +++ b/src/rust/include/rust/types.h @@ -0,0 +1,16 @@ +// Copyright (c) 2020 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#ifndef RUST_TYPES_H_ +#define RUST_TYPES_H_ + +#include + +#ifdef WIN32 +typedef uint16_t codeunit; +#else +typedef uint8_t codeunit; +#endif + +#endif // RUST_TYPES_H_ diff --git a/src/rust/include/tracing.h b/src/rust/include/tracing.h new file mode 100644 index 000000000..89bd87c4a --- /dev/null +++ b/src/rust/include/tracing.h @@ -0,0 +1,301 @@ +// Copyright (c) 2020 Jack Grigg +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#ifndef TRACING_INCLUDE_H_ +#define TRACING_INCLUDE_H_ + +#include "rust/types.h" + +#include +#include + +#ifdef __cplusplus +#include + +extern "C" { +#endif + +struct TracingHandle; +typedef struct TracingHandle TracingHandle; + +/// Initializes the tracing crate, returning a handle for the logging +/// component. The handle must be freed to close the logging component. +/// +/// If log_path is NULL, logging is sent to standard output. +TracingHandle* tracing_init( + const codeunit* log_path, + size_t log_path_len, + const char* initial_filter, + bool log_timestamps); + +/// Frees a tracing handle returned from `tracing_init`; +void tracing_free(TracingHandle* handle); + +/// Reloads the tracing filter. +/// +/// Returns `true` if the reload succeeded. +bool tracing_reload(TracingHandle* handle, const char* new_filter); + +struct TracingCallsite; +typedef struct TracingCallsite TracingCallsite; + +/// Creates a tracing callsite. +/// +/// You should usually call the `TracingLog` macro (or one of the helper +/// macros such as `TracingInfo`) instead of calling this directly. +/// +/// This MUST ONLY be called to assign a `static TracingCallsite*`, and all +/// string arguments MUST be static `const char*` constants, and MUST be valid +/// UTF-8. +TracingCallsite* tracing_callsite( + const char* name, + const char* target, + const char* level, + const char* file, + uint32_t line, + const char* const* fields, + size_t fields_len, + bool is_span); + +struct TracingSpanHandle; +typedef struct TracingSpanHandle TracingSpanHandle; + +struct TracingSpanGuard; +typedef struct TracingSpanGuard TracingSpanGuard; + +/// Creates a span for a callsite. +/// +/// The span must be freed when it goes out of scope. +TracingSpanHandle* tracing_span_create(const TracingCallsite* callsite); + +/// Clones the given span. +/// +/// Both spans need to be separately freed when they go out of scope. +TracingSpanHandle* tracing_span_clone(const TracingSpanHandle* span); + +/// Frees a span. +void tracing_span_free(TracingSpanHandle* span); + +/// Enters the given span, returning a guard. +/// +/// `tracing_span_exit` must be called to drop this guard before the span +/// goes out of scope. +TracingSpanGuard* tracing_span_enter(const TracingSpanHandle* span); + +/// Exits a span by dropping the given guard. +void tracing_span_exit(TracingSpanGuard* guard); + +/// Logs a message for a callsite. +/// +/// You should usually call the `TracingLog` macro (or one of the helper +/// macros such as `TracingInfo`) instead of calling this directly. +void tracing_log( + const TracingCallsite* callsite, + const char* const* field_values, + size_t fields_len); + +#ifdef __cplusplus +} +#endif + +// +// Helper macros +// + +#define T_DOUBLEESCAPE(a) #a +#define T_ESCAPEQUOTE(a) T_DOUBLEESCAPE(a) + +// Computes the length of the given array. This is COUNT_OF from Chromium. +#define T_ARRLEN(x) ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x]))))) + +#ifdef __cplusplus +// Constructs a tracing callsite. +// +// The 'static constexpr' hack ensures that name, target, level, and fields are +// compile-time constants with static storage duration. The output of this macro +// MUST be stored as a static TracingCallsite*. +#define T_CALLSITE(name, target, level, fields, is_span) ([&] { \ + static constexpr const char* _t_name = name; \ + static constexpr const char* _t_target = target; \ + static constexpr const char* _t_level = level; \ + static constexpr const char* const* _t_fields = fields; \ + return tracing_callsite( \ + _t_name, \ + _t_target, \ + _t_level, \ + __FILE__, \ + __LINE__, \ + _t_fields, \ + T_ARRLEN(fields), \ + is_span); \ +}()) +#else +// Constructs a tracing callsite. +// +// name, target, level, and fields MUST be static constants, and the output of +// this macro MUST be stored as a static TracingCallsite*. +#define T_CALLSITE(name, target, level, fields, is_span) \ + tracing_callsite( \ + name, \ + target, \ + level, \ + __FILE__, \ + __LINE__, \ + fields, \ + T_ARRLEN(fields), \ + is_span) +#endif + +// +// Spans +// + +#ifdef __cplusplus +namespace tracing +{ +class Span; + +/// A guard representing a span which has been entered and is currently +/// executing. +/// +/// When the guard is dropped, the span will be exited. +/// +/// This is returned by the `Span::Enter` function. +class Entered +{ +private: + friend class Span; + std::unique_ptr inner; + + Entered(const TracingSpanHandle* span) : inner(tracing_span_enter(span), tracing_span_exit) {} +}; + +/// A handle representing a span, with the capability to enter the span if it +/// exists. +/// +/// If the span was rejected by the current `Subscriber`'s filter, entering the +/// span will silently do nothing. Thus, the handle can be used in the same +/// manner regardless of whether or not the trace is currently being collected. +class Span +{ +private: + std::unique_ptr inner; + +public: + /// Constructs a span that does nothing. + /// + /// This constructor is present to enable spans to be stored in classes, + /// while also containing fields that are initialized within the class + /// constructor: + /// + /// class Foo { + /// std::string name; + /// tracing::Span span; + /// + /// Foo(std::string tag) + /// { + /// name = "Foo-" + tag; + /// span = TracingSpan("info", "main", "Foo", "name", name); + /// } + /// } + Span() : inner(nullptr, tracing_span_free) {} + + /// Use the `TracingSpan` macro instead of calling this constructor directly. + Span(const TracingCallsite* callsite) : inner(tracing_span_create(callsite), tracing_span_free) {} + + Span(Span& span) : inner(std::move(span.inner)) {} + Span(const Span& span) : inner(tracing_span_clone(span.inner.get()), tracing_span_free) {} + Span& operator=(Span& span) + { + if (this != &span) { + inner = std::move(span.inner); + } + return *this; + } + Span& operator=(const Span& span) + { + if (this != &span) { + inner.reset(tracing_span_clone(span.inner.get())); + } + return *this; + } + + /// Enters this span, returning a guard that will exit the span when dropped. + /// + /// If this span is enabled by the current subscriber, then this function + /// will call `Subscriber::enter` with the span's `Id`, and dropping the + /// guard will call `Subscriber::exit`. If the span is disabled, this does + /// nothing. + Entered Enter() + { + return Entered(inner.get()); + } +}; +} // namespace tracing + +/// Expands to a `tracing::Span` object which is used to record a span. +/// The `Span::Enter` method on that object records that the span has been +/// entered, and returns a RAII guard object, which will exit the span when +/// dropped. +/// +/// level, target, and name MUST be static constants, and MUST be valid UTF-8 +/// strings. +#define TracingSpan(level, target, name) ([&] { \ + static constexpr const char* const FIELDS[] = {}; \ + static TracingCallsite* CALLSITE = \ + T_CALLSITE(name, target, level, FIELDS, true); \ + return tracing::Span(CALLSITE); \ +}()) +#endif + +// +// Events +// + +/// Constructs a new event. +/// +/// level and target MUST be static constants, and MUST be valid UTF-8 strings. +#define TracingLog(level, target, message) \ + do { \ + static constexpr const char* const FIELDS[] = \ + {"message"}; \ + const char* T_VALUES[] = {message}; \ + static TracingCallsite* CALLSITE = T_CALLSITE( \ + "event " __FILE__ ":" T_ESCAPEQUOTE(__LINE__), \ + target, level, FIELDS, false); \ + tracing_log(CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \ + } while (0) + +/// Constructs an event at the error level. +/// +/// Arguments: (target, message) +/// +/// target MUST be a static constant, and MUST be valid UTF-8 string. +#define TracingError(...) TracingLog("error", __VA_ARGS__) +/// Constructs an event at the warn level. +/// +/// Arguments: (target, message) +/// +/// target MUST be a static constant, and MUST be valid UTF-8 string. +#define TracingWarn(...) TracingLog("warn", __VA_ARGS__) +/// Constructs an event at the info level. +/// +/// Arguments: (target, message) +/// +/// target MUST be a static constant, and MUST be valid UTF-8 string. +#define TracingInfo(...) TracingLog("info", __VA_ARGS__) +/// Constructs an event at the debug level. +/// +/// Arguments: (target, message) +/// +/// target MUST be a static constant, and MUST be valid UTF-8 string. +#define TracingDebug(...) TracingLog("debug", __VA_ARGS__) +/// Constructs an event at the trace level. +/// +/// Arguments: (target, message) +/// +/// target MUST be a static constant, and MUST be valid UTF-8 string. +#define TracingTrace(...) TracingLog("trace", __VA_ARGS__) + +#endif // TRACING_INCLUDE_H_ diff --git a/src/rust/src/rustzcash.rs b/src/rust/src/rustzcash.rs index 42933a983..aded2f3e6 100644 --- a/src/rust/src/rustzcash.rs +++ b/src/rust/src/rustzcash.rs @@ -67,6 +67,8 @@ use zcash_proofs::{ use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree}; +mod tracing_ffi; + #[cfg(test)] mod tests; diff --git a/src/rust/src/tracing_ffi.rs b/src/rust/src/tracing_ffi.rs new file mode 100644 index 000000000..2f7ecf731 --- /dev/null +++ b/src/rust/src/tracing_ffi.rs @@ -0,0 +1,552 @@ +use libc::c_char; +use std::ffi::CStr; +use std::path::Path; +use std::slice; +use std::str; +use std::sync::atomic::{AtomicUsize, Ordering}; +use tracing::{ + callsite::{Callsite, Identifier}, + field::{FieldSet, Value}, + level_enabled, + metadata::Kind, + span::Entered, + subscriber::{Interest, Subscriber}, + Event, Metadata, Span, +}; +use tracing_appender::non_blocking::WorkerGuard; +use tracing_core::Once; +use tracing_subscriber::{ + filter::EnvFilter, + layer::Layer, + reload::{self, Handle}, +}; + +#[cfg(not(target_os = "windows"))] +use std::ffi::OsStr; +#[cfg(not(target_os = "windows"))] +use std::os::unix::ffi::OsStrExt; + +#[cfg(target_os = "windows")] +use std::ffi::OsString; +#[cfg(target_os = "windows")] +use std::os::windows::ffi::OsStringExt; + +trait ReloadHandle { + fn reload(&self, new_filter: EnvFilter) -> Result<(), reload::Error>; +} + +impl ReloadHandle for Handle +where + L: From + Layer + 'static, + S: Subscriber, +{ + fn reload(&self, new_filter: EnvFilter) -> Result<(), reload::Error> { + self.reload(new_filter) + } +} + +pub struct TracingHandle { + _file_guard: Option, + reload_handle: Box, +} + +#[no_mangle] +pub extern "C" fn tracing_init( + #[cfg(not(target_os = "windows"))] log_path: *const u8, + #[cfg(target_os = "windows")] log_path: *const u16, + log_path_len: usize, + initial_filter: *const c_char, + log_timestamps: bool, +) -> *mut TracingHandle { + let initial_filter = unsafe { CStr::from_ptr(initial_filter) } + .to_str() + .expect("initial filter should be a valid string"); + + if log_path.is_null() { + tracing_init_stdout(initial_filter, log_timestamps) + } else { + let log_path = unsafe { slice::from_raw_parts(log_path, log_path_len) }; + + #[cfg(not(target_os = "windows"))] + let log_path = Path::new(OsStr::from_bytes(log_path)); + + #[cfg(target_os = "windows")] + let log_path = Path::new(OsString::from_wide(log_path)); + + tracing_init_file(log_path, initial_filter, log_timestamps) + } +} + +fn tracing_init_stdout(initial_filter: &str, log_timestamps: bool) -> *mut TracingHandle { + let builder = tracing_subscriber::fmt() + .with_ansi(true) + .with_env_filter(initial_filter); + + let reload_handle = if log_timestamps { + let builder = builder.with_filter_reloading(); + let reload_handle = builder.reload_handle(); + builder.init(); + Box::new(reload_handle) as Box + } else { + let builder = builder.without_time().with_filter_reloading(); + let reload_handle = builder.reload_handle(); + builder.init(); + Box::new(reload_handle) as Box + }; + + Box::into_raw(Box::new(TracingHandle { + _file_guard: None, + reload_handle, + })) +} + +fn tracing_init_file( + log_path: &Path, + initial_filter: &str, + log_timestamps: bool, +) -> *mut TracingHandle { + let file_appender = + tracing_appender::rolling::never(log_path.parent().unwrap(), log_path.file_name().unwrap()); + let (non_blocking, file_guard) = tracing_appender::non_blocking(file_appender); + + let builder = tracing_subscriber::fmt() + .with_ansi(false) + .with_env_filter(initial_filter) + .with_writer(non_blocking); + + let reload_handle = if log_timestamps { + let builder = builder.with_filter_reloading(); + let reload_handle = builder.reload_handle(); + builder.init(); + Box::new(reload_handle) as Box + } else { + let builder = builder.without_time().with_filter_reloading(); + let reload_handle = builder.reload_handle(); + builder.init(); + Box::new(reload_handle) as Box + }; + + Box::into_raw(Box::new(TracingHandle { + _file_guard: Some(file_guard), + reload_handle, + })) +} + +#[no_mangle] +pub extern "C" fn tracing_free(handle: *mut TracingHandle) { + drop(unsafe { Box::from_raw(handle) }); +} + +#[no_mangle] +pub extern "C" fn tracing_reload(handle: *mut TracingHandle, new_filter: *const c_char) -> bool { + let handle = unsafe { &mut *handle }; + + match unsafe { CStr::from_ptr(new_filter) } + .to_str() + .map(EnvFilter::new) + { + Err(e) => { + tracing::error!("New filter is not valid UTF-8: {}", e); + false + } + Ok(new_filter) => { + if let Err(e) = handle.reload_handle.reload(new_filter) { + tracing::error!("Filter reload failed: {}", e); + false + } else { + true + } + } + } +} + +pub struct FfiCallsite { + interest: AtomicUsize, + meta: Option>, + registration: Once, + fields: Vec<&'static str>, +} + +impl FfiCallsite { + fn new(fields: Vec<&'static str>) -> Self { + FfiCallsite { + interest: AtomicUsize::new(0), + meta: None, + registration: Once::new(), + fields, + } + } + + #[inline(always)] + fn is_enabled(&self) -> bool { + let interest = self.interest(); + if interest.is_always() { + return true; + } + if interest.is_never() { + return false; + } + + tracing::dispatcher::get_default(|current| current.enabled(self.metadata())) + } + + #[inline(always)] + pub fn register(&'static self) { + self.registration + .call_once(|| tracing::callsite::register(self)); + } + + #[inline(always)] + fn interest(&self) -> Interest { + match self.interest.load(Ordering::Relaxed) { + 0 => Interest::never(), + 2 => Interest::always(), + _ => Interest::sometimes(), + } + } +} + +impl Callsite for FfiCallsite { + fn set_interest(&self, interest: Interest) { + let interest = match () { + _ if interest.is_never() => 0, + _ if interest.is_always() => 2, + _ => 1, + }; + self.interest.store(interest, Ordering::SeqCst); + } + + #[inline(always)] + fn metadata(&self) -> &Metadata<'static> { + self.meta.as_ref().unwrap() + } +} + +#[no_mangle] +pub extern "C" fn tracing_callsite( + name: *const c_char, + target: *const c_char, + level: *const c_char, + file: *const c_char, + line: u32, + fields: *const *const c_char, + fields_len: usize, + is_span: bool, +) -> *mut FfiCallsite { + let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap(); + let target = unsafe { CStr::from_ptr(target) }.to_str().unwrap(); + let level = unsafe { CStr::from_ptr(level) }.to_str().unwrap(); + let file = unsafe { CStr::from_ptr(file) }.to_str().unwrap(); + + let fields = unsafe { slice::from_raw_parts(fields, fields_len) }; + let fields = fields + .iter() + .map(|&p| unsafe { CStr::from_ptr(p) }) + .map(|cs| cs.to_str()) + .collect::, _>>() + .unwrap(); + + let level = level.parse().unwrap(); + + // We immediately convert the new callsite into a pointer to erase lifetime + // information. The caller MUST ensure that the callsite is stored statically. + let site = Box::into_raw(Box::new(FfiCallsite::new(fields))); + let site_ref = unsafe { &*site }; + + let meta: Metadata<'static> = Metadata::new( + name, + target, + level, + Some(file), + Some(line), + None, + FieldSet::new(&site_ref.fields, Identifier(site_ref)), + if is_span { Kind::SPAN } else { Kind::EVENT }, + ); + unsafe { &mut *site }.meta = Some(meta); + + site_ref.register(); + site +} + +macro_rules! repeat { + (1, $val:expr) => { + [$val] + }; + (2, $val:expr) => { + [$val, $val] + }; + (3, $val:expr) => { + [$val, $val, $val] + }; + (4, $val:expr) => { + [$val, $val, $val, $val] + }; + (5, $val:expr) => { + [$val, $val, $val, $val, $val] + }; + (6, $val:expr) => { + [$val, $val, $val, $val, $val, $val] + }; + (7, $val:expr) => { + [$val, $val, $val, $val, $val, $val, $val] + }; + (8, $val:expr) => { + [$val, $val, $val, $val, $val, $val, $val, $val] + }; + (9, $val:expr) => { + [$val, $val, $val, $val, $val, $val, $val, $val, $val] + }; + (10, $val:expr) => { + [$val, $val, $val, $val, $val, $val, $val, $val, $val, $val] + }; + (11, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (12, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (13, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (14, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (15, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, + ] + }; + (16, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, + ] + }; + (17, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, + ] + }; + (18, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, + ] + }; + (19, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, + ] + }; + (20, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, + ] + }; + (21, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, + ] + }; + (22, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (23, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (24, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (25, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (26, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (27, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (28, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + ] + }; + (29, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, + ] + }; + (30, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, + ] + }; + (31, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, + ] + }; + (32, $val:expr) => { + [ + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, + $val, $val, $val, $val, + ] + }; +} + +#[no_mangle] +pub extern "C" fn tracing_span_create(callsite: *const FfiCallsite) -> *mut Span { + let callsite = unsafe { &*callsite }; + + let meta = callsite.metadata(); + assert!(meta.is_span()); + + let span = if level_enabled!(*meta.level()) && callsite.is_enabled() { + Span::new(meta, &meta.fields().value_set(&[])) + } else { + Span::none() + }; + + Box::into_raw(Box::new(span)) +} + +#[no_mangle] +pub extern "C" fn tracing_span_clone(span: *const Span) -> *mut Span { + unsafe { span.as_ref() } + .map(|span| Box::into_raw(Box::new(span.clone()))) + .unwrap_or(std::ptr::null_mut()) +} + +#[no_mangle] +pub extern "C" fn tracing_span_free(span: *mut Span) { + if !span.is_null() { + drop(unsafe { Box::from_raw(span) }); + } +} + +#[no_mangle] +pub extern "C" fn tracing_span_enter(span: *const Span) -> *mut Entered<'static> { + unsafe { span.as_ref() } + .map(|span| Box::into_raw(Box::new(span.enter()))) + .unwrap_or(std::ptr::null_mut()) +} + +#[no_mangle] +pub extern "C" fn tracing_span_exit(guard: *mut Entered) { + if !guard.is_null() { + drop(unsafe { Box::from_raw(guard) }); + } +} + +#[no_mangle] +pub extern "C" fn tracing_log( + callsite: *const FfiCallsite, + field_values: *const *const c_char, + fields_len: usize, +) { + let callsite = unsafe { &*callsite }; + let field_values = unsafe { slice::from_raw_parts(field_values, fields_len) }; + + let meta = callsite.metadata(); + assert!(meta.is_event()); + + if level_enabled!(*meta.level()) && callsite.is_enabled() { + let mut fi = meta.fields().iter(); + let mut vi = field_values + .iter() + .map(|&p| unsafe { CStr::from_ptr(p) }) + .map(|cs| cs.to_string_lossy()); + + macro_rules! dispatch { + ($n:tt) => { + Event::dispatch( + meta, + &meta.fields().value_set(&repeat!( + $n, + ( + &fi.next().unwrap(), + Some(&vi.next().unwrap().as_ref() as &dyn Value) + ) + )), + ) + }; + } + + // https://github.com/tokio-rs/tracing/issues/782 might help improve things here. + match field_values.len() { + 1 => dispatch!(1), + 2 => dispatch!(2), + 3 => dispatch!(3), + 4 => dispatch!(4), + 5 => dispatch!(5), + 6 => dispatch!(6), + 7 => dispatch!(7), + 8 => dispatch!(8), + 9 => dispatch!(9), + 10 => dispatch!(10), + 11 => dispatch!(11), + 12 => dispatch!(12), + 13 => dispatch!(13), + 14 => dispatch!(14), + 15 => dispatch!(15), + 16 => dispatch!(16), + 17 => dispatch!(17), + 18 => dispatch!(18), + 19 => dispatch!(19), + 20 => dispatch!(20), + 21 => dispatch!(21), + 22 => dispatch!(22), + 23 => dispatch!(23), + 24 => dispatch!(24), + 25 => dispatch!(25), + 26 => dispatch!(26), + 27 => dispatch!(27), + 28 => dispatch!(28), + 29 => dispatch!(29), + 30 => dispatch!(30), + 31 => dispatch!(31), + 32 => dispatch!(32), + _ => unimplemented!(), + } + } +} diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 806db4de2..06e2ed72e 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -32,6 +32,8 @@ #include "librustzcash.h" CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h + +TracingHandle* pTracingHandle = nullptr; FastRandomContext insecure_rand_ctx(true); extern bool fPrintToConsole; diff --git a/src/util.cpp b/src/util.cpp index ef2ae9b74..e84e7e6a5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -221,30 +221,23 @@ boost::filesystem::path GetDebugLogPath() } } -bool OpenDebugLog() +std::string LogConfigFilter() { - boost::call_once(&DebugPrintInit, debugPrintInitFlag); - boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); + // With no -debug flags, show errors and LogPrintf lines. + std::string filter = "error,main=info"; - assert(fileout == NULL); - assert(vMsgsBeforeOpenLog); - - boost::filesystem::path pathDebug = GetDebugLogPath(); - fileout = fopen(pathDebug.string().c_str(), "a"); - if (!fileout) { - return false; + auto& categories = mapMultiArgs["-debug"]; + std::set setCategories(categories.begin(), categories.end()); + if (setCategories.count(string("")) != 0 || setCategories.count(string("1")) != 0) { + // Turn on the firehose! + filter = "info"; + } else { + for (auto category : setCategories) { + filter += "," + category + "=info"; + } } - setbuf(fileout, nullptr); // unbuffered - // dump buffered messages from before we opened the log - while (!vMsgsBeforeOpenLog->empty()) { - FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); - vMsgsBeforeOpenLog->pop_front(); - } - - delete vMsgsBeforeOpenLog; - vMsgsBeforeOpenLog = NULL; - return true; + return filter; } bool LogAcceptCategory(const char* category) @@ -276,70 +269,6 @@ bool LogAcceptCategory(const char* category) return true; } -/** - * fStartedNewLine is a state variable held by the calling context that will - * suppress printing of the timestamp when multiple calls are made that don't - * end in a newline. Initialize it to true, and hold it, in the calling context. - */ -static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine) -{ - string strStamped; - - if (!fLogTimestamps) - return str; - - if (*fStartedNewLine) - strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str; - else - strStamped = str; - - if (!str.empty() && str[str.size()-1] == '\n') - *fStartedNewLine = true; - else - *fStartedNewLine = false; - - return strStamped; -} - -int LogPrintStr(const std::string &str) -{ - int ret = 0; // Returns total number of characters written - static bool fStartedNewLine = true; - if (fPrintToConsole) - { - // print to console - ret = fwrite(str.data(), 1, str.size(), stdout); - fflush(stdout); - } - else if (fPrintToDebugLog) - { - boost::call_once(&DebugPrintInit, debugPrintInitFlag); - boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); - - string strTimestamped = LogTimestampStr(str, &fStartedNewLine); - - // buffer if we haven't opened the log yet - if (fileout == NULL) { - assert(vMsgsBeforeOpenLog); - ret = strTimestamped.length(); - vMsgsBeforeOpenLog->push_back(strTimestamped); - } - else - { - // reopen the log file, if requested - if (fReopenDebugLog) { - fReopenDebugLog = false; - boost::filesystem::path pathDebug = GetDebugLogPath(); - if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) - setbuf(fileout, NULL); // unbuffered - } - - ret = FileWriteStr(strTimestamped, fileout); - } - } - return ret; -} - /** Interpret string as boolean, for argument parsing */ static bool InterpretBool(const std::string& strValue) { diff --git a/src/util.h b/src/util.h index d356cf8b4..60e7dd258 100644 --- a/src/util.h +++ b/src/util.h @@ -29,6 +29,8 @@ #include #include +#include + static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGTIMESTAMPS = true; @@ -72,48 +74,34 @@ inline std::string _(const char* psz) void SetupEnvironment(); bool SetupNetworking(); +/** Returns the filtering directive set by the -debug flags. */ +std::string LogConfigFilter(); /** Return true if log accepts specified category */ bool LogAcceptCategory(const char* category); -/** Send a string to the log output */ -int LogPrintStr(const std::string &str); #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) -/** - * When we switch to C++11, this can be switched to variadic templates instead - * of this macro-based construction (see tinyformat.h). - */ -#define MAKE_ERROR_AND_LOG_FUNC(n) \ - /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \ - template \ - static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ - { \ - if(!LogAcceptCategory(category)) return 0; \ - return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ - } \ - /** Log error and return false */ \ - template \ - static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ - { \ - LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ - return false; \ - } +/** Print to debug.log if -debug=category switch is given OR category is NULL. */ +#define LogPrint(category, ...) do { \ + std::string T_MSG = tfm::format(__VA_ARGS__); \ + if (!T_MSG.empty() && T_MSG[T_MSG.size()-1] == '\n') { \ + T_MSG.erase(T_MSG.size()-1); \ + } \ + TracingInfo( \ + category == NULL ? "main" : category, \ + T_MSG.c_str()); \ +} while(0) -TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) +#define LogError(category, ...) ([&]() { \ + std::string T_MSG = tfm::format(__VA_ARGS__); \ + TracingError(category, T_MSG.c_str()); \ + return false; \ +}()) -/** - * Zero-arg versions of logging and error, these are not covered by - * TINYFORMAT_FOREACH_ARGNUM - */ -static inline int LogPrint(const char* category, const char* format) +template +static inline bool error(const char* format, const Args&... args) { - if(!LogAcceptCategory(category)) return 0; - return LogPrintStr(format); -} -static inline bool error(const char* format) -{ - LogPrintStr(std::string("ERROR: ") + format + "\n"); - return false; + return LogError("main", format, args...); } const boost::filesystem::path &ZC_GetParamsDir(); @@ -144,7 +132,6 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif boost::filesystem::path GetTempPath(); boost::filesystem::path GetDebugLogPath(); -bool OpenDebugLog(); void ShrinkDebugFile(); void runCommand(const std::string& strCommand); const boost::filesystem::path GetExportDir(); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 0a76c6672..b7d9ee8df 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -254,8 +254,13 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() tx_ = CTransaction(rawTx); } - LogPrint(isPureTaddrOnlyTx ? "zrpc" : "zrpcunsafe", "%s: spending %s to send %s with fee %s\n", + if (isPureTaddrOnlyTx) { + LogPrint("zrpc", "%s: spending %s to send %s with fee %s\n", getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); + } else { + LogPrint("zrpcunsafe", "%s: spending %s to send %s with fee %s\n", + getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); + } LogPrint("zrpc", "%s: transparent input: %s\n", getId(), FormatMoney(t_inputs_total)); LogPrint("zrpcunsafe", "%s: private input: %s\n", getId(), FormatMoney(z_inputs_total)); if (isToTaddr_) { diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 01425b03c..e1677f741 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -338,8 +338,13 @@ bool AsyncRPCOperation_sendmany::main_impl() { } } - LogPrint((isfromtaddr_) ? "zrpc" : "zrpcunsafe", "%s: spending %s to send %s with fee %s\n", + if (isfromtaddr_) { + LogPrint("zrpc", "%s: spending %s to send %s with fee %s\n", getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); + } else { + LogPrint("zrpcunsafe", "%s: spending %s to send %s with fee %s\n", + getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); + } LogPrint("zrpc", "%s: transparent input: %s (to choose from)\n", getId(), FormatMoney(t_inputs_total)); LogPrint("zrpcunsafe", "%s: private input: %s (to choose from)\n", getId(), FormatMoney(z_inputs_total)); LogPrint("zrpc", "%s: transparent output: %s\n", getId(), FormatMoney(t_outputs_total));