Skip to content

Commit

Permalink
Remove initialize signers (solana-labs#84)
Browse files Browse the repository at this point in the history
* Remove initialize signers

* update js to do initialize atomically
  • Loading branch information
jackcmay authored Jul 7, 2020
1 parent 271073e commit 666b0b7
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 72 deletions.
18 changes: 15 additions & 3 deletions token/inc/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ typedef enum Token_TokenInstruction_Tag {
/**
* Initializes a new mint and optionally deposits all the newly minted tokens in an account.
*
* The `InitializeWrappedAccount` instruction requires no signers and MUST be included within
* the Transaction that creates the uninitialized account with the system program. Otherwise
* another party can acquire ownership of the uninitialized token account.
*
* Accounts expected by this instruction:
*
* 0. `[writable, signer]` The mint to initialize.
* 0. `[writable]` The mint to initialize.
* 1.
* * If supply is non-zero: `[writable]` The account to hold all the newly minted tokens.
* * If supply is zero: `[]` The owner/multisignature of the mint.
Expand All @@ -52,9 +56,13 @@ typedef enum Token_TokenInstruction_Tag {
/**
* Initializes a new account to hold tokens.
*
* The `InitializeWrappedAccount` instruction requires no signers and MUST be included within
* the Transaction that creates the uninitialized account with the system program. Otherwise
* another party can acquire ownership of the uninitialized token account.
*
* Accounts expected by this instruction:
*
* 0. `[writable, signer]` The account to initialize.
* 0. `[writable]` The account to initialize.
* 1. `[]` The mint this account will be associated with.
* 2. `[]` The new account's owner/multisignature.
*/
Expand All @@ -66,9 +74,13 @@ typedef enum Token_TokenInstruction_Tag {
* token instruction that require an owner/delegate to be present. The variant field represents the
* number of signers (M) required to validate this multisignature account.
*
* The `InitializeWrappedAccount` instruction requires no signers and MUST be included within
* the Transaction that creates the uninitialized account with the system program. Otherwise
* another party can acquire ownership of the uninitialized token account.
*
* Accounts expected by this instruction:
*
* 0. `[signer, writable]` The multisignature account to initialize.
* 0. `[writable]` The multisignature account to initialize.
* 1. ..1+N. `[]` The signer accounts, must equal to N where 1 <= N <= 11.
*/
InitializeMultisig,
Expand Down
7 changes: 0 additions & 7 deletions token/js/cli/token-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,6 @@ export async function invalidApprove(): Promise<void> {
}

export async function failOnApproveOverspend(): Promise<void> {
const connection = await getConnection();
const balanceNeeded =
(await Token.getMinBalanceRentForExemptAccount(connection)) * 3;
const owner = new Account();
const account1 = await testToken.createAccount(owner.publicKey);
const account2 = await testToken.createAccount(owner.publicKey);
Expand Down Expand Up @@ -324,10 +321,6 @@ export async function multisig(): Promise<void> {
const m = 2;
const n = 5;

const connection = await getConnection();
const balanceNeeded = await Token.getMinBalanceRentForExemptAccount(
connection,
);
let signerAccounts = [];
for (var i = 0; i < n; i++) {
signerAccounts.push(new Account());
Expand Down
54 changes: 18 additions & 36 deletions token/js/client/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,17 +289,10 @@ export class Token {
space: MintLayout.span,
programId,
});
await sendAndConfirmTransaction(
'createAccount',
connection,
transaction,
payer,
mintAccount,
);

// Create the mint
let keys = [
{pubkey: mintAccount.publicKey, isSigner: true, isWritable: false},
{pubkey: mintAccount.publicKey, isSigner: false, isWritable: true},
];
if (supply.toNumber() != 0) {
keys.push({pubkey: initialAccountPublicKey, isSigner: false, isWritable: true});
Expand All @@ -324,18 +317,19 @@ export class Token {
);
data = data.slice(0, encodeLength);
}

transaction = new Transaction().add({
transaction.add({
keys,
programId,
data,
});

// Send the two instructions
await sendAndConfirmTransaction(
'InitializeMint',
'createAccount and InitializeMint',
connection,
transaction,
payer,
mintAccount,
mintAccount
);

return [token, initialAccountPublicKey];
Expand Down Expand Up @@ -371,21 +365,13 @@ export class Token {
space: AccountLayout.span,
programId: this.programId,
});
await sendAndConfirmTransaction(
'createAccount',
this.connection,
transaction,
this.payer,
mintAccount,
);

// create the new account
const keys = [
{pubkey: mintAccount.publicKey, isSigner: true, isWritable: true},
{pubkey: mintAccount.publicKey, isSigner: false, isWritable: true},
{pubkey: this.publicKey, isSigner: false, isWritable: false},
{pubkey: owner, isSigner: false, isWritable: false},
];

const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction')]);
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
Expand All @@ -394,17 +380,19 @@ export class Token {
},
data,
);
transaction = new Transaction().add({
transaction.add({
keys,
programId: this.programId,
data,
});

// Send the two instructions
await sendAndConfirmTransaction(
'InitializeAccount',
'createAccount and InitializeAccount',
this.connection,
transaction,
this.payer,
mintAccount,
mintAccount
);

return mintAccount.publicKey;
Expand Down Expand Up @@ -436,20 +424,12 @@ export class Token {
space: MultisigLayout.span,
programId: this.programId,
});
await sendAndConfirmTransaction(
'createAccount',
this.connection,
transaction,
this.payer,
multisigAccount,
);

// create the new account
let keys = [
{pubkey: multisigAccount.publicKey, isSigner: true, isWritable: true},
{pubkey: multisigAccount.publicKey, isSigner: false, isWritable: true},
];
signers.forEach(signer => keys.push({pubkey: signer, isSigner: false, isWritable: false}));

const dataLayout = BufferLayout.struct(
[
BufferLayout.u8('instruction'),
Expand All @@ -464,17 +444,19 @@ export class Token {
},
data,
);
transaction = new Transaction().add({
transaction.add({
keys,
programId: this.programId,
data,
});

// Send the two instructions
await sendAndConfirmTransaction(
'InitializeMultisig',
'createAccount and InitializeMultisig',
this.connection,
transaction,
this.payer,
multisigAccount,
multisigAccount
);

return multisigAccount.publicKey;
Expand Down
24 changes: 18 additions & 6 deletions token/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ pub struct TokenInfo {
pub enum TokenInstruction {
/// Initializes a new mint and optionally deposits all the newly minted tokens in an account.
///
/// The `InitializeWrappedAccount` instruction requires no signers and MUST be included within
/// the Transaction that creates the uninitialized account with the system program. Otherwise
/// another party can acquire ownership of the uninitialized token account.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable, signer]` The mint to initialize.
/// 0. `[writable]` The mint to initialize.
/// 1.
/// * If supply is non-zero: `[writable]` The account to hold all the newly minted tokens.
/// * If supply is zero: `[]` The owner/multisignature of the mint.
Expand All @@ -41,9 +45,13 @@ pub enum TokenInstruction {
InitializeMint(TokenInfo),
/// Initializes a new account to hold tokens.
///
/// The `InitializeWrappedAccount` instruction requires no signers and MUST be included within
/// the Transaction that creates the uninitialized account with the system program. Otherwise
/// another party can acquire ownership of the uninitialized token account.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable, signer]` The account to initialize.
/// 0. `[writable]` The account to initialize.
/// 1. `[]` The mint this account will be associated with.
/// 2. `[]` The new account's owner/multisignature.
InitializeAccount,
Expand All @@ -53,9 +61,13 @@ pub enum TokenInstruction {
/// token instruction that require an owner/delegate to be present. The variant field represents the
/// number of signers (M) required to validate this multisignature account.
///
/// The `InitializeWrappedAccount` instruction requires no signers and MUST be included within
/// the Transaction that creates the uninitialized account with the system program. Otherwise
/// another party can acquire ownership of the uninitialized token account.
///
/// Accounts expected by this instruction:
///
/// 0. `[signer, writable]` The multisignature account to initialize.
/// 0. `[writable]` The multisignature account to initialize.
/// 1. ..1+N. `[]` The signer accounts, must equal to N where 1 <= N <= 11.
InitializeMultisig(u8),
/// Transfers tokens from one account to another either directly or via a delegate.
Expand Down Expand Up @@ -254,7 +266,7 @@ pub fn initialize_mint(
) -> Result<Instruction, ProgramError> {
let data = TokenInstruction::InitializeMint(token_info).serialize()?;

let mut accounts = vec![AccountMeta::new(*mint_pubkey, true)];
let mut accounts = vec![AccountMeta::new(*mint_pubkey, false)];
if token_info.supply != 0 {
match account_pubkey {
Some(pubkey) => accounts.push(AccountMeta::new(*pubkey, false)),
Expand Down Expand Up @@ -289,7 +301,7 @@ pub fn initialize_account(
let data = TokenInstruction::InitializeAccount.serialize()?;

let accounts = vec![
AccountMeta::new(*account_pubkey, true),
AccountMeta::new(*account_pubkey, false),
AccountMeta::new_readonly(*mint_pubkey, false),
AccountMeta::new_readonly(*owner_pubkey, false),
];
Expand Down Expand Up @@ -317,7 +329,7 @@ pub fn initialize_multisig(
let data = TokenInstruction::InitializeMultisig(m).serialize()?;

let mut accounts = Vec::with_capacity(1 + signer_pubkeys.len());
accounts.push(AccountMeta::new(*multisig_pubkey, true));
accounts.push(AccountMeta::new(*multisig_pubkey, false));
for signer_pubkey in signer_pubkeys.iter() {
accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
}
Expand Down
20 changes: 0 additions & 20 deletions token/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ impl State {
let account_info_iter = &mut accounts.iter();
let mint_info = next_account_info(account_info_iter)?;

if !mint_info.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}

if State::Unallocated != State::deserialize(&mint_info.data.borrow())? {
return Err(TokenError::AlreadyInUse.into());
}
Expand Down Expand Up @@ -140,10 +136,6 @@ impl State {
let mint_info = next_account_info(account_info_iter)?;
let owner_info = next_account_info(account_info_iter)?;

if !new_account_info.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}

let mut new_account_data = new_account_info.data.borrow_mut();
if State::Unallocated != State::deserialize(&new_account_data)? {
return Err(TokenError::AlreadyInUse.into());
Expand Down Expand Up @@ -713,18 +705,6 @@ mod tests {
let mint_key = pubkey_rand();
let mut mint_account = Account::new(0, size_of::<State>(), &program_id);

// missing signer
let mut instruction =
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap();
instruction.accounts[0].is_signer = false;
assert_eq!(
Err(ProgramError::MissingRequiredSignature),
do_process_instruction(
instruction,
vec![&mut account_account, &mut mint_account, &mut owner_account],
)
);

// create account
do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
Expand Down

0 comments on commit 666b0b7

Please sign in to comment.