Skip to content

Commit c2a4f2c

Browse files
authored
harness: use Message to compile accounts (#189)
1 parent 9999603 commit c2a4f2c

File tree

15 files changed

+209
-797
lines changed

15 files changed

+209
-797
lines changed

Cargo.lock

Lines changed: 2 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ members = [
55
"error",
66
"fuzz/*",
77
"harness",
8-
"keys",
98
"programs/*",
109
"result",
1110
"test-programs/*",
@@ -39,7 +38,6 @@ mollusk-svm-error = { path = "error", version = "0.8.1" }
3938
mollusk-svm-fuzz-fixture = { path = "fuzz/fixture", version = "0.8.1" }
4039
mollusk-svm-fuzz-fixture-firedancer = { path = "fuzz/fixture-fd", version = "0.8.1" }
4140
mollusk-svm-fuzz-fs = { path = "fuzz/fs", version = "0.8.1" }
42-
mollusk-svm-keys = { path = "keys", version = "0.8.1" }
4341
mollusk-svm-programs-memo = { path = "programs/memo", version = "0.8.1" }
4442
mollusk-svm-result = { path = "result", version = "0.8.1" }
4543
mollusk-svm-programs-token = { path = "programs/token", version = "0.8.1" }
@@ -90,6 +88,7 @@ solana-stake-interface = "2.0.1"
9088
solana-svm-callback = "3.1.0"
9189
solana-svm-log-collector = "3.1.0"
9290
solana-svm-timings = "3.1.0"
91+
solana-svm-transaction = "3.0.0"
9392
solana-system-interface = "2.0"
9493
solana-system-program = "3.1.0"
9594
solana-sysvar = "3.0"

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ publish:
4949
@set -e && set -u && set -o pipefail && \
5050
CRATES=( \
5151
"mollusk-svm-error" \
52-
"mollusk-svm-keys" \
5352
"mollusk-svm-fuzz-fs" \
5453
"mollusk-svm-fuzz-fixture" \
5554
"mollusk-svm-fuzz-fixture-firedancer" \

harness/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ fuzz-fd = [
2727
]
2828
inner-instructions = [
2929
"mollusk-svm-result/inner-instructions",
30-
"dep:solana-message",
3130
"dep:solana-transaction-status-client-types",
3231
]
3332
invocation-inspect-callback = []
@@ -53,7 +52,6 @@ mollusk-svm-error = { workspace = true }
5352
mollusk-svm-fuzz-fixture = { workspace = true, optional = true }
5453
mollusk-svm-fuzz-fixture-firedancer = { workspace = true, optional = true }
5554
mollusk-svm-fuzz-fs = { workspace = true, optional = true }
56-
mollusk-svm-keys = { workspace = true }
5755
mollusk-svm-result = { workspace = true }
5856
sha2 = { workspace = true, optional = true }
5957
solana-account = { workspace = true }
@@ -70,7 +68,7 @@ solana-loader-v3-interface = { workspace = true, features = ["serde"] }
7068
solana-loader-v4-interface = { workspace = true }
7169
solana-loader-v4-program = { workspace = true, features = ["agave-unstable-api"], optional = true }
7270
solana-logger = { workspace = true }
73-
solana-message = { workspace = true, optional = true }
71+
solana-message = { workspace = true }
7472
solana-precompile-error = { workspace = true }
7573
solana-program-error = { workspace = true }
7674
solana-program-runtime = { workspace = true }
@@ -82,6 +80,7 @@ solana-stake-interface = { workspace = true }
8280
solana-svm-callback = { workspace = true }
8381
solana-svm-log-collector = { workspace = true }
8482
solana-svm-timings = { workspace = true }
83+
solana-svm-transaction = { workspace = true }
8584
solana-system-program = { workspace = true, features = ["agave-unstable-api"] }
8685
solana-sysvar = { workspace = true }
8786
solana-sysvar-id = { workspace = true }

harness/src/compile_accounts.rs

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,82 @@
22
//! privilege handling, and program account stubbing.
33
44
use {
5-
mollusk_svm_keys::{
6-
accounts::{
7-
compile_instruction_accounts, compile_instruction_without_data,
8-
compile_transaction_accounts,
9-
},
10-
keys::KeyMap,
11-
},
12-
solana_account::{Account, AccountSharedData},
5+
mollusk_svm_error::error::{MolluskError, MolluskPanic},
6+
solana_account::{Account, AccountSharedData, WritableAccount},
137
solana_instruction::Instruction,
8+
solana_message::{LegacyMessage, Message, SanitizedMessage},
149
solana_pubkey::Pubkey,
15-
solana_transaction_context::InstructionAccount,
16-
std::collections::HashMap,
10+
std::collections::{HashMap, HashSet},
1711
};
1812

19-
pub struct CompiledAccounts {
20-
pub program_id_index: u16,
21-
pub instruction_accounts: Vec<InstructionAccount>,
22-
pub transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
23-
}
24-
2513
pub fn compile_accounts<'a>(
2614
instruction: &Instruction,
2715
accounts: impl Iterator<Item = &'a (Pubkey, Account)>,
2816
fallback_accounts: &HashMap<Pubkey, Account>,
29-
) -> CompiledAccounts {
30-
let key_map = KeyMap::compile_from_instruction(instruction);
31-
let compiled_instruction = compile_instruction_without_data(&key_map, instruction);
32-
let instruction_accounts = compile_instruction_accounts(&key_map, &compiled_instruction);
33-
let transaction_accounts = compile_transaction_accounts(&key_map, accounts, fallback_accounts);
34-
35-
CompiledAccounts {
36-
program_id_index: compiled_instruction.program_id_index as u16,
37-
instruction_accounts,
38-
transaction_accounts,
39-
}
17+
) -> (SanitizedMessage, Vec<(Pubkey, AccountSharedData)>) {
18+
let message = Message::new(std::slice::from_ref(instruction), None);
19+
let sanitized_message = SanitizedMessage::Legacy(LegacyMessage::new(message, &HashSet::new()));
20+
21+
let accounts: Vec<_> = accounts.collect();
22+
let transaction_accounts = build_transaction_accounts(
23+
&sanitized_message,
24+
instruction.program_id,
25+
&accounts,
26+
std::slice::from_ref(instruction),
27+
fallback_accounts,
28+
);
29+
30+
(sanitized_message, transaction_accounts)
31+
}
32+
33+
fn build_transaction_accounts(
34+
message: &SanitizedMessage,
35+
program_id: Pubkey,
36+
accounts: &[&(Pubkey, Account)],
37+
all_instructions: &[Instruction],
38+
fallback_accounts: &HashMap<Pubkey, Account>,
39+
) -> Vec<(Pubkey, AccountSharedData)> {
40+
message
41+
.account_keys()
42+
.iter()
43+
.map(|key| {
44+
if *key == program_id {
45+
if let Some(provided_account) = accounts.iter().find(|(k, _)| k == key) {
46+
return (*key, AccountSharedData::from(provided_account.1.clone()));
47+
}
48+
if let Some(fallback) = fallback_accounts.get(key) {
49+
return (*key, AccountSharedData::from(fallback.clone()));
50+
}
51+
// This shouldn't happen if fallbacks are set up correctly.
52+
let mut program_account = Account::default();
53+
program_account.set_executable(true);
54+
return (*key, program_account.into());
55+
}
56+
57+
if *key == solana_instructions_sysvar::ID {
58+
if let Some((_, provided_account)) = accounts.iter().find(|(k, _)| k == key) {
59+
return (*key, AccountSharedData::from(provided_account.clone()));
60+
}
61+
if let Some(fallback) = fallback_accounts.get(key) {
62+
return (*key, AccountSharedData::from(fallback.clone()));
63+
}
64+
let (_, account) =
65+
crate::instructions_sysvar::keyed_account(all_instructions.iter());
66+
return (*key, account.into());
67+
}
68+
69+
let account = accounts
70+
.iter()
71+
.find(|(k, _)| k == key)
72+
.map(|(_, a)| AccountSharedData::from(a.clone()))
73+
.or_else(|| {
74+
fallback_accounts
75+
.get(key)
76+
.map(|a| AccountSharedData::from(a.clone()))
77+
})
78+
.or_panic_with(MolluskError::AccountMissing(key));
79+
80+
(*key, account)
81+
})
82+
.collect()
4083
}

harness/src/fuzz/firedancer.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
//! Only available when the `fuzz-fd` feature is enabled.
66
77
use {
8-
crate::{
9-
compile_accounts::{compile_accounts, CompiledAccounts},
10-
Mollusk, DEFAULT_LOADER_KEY,
11-
},
8+
crate::{compile_accounts::compile_accounts, Mollusk, DEFAULT_LOADER_KEY},
129
agave_feature_set::FeatureSet,
1310
mollusk_svm_fuzz_fixture_firedancer::{
1411
context::{
@@ -24,6 +21,8 @@ use {
2421
solana_compute_budget::compute_budget::ComputeBudget,
2522
solana_instruction::{error::InstructionError, AccountMeta, Instruction},
2623
solana_pubkey::Pubkey,
24+
solana_transaction_context::InstructionAccount,
25+
std::collections::HashMap,
2726
};
2827

2928
static BUILTIN_PROGRAM_IDS: &[Pubkey] = &[
@@ -69,7 +68,7 @@ fn build_fixture_context(
6968
DEFAULT_LOADER_KEY
7069
};
7170

72-
let fallbacks = [(
71+
let fallbacks: HashMap<Pubkey, Account> = [(
7372
instruction.program_id,
7473
Account {
7574
owner: loader_key,
@@ -80,11 +79,22 @@ fn build_fixture_context(
8079
.into_iter()
8180
.collect();
8281

83-
let CompiledAccounts {
84-
instruction_accounts,
85-
transaction_accounts,
86-
..
87-
} = compile_accounts(instruction, accounts.iter(), &fallbacks);
82+
let (sanitized_message, transaction_accounts) =
83+
compile_accounts(instruction, accounts.iter(), &fallbacks);
84+
85+
let compiled_ix = sanitized_message.instructions().first().unwrap();
86+
let instruction_accounts: Vec<InstructionAccount> = compiled_ix
87+
.accounts
88+
.iter()
89+
.map(|&index_in_transaction| {
90+
let index = index_in_transaction as usize;
91+
InstructionAccount::new(
92+
index_in_transaction as u16,
93+
sanitized_message.is_signer(index),
94+
sanitized_message.is_writable(index),
95+
)
96+
})
97+
.collect();
8898

8999
let accounts = transaction_accounts
90100
.into_iter()
@@ -238,6 +248,8 @@ pub(crate) fn parse_fixture_effects(
238248
resulting_accounts,
239249
#[cfg(feature = "inner-instructions")]
240250
inner_instructions: vec![],
251+
#[cfg(feature = "inner-instructions")]
252+
message: None,
241253
}
242254
}
243255

0 commit comments

Comments
 (0)