Preload BPF loader (#1573)

Preload BPF loader
This commit is contained in:
jackcmay 2018-10-23 14:44:41 -07:00 committed by GitHub
parent 8d9912b4e2
commit 5ca52d785c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 11 deletions

View File

@ -5,6 +5,7 @@
use bincode::deserialize;
use bincode::serialize;
use bpf_loader;
use budget_program::BudgetState;
use budget_transaction::BudgetTransaction;
use counter::Counter;
@ -187,6 +188,13 @@ impl Default for Bank {
}
impl Bank {
/// Create an Bank with built-in programs.
pub fn new_with_builtin_programs() -> Self {
let bank = Self::default();
bank.add_builtin_programs();
bank
}
/// Create an Bank using a deposit.
pub fn new_from_deposit(deposit: &Payment) -> Self {
let bank = Self::default();
@ -195,6 +203,7 @@ impl Bank {
let account = accounts.entry(deposit.to).or_insert_with(Account::default);
Self::apply_payment(deposit, account);
}
bank.add_builtin_programs();
bank
}
@ -209,6 +218,15 @@ impl Bank {
bank
}
fn add_builtin_programs(&self) {
// Preload Bpf Loader account
let mut accounts = self.accounts.write().unwrap();
let mut account = accounts
.entry(bpf_loader::id())
.or_insert_with(Account::default);
bpf_loader::populate_account(&mut account);
}
/// Commit funds to the given account
fn apply_payment(payment: &Payment, account: &mut Account) {
trace!("apply payments {}", payment.tokens);

19
src/bpf_loader.rs Normal file
View File

@ -0,0 +1,19 @@
//! BPF loader
use native_loader;
use solana_program_interface::account::Account;
use solana_program_interface::pubkey::Pubkey;
pub const BPF_LOADER_PROGRAM_ID: [u8; 32] = [6u8; 32];
pub const BPF_LOADER_NAME: &str = "bpf_loader";
pub fn id() -> Pubkey {
Pubkey::new(&BPF_LOADER_PROGRAM_ID)
}
pub fn populate_account(account: &mut Account) {
account.tokens = 0;
account.program_id = id();
account.userdata = BPF_LOADER_NAME.as_bytes().to_vec();
account.executable = true;
account.loader_program_id = native_loader::id();
}

View File

@ -585,7 +585,7 @@ impl Fullnode {
ledger_path: &str,
leader_scheduler: &mut LeaderScheduler,
) -> (Bank, u64, u64, Vec<Entry>) {
let bank = Bank::default();
let bank = Bank::new_with_builtin_programs();
let entries = read_ledger(ledger_path, true).expect("opening ledger");
let entries = entries
.map(|e| e.unwrap_or_else(|err| panic!("failed to parse entry. error: {}", err)));

View File

@ -12,6 +12,7 @@ pub mod counter;
pub mod bank;
pub mod banking_stage;
pub mod blob_fetch_stage;
pub mod bpf_loader;
pub mod broadcast_stage;
pub mod budget;
pub mod budget_instruction;

View File

@ -1,3 +1,4 @@
//! Native loader
use bincode::deserialize;
use libc;
#[cfg(unix)]
@ -39,18 +40,18 @@ fn create_path(name: &str) -> PathBuf {
)
}
pub const NATIVE_PROGRAM_ID: [u8; 32] = [2u8; 32];
const NATIVE_LOADER_PROGRAM_ID: [u8; 32] = [2u8; 32];
// All native programs export a symbol named process()
const ENTRYPOINT: &str = "process";
type Entrypoint = unsafe extern "C" fn(keyed_accounts: &mut [KeyedAccount], data: &[u8]) -> bool;
pub fn check_id(program_id: &Pubkey) -> bool {
program_id.as_ref() == NATIVE_PROGRAM_ID
program_id.as_ref() == NATIVE_LOADER_PROGRAM_ID
}
pub fn id() -> Pubkey {
Pubkey::new(&NATIVE_PROGRAM_ID)
Pubkey::new(&NATIVE_LOADER_PROGRAM_ID)
}
pub fn process_transaction(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8]) -> bool {

View File

@ -5,6 +5,8 @@ extern crate solana_program_interface;
use bincode::serialize;
use solana::bank::Bank;
#[cfg(feature = "bpf_c")]
use solana::bpf_loader;
use solana::loader_transaction::LoaderTransaction;
use solana::logger;
use solana::mint::Mint;
@ -60,7 +62,7 @@ impl Loader {
let bank = Bank::new(&mint);
let loader = Keypair::new();
// allocate, populate, finalize, and spawn BPF loader
// allocate, populate, finalize, and spawn loader
let tx = Transaction::system_create(
&mint.keypair(),
@ -104,6 +106,15 @@ impl Loader {
Loader { mint, bank, loader }
}
#[cfg(feature = "bpf_c")]
pub fn new_bpf() -> Self {
let mint = Mint::new(50);
let bank = Bank::new(&mint);
let loader = bpf_loader::id();
Loader { mint, bank, loader }
}
}
struct Program {
@ -114,7 +125,7 @@ impl Program {
pub fn new(loader: &Loader, userdata: Vec<u8>) -> Self {
let program = Keypair::new();
// allocate, populate, and finalize and spawn program
// allocate, populate, finalize and spawn program
let tx = Transaction::system_create(
&loader.mint.keypair(),
@ -131,7 +142,7 @@ impl Program {
loader.bank.process_transactions(&vec![tx.clone()]),
);
let chunk_size = 256; // Size of chunk just needs to fix into tx
let chunk_size = 256; // Size of chunk just needs to fit into tx
let mut offset = 0;
for chunk in userdata.chunks(chunk_size) {
let tx = Transaction::write(
@ -178,7 +189,6 @@ fn test_program_native_noop() {
let program = Program::new(&loader, userdata);
// Call user program
let tx = Transaction::new(
&loader.mint.keypair(),
&[],
@ -260,6 +270,38 @@ fn test_program_lua_move_funds() {
assert_eq!(loader.bank.get_balance(&to), 11);
}
#[cfg(feature = "bpf_c")]
#[test]
fn test_program_builtin_bpf_noop() {
logger::setup();
let loader = Loader::new_bpf();
let program = Program::new(
&loader,
elf::File::open_path(&create_bpf_path("noop_c"))
.unwrap()
.get_section(PLATFORM_SECTION_C)
.unwrap()
.data
.clone(),
);
// Call user program
let tx = Transaction::new(
&loader.mint.keypair(),
&[],
program.program.pubkey(),
vec![1u8],
loader.mint.last_id(),
0,
);
check_tx_results(
&loader.bank,
&tx,
loader.bank.process_transactions(&vec![tx.clone()]),
);
}
#[cfg(feature = "bpf_c")]
#[test]
fn test_program_bpf_noop_c() {
@ -277,7 +319,6 @@ fn test_program_bpf_noop_c() {
);
// Call user program
let tx = Transaction::new(
&loader.mint.keypair(),
&[],
@ -304,7 +345,6 @@ impl TicTacToe {
let game = Keypair::new();
// Create game account
let tx = Transaction::system_create(
&loader.mint.keypair(),
game.pubkey(),
@ -400,7 +440,6 @@ impl Dashboard {
let dashboard = Keypair::new();
// Create game account
let tx = Transaction::system_create(
&loader.mint.keypair(),
dashboard.pubkey(),