parent
8d9912b4e2
commit
5ca52d785c
18
src/bank.rs
18
src/bank.rs
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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)));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Reference in New Issue