From da801b753bf3537c866b0a27184b7f81b51e92a7 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 21:45:30 +0000 Subject: [PATCH] Speed up program deploys by writing larger chunks (backport #19654) (#19680) * Speed up program deploys by writing larger chunks (#19654) (cherry picked from commit 24fd47a32d5d65bed361bdaab8cafb3387ba84a6) # Conflicts: # cli/src/program.rs * resolve conflict Co-authored-by: Justin Starry --- cli/src/program.rs | 71 ++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/cli/src/program.rs b/cli/src/program.rs index 2eac679314..3cc121ace4 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -39,8 +39,9 @@ use solana_sdk::{ loader_instruction, message::Message, native_token::Sol, + packet::PACKET_DATA_SIZE, pubkey::Pubkey, - signature::{keypair_from_seed, read_keypair_file, Keypair, Signer}, + signature::{keypair_from_seed, read_keypair_file, Keypair, Signature, Signer}, signers::Signers, system_instruction::{self, SystemError}, system_program, @@ -61,8 +62,6 @@ use std::{ time::Duration, }; -const DATA_CHUNK_SIZE: usize = 229; // Keep program chunks under PACKET_DATA_SIZE - #[derive(Debug, PartialEq)] pub enum ProgramCliCommand { Deploy { @@ -1681,6 +1680,23 @@ pub fn process_deploy( result } +fn calculate_max_chunk_size(create_msg: &F) -> usize +where + F: Fn(u32, Vec) -> Message, +{ + let baseline_msg = create_msg(0, Vec::new()); + let tx_size = bincode::serialized_size(&Transaction { + signatures: vec![ + Signature::default(); + baseline_msg.header.num_required_signatures as usize + ], + message: baseline_msg, + }) + .unwrap() as usize; + // add 1 byte buffer to account for shortvec encoding + PACKET_DATA_SIZE.saturating_sub(tx_size).saturating_sub(1) +} + #[allow(clippy::too_many_arguments)] fn do_process_program_write_and_deploy( rpc_client: Arc, @@ -1753,25 +1769,25 @@ fn do_process_program_write_and_deploy( // Create and add write messages - let mut write_messages = vec![]; - for (chunk, i) in program_data.chunks(DATA_CHUNK_SIZE).zip(0..) { + let payer_pubkey = config.signers[0].pubkey(); + let create_msg = |offset: u32, bytes: Vec| { let instruction = if loader_id == &bpf_loader_upgradeable::id() { bpf_loader_upgradeable::write( buffer_pubkey, &buffer_authority_signer.pubkey(), - (i * DATA_CHUNK_SIZE) as u32, - chunk.to_vec(), + offset, + bytes, ) } else { - loader_instruction::write( - buffer_pubkey, - loader_id, - (i * DATA_CHUNK_SIZE) as u32, - chunk.to_vec(), - ) + loader_instruction::write(buffer_pubkey, loader_id, offset, bytes) }; - let message = Message::new(&[instruction], Some(&config.signers[0].pubkey())); - write_messages.push(message); + Message::new(&[instruction], Some(&payer_pubkey)) + }; + + let mut write_messages = vec![]; + let chunk_size = calculate_max_chunk_size(&create_msg); + for (chunk, i) in program_data.chunks(chunk_size).zip(0..) { + write_messages.push(create_msg((i * chunk_size) as u32, chunk.to_vec())); } (initial_message, Some(write_messages), balance_needed) @@ -1903,17 +1919,24 @@ fn do_process_program_upgrade( None }; + let buffer_signer_pubkey = buffer_signer.pubkey(); + let upgrade_authority_pubkey = upgrade_authority.pubkey(); + let payer_pubkey = config.signers[0].pubkey(); + let create_msg = |offset: u32, bytes: Vec| { + let instruction = bpf_loader_upgradeable::write( + &buffer_signer_pubkey, + &upgrade_authority_pubkey, + offset, + bytes, + ); + Message::new(&[instruction], Some(&payer_pubkey)) + }; + // Create and add write messages let mut write_messages = vec![]; - for (chunk, i) in program_data.chunks(DATA_CHUNK_SIZE).zip(0..) { - let instruction = bpf_loader_upgradeable::write( - &buffer_signer.pubkey(), - &upgrade_authority.pubkey(), - (i * DATA_CHUNK_SIZE) as u32, - chunk.to_vec(), - ); - let message = Message::new(&[instruction], Some(&config.signers[0].pubkey())); - write_messages.push(message); + let chunk_size = calculate_max_chunk_size(&create_msg); + for (chunk, i) in program_data.chunks(chunk_size).zip(0..) { + write_messages.push(create_msg((i * chunk_size) as u32, chunk.to_vec())); } (initial_message, Some(write_messages), balance_needed)