diff --git a/Cargo.lock b/Cargo.lock index 508210187..1f22d8f06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1994,6 +1994,7 @@ dependencies = [ "solana-netutil 0.12.0", "solana-runtime 0.12.0", "solana-sdk 0.12.0", + "solana-vote-api 0.12.0", "solana-vote-program 0.12.0", "solana-vote-signer 0.12.0", "sys-info 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2108,6 +2109,7 @@ dependencies = [ "solana-netutil 0.12.0", "solana-runtime 0.12.0", "solana-sdk 0.12.0", + "solana-vote-api 0.12.0", "solana-vote-signer 0.12.0", ] @@ -2246,6 +2248,7 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "solana-sdk 0.12.0", + "solana-vote-api 0.12.0", ] [[package]] @@ -2258,6 +2261,7 @@ dependencies = [ "solana-rewards-api 0.12.0", "solana-runtime 0.12.0", "solana-sdk 0.12.0", + "solana-vote-api 0.12.0", ] [[package]] @@ -2280,6 +2284,7 @@ dependencies = [ "solana-native-loader 0.12.0", "solana-sdk 0.12.0", "solana-system-program 0.12.0", + "solana-vote-api 0.12.0", ] [[package]] @@ -2345,6 +2350,17 @@ dependencies = [ "solana-metrics 0.12.0", ] +[[package]] +name = "solana-vote-api" +version = "0.12.0" +dependencies = [ + "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-sdk 0.12.0", +] + [[package]] name = "solana-vote-program" version = "0.12.0" @@ -2355,6 +2371,7 @@ dependencies = [ "solana-metrics 0.12.0", "solana-runtime 0.12.0", "solana-sdk 0.12.0", + "solana-vote-api 0.12.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4ffe5cab2..90a54b810 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,6 +83,7 @@ members = [ "programs/native/storage", "programs/native/system", "programs/native/vote", + "programs/native/vote_api", "replicator", "sdk", "upload-perf", diff --git a/core/Cargo.toml b/core/Cargo.toml index d161749fa..add002465 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -53,6 +53,7 @@ solana-metrics = { path = "../metrics", version = "0.12.0" } solana-netutil = { path = "../netutil", version = "0.12.0" } solana-runtime = { path = "../runtime", version = "0.12.0" } solana-sdk = { path = "../sdk", version = "0.12.0" } +solana-vote-api = { path = "../programs/native/vote_api", version = "0.12.0" } solana-vote-signer = { path = "../vote-signer", version = "0.12.0" } sys-info = "0.5.6" tokio = "0.1" diff --git a/core/src/entry.rs b/core/src/entry.rs index d06e42864..0d75efb4a 100644 --- a/core/src/entry.rs +++ b/core/src/entry.rs @@ -13,8 +13,8 @@ use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::Transaction; -use solana_sdk::vote_program::Vote; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_instruction::Vote; +use solana_vote_api::vote_transaction::VoteTransaction; use std::borrow::Borrow; use std::io::Cursor; use std::mem::size_of; diff --git a/core/src/fullnode.rs b/core/src/fullnode.rs index 29bd4592e..a1c50a382 100644 --- a/core/src/fullnode.rs +++ b/core/src/fullnode.rs @@ -25,7 +25,7 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::timing::timestamp; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_transaction::VoteTransaction; use std::net::UdpSocket; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/core/src/leader_confirmation_service.rs b/core/src/leader_confirmation_service.rs index 28d7c9ecc..7a86f30b1 100644 --- a/core/src/leader_confirmation_service.rs +++ b/core/src/leader_confirmation_service.rs @@ -6,7 +6,7 @@ use crate::service::Service; use solana_metrics::{influxdb, submit}; use solana_runtime::bank::Bank; use solana_sdk::timing; -use solana_sdk::vote_program::VoteState; +use solana_vote_api::vote_state::VoteState; use std::result; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -127,7 +127,7 @@ mod tests { use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::hash; use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::vote_transaction::VoteTransaction; + use solana_vote_api::vote_transaction::VoteTransaction; use std::sync::Arc; #[test] diff --git a/core/src/local_cluster.rs b/core/src/local_cluster.rs index 89ad47099..bacf02eec 100644 --- a/core/src/local_cluster.rs +++ b/core/src/local_cluster.rs @@ -10,8 +10,8 @@ use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; -use solana_sdk::vote_program::VoteState; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_state::VoteState; +use solana_vote_api::vote_transaction::VoteTransaction; use std::fs::remove_dir_all; use std::io::{Error, ErrorKind, Result}; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 50060cbd6..78e7c2ac8 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -18,7 +18,7 @@ use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::KeypairUtil; use solana_sdk::timing::duration_as_ms; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_transaction::VoteTransaction; use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{channel, Receiver, RecvTimeoutError}; diff --git a/core/src/staking_utils.rs b/core/src/staking_utils.rs index 75d69e48a..89adfc3b4 100644 --- a/core/src/staking_utils.rs +++ b/core/src/staking_utils.rs @@ -1,7 +1,7 @@ use hashbrown::HashMap; use solana_runtime::bank::Bank; use solana_sdk::pubkey::Pubkey; -use solana_sdk::vote_program::VoteState; +use solana_vote_api::vote_state::VoteState; /// Looks through vote accounts, and finds the latest slot that has achieved /// supermajority lockout diff --git a/core/src/storage_stage.rs b/core/src/storage_stage.rs index 13a10c662..7517bede9 100644 --- a/core/src/storage_stage.rs +++ b/core/src/storage_stage.rs @@ -18,7 +18,6 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, Signature}; use solana_sdk::storage_program::{self, StorageProgram, StorageTransaction}; use solana_sdk::transaction::Transaction; -use solana_sdk::vote_program; use std::collections::HashSet; use std::io; use std::mem::size_of; @@ -368,7 +367,7 @@ impl StorageStage { // the storage_keys with their signatures. for tx in entry.transactions { for (i, program_id) in tx.program_ids.iter().enumerate() { - if vote_program::check_id(&program_id) { + if solana_vote_api::check_id(&program_id) { debug!( "generating storage_keys from votes current_key_idx: {}", *current_key_idx @@ -459,7 +458,7 @@ mod tests { use solana_sdk::hash::Hasher; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::vote_transaction::VoteTransaction; + use solana_vote_api::vote_transaction::VoteTransaction; use std::cmp::{max, min}; use std::fs::remove_dir_all; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; diff --git a/core/src/thin_client.rs b/core/src/thin_client.rs index 4b3ca8c1b..f89c47f0f 100644 --- a/core/src/thin_client.rs +++ b/core/src/thin_client.rs @@ -490,8 +490,8 @@ mod tests { use crate::client::mk_client; use bincode::{deserialize, serialize}; use solana_sdk::system_instruction::SystemInstruction; - use solana_sdk::vote_program::VoteState; - use solana_sdk::vote_transaction::VoteTransaction; + use solana_vote_api::vote_state::VoteState; + use solana_vote_api::vote_transaction::VoteTransaction; use std::fs::remove_dir_all; #[test] diff --git a/core/src/voting_keypair.rs b/core/src/voting_keypair.rs index e03df9190..e6ede8367 100644 --- a/core/src/voting_keypair.rs +++ b/core/src/voting_keypair.rs @@ -101,7 +101,7 @@ pub mod tests { use solana_runtime::bank::Bank; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::vote_transaction::VoteTransaction; + use solana_vote_api::vote_transaction::VoteTransaction; pub fn new_vote_account( from_keypair: &Keypair, diff --git a/fullnode/Cargo.toml b/fullnode/Cargo.toml index 1bfd5c18d..93aca84fb 100644 --- a/fullnode/Cargo.toml +++ b/fullnode/Cargo.toml @@ -20,6 +20,7 @@ solana-netutil = { path = "../netutil", version = "0.12.0" } solana-metrics = { path = "../metrics", version = "0.12.0" } solana-runtime = { path = "../runtime", version = "0.12.0" } solana-sdk = { path = "../sdk", version = "0.12.0" } +solana-vote-api = { path = "../programs/native/vote_api", version = "0.12.0" } solana-vote-signer = { path = "../vote-signer", version = "0.12.0" } [features] diff --git a/fullnode/src/main.rs b/fullnode/src/main.rs index 87a4781aa..b23595849 100644 --- a/fullnode/src/main.rs +++ b/fullnode/src/main.rs @@ -10,8 +10,8 @@ use solana::voting_keypair::{RemoteVoteSigner, VotingKeypair}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::vote_program::VoteState; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_state::VoteState; +use solana_vote_api::vote_transaction::VoteTransaction; use solana_vote_signer::rpc::{LocalVoteSigner, VoteSigner}; use std::fs::File; use std::io::{Error, ErrorKind, Result}; diff --git a/programs/native/rewards/Cargo.toml b/programs/native/rewards/Cargo.toml index 9104ad148..7126d05e4 100644 --- a/programs/native/rewards/Cargo.toml +++ b/programs/native/rewards/Cargo.toml @@ -14,6 +14,7 @@ log = "0.4.2" solana-logger = { path = "../../../logger", version = "0.12.0" } solana-sdk = { path = "../../../sdk", version = "0.12.0" } solana-rewards-api = { path = "../rewards_api", version = "0.12.0" } +solana-vote-api = { path = "../vote_api", version = "0.12.0" } [dev-dependencies] solana-runtime = { path = "../../../runtime", version = "0.12.0" } diff --git a/programs/native/rewards/src/lib.rs b/programs/native/rewards/src/lib.rs index f47f645ac..7559a5c3d 100644 --- a/programs/native/rewards/src/lib.rs +++ b/programs/native/rewards/src/lib.rs @@ -8,7 +8,7 @@ use solana_sdk::account::KeyedAccount; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; use solana_sdk::solana_entrypoint; -use solana_sdk::vote_program::{self, VoteState}; +use solana_vote_api::vote_state::VoteState; const INTEREST_PER_CREDIT_DIVISOR: u64 = 100; // Staker earns 1/INTEREST_PER_CREDIT_DIVISOR of interest per credit const MINIMUM_CREDITS_PER_REDEMPTION: u64 = 1; // Raise this to either minimize congestion or lengthen the interest period @@ -35,7 +35,7 @@ fn redeem_vote_credits(keyed_accounts: &mut [KeyedAccount]) -> Result<(), Progra Err(ProgramError::InvalidArgument)?; } - if !vote_program::check_id(&keyed_accounts[0].account.owner) { + if !solana_vote_api::check_id(&keyed_accounts[0].account.owner) { error!("account[0] is not assigned to the VOTE_PROGRAM"); Err(ProgramError::InvalidArgument)?; } @@ -87,7 +87,8 @@ mod tests { use solana_rewards_api::rewards_state::RewardsState; use solana_sdk::account::Account; use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::vote_program::{self, Vote}; + use solana_vote_api::vote_instruction::Vote; + use solana_vote_api::vote_state; fn create_rewards_account(tokens: u64) -> Account { let space = RewardsState::max_size(); @@ -113,8 +114,8 @@ mod tests { let mut staker_account = Account::new(100, 0, Pubkey::default()); let vote_id = Keypair::new().pubkey(); - let mut vote_account = vote_program::create_vote_account(100); - vote_program::initialize_and_deserialize( + let mut vote_account = vote_state::create_vote_account(100); + vote_state::initialize_and_deserialize( &staker_id, &mut staker_account, &vote_id, @@ -122,17 +123,17 @@ mod tests { ) .unwrap(); - for i in 0..vote_program::MAX_LOCKOUT_HISTORY { + for i in 0..vote_state::MAX_LOCKOUT_HISTORY { let vote = Vote::new(i as u64); let vote_state = - vote_program::vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()) + vote_state::vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()) .unwrap(); assert_eq!(vote_state.credits(), 0); } - let vote = Vote::new(vote_program::MAX_LOCKOUT_HISTORY as u64 + 1); + let vote = Vote::new(vote_state::MAX_LOCKOUT_HISTORY as u64 + 1); let vote_state = - vote_program::vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()).unwrap(); + vote_state::vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()).unwrap(); assert_eq!(vote_state.credits(), 1); let rewards_id = Keypair::new().pubkey(); diff --git a/programs/native/rewards/tests/rewards.rs b/programs/native/rewards/tests/rewards.rs index 588940686..a42e2608a 100644 --- a/programs/native/rewards/tests/rewards.rs +++ b/programs/native/rewards/tests/rewards.rs @@ -1,12 +1,11 @@ -use solana_rewards_api; use solana_rewards_api::rewards_transaction::RewardsTransaction; use solana_runtime::bank::{Bank, Result}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::hash; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::vote_program::{self, VoteState}; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_state::{self, VoteState}; +use solana_vote_api::vote_transaction::VoteTransaction; struct RewardsBank<'a> { bank: &'a Bank, @@ -81,12 +80,12 @@ fn test_redeem_vote_credits_via_bank() { .unwrap(); // The validator submits votes to accumulate credits. - for i in 0..vote_program::MAX_LOCKOUT_HISTORY { + for i in 0..vote_state::MAX_LOCKOUT_HISTORY { let vote_state = rewards_bank.submit_vote(&vote_keypair, i as u64).unwrap(); assert_eq!(vote_state.credits(), 0); } let vote_state = rewards_bank - .submit_vote(&vote_keypair, vote_program::MAX_LOCKOUT_HISTORY as u64 + 1) + .submit_vote(&vote_keypair, vote_state::MAX_LOCKOUT_HISTORY as u64 + 1) .unwrap(); assert_eq!(vote_state.credits(), 1); diff --git a/programs/native/rewards_api/Cargo.toml b/programs/native/rewards_api/Cargo.toml index 0b66574ae..4af32f037 100644 --- a/programs/native/rewards_api/Cargo.toml +++ b/programs/native/rewards_api/Cargo.toml @@ -13,6 +13,7 @@ bincode = "1.1.2" serde = "1.0.89" serde_derive = "1.0.89" solana-sdk = { path = "../../../sdk", version = "0.12.0" } +solana-vote-api = { path = "../vote_api", version = "0.12.0" } [lib] name = "solana_rewards_api" diff --git a/programs/native/rewards_api/src/rewards_transaction.rs b/programs/native/rewards_api/src/rewards_transaction.rs index 7d8e9708d..5ff60577e 100644 --- a/programs/native/rewards_api/src/rewards_transaction.rs +++ b/programs/native/rewards_api/src/rewards_transaction.rs @@ -10,7 +10,7 @@ use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::transaction::Transaction; use solana_sdk::transaction_builder::TransactionBuilder; -use solana_sdk::vote_program::VoteInstruction; +use solana_vote_api::vote_instruction::VoteInstruction; pub struct RewardsTransaction {} diff --git a/programs/native/vote/Cargo.toml b/programs/native/vote/Cargo.toml index fa3c7b503..0d332ab3c 100644 --- a/programs/native/vote/Cargo.toml +++ b/programs/native/vote/Cargo.toml @@ -14,6 +14,7 @@ log = "0.4.2" solana-logger = { path = "../../../logger", version = "0.12.0" } solana-metrics = { path = "../../../metrics", version = "0.12.0" } solana-sdk = { path = "../../../sdk", version = "0.12.0" } +solana-vote-api = { path = "../vote_api", version = "0.12.0" } [dev-dependencies] solana-runtime = { path = "../../../runtime", version = "0.12.0" } diff --git a/programs/native/vote/src/lib.rs b/programs/native/vote/src/lib.rs index a2f55c1f3..c326b6a18 100644 --- a/programs/native/vote/src/lib.rs +++ b/programs/native/vote/src/lib.rs @@ -7,7 +7,8 @@ use solana_sdk::account::KeyedAccount; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; use solana_sdk::solana_entrypoint; -use solana_sdk::vote_program::{self, VoteInstruction}; +use solana_vote_api::vote_instruction::VoteInstruction; +use solana_vote_api::vote_state; solana_entrypoint!(entrypoint); fn entrypoint( @@ -22,9 +23,9 @@ fn entrypoint( trace!("keyed_accounts: {:?}", keyed_accounts); match deserialize(data).map_err(|_| ProgramError::InvalidUserdata)? { - VoteInstruction::InitializeAccount => vote_program::initialize_account(keyed_accounts), + VoteInstruction::InitializeAccount => vote_state::initialize_account(keyed_accounts), VoteInstruction::DelegateStake(delegate_id) => { - vote_program::delegate_stake(keyed_accounts, delegate_id) + vote_state::delegate_stake(keyed_accounts, delegate_id) } VoteInstruction::Vote(vote) => { debug!("{:?} by {}", vote, keyed_accounts[0].signer_key().unwrap()); @@ -33,8 +34,8 @@ fn entrypoint( .add_field("count", solana_metrics::influxdb::Value::Integer(1)) .to_owned(), ); - vote_program::process_vote(keyed_accounts, vote) + vote_state::process_vote(keyed_accounts, vote) } - VoteInstruction::ClearCredits => vote_program::clear_credits(keyed_accounts), + VoteInstruction::ClearCredits => vote_state::clear_credits(keyed_accounts), } } diff --git a/programs/native/vote/tests/vote.rs b/programs/native/vote/tests/vote.rs index 1b34f176f..240db2390 100644 --- a/programs/native/vote/tests/vote.rs +++ b/programs/native/vote/tests/vote.rs @@ -7,8 +7,9 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::transaction_builder::{BuilderInstruction, TransactionBuilder}; -use solana_sdk::vote_program::{self, Vote, VoteInstruction, VoteState}; -use solana_sdk::vote_transaction::VoteTransaction; +use solana_vote_api::vote_instruction::{Vote, VoteInstruction}; +use solana_vote_api::vote_state::VoteState; +use solana_vote_api::vote_transaction::VoteTransaction; struct VoteBank<'a> { bank: &'a Bank, @@ -16,7 +17,7 @@ struct VoteBank<'a> { impl<'a> VoteBank<'a> { fn new(bank: &'a Bank) -> Self { - bank.add_native_program("solana_vote_program", &vote_program::id()); + bank.add_native_program("solana_vote_program", &solana_vote_api::id()); Self { bank } } @@ -74,7 +75,7 @@ fn test_vote_via_bank_with_no_signature() { let mallory_id = mallory_keypair.pubkey(); let blockhash = bank.last_blockhash(); let vote_ix = BuilderInstruction::new( - vote_program::id(), + solana_vote_api::id(), &VoteInstruction::Vote(Vote::new(0)), vec![(vote_id, false)], // <--- attack!! No signature. ); diff --git a/programs/native/vote_api/Cargo.toml b/programs/native/vote_api/Cargo.toml new file mode 100644 index 000000000..3379797f7 --- /dev/null +++ b/programs/native/vote_api/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "solana-vote-api" +version = "0.12.0" +description = "Solana Vote program API" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2018" + +[dependencies] +bincode = "1.1.2" +log = "0.4.2" +serde = "1.0.89" +serde_derive = "1.0.89" +solana-sdk = { path = "../../../sdk", version = "0.12.0" } + +[lib] +name = "solana_vote_api" +crate-type = ["lib"] diff --git a/programs/native/vote_api/src/lib.rs b/programs/native/vote_api/src/lib.rs new file mode 100644 index 000000000..df3ed3239 --- /dev/null +++ b/programs/native/vote_api/src/lib.rs @@ -0,0 +1,18 @@ +pub mod vote_instruction; +pub mod vote_state; +pub mod vote_transaction; + +use solana_sdk::pubkey::Pubkey; + +pub const VOTE_PROGRAM_ID: [u8; 32] = [ + 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +]; + +pub fn check_id(program_id: &Pubkey) -> bool { + program_id.as_ref() == VOTE_PROGRAM_ID +} + +pub fn id() -> Pubkey { + Pubkey::new(&VOTE_PROGRAM_ID) +} diff --git a/programs/native/vote_api/src/vote_instruction.rs b/programs/native/vote_api/src/vote_instruction.rs new file mode 100644 index 000000000..1a6760791 --- /dev/null +++ b/programs/native/vote_api/src/vote_instruction.rs @@ -0,0 +1,54 @@ +use crate::id; +use serde_derive::{Deserialize, Serialize}; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::transaction_builder::BuilderInstruction; + +#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] +pub struct Vote { + // TODO: add signature of the state here as well + /// A vote for height slot_height + pub slot_height: u64, +} + +impl Vote { + pub fn new(slot_height: u64) -> Self { + Self { slot_height } + } +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub enum VoteInstruction { + /// Initialize the VoteState for this `vote account` + /// * Transaction::keys[0] - the staker id that is also assumed to be the delegate by default + /// * Transaction::keys[1] - the new "vote account" to be associated with the delegate + InitializeAccount, + /// `Delegate` or `Assign` A staking account to a particular node + DelegateStake(Pubkey), + Vote(Vote), + /// Clear the credits in the vote account + /// * Transaction::keys[0] - the "vote account" + ClearCredits, +} + +impl VoteInstruction { + pub fn new_clear_credits(vote_id: Pubkey) -> BuilderInstruction { + BuilderInstruction::new(id(), &VoteInstruction::ClearCredits, vec![(vote_id, true)]) + } + pub fn new_delegate_stake(vote_id: Pubkey, delegate_id: Pubkey) -> BuilderInstruction { + BuilderInstruction::new( + id(), + &VoteInstruction::DelegateStake(delegate_id), + vec![(vote_id, true)], + ) + } + pub fn new_initialize_account(vote_id: Pubkey, staker_id: Pubkey) -> BuilderInstruction { + BuilderInstruction::new( + id(), + &VoteInstruction::InitializeAccount, + vec![(staker_id, true), (vote_id, false)], + ) + } + pub fn new_vote(vote_id: Pubkey, vote: Vote) -> BuilderInstruction { + BuilderInstruction::new(id(), &VoteInstruction::Vote(vote), vec![(vote_id, true)]) + } +} diff --git a/sdk/src/vote_program.rs b/programs/native/vote_api/src/vote_state.rs similarity index 84% rename from sdk/src/vote_program.rs rename to programs/native/vote_api/src/vote_state.rs index f5bc8331f..0d61ba5e5 100644 --- a/sdk/src/vote_program.rs +++ b/programs/native/vote_api/src/vote_state.rs @@ -1,44 +1,20 @@ -//! Vote program +//! Vote stte //! Receive and processes votes from validators -use crate::account::{Account, KeyedAccount}; -use crate::native_program::ProgramError; -use crate::pubkey::Pubkey; -use crate::transaction_builder::BuilderInstruction; +use crate::vote_instruction::Vote; +use crate::{check_id, id}; use bincode::{deserialize, serialize_into, serialized_size, ErrorKind}; use log::*; +use serde_derive::{Deserialize, Serialize}; +use solana_sdk::account::{Account, KeyedAccount}; +use solana_sdk::native_program::ProgramError; +use solana_sdk::pubkey::Pubkey; use std::collections::VecDeque; -pub const VOTE_PROGRAM_ID: [u8; 32] = [ - 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -]; - -pub fn check_id(program_id: &Pubkey) -> bool { - program_id.as_ref() == VOTE_PROGRAM_ID -} - -pub fn id() -> Pubkey { - Pubkey::new(&VOTE_PROGRAM_ID) -} - // Maximum number of votes to keep around pub const MAX_LOCKOUT_HISTORY: usize = 31; pub const INITIAL_LOCKOUT: usize = 2; -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] -pub struct Vote { - // TODO: add signature of the state here as well - /// A vote for height slot_height - pub slot_height: u64, -} - -impl Vote { - pub fn new(slot_height: u64) -> Self { - Self { slot_height } - } -} - #[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Lockout { pub slot_height: u64, @@ -65,43 +41,6 @@ impl Lockout { } } -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub enum VoteInstruction { - /// Initialize the VoteState for this `vote account` - /// * Transaction::keys[0] - the staker id that is also assumed to be the delegate by default - /// * Transaction::keys[1] - the new "vote account" to be associated with the delegate - InitializeAccount, - /// `Delegate` or `Assign` A staking account to a particular node - DelegateStake(Pubkey), - Vote(Vote), - /// Clear the credits in the vote account - /// * Transaction::keys[0] - the "vote account" - ClearCredits, -} - -impl VoteInstruction { - pub fn new_clear_credits(vote_id: Pubkey) -> BuilderInstruction { - BuilderInstruction::new(id(), &VoteInstruction::ClearCredits, vec![(vote_id, true)]) - } - pub fn new_delegate_stake(vote_id: Pubkey, delegate_id: Pubkey) -> BuilderInstruction { - BuilderInstruction::new( - id(), - &VoteInstruction::DelegateStake(delegate_id), - vec![(vote_id, true)], - ) - } - pub fn new_initialize_account(vote_id: Pubkey, staker_id: Pubkey) -> BuilderInstruction { - BuilderInstruction::new( - id(), - &VoteInstruction::InitializeAccount, - vec![(staker_id, true), (vote_id, false)], - ) - } - pub fn new_vote(vote_id: Pubkey, vote: Vote) -> BuilderInstruction { - BuilderInstruction::new(id(), &VoteInstruction::Vote(vote), vec![(vote_id, true)]) - } -} - #[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct VoteState { pub votes: VecDeque, @@ -110,15 +49,6 @@ pub struct VoteState { credits: u64, } -pub fn get_max_size() -> usize { - // Upper limit on the size of the Vote State. Equal to - // sizeof(VoteState) when votes.len() is MAX_LOCKOUT_HISTORY - let mut vote_state = VoteState::default(); - vote_state.votes = VecDeque::from(vec![Lockout::default(); MAX_LOCKOUT_HISTORY]); - vote_state.root_slot = Some(std::u64::MAX); - serialized_size(&vote_state).unwrap() as usize -} - impl VoteState { pub fn new(delegate_id: Pubkey) -> Self { let votes = VecDeque::new(); @@ -132,6 +62,15 @@ impl VoteState { } } + pub fn max_size() -> usize { + // Upper limit on the size of the Vote State. Equal to + // sizeof(VoteState) when votes.len() is MAX_LOCKOUT_HISTORY + let mut vote_state = Self::default(); + vote_state.votes = VecDeque::from(vec![Lockout::default(); MAX_LOCKOUT_HISTORY]); + vote_state.root_slot = Some(std::u64::MAX); + serialized_size(&vote_state).unwrap() as usize + } + pub fn deserialize(input: &[u8]) -> Result { deserialize(input).map_err(|_| ProgramError::InvalidUserdata) } @@ -296,7 +235,7 @@ pub fn clear_credits(keyed_accounts: &mut [KeyedAccount]) -> Result<(), ProgramE } pub fn create_vote_account(tokens: u64) -> Account { - let space = get_max_size(); + let space = VoteState::max_size(); Account::new(tokens, space, id()) } @@ -329,7 +268,7 @@ pub fn vote_and_deserialize( #[cfg(test)] mod tests { use super::*; - use crate::signature::{Keypair, KeypairUtil}; + use solana_sdk::signature::{Keypair, KeypairUtil}; #[test] fn test_initialize_staking_account() { @@ -369,7 +308,7 @@ mod tests { #[test] fn test_vote_serialize() { - let mut buffer: Vec = vec![0; get_max_size()]; + let mut buffer: Vec = vec![0; VoteState::max_size()]; let mut vote_state = VoteState::default(); vote_state .votes diff --git a/sdk/src/vote_transaction.rs b/programs/native/vote_api/src/vote_transaction.rs similarity index 82% rename from sdk/src/vote_transaction.rs rename to programs/native/vote_api/src/vote_transaction.rs index 18fab837e..556c122a4 100644 --- a/sdk/src/vote_transaction.rs +++ b/programs/native/vote_api/src/vote_transaction.rs @@ -1,14 +1,16 @@ //! The `vote_transaction` module provides functionality for creating vote transactions. -use crate::hash::Hash; -use crate::pubkey::Pubkey; -use crate::signature::{Keypair, KeypairUtil}; -use crate::system_instruction::SystemInstruction; -use crate::system_program; -use crate::transaction::{Instruction, Transaction}; -use crate::transaction_builder::TransactionBuilder; -use crate::vote_program::{self, Vote, VoteInstruction}; +use crate::vote_instruction::{Vote, VoteInstruction}; +use crate::vote_state::VoteState; +use crate::{check_id, id}; use bincode::deserialize; +use solana_sdk::hash::Hash; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::{Keypair, KeypairUtil}; +use solana_sdk::system_instruction::SystemInstruction; +use solana_sdk::system_program; +use solana_sdk::transaction::{Instruction, Transaction}; +use solana_sdk::transaction_builder::TransactionBuilder; pub struct VoteTransaction {} @@ -35,15 +37,15 @@ impl VoteTransaction { ) -> Transaction { let create_tx = SystemInstruction::CreateAccount { tokens: num_tokens, - space: vote_program::get_max_size() as u64, - program_id: vote_program::id(), + space: VoteState::max_size() as u64, + program_id: id(), }; Transaction::new_with_instructions( &[from_keypair], &[vote_account_id], recent_blockhash, fee, - vec![system_program::id(), vote_program::id()], + vec![system_program::id(), id()], vec![ Instruction::new(0, &create_tx, vec![0, 1]), Instruction::new(1, &VoteInstruction::InitializeAccount, vec![0, 1]), @@ -67,7 +69,7 @@ impl VoteTransaction { } fn get_vote(tx: &Transaction, ix_index: usize) -> Option<(Pubkey, Vote, Hash)> { - if !vote_program::check_id(&tx.program_id(ix_index)) { + if !check_id(&tx.program_id(ix_index)) { return None; } let instruction = deserialize(&tx.userdata(ix_index)).unwrap(); diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index db7164d88..54072ee3f 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -25,6 +25,7 @@ solana-metrics = { path = "../metrics", version = "0.12.0" } solana-sdk = { path = "../sdk", version = "0.12.0" } solana-native-loader = { path = "../programs/native/native_loader", version = "0.12.0" } solana-system-program = { path = "../programs/native/system", version = "0.12.0" } +solana-vote-api = { path = "../programs/native/vote_api", version = "0.12.0" } [lib] name = "solana_runtime" diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index a4d8ffffb..11fe0d178 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -11,7 +11,7 @@ use solana_sdk::native_loader; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::Transaction; -use solana_sdk::vote_program; +use solana_vote_api; use std::collections::BTreeMap; use std::env; use std::fs::{create_dir_all, remove_dir_all}; @@ -427,7 +427,7 @@ impl AccountsDB { index: &HashMap, pubkey: &Pubkey, ) { - if vote_program::check_id(&account.owner) { + if solana_vote_api::check_id(&account.owner) { if Self::account_map_is_empty(pubkey, index) { self.index_info.vote_index.write().unwrap().remove(pubkey); } else { @@ -1454,7 +1454,7 @@ mod tests { let pubkey = Keypair::new().pubkey(); let mut default_account = Account::default(); pubkeys.push(pubkey.clone()); - default_account.owner = vote_program::id(); + default_account.owner = solana_vote_api::id(); default_account.tokens = (num + t + 1) as u64; assert!(accounts.load(0, &pubkey, true).is_none()); accounts.store(0, &pubkey, &default_account); @@ -1593,7 +1593,7 @@ mod tests { fn test_accounts_vote_filter() { solana_logger::setup(); let accounts = Accounts::new(0, None); - let mut vote_account = Account::new(1, 0, vote_program::id()); + let mut vote_account = Account::new(1, 0, solana_vote_api::id()); let key = Keypair::new().pubkey(); accounts.store_slow(0, &key, &vote_account); @@ -1608,7 +1608,7 @@ mod tests { vote_accounts = accounts.get_vote_accounts(1).collect(); assert_eq!(vote_accounts.len(), 0); - let mut vote_account1 = Account::new(2, 0, vote_program::id()); + let mut vote_account1 = Account::new(2, 0, solana_vote_api::id()); let key1 = Keypair::new().pubkey(); accounts.store_slow(1, &key1, &vote_account1); @@ -1636,10 +1636,10 @@ mod tests { let accounts = accounts_db.get_vote_accounts(0); assert_eq!(accounts.len(), 1); accounts.iter().for_each(|(_, account)| { - assert_eq!(account.owner, vote_program::id()); + assert_eq!(account.owner, solana_vote_api::id()); }); let lastkey = Keypair::new().pubkey(); - let mut lastaccount = Account::new(1, 0, vote_program::id()); + let mut lastaccount = Account::new(1, 0, solana_vote_api::id()); accounts_db.store(0, &lastkey, &lastaccount); assert_eq!(accounts_db.get_vote_accounts(0).len(), 2); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 19844b4e3..3c44c0a11 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -26,7 +26,9 @@ use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::timing::{duration_as_us, MAX_RECENT_BLOCKHASHES, NUM_TICKS_PER_SECOND}; use solana_sdk::token_program; use solana_sdk::transaction::Transaction; -use solana_sdk::vote_program::{self, VoteState}; +use solana_vote_api; +use solana_vote_api::vote_instruction::Vote; +use solana_vote_api::vote_state::{Lockout, VoteState}; use std::result; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, RwLock}; @@ -255,15 +257,13 @@ impl Bank { // will be forced to select it as the leader for height 0 let mut bootstrap_leader_staking_account = Account { tokens: bootstrap_leader_stake, - userdata: vec![0; vote_program::get_max_size() as usize], - owner: vote_program::id(), + userdata: vec![0; VoteState::max_size() as usize], + owner: solana_vote_api::id(), executable: false, }; let mut vote_state = VoteState::new(genesis_block.bootstrap_leader_id); - vote_state - .votes - .push_back(vote_program::Lockout::new(&vote_program::Vote::new(0))); + vote_state.votes.push_back(Lockout::new(&Vote::new(0))); vote_state .serialize(&mut bootstrap_leader_staking_account.userdata) .unwrap(); @@ -292,7 +292,7 @@ impl Bank { fn add_builtin_programs(&self) { self.add_native_program("solana_system_program", &system_program::id()); - self.add_native_program("solana_vote_program", &vote_program::id()); + self.add_native_program("solana_vote_program", &solana_vote_api::id()); self.add_native_program("solana_storage_program", &storage_program::id()); self.add_native_program("solana_bpf_loader", &bpf_loader::id()); self.add_native_program("solana_budget_program", &solana_budget_api::id()); @@ -1289,7 +1289,7 @@ mod tests { assert_eq!(solana_budget_api::id(), budget); assert_eq!(storage_program::id(), storage); assert_eq!(token_program::id(), token); - assert_eq!(vote_program::id(), vote); + assert_eq!(solana_vote_api::id(), vote); } #[test] @@ -1302,7 +1302,7 @@ mod tests { solana_budget_api::id(), storage_program::id(), token_program::id(), - vote_program::id(), + solana_vote_api::id(), ]; assert!(ids.into_iter().all(move |id| unique.insert(id))); } diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 5fea1bfa3..f4ddceca7 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -18,8 +18,6 @@ pub mod timing; pub mod token_program; pub mod transaction; pub mod transaction_builder; -pub mod vote_program; -pub mod vote_transaction; #[macro_use] extern crate serde_derive;