Skip to content

Load Surfpool test fixtures with --skip-deploy and allow extra launch arguments - #5221

Open
xternet wants to merge 6 commits into
otter-sec:masterfrom
xternet:feat/surfpool-fixtures-and-arguments
Open

xternet wants to merge 6 commits into
otter-sec:masterfrom
xternet:feat/surfpool-fixtures-and-arguments

Conversation

@xternet

@xternet xternet commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

When using Surfpool, --skip-deploy should skip program deployment, not configured test fixtures.

  • Fixtures: load and verify account/genesis fixtures; reject malformed input and bound zstd decompression.
  • Arguments: add [surfpool].extra_args; reject Anchor-managed flags.
  • Tests/docs: group tests by behavior; update both references and the example.
  • Compatibility: exhaustive SurfpoolConfig literals need extra_args; normal deployment is unchanged.

@vercel

vercel Bot commented Oct 23, 2026

Copy link
Copy Markdown

@xternet is attempting to deploy a commit to the OtterSec Team on Vercel.

A member of the Team first needs to authorize it.

Comment thread CHANGELOG.md Outdated
@@ -1,5 +1,7 @@
# Changelog

- cli: Honor account-file, directory and genesis fixtures on the Surfpool test backend.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be added under Unreleased


```toml
[surfpool]
extra_args = ["--no-studio"]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surfpool rejects any flag if given twice. This example breaks anchor test since Anchor already passes --no-studio on every run.

Comment thread cli/src/lib.rs
flags.push("--no-studio".to_string());
}

if let Some(extra_args) = surfpool_config.as_ref().and_then(|c| c.extra_args.as_ref()) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting extra_args = ["--no-deploy"] without --skip-deploy passes both --no-deploy and --legacy-anchor-compatibility.

Reject --no-deploy, --legacy-anchor-compatibility, and --anchor-test-config-path in extra_args. Update the documentation to clarify that these flags are not allowed because Anchor sets them through --skip-deploy.

block_production_mode = "clock"
```

### `extra_args`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the documentation so that both documentation (v1 & v2) matches.

url = "https://anchor.projectserum.com"
```

### Account and genesis fixtures on Surfpool

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move this section up, before ## toolchain.

let text = parts[0]
.as_str()
.ok_or_else(|| anyhow!("invalid account data"))?;
match parts[1].as_str() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add support for base64+zstd

Comment thread cli/src/surfpool_fixtures/verify.rs Outdated
for (address, image) in images {
let key: Pubkey = address.parse()?;
let actual = client
.get_account_with_commitment(&key, CommitmentConfig::processed())?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use get_multiple_accounts_with_commitment here instead of get_account_with_commitment

Comment thread cli/src/surfpool_fixtures/programs.rs Outdated
let data_state = UpgradeableLoaderState::ProgramData {
slot: 0,
upgrade_authority_address: Some(if program.upgradeable == Some(true) {
cfg.wallet_kp()?.pubkey()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are reading cfg.wallet_kp()?.pubkey() once per genesis entry. Read it once before the loop and reuse it.

Comment thread cli/src/surfpool_fixtures/verify.rs Outdated
if flags.first().map(String::as_str) != Some("--snapshot") {
return Ok(());
}
{

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The bare { … } block here doesn’t seem to do anything here. Could you remove the braces and format the code.

Comment thread cli/src/surfpool_fixtures/programs.rs Outdated
if !elf.starts_with(b"\x7fELF") {
bail!("Genesis program {} is not an ELF file", path.display());
}
{

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The bare { … } block here doesn’t seem to do anything here. Could you remove the braces and format the code.

@swaroop-osec

swaroop-osec commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Another thing I noticed is the same fixture files are parsed three different ways.

  • account_dir_pubkeys -> JSON file with no pubkey is silently skipped (continue).
  • validator_supplied_account_pubkeys -> Has a new "-" handling
  • load -> File with no pubkey is an error

It would be better to extract the logic into a helper function and reuse it across all three places.

@swaroop-osec

Copy link
Copy Markdown
Collaborator

Please don't use LLMs to write PR descriptions or documentation without reviewing the generated content first. Refer to the PR guidelines for more details.

Share fixture parsing, bound compressed data decoding, and batch account verification. Reject managed launch arguments, reuse the genesis authority, and correct the fixture documentation and examples.
@xternet

xternet commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Fixed in cfa76dd:

✅ Shared fixture parsing and base64+zstd support.
✅ Batched reads and one-time wallet-key reading.
✅ Rejected conflicting deployment flags.
✅ Fixed both docs, example and changelog.
✅ Removed redundant blocks.

Local checks pass: 171 tests in each Solana configuration, 4 integration cases, build, formatting and Clippy.

Also carried into #5222 and tested.

@swaroop-osec

Copy link
Copy Markdown
Collaborator

@xternet docs-v2 formatting was changed completely.

@xternet

xternet commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

You’re right, the rewrite was unnecessary. Restored docs-v2’s formatting in ca72d49 and carried it into #5222. Local checks pass.

@jamie-osec

Copy link
Copy Markdown
Collaborator

Can we isolate all tests into a tests/ directory or something? It seems like this PR is mostly tests and it makes it hard to judge complexity currently.
Also, I see one file is named review_tests.rs - if these are tests for issues raised in this PR review, this naming is nonsensical for commited code. Please reorganise into a coherent structure

@xternet

xternet commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Done. Tests are now grouped by behavior in tests/ modules, with review-specific file and test names removed.


fn image(owner: String, data: &[u8], executable: bool) -> Value {
json!({"owner":owner,"data":STANDARD.encode(data),"lamports":rent_exempt_minimum(data.len() as u64),
"executable":executable,"rentEpoch":RENT_EPOCH_NEVER,"parsedData":null})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here assigns RENT_EPOCH_NEVER to both program and program-data accounts; whereas verify does not compare rentEpoch, so the mismatch passes verification.

Comment thread cli/src/lib.rs
}

if let Some(extra_args) = surfpool_config.as_ref().and_then(|c| c.extra_args.as_ref()) {
flags.extend(extra_args.iter().cloned());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setting extra_args = ["--no-studio"] cause duplicate args in extra_args; but it shouldnt allow duplicate runtime flags --no-studio or --port right? causing surfpool startup failures

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants