diff --git a/book/src/cluster/stake-delegation-and-rewards.md b/book/src/cluster/stake-delegation-and-rewards.md index fb2e0f03cc..952d7374ec 100644 --- a/book/src/cluster/stake-delegation-and-rewards.md +++ b/book/src/cluster/stake-delegation-and-rewards.md @@ -76,7 +76,7 @@ StakeState::Stake is the current delegation preference of the **staker** and con * `deactivated` - the epoch at which this stake was de-activated, some cool down epochs are required before the account ```text - is fully deactivated, and the stake available for withdrawal + is fully deactivated, and the stake available for withdrawal ``` * `authorized_staker` - the pubkey of the entity that must sign delegation, activation, and deactivation transactions @@ -94,7 +94,7 @@ The Stakes and the RewardsPool are accounts that are owned by the same `Stake` p ### StakeInstruction::DelegateStake -The Stake account is moved from Ininitialized to StakeState::Stake form. This is how stakers choose their initial delegate validator node and activate their stake account lamports. If the stake account is already StakeState::Stake \(i.e. already activated\), the stake is re-delegated The transaction must be signed by the stake's `authorized_staker`. +The Stake account is moved from Ininitialized to StakeState::Stake form. This is how stakers choose their initial delegate validator node and activate their stake account lamports. The transaction must be signed by the stake's `authorized_staker`. If the stake account is already StakeState::Stake \(i.e. already activated\), the stake is re-delegated. Stakes may be re-delegated at any time, and updated stakes are reflected immediately, but only one re-delegation is permitted per epoch. * `account[0]` - RW - The StakeState::Stake instance. `StakeState::Stake::credits_observed` is initialized to `VoteState::credits`, `StakeState::Stake::voter_pubkey` is initialized to `account[1]`. If this is the initial delegation of stake, `StakeState::Stake::stake` is initialized to the account's balance in lamports, `StakeState::Stake::activated` is initialized to the current Bank epoch, and `StakeState::Stake::deactivated` is initialized to std::u64::MAX * `account[1]` - R - The VoteState instance. @@ -132,7 +132,7 @@ stake_state.credits_observed = vote_state.credits; ### StakeInstruction::Deactivate -A staker may wish to withdraw from the network. To do so he must first deactivate his stake, and wait for cool down. +A staker may wish to withdraw from the network. To do so he must first deactivate his stake, and wait for cool down. The transaction must be signed by the stake's `authorized_staker`. * `account[0]` - RW - The StakeState::Stake instance that is deactivating. @@ -229,4 +229,3 @@ Only lamports in excess of effective+activating stake may be withdrawn at any ti ### Lock-up Stake accounts support the notion of lock-up, wherein the stake account balance is unavailable for withdrawal until a specified time. Lock-up is specified as a slot height, i.e. the minimum slot height that must be reached by the network before the stake account balance is available for withdrawal, except to a specified custodian. This information is gathered when the stake account is created. - diff --git a/book/src/running-validator/validator-stake.md b/book/src/running-validator/validator-stake.md index b977270def..7823d4913a 100644 --- a/book/src/running-validator/validator-stake.md +++ b/book/src/running-validator/validator-stake.md @@ -19,7 +19,7 @@ $ solana delegate-stake ~/validator-config/stake-keypair.json ~/validator-vote-k Note that stakes need to warm up, and warmup increments are applied at Epoch boundaries, so it can take an hour or more for the change to fully take effect. -Stakes can be re-delegated to another node at any time with the same command: +Stakes can be re-delegated to another node at any time with the same command, but only one re-delegation is permitted per epoch: ```bash $ solana delegate-stake ~/validator-config/stake-keypair.json ~/some-other-validator-vote-keypair.json @@ -44,4 +44,3 @@ The stake will cool down, deactivate over time. While cooling down, your stake w Note that a stake account may only be used once, so after deactivation, use the cli's `withdraw-stake` command to recover the previously staked lamports. Be sure and redeem your credits before withdrawing all your lamports. Once the account is fully withdrawn, the account is destroyed. - diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index cc61de70e3..3a03a06b36 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -80,7 +80,7 @@ dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -107,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -177,7 +177,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "feature-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -251,7 +251,7 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -322,7 +322,7 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -611,7 +611,7 @@ name = "generic-array" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -791,7 +791,7 @@ dependencies = [ [[package]] name = "itertools" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1359,7 +1359,7 @@ dependencies = [ "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1466,10 +1466,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1477,12 +1477,12 @@ name = "serde_bytes" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1497,7 +1497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1507,7 +1507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1545,165 +1545,165 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "solana-bpf-loader-api" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-logger 0.20.0", - "solana-sdk 0.20.0", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 0.21.0", + "solana-sdk 0.21.0", "solana_rbpf 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "solana-bpf-loader-program" -version = "0.20.0" +version = "0.21.0" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-bpf-loader-api 0.20.0", - "solana-logger 0.20.0", - "solana-sdk 0.20.0", + "solana-bpf-loader-api 0.21.0", + "solana-logger 0.21.0", + "solana-sdk 0.21.0", ] [[package]] name = "solana-bpf-programs" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "elf 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-bpf-loader-api 0.20.0", - "solana-logger 0.20.0", - "solana-runtime 0.20.0", - "solana-sdk 0.20.0", + "solana-bpf-loader-api 0.21.0", + "solana-logger 0.21.0", + "solana-runtime 0.21.0", + "solana-sdk 0.21.0", "solana_rbpf 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "solana-bpf-rust-128bit" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-bpf-rust-128bit-dep 0.20.0", - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-bpf-rust-128bit-dep 0.21.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-128bit-dep" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-alloc" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-dep-crate" -version = "0.20.0" +version = "0.21.0" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-external-spend" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-iter" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-many-args" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-bpf-rust-many-args-dep 0.20.0", - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-bpf-rust-many-args-dep 0.21.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-many-args-dep" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-noop" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-panic" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-param-passing" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-bpf-rust-param-passing-dep 0.20.0", - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-bpf-rust-param-passing-dep 0.21.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-param-passing-dep" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-bpf-rust-sysval" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", - "solana-sdk-bpf-test 0.20.0", + "solana-sdk 0.21.0", + "solana-sdk-bpf-test 0.21.0", ] [[package]] name = "solana-config-api" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-sdk 0.20.0", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-sdk 0.21.0", ] [[package]] name = "solana-crate-features" -version = "0.20.0" +version = "0.21.0" dependencies = [ "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1716,7 +1716,7 @@ dependencies = [ "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "solana-ed25519-dalek 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1733,13 +1733,13 @@ dependencies = [ "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "solana-logger" -version = "0.20.0" +version = "0.21.0" dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1748,26 +1748,26 @@ dependencies = [ [[package]] name = "solana-measure" -version = "0.20.0" +version = "0.21.0" dependencies = [ - "solana-sdk 0.20.0", + "solana-sdk 0.21.0", ] [[package]] name = "solana-metrics" -version = "0.20.0" +version = "0.21.0" dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-sdk 0.20.0", + "solana-sdk 0.21.0", "sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "solana-rayon-threadlimit" -version = "0.20.0" +version = "0.21.0" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1775,14 +1775,14 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "bv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1790,28 +1790,28 @@ dependencies = [ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-bpf-loader-api 0.20.0", - "solana-bpf-loader-program 0.20.0", - "solana-logger 0.20.0", - "solana-measure 0.20.0", - "solana-metrics 0.20.0", - "solana-rayon-threadlimit 0.20.0", - "solana-sdk 0.20.0", - "solana-stake-api 0.20.0", - "solana-stake-program 0.20.0", - "solana-storage-api 0.20.0", - "solana-vote-api 0.20.0", - "solana-vote-program 0.20.0", + "solana-bpf-loader-api 0.21.0", + "solana-bpf-loader-program 0.21.0", + "solana-logger 0.21.0", + "solana-measure 0.21.0", + "solana-metrics 0.21.0", + "solana-rayon-threadlimit 0.21.0", + "solana-sdk 0.21.0", + "solana-stake-api 0.21.0", + "solana-stake-program 0.21.0", + "solana-storage-api 0.21.0", + "solana-vote-api 0.21.0", + "solana-vote-program 0.21.0", "sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "solana-sdk" -version = "0.20.0" +version = "0.21.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1820,7 +1820,7 @@ dependencies = [ "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1828,52 +1828,52 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-crate-features 0.20.0", + "solana-crate-features 0.21.0", "solana-ed25519-dalek 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-logger 0.20.0", + "solana-logger 0.21.0", "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "solana-sdk-bpf-test" -version = "0.20.0" +version = "0.21.0" [[package]] name = "solana-stake-api" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "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.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-config-api 0.20.0", - "solana-logger 0.20.0", - "solana-metrics 0.20.0", - "solana-sdk 0.20.0", - "solana-vote-api 0.20.0", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-config-api 0.21.0", + "solana-logger 0.21.0", + "solana-metrics 0.21.0", + "solana-sdk 0.21.0", + "solana-vote-api 0.21.0", ] [[package]] name = "solana-stake-program" -version = "0.20.0" +version = "0.21.0" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-logger 0.20.0", - "solana-sdk 0.20.0", - "solana-stake-api 0.20.0", + "solana-logger 0.21.0", + "solana-sdk 0.21.0", + "solana-stake-api 0.21.0", ] [[package]] name = "solana-storage-api" -version = "0.20.0" +version = "0.21.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1881,35 +1881,35 @@ dependencies = [ "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-logger 0.20.0", - "solana-sdk 0.20.0", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 0.21.0", + "solana-sdk 0.21.0", ] [[package]] name = "solana-vote-api" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "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.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-logger 0.20.0", - "solana-metrics 0.20.0", - "solana-sdk 0.20.0", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 0.21.0", + "solana-metrics 0.21.0", + "solana-sdk 0.21.0", ] [[package]] name = "solana-vote-program" -version = "0.20.0" +version = "0.21.0" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-logger 0.20.0", - "solana-sdk 0.20.0", - "solana-vote-api 0.20.0", + "solana-logger 0.21.0", + "solana-sdk 0.21.0", + "solana-vote-api 0.21.0", ] [[package]] @@ -2660,7 +2660,7 @@ dependencies = [ "checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +"checksum itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87fa75c9dea7b07be3138c49abbb83fd4bea199b5cdc76f9804458edc5da0d6e" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" "checksum js-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "1efc4f2a556c58e79c5500912e221dd826bec64ff4aabd8ce71ccef6da02d7d4" @@ -2738,9 +2738,9 @@ dependencies = [ "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" "checksum serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45af0182ff64abaeea290235eb67da3825a576c5d53e642c4d5b652e12e6effc" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" diff --git a/programs/stake_api/src/stake_instruction.rs b/programs/stake_api/src/stake_instruction.rs index d38676888c..551a597b83 100644 --- a/programs/stake_api/src/stake_instruction.rs +++ b/programs/stake_api/src/stake_instruction.rs @@ -20,6 +20,7 @@ pub enum StakeError { NoCreditsToRedeem, LockupInForce, AlreadyDeactivated, + TooSoonToRedelegate, } impl DecodeError for StakeError { fn type_of() -> &'static str { @@ -32,6 +33,9 @@ impl std::fmt::Display for StakeError { StakeError::NoCreditsToRedeem => write!(f, "not enough credits to redeem"), StakeError::LockupInForce => write!(f, "lockup has not yet expired"), StakeError::AlreadyDeactivated => write!(f, "stake already deactivated"), + StakeError::TooSoonToRedelegate => { + write!(f, "only one redelegation permitted per epoch") + } } } } diff --git a/programs/stake_api/src/stake_state.rs b/programs/stake_api/src/stake_state.rs index 4204b073e5..84e0a8cc3c 100644 --- a/programs/stake_api/src/stake_state.rs +++ b/programs/stake_api/src/stake_state.rs @@ -103,7 +103,7 @@ pub struct Stake { pub config: Config, /// history of prior delegates and the epoch ranges for which /// they were set, circular buffer - pub prior_delegates: [(Pubkey, Epoch, Epoch); MAX_PRIOR_DELEGATES], + pub prior_delegates: [(Pubkey, Epoch, Epoch, Slot); MAX_PRIOR_DELEGATES], /// next pointer pub prior_delegates_idx: usize, } @@ -120,7 +120,7 @@ impl Default for Stake { activation_epoch: 0, deactivation_epoch: std::u64::MAX, config: Config::default(), - prior_delegates: <[(Pubkey, Epoch, Epoch); MAX_PRIOR_DELEGATES]>::default(), + prior_delegates: <[(Pubkey, Epoch, Epoch, Slot); MAX_PRIOR_DELEGATES]>::default(), prior_delegates_idx: MAX_PRIOR_DELEGATES - 1, } } @@ -169,17 +169,6 @@ impl Stake { self.stake_activating_and_deactivating(epoch, history).0 } - pub fn voter_pubkey(&self, epoch: Epoch) -> &Pubkey { - let prior_delegate_pubkey = &self.prior_delegates[self.prior_delegates_idx].0; - // next epoch from re-delegation, or no redelegations - if epoch > self.voter_pubkey_epoch || *prior_delegate_pubkey == Pubkey::default() { - &self.voter_pubkey - } else { - assert!(epoch <= self.prior_delegates[self.prior_delegates_idx].2); - prior_delegate_pubkey - } - } - fn stake_activating_and_deactivating( &self, epoch: Epoch, @@ -362,18 +351,26 @@ impl Stake { &mut self, voter_pubkey: &Pubkey, vote_state: &VoteState, - epoch: Epoch, + clock: &sysvar::clock::Clock, ) -> Result<(), StakeError> { - // remember old delegate, - if epoch != self.voter_pubkey_epoch { - self.prior_delegates_idx += 1; - self.prior_delegates_idx %= MAX_PRIOR_DELEGATES; - - self.prior_delegates[self.prior_delegates_idx] = - (self.voter_pubkey, self.voter_pubkey_epoch, epoch); + // only one re-delegation supported per epoch + if self.voter_pubkey_epoch == clock.epoch { + return Err(StakeError::TooSoonToRedelegate); } + + // remember prior delegate and when we switched, to support later slashing + self.prior_delegates_idx += 1; + self.prior_delegates_idx %= MAX_PRIOR_DELEGATES; + + self.prior_delegates[self.prior_delegates_idx] = ( + self.voter_pubkey, + self.voter_pubkey_epoch, + clock.epoch, + clock.slot, + ); + self.voter_pubkey = *voter_pubkey; - self.voter_pubkey_epoch = epoch; + self.voter_pubkey_epoch = clock.epoch; self.credits_observed = vote_state.credits(); Ok(()) } @@ -500,11 +497,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { self.set_state(&StakeState::Stake(authorized, lockup, stake)) } else if let StakeState::Stake(authorized, lockup, mut stake) = self.state()? { authorized.check(signers, StakeAuthorize::Staker)?; - stake.redelegate( - vote_account.unsigned_key(), - &vote_account.state()?, - clock.epoch, - )?; + stake.redelegate(vote_account.unsigned_key(), &vote_account.state()?, &clock)?; self.set_state(&StakeState::Stake(authorized, lockup, stake)) } else { Err(InstructionError::InvalidAccountData) @@ -711,7 +704,7 @@ mod tests { #[test] fn test_stake_delegate_stake() { - let clock = sysvar::clock::Clock { + let mut clock = sysvar::clock::Clock { epoch: 1, ..sysvar::clock::Clock::default() }; @@ -792,12 +785,18 @@ mod tests { ..Stake::default() } ); + // verify that delegate_stake can be called twice, 2nd is redelegate + assert_eq!( + stake_keyed_account.delegate_stake( + &vote_keyed_account, + &clock, + &Config::default(), + &signers + ), + Err(StakeError::TooSoonToRedelegate.into()) + ); - // verify that voter_pubkey() is right for all epochs, even ones that don't count (like 0) - for epoch in 0..=clock.epoch + 1 { - assert_eq!(stake.voter_pubkey(epoch), &vote_pubkey); - } - + clock.epoch += 1; // verify that delegate_stake can be called twice, 2nd is redelegate assert!(stake_keyed_account .delegate_stake(&vote_keyed_account, &clock, &Config::default(), &signers) @@ -820,33 +819,34 @@ mod tests { voter_pubkey_epoch: 0, ..Stake::default() }; - // verify that redelegation any number of times since first delegation works just fine, - // and that the stake is delegated to the most recent vote account - for epoch in 0..=MAX_PRIOR_DELEGATES + 1 { + // verify that redelegation works when epoch is changing, that + // wraparound works, and that the stake is delegated + // to the most recent vote account + for epoch in 1..=MAX_PRIOR_DELEGATES + 2 { let voter_pubkey = Pubkey::new_rand(); - let _ignored = stake.redelegate(&voter_pubkey, &VoteState::default(), 0); - assert_eq!(stake.voter_pubkey(epoch as u64), &voter_pubkey); - } - - // get a new voter_pubkey - let voter_pubkey = Pubkey::new_rand(); - // save off old voter_pubkey - let prior_voter_pubkey = stake.voter_pubkey; - - // actually redelegate in epoch 1 - let _ignored = stake.redelegate(&voter_pubkey, &VoteState::default(), 1); - // verify that delegation is delayed - assert_eq!(stake.voter_pubkey(0 as u64), &prior_voter_pubkey); - assert_eq!(stake.voter_pubkey(1 as u64), &prior_voter_pubkey); - assert_eq!(stake.voter_pubkey(2 as u64), &voter_pubkey); - - // verify that prior_delegates wraps around safely... - for epoch in 0..=MAX_PRIOR_DELEGATES + 1 { - let voter_pubkey = Pubkey::new_rand(); - let prior_voter_pubkey = stake.voter_pubkey; - let _ignored = stake.redelegate(&voter_pubkey, &VoteState::default(), epoch as u64); - assert_eq!(stake.voter_pubkey(epoch as u64), &prior_voter_pubkey); - assert_eq!(stake.voter_pubkey((epoch + 1) as u64), &voter_pubkey); + assert_eq!( + stake.redelegate( + &voter_pubkey, + &VoteState::default(), + &sysvar::clock::Clock { + epoch: epoch as u64, + ..sysvar::clock::Clock::default() + }, + ), + Ok(()) + ); + assert_eq!( + stake.redelegate( + &voter_pubkey, + &VoteState::default(), + &sysvar::clock::Clock { + epoch: epoch as u64, + ..sysvar::clock::Clock::default() + }, + ), + Err(StakeError::TooSoonToRedelegate) + ); + assert_eq!(stake.voter_pubkey, voter_pubkey); } } @@ -1908,7 +1908,7 @@ mod tests { ) .expect("stake_account"); - let clock = sysvar::clock::Clock::default(); + let mut clock = sysvar::clock::Clock::default(); let vote_pubkey = Pubkey::new_rand(); let mut vote_account = @@ -1943,6 +1943,8 @@ mod tests { KeyedAccount::new(&new_voter_pubkey, false, &mut new_vote_account); new_vote_keyed_account.set_state(&vote_state).unwrap(); + // time passes, so we can re-delegate + clock.epoch += 1; // Random other account should fail assert_eq!( stake_keyed_account.delegate_stake( @@ -1966,7 +1968,7 @@ mod tests { Ok(()) ); let stake = StakeState::stake_from(&stake_keyed_account.account).unwrap(); - assert_eq!(stake.voter_pubkey(0), &new_voter_pubkey); + assert_eq!(stake.voter_pubkey, new_voter_pubkey); // Test another staking action assert_eq!( diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index bcae8d5bc1..f7b93c4729 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -85,7 +85,7 @@ impl Stakes { .iter() .map(|(_, stake_account)| { StakeState::stake_from(stake_account).map_or(0, |stake| { - if stake.voter_pubkey(epoch) == voter_pubkey { + if &stake.voter_pubkey == voter_pubkey { stake.stake(epoch, stake_history) } else { 0 @@ -129,7 +129,7 @@ impl Stakes { let old_stake = self.stake_accounts.get(pubkey).and_then(|old_account| { StakeState::stake_from(old_account).map(|stake| { ( - *stake.voter_pubkey(self.epoch), + stake.voter_pubkey, stake.stake(self.epoch, Some(&self.stake_history)), ) }) @@ -137,7 +137,7 @@ impl Stakes { let stake = StakeState::stake_from(account).map(|stake| { ( - *stake.voter_pubkey(self.epoch), + stake.voter_pubkey, if account.lamports != 0 { stake.stake(self.epoch, Some(&self.stake_history)) } else {