Skip to content

Commit

Permalink
cli: Specify programs to embed into local validator genesis via Ancho…
Browse files Browse the repository at this point in the history
…r.toml
  • Loading branch information
armaniferrante committed Feb 22, 2021
1 parent 4bfb4df commit b3803ae
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ incremented for features.
## Features

* ts: Allow preloading instructions for state rpc transactions ([cf9c84](https://github.com/project-serum/anchor/commit/cf9c847e4144989b5bc1936149d171e90204777b)).
* cli: Specify programs to embed into local validator genesis via Anchor.toml while testing.

## Fixes

Expand Down
22 changes: 19 additions & 3 deletions cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;

#[derive(Default)]
#[derive(Debug, Default)]
pub struct Config {
pub cluster: Cluster,
pub wallet: WalletPath,
pub test: Option<Test>,
}

impl Config {
Expand Down Expand Up @@ -61,17 +62,19 @@ impl Config {

// Pubkey serializes as a byte array so use this type a hack to serialize
// into base 58 strings.
#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
struct _Config {
cluster: String,
wallet: String,
test: Option<Test>,
}

impl ToString for Config {
fn to_string(&self) -> String {
let cfg = _Config {
cluster: format!("{}", self.cluster),
wallet: self.wallet.to_string(),
test: self.test.clone(),
};

toml::to_string(&cfg).expect("Must be well formed")
Expand All @@ -84,14 +87,27 @@ impl FromStr for Config {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let cfg: _Config = toml::from_str(s)
.map_err(|e| anyhow::format_err!("Unable to deserialize config: {}", e.to_string()))?;

Ok(Config {
cluster: cfg.cluster.parse()?,
wallet: shellexpand::tilde(&cfg.wallet).parse()?,
test: cfg.test,
})
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Test {
pub genesis: Vec<GenesisEntry>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenesisEntry {
// Base58 pubkey string.
pub address: String,
// Filepath to the compiled program to embed into the genesis.
pub program: String,
}

// TODO: this should read idl dir instead of parsing source.
pub fn read_all_programs() -> Result<Vec<Program>> {
let files = fs::read_dir("programs")?;
Expand Down
11 changes: 9 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ fn test(skip_deploy: bool) -> Result<()> {
build(None)?;
let flags = match skip_deploy {
true => None,
false => Some(genesis_flags()?),
false => Some(genesis_flags(cfg)?),
};
Some(start_test_validator(flags)?)
}
Expand Down Expand Up @@ -635,7 +635,7 @@ fn test(skip_deploy: bool) -> Result<()> {

// Returns the solana-test-validator flags to embed the workspace programs
// in the genesis block. This allows us to run tests without every deploying.
fn genesis_flags() -> Result<Vec<String>> {
fn genesis_flags(cfg: &Config) -> Result<Vec<String>> {
let mut flags = Vec::new();
for mut program in read_all_programs()? {
let binary_path = program.binary_path().display().to_string();
Expand All @@ -656,6 +656,13 @@ fn genesis_flags() -> Result<Vec<String>> {
.with_extension("json");
write_idl(&program.idl, OutFile::File(idl_out))?;
}
if let Some(test) = cfg.test.as_ref() {
for entry in &test.genesis {
flags.push("--bpf-program".to_string());
flags.push(entry.address.clone());
flags.push(entry.program.clone());
}
}
Ok(flags)
}

Expand Down
4 changes: 4 additions & 0 deletions examples/misc/Anchor.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
cluster = "localnet"
wallet = "/home/armaniferrante/.config/solana/id.json"

[[test.genesis]]
address = "FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
program = "./target/deploy/misc.so"
11 changes: 10 additions & 1 deletion examples/misc/tests/misc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const anchor = require('@project-serum/anchor');
const anchor = require("@project-serum/anchor");
const serumCmn = require("@project-serum/common");
const assert = require("assert");

describe("misc", () => {
Expand All @@ -24,4 +25,12 @@ describe("misc", () => {
assert.ok(dataAccount.udata.eq(new anchor.BN(1234)));
assert.ok(dataAccount.idata.eq(new anchor.BN(22)));
});

it("Can embed programs into genesis from the Anchor.toml", async () => {
const pid = new anchor.web3.PublicKey(
"FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
);
let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
assert.ok(accInfo.executable);
});
});

0 comments on commit b3803ae

Please sign in to comment.