terminology update, nonce to bump seed (#12840)
This commit is contained in:
@ -31,9 +31,9 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
return ERROR_INVALID_ARGUMENT;
|
return ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t nonce1 = params.data[1];
|
uint8_t bump_seed1 = params.data[1];
|
||||||
uint8_t nonce2 = params.data[2];
|
uint8_t bump_seed2 = params.data[2];
|
||||||
uint8_t nonce3 = params.data[3];
|
uint8_t bump_seed3 = params.data[3];
|
||||||
|
|
||||||
switch (params.data[0]) {
|
switch (params.data[0]) {
|
||||||
case TEST_SUCCESS: {
|
case TEST_SUCCESS: {
|
||||||
@ -54,7 +54,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
|
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
|
||||||
' ', 'b', 'u', 't', 't', 'e', 'r'};
|
' ', 'b', 'u', 't', 't', 'e', 'r'};
|
||||||
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
||||||
{&nonce1, 1}};
|
{&bump_seed1, 1}};
|
||||||
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)}};
|
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)}};
|
||||||
sol_assert(SUCCESS == sol_invoke_signed(&instruction, accounts,
|
sol_assert(SUCCESS == sol_invoke_signed(&instruction, accounts,
|
||||||
SOL_ARRAY_SIZE(accounts),
|
SOL_ARRAY_SIZE(accounts),
|
||||||
@ -144,7 +144,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
|
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
|
||||||
' ', 'b', 'u', 't', 't', 'e', 'r'};
|
' ', 'b', 'u', 't', 't', 'e', 'r'};
|
||||||
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
||||||
{&nonce1, 1}};
|
{&bump_seed1, 1}};
|
||||||
SolPubkey address;
|
SolPubkey address;
|
||||||
sol_assert(SUCCESS ==
|
sol_assert(SUCCESS ==
|
||||||
sol_create_program_address(seeds1, SOL_ARRAY_SIZE(seeds1),
|
sol_create_program_address(seeds1, SOL_ARRAY_SIZE(seeds1),
|
||||||
@ -163,14 +163,14 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
{accounts[DERIVED_KEY1_INDEX].key, true, true},
|
{accounts[DERIVED_KEY1_INDEX].key, true, true},
|
||||||
{accounts[DERIVED_KEY2_INDEX].key, true, false},
|
{accounts[DERIVED_KEY2_INDEX].key, true, false},
|
||||||
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
|
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
|
||||||
uint8_t data[] = {TEST_DERIVED_SIGNERS, nonce2, nonce3};
|
uint8_t data[] = {TEST_DERIVED_SIGNERS, bump_seed2, bump_seed3};
|
||||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||||
arguments, SOL_ARRAY_SIZE(arguments),
|
arguments, SOL_ARRAY_SIZE(arguments),
|
||||||
data, SOL_ARRAY_SIZE(data)};
|
data, SOL_ARRAY_SIZE(data)};
|
||||||
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
|
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
|
||||||
' ', 'b', 'u', 't', 't', 'e', 'r'};
|
' ', 'b', 'u', 't', 't', 'e', 'r'};
|
||||||
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
||||||
{&nonce1, 1}};
|
{&bump_seed1, 1}};
|
||||||
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)}};
|
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)}};
|
||||||
sol_assert(SUCCESS == sol_invoke_signed(&instruction, accounts,
|
sol_assert(SUCCESS == sol_invoke_signed(&instruction, accounts,
|
||||||
SOL_ARRAY_SIZE(accounts),
|
SOL_ARRAY_SIZE(accounts),
|
||||||
|
@ -101,8 +101,8 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
|
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
|
||||||
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
|
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
|
||||||
|
|
||||||
uint8_t nonce2 = params.data[1];
|
uint8_t bump_seed2 = params.data[1];
|
||||||
uint8_t nonce3 = params.data[2];
|
uint8_t bump_seed3 = params.data[2];
|
||||||
|
|
||||||
SolAccountMeta arguments[] = {
|
SolAccountMeta arguments[] = {
|
||||||
{accounts[DERIVED_KEY1_INDEX].key, true, false},
|
{accounts[DERIVED_KEY1_INDEX].key, true, false},
|
||||||
@ -116,10 +116,10 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
uint8_t seed2[] = {'B', 'i', 't', 's'};
|
uint8_t seed2[] = {'B', 'i', 't', 's'};
|
||||||
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
const SolSignerSeed seeds1[] = {{seed1, SOL_ARRAY_SIZE(seed1)},
|
||||||
{seed2, SOL_ARRAY_SIZE(seed2)},
|
{seed2, SOL_ARRAY_SIZE(seed2)},
|
||||||
{&nonce2, 1}};
|
{&bump_seed2, 1}};
|
||||||
const SolSignerSeed seeds2[] = {
|
const SolSignerSeed seeds2[] = {
|
||||||
{(uint8_t *)accounts[DERIVED_KEY2_INDEX].key, SIZE_PUBKEY},
|
{(uint8_t *)accounts[DERIVED_KEY2_INDEX].key, SIZE_PUBKEY},
|
||||||
{&nonce3, 1}};
|
{&bump_seed3, 1}};
|
||||||
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)},
|
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)},
|
||||||
{seeds2, SOL_ARRAY_SIZE(seeds2)}};
|
{seeds2, SOL_ARRAY_SIZE(seeds2)}};
|
||||||
|
|
||||||
|
@ -41,9 +41,9 @@ fn process_instruction(
|
|||||||
) -> ProgramResult {
|
) -> ProgramResult {
|
||||||
info!("invoke Rust program");
|
info!("invoke Rust program");
|
||||||
|
|
||||||
let nonce1 = instruction_data[1];
|
let bump_seed1 = instruction_data[1];
|
||||||
let nonce2 = instruction_data[2];
|
let bump_seed2 = instruction_data[2];
|
||||||
let nonce3 = instruction_data[3];
|
let bump_seed3 = instruction_data[3];
|
||||||
|
|
||||||
match instruction_data[0] {
|
match instruction_data[0] {
|
||||||
TEST_SUCCESS => {
|
TEST_SUCCESS => {
|
||||||
@ -63,7 +63,11 @@ fn process_instruction(
|
|||||||
MAX_PERMITTED_DATA_INCREASE as u64,
|
MAX_PERMITTED_DATA_INCREASE as u64,
|
||||||
program_id,
|
program_id,
|
||||||
);
|
);
|
||||||
invoke_signed(&instruction, accounts, &[&[b"You pass butter", &[nonce1]]])?;
|
invoke_signed(
|
||||||
|
&instruction,
|
||||||
|
accounts,
|
||||||
|
&[&[b"You pass butter", &[bump_seed1]]],
|
||||||
|
)?;
|
||||||
|
|
||||||
assert_eq!(accounts[FROM_INDEX].lamports(), from_lamports - 42);
|
assert_eq!(accounts[FROM_INDEX].lamports(), from_lamports - 42);
|
||||||
assert_eq!(accounts[DERIVED_KEY1_INDEX].lamports(), to_lamports + 42);
|
assert_eq!(accounts[DERIVED_KEY1_INDEX].lamports(), to_lamports + 42);
|
||||||
@ -143,7 +147,10 @@ fn process_instruction(
|
|||||||
info!("Test create_program_address");
|
info!("Test create_program_address");
|
||||||
{
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&Pubkey::create_program_address(&[b"You pass butter", &[nonce1]], program_id)?,
|
&Pubkey::create_program_address(
|
||||||
|
&[b"You pass butter", &[bump_seed1]],
|
||||||
|
program_id
|
||||||
|
)?,
|
||||||
accounts[DERIVED_KEY1_INDEX].key
|
accounts[DERIVED_KEY1_INDEX].key
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -167,12 +174,12 @@ fn process_instruction(
|
|||||||
(accounts[DERIVED_KEY2_INDEX].key, true, false),
|
(accounts[DERIVED_KEY2_INDEX].key, true, false),
|
||||||
(accounts[DERIVED_KEY3_INDEX].key, false, false),
|
(accounts[DERIVED_KEY3_INDEX].key, false, false),
|
||||||
],
|
],
|
||||||
vec![TEST_DERIVED_SIGNERS, nonce2, nonce3],
|
vec![TEST_DERIVED_SIGNERS, bump_seed2, bump_seed3],
|
||||||
);
|
);
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
&invoked_instruction,
|
&invoked_instruction,
|
||||||
accounts,
|
accounts,
|
||||||
&[&[b"You pass butter", &[nonce1]]],
|
&[&[b"You pass butter", &[bump_seed1]]],
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ fn process_instruction(
|
|||||||
assert!(!accounts[DERIVED_KEY2_INDEX].is_signer);
|
assert!(!accounts[DERIVED_KEY2_INDEX].is_signer);
|
||||||
assert!(!accounts[DERIVED_KEY3_INDEX].is_signer);
|
assert!(!accounts[DERIVED_KEY3_INDEX].is_signer);
|
||||||
|
|
||||||
let nonce2 = instruction_data[1];
|
let bump_seed2 = instruction_data[1];
|
||||||
let nonce3 = instruction_data[2];
|
let bump_seed3 = instruction_data[2];
|
||||||
let invoked_instruction = create_instruction(
|
let invoked_instruction = create_instruction(
|
||||||
*accounts[INVOKED_PROGRAM_INDEX].key,
|
*accounts[INVOKED_PROGRAM_INDEX].key,
|
||||||
&[
|
&[
|
||||||
@ -133,8 +133,8 @@ fn process_instruction(
|
|||||||
&invoked_instruction,
|
&invoked_instruction,
|
||||||
accounts,
|
accounts,
|
||||||
&[
|
&[
|
||||||
&[b"Lil'", b"Bits", &[nonce2]],
|
&[b"Lil'", b"Bits", &[bump_seed2]],
|
||||||
&[accounts[DERIVED_KEY2_INDEX].key.as_ref(), &[nonce3]],
|
&[accounts[DERIVED_KEY2_INDEX].key.as_ref(), &[bump_seed3]],
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -480,11 +480,11 @@ fn test_program_bpf_invoke() {
|
|||||||
let account = Account::new(84, 0, &solana_sdk::system_program::id());
|
let account = Account::new(84, 0, &solana_sdk::system_program::id());
|
||||||
bank.store_account(&from_keypair.pubkey(), &account);
|
bank.store_account(&from_keypair.pubkey(), &account);
|
||||||
|
|
||||||
let (derived_key1, nonce1) =
|
let (derived_key1, bump_seed1) =
|
||||||
Pubkey::find_program_address(&[b"You pass butter"], &invoke_program_id);
|
Pubkey::find_program_address(&[b"You pass butter"], &invoke_program_id);
|
||||||
let (derived_key2, nonce2) =
|
let (derived_key2, bump_seed2) =
|
||||||
Pubkey::find_program_address(&[b"Lil'", b"Bits"], &invoked_program_id);
|
Pubkey::find_program_address(&[b"Lil'", b"Bits"], &invoked_program_id);
|
||||||
let (derived_key3, nonce3) =
|
let (derived_key3, bump_seed3) =
|
||||||
Pubkey::find_program_address(&[derived_key2.as_ref()], &invoked_program_id);
|
Pubkey::find_program_address(&[derived_key2.as_ref()], &invoked_program_id);
|
||||||
|
|
||||||
let mint_pubkey = mint_keypair.pubkey();
|
let mint_pubkey = mint_keypair.pubkey();
|
||||||
@ -506,7 +506,7 @@ fn test_program_bpf_invoke() {
|
|||||||
|
|
||||||
let instruction = Instruction::new(
|
let instruction = Instruction::new(
|
||||||
invoke_program_id,
|
invoke_program_id,
|
||||||
&[TEST_SUCCESS, nonce1, nonce2, nonce3],
|
&[TEST_SUCCESS, bump_seed1, bump_seed2, bump_seed3],
|
||||||
account_metas.clone(),
|
account_metas.clone(),
|
||||||
);
|
);
|
||||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||||
@ -548,7 +548,7 @@ fn test_program_bpf_invoke() {
|
|||||||
|
|
||||||
let instruction = Instruction::new(
|
let instruction = Instruction::new(
|
||||||
invoke_program_id,
|
invoke_program_id,
|
||||||
&[TEST_PRIVILEGE_ESCALATION_SIGNER, nonce1, nonce2, nonce3],
|
&[TEST_PRIVILEGE_ESCALATION_SIGNER, bump_seed1, bump_seed2, bump_seed3],
|
||||||
account_metas.clone(),
|
account_metas.clone(),
|
||||||
);
|
);
|
||||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||||
@ -576,7 +576,7 @@ fn test_program_bpf_invoke() {
|
|||||||
|
|
||||||
let instruction = Instruction::new(
|
let instruction = Instruction::new(
|
||||||
invoke_program_id,
|
invoke_program_id,
|
||||||
&[TEST_PRIVILEGE_ESCALATION_WRITABLE, nonce1, nonce2, nonce3],
|
&[TEST_PRIVILEGE_ESCALATION_WRITABLE, bump_seed1, bump_seed2, bump_seed3],
|
||||||
account_metas.clone(),
|
account_metas.clone(),
|
||||||
);
|
);
|
||||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||||
@ -603,7 +603,7 @@ fn test_program_bpf_invoke() {
|
|||||||
|
|
||||||
let instruction = Instruction::new(
|
let instruction = Instruction::new(
|
||||||
invoke_program_id,
|
invoke_program_id,
|
||||||
&[TEST_PPROGRAM_NOT_EXECUTABLE, nonce1, nonce2, nonce3],
|
&[TEST_PPROGRAM_NOT_EXECUTABLE, bump_seed1, bump_seed2, bump_seed3],
|
||||||
account_metas.clone(),
|
account_metas.clone(),
|
||||||
);
|
);
|
||||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||||
|
@ -112,8 +112,8 @@ impl Pubkey {
|
|||||||
///
|
///
|
||||||
/// Because the program address cannot lie on the ed25519 curve there may be
|
/// Because the program address cannot lie on the ed25519 curve there may be
|
||||||
/// seed and program id combinations that are invalid. In these cases an
|
/// seed and program id combinations that are invalid. In these cases an
|
||||||
/// extra seed (nonce) can be calculated that results in a point off the
|
/// extra seed (bump seed) can be calculated that results in a point off the
|
||||||
/// curve. Use `find_program_address` to calculate that nonce.
|
/// curve. Use `find_program_address` to calculate that bump seed.
|
||||||
///
|
///
|
||||||
/// Warning: Because of the way the seeds are hashed there is a potential
|
/// Warning: Because of the way the seeds are hashed there is a potential
|
||||||
/// for program address collisions for the same program id. The seeds are
|
/// for program address collisions for the same program id. The seeds are
|
||||||
@ -176,22 +176,22 @@ impl Pubkey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a valid program address and its corresponding nonce which must be passed
|
/// Find a valid program address and its corresponding bump seed which must be passed
|
||||||
/// as an additional seed when calling `invoke_signed`
|
/// as an additional seed when calling `invoke_signed`
|
||||||
#[allow(clippy::same_item_push)]
|
#[allow(clippy::same_item_push)]
|
||||||
pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8) {
|
pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8) {
|
||||||
let mut nonce = [std::u8::MAX];
|
let mut bump_seed = [std::u8::MAX];
|
||||||
for _ in 0..std::u8::MAX {
|
for _ in 0..std::u8::MAX {
|
||||||
{
|
{
|
||||||
let mut seeds_with_nonce = seeds.to_vec();
|
let mut seeds_with_bump = seeds.to_vec();
|
||||||
seeds_with_nonce.push(&nonce);
|
seeds_with_bump.push(&bump_seed);
|
||||||
if let Ok(address) = Self::create_program_address(&seeds_with_nonce, program_id) {
|
if let Ok(address) = Self::create_program_address(&seeds_with_bump, program_id) {
|
||||||
return (address, nonce[0]);
|
return (address, bump_seed[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nonce[0] -= 1;
|
bump_seed[0] -= 1;
|
||||||
}
|
}
|
||||||
panic!("Unable to find a viable program address nonce");
|
panic!("Unable to find a viable program address bump seed");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "program"))]
|
#[cfg(not(feature = "program"))]
|
||||||
@ -411,10 +411,12 @@ mod tests {
|
|||||||
fn test_find_program_address() {
|
fn test_find_program_address() {
|
||||||
for _ in 0..1_000 {
|
for _ in 0..1_000 {
|
||||||
let program_id = Pubkey::new_rand();
|
let program_id = Pubkey::new_rand();
|
||||||
let (address, nonce) = Pubkey::find_program_address(&[b"Lil'", b"Bits"], &program_id);
|
let (address, bump_seed) =
|
||||||
|
Pubkey::find_program_address(&[b"Lil'", b"Bits"], &program_id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
address,
|
address,
|
||||||
Pubkey::create_program_address(&[b"Lil'", b"Bits", &[nonce]], &program_id).unwrap()
|
Pubkey::create_program_address(&[b"Lil'", b"Bits", &[bump_seed]], &program_id)
|
||||||
|
.unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user