fix: return correct number of signatures needed to load programs (#12729)

This commit is contained in:
Justin Starry
2020-10-09 08:58:03 +08:00
committed by GitHub
parent 2c5f83c264
commit 6972e63f51
2 changed files with 23 additions and 10 deletions

View File

@ -34,7 +34,12 @@ export class Loader {
* Can be used to calculate transaction fees * Can be used to calculate transaction fees
*/ */
static getMinNumSignatures(dataLength: number): number { static getMinNumSignatures(dataLength: number): number {
return Math.ceil(dataLength / Loader.chunkSize); return (
2 * // Every transaction requires two signatures (payer + program)
(Math.ceil(dataLength / Loader.chunkSize) +
1 + // Add one for Create transaction
1) // Add one for Finalize transaction
);
} }
/** /**

View File

@ -19,8 +19,6 @@ if (!mockRpcEnabled) {
jest.setTimeout(120000); jest.setTimeout(120000);
} }
const NUM_RETRIES = 100; /* allow some number of retries */
test('load BPF C program', async () => { test('load BPF C program', async () => {
if (mockRpcEnabled) { if (mockRpcEnabled) {
console.log('non-live test skipped'); console.log('non-live test skipped');
@ -33,14 +31,23 @@ test('load BPF C program', async () => {
const {feeCalculator} = await connection.getRecentBlockhash(); const {feeCalculator} = await connection.getRecentBlockhash();
const fees = const fees =
feeCalculator.lamportsPerSignature * feeCalculator.lamportsPerSignature *
(BpfLoader.getMinNumSignatures(data.length) + NUM_RETRIES); BpfLoader.getMinNumSignatures(data.length);
const balanceNeeded = await connection.getMinimumBalanceForRentExemption( const payerBalance = await connection.getMinimumBalanceForRentExemption(0);
const executableBalance = await connection.getMinimumBalanceForRentExemption(
data.length, data.length,
); );
const from = await newAccountWithLamports(connection, fees + balanceNeeded); const from = await newAccountWithLamports(
connection,
payerBalance + fees + executableBalance,
);
const program = new Account(); const program = new Account();
await BpfLoader.load(connection, from, program, data, BPF_LOADER_PROGRAM_ID); await BpfLoader.load(connection, from, program, data, BPF_LOADER_PROGRAM_ID);
// Check that program loading costed exactly `fees + executableBalance`
const fromBalance = await connection.getBalance(from.publicKey);
expect(fromBalance).toEqual(payerBalance);
const transaction = new Transaction().add({ const transaction = new Transaction().add({
keys: [{pubkey: from.publicKey, isSigner: true, isWritable: true}], keys: [{pubkey: from.publicKey, isSigner: true, isWritable: true}],
programId: program.publicKey, programId: program.publicKey,
@ -72,18 +79,19 @@ describe('load BPF Rust program', () => {
const {feeCalculator} = await connection.getRecentBlockhash(); const {feeCalculator} = await connection.getRecentBlockhash();
const fees = const fees =
feeCalculator.lamportsPerSignature * feeCalculator.lamportsPerSignature *
(BpfLoader.getMinNumSignatures(programData.length) + NUM_RETRIES); BpfLoader.getMinNumSignatures(programData.length);
const balanceNeeded = await connection.getMinimumBalanceForRentExemption( const payerBalance = await connection.getMinimumBalanceForRentExemption(0);
const executableBalance = await connection.getMinimumBalanceForRentExemption(
programData.length, programData.length,
); );
payerAccount = await newAccountWithLamports( payerAccount = await newAccountWithLamports(
connection, connection,
fees + balanceNeeded, payerBalance + fees + executableBalance,
); );
// Create program account with low balance // Create program account with low balance
program = await newAccountWithLamports(connection, balanceNeeded - 1); program = await newAccountWithLamports(connection, executableBalance - 1);
// First load will fail part way due to lack of funds // First load will fail part way due to lack of funds
const insufficientPayerAccount = await newAccountWithLamports( const insufficientPayerAccount = await newAccountWithLamports(