Move address creation with seed into pubkey (#8991)

This commit is contained in:
Jack May 2020-03-20 15:20:48 -07:00 committed by GitHub
parent 1aab959d4e
commit e28368ff1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 117 additions and 113 deletions

View File

@ -38,9 +38,9 @@ use solana_sdk::{
message::Message,
native_token::lamports_to_sol,
program_utils::DecodeError,
pubkey::Pubkey,
pubkey::{Pubkey, MAX_SEED_LEN},
signature::{Keypair, Signature, Signer, SignerError},
system_instruction::{self, create_address_with_seed, SystemError, MAX_ADDRESS_SEED_LEN},
system_instruction::{self, SystemError},
system_program,
transaction::{Transaction, TransactionError},
};
@ -1076,7 +1076,7 @@ pub fn parse_create_address_with_seed(
let seed = matches.value_of("seed").unwrap().to_string();
if seed.len() > MAX_ADDRESS_SEED_LEN {
if seed.len() > MAX_SEED_LEN {
return Err(CliError::BadParameter(
"Address seed must not be longer than 32 bytes".to_string(),
));
@ -1103,7 +1103,7 @@ fn process_create_address_with_seed(
} else {
config.pubkey()?
};
let address = create_address_with_seed(&from_pubkey, seed, program_id)?;
let address = Pubkey::create_with_seed(&from_pubkey, seed, program_id)?;
Ok(address.to_string())
}
@ -3390,7 +3390,7 @@ mod tests {
};
let address = process_command(&config);
let expected_address =
create_address_with_seed(&from_pubkey, "seed", &solana_stake_program::id()).unwrap();
Pubkey::create_with_seed(&from_pubkey, "seed", &solana_stake_program::id()).unwrap();
assert_eq!(address.unwrap(), expected_address.to_string());
// Need airdrop cases

View File

@ -21,9 +21,8 @@ use solana_sdk::{
},
pubkey::Pubkey,
system_instruction::{
advance_nonce_account, authorize_nonce_account, create_address_with_seed,
create_nonce_account, create_nonce_account_with_seed, withdraw_nonce_account, NonceError,
SystemError,
advance_nonce_account, authorize_nonce_account, create_nonce_account,
create_nonce_account_with_seed, withdraw_nonce_account, NonceError, SystemError,
},
system_program,
transaction::Transaction,
@ -474,7 +473,7 @@ pub fn process_create_nonce_account(
) -> ProcessResult {
let nonce_account_pubkey = config.signers[nonce_account].pubkey();
let nonce_account_address = if let Some(seed) = seed.clone() {
create_address_with_seed(&nonce_account_pubkey, &seed, &system_program::id())?
Pubkey::create_with_seed(&nonce_account_pubkey, &seed, &system_program::id())?
} else {
nonce_account_pubkey
};

View File

@ -17,7 +17,7 @@ use solana_sdk::{
account_utils::StateMut,
message::Message,
pubkey::Pubkey,
system_instruction::{create_address_with_seed, SystemError},
system_instruction::SystemError,
sysvar::{
stake_history::{self, StakeHistory},
Sysvar,
@ -769,7 +769,7 @@ pub fn process_create_stake_account(
) -> ProcessResult {
let stake_account = config.signers[stake_account];
let stake_account_address = if let Some(seed) = seed {
create_address_with_seed(&stake_account.pubkey(), &seed, &solana_stake_program::id())?
Pubkey::create_with_seed(&stake_account.pubkey(), &seed, &solana_stake_program::id())?
} else {
stake_account.pubkey()
};
@ -1085,7 +1085,7 @@ pub fn process_split_stake(
let stake_authority = config.signers[stake_authority];
let split_stake_account_address = if let Some(seed) = split_stake_account_seed {
create_address_with_seed(
Pubkey::create_with_seed(
&split_stake_account.pubkey(),
&seed,
&solana_stake_program::id(),

View File

@ -8,12 +8,8 @@ use solana_clap_utils::{input_parsers::*, input_validators::*};
use solana_client::rpc_client::RpcClient;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
account::Account,
commitment_config::CommitmentConfig,
message::Message,
pubkey::Pubkey,
system_instruction::{create_address_with_seed, SystemError},
transaction::Transaction,
account::Account, commitment_config::CommitmentConfig, message::Message, pubkey::Pubkey,
system_instruction::SystemError, transaction::Transaction,
};
use solana_vote_program::{
vote_instruction::{self, withdraw, VoteError},
@ -381,7 +377,7 @@ pub fn process_create_vote_account(
let vote_account = config.signers[1];
let vote_account_pubkey = vote_account.pubkey();
let vote_account_address = if let Some(seed) = seed {
create_address_with_seed(&vote_account_pubkey, &seed, &solana_vote_program::id())?
Pubkey::create_with_seed(&vote_account_pubkey, &seed, &solana_vote_program::id())?
} else {
vote_account_pubkey
};

View File

@ -13,7 +13,6 @@ use solana_sdk::{
hash::Hash,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, Signer},
system_instruction::create_address_with_seed,
system_program,
};
use std::{fs::remove_dir_all, sync::mpsc::channel, thread::sleep, time::Duration};
@ -130,7 +129,7 @@ fn full_battery_tests(
config_nonce.signers = vec![&nonce_keypair];
let nonce_account = if let Some(seed) = seed.as_ref() {
create_address_with_seed(
Pubkey::create_with_seed(
&config_nonce.signers[0].pubkey(),
seed,
&system_program::id(),
@ -301,7 +300,7 @@ fn test_create_account_with_seed() {
let authority_pubkey = offline_nonce_authority_signer.pubkey();
let seed = authority_pubkey.to_string()[0..32].to_string();
let nonce_address =
create_address_with_seed(&creator_pubkey, &seed, &system_program::id()).unwrap();
Pubkey::create_with_seed(&creator_pubkey, &seed, &system_program::id()).unwrap();
check_balance(0, &rpc_client, &nonce_address);
let mut creator_config = CliConfig::default();

View File

@ -14,7 +14,6 @@ use solana_sdk::{
nonce::State as NonceState,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, Signer},
system_instruction::create_address_with_seed,
};
use solana_stake_program::{
stake_instruction::LockupArgs,
@ -160,7 +159,7 @@ fn test_seed_stake_delegation_and_deactivation() {
.unwrap();
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
let stake_address = create_address_with_seed(
let stake_address = Pubkey::create_with_seed(
&config_validator.signers[0].pubkey(),
"hi there",
&solana_stake_program::id(),
@ -1512,7 +1511,7 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
};
process_command(&config).unwrap();
let seed_address =
create_address_with_seed(&stake_pubkey, seed, &solana_stake_program::id()).unwrap();
Pubkey::create_with_seed(&stake_pubkey, seed, &solana_stake_program::id()).unwrap();
check_balance(50_000, &rpc_client, &seed_address);
server.close().unwrap();

View File

@ -1,4 +1,4 @@
use solana_sdk::{pubkey::Pubkey, system_instruction::create_address_with_seed};
use solana_sdk::pubkey::Pubkey;
#[derive(Default)]
pub struct AddressGenerator {
@ -17,7 +17,7 @@ impl AddressGenerator {
}
pub fn nth(&self, nth: usize) -> Pubkey {
create_address_with_seed(&self.base_pubkey, &format!("{}", nth), &self.program_id).unwrap()
Pubkey::create_with_seed(&self.base_pubkey, &format!("{}", nth), &self.program_id).unwrap()
}
#[allow(clippy::should_implement_trait)]

View File

@ -6,9 +6,7 @@ use solana_sdk::{
nonce::{self, Account as NonceAccount},
program_utils::{limited_deserialize, next_keyed_account},
pubkey::Pubkey,
system_instruction::{
create_address_with_seed, SystemError, SystemInstruction, MAX_PERMITTED_DATA_LENGTH,
},
system_instruction::{SystemError, SystemInstruction, MAX_PERMITTED_DATA_LENGTH},
system_program,
sysvar::{self, recent_blockhashes::RecentBlockhashes, rent::Rent, Sysvar},
};
@ -36,7 +34,7 @@ impl Address {
) -> Result<Self, InstructionError> {
let base = if let Some((base, seed, program_id)) = with_seed {
// re-derive the address, must match the supplied address
if *address != create_address_with_seed(base, seed, program_id)? {
if *address != Pubkey::create_with_seed(base, seed, program_id)? {
return Err(SystemError::AddressWithSeedMismatch.into());
}
Some(*base)
@ -404,7 +402,7 @@ mod tests {
let new_program_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_rand();
let seed = "shiny pepper";
let to = create_address_with_seed(&from, seed, &new_program_owner).unwrap();
let to = Pubkey::create_with_seed(&from, seed, &new_program_owner).unwrap();
let from_account = Account::new_ref(100, 0, &system_program::id());
let to_account = Account::new_ref(0, 0, &Pubkey::default());
@ -451,7 +449,7 @@ mod tests {
let new_program_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_rand();
let seed = "dull boy";
let to = create_address_with_seed(&from, seed, &new_program_owner).unwrap();
let to = Pubkey::create_with_seed(&from, seed, &new_program_owner).unwrap();
let from_account = Account::new_ref(100, 0, &system_program::id());
let mut to_account = Account::new(0, 0, &Pubkey::default());
@ -919,7 +917,7 @@ mod tests {
let alice_pubkey = alice_keypair.pubkey();
let seed = "seed";
let program_id = Pubkey::new_rand();
let alice_with_seed = create_address_with_seed(&alice_pubkey, seed, &program_id).unwrap();
let alice_with_seed = Pubkey::create_with_seed(&alice_pubkey, seed, &program_id).unwrap();
bank_client
.transfer(50, &mint_keypair, &alice_pubkey)
@ -1029,7 +1027,7 @@ mod tests {
let alice_pubkey = alice_keypair.pubkey();
let seed = "seed";
let program_id = Pubkey::new_rand();
let alice_with_seed = create_address_with_seed(&alice_pubkey, seed, &program_id).unwrap();
let alice_with_seed = Pubkey::create_with_seed(&alice_pubkey, seed, &program_id).unwrap();
bank_client
.transfer(50, &mint_keypair, &alice_pubkey)

View File

@ -9,7 +9,6 @@ use solana_sdk::{
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
system_instruction::create_address_with_seed,
sysvar::{self, stake_history::StakeHistory, Sysvar},
};
use solana_stake_program::{
@ -114,7 +113,7 @@ fn test_stake_create_and_split_single_signature() {
let bank_client = BankClient::new_shared(&Arc::new(Bank::new(&genesis_config)));
let stake_address =
create_address_with_seed(&staker_pubkey, "stake", &solana_stake_program::id()).unwrap();
Pubkey::create_with_seed(&staker_pubkey, "stake", &solana_stake_program::id()).unwrap();
let authorized = stake_state::Authorized::auto(&staker_pubkey);
@ -138,7 +137,7 @@ fn test_stake_create_and_split_single_signature() {
// split the stake
let split_stake_address =
create_address_with_seed(&staker_pubkey, "split_stake", &solana_stake_program::id())
Pubkey::create_with_seed(&staker_pubkey, "split_stake", &solana_stake_program::id())
.unwrap();
// Test split
let message = Message::new(&stake_instruction::split_with_seed(
@ -413,7 +412,7 @@ fn test_create_stake_account_from_seed() {
let seed = "test-string";
let stake_pubkey =
create_address_with_seed(&mint_pubkey, seed, &solana_stake_program::id()).unwrap();
Pubkey::create_with_seed(&mint_pubkey, seed, &solana_stake_program::id()).unwrap();
// Create Vote Account
let message = Message::new(&vote_instruction::create_account(

View File

@ -1,7 +1,25 @@
use crate::{hash::hashv, program_utils::DecodeError};
use num_derive::{FromPrimitive, ToPrimitive};
use std::{convert::TryFrom, error, fmt, mem, str::FromStr};
use thiserror::Error;
pub use bs58;
/// maximum length of derived pubkey seed
pub const MAX_SEED_LEN: usize = 32;
#[derive(Error, Debug, Serialize, Clone, PartialEq, FromPrimitive, ToPrimitive)]
pub enum PubkeyError {
#[error("length of requested seed is too long")]
MaxSeedLengthExceeded,
}
impl<T> DecodeError<T> for PubkeyError {
fn type_of() -> &'static str {
"PubkeyError"
}
}
#[repr(transparent)]
#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Pubkey([u8; 32]);
@ -47,6 +65,20 @@ impl Pubkey {
Self(pubkey_array)
}
pub fn create_with_seed(
base: &Pubkey,
seed: &str,
program_id: &Pubkey,
) -> Result<Pubkey, PubkeyError> {
if seed.len() > MAX_SEED_LEN {
return Err(PubkeyError::MaxSeedLengthExceeded);
}
Ok(Pubkey::new(
hashv(&[base.as_ref(), seed.as_ref(), program_id.as_ref()]).as_ref(),
))
}
#[cfg(not(feature = "program"))]
pub fn new_rand() -> Self {
Self::new(&rand::random::<[u8; 32]>())
@ -101,7 +133,7 @@ pub fn read_pubkey_file(infile: &str) -> Result<Pubkey, Box<dyn error::Error>> {
#[cfg(test)]
mod tests {
use super::*;
use std::fs::remove_file;
use std::{fs::remove_file, str::from_utf8};
#[test]
fn pubkey_fromstr() {
@ -136,6 +168,58 @@ mod tests {
);
}
#[test]
fn test_create_with_seed() {
assert!(Pubkey::create_with_seed(&Pubkey::new_rand(), "", &Pubkey::new_rand()).is_ok());
assert_eq!(
Pubkey::create_with_seed(
&Pubkey::new_rand(),
from_utf8(&[127; MAX_SEED_LEN + 1]).unwrap(),
&Pubkey::new_rand()
),
Err(PubkeyError::MaxSeedLengthExceeded)
);
assert!(Pubkey::create_with_seed(
&Pubkey::new_rand(),
"\
\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\
",
&Pubkey::new_rand()
)
.is_ok());
// utf-8 abuse ;)
assert_eq!(
Pubkey::create_with_seed(
&Pubkey::new_rand(),
"\
x\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\
",
&Pubkey::new_rand()
),
Err(PubkeyError::MaxSeedLengthExceeded)
);
assert!(Pubkey::create_with_seed(
&Pubkey::new_rand(),
std::str::from_utf8(&[0; MAX_SEED_LEN]).unwrap(),
&Pubkey::new_rand(),
)
.is_ok());
assert!(Pubkey::create_with_seed(&Pubkey::new_rand(), "", &Pubkey::new_rand(),).is_ok());
assert_eq!(
Pubkey::create_with_seed(
&Pubkey::default(),
"limber chicken: 4/45",
&Pubkey::default(),
),
Ok("9h1HyLCW5dZnBVap8C5egQ9Z6pHyjsh5MNy83iPqqRuq"
.parse()
.unwrap())
);
}
#[test]
fn test_read_write_pubkey() -> Result<(), Box<dyn error::Error>> {
let filename = "test_pubkey.json";

View File

@ -1,5 +1,4 @@
use crate::{
hash::hashv,
instruction::{AccountMeta, Instruction, WithSigner},
nonce,
program_utils::DecodeError,
@ -50,9 +49,6 @@ impl<E> DecodeError<E> for NonceError {
}
}
/// maximum length of derived address seed
pub const MAX_ADDRESS_SEED_LEN: usize = 32;
/// maximum permitted size of data: 10 MB
pub const MAX_PERMITTED_DATA_LENGTH: u64 = 10 * 1024 * 1024;
@ -80,7 +76,7 @@ pub enum SystemInstruction {
/// a base pubkey and a seed
/// * Transaction::keys[0] - source
/// * Transaction::keys[1] - new account key
/// * seed - string of ascii chars, no longer than MAX_ADDRESS_SEED_LEN
/// * seed - string of ascii chars, no longer than pubkey::MAX_SEED_LEN
/// * lamports - number of lamports to transfer to the new account
/// * space - number of bytes of memory to allocate
/// * program_id - the program id of the new account
@ -143,7 +139,7 @@ pub enum SystemInstruction {
/// Allocate space for and assign an account at an address
/// derived from a base pubkey and a seed
/// * Transaction::keys[0] - new account key
/// * seed - string of ascii chars, no longer than MAX_ADDRESS_SEED_LEN
/// * seed - string of ascii chars, no longer than pubkey::MAX_SEED_LEN
/// * space - number of bytes of memory to allocate
/// * program_id - the program id of the new account
AllocateWithSeed {
@ -154,7 +150,7 @@ pub enum SystemInstruction {
},
/// Assign account to a program based on a seed
/// * Transaction::keys[0] - account to assign
/// * seed - string of ascii chars, no longer than MAX_ADDRESS_SEED_LEN
/// * seed - string of ascii chars, no longer than pubkey::MAX_SEED_LEN
/// * program_id - the program id of the new account
AssignWithSeed {
base: Pubkey,
@ -293,20 +289,6 @@ pub fn transfer_many(from_pubkey: &Pubkey, to_lamports: &[(Pubkey, u64)]) -> Vec
.collect()
}
pub fn create_address_with_seed(
base: &Pubkey,
seed: &str,
program_id: &Pubkey,
) -> Result<Pubkey, SystemError> {
if seed.len() > MAX_ADDRESS_SEED_LEN {
return Err(SystemError::MaxSeedLengthExceeded);
}
Ok(Pubkey::new(
hashv(&[base.as_ref(), seed.as_ref(), program_id.as_ref()]).as_ref(),
))
}
pub fn create_nonce_account_with_seed(
from_pubkey: &Pubkey,
nonce_pubkey: &Pubkey,
@ -418,58 +400,6 @@ mod tests {
instruction.accounts.iter().map(|x| x.pubkey).collect()
}
#[test]
fn test_create_address_with_seed() {
assert!(create_address_with_seed(&Pubkey::new_rand(), "", &Pubkey::new_rand()).is_ok());
assert_eq!(
create_address_with_seed(
&Pubkey::new_rand(),
std::str::from_utf8(&[127; MAX_ADDRESS_SEED_LEN + 1]).unwrap(),
&Pubkey::new_rand()
),
Err(SystemError::MaxSeedLengthExceeded)
);
assert!(create_address_with_seed(
&Pubkey::new_rand(),
"\
\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\
",
&Pubkey::new_rand()
)
.is_ok());
// utf-8 abuse ;)
assert_eq!(
create_address_with_seed(
&Pubkey::new_rand(),
"\
x\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\u{10FFFF}\
",
&Pubkey::new_rand()
),
Err(SystemError::MaxSeedLengthExceeded)
);
assert!(create_address_with_seed(
&Pubkey::new_rand(),
std::str::from_utf8(&[0; MAX_ADDRESS_SEED_LEN]).unwrap(),
&Pubkey::new_rand(),
)
.is_ok());
assert!(create_address_with_seed(&Pubkey::new_rand(), "", &Pubkey::new_rand(),).is_ok());
assert_eq!(
create_address_with_seed(
&Pubkey::default(),
"limber chicken: 4/45",
&Pubkey::default(),
),
Ok("9h1HyLCW5dZnBVap8C5egQ9Z6pHyjsh5MNy83iPqqRuq"
.parse()
.unwrap())
);
}
#[test]
fn test_move_many() {
let alice_pubkey = Pubkey::new_rand();