This reverts commit 0fdbec9735
.
This commit is contained in:
@ -1516,10 +1516,7 @@ impl ReplayStage {
|
|||||||
root_slot,
|
root_slot,
|
||||||
my_pubkey,
|
my_pubkey,
|
||||||
rpc_subscriptions,
|
rpc_subscriptions,
|
||||||
NewBankOptions {
|
NewBankOptions { vote_only_bank },
|
||||||
vote_only_bank,
|
|
||||||
simulation_bank: false,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let tpu_bank = bank_forks.write().unwrap().insert(tpu_bank);
|
let tpu_bank = bank_forks.write().unwrap().insert(tpu_bank);
|
||||||
|
2868
programs/bpf/Cargo.lock
generated
2868
programs/bpf/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -83,7 +83,6 @@ members = [
|
|||||||
"rust/sha",
|
"rust/sha",
|
||||||
"rust/sibling_inner_instruction",
|
"rust/sibling_inner_instruction",
|
||||||
"rust/sibling_instruction",
|
"rust/sibling_instruction",
|
||||||
"rust/simulation",
|
|
||||||
"rust/spoof1",
|
"rust/spoof1",
|
||||||
"rust/spoof1_system",
|
"rust/spoof1_system",
|
||||||
"rust/sysvar",
|
"rust/sysvar",
|
||||||
|
@ -93,7 +93,6 @@ fn main() {
|
|||||||
"sha",
|
"sha",
|
||||||
"sibling_inner_instruction",
|
"sibling_inner_instruction",
|
||||||
"sibling_instruction",
|
"sibling_instruction",
|
||||||
"simulation",
|
|
||||||
"spoof1",
|
"spoof1",
|
||||||
"spoof1_system",
|
"spoof1_system",
|
||||||
"upgradeable",
|
"upgradeable",
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "solana-bpf-rust-simulation"
|
|
||||||
version = "1.9.9"
|
|
||||||
description = "Solana BPF Program Simulation Differences"
|
|
||||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
|
||||||
repository = "https://github.com/solana-labs/solana"
|
|
||||||
license = "Apache-2.0"
|
|
||||||
homepage = "https://solana.com/"
|
|
||||||
documentation = "https://docs.rs/solana-bpf-rust-simulation"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
test-bpf = []
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
solana-program = { path = "../../../../sdk/program", version = "=1.9.9" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
solana-logger = { path = "../../../../logger", version = "=1.9.9" }
|
|
||||||
solana-program-test = { path = "../../../../program-test", version = "=1.9.9" }
|
|
||||||
solana-sdk = { path = "../../../../sdk", version = "=1.9.9" }
|
|
||||||
solana-validator = { path = "../../../../validator", version = "=1.9.9" }
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["cdylib", "lib"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
|
@ -1,39 +0,0 @@
|
|||||||
use solana_program::{
|
|
||||||
account_info::{next_account_info, AccountInfo},
|
|
||||||
clock::Clock,
|
|
||||||
declare_id, entrypoint,
|
|
||||||
entrypoint::ProgramResult,
|
|
||||||
msg,
|
|
||||||
pubkey::Pubkey,
|
|
||||||
sysvar::Sysvar,
|
|
||||||
};
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
declare_id!("Sim1jD5C35odT8mzctm8BWnjic8xW5xgeb5MbcbErTo");
|
|
||||||
|
|
||||||
entrypoint!(process_instruction);
|
|
||||||
|
|
||||||
pub fn process_instruction(
|
|
||||||
_program_id: &Pubkey,
|
|
||||||
accounts: &[AccountInfo],
|
|
||||||
_instruction_data: &[u8],
|
|
||||||
) -> ProgramResult {
|
|
||||||
let account_info_iter = &mut accounts.iter();
|
|
||||||
let slot_account = next_account_info(account_info_iter)?;
|
|
||||||
|
|
||||||
// Slot is an u64 at the end of the structure
|
|
||||||
let data = slot_account.data.borrow();
|
|
||||||
let slot: u64 = u64::from_le_bytes(data[data.len() - 8..].try_into().unwrap());
|
|
||||||
|
|
||||||
let clock = Clock::get().unwrap();
|
|
||||||
|
|
||||||
msg!("next_slot is {:?} ", slot);
|
|
||||||
msg!("clock is in slot {:?} ", clock.slot);
|
|
||||||
if clock.slot >= slot {
|
|
||||||
msg!("On-chain");
|
|
||||||
} else {
|
|
||||||
panic!("Simulation");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
#![cfg(feature = "test-bpf")]
|
|
||||||
|
|
||||||
use {
|
|
||||||
solana_bpf_rust_simulation::process_instruction,
|
|
||||||
solana_program_test::{processor, tokio, ProgramTest},
|
|
||||||
solana_sdk::{
|
|
||||||
instruction::{AccountMeta, Instruction},
|
|
||||||
pubkey::Pubkey,
|
|
||||||
signature::Signer,
|
|
||||||
sysvar,
|
|
||||||
transaction::Transaction,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn no_panic() {
|
|
||||||
let program_id = Pubkey::new_unique();
|
|
||||||
let program_test = ProgramTest::new(
|
|
||||||
"solana_bpf_rust_simulation",
|
|
||||||
program_id,
|
|
||||||
processor!(process_instruction),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut context = program_test.start_with_context().await;
|
|
||||||
let transaction = Transaction::new_signed_with_payer(
|
|
||||||
&[Instruction {
|
|
||||||
program_id,
|
|
||||||
accounts: vec![AccountMeta::new_readonly(sysvar::slot_history::id(), false)],
|
|
||||||
data: vec![],
|
|
||||||
}],
|
|
||||||
Some(&context.payer.pubkey()),
|
|
||||||
&[&context.payer],
|
|
||||||
context.last_blockhash,
|
|
||||||
);
|
|
||||||
|
|
||||||
context
|
|
||||||
.banks_client
|
|
||||||
.process_transaction_with_preflight(transaction)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
#![cfg(feature = "test-bpf")]
|
|
||||||
|
|
||||||
use {
|
|
||||||
solana_program::{
|
|
||||||
instruction::{AccountMeta, Instruction},
|
|
||||||
pubkey::Pubkey,
|
|
||||||
sysvar,
|
|
||||||
},
|
|
||||||
solana_sdk::{signature::Signer, transaction::Transaction},
|
|
||||||
solana_validator::test_validator::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_panic() {
|
|
||||||
solana_logger::setup_with_default("solana_program_runtime=debug");
|
|
||||||
let program_id = Pubkey::new_unique();
|
|
||||||
|
|
||||||
let (test_validator, payer) = TestValidatorGenesis::default()
|
|
||||||
.add_program("solana_bpf_rust_simulation", program_id)
|
|
||||||
.start();
|
|
||||||
let rpc_client = test_validator.get_rpc_client();
|
|
||||||
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
|
||||||
|
|
||||||
let transaction = Transaction::new_signed_with_payer(
|
|
||||||
&[Instruction {
|
|
||||||
program_id,
|
|
||||||
accounts: vec![AccountMeta::new_readonly(sysvar::slot_history::id(), false)],
|
|
||||||
data: vec![],
|
|
||||||
}],
|
|
||||||
Some(&payer.pubkey()),
|
|
||||||
&[&payer],
|
|
||||||
blockhash,
|
|
||||||
);
|
|
||||||
|
|
||||||
rpc_client
|
|
||||||
.send_and_confirm_transaction(&transaction)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
@ -3468,7 +3468,7 @@ pub mod rpc_full {
|
|||||||
let preflight_commitment = config
|
let preflight_commitment = config
|
||||||
.preflight_commitment
|
.preflight_commitment
|
||||||
.map(|commitment| CommitmentConfig { commitment });
|
.map(|commitment| CommitmentConfig { commitment });
|
||||||
let preflight_bank = meta.bank(preflight_commitment);
|
let preflight_bank = &*meta.bank(preflight_commitment);
|
||||||
let transaction = sanitize_transaction(unsanitized_tx)?;
|
let transaction = sanitize_transaction(unsanitized_tx)?;
|
||||||
let signature = *transaction.signature();
|
let signature = *transaction.signature();
|
||||||
|
|
||||||
@ -3565,7 +3565,7 @@ pub mod rpc_full {
|
|||||||
let (_, mut unsanitized_tx) =
|
let (_, mut unsanitized_tx) =
|
||||||
decode_and_deserialize::<VersionedTransaction>(data, encoding)?;
|
decode_and_deserialize::<VersionedTransaction>(data, encoding)?;
|
||||||
|
|
||||||
let bank = meta.bank(config.commitment);
|
let bank = &*meta.bank(config.commitment);
|
||||||
if config.replace_recent_blockhash {
|
if config.replace_recent_blockhash {
|
||||||
if config.sig_verify {
|
if config.sig_verify {
|
||||||
return Err(Error::invalid_params(
|
return Err(Error::invalid_params(
|
||||||
@ -3636,7 +3636,7 @@ pub mod rpc_full {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(new_response(
|
Ok(new_response(
|
||||||
&bank,
|
bank,
|
||||||
RpcSimulateTransactionResult {
|
RpcSimulateTransactionResult {
|
||||||
err: result.err(),
|
err: result.err(),
|
||||||
logs: Some(logs),
|
logs: Some(logs),
|
||||||
|
@ -198,16 +198,9 @@ impl Accounts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_parent(
|
pub fn new_from_parent(parent: &Accounts, slot: Slot, parent_slot: Slot) -> Self {
|
||||||
parent: &Accounts,
|
|
||||||
slot: Slot,
|
|
||||||
parent_slot: Slot,
|
|
||||||
simulation_bank: bool,
|
|
||||||
) -> Self {
|
|
||||||
let accounts_db = parent.accounts_db.clone();
|
let accounts_db = parent.accounts_db.clone();
|
||||||
if !simulation_bank {
|
accounts_db.set_hash(slot, parent_slot);
|
||||||
accounts_db.set_hash(slot, parent_slot);
|
|
||||||
}
|
|
||||||
Self {
|
Self {
|
||||||
accounts_db,
|
accounts_db,
|
||||||
account_locks: Mutex::new(AccountLocks::default()),
|
account_locks: Mutex::new(AccountLocks::default()),
|
||||||
|
@ -1021,18 +1021,6 @@ pub trait DropCallback: fmt::Debug {
|
|||||||
fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
|
fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Noop callback on dropping banks is useful for simulation banks, which are
|
|
||||||
/// new banks created from a frozen bank, but should not be purged in the same
|
|
||||||
/// way.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct NoopDropCallback;
|
|
||||||
impl DropCallback for NoopDropCallback {
|
|
||||||
fn callback(&self, _b: &Bank) {}
|
|
||||||
fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize, AbiExample, Clone, Copy)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize, AbiExample, Clone, Copy)]
|
||||||
pub struct RewardInfo {
|
pub struct RewardInfo {
|
||||||
pub reward_type: RewardType,
|
pub reward_type: RewardType,
|
||||||
@ -1251,7 +1239,6 @@ struct LoadVoteAndStakeAccountsResult {
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct NewBankOptions {
|
pub struct NewBankOptions {
|
||||||
pub vote_only_bank: bool,
|
pub vote_only_bank: bool,
|
||||||
pub simulation_bank: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bank {
|
impl Bank {
|
||||||
@ -1522,10 +1509,7 @@ impl Bank {
|
|||||||
new_bank_options: NewBankOptions,
|
new_bank_options: NewBankOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut time = Measure::start("bank::new_from_parent");
|
let mut time = Measure::start("bank::new_from_parent");
|
||||||
let NewBankOptions {
|
let NewBankOptions { vote_only_bank } = new_bank_options;
|
||||||
vote_only_bank,
|
|
||||||
simulation_bank,
|
|
||||||
} = new_bank_options;
|
|
||||||
|
|
||||||
parent.freeze();
|
parent.freeze();
|
||||||
assert_ne!(slot, parent.slot());
|
assert_ne!(slot, parent.slot());
|
||||||
@ -1539,7 +1523,6 @@ impl Bank {
|
|||||||
&parent.rc.accounts,
|
&parent.rc.accounts,
|
||||||
slot,
|
slot,
|
||||||
parent.slot(),
|
parent.slot(),
|
||||||
simulation_bank,
|
|
||||||
)),
|
)),
|
||||||
parent: RwLock::new(Some(parent.clone())),
|
parent: RwLock::new(Some(parent.clone())),
|
||||||
slot,
|
slot,
|
||||||
@ -1629,20 +1612,6 @@ impl Bank {
|
|||||||
let (feature_set, feature_set_time) =
|
let (feature_set, feature_set_time) =
|
||||||
Measure::this(|_| parent.feature_set.clone(), (), "feature_set_creation");
|
Measure::this(|_| parent.feature_set.clone(), (), "feature_set_creation");
|
||||||
|
|
||||||
let drop_callback = if simulation_bank {
|
|
||||||
RwLock::new(OptionalDropCallback(Some(Box::new(NoopDropCallback))))
|
|
||||||
} else {
|
|
||||||
RwLock::new(OptionalDropCallback(
|
|
||||||
parent
|
|
||||||
.drop_callback
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.as_ref()
|
|
||||||
.map(|drop_callback| drop_callback.clone_box()),
|
|
||||||
))
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut new = Bank {
|
let mut new = Bank {
|
||||||
rc,
|
rc,
|
||||||
src,
|
src,
|
||||||
@ -1696,7 +1665,15 @@ impl Bank {
|
|||||||
transaction_log_collector_config,
|
transaction_log_collector_config,
|
||||||
transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
|
transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
|
||||||
feature_set,
|
feature_set,
|
||||||
drop_callback,
|
drop_callback: RwLock::new(OptionalDropCallback(
|
||||||
|
parent
|
||||||
|
.drop_callback
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.as_ref()
|
||||||
|
.map(|drop_callback| drop_callback.clone_box()),
|
||||||
|
)),
|
||||||
freeze_started: AtomicBool::new(false),
|
freeze_started: AtomicBool::new(false),
|
||||||
cost_tracker: RwLock::new(CostTracker::default()),
|
cost_tracker: RwLock::new(CostTracker::default()),
|
||||||
sysvar_cache: RwLock::new(SysvarCache::default()),
|
sysvar_cache: RwLock::new(SysvarCache::default()),
|
||||||
@ -3503,26 +3480,12 @@ impl Bank {
|
|||||||
|
|
||||||
/// Run transactions against a frozen bank without committing the results
|
/// Run transactions against a frozen bank without committing the results
|
||||||
pub fn simulate_transaction(
|
pub fn simulate_transaction(
|
||||||
self: &Arc<Bank>,
|
&self,
|
||||||
transaction: SanitizedTransaction,
|
transaction: SanitizedTransaction,
|
||||||
) -> TransactionSimulationResult {
|
) -> TransactionSimulationResult {
|
||||||
assert!(self.is_frozen(), "simulation bank must be frozen");
|
assert!(self.is_frozen(), "simulation bank must be frozen");
|
||||||
|
|
||||||
// Simulation detection countermeasure 1: Create a new child bank for the simulation. This
|
self.simulate_transaction_unchecked(transaction)
|
||||||
// ensures comparing the slot values between the Clock and SlotHistory sysvars does not
|
|
||||||
// reveal that the program is running in simulation.
|
|
||||||
//
|
|
||||||
// Reference: https://opcodes.fr/en/publications/2022-01/detecting-transaction-simulation/
|
|
||||||
let bank = Bank::new_from_parent_with_options(
|
|
||||||
self,
|
|
||||||
&Pubkey::default(),
|
|
||||||
self.slot().saturating_add(1),
|
|
||||||
NewBankOptions {
|
|
||||||
simulation_bank: true,
|
|
||||||
..NewBankOptions::default()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
bank.simulate_transaction_unchecked(transaction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run transactions against a bank without committing the results; does not check if the bank
|
/// Run transactions against a bank without committing the results; does not check if the bank
|
||||||
|
Reference in New Issue
Block a user