From 39b3ac6a8d29e14faa1de73d8b46d390ad41797b Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Mon, 6 Jul 2020 20:22:23 +0900 Subject: [PATCH] Introduce automatic ABI maintenance mechanism (2/2; rollout) (#8012) * Introduce automatic ABI maintenance mechanism (2/2; rollout) * Fix stable clippy * Change to symlink * Freeze abi of Tower * fmt... * Improve dev-experience! * Update BankSlotDelta $ diff -u /tmp/abi8/*7dg6BreYxTuxiVz6aLvk3p2Z7GQk2cJqfGvC9h4FAoSj* /tmp/abi8/*9chBcbXVJ4fK7uGgydQzam5aHipaAKFw6V4LDFpjbE4w* --- /tmp/abi8/bank__BankSlotDelta_frozen_abi__test_abi_digest_7dg6BreYxTuxiVz6aLvk3p2Z7GQk2cJqfGvC9h4FAoSj 2020-06-18 18:01:22.831228087 +0900 +++ /tmp/abi8/bank__BankSlotDelta_frozen_abi__test_abi_digest_9chBcbXVJ4fK7uGgydQzam5aHipaAKFw6V4LDFpjbE4w 2020-07-03 15:59:58.430695244 +0900 @@ -140,7 +140,7 @@ field u8 primitive u8 field solana_sdk::instruction::InstructionError - enum InstructionError (variants = 34) + enum InstructionError (variants = 35) variant(0) GenericError (unit) variant(1) InvalidArgument (unit) variant(2) InvalidInstructionData (unit) @@ -176,6 +176,7 @@ variant(31) CallDepth (unit) variant(32) MissingAccount (unit) variant(33) ReentrancyNotAllowed (unit) + variant(34) MaxSeedLengthExceeded (unit) variant(9) CallChainTooDeep (unit) variant(10) MissingSignatureForFee (unit) variant(11) InvalidAccountIndex (unit) * Fix some merge conflicts... --- Cargo.lock | 13 +++++++ ci/test-checks.sh | 1 + core/Cargo.toml | 4 +++ core/build.rs | 1 + core/src/cluster_info.rs | 5 +-- core/src/consensus.rs | 2 ++ core/src/contact_info.rs | 2 +- core/src/crds_gossip_pull.rs | 2 +- core/src/crds_value.rs | 12 +++---- core/src/deprecated.rs | 4 +-- core/src/epoch_slots.rs | 8 ++--- core/src/lib.rs | 4 +++ programs/bpf/Cargo.lock | 7 ++++ programs/librapay/Cargo.lock | 7 ++++ programs/stake/Cargo.toml | 4 +++ programs/stake/build.rs | 1 + programs/stake/src/lib.rs | 4 +++ programs/stake/src/stake_state.rs | 14 ++++---- programs/vote/Cargo.toml | 5 +++ programs/vote/build.rs | 1 + programs/vote/src/authorized_voters.rs | 2 +- programs/vote/src/lib.rs | 5 +++ programs/vote/src/vote_state/mod.rs | 12 ++++--- runtime/Cargo.toml | 4 +++ runtime/build.rs | 1 + runtime/src/accounts.rs | 4 +-- runtime/src/accounts_db.rs | 21 ++++++++++-- runtime/src/append_vec.rs | 2 +- runtime/src/bank.rs | 22 ++++++++++-- runtime/src/blockhash_queue.rs | 5 +-- runtime/src/bloom.rs | 2 +- runtime/src/epoch_stakes.rs | 4 +-- runtime/src/lib.rs | 4 +++ runtime/src/message_processor.rs | 10 ++++++ runtime/src/rent_collector.rs | 2 +- runtime/src/serde_snapshot/future.rs | 3 ++ runtime/src/serde_snapshot/legacy.rs | 8 +++++ runtime/src/serde_snapshot/tests.rs | 47 ++++++++++++++++++++++++++ runtime/src/serde_snapshot/utils.rs | 11 ++++++ runtime/src/stakes.rs | 2 +- runtime/src/status_cache.rs | 2 +- sdk/macro-frozen-abi/Cargo.toml | 1 - sdk/macro-frozen-abi/build.rs | 1 + sdk/macro-frozen-abi/src/lib.rs | 11 ++++-- sdk/src/abi_example.rs | 9 ++++- sdk/src/account.rs | 3 +- sdk/src/epoch_schedule.rs | 2 +- sdk/src/fee_calculator.rs | 4 +-- sdk/src/genesis_config.rs | 5 +-- sdk/src/hard_forks.rs | 2 +- sdk/src/hash.rs | 4 ++- sdk/src/inflation.rs | 2 +- sdk/src/instruction.rs | 4 +-- sdk/src/lib.rs | 2 -- sdk/src/message.rs | 6 ++-- sdk/src/packet.rs | 3 +- sdk/src/poh_config.rs | 2 +- sdk/src/pubkey.rs | 4 ++- sdk/src/rent.rs | 2 +- sdk/src/short_vec.rs | 1 + sdk/src/signature.rs | 4 ++- sdk/src/stake_history.rs | 4 +-- sdk/src/system_instruction.rs | 3 +- sdk/src/transaction.rs | 5 +-- version/Cargo.toml | 6 ++++ version/build.rs | 1 + version/src/lib.rs | 7 +++- 67 files changed, 295 insertions(+), 77 deletions(-) create mode 120000 core/build.rs create mode 120000 programs/stake/build.rs create mode 120000 programs/vote/build.rs create mode 120000 runtime/build.rs create mode 120000 sdk/macro-frozen-abi/build.rs create mode 120000 version/build.rs diff --git a/Cargo.lock b/Cargo.lock index 8c37e49d5d..5a2765fe84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3950,6 +3950,7 @@ dependencies = [ "rayon", "regex", "reqwest", + "rustc_version", "serde", "serde_derive", "serde_json", @@ -3972,6 +3973,7 @@ dependencies = [ "solana-rayon-threadlimit", "solana-runtime", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi", "solana-stake-program", "solana-streamer", "solana-sys-tuner", @@ -4561,6 +4563,7 @@ dependencies = [ "rand 0.7.3", "rayon", "regex", + "rustc_version", "serde", "serde_derive", "solana-config-program", @@ -4570,6 +4573,7 @@ dependencies = [ "solana-noop-program", "solana-rayon-threadlimit", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi", "solana-stake-program", "solana-vote-program", "symlink", @@ -4746,12 +4750,14 @@ dependencies = [ "log 0.4.8", "num-derive 0.3.0", "num-traits", + "rustc_version", "serde", "serde_derive", "solana-config-program", "solana-logger", "solana-metrics", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi", "solana-vote-program", "thiserror", ] @@ -4871,9 +4877,13 @@ dependencies = [ name = "solana-version" version = "1.3.0" dependencies = [ + "log 0.4.8", + "rustc_version", "serde", "serde_derive", + "solana-logger", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi", ] [[package]] @@ -4900,10 +4910,13 @@ dependencies = [ "log 0.4.8", "num-derive 0.3.0", "num-traits", + "rustc_version", "serde", "serde_derive", + "solana-logger", "solana-metrics", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi", "thiserror", ] diff --git a/ci/test-checks.sh b/ci/test-checks.sh index 9ba43ecd48..817e9d68d8 100755 --- a/ci/test-checks.sh +++ b/ci/test-checks.sh @@ -52,6 +52,7 @@ _ ci/order-crates-for-publishing.py _ cargo +"$rust_stable" fmt --all -- --check # -Z... is needed because of clippy bug: https://github.com/rust-lang/rust-clippy/issues/4612 +# run nightly clippy for `sdk/` as there's a moderate amount of nightly-only code there _ cargo +"$rust_nightly" clippy -Zunstable-options --workspace --all-targets -- --deny=warnings _ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-2020-0002 --ignore RUSTSEC-2020-0008 diff --git a/core/Cargo.toml b/core/Cargo.toml index 46f39ebd3f..5047c8b327 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -59,6 +59,7 @@ solana-net-utils = { path = "../net-utils", version = "1.3.0" } solana-perf = { path = "../perf", version = "1.3.0" } solana-runtime = { path = "../runtime", version = "1.3.0" } solana-sdk = { path = "../sdk", version = "1.3.0" } +solana-sdk-macro-frozen-abi = { path = "../sdk/macro-frozen-abi", version = "1.3.0" } solana-stake-program = { path = "../programs/stake", version = "1.3.0" } solana-streamer = { path = "../streamer", version = "1.3.0" } solana-sys-tuner = { path = "../sys-tuner", version = "1.3.0" } @@ -82,6 +83,9 @@ serial_test = "0.4.0" serial_test_derive = "0.4.0" systemstat = "0.1.5" +[build-dependencies] +rustc_version = "0.2" + [[bench]] name = "banking_stage" diff --git a/core/build.rs b/core/build.rs new file mode 120000 index 0000000000..8780ebe559 --- /dev/null +++ b/core/build.rs @@ -0,0 +1 @@ +../sdk/build.rs \ No newline at end of file diff --git a/core/src/cluster_info.rs b/core/src/cluster_info.rs index 0ca7300772..5d7a86ed8a 100644 --- a/core/src/cluster_info.rs +++ b/core/src/cluster_info.rs @@ -288,7 +288,7 @@ impl fmt::Debug for Locality { } } -#[derive(Debug, Default, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize, AbiExample)] pub struct PruneData { /// Pubkey of the node that sent this prune data pub pubkey: Pubkey, @@ -357,7 +357,8 @@ pub fn make_accounts_hashes_message( } // TODO These messages should go through the gpu pipeline for spam filtering -#[derive(Serialize, Deserialize, Debug)] +#[frozen_abi(digest = "6qRS1ZwydpdSqzeyRdDvn5uwfDdFYkuUz4K4jSkd1oFW")] +#[derive(Serialize, Deserialize, Debug, AbiEnumVisitor, AbiExample)] #[allow(clippy::large_enum_variant)] enum Protocol { /// Gossip protocol messages diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 3571e42c8a..887ae1348d 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -72,6 +72,8 @@ pub(crate) struct ComputedBankState { pub pubkey_votes: Vec<(Pubkey, Slot)>, } +#[frozen_abi(digest = "2ZUeCLMVQxmHYbeqMH7M97ifVSKoVErGvRHzyxcQRjgU")] +#[derive(Serialize, AbiExample)] pub struct Tower { node_pubkey: Pubkey, threshold_depth: usize, diff --git a/core/src/contact_info.rs b/core/src/contact_info.rs index 962b92b8b6..1d75a934b6 100644 --- a/core/src/contact_info.rs +++ b/core/src/contact_info.rs @@ -10,7 +10,7 @@ use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; use std::net::{IpAddr, SocketAddr}; /// Structure representing a node on the network -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, AbiExample)] pub struct ContactInfo { pub id: Pubkey, /// gossip address diff --git a/core/src/crds_gossip_pull.rs b/core/src/crds_gossip_pull.rs index 75b471a1a5..11a2ef8afe 100644 --- a/core/src/crds_gossip_pull.rs +++ b/core/src/crds_gossip_pull.rs @@ -29,7 +29,7 @@ pub const CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS: u64 = 60000; pub const FALSE_RATE: f64 = 0.1f64; pub const KEYS: f64 = 8f64; -#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, AbiExample)] pub struct CrdsFilter { pub filter: Bloom, mask: u64, diff --git a/core/src/crds_value.rs b/core/src/crds_value.rs index 880655a674..52fb8ebaaf 100644 --- a/core/src/crds_value.rs +++ b/core/src/crds_value.rs @@ -27,7 +27,7 @@ pub type EpochSlotsIndex = u8; pub const MAX_EPOCH_SLOTS: EpochSlotsIndex = 255; /// CrdsValue that is replicated across the cluster -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct CrdsValue { pub signature: Signature, pub data: CrdsData, @@ -67,7 +67,7 @@ impl Signable for CrdsValue { /// * Merge Strategy - Latest wallclock is picked /// * LowestSlot index is deprecated #[allow(clippy::large_enum_variant)] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample, AbiEnumVisitor)] pub enum CrdsData { ContactInfo(ContactInfo), Vote(VoteIndex, Vote), @@ -107,7 +107,7 @@ impl Sanitize for CrdsData { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct SnapshotHash { pub from: Pubkey, pub hashes: Vec<(Slot, Hash)>, @@ -137,7 +137,7 @@ impl SnapshotHash { } } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct LowestSlot { pub from: Pubkey, root: Slot, //deprecated @@ -181,7 +181,7 @@ impl Sanitize for LowestSlot { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct Vote { pub from: Pubkey, pub transaction: Transaction, @@ -208,7 +208,7 @@ impl Vote { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct Version { pub from: Pubkey, pub wallclock: u64, diff --git a/core/src/deprecated.rs b/core/src/deprecated.rs index 06e7725054..57a7a8315c 100644 --- a/core/src/deprecated.rs +++ b/core/src/deprecated.rs @@ -1,6 +1,6 @@ use solana_sdk::clock::Slot; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample, AbiEnumVisitor)] enum CompressionType { Uncompressed, GZip, @@ -13,7 +13,7 @@ impl Default for CompressionType { } } -#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, AbiExample)] pub(crate) struct EpochIncompleteSlots { first: Slot, compression: CompressionType, diff --git a/core/src/epoch_slots.rs b/core/src/epoch_slots.rs index e69622e211..758c21e596 100644 --- a/core/src/epoch_slots.rs +++ b/core/src/epoch_slots.rs @@ -9,7 +9,7 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::sanitize::{Sanitize, SanitizeError}; const MAX_SLOTS_PER_ENTRY: usize = 2048 * 8; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct Uncompressed { pub first_slot: Slot, pub num: usize, @@ -28,7 +28,7 @@ impl Sanitize for Uncompressed { } } -#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, AbiExample)] pub struct Flate2 { pub first_slot: Slot, pub num: usize, @@ -142,7 +142,7 @@ impl Uncompressed { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample, AbiEnumVisitor)] pub enum CompressedSlots { Flate2(Flate2), Uncompressed(Uncompressed), @@ -211,7 +211,7 @@ impl CompressedSlots { } } -#[derive(Serialize, Deserialize, Clone, Default, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Default, PartialEq, AbiExample)] pub struct EpochSlots { pub from: Pubkey, pub slots: Vec, diff --git a/core/src/lib.rs b/core/src/lib.rs index 019d37a46d..7b21c95e3b 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] //! The `solana` library implements the Solana high-performance blockchain architecture. //! It includes a full Rust implementation of the architecture (see //! [Validator](server/struct.Validator.html)) as well as hooks to GPU implementations of its most @@ -86,6 +87,9 @@ extern crate serde_json; #[macro_use] extern crate solana_metrics; +#[macro_use] +extern crate solana_sdk_macro_frozen_abi; + #[cfg(test)] #[macro_use] extern crate matches; diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 25ed3f087f..ed15626a75 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -1667,6 +1667,7 @@ dependencies = [ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "solana-config-program 1.3.0", @@ -1675,6 +1676,7 @@ dependencies = [ "solana-metrics 1.3.0", "solana-rayon-threadlimit 1.3.0", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi 1.3.0", "solana-stake-program 1.3.0", "solana-vote-program 1.3.0", "symlink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1748,11 +1750,13 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "solana-config-program 1.3.0", "solana-metrics 1.3.0", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi 1.3.0", "solana-vote-program 1.3.0", "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1765,10 +1769,13 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 1.3.0", "solana-metrics 1.3.0", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi 1.3.0", "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/programs/librapay/Cargo.lock b/programs/librapay/Cargo.lock index 9d3fb6e2ff..bce5558a34 100644 --- a/programs/librapay/Cargo.lock +++ b/programs/librapay/Cargo.lock @@ -2497,6 +2497,7 @@ dependencies = [ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "solana-config-program 1.3.0", @@ -2505,6 +2506,7 @@ dependencies = [ "solana-metrics 1.3.0", "solana-rayon-threadlimit 1.3.0", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi 1.3.0", "solana-stake-program 1.3.0", "solana-vote-program 1.3.0", "symlink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2578,11 +2580,13 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "solana-config-program 1.3.0", "solana-metrics 1.3.0", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi 1.3.0", "solana-vote-program 1.3.0", "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2595,10 +2599,13 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 1.3.0", "solana-metrics 1.3.0", "solana-sdk 1.3.0", + "solana-sdk-macro-frozen-abi 1.3.0", "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/programs/stake/Cargo.toml b/programs/stake/Cargo.toml index 68e356fcb0..622999230a 100644 --- a/programs/stake/Cargo.toml +++ b/programs/stake/Cargo.toml @@ -19,11 +19,15 @@ solana-metrics = { path = "../../metrics", version = "1.3.0" } solana-sdk = { path = "../../sdk", version = "1.3.0" } solana-vote-program = { path = "../vote", version = "1.3.0" } solana-config-program = { path = "../config", version = "1.3.0" } +solana-sdk-macro-frozen-abi = { path = "../../sdk/macro-frozen-abi", version = "1.3.0" } thiserror = "1.0" [dev-dependencies] solana-logger = { path = "../../logger", version = "1.3.0" } +[build-dependencies] +rustc_version = "0.2" + [lib] crate-type = ["lib"] name = "solana_stake_program" diff --git a/programs/stake/build.rs b/programs/stake/build.rs new file mode 120000 index 0000000000..c632c0d98b --- /dev/null +++ b/programs/stake/build.rs @@ -0,0 +1 @@ +../../sdk/build.rs \ No newline at end of file diff --git a/programs/stake/src/lib.rs b/programs/stake/src/lib.rs index 78d1a5f706..de15175b0a 100644 --- a/programs/stake/src/lib.rs +++ b/programs/stake/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] use solana_sdk::genesis_config::GenesisConfig; pub mod config; @@ -9,3 +10,6 @@ solana_sdk::declare_id!("Stake11111111111111111111111111111111111111"); pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig) -> u64 { config::add_genesis_account(genesis_config) } + +#[macro_use] +extern crate solana_sdk_macro_frozen_abi; diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 76ba169cfa..b1d6ae497e 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -21,7 +21,7 @@ use solana_sdk::{ use solana_vote_program::vote_state::{VoteState, VoteStateVersions}; use std::collections::HashSet; -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] #[allow(clippy::large_enum_variant)] pub enum StakeState { Uninitialized, @@ -91,13 +91,13 @@ impl StakeState { } } -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] pub enum StakeAuthorize { Staker, Withdrawer, } -#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] pub struct Lockup { /// UnixTimestamp at which this stake will allow withdrawal, unless the /// transaction is signed by the custodian @@ -117,13 +117,13 @@ impl Lockup { } } -#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] pub struct Authorized { pub staker: Pubkey, pub withdrawer: Pubkey, } -#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] pub struct Meta { pub rent_exempt_reserve: u64, pub authorized: Authorized, @@ -152,7 +152,7 @@ impl Meta { } } -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] pub struct Delegation { /// to whom the stake is delegated pub voter_pubkey: Pubkey, @@ -313,7 +313,7 @@ impl Delegation { } } -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone, Copy)] +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] pub struct Stake { pub delegation: Delegation, /// credits observed is credits from vote account state when delegated or redeemed diff --git a/programs/vote/Cargo.toml b/programs/vote/Cargo.toml index 523d071df4..16339b4e59 100644 --- a/programs/vote/Cargo.toml +++ b/programs/vote/Cargo.toml @@ -15,10 +15,15 @@ num-derive = "0.3" num-traits = "0.2" serde = "1.0.112" serde_derive = "1.0.103" +solana-logger = { path = "../../logger", version = "1.3.0" } solana-metrics = { path = "../../metrics", version = "1.3.0" } solana-sdk = { path = "../../sdk", version = "1.3.0" } +solana-sdk-macro-frozen-abi = { path = "../../sdk/macro-frozen-abi", version = "1.3.0" } thiserror = "1.0" +[build-dependencies] +rustc_version = "0.2" + [lib] crate-type = ["lib"] name = "solana_vote_program" diff --git a/programs/vote/build.rs b/programs/vote/build.rs new file mode 120000 index 0000000000..c632c0d98b --- /dev/null +++ b/programs/vote/build.rs @@ -0,0 +1 @@ +../../sdk/build.rs \ No newline at end of file diff --git a/programs/vote/src/authorized_voters.rs b/programs/vote/src/authorized_voters.rs index 8606c2ccbf..134d06b6b4 100644 --- a/programs/vote/src/authorized_voters.rs +++ b/programs/vote/src/authorized_voters.rs @@ -3,7 +3,7 @@ use serde_derive::{Deserialize, Serialize}; use solana_sdk::{clock::Epoch, pubkey::Pubkey}; use std::collections::BTreeMap; -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone, AbiExample)] pub struct AuthorizedVoters { authorized_voters: BTreeMap, } diff --git a/programs/vote/src/lib.rs b/programs/vote/src/lib.rs index fbb37f7863..3ab1cb5828 100644 --- a/programs/vote/src/lib.rs +++ b/programs/vote/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] + pub mod authorized_voters; pub mod vote_instruction; pub mod vote_state; @@ -6,4 +8,7 @@ pub mod vote_transaction; #[macro_use] extern crate solana_metrics; +#[macro_use] +extern crate solana_sdk_macro_frozen_abi; + solana_sdk::declare_id!("Vote111111111111111111111111111111111111111"); diff --git a/programs/vote/src/vote_state/mod.rs b/programs/vote/src/vote_state/mod.rs index 17ccbf0de5..7cdc242692 100644 --- a/programs/vote/src/vote_state/mod.rs +++ b/programs/vote/src/vote_state/mod.rs @@ -36,7 +36,8 @@ pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64; // defaults, intended to limit block time drift to < 1hr pub const TIMESTAMP_SLOT_INTERVAL: u64 = 4500; -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] +#[frozen_abi(digest = "69hYtmmcuqPbhpc64ZaNJDidaUcg66CW6wzPFiuYZ3To")] +#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample)] pub struct Vote { /// A stack of votes starting with the oldest vote pub slots: Vec, @@ -60,7 +61,7 @@ impl Vote { } } -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample)] pub struct Lockout { pub slot: Slot, pub confirmation_count: u32, @@ -103,7 +104,7 @@ pub enum VoteAuthorize { Withdrawer, } -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone, AbiExample)] pub struct BlockTimestamp { pub slot: Slot, pub timestamp: UnixTimestamp, @@ -112,7 +113,7 @@ pub struct BlockTimestamp { // this is how many epochs a voter can be remembered for slashing const MAX_ITEMS: usize = 32; -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, AbiExample)] pub struct CircBuf { buf: [I; MAX_ITEMS], /// next pointer @@ -153,7 +154,8 @@ impl CircBuf { } } -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[frozen_abi(digest = "H7z93iz4PiRJqahQ9G1aJXao1huusBz47SA5WfP8g4yd")] +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone, AbiExample)] pub struct VoteState { /// the node that votes in this account pub node_pubkey: Pubkey, diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 2d9bc4b944..edca8caeac 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -37,6 +37,7 @@ solana-measure = { path = "../measure", version = "1.3.0" } solana-metrics = { path = "../metrics", version = "1.3.0" } solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.3.0" } solana-sdk = { path = "../sdk", version = "1.3.0" } +solana-sdk-macro-frozen-abi = { path = "../sdk/macro-frozen-abi", version = "1.3.0" } solana-stake-program = { path = "../programs/stake", version = "1.3.0" } solana-vote-program = { path = "../programs/vote", version = "1.3.0" } symlink = "0.1.0" @@ -55,3 +56,6 @@ solana-noop-program = { path = "../programs/noop", version = "1.3.0" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[build-dependencies] +rustc_version = "0.2" diff --git a/runtime/build.rs b/runtime/build.rs new file mode 120000 index 0000000000..8780ebe559 --- /dev/null +++ b/runtime/build.rs @@ -0,0 +1 @@ +../sdk/build.rs \ No newline at end of file diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index c006db6ac1..6b8342821d 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -31,13 +31,13 @@ use std::{ sync::{Arc, Mutex, RwLock}, }; -#[derive(Default, Debug)] +#[derive(Default, Debug, AbiExample)] pub(crate) struct ReadonlyLock { lock_count: Mutex, } /// This structure handles synchronization for db -#[derive(Default, Debug)] +#[derive(Default, Debug, AbiExample)] pub struct Accounts { /// my slot pub slot: Slot, diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index f99b0ecb95..7d0f91d937 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -132,7 +132,7 @@ impl AccountStorage { } } -#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize)] +#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize, AbiExample, AbiEnumVisitor)] pub enum AccountStorageStatus { Available = 0, Full = 1, @@ -324,7 +324,7 @@ pub fn get_temp_accounts_paths(count: u32) -> IOResult<(Vec, Vec ThreadPool { .unwrap() } +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +impl solana_sdk::abi_example::AbiExample for AccountsDB { + fn example() -> Self { + let accounts_db = AccountsDB::new_single(); + let key = Pubkey::default(); + let some_data_len = 5; + let some_slot: Slot = 0; + let account = Account::new(1, some_data_len, &key); + accounts_db.store(some_slot, &[(&key, &account)]); + accounts_db.add_root(0); + + accounts_db + } +} + impl Default for AccountsDB { fn default() -> Self { let num_threads = get_thread_count(); diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index 82a3b3b06f..f0743acb64 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -100,7 +100,7 @@ impl<'a> StoredAccount<'a> { } } -#[derive(Debug)] +#[derive(Debug, AbiExample)] #[allow(clippy::mutex_atomic)] pub struct AppendVec { path: PathBuf, diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 4c6152afcf..d426ecdf0d 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -74,6 +74,7 @@ pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0; pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5; type BankStatusCache = StatusCache>; +#[frozen_abi(digest = "9chBcbXVJ4fK7uGgydQzam5aHipaAKFw6V4LDFpjbE4w")] pub type BankSlotDelta = SlotDelta>; type TransactionAccountRefCells = Vec>>; type TransactionLoaderRefCells = Vec)>>; @@ -107,6 +108,20 @@ pub struct BankRc { pub(crate) slot: Slot, } +#[cfg(RUSTC_WITH_SPECIALIZATION)] +use solana_sdk::abi_example::AbiExample; +#[cfg(RUSTC_WITH_SPECIALIZATION)] +impl AbiExample for BankRc { + fn example() -> Self { + BankRc { + // Set parent to None to cut the recursion into another Bank + parent: RwLock::new(None), + accounts: AbiExample::example(), + slot: AbiExample::example(), + } + } +} + impl BankRc { pub(crate) fn new(accounts: Accounts, slot: Slot) -> Self { Self { @@ -121,7 +136,7 @@ impl BankRc { } } -#[derive(Default)] +#[derive(Default, AbiExample)] pub struct StatusCacheRc { /// where all the Accounts are stored /// A cache of signature statuses @@ -188,7 +203,7 @@ impl HashAgeKind { } } -#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize)] +#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)] struct UnusedAccounts { unused1: HashSet, unused2: HashSet, @@ -196,7 +211,8 @@ struct UnusedAccounts { } /// Manager for the state of all accounts and programs after processing its entries. -#[derive(Default, Deserialize, Serialize)] +#[frozen_abi(digest = "GsvisJfTaHxmTX4s6gQs2bZtxVggB7F325XDdXTA573p")] +#[derive(Default, Deserialize, Serialize, AbiExample)] pub struct Bank { /// References to accounts, parent and signature status #[serde(skip)] diff --git a/runtime/src/blockhash_queue.rs b/runtime/src/blockhash_queue.rs index be3eab19d3..9343c178d0 100644 --- a/runtime/src/blockhash_queue.rs +++ b/runtime/src/blockhash_queue.rs @@ -4,7 +4,7 @@ use solana_sdk::{ }; use std::collections::HashMap; -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, AbiExample)] struct HashAge { fee_calculator: FeeCalculator, hash_height: u64, @@ -12,7 +12,8 @@ struct HashAge { } /// Low memory overhead, so can be cloned for every checkpoint -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[frozen_abi(digest = "EwaoLA34VN18E95GvjmkeStUpWqTeBd7FGpd7mppLmEw")] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, AbiExample)] pub struct BlockhashQueue { /// updated whenever an hash is registered hash_height: u64, diff --git a/runtime/src/bloom.rs b/runtime/src/bloom.rs index c6dbd42bc5..7f09d291d7 100644 --- a/runtime/src/bloom.rs +++ b/runtime/src/bloom.rs @@ -11,7 +11,7 @@ pub trait BloomHashIndex { fn hash_at_index(&self, hash_index: u64) -> u64; } -#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, AbiExample)] pub struct Bloom { pub keys: Vec, pub bits: BitVec, diff --git a/runtime/src/epoch_stakes.rs b/runtime/src/epoch_stakes.rs index b7885c02d4..20d6079acb 100644 --- a/runtime/src/epoch_stakes.rs +++ b/runtime/src/epoch_stakes.rs @@ -7,13 +7,13 @@ use std::{collections::HashMap, sync::Arc}; pub type NodeIdToVoteAccounts = HashMap; pub type EpochAuthorizedVoters = HashMap; -#[derive(Clone, Serialize, Debug, Deserialize, Default, PartialEq)] +#[derive(Clone, Serialize, Debug, Deserialize, Default, PartialEq, AbiExample)] pub struct NodeVoteAccounts { pub vote_accounts: Vec, pub total_stake: u64, } -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize, AbiExample)] pub struct EpochStakes { stakes: Arc, total_stake: u64, diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index fd69472757..674d3600a7 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] pub mod accounts; pub mod accounts_db; pub mod accounts_index; @@ -38,5 +39,8 @@ extern crate solana_metrics; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate solana_sdk_macro_frozen_abi; + extern crate fs_extra; extern crate tempfile; diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index bece5a3916..109143e69d 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -262,6 +262,16 @@ impl Clone for MessageProcessor { } } } + +#[cfg(RUSTC_WITH_SPECIALIZATION)] +impl ::solana_sdk::abi_example::AbiExample for MessageProcessor { + fn example() -> Self { + // MessageProcessor's fields are #[serde(skip)]-ed and not Serialize + // so, just rely on Default anyway. + MessageProcessor::default() + } +} + impl MessageProcessor { /// Add a static entrypoint to intercept instructions before the dynamic loader. pub fn add_program(&mut self, program_id: Pubkey, process_instruction: ProcessInstruction) { diff --git a/runtime/src/rent_collector.rs b/runtime/src/rent_collector.rs index e71a1575cf..375b61f8c1 100644 --- a/runtime/src/rent_collector.rs +++ b/runtime/src/rent_collector.rs @@ -4,7 +4,7 @@ use solana_sdk::{ rent::Rent, sysvar, }; -#[derive(Default, Serialize, Deserialize, Clone)] +#[derive(Default, Serialize, Deserialize, Clone, AbiExample)] pub struct RentCollector { pub epoch: Epoch, pub epoch_schedule: EpochSchedule, diff --git a/runtime/src/serde_snapshot/future.rs b/runtime/src/serde_snapshot/future.rs index f78a1165aa..ce12527e32 100644 --- a/runtime/src/serde_snapshot/future.rs +++ b/runtime/src/serde_snapshot/future.rs @@ -7,6 +7,9 @@ pub(super) struct SerializableAccountStorageEntry { accounts_current_len: usize, } +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +impl solana_sdk::abi_example::IgnoreAsHelper for SerializableAccountStorageEntry {} + impl From<&AccountStorageEntry> for SerializableAccountStorageEntry { fn from(rhs: &AccountStorageEntry) -> Self { Self { diff --git a/runtime/src/serde_snapshot/legacy.rs b/runtime/src/serde_snapshot/legacy.rs index 4a6ba2c34c..aa554eba98 100644 --- a/runtime/src/serde_snapshot/legacy.rs +++ b/runtime/src/serde_snapshot/legacy.rs @@ -1,3 +1,5 @@ +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +use solana_sdk::abi_example::IgnoreAsHelper; use {super::*, solana_measure::measure::Measure, std::cell::RefCell}; // Serializable version of AccountStorageEntry for snapshot format @@ -8,6 +10,9 @@ pub(super) struct SerializableAccountStorageEntry { count_and_status: (usize, AccountStorageStatus), } +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +impl IgnoreAsHelper for SerializableAccountStorageEntry {} + impl From<&AccountStorageEntry> for SerializableAccountStorageEntry { fn from(rhs: &AccountStorageEntry) -> Self { Self { @@ -30,6 +35,9 @@ struct SerializableAppendVec { current_len: usize, } +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +impl IgnoreAsHelper for SerializableAppendVec {} + impl From<&AppendVec> for SerializableAppendVec { fn from(rhs: &AppendVec) -> SerializableAppendVec { SerializableAppendVec { diff --git a/runtime/src/serde_snapshot/tests.rs b/runtime/src/serde_snapshot/tests.rs index a756d4bb59..14a9d53a78 100644 --- a/runtime/src/serde_snapshot/tests.rs +++ b/runtime/src/serde_snapshot/tests.rs @@ -278,3 +278,50 @@ fn test_bank_serialize_newer() { fn test_bank_serialize_older() { test_bank_serialize_style(SerdeStyle::OLDER) } + +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +mod test_bank_rc_serialize { + use super::*; + + // These some what long test harness is required to freeze the ABI of + // BankRc's serialization due to versioned nature + #[frozen_abi(digest = "HfCP74JKqPdeAccNJEj7KEoNxtsmX3zRqc2rpTy1NC7H")] + #[derive(Serialize, AbiExample)] + pub struct BandRcAbiTestWrapperFuture { + #[serde(serialize_with = "wrapper_future")] + bank_rc: BankRc, + } + + pub fn wrapper_future(bank_rc: &BankRc, s: S) -> std::result::Result + where + S: serde::Serializer, + { + let snapshot_storages = bank_rc.accounts.accounts_db.get_snapshot_storages(0); + (SerializableBankRc:: { + bank_rc, + snapshot_storages: &snapshot_storages, + phantom: std::marker::PhantomData::default(), + }) + .serialize(s) + } + + #[frozen_abi(digest = "43niyekyWwreLALcdEeFFpd7h8U6pgSXGqfKBRw8H7Vy")] + #[derive(Serialize, AbiExample)] + pub struct BandRcAbiTestWrapperLegacy { + #[serde(serialize_with = "wrapper_legacy")] + bank_rc: BankRc, + } + + pub fn wrapper_legacy(bank_rc: &BankRc, s: S) -> std::result::Result + where + S: serde::Serializer, + { + let snapshot_storages = bank_rc.accounts.accounts_db.get_snapshot_storages(0); + (SerializableBankRc:: { + bank_rc, + snapshot_storages: &snapshot_storages, + phantom: std::marker::PhantomData::default(), + }) + .serialize(s) + } +} diff --git a/runtime/src/serde_snapshot/utils.rs b/runtime/src/serde_snapshot/utils.rs index 043cc51470..a6af938e84 100644 --- a/runtime/src/serde_snapshot/utils.rs +++ b/runtime/src/serde_snapshot/utils.rs @@ -2,6 +2,8 @@ use serde::{ ser::{SerializeSeq, SerializeTuple}, Serialize, Serializer, }; +#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] +use solana_sdk::abi_example::IgnoreAsHelper; // consumes an iterator and returns an object that will serialize as a serde seq #[allow(dead_code)] @@ -15,6 +17,9 @@ where iter: std::cell::RefCell>, } + #[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] + impl IgnoreAsHelper for SerializableSequencedIterator {} + impl Serialize for SerializableSequencedIterator where I: IntoIterator, @@ -51,6 +56,9 @@ where iter: std::cell::RefCell>, } + #[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] + impl IgnoreAsHelper for SerializableSequencedIterator {} + impl Serialize for SerializableSequencedIterator where I: IntoIterator, @@ -87,6 +95,9 @@ where iter: std::cell::RefCell>, } + #[cfg(all(test, RUSTC_WITH_SPECIALIZATION))] + impl IgnoreAsHelper for SerializableMappedIterator {} + impl Serialize for SerializableMappedIterator where K: Serialize, diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index 3a6c5cf2a4..5553b9d816 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -7,7 +7,7 @@ use solana_stake_program::stake_state::{new_stake_history_entry, Delegation, Sta use solana_vote_program::vote_state::VoteState; use std::collections::HashMap; -#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize)] +#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)] pub struct Stakes { /// vote accounts vote_accounts: HashMap, diff --git a/runtime/src/status_cache.rs b/runtime/src/status_cache.rs index ffeff7db1c..80da95b86d 100644 --- a/runtime/src/status_cache.rs +++ b/runtime/src/status_cache.rs @@ -41,7 +41,7 @@ pub struct SignatureConfirmationStatus { pub status: T, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, AbiExample)] pub struct StatusCache { cache: StatusMap, roots: HashSet, diff --git a/sdk/macro-frozen-abi/Cargo.toml b/sdk/macro-frozen-abi/Cargo.toml index f8665c2c9a..00a5e073f0 100644 --- a/sdk/macro-frozen-abi/Cargo.toml +++ b/sdk/macro-frozen-abi/Cargo.toml @@ -7,7 +7,6 @@ repository = "https://github.com/solana-labs/solana" homepage = "https://solana.com/" license = "Apache-2.0" edition = "2018" -build = "../build.rs" [lib] proc-macro = true diff --git a/sdk/macro-frozen-abi/build.rs b/sdk/macro-frozen-abi/build.rs new file mode 120000 index 0000000000..10238032f5 --- /dev/null +++ b/sdk/macro-frozen-abi/build.rs @@ -0,0 +1 @@ +../build.rs \ No newline at end of file diff --git a/sdk/macro-frozen-abi/src/lib.rs b/sdk/macro-frozen-abi/src/lib.rs index a83e612eb9..e53171dc1d 100644 --- a/sdk/macro-frozen-abi/src/lib.rs +++ b/sdk/macro-frozen-abi/src/lib.rs @@ -307,7 +307,7 @@ fn quote_for_test( #[cfg(test)] mod #test_mod_ident { use super::*; - use ::solana_sdk::{abi_digester::AbiEnumVisitor, abi_example::AbiExample}; + use ::solana_sdk::abi_example::{AbiExample, AbiEnumVisitor}; #[test] fn test_abi_digest() { @@ -321,13 +321,18 @@ fn quote_for_test( ::log::error!("digest error: {:#?}", result); } result.unwrap(); + let actual_digest = format!("{}", hash); if ::std::env::var("SOLANA_ABI_BULK_UPDATE").is_ok() { - if #expected_digest != format!("{}", hash) { + if #expected_digest != actual_digest { #p!("sed -i -e 's/{}/{}/g' $(git grep --files-with-matches frozen_abi)", #expected_digest, hash); } ::log::warn!("Not testing the abi digest under SOLANA_ABI_BULK_UPDATE!"); } else { - assert_eq!(#expected_digest, format!("{}", hash), "Possibly ABI changed? Confirm the diff by rerunning before and after this test failed with SOLANA_ABI_DUMP_DIR"); + if let Ok(dir) = ::std::env::var("SOLANA_ABI_DUMP_DIR") { + assert_eq!(#expected_digest, actual_digest, "Possibly ABI changed? Examine the diff in SOLANA_ABI_DUMP_DIR!: $ diff -u {}/*{}* {}/*{}*", dir, #expected_digest, dir, actual_digest); + } else { + assert_eq!(#expected_digest, actual_digest, "Possibly ABI changed? Confirm the diff by rerunning before and after this test failed with SOLANA_ABI_DUMP_DIR!"); + } } } } diff --git a/sdk/src/abi_example.rs b/sdk/src/abi_example.rs index 8f4c369a16..f2126c32ab 100644 --- a/sdk/src/abi_example.rs +++ b/sdk/src/abi_example.rs @@ -347,7 +347,7 @@ impl AbiExample for std::sync::RwLock { } } -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}; impl< T: std::cmp::Eq + std::hash::Hash + AbiExample, @@ -379,6 +379,13 @@ impl AbiExample for Vec { } } +impl AbiExample for VecDeque { + fn example() -> Self { + info!("AbiExample for (Vec): {}", type_name::()); + VecDeque::from(vec![T::example()]) + } +} + impl AbiExample for HashSet { diff --git a/sdk/src/account.rs b/sdk/src/account.rs index be337f4c30..0e0d2710c7 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -8,7 +8,8 @@ use std::{ /// An Account with data that is stored on chain #[repr(C)] -#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Default)] +#[frozen_abi(digest = "By9FhuLAM947tkLxbTVQru9ZKTrRQuvCR5W387nPSLNu")] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Default, AbiExample)] #[serde(rename_all = "camelCase")] pub struct Account { /// lamports in the account diff --git a/sdk/src/epoch_schedule.rs b/sdk/src/epoch_schedule.rs index c266a49403..87c5368498 100644 --- a/sdk/src/epoch_schedule.rs +++ b/sdk/src/epoch_schedule.rs @@ -17,7 +17,7 @@ pub const MAX_LEADER_SCHEDULE_EPOCH_OFFSET: u64 = 3; pub const MINIMUM_SLOTS_PER_EPOCH: u64 = 32; #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize, AbiExample)] #[serde(rename_all = "camelCase")] pub struct EpochSchedule { /// The maximum number of slots in each epoch. diff --git a/sdk/src/fee_calculator.rs b/sdk/src/fee_calculator.rs index e255943b5f..2729bea431 100644 --- a/sdk/src/fee_calculator.rs +++ b/sdk/src/fee_calculator.rs @@ -2,7 +2,7 @@ use crate::clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT}; use crate::message::Message; use log::*; -#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, AbiExample)] #[serde(rename_all = "camelCase")] pub struct FeeCalculator { // The current cost of a signature This amount may increase/decrease over time based on @@ -30,7 +30,7 @@ impl FeeCalculator { } } -#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, AbiExample)] #[serde(rename_all = "camelCase")] pub struct FeeRateGovernor { // The current cost of a signature This amount may increase/decrease over time based on diff --git a/sdk/src/genesis_config.rs b/sdk/src/genesis_config.rs index 75254f47ed..df9cb06901 100644 --- a/sdk/src/genesis_config.rs +++ b/sdk/src/genesis_config.rs @@ -30,14 +30,15 @@ use std::{ // deprecated default that is no longer used pub const UNUSED_DEFAULT: u64 = 1024; -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, AbiEnumVisitor, AbiExample)] pub enum OperatingMode { Preview, // Next set of cluster features to be promoted to Stable Stable, // Stable cluster features Development, // All features (including experimental features) } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[frozen_abi(digest = "2KQs7m2DbLxkEx6pY9Z6qwYJAhN2Q4AdoNgUcULmscgB")] +#[derive(Serialize, Deserialize, Debug, Clone, AbiExample)] pub struct GenesisConfig { /// when the network (bootstrap validator) was started relative to the UNIX Epoch pub creation_time: UnixTimestamp, diff --git a/sdk/src/hard_forks.rs b/sdk/src/hard_forks.rs index 03d32588dc..6ae25076b7 100644 --- a/sdk/src/hard_forks.rs +++ b/sdk/src/hard_forks.rs @@ -4,7 +4,7 @@ use byteorder::{ByteOrder, LittleEndian}; use solana_sdk::clock::Slot; -#[derive(Default, Clone, Deserialize, Serialize)] +#[derive(Default, Clone, Deserialize, Serialize, AbiExample)] pub struct HardForks { hard_forks: Vec<(Slot, usize)>, } diff --git a/sdk/src/hash.rs b/sdk/src/hash.rs index 46f1a371bb..9597418970 100644 --- a/sdk/src/hash.rs +++ b/sdk/src/hash.rs @@ -6,7 +6,9 @@ use std::{convert::TryFrom, fmt, mem, str::FromStr}; use thiserror::Error; pub const HASH_BYTES: usize = 32; -#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive( + Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, AbiExample, +)] #[repr(transparent)] pub struct Hash([u8; HASH_BYTES]); diff --git a/sdk/src/inflation.rs b/sdk/src/inflation.rs index 56b58cc815..a99be5cb7c 100644 --- a/sdk/src/inflation.rs +++ b/sdk/src/inflation.rs @@ -1,6 +1,6 @@ //! configuration for network inflation -#[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Copy)] +#[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Copy, AbiExample)] #[serde(rename_all = "camelCase")] pub struct Inflation { /// Initial inflation percentage, from time=0 diff --git a/sdk/src/instruction.rs b/sdk/src/instruction.rs index 6131c37355..46b7cc3343 100644 --- a/sdk/src/instruction.rs +++ b/sdk/src/instruction.rs @@ -7,7 +7,7 @@ use serde::Serialize; use thiserror::Error; /// Reasons the runtime might have rejected an instruction. -#[derive(Serialize, Deserialize, Debug, Error, PartialEq, Eq, Clone)] +#[derive(Serialize, Deserialize, Debug, Error, PartialEq, Eq, Clone, AbiExample, AbiEnumVisitor)] pub enum InstructionError { /// Deprecated! Use CustomError instead! /// The program instruction returned an error @@ -214,7 +214,7 @@ impl AccountMeta { } /// An instruction to execute a program -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample)] #[serde(rename_all = "camelCase")] pub struct CompiledInstruction { /// Index into the transaction keys array indicating the program account that executes this instruction diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 470f4eb5f5..99c3b7098f 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -101,7 +101,5 @@ extern crate serde_derive; pub extern crate bs58; extern crate log as logger; -#[cfg(RUSTC_WITH_SPECIALIZATION)] -#[cfg(test)] #[macro_use] extern crate solana_sdk_macro_frozen_abi; diff --git a/sdk/src/message.rs b/sdk/src/message.rs index f82f1b0e24..4814fdb1d8 100644 --- a/sdk/src/message.rs +++ b/sdk/src/message.rs @@ -138,7 +138,8 @@ fn get_program_ids(instructions: &[Instruction]) -> Vec { .collect() } -#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)] +#[frozen_abi(digest = "BVC5RhetsNpheGipt5rUrkR6RDDUHtD5sCLK1UjymL4S")] +#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, AbiExample)] #[serde(rename_all = "camelCase")] pub struct MessageHeader { /// The number of signatures required for this message to be considered valid. The @@ -156,7 +157,8 @@ pub struct MessageHeader { pub num_readonly_unsigned_accounts: u8, } -#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)] +#[frozen_abi(digest = "A18PN3BWKw4hU69STY79SyRS3tS6w54nCgYRRx77vQiL")] +#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, AbiExample)] #[serde(rename_all = "camelCase")] pub struct Message { /// The message header, identifying signed and read-only `account_keys` diff --git a/sdk/src/packet.rs b/sdk/src/packet.rs index 47d0fac369..ae35572a83 100644 --- a/sdk/src/packet.rs +++ b/sdk/src/packet.rs @@ -12,7 +12,8 @@ use std::{ /// 8 bytes is the size of the fragment header pub const PACKET_DATA_SIZE: usize = 1280 - 40 - 8; -#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +#[frozen_abi(digest = "9AiPd36yycNg18hDuCBVGwpTfzjX1VV4QtUKUdqeyAKH")] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, AbiExample)] #[repr(C)] pub struct Meta { pub size: usize, diff --git a/sdk/src/poh_config.rs b/sdk/src/poh_config.rs index 76334e20b3..5c14e6d6de 100644 --- a/sdk/src/poh_config.rs +++ b/sdk/src/poh_config.rs @@ -1,7 +1,7 @@ use crate::clock::DEFAULT_TICKS_PER_SECOND; use std::time::Duration; -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, AbiExample)] pub struct PohConfig { /// The target tick rate of the cluster. pub target_tick_duration: Duration, diff --git a/sdk/src/pubkey.rs b/sdk/src/pubkey.rs index a41b9b1801..36c739ed01 100644 --- a/sdk/src/pubkey.rs +++ b/sdk/src/pubkey.rs @@ -26,7 +26,9 @@ impl DecodeError for PubkeyError { } #[repr(transparent)] -#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive( + Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, AbiExample, +)] pub struct Pubkey([u8; 32]); impl crate::sanitize::Sanitize for Pubkey {} diff --git a/sdk/src/rent.rs b/sdk/src/rent.rs index 0e2eed8286..ecfdcc1ceb 100644 --- a/sdk/src/rent.rs +++ b/sdk/src/rent.rs @@ -1,7 +1,7 @@ //! configuration for network rent #[repr(C)] -#[derive(Serialize, Deserialize, PartialEq, Clone, Copy, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Clone, Copy, Debug, AbiExample)] pub struct Rent { /// Rental rate pub lamports_per_byte_year: u64, diff --git a/sdk/src/short_vec.rs b/sdk/src/short_vec.rs index 32f22b1d5a..3f9e94e3dc 100644 --- a/sdk/src/short_vec.rs +++ b/sdk/src/short_vec.rs @@ -10,6 +10,7 @@ use std::{fmt, marker::PhantomData, mem::size_of}; /// bytes. Each byte follows the same pattern until the 3rd byte. The 3rd /// byte, if needed, uses all 8 bits to store the last byte of the original /// value. +#[derive(AbiExample)] pub struct ShortU16(pub u16); impl Serialize for ShortU16 { diff --git a/sdk/src/signature.rs b/sdk/src/signature.rs index d360471f6a..423e47acbe 100644 --- a/sdk/src/signature.rs +++ b/sdk/src/signature.rs @@ -47,7 +47,9 @@ impl Keypair { } #[repr(transparent)] -#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive( + Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, AbiExample, +)] pub struct Signature(GenericArray); impl crate::sanitize::Sanitize for Signature {} diff --git a/sdk/src/stake_history.rs b/sdk/src/stake_history.rs index aaece88100..818a0c427e 100644 --- a/sdk/src/stake_history.rs +++ b/sdk/src/stake_history.rs @@ -8,7 +8,7 @@ use std::ops::Deref; pub const MAX_ENTRIES: usize = 512; // it should never take as many as 512 epochs to warm up or cool down -#[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone, AbiExample)] pub struct StakeHistoryEntry { pub effective: u64, // effective stake at this epoch pub activating: u64, // sum of portion of stakes not fully warmed up @@ -16,7 +16,7 @@ pub struct StakeHistoryEntry { } #[repr(C)] -#[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone, AbiExample)] pub struct StakeHistory(Vec<(Epoch, StakeHistoryEntry)>); impl StakeHistory { diff --git a/sdk/src/system_instruction.rs b/sdk/src/system_instruction.rs index dabc716fdb..b737deaa80 100644 --- a/sdk/src/system_instruction.rs +++ b/sdk/src/system_instruction.rs @@ -52,7 +52,8 @@ impl DecodeError for NonceError { /// maximum permitted size of data: 10 MB pub const MAX_PERMITTED_DATA_LENGTH: u64 = 10 * 1024 * 1024; -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[frozen_abi(digest = "E343asdJPd3aEbHSsmeeGzvztc9X2maaHhWxVS4P6hvW")] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, AbiExample, AbiEnumVisitor)] pub enum SystemInstruction { /// Create a new account /// diff --git a/sdk/src/transaction.rs b/sdk/src/transaction.rs index a7d778fb93..6105c3d7f5 100644 --- a/sdk/src/transaction.rs +++ b/sdk/src/transaction.rs @@ -14,7 +14,7 @@ use std::result; use thiserror::Error; /// Reasons a transaction might be rejected. -#[derive(Error, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive(Error, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample, AbiEnumVisitor)] pub enum TransactionError { /// An account is already being processed in another transaction in a way /// that does not support parallelism @@ -88,7 +88,8 @@ pub enum TransactionError { pub type Result = result::Result; /// An atomic transaction -#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)] +#[frozen_abi(digest = "GoxM5ZMMjM2FSuY1VtuMhs1j8u9kMuYsH3dpYcSVVnTe")] +#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, AbiExample)] pub struct Transaction { /// A set of digital signatures of `account_keys`, `program_ids`, `recent_blockhash`, and `instructions`, signed by the first /// signatures.len() keys of account_keys diff --git a/version/Cargo.toml b/version/Cargo.toml index a4f5095ea3..5d3f751664 100644 --- a/version/Cargo.toml +++ b/version/Cargo.toml @@ -9,12 +9,18 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] +log = "0.4.8" serde = "1.0.112" serde_derive = "1.0.103" +solana-logger = { path = "../logger", version = "1.3.0" } solana-sdk = { path = "../sdk", version = "1.3.0" } +solana-sdk-macro-frozen-abi = { path = "../sdk/macro-frozen-abi", version = "1.2.0" } [lib] name = "solana_version" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[build-dependencies] +rustc_version = "0.2" diff --git a/version/build.rs b/version/build.rs new file mode 120000 index 0000000000..8780ebe559 --- /dev/null +++ b/version/build.rs @@ -0,0 +1 @@ +../sdk/build.rs \ No newline at end of file diff --git a/version/src/lib.rs b/version/src/lib.rs index ad769a0167..7e74c60579 100644 --- a/version/src/lib.rs +++ b/version/src/lib.rs @@ -1,9 +1,14 @@ +#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] + extern crate serde_derive; use serde_derive::{Deserialize, Serialize}; use solana_sdk::sanitize::Sanitize; use std::fmt; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[macro_use] +extern crate solana_sdk_macro_frozen_abi; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)] pub struct Version { major: u16, minor: u16,