cli: Specify programs to embed into local validator genesis via Anchor.toml

This commit is contained in:
Armani Ferrante 2021-02-23 01:41:40 +08:00
parent 4bfb4df79a
commit b3803aec03
No known key found for this signature in database
GPG Key ID: D597A80BCF8E12B7
5 changed files with 43 additions and 6 deletions

View File

@ -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

View File

@ -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 {
@ -61,10 +62,11 @@ 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 {
@ -72,6 +74,7 @@ impl ToString for Config {
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")
@ -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")?;

View File

@ -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)?)
}
@ -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();
@ -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)
}

View File

@ -1,2 +1,6 @@
cluster = "localnet"
wallet = "/home/armaniferrante/.config/solana/id.json"
[[test.genesis]]
address = "FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
program = "./target/deploy/misc.so"

View File

@ -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", () => {
@ -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);
});
});