Remove initialize signers (#84)

* Remove initialize signers

* update js to do initialize atomically
This commit is contained in:
Jack May 2020-07-07 01:55:49 -07:00 committed by GitHub
parent 271073e67b
commit 666b0b75e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 72 deletions

View File

@ -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.
@ -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.
*/
@ -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,

View File

@ -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);
@ -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());

View File

@ -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});
@ -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];
@ -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(
@ -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;
@ -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'),
@ -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;

View File

@ -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.
@ -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,
@ -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.
@ -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)),
@ -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),
];
@ -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));
}

View File

@ -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());
}
@ -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());
@ -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(),