Add unix_timestap to stake lockups (#7569)
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -3264,6 +3264,7 @@ dependencies = [
|
|||||||
name = "solana-clap-utils"
|
name = "solana-clap-utils"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -3497,7 +3498,6 @@ name = "solana-genesis"
|
|||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@ semver = "0.9.0"
|
|||||||
solana-sdk = { path = "../sdk", version = "0.22.0" }
|
solana-sdk = { path = "../sdk", version = "0.22.0" }
|
||||||
tiny-bip39 = "0.6.2"
|
tiny-bip39 = "0.6.2"
|
||||||
url = "2.1.0"
|
url = "2.1.0"
|
||||||
|
chrono = "0.4"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "solana_clap_utils"
|
name = "solana_clap_utils"
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use crate::keypair::{keypair_from_seed_phrase, ASK_KEYWORD, SKIP_SEED_PHRASE_VALIDATION_ARG};
|
use crate::keypair::{keypair_from_seed_phrase, ASK_KEYWORD, SKIP_SEED_PHRASE_VALIDATION_ARG};
|
||||||
|
use chrono::DateTime;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
clock::UnixTimestamp,
|
||||||
native_token::sol_to_lamports,
|
native_token::sol_to_lamports,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{read_keypair_file, Keypair, KeypairUtil, Signature},
|
signature::{read_keypair_file, Keypair, KeypairUtil, Signature},
|
||||||
@ -31,6 +33,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unix_timestamp_of(matches: &ArgMatches<'_>, name: &str) -> Option<UnixTimestamp> {
|
||||||
|
matches.value_of(name).and_then(|value| {
|
||||||
|
DateTime::parse_from_rfc3339(value)
|
||||||
|
.ok()
|
||||||
|
.map(|date_time| date_time.timestamp())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Return the keypair for an argument with filename `name` or None if not present.
|
// Return the keypair for an argument with filename `name` or None if not present.
|
||||||
pub fn keypair_of(matches: &ArgMatches<'_>, name: &str) -> Option<Keypair> {
|
pub fn keypair_of(matches: &ArgMatches<'_>, name: &str) -> Option<Keypair> {
|
||||||
if let Some(value) = matches.value_of(name) {
|
if let Some(value) = matches.value_of(name) {
|
||||||
|
@ -287,7 +287,7 @@ pub struct CliConfig {
|
|||||||
pub keypair: Keypair,
|
pub keypair: Keypair,
|
||||||
pub keypair_path: Option<String>,
|
pub keypair_path: Option<String>,
|
||||||
pub rpc_client: Option<RpcClient>,
|
pub rpc_client: Option<RpcClient>,
|
||||||
pub print_header: bool,
|
pub verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliConfig {
|
impl CliConfig {
|
||||||
@ -313,7 +313,7 @@ impl Default for CliConfig {
|
|||||||
keypair: Keypair::new(),
|
keypair: Keypair::new(),
|
||||||
keypair_path: Some(Self::default_keypair_path()),
|
keypair_path: Some(Self::default_keypair_path()),
|
||||||
rpc_client: None,
|
rpc_client: None,
|
||||||
print_header: true,
|
verbose: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1073,14 +1073,10 @@ fn process_witness(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_command(config: &CliConfig) -> ProcessResult {
|
pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||||
if config.print_header {
|
if config.verbose {
|
||||||
if let Some(keypair_path) = &config.keypair_path {
|
if let Some(keypair_path) = &config.keypair_path {
|
||||||
println_name_value("Keypair:", keypair_path);
|
println_name_value("Keypair:", keypair_path);
|
||||||
}
|
}
|
||||||
if let CliCommand::Address = config.command {
|
|
||||||
// Get address of this client
|
|
||||||
return Ok(format!("{}", config.keypair.pubkey()));
|
|
||||||
}
|
|
||||||
println_name_value("RPC Endpoint:", &config.json_rpc_url);
|
println_name_value("RPC Endpoint:", &config.json_rpc_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1095,6 +1091,8 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
|
|
||||||
match &config.command {
|
match &config.command {
|
||||||
// Cluster Query Commands
|
// Cluster Query Commands
|
||||||
|
// Get address of this client
|
||||||
|
CliCommand::Address => Ok(format!("{}", config.keypair.pubkey())),
|
||||||
|
|
||||||
// Return software version of solana-cli and cluster entrypoint node
|
// Return software version of solana-cli and cluster entrypoint node
|
||||||
CliCommand::Catchup { node_pubkey } => process_catchup(&rpc_client, node_pubkey),
|
CliCommand::Catchup { node_pubkey } => process_catchup(&rpc_client, node_pubkey),
|
||||||
@ -1383,8 +1381,6 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
|
|
||||||
// Wallet Commands
|
// Wallet Commands
|
||||||
|
|
||||||
// Get address of this client
|
|
||||||
CliCommand::Address => unreachable!(),
|
|
||||||
// Request an airdrop from Solana Faucet;
|
// Request an airdrop from Solana Faucet;
|
||||||
CliCommand::Airdrop {
|
CliCommand::Airdrop {
|
||||||
faucet_host,
|
faucet_host,
|
||||||
@ -2460,6 +2456,7 @@ mod tests {
|
|||||||
withdrawer: None,
|
withdrawer: None,
|
||||||
lockup: Lockup {
|
lockup: Lockup {
|
||||||
epoch: 0,
|
epoch: 0,
|
||||||
|
unix_timestamp: 0,
|
||||||
custodian,
|
custodian,
|
||||||
},
|
},
|
||||||
lamports: 1234,
|
lamports: 1234,
|
||||||
|
@ -133,15 +133,13 @@ pub fn parse_args(matches: &ArgMatches<'_>) -> Result<CliConfig, Box<dyn error::
|
|||||||
(default.keypair, None)
|
(default.keypair, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let print_header = !matches.is_present("no_header");
|
|
||||||
|
|
||||||
Ok(CliConfig {
|
Ok(CliConfig {
|
||||||
command,
|
command,
|
||||||
json_rpc_url,
|
json_rpc_url,
|
||||||
keypair,
|
keypair,
|
||||||
keypair_path,
|
keypair_path,
|
||||||
rpc_client: None,
|
rpc_client: None,
|
||||||
print_header,
|
verbose: matches.is_present("verbose"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,10 +184,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.help("/path/to/id.json"),
|
.help("/path/to/id.json"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("no_header")
|
Arg::with_name("verbose")
|
||||||
.long("no-header")
|
.long("verbose")
|
||||||
|
.short("v")
|
||||||
.global(true)
|
.global(true)
|
||||||
.help("Disable information header"),
|
.help("Show extra information header"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(ASK_SEED_PHRASE_ARG.name)
|
Arg::with_name(ASK_SEED_PHRASE_ARG.name)
|
||||||
|
@ -73,11 +73,18 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.help("Identity of the custodian (can withdraw before lockup expires)")
|
.help("Identity of the custodian (can withdraw before lockup expires)")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("lockup")
|
Arg::with_name("lockup_epoch")
|
||||||
.long("lockup")
|
.long("lockup-epoch")
|
||||||
.value_name("SLOT")
|
.value_name("EPOCH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("The slot height at which this account will be available for withdrawal")
|
.help("The epoch height at which this account will be available for withdrawal")
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("lockup_date")
|
||||||
|
.long("lockup-date")
|
||||||
|
.value_name("RFC3339 DATE TIME")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("The date and time at which this account will be available for withdrawal")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("authorized_staker")
|
Arg::with_name("authorized_staker")
|
||||||
@ -322,7 +329,8 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
|
|
||||||
pub fn parse_stake_create_account(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
pub fn parse_stake_create_account(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
let stake_account = keypair_of(matches, "stake_account").unwrap();
|
let stake_account = keypair_of(matches, "stake_account").unwrap();
|
||||||
let epoch = value_of(&matches, "lockup").unwrap_or(0);
|
let epoch = value_of(&matches, "lockup_epoch").unwrap_or(0);
|
||||||
|
let unix_timestamp = unix_timestamp_of(&matches, "lockup_date").unwrap_or(0);
|
||||||
let custodian = pubkey_of(matches, "custodian").unwrap_or_default();
|
let custodian = pubkey_of(matches, "custodian").unwrap_or_default();
|
||||||
let staker = pubkey_of(matches, "authorized_staker");
|
let staker = pubkey_of(matches, "authorized_staker");
|
||||||
let withdrawer = pubkey_of(matches, "authorized_withdrawer");
|
let withdrawer = pubkey_of(matches, "authorized_withdrawer");
|
||||||
@ -333,7 +341,11 @@ pub fn parse_stake_create_account(matches: &ArgMatches<'_>) -> Result<CliCommand
|
|||||||
stake_account: stake_account.into(),
|
stake_account: stake_account.into(),
|
||||||
staker,
|
staker,
|
||||||
withdrawer,
|
withdrawer,
|
||||||
lockup: Lockup { custodian, epoch },
|
lockup: Lockup {
|
||||||
|
custodian,
|
||||||
|
epoch,
|
||||||
|
unix_timestamp,
|
||||||
|
},
|
||||||
lamports,
|
lamports,
|
||||||
},
|
},
|
||||||
require_keypair: true,
|
require_keypair: true,
|
||||||
@ -906,7 +918,7 @@ mod tests {
|
|||||||
&authorized_string,
|
&authorized_string,
|
||||||
"--custodian",
|
"--custodian",
|
||||||
&custodian_string,
|
&custodian_string,
|
||||||
"--lockup",
|
"--lockup-epoch",
|
||||||
"43",
|
"43",
|
||||||
"lamports",
|
"lamports",
|
||||||
]);
|
]);
|
||||||
@ -919,6 +931,7 @@ mod tests {
|
|||||||
withdrawer: Some(authorized),
|
withdrawer: Some(authorized),
|
||||||
lockup: Lockup {
|
lockup: Lockup {
|
||||||
epoch: 43,
|
epoch: 43,
|
||||||
|
unix_timestamp: 0,
|
||||||
custodian,
|
custodian,
|
||||||
},
|
},
|
||||||
lamports: 50
|
lamports: 50
|
||||||
|
@ -88,10 +88,7 @@ fn test_stake_delegation_and_deactivation() {
|
|||||||
stake_account: read_keypair_file(&stake_keypair_file).unwrap().into(),
|
stake_account: read_keypair_file(&stake_keypair_file).unwrap().into(),
|
||||||
staker: None,
|
staker: None,
|
||||||
withdrawer: None,
|
withdrawer: None,
|
||||||
lockup: Lockup {
|
lockup: Lockup::default(),
|
||||||
custodian: Pubkey::default(),
|
|
||||||
epoch: 0,
|
|
||||||
},
|
|
||||||
lamports: 50_000,
|
lamports: 50_000,
|
||||||
};
|
};
|
||||||
process_command(&config_validator).unwrap();
|
process_command(&config_validator).unwrap();
|
||||||
@ -175,10 +172,7 @@ fn test_stake_delegation_and_deactivation_offline() {
|
|||||||
stake_account: read_keypair_file(&stake_keypair_file).unwrap().into(),
|
stake_account: read_keypair_file(&stake_keypair_file).unwrap().into(),
|
||||||
staker: None,
|
staker: None,
|
||||||
withdrawer: None,
|
withdrawer: None,
|
||||||
lockup: Lockup {
|
lockup: Lockup::default(),
|
||||||
custodian: Pubkey::default(),
|
|
||||||
epoch: 0,
|
|
||||||
},
|
|
||||||
lamports: 50_000,
|
lamports: 50_000,
|
||||||
};
|
};
|
||||||
process_command(&config_validator).unwrap();
|
process_command(&config_validator).unwrap();
|
||||||
|
@ -11,7 +11,6 @@ homepage = "https://solana.com/"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.11.0"
|
base64 = "0.11.0"
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
chrono = "0.4"
|
|
||||||
hex = "0.4.0"
|
hex = "0.4.0"
|
||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
//! A command-line executable for generating the chain's genesis config.
|
//! A command-line executable for generating the chain's genesis config.
|
||||||
|
|
||||||
use chrono::DateTime;
|
|
||||||
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg, ArgMatches};
|
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg, ArgMatches};
|
||||||
use solana_clap_utils::{input_parsers::pubkey_of, input_validators::is_valid_percentage};
|
use solana_clap_utils::{
|
||||||
|
input_parsers::{pubkey_of, unix_timestamp_of},
|
||||||
|
input_validators::is_valid_percentage,
|
||||||
|
};
|
||||||
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
||||||
use solana_ledger::{blocktree::create_new_ledger, poh::compute_hashes_per_tick};
|
use solana_ledger::{blocktree::create_new_ledger, poh::compute_hashes_per_tick};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
@ -484,8 +486,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
..GenesisConfig::default()
|
..GenesisConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(creation_time) = matches.value_of("creation_time") {
|
if let Some(creation_time) = unix_timestamp_of(&matches, "creation_time") {
|
||||||
genesis_config.creation_time = DateTime::parse_from_rfc3339(creation_time)?.timestamp();
|
genesis_config.creation_time = creation_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(faucet_pubkey) = faucet_pubkey {
|
if let Some(faucet_pubkey) = faucet_pubkey {
|
||||||
|
@ -109,6 +109,7 @@ pub fn create_and_add_stakes(
|
|||||||
let lockup = Lockup {
|
let lockup = Lockup {
|
||||||
epoch: unlock.epoch,
|
epoch: unlock.epoch,
|
||||||
custodian,
|
custodian,
|
||||||
|
unix_timestamp: 0,
|
||||||
};
|
};
|
||||||
for _ in 0..(lamports / granularity).saturating_sub(1) {
|
for _ in 0..(lamports / granularity).saturating_sub(1) {
|
||||||
genesis_config.add_account(
|
genesis_config.add_account(
|
||||||
|
@ -8,7 +8,7 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{Account, KeyedAccount},
|
account::{Account, KeyedAccount},
|
||||||
account_utils::State,
|
account_utils::State,
|
||||||
clock::{Clock, Epoch, Slot},
|
clock::{Clock, Epoch, Slot, UnixTimestamp},
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
@ -86,7 +86,10 @@ pub enum StakeAuthorize {
|
|||||||
|
|
||||||
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
|
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
|
||||||
pub struct Lockup {
|
pub struct Lockup {
|
||||||
/// epoch at which this stake will allow withdrawal, unless
|
/// UnixTimestamp at which this stake will allow withdrawal, unless
|
||||||
|
/// to the custodian.
|
||||||
|
pub unix_timestamp: UnixTimestamp,
|
||||||
|
/// epoch height at which this stake will allow withdrawal, unless
|
||||||
/// to the custodian
|
/// to the custodian
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
/// custodian account, the only account to which this stake will honor a
|
/// custodian account, the only account to which this stake will honor a
|
||||||
@ -95,6 +98,13 @@ pub struct Lockup {
|
|||||||
pub custodian: Pubkey,
|
pub custodian: Pubkey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Lockup {
|
||||||
|
pub fn is_in_force(&self, clock: &Clock, signers: &HashSet<Pubkey>) -> bool {
|
||||||
|
(self.unix_timestamp > clock.unix_timestamp || self.epoch > clock.epoch)
|
||||||
|
&& !signers.contains(&self.custodian)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
|
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
|
||||||
pub struct Authorized {
|
pub struct Authorized {
|
||||||
pub staker: Pubkey,
|
pub staker: Pubkey,
|
||||||
@ -754,8 +764,8 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// verify that lockup has expired or that the withdrawal is signed by
|
// verify that lockup has expired or that the withdrawal is signed by
|
||||||
// the custodian
|
// the custodian, both epoch and unix_timestamp must have passed
|
||||||
if lockup.epoch > clock.epoch && !signers.contains(&lockup.custodian) {
|
if lockup.is_in_force(&clock, signers) {
|
||||||
return Err(StakeError::LockupInForce.into());
|
return Err(StakeError::LockupInForce.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1404,6 +1414,7 @@ mod tests {
|
|||||||
&Authorized::auto(&stake_pubkey),
|
&Authorized::auto(&stake_pubkey),
|
||||||
&Lockup {
|
&Lockup {
|
||||||
epoch: 1,
|
epoch: 1,
|
||||||
|
unix_timestamp: 0,
|
||||||
custodian
|
custodian
|
||||||
},
|
},
|
||||||
&Rent::free(),
|
&Rent::free(),
|
||||||
@ -1415,6 +1426,7 @@ mod tests {
|
|||||||
StakeState::from(&stake_keyed_account.account).unwrap(),
|
StakeState::from(&stake_keyed_account.account).unwrap(),
|
||||||
StakeState::Initialized(Meta {
|
StakeState::Initialized(Meta {
|
||||||
lockup: Lockup {
|
lockup: Lockup {
|
||||||
|
unix_timestamp: 0,
|
||||||
epoch: 1,
|
epoch: 1,
|
||||||
custodian
|
custodian
|
||||||
},
|
},
|
||||||
@ -1555,6 +1567,7 @@ mod tests {
|
|||||||
.initialize(
|
.initialize(
|
||||||
&Authorized::auto(&stake_pubkey),
|
&Authorized::auto(&stake_pubkey),
|
||||||
&Lockup {
|
&Lockup {
|
||||||
|
unix_timestamp: 0,
|
||||||
epoch: 0,
|
epoch: 0,
|
||||||
custodian,
|
custodian,
|
||||||
},
|
},
|
||||||
@ -1759,6 +1772,7 @@ mod tests {
|
|||||||
total_lamports,
|
total_lamports,
|
||||||
&StakeState::Initialized(Meta {
|
&StakeState::Initialized(Meta {
|
||||||
lockup: Lockup {
|
lockup: Lockup {
|
||||||
|
unix_timestamp: 0,
|
||||||
epoch: 1,
|
epoch: 1,
|
||||||
custodian,
|
custodian,
|
||||||
},
|
},
|
||||||
@ -2591,6 +2605,77 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lockup_is_expired() {
|
||||||
|
let custodian = Pubkey::new_rand();
|
||||||
|
let signers = [custodian].iter().cloned().collect::<HashSet<_>>();
|
||||||
|
let lockup = Lockup {
|
||||||
|
epoch: 1,
|
||||||
|
unix_timestamp: 1,
|
||||||
|
custodian,
|
||||||
|
};
|
||||||
|
// neither time
|
||||||
|
assert_eq!(
|
||||||
|
lockup.is_in_force(
|
||||||
|
&Clock {
|
||||||
|
epoch: 0,
|
||||||
|
unix_timestamp: 0,
|
||||||
|
..Clock::default()
|
||||||
|
},
|
||||||
|
&HashSet::new()
|
||||||
|
),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// not timestamp
|
||||||
|
assert_eq!(
|
||||||
|
lockup.is_in_force(
|
||||||
|
&Clock {
|
||||||
|
epoch: 2,
|
||||||
|
unix_timestamp: 0,
|
||||||
|
..Clock::default()
|
||||||
|
},
|
||||||
|
&HashSet::new()
|
||||||
|
),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// not epoch
|
||||||
|
assert_eq!(
|
||||||
|
lockup.is_in_force(
|
||||||
|
&Clock {
|
||||||
|
epoch: 0,
|
||||||
|
unix_timestamp: 2,
|
||||||
|
..Clock::default()
|
||||||
|
},
|
||||||
|
&HashSet::new()
|
||||||
|
),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// both, no custodian
|
||||||
|
assert_eq!(
|
||||||
|
lockup.is_in_force(
|
||||||
|
&Clock {
|
||||||
|
epoch: 1,
|
||||||
|
unix_timestamp: 1,
|
||||||
|
..Clock::default()
|
||||||
|
},
|
||||||
|
&HashSet::new()
|
||||||
|
),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
// neither, but custodian
|
||||||
|
assert_eq!(
|
||||||
|
lockup.is_in_force(
|
||||||
|
&Clock {
|
||||||
|
epoch: 0,
|
||||||
|
unix_timestamp: 0,
|
||||||
|
..Clock::default()
|
||||||
|
},
|
||||||
|
&signers,
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_authorize_delegated_stake() {
|
fn test_authorize_delegated_stake() {
|
||||||
let stake_pubkey = Pubkey::new_rand();
|
let stake_pubkey = Pubkey::new_rand();
|
||||||
|
Reference in New Issue
Block a user