Skip to content

Commit

Permalink
feat(sdk): use lookup tables for vault_transaction_execute and batch_…
Browse files Browse the repository at this point in the history
…execute_transaction transactions
  • Loading branch information
vovacodes committed Mar 20, 2023
1 parent b91e3a5 commit 3f80faf
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 75 deletions.
48 changes: 30 additions & 18 deletions sdk/multisig/src/instructions/batchExecuteTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Connection, PublicKey } from "@solana/web3.js";
import {
AddressLookupTableAccount,
Connection,
PublicKey,
TransactionInstruction,
} from "@solana/web3.js";
import {
Batch,
createBatchExecuteTransactionInstruction,
Expand All @@ -10,7 +15,7 @@ import {
getTransactionPda,
getVaultPda,
} from "../pda";
import { remainingAccountsForTransactionExecute } from "../utils";
import { accountsForTransactionExecute } from "../utils";

export async function batchExecuteTransaction({
connection,
Expand All @@ -24,7 +29,10 @@ export async function batchExecuteTransaction({
member: PublicKey;
batchIndex: bigint;
transactionIndex: number;
}) {
}): Promise<{
instruction: TransactionInstruction;
lookupTableAccounts: AddressLookupTableAccount[];
}> {
const [proposalPda] = getProposalPda({
multisigPda,
transactionIndex: batchIndex,
Expand All @@ -51,20 +59,24 @@ export async function batchExecuteTransaction({
batchTransactionPda
);

const remainingAccounts = await remainingAccountsForTransactionExecute({
connection,
message: batchTransactionAccount.message,
ephemeralSignerBumps: [...batchTransactionAccount.ephemeralSignerBumps],
vaultPda,
transactionPda: batchPda,
});
const { accountMetas, lookupTableAccounts } =
await accountsForTransactionExecute({
connection,
message: batchTransactionAccount.message,
ephemeralSignerBumps: [...batchTransactionAccount.ephemeralSignerBumps],
vaultPda,
transactionPda: batchPda,
});

return createBatchExecuteTransactionInstruction({
multisig: multisigPda,
member,
proposal: proposalPda,
batch: batchPda,
transaction: batchTransactionPda,
anchorRemainingAccounts: remainingAccounts,
});
return {
instruction: createBatchExecuteTransactionInstruction({
multisig: multisigPda,
member,
proposal: proposalPda,
batch: batchPda,
transaction: batchTransactionPda,
anchorRemainingAccounts: accountMetas,
}),
lookupTableAccounts,
};
}
46 changes: 29 additions & 17 deletions sdk/multisig/src/instructions/vaultTransactionExecute.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { Connection, PublicKey } from "@solana/web3.js";
import {
AddressLookupTableAccount,
Connection,
PublicKey,
TransactionInstruction,
} from "@solana/web3.js";
import { getProposalPda, getTransactionPda, getVaultPda } from "../pda";
import {
createVaultTransactionExecuteInstruction,
VaultTransaction,
} from "../generated";
import { remainingAccountsForTransactionExecute } from "../utils";
import { accountsForTransactionExecute } from "../utils";

export async function vaultTransactionExecute({
connection,
Expand All @@ -16,7 +21,10 @@ export async function vaultTransactionExecute({
multisigPda: PublicKey;
transactionIndex: bigint;
member: PublicKey;
}) {
}): Promise<{
instruction: TransactionInstruction;
lookupTableAccounts: AddressLookupTableAccount[];
}> {
const [proposalPda] = getProposalPda({
multisigPda,
transactionIndex,
Expand All @@ -35,19 +43,23 @@ export async function vaultTransactionExecute({
index: transactionAccount.vaultIndex,
});

const remainingAccounts = await remainingAccountsForTransactionExecute({
connection,
message: transactionAccount.message,
ephemeralSignerBumps: [...transactionAccount.ephemeralSignerBumps],
vaultPda,
transactionPda,
});
const { accountMetas, lookupTableAccounts } =
await accountsForTransactionExecute({
connection,
message: transactionAccount.message,
ephemeralSignerBumps: [...transactionAccount.ephemeralSignerBumps],
vaultPda,
transactionPda,
});

return createVaultTransactionExecuteInstruction({
multisig: multisigPda,
member,
proposal: proposalPda,
transaction: transactionPda,
anchorRemainingAccounts: remainingAccounts,
});
return {
instruction: createVaultTransactionExecuteInstruction({
multisig: multisigPda,
member,
proposal: proposalPda,
transaction: transactionPda,
anchorRemainingAccounts: accountMetas,
}),
lookupTableAccounts,
};
}
21 changes: 11 additions & 10 deletions sdk/multisig/src/transactions/batchExecuteTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,20 @@ export async function batchExecuteTransaction({
batchIndex: bigint;
transactionIndex: number;
}): Promise<VersionedTransaction> {
const { instruction, lookupTableAccounts } =
await instructions.batchExecuteTransaction({
connection,
multisigPda,
member,
batchIndex,
transactionIndex,
});

const message = new TransactionMessage({
payerKey: feePayer,
recentBlockhash: blockhash,
instructions: [
await instructions.batchExecuteTransaction({
connection,
multisigPda,
member,
batchIndex,
transactionIndex,
}),
],
}).compileToV0Message();
instructions: [instruction],
}).compileToV0Message(lookupTableAccounts);

return new VersionedTransaction(message);
}
17 changes: 9 additions & 8 deletions sdk/multisig/src/transactions/vaultTransactionExecute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@ export async function vaultTransactionExecute({
transactionIndex: bigint;
member: PublicKey;
}): Promise<VersionedTransaction> {
const ix = await instructions.vaultTransactionExecute({
connection,
multisigPda,
member,
transactionIndex,
});
const { instruction, lookupTableAccounts } =
await instructions.vaultTransactionExecute({
connection,
multisigPda,
member,
transactionIndex,
});

const message = new TransactionMessage({
payerKey: feePayer,
recentBlockhash: blockhash,
instructions: [ix],
}).compileToV0Message();
instructions: [instruction],
}).compileToV0Message(lookupTableAccounts);

return new VersionedTransaction(message);
}
26 changes: 17 additions & 9 deletions sdk/multisig/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export function transactionMessageToMultisigTransactionMessageBytes({
}

/** Populate remaining accounts required for execution of the transaction. */
export async function remainingAccountsForTransactionExecute({
export async function accountsForTransactionExecute({
connection,
transactionPda,
vaultPda,
Expand All @@ -145,7 +145,12 @@ export async function remainingAccountsForTransactionExecute({
ephemeralSignerBumps: number[];
vaultPda: PublicKey;
transactionPda: PublicKey;
}): Promise<AccountMeta[]> {
}): Promise<{
/** Account metas used in the `message`. */
accountMetas: AccountMeta[];
/** Address lookup table accounts used in the `message`. */
lookupTableAccounts: AddressLookupTableAccount[];
}> {
const ephemeralSignerPdas = ephemeralSignerBumps.map(
(_, additionalSignerIndex) => {
return getEphemeralSignerPda({
Expand All @@ -172,17 +177,17 @@ export async function remainingAccountsForTransactionExecute({
)
);

// Populate remaining accounts required for execution of the transaction.
const remainingAccounts: AccountMeta[] = [];
// Populate account metas required for execution of the transaction.
const accountMetas: AccountMeta[] = [];
// First add the lookup table accounts used by the transaction. They are needed for on-chain validation.
remainingAccounts.push(
accountMetas.push(
...addressLookupTableKeys.map((key) => {
return { pubkey: key, isSigner: false, isWritable: false };
})
);
// Then add static account keys included into the message.
for (const [accountIndex, accountKey] of message.accountKeys.entries()) {
remainingAccounts.push({
accountMetas.push({
pubkey: accountKey,
isWritable: isStaticWritableIndex(message, accountIndex),
// NOTE: vaultPda and ephemeralSignerPdas cannot be marked as signers,
Expand Down Expand Up @@ -210,7 +215,7 @@ export async function remainingAccountsForTransactionExecute({
pubkey,
`Address lookup table account ${lookup.accountKey.toBase58()} does not contain address at index ${accountIndex}`
);
remainingAccounts.push({
accountMetas.push({
pubkey,
isWritable: true,
// Accounts in address lookup tables can not be signers.
Expand All @@ -224,7 +229,7 @@ export async function remainingAccountsForTransactionExecute({
pubkey,
`Address lookup table account ${lookup.accountKey.toBase58()} does not contain address at index ${accountIndex}`
);
remainingAccounts.push({
accountMetas.push({
pubkey,
isWritable: false,
// Accounts in address lookup tables can not be signers.
Expand All @@ -233,5 +238,8 @@ export async function remainingAccountsForTransactionExecute({
}
}

return remainingAccounts;
return {
accountMetas,
lookupTableAccounts: [...addressLookupTableAccounts.values()],
};
}
21 changes: 8 additions & 13 deletions tests/multisig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2264,19 +2264,14 @@ describe("multisig", () => {

// Execute the transactions from the batch sequentially one-by-one.
for (const transactionIndex of range(1, testTransactionMessages.length)) {
signature = await multisig.rpc
.batchExecuteTransaction({
connection,
feePayer: feePayer,
multisigPda,
member: members.executor,
batchIndex,
transactionIndex,
})
.catch((err: any) => {
console.error(err.logs);
throw err;
});
signature = await multisig.rpc.batchExecuteTransaction({
connection,
feePayer: feePayer,
multisigPda,
member: members.executor,
batchIndex,
transactionIndex,
});
await connection.confirmTransaction(signature);
}

Expand Down

0 comments on commit 3f80faf

Please sign in to comment.