Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions build-verified/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ inputs:
description: "Features to enable during build"
required: false
default: ""
base-image:
description: "Override solana-verify's --base-image. Pass the same value
to verify-build to keep the verify-PDA aligned."
required: false
default: ""

runs:
using: "composite"
Expand All @@ -20,10 +25,18 @@ runs:

- name: Build Verified
shell: bash
env:
FEATURES_INPUT: ${{ inputs.features }}
BASE_IMAGE: ${{ inputs.base-image }}
PROGRAM: ${{ inputs.program }}
run: |
FEATURES="${{ inputs.features }}"
if [ ! -z "$FEATURES" ]; then
FEATURES="--features $FEATURES"
FEATURES=""
if [ -n "$FEATURES_INPUT" ]; then
FEATURES="--features $FEATURES_INPUT"
fi
BASE_IMAGE_ARG=""
if [ -n "$BASE_IMAGE" ]; then
BASE_IMAGE_ARG="--base-image $BASE_IMAGE"
fi
# Run solana-verify directly without Docker
~/.cargo/bin/solana-verify build --library-name ${{ inputs.program }} -- $FEATURES
~/.cargo/bin/solana-verify build $BASE_IMAGE_ARG --library-name "$PROGRAM" -- $FEATURES
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ These actions use the [program-metadata](https://github.com/solana-program/progr
- `build-anchor`: Specialized Anchor program builder
- `program-upgrade`: Handles the exteding of the program account in case the program is getting bigger and either sets the buffer or skips that in case of squads deploy
- `idl-upload`: Either sets the Anchor IDL buffer or skips that in case of squads deploy
- `verify-build`: Verifies on-chain programs match source using solana-verify andthe osec api
- `verify-build`: Writes the signer's verify PDA and queues a remote build with `solana-verify remote submit-job` (mainnet only), recording the hash before deploy so the buffer is resolvable via the osec api; with squads also exports the program-authority PDA tx (`pda_tx`) for the multisig

### Squads buffer-only release

Expand Down
115 changes: 91 additions & 24 deletions verify-build/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ inputs:
vault-address:
description: "The Squads vault address (required if use-squads is true)"
required: false
base-image:
description: "Override solana-verify's --base-image. Must match
build-verified to keep the verify-PDA aligned with the built .so."
required: false
default: ""
features:
description: "Comma-separated cargo features. Must match build-verified
to keep the verify-PDA aligned with the built .so."
required: false
default: ""

runs:
using: "composite"
Expand All @@ -54,62 +64,119 @@ runs:

- name: Debug Environment
shell: bash
env:
EVENT_NETWORK: ${{ github.event.inputs.network }}
EVENT_VERIFY: ${{ github.event.inputs.verify }}
HAS_KEYPAIR: ${{ inputs.keypair != '' }}
run: |
echo "Network: ${{ github.event.inputs.network }}"
echo "Verify: ${{ github.event.inputs.verify }}"
echo "Has keypair: ${{ inputs.keypair != '' }}"
echo "Network: $EVENT_NETWORK"
echo "Verify: $EVENT_VERIFY"
echo "Has keypair: $HAS_KEYPAIR"

# Writes the signer's verify PDA and queues a remote build. Runs for both squads and non-squads so the built hash is recorded before deploy and the buffer is resolvable via /resolve-hash
# In the squads flow this is separate from the program authority PDA tx exported below which the multisig executes itself
- name: Verify Build
shell: bash
if: inputs.use-squads == 'false'
env:
SKIP_BUILD: ${{ inputs.skip-build }}
SKIP_PROMPT: ${{ inputs.skip-prompt }}
MOUNT_PATH: ${{ inputs.mount-path }}
COMMIT_HASH: ${{ inputs.commit-hash }}
NETWORK: ${{ inputs.network }}
BASE_IMAGE: ${{ inputs.base-image }}
FEATURES_INPUT: ${{ inputs.features }}
PROGRAM_ID: ${{ inputs.program-id }}
RPC_URL: ${{ inputs.rpc-url }}
PROGRAM: ${{ inputs.program }}
REPO_URL: ${{ inputs.repo-url }}
run: |
ARGS=""

if [ "${{ inputs.skip-build }}" = "true" ]; then
if [ "$SKIP_BUILD" = "true" ]; then
ARGS="$ARGS --skip-build"
fi

if [ "${{ inputs.skip-prompt }}" = "true" ]; then
if [ "$SKIP_PROMPT" = "true" ]; then
ARGS="$ARGS --skip-prompt"
fi

if [ -n "${{ inputs.mount-path }}" ]; then
ARGS="$ARGS --mount-path ${{ inputs.mount-path }}"
if [ -n "$MOUNT_PATH" ]; then
ARGS="$ARGS --mount-path $MOUNT_PATH"
fi

if [ -n "${{ inputs.commit-hash }}" ]; then
ARGS="$ARGS --commit-hash ${{ inputs.commit-hash }}"
if [ -n "$COMMIT_HASH" ]; then
ARGS="$ARGS --commit-hash $COMMIT_HASH"
fi

if [ "${{ inputs.network }}" = "mainnet" ]; then
ARGS="$ARGS --remote"
if [ -n "$BASE_IMAGE" ]; then
ARGS="$ARGS --base-image $BASE_IMAGE"
fi

CARGO_ARGS=""
if [ -n "$FEATURES_INPUT" ]; then
CARGO_ARGS="-- --features $FEATURES_INPUT"
fi

# With --skip-build this only uploads the PDA, the remote worker does the actual build
solana-verify verify-from-repo \
--program-id ${{ inputs.program-id }} \
--url ${{ inputs.rpc-url }} \
--library-name ${{ inputs.program }} \
--program-id "$PROGRAM_ID" \
--url "$RPC_URL" \
--library-name "$PROGRAM" \
-k ./deploy-keypair.json \
$ARGS \
${{ inputs.repo-url }}
"$REPO_URL" \
$CARGO_ARGS

# Queue the remote build. Replaces the deprecated --remote flag and is mainnet only
if [ "$NETWORK" = "mainnet" ]; then
UPLOADER=$(solana-keygen pubkey ./deploy-keypair.json)
echo "Queuing remote verify job for program $PROGRAM_ID (uploader $UPLOADER)"
solana-verify remote submit-job \
--program-id "$PROGRAM_ID" \
--uploader "$UPLOADER" \
--url "$RPC_URL"
else
echo "Network is '$NETWORK', not mainnet; skipping remote submit-job (remote verification is mainnet-only)."
fi

- name: Export PDA Transaction
id: export-pda
if: inputs.use-squads == 'true'
shell: bash
env:
BASE_IMAGE: ${{ inputs.base-image }}
FEATURES_INPUT: ${{ inputs.features }}
REPO_URL: ${{ inputs.repo-url }}
PROGRAM_ID: ${{ inputs.program-id }}
VAULT_ADDRESS: ${{ inputs.vault-address }}
COMMIT_HASH: ${{ inputs.commit-hash }}
RPC_URL: ${{ inputs.rpc-url }}
PROGRAM: ${{ inputs.program }}
run: |
echo "=== Exporting PDA Transaction ==="

BASE_IMAGE_ARG=""
if [ -n "$BASE_IMAGE" ]; then
BASE_IMAGE_ARG="--base-image $BASE_IMAGE"
fi

CARGO_ARGS=""
if [ -n "$FEATURES_INPUT" ]; then
CARGO_ARGS="-- --features $FEATURES_INPUT"
fi

# Get the last line which should be the base64 transaction
TX=$(solana-verify export-pda-tx \
${{ inputs.repo-url }} \
--program-id ${{ inputs.program-id }} \
--uploader ${{ inputs.vault-address }} \
--commit-hash ${{ inputs.commit-hash }} \
--url ${{ inputs.rpc-url }} \
--library-name ${{ inputs.program }} \
--encoding base64 | tail -n 1)

"$REPO_URL" \
--program-id "$PROGRAM_ID" \
--uploader "$VAULT_ADDRESS" \
--commit-hash "$COMMIT_HASH" \
--url "$RPC_URL" \
--library-name "$PROGRAM" \
$BASE_IMAGE_ARG \
--encoding base64 \
$CARGO_ARGS | tail -n 1)

# Verify we got a base64 string
if [[ ! "$TX" =~ ^[A-Za-z0-9+/=]*$ ]]; then
echo "Error: Invalid base64 transaction"
Expand Down
19 changes: 19 additions & 0 deletions write-program-buffer/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,32 @@ runs:
if: steps.check-program.outputs.exists == 'true'
shell: bash
run: |
MIN_EXTEND_SIZE=10240
MAX_PERMITTED_DATA_LENGTH=10485760
PROGRAMDATA_METADATA_SIZE=45
MAX_PROGRAM_SIZE=$((MAX_PERMITTED_DATA_LENGTH - PROGRAMDATA_METADATA_SIZE))

REQUIRED_SIZE=$(wc -c < ./target/deploy/${{ inputs.program }}.so)
CURRENT_SIZE="${{ steps.check-program.outputs.data_len }}"
echo "Required size: $REQUIRED_SIZE"
echo "Current size: $CURRENT_SIZE"

if [ "$REQUIRED_SIZE" -gt "$MAX_PROGRAM_SIZE" ]; then
echo "Error: program size of $REQUIRED_SIZE bytes exceeds the maximum program size of $MAX_PROGRAM_SIZE bytes"
exit 1
fi

if [ "$REQUIRED_SIZE" -gt "$CURRENT_SIZE" ]; then
HEADROOM=$((MAX_PROGRAM_SIZE - CURRENT_SIZE))
if [ "$HEADROOM" -lt "$MIN_EXTEND_SIZE" ]; then
echo "Only $HEADROOM bytes of headroom to the maximum account size, the SIMD-0431 minimum does not apply"
MIN_EXTEND_SIZE=$HEADROOM
fi
EXTEND_SIZE=$((REQUIRED_SIZE - CURRENT_SIZE))
if [ "$EXTEND_SIZE" -lt "$MIN_EXTEND_SIZE" ]; then
echo "Extend size of $EXTEND_SIZE bytes is below the SIMD-0431 minimum, extending by $MIN_EXTEND_SIZE bytes instead"
EXTEND_SIZE=$MIN_EXTEND_SIZE
fi
echo "Program needs to be extended by $EXTEND_SIZE bytes"
solana program extend ${{ inputs.program-id }} $EXTEND_SIZE \
--keypair ./deploy-keypair.json \
Expand Down