Soldev

Deploy a program

Last updated:

Program deployments are done by invoking the BPF Loader program.

This is a special builtin program that allows the program to access additional computational resources like verifying the program that is being deployed.

To deploy a program you use the solana cli:

solana program deploy .

Deployment accounts

When we run this the Solana CLI is going to send a set of transactions. Deployment actually means initializing two accounts:

  1. The Program Account which stores the metadata
  2. The Program Data Account which stores the executable code

The program account comes from target/debug/programName-keypair.json that gets created when you anchor build. It stores metadata about the program, but not the program itself.

The program data account is where your actual .so data lives. Unless you do some low-level stuff this account will be configured for twice the size of the initially uploaded file to give you ample headroom for upgrades.

Once your program is deployed, people actually interact with it through its Program ID. They do not use the program account or program data account directly.

And finally, the Program Authority is the actual account that has permission to administrate the program. This is by default your CLI wallet.

Using a hardware wallet

Typically if we are developing an app that is going to mainnet we are going to want to use a key that is not stored on our physical machine.

By default the Solana CLI uses the keypair stored in ~/.config/solana/id.json.

To use a hardware wallet we can use a specific keypath with the following format:

usb://[/][?key=]

So a full key might look like:

usb://ledger/BsNsvfXqQTtJnagwFWdBS7FBXgnsK8VZ5CmuznN85swK?key=0/0

Here the BsNsvfXqQTtJnagwFWdBS7FBXgnsK8VZ5CmuznN85swK is the wallet ID (NOT the pubkey) and 0/0 is the derivation path.

These keypaths can be used anywhere we have a <KEYPAIR> argument in the Solana CLI.

To see what wallets are available and connected we can run:

solana-keygen pubkey usb://ledger?key=0

This should show the same one that shows up in ledger live as your first account.

For these commands to work your ledger must be plugged in, unlocked, and the Solana program must be opened.

If you're using Linux you might have to enable the udev rules if they are not already enabled.

Using squads multisig

Using a hardware wallet makes it hard to share deployment authority with a team. A better approach is to use a multisig wallet.

A multisig allows control over assets through multiple private keys. It can be thought of as a safe that requires multiple unique keys to open it and move the assets. That means that there is no single point of failure, even if one of the keys is compromised.

A popular solution for multisig in Solana is Squads. Squads are programmable wallets which is just a program on Solana that lets us perform certain actions only after certain conditions are met.

Every action in the Squad triggers a transaction that needs to be approved and executed by the owners of a Squad.

You can find the full instructions for creating a program on Squads here

To actually deploy a program for the first time we just deploy normally, either with the generated key from the Solana CLI or perhaps a hardware wallet. Then we go onto Squads and create a program. Squads will give us an address that we can then set the program authority to.

During an upgrade we no longer have the authority so we have to first write our upgrade to a buffer and then transfer the authority back to Squads.

Then we write the program to a buffer:

solana program write-buffer 

We tell Squads about the details of this buffer and then set the authority over this buffer to Squads.

Finally, through squads we can trigger the upgrade and sign via multisig.

Deployment process

First it allocates a buffer account where it writes the program's ELF file. These can be quite large so it happens over several transactions that chunk it in.

Once this process finishes, a final deploy instruction is given which will verify the ELF stored in the buffer account. Then it moves the ELF into a real program account and marks it as executable.

This verification is handled by:

  1. Loading the program (the .so file), which is parsed as an ELF binary containing extended Berkeley Packet Filter (eBPF) bytecode with a strict runtime environment
  2. Verify the loaded executor (usually rBPF, which is Solana's Rust implementation of an eBPF virtual machine) against the Instruction Set Architecture (ISA), which in this case is the eBPF.
  3. Reload the program with the current runtime environment that the validator is using.

This is all done so we can get a nice executable boolean on programs, discarding the invalid ones, which allows the runtime not to have to recheck whether the program is valid or not.

Upgrade process

Upgrading a program is similar to deploying it. The main difference is that the program account and the program metadata account do not change during an upgrade. Only the program data account's bytecode and slot metadata are updated.

Estimating deployment cost

Start by getting the size of the program:

du -b target/deploy/programName.so

Anchor will size the buffer account to 2n + 45 bytes.

Then we can price the bytes with the latest rent:

solana rent 

Which tells you the amount of SOL needed for the buffer account.

This ignores the fact that transactions have a size limit of 1232 bytes so anything larger than that requires multiple transactions. There will also be another 0.001 SOL for the program data account.