s/contract/program

This commit is contained in:
Anatoly Yakovenko 2018-09-19 17:25:57 -07:00 committed by Michael Vines
parent 6073cd57fa
commit 9bfead2e01
7 changed files with 147 additions and 148 deletions

View File

@ -5,7 +5,7 @@
use bincode::deserialize; use bincode::deserialize;
use bincode::serialize; use bincode::serialize;
use budget_contract::BudgetContract; use budget_program::BudgetProgram;
use counter::Counter; use counter::Counter;
use entry::Entry; use entry::Entry;
use hash::{hash, Hash}; use hash::{hash, Hash};
@ -21,7 +21,7 @@ use std::result;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::RwLock; use std::sync::RwLock;
use std::time::Instant; use std::time::Instant;
use system_contract::SystemContract; use system_program::SystemProgram;
use timing::{duration_as_us, timestamp}; use timing::{duration_as_us, timestamp};
use transaction::Transaction; use transaction::Transaction;
use window::WINDOW_SIZE; use window::WINDOW_SIZE;
@ -35,14 +35,14 @@ pub struct Account {
/// A transaction can write to its userdata /// A transaction can write to its userdata
pub userdata: Vec<u8>, pub userdata: Vec<u8>,
/// contract id this contract belongs to /// contract id this contract belongs to
pub contract_id: Pubkey, pub program_id: Pubkey,
} }
impl Account { impl Account {
pub fn new(tokens: i64, space: usize, contract_id: Pubkey) -> Account { pub fn new(tokens: i64, space: usize, program_id: Pubkey) -> Account {
Account { Account {
tokens, tokens,
userdata: vec![0u8; space], userdata: vec![0u8; space],
contract_id, program_id,
} }
} }
} }
@ -52,7 +52,7 @@ impl Default for Account {
Account { Account {
tokens: 0, tokens: 0,
userdata: vec![], userdata: vec![],
contract_id: SystemContract::id(), program_id: SystemProgram::id(),
} }
} }
} }
@ -284,7 +284,7 @@ impl Bank {
} else { } else {
error_counters.account_not_found_leader += 1; error_counters.account_not_found_leader += 1;
} }
if BudgetContract::check_id(&tx.contract_id) { if BudgetProgram::check_id(&tx.program_id) {
use instruction::Instruction; use instruction::Instruction;
if let Some(Instruction::NewVote(_vote)) = tx.instruction() { if let Some(Instruction::NewVote(_vote)) = tx.instruction() {
error_counters.account_not_found_vote += 1; error_counters.account_not_found_vote += 1;
@ -318,21 +318,21 @@ impl Bank {
} }
pub fn verify_transaction( pub fn verify_transaction(
tx: &Transaction, tx: &Transaction,
pre_contract_id: &Pubkey, pre_program_id: &Pubkey,
pre_tokens: i64, pre_tokens: i64,
account: &Account, account: &Account,
) -> Result<()> { ) -> Result<()> {
// Verify the transaction // Verify the transaction
// make sure that contract_id is still the same or this was just assigned by the system call contract // make sure that program_id is still the same or this was just assigned by the system call contract
if !((*pre_contract_id == account.contract_id) if !((*pre_program_id == account.program_id)
|| (SystemContract::check_id(&tx.contract_id) || (SystemProgram::check_id(&tx.program_id)
&& SystemContract::check_id(&pre_contract_id))) && SystemProgram::check_id(&pre_program_id)))
{ {
//TODO, this maybe redundant bpf should be able to guarantee this property //TODO, this maybe redundant bpf should be able to guarantee this property
return Err(BankError::ModifiedContractId(tx.signature)); return Err(BankError::ModifiedContractId(tx.signature));
} }
// For accounts unassigned to the contract, the individual balance of each accounts cannot decrease. // For accounts unassigned to the contract, the individual balance of each accounts cannot decrease.
if tx.contract_id != account.contract_id && pre_tokens > account.tokens { if tx.program_id != account.program_id && pre_tokens > account.tokens {
return Err(BankError::ExternalAccountTokenSpend(tx.signature)); return Err(BankError::ExternalAccountTokenSpend(tx.signature));
} }
if account.tokens < 0 { if account.tokens < 0 {
@ -348,23 +348,23 @@ impl Bank {
let pre_total: i64 = accounts.iter().map(|a| a.tokens).sum(); let pre_total: i64 = accounts.iter().map(|a| a.tokens).sum();
let pre_data: Vec<_> = accounts let pre_data: Vec<_> = accounts
.iter_mut() .iter_mut()
.map(|a| (a.contract_id, a.tokens)) .map(|a| (a.program_id, a.tokens))
.collect(); .collect();
// Call the contract method // Call the contract method
// It's up to the contract to implement its own rules on moving funds // It's up to the contract to implement its own rules on moving funds
if SystemContract::check_id(&tx.contract_id) { if SystemProgram::check_id(&tx.program_id) {
SystemContract::process_transaction(&tx, accounts) SystemProgram::process_transaction(&tx, accounts)
} else if BudgetContract::check_id(&tx.contract_id) { } else if BudgetProgram::check_id(&tx.program_id) {
// TODO: the runtime should be checking read/write access to memory // TODO: the runtime should be checking read/write access to memory
// we are trusting the hard coded contracts not to clobber or allocate // we are trusting the hard coded contracts not to clobber or allocate
BudgetContract::process_transaction(&tx, accounts) BudgetProgram::process_transaction(&tx, accounts)
} else { } else {
return Err(BankError::UnknownContractId(tx.contract_id)); return Err(BankError::UnknownContractId(tx.program_id));
} }
// Verify the transaction // Verify the transaction
for ((pre_contract_id, pre_tokens), post_account) in pre_data.iter().zip(accounts.iter()) { for ((pre_program_id, pre_tokens), post_account) in pre_data.iter().zip(accounts.iter()) {
Self::verify_transaction(&tx, pre_contract_id, *pre_tokens, post_account)?; Self::verify_transaction(&tx, pre_program_id, *pre_tokens, post_account)?;
} }
// The total sum of all the tokens in all the pages cannot change. // The total sum of all the tokens in all the pages cannot change.
let post_total: i64 = accounts.iter().map(|a| a.tokens).sum(); let post_total: i64 = accounts.iter().map(|a| a.tokens).sum();
@ -560,9 +560,9 @@ impl Bank {
.expect("invalid ledger: need at least 2 entries"); .expect("invalid ledger: need at least 2 entries");
{ {
let tx = &entry1.transactions[0]; let tx = &entry1.transactions[0];
assert!(SystemContract::check_id(&tx.contract_id), "Invalid ledger"); assert!(SystemProgram::check_id(&tx.program_id), "Invalid ledger");
let instruction: SystemContract = deserialize(&tx.userdata).unwrap(); let instruction: SystemProgram = deserialize(&tx.userdata).unwrap();
let deposit = if let SystemContract::Move { tokens } = instruction { let deposit = if let SystemProgram::Move { tokens } = instruction {
Some(tokens) Some(tokens)
} else { } else {
None None
@ -607,10 +607,10 @@ impl Bank {
} }
pub fn read_balance(account: &Account) -> i64 { pub fn read_balance(account: &Account) -> i64 {
if SystemContract::check_id(&account.contract_id) { if SystemProgram::check_id(&account.program_id) {
SystemContract::get_balance(account) SystemProgram::get_balance(account)
} else if BudgetContract::check_id(&account.contract_id) { } else if BudgetProgram::check_id(&account.program_id) {
BudgetContract::get_balance(account) BudgetProgram::get_balance(account)
} else { } else {
account.tokens account.tokens
} }

View File

@ -1,4 +1,4 @@
//! budget contract //! budget program
use bank::Account; use bank::Account;
use bincode::{self, deserialize, serialize_into, serialized_size}; use bincode::{self, deserialize, serialize_into, serialized_size};
use budget::Budget; use budget::Budget;
@ -23,24 +23,24 @@ pub enum BudgetError {
} }
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
pub struct BudgetContract { pub struct BudgetProgram {
pub initialized: bool, pub initialized: bool,
pub pending_budget: Option<Budget>, pub pending_budget: Option<Budget>,
pub last_error: Option<BudgetError>, pub last_error: Option<BudgetError>,
} }
pub const BUDGET_CONTRACT_ID: [u8; 32] = [ pub const BUDGET_PROGRAM_ID: [u8; 32] = [
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
impl BudgetContract { impl BudgetProgram {
fn is_pending(&self) -> bool { fn is_pending(&self) -> bool {
self.pending_budget != None self.pending_budget != None
} }
pub fn id() -> Pubkey { pub fn id() -> Pubkey {
Pubkey::new(&BUDGET_CONTRACT_ID) Pubkey::new(&BUDGET_PROGRAM_ID)
} }
pub fn check_id(contract_id: &Pubkey) -> bool { pub fn check_id(program_id: &Pubkey) -> bool {
contract_id.as_ref() == BUDGET_CONTRACT_ID program_id.as_ref() == BUDGET_PROGRAM_ID
} }
/// Process a Witness Signature. Any payment plans waiting on this signature /// Process a Witness Signature. Any payment plans waiting on this signature
@ -145,7 +145,7 @@ impl BudgetContract {
trace!("contract already exists"); trace!("contract already exists");
Err(BudgetError::ContractAlreadyExists(tx.keys[1])) Err(BudgetError::ContractAlreadyExists(tx.keys[1]))
} else { } else {
let mut state = BudgetContract::default(); let mut state = BudgetProgram::default();
state.pending_budget = Some(budget); state.pending_budget = Some(budget);
accounts[1].tokens += contract.tokens; accounts[1].tokens += contract.tokens;
state.initialized = true; state.initialized = true;
@ -231,7 +231,7 @@ impl BudgetContract {
} }
fn save_error_to_budget_state(e: BudgetError, accounts: &mut [Account]) -> () { fn save_error_to_budget_state(e: BudgetError, accounts: &mut [Account]) -> () {
if let Ok(mut state) = BudgetContract::deserialize(&accounts[1].userdata) { if let Ok(mut state) = BudgetProgram::deserialize(&accounts[1].userdata) {
trace!("saved error {:?}", e); trace!("saved error {:?}", e);
state.last_error = Some(e); state.last_error = Some(e);
state.serialize(&mut accounts[1].userdata).unwrap(); state.serialize(&mut accounts[1].userdata).unwrap();
@ -262,7 +262,7 @@ impl BudgetContract {
//TODO the contract needs to provide a "get_balance" introspection call of the userdata //TODO the contract needs to provide a "get_balance" introspection call of the userdata
pub fn get_balance(account: &Account) -> i64 { pub fn get_balance(account: &Account) -> i64 {
if let Ok(state) = deserialize(&account.userdata) { if let Ok(state) = deserialize(&account.userdata) {
let state: BudgetContract = state; let state: BudgetProgram = state;
if state.is_pending() { if state.is_pending() {
0 0
} else { } else {
@ -277,19 +277,19 @@ impl BudgetContract {
mod test { mod test {
use bank::Account; use bank::Account;
use bincode::serialize; use bincode::serialize;
use budget_contract::{BudgetContract, BudgetError}; use budget_program::{BudgetError, BudgetProgram};
use chrono::prelude::{DateTime, NaiveDate, Utc}; use chrono::prelude::{DateTime, NaiveDate, Utc};
use hash::Hash; use hash::Hash;
use signature::{GenKeys, Keypair, KeypairUtil, Pubkey}; use signature::{GenKeys, Keypair, KeypairUtil, Pubkey};
use transaction::Transaction; use transaction::Transaction;
#[test] #[test]
fn test_serializer() { fn test_serializer() {
let mut a = Account::new(0, 512, BudgetContract::id()); let mut a = Account::new(0, 512, BudgetProgram::id());
let b = BudgetContract::default(); let b = BudgetProgram::default();
b.serialize(&mut a.userdata).unwrap(); b.serialize(&mut a.userdata).unwrap();
let buf = serialize(&b).unwrap(); let buf = serialize(&b).unwrap();
assert_eq!(a.userdata[8..8 + buf.len()], buf[0..]); assert_eq!(a.userdata[8..8 + buf.len()], buf[0..]);
let c = BudgetContract::deserialize(&a.userdata).unwrap(); let c = BudgetProgram::deserialize(&a.userdata).unwrap();
assert_eq!(b, c); assert_eq!(b, c);
} }
@ -327,9 +327,9 @@ mod test {
#[test] #[test]
fn test_transfer_on_date() { fn test_transfer_on_date() {
let mut accounts = vec![ let mut accounts = vec![
Account::new(1, 0, BudgetContract::id()), Account::new(1, 0, BudgetProgram::id()),
Account::new(0, 512, BudgetContract::id()), Account::new(0, 512, BudgetProgram::id()),
Account::new(0, 0, BudgetContract::id()), Account::new(0, 0, BudgetProgram::id()),
]; ];
let from_account = 0; let from_account = 0;
let contract_account = 1; let contract_account = 1;
@ -347,10 +347,10 @@ mod test {
1, 1,
Hash::default(), Hash::default(),
); );
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 1); assert_eq!(accounts[contract_account].tokens, 1);
let state = BudgetContract::deserialize(&accounts[contract_account].userdata).unwrap(); let state = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
assert_eq!(state.last_error, None); assert_eq!(state.last_error, None);
assert!(state.is_pending()); assert!(state.is_pending());
@ -362,12 +362,12 @@ mod test {
dt, dt,
Hash::default(), Hash::default(),
); );
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 1); assert_eq!(accounts[contract_account].tokens, 1);
assert_eq!(accounts[to_account].tokens, 0); assert_eq!(accounts[to_account].tokens, 0);
let state = BudgetContract::deserialize(&accounts[contract_account].userdata).unwrap(); let state = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
assert_eq!( assert_eq!(
state.last_error, state.last_error,
Some(BudgetError::DestinationMissing(to.pubkey())) Some(BudgetError::DestinationMissing(to.pubkey()))
@ -383,20 +383,20 @@ mod test {
dt, dt,
Hash::default(), Hash::default(),
); );
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 0); assert_eq!(accounts[contract_account].tokens, 0);
assert_eq!(accounts[to_account].tokens, 1); assert_eq!(accounts[to_account].tokens, 1);
let state = BudgetContract::deserialize(&accounts[contract_account].userdata).unwrap(); let state = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
assert!(!state.is_pending()); assert!(!state.is_pending());
// try to replay the timestamp contract // try to replay the timestamp contract
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 0); assert_eq!(accounts[contract_account].tokens, 0);
assert_eq!(accounts[to_account].tokens, 1); assert_eq!(accounts[to_account].tokens, 1);
let state = BudgetContract::deserialize(&accounts[contract_account].userdata).unwrap(); let state = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
assert_eq!( assert_eq!(
state.last_error, state.last_error,
Some(BudgetError::ContractNotPending(contract.pubkey())) Some(BudgetError::ContractNotPending(contract.pubkey()))
@ -405,9 +405,9 @@ mod test {
#[test] #[test]
fn test_cancel_transfer() { fn test_cancel_transfer() {
let mut accounts = vec![ let mut accounts = vec![
Account::new(1, 0, BudgetContract::id()), Account::new(1, 0, BudgetProgram::id()),
Account::new(0, 512, BudgetContract::id()), Account::new(0, 512, BudgetProgram::id()),
Account::new(0, 0, BudgetContract::id()), Account::new(0, 0, BudgetProgram::id()),
]; ];
let from_account = 0; let from_account = 0;
let contract_account = 1; let contract_account = 1;
@ -424,10 +424,10 @@ mod test {
1, 1,
Hash::default(), Hash::default(),
); );
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 1); assert_eq!(accounts[contract_account].tokens, 1);
let state = BudgetContract::deserialize(&accounts[contract_account].userdata).unwrap(); let state = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
assert_eq!(state.last_error, None); assert_eq!(state.last_error, None);
assert!(state.is_pending()); assert!(state.is_pending());
@ -436,7 +436,7 @@ mod test {
Transaction::budget_new_signature(&to, contract.pubkey(), to.pubkey(), Hash::default()); Transaction::budget_new_signature(&to, contract.pubkey(), to.pubkey(), Hash::default());
// unit test hack, the `from account` is passed instead of the `to` account to avoid // unit test hack, the `from account` is passed instead of the `to` account to avoid
// creating more account vectors // creating more account vectors
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
// nothing should be changed because apply witness didn't finalize a payment // nothing should be changed because apply witness didn't finalize a payment
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 1); assert_eq!(accounts[contract_account].tokens, 1);
@ -450,7 +450,7 @@ mod test {
from.pubkey(), from.pubkey(),
Hash::default(), Hash::default(),
); );
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 0); assert_eq!(accounts[contract_account].tokens, 0);
assert_eq!(accounts[pay_account].tokens, 1); assert_eq!(accounts[pay_account].tokens, 1);
@ -462,12 +462,12 @@ mod test {
from.pubkey(), from.pubkey(),
Hash::default(), Hash::default(),
); );
BudgetContract::process_transaction(&tx, &mut accounts); BudgetProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[from_account].tokens, 0); assert_eq!(accounts[from_account].tokens, 0);
assert_eq!(accounts[contract_account].tokens, 0); assert_eq!(accounts[contract_account].tokens, 0);
assert_eq!(accounts[pay_account].tokens, 1); assert_eq!(accounts[pay_account].tokens, 1);
let state = BudgetContract::deserialize(&accounts[contract_account].userdata).unwrap(); let state = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
assert_eq!( assert_eq!(
state.last_error, state.last_error,
Some(BudgetError::ContractNotPending(contract.pubkey())) Some(BudgetError::ContractNotPending(contract.pubkey()))

View File

@ -19,7 +19,7 @@ pub mod client;
pub mod instruction; pub mod instruction;
#[macro_use] #[macro_use]
pub mod crdt; pub mod crdt;
pub mod budget_contract; pub mod budget_program;
pub mod drone; pub mod drone;
pub mod entry; pub mod entry;
pub mod entry_writer; pub mod entry_writer;
@ -55,7 +55,7 @@ pub mod signature;
pub mod sigverify; pub mod sigverify;
pub mod sigverify_stage; pub mod sigverify_stage;
pub mod streamer; pub mod streamer;
pub mod system_contract; pub mod system_program;
pub mod thin_client; pub mod thin_client;
pub mod timing; pub mod timing;
pub mod tpu; pub mod tpu;

View File

@ -68,15 +68,15 @@ mod tests {
use super::*; use super::*;
use bincode::deserialize; use bincode::deserialize;
use ledger::Block; use ledger::Block;
use system_contract::SystemContract; use system_program::SystemProgram;
#[test] #[test]
fn test_create_transactions() { fn test_create_transactions() {
let mut transactions = Mint::new(100).create_transactions().into_iter(); let mut transactions = Mint::new(100).create_transactions().into_iter();
let tx = transactions.next().unwrap(); let tx = transactions.next().unwrap();
assert!(SystemContract::check_id(&tx.contract_id)); assert!(SystemProgram::check_id(&tx.program_id));
let instruction: SystemContract = deserialize(&tx.userdata).unwrap(); let instruction: SystemProgram = deserialize(&tx.userdata).unwrap();
if let SystemContract::Move { tokens } = instruction { if let SystemProgram::Move { tokens } = instruction {
assert_eq!(tokens, 100); assert_eq!(tokens, 100);
} }
assert_eq!(transactions.next(), None); assert_eq!(transactions.next(), None);

View File

@ -1,4 +1,4 @@
//! system smart contract //! system program
use bank::Account; use bank::Account;
use bincode::deserialize; use bincode::deserialize;
@ -6,74 +6,73 @@ use signature::Pubkey;
use transaction::Transaction; use transaction::Transaction;
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub enum SystemContract { pub enum SystemProgram {
/// Create a new account /// Create a new account
/// * Transaction::keys[0] - source /// * Transaction::keys[0] - source
/// * Transaction::keys[1] - new account key /// * Transaction::keys[1] - new account key
/// * tokens - number of tokens to transfer to the new account /// * tokens - number of tokens to transfer to the new account
/// * space - memory to allocate if greater then zero /// * space - memory to allocate if greater then zero
/// * contract - the contract id of the new account /// * program_id - the program id of the new account
CreateAccount { CreateAccount {
tokens: i64, tokens: i64,
space: u64, space: u64,
contract_id: Pubkey, program_id: Pubkey,
}, },
/// Assign account to a contract /// Assign account to a program
/// * Transaction::keys[0] - account to assign /// * Transaction::keys[0] - account to assign
Assign { contract_id: Pubkey }, Assign { program_id: Pubkey },
/// Move tokens /// Move tokens
/// * Transaction::keys[0] - source /// * Transaction::keys[0] - source
/// * Transaction::keys[1] - destination /// * Transaction::keys[1] - destination
Move { tokens: i64 }, Move { tokens: i64 },
} }
pub const SYSTEM_CONTRACT_ID: [u8; 32] = [0u8; 32]; pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32];
impl SystemContract { impl SystemProgram {
pub fn check_id(contract_id: &Pubkey) -> bool { pub fn check_id(program_id: &Pubkey) -> bool {
contract_id.as_ref() == SYSTEM_CONTRACT_ID program_id.as_ref() == SYSTEM_PROGRAM_ID
} }
pub fn id() -> Pubkey { pub fn id() -> Pubkey {
Pubkey::new(&SYSTEM_CONTRACT_ID) Pubkey::new(&SYSTEM_PROGRAM_ID)
} }
pub fn get_balance(account: &Account) -> i64 { pub fn get_balance(account: &Account) -> i64 {
account.tokens account.tokens
} }
pub fn process_transaction(tx: &Transaction, accounts: &mut [Account]) { pub fn process_transaction(tx: &Transaction, accounts: &mut [Account]) {
if let Ok(syscall) = deserialize(&tx.userdata) { if let Ok(syscall) = deserialize(&tx.userdata){
trace!("process_transaction: {:?}", syscall); trace!("process_transaction: {:?}", syscall);
match syscall { match syscall {
SystemContract::CreateAccount { SystemProgram::CreateAccount {
tokens, tokens,
space, space,
contract_id, program_id,
} => { } => {
if !Self::check_id(&accounts[0].contract_id) { if !Self::check_id(&accounts[0].program_id) {
return; return;
} }
if space > 0 if space > 0
&& (!accounts[1].userdata.is_empty() && (!accounts[1].userdata.is_empty()
|| !Self::check_id(&accounts[1].contract_id)) || !Self::check_id(&accounts[1].program_id))
{ {
return; return;
} }
accounts[0].tokens -= tokens; accounts[0].tokens -= tokens;
accounts[1].tokens += tokens; accounts[1].tokens += tokens;
accounts[1].contract_id = contract_id; accounts[1].program_id = program_id;
accounts[1].userdata = vec![0; space as usize]; accounts[1].userdata = vec![0; space as usize];
} }
SystemContract::Assign { contract_id } => { SystemProgram::Assign { program_id } => {
if !Self::check_id(&accounts[0].contract_id) { if !Self::check_id(&accounts[0].program_id) {
return; return;
} }
accounts[0].contract_id = contract_id; accounts[0].program_id = program_id;
} }
SystemContract::Move { tokens } => { SystemProgram::Move { tokens } => {
//bank should be verifying correctness //bank should be verifying correctness
accounts[0].tokens -= tokens; accounts[0].tokens -= tokens;
accounts[1].tokens += tokens; accounts[1].tokens += tokens;
}
} }
} else { } else {
info!("Invalid transaction userdata: {:?}", tx.userdata); info!("Invalid transaction userdata: {:?}", tx.userdata);
@ -85,7 +84,7 @@ mod test {
use bank::Account; use bank::Account;
use hash::Hash; use hash::Hash;
use signature::{Keypair, KeypairUtil, Pubkey}; use signature::{Keypair, KeypairUtil, Pubkey};
use system_contract::SystemContract; use system_program::SystemProgram;
use transaction::Transaction; use transaction::Transaction;
#[test] #[test]
fn test_create_noop() { fn test_create_noop() {
@ -93,7 +92,7 @@ mod test {
let to = Keypair::new(); let to = Keypair::new();
let mut accounts = vec![Account::default(), Account::default()]; let mut accounts = vec![Account::default(), Account::default()];
let tx = Transaction::system_new(&from, to.pubkey(), 0, Hash::default()); let tx = Transaction::system_new(&from, to.pubkey(), 0, Hash::default());
SystemContract::process_transaction(&tx, &mut accounts); SystemProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[0].tokens, 0); assert_eq!(accounts[0].tokens, 0);
assert_eq!(accounts[1].tokens, 0); assert_eq!(accounts[1].tokens, 0);
} }
@ -104,7 +103,7 @@ mod test {
let mut accounts = vec![Account::default(), Account::default()]; let mut accounts = vec![Account::default(), Account::default()];
accounts[0].tokens = 1; accounts[0].tokens = 1;
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default()); let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
SystemContract::process_transaction(&tx, &mut accounts); SystemProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[0].tokens, 0); assert_eq!(accounts[0].tokens, 0);
assert_eq!(accounts[1].tokens, 1); assert_eq!(accounts[1].tokens, 1);
} }
@ -114,9 +113,9 @@ mod test {
let to = Keypair::new(); let to = Keypair::new();
let mut accounts = vec![Account::default(), Account::default()]; let mut accounts = vec![Account::default(), Account::default()];
accounts[0].tokens = 1; accounts[0].tokens = 1;
accounts[0].contract_id = from.pubkey(); accounts[0].program_id = from.pubkey();
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default()); let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
SystemContract::process_transaction(&tx, &mut accounts); SystemProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[0].tokens, 1); assert_eq!(accounts[0].tokens, 1);
assert_eq!(accounts[1].tokens, 0); assert_eq!(accounts[1].tokens, 0);
} }
@ -130,10 +129,10 @@ mod test {
SystemContract::process_transaction(&tx, &mut accounts); SystemContract::process_transaction(&tx, &mut accounts);
assert!(accounts[0].userdata.is_empty()); assert!(accounts[0].userdata.is_empty());
assert_eq!(accounts[1].userdata.len(), 1); assert_eq!(accounts[1].userdata.len(), 1);
assert_eq!(accounts[1].contract_id, to.pubkey()); assert_eq!(accounts[1].program_id, to.pubkey());
} }
#[test] #[test]
fn test_create_allocate_wrong_dest_contract() { fn test_create_allocate_wrong_dest_program() {
let from = Keypair::new(); let from = Keypair::new();
let to = Keypair::new(); let to = Keypair::new();
let mut accounts = vec![Account::default(), Account::default()]; let mut accounts = vec![Account::default(), Account::default()];
@ -151,11 +150,11 @@ mod test {
assert!(accounts[1].userdata.is_empty()); assert!(accounts[1].userdata.is_empty());
} }
#[test] #[test]
fn test_create_allocate_wrong_source_contract() { fn test_create_allocate_wrong_source_program() {
let from = Keypair::new(); let from = Keypair::new();
let to = Keypair::new(); let to = Keypair::new();
let mut accounts = vec![Account::default(), Account::default()]; let mut accounts = vec![Account::default(), Account::default()];
accounts[0].contract_id = to.pubkey(); accounts[0].program_id = to.pubkey();
let tx = Transaction::system_create( let tx = Transaction::system_create(
&from, &from,
to.pubkey(), to.pubkey(),
@ -189,11 +188,11 @@ mod test {
#[test] #[test]
fn test_create_assign() { fn test_create_assign() {
let from = Keypair::new(); let from = Keypair::new();
let contract = Keypair::new(); let program = Keypair::new();
let mut accounts = vec![Account::default()]; let mut accounts = vec![Account::default()];
let tx = Transaction::system_assign(&from, Hash::default(), contract.pubkey(), 0); let tx = Transaction::system_assign(&from, Hash::default(), program.pubkey(), 0);
SystemContract::process_transaction(&tx, &mut accounts); SystemProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[0].contract_id, contract.pubkey()); assert_eq!(accounts[0].program_id, program.pubkey());
} }
#[test] #[test]
fn test_move() { fn test_move() {
@ -202,17 +201,17 @@ mod test {
let mut accounts = vec![Account::default(), Account::default()]; let mut accounts = vec![Account::default(), Account::default()];
accounts[0].tokens = 1; accounts[0].tokens = 1;
let tx = Transaction::new(&from, to.pubkey(), 1, Hash::default()); let tx = Transaction::new(&from, to.pubkey(), 1, Hash::default());
SystemContract::process_transaction(&tx, &mut accounts); SystemProgram::process_transaction(&tx, &mut accounts);
assert_eq!(accounts[0].tokens, 0); assert_eq!(accounts[0].tokens, 0);
assert_eq!(accounts[1].tokens, 1); assert_eq!(accounts[1].tokens, 1);
} }
/// Detect binary changes in the serialized contract userdata, which could have a downstream /// Detect binary changes in the serialized program userdata, which could have a downstream
/// affect on SDKs and DApps /// affect on SDKs and DApps
#[test] #[test]
fn test_sdk_serialize() { fn test_sdk_serialize() {
let keypair = Keypair::new(); let keypair = Keypair::new();
use budget_contract::BUDGET_CONTRACT_ID; use budget_program::BUDGET_PROGRAM_ID;
// CreateAccount // CreateAccount
let tx = Transaction::system_create( let tx = Transaction::system_create(
@ -221,7 +220,7 @@ mod test {
Hash::default(), Hash::default(),
111, 111,
222, 222,
Pubkey::new(&BUDGET_CONTRACT_ID), Pubkey::new(&BUDGET_PROGRAM_ID),
0, 0,
); );
@ -256,7 +255,7 @@ mod test {
let tx = Transaction::system_assign( let tx = Transaction::system_assign(
&keypair, &keypair,
Hash::default(), Hash::default(),
Pubkey::new(&BUDGET_CONTRACT_ID), Pubkey::new(&BUDGET_PROGRAM_ID),
0, 0,
); );
assert_eq!( assert_eq!(

View File

@ -428,7 +428,7 @@ mod tests {
use mint::Mint; use mint::Mint;
use signature::{Keypair, KeypairUtil}; use signature::{Keypair, KeypairUtil};
use std::fs::remove_dir_all; use std::fs::remove_dir_all;
use system_contract::SystemContract; use system_program::SystemProgram;
fn tmp_ledger(name: &str, mint: &Mint) -> String { fn tmp_ledger(name: &str, mint: &Mint) -> String {
use std::env; use std::env;
@ -536,7 +536,7 @@ mod tests {
let mut tr2 = Transaction::new(&alice.keypair(), bob_pubkey, 501, last_id); let mut tr2 = Transaction::new(&alice.keypair(), bob_pubkey, 501, last_id);
let mut instruction2 = deserialize(&tr2.userdata).unwrap(); let mut instruction2 = deserialize(&tr2.userdata).unwrap();
if let SystemContract::Move { ref mut tokens } = instruction2 { if let SystemProgram::Move { ref mut tokens } = instruction2 {
*tokens = 502; *tokens = 502;
} }
tr2.userdata = serialize(&instruction2).unwrap(); tr2.userdata = serialize(&instruction2).unwrap();

View File

@ -2,14 +2,14 @@
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
use budget::{Budget, Condition}; use budget::{Budget, Condition};
use budget_contract::BudgetContract; use budget_program::BudgetProgram;
use chrono::prelude::*; use chrono::prelude::*;
use hash::Hash; use hash::Hash;
use instruction::{Contract, Instruction, Vote}; use instruction::{Contract, Instruction, Vote};
use payment_plan::Payment; use payment_plan::Payment;
use signature::{Keypair, KeypairUtil, Pubkey, Signature}; use signature::{Keypair, KeypairUtil, Pubkey, Signature};
use std::mem::size_of; use std::mem::size_of;
use system_contract::SystemContract; use system_program::SystemProgram;
pub const SIGNED_DATA_OFFSET: usize = size_of::<Signature>(); pub const SIGNED_DATA_OFFSET: usize = size_of::<Signature>();
pub const SIG_OFFSET: usize = 0; pub const SIG_OFFSET: usize = 0;
@ -18,18 +18,18 @@ pub const PUB_KEY_OFFSET: usize = size_of::<Signature>() + size_of::<u64>();
/// An instruction signed by a client with `Pubkey`. /// An instruction signed by a client with `Pubkey`.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Transaction { pub struct Transaction {
/// A digital signature of `keys`, `contract_id`, `last_id`, `fee` and `userdata`, signed by `Pubkey`. /// A digital signature of `keys`, `program_id`, `last_id`, `fee` and `userdata`, signed by `Pubkey`.
pub signature: Signature, pub signature: Signature,
/// The `Pubkeys` that are executing this transaction userdata. The meaning of each key is /// The `Pubkeys` that are executing this transaction userdata. The meaning of each key is
/// contract-specific. /// program-specific.
/// * keys[0] - Typically this is the `caller` public key. `signature` is verified with keys[0]. /// * keys[0] - Typically this is the `caller` public key. `signature` is verified with keys[0].
/// In the future which key pays the fee and which keys have signatures would be configurable. /// In the future which key pays the fee and which keys have signatures would be configurable.
/// * keys[1] - Typically this is the contract context or the recipient of the tokens /// * keys[1] - Typically this is the program context or the recipient of the tokens
pub keys: Vec<Pubkey>, pub keys: Vec<Pubkey>,
/// the contract id to execute /// The program code that executes this transaction is identified by the program_id.
pub contract_id: Pubkey, pub program_id: Pubkey,
/// The ID of a recent ledger entry. /// The ID of a recent ledger entry.
pub last_id: Hash, pub last_id: Hash,
@ -44,15 +44,15 @@ pub struct Transaction {
impl Transaction { impl Transaction {
/// Create a signed transaction from the given `Instruction`. /// Create a signed transaction from the given `Instruction`.
/// * `from_keypair` - The key used to sign the transaction. This key is stored as keys[0] /// * `from_keypair` - The key used to sign the transaction. This key is stored as keys[0]
/// * `transaction_keys` - The keys for the transaction. These are the contract state /// * `transaction_keys` - The keys for the transaction. These are the program state
/// instances or token recipient keys. /// instances or token recipient keys.
/// * `userdata` - The input data that the contract will execute with /// * `userdata` - The input data that the program will execute with
/// * `last_id` - The PoH hash. /// * `last_id` - The PoH hash.
/// * `fee` - The transaction fee. /// * `fee` - The transaction fee.
pub fn new_with_userdata( pub fn new_with_userdata(
from_keypair: &Keypair, from_keypair: &Keypair,
transaction_keys: &[Pubkey], transaction_keys: &[Pubkey],
contract_id: Pubkey, program_id: Pubkey,
userdata: Vec<u8>, userdata: Vec<u8>,
last_id: Hash, last_id: Hash,
fee: i64, fee: i64,
@ -63,7 +63,7 @@ impl Transaction {
let mut tx = Transaction { let mut tx = Transaction {
signature: Signature::default(), signature: Signature::default(),
keys, keys,
contract_id, program_id,
last_id, last_id,
fee, fee,
userdata, userdata,
@ -74,22 +74,22 @@ impl Transaction {
/// Create and sign a new Transaction. Used for unit-testing. /// Create and sign a new Transaction. Used for unit-testing.
pub fn budget_new_taxed( pub fn budget_new_taxed(
from_keypair: &Keypair, from_keypair: &Keypair,
contract: Pubkey, to: Pubkey,
tokens: i64, tokens: i64,
fee: i64, fee: i64,
last_id: Hash, last_id: Hash,
) -> Self { ) -> Self {
let payment = Payment { let payment = Payment {
tokens: tokens - fee, tokens: tokens - fee,
to: contract, to: to,
}; };
let budget = Budget::Pay(payment); let budget = Budget::Pay(payment);
let instruction = Instruction::NewContract(Contract { budget, tokens }); let instruction = Instruction::NewContract(Contract { budget, tokens });
let userdata = serialize(&instruction).unwrap(); let userdata = serialize(&instruction).unwrap();
Self::new_with_userdata( Self::new_with_userdata(
from_keypair, from_keypair,
&[contract], &[to],
BudgetContract::id(), BudgetProgram::id(),
userdata, userdata,
last_id, last_id,
fee, fee,
@ -114,7 +114,7 @@ impl Transaction {
Self::new_with_userdata( Self::new_with_userdata(
from_keypair, from_keypair,
&[contract, to], &[contract, to],
BudgetContract::id(), BudgetProgram::id(),
userdata, userdata,
last_id, last_id,
0, 0,
@ -133,7 +133,7 @@ impl Transaction {
Self::new_with_userdata( Self::new_with_userdata(
from_keypair, from_keypair,
&[contract, to], &[contract, to],
BudgetContract::id(), BudgetProgram::id(),
userdata, userdata,
last_id, last_id,
0, 0,
@ -146,7 +146,7 @@ impl Transaction {
Self::new_with_userdata( Self::new_with_userdata(
from_keypair, from_keypair,
&[], &[],
BudgetContract::id(), BudgetProgram::id(),
userdata, userdata,
last_id, last_id,
fee, fee,
@ -172,58 +172,58 @@ impl Transaction {
Self::new_with_userdata( Self::new_with_userdata(
from_keypair, from_keypair,
&[contract], &[contract],
BudgetContract::id(), BudgetProgram::id(),
userdata, userdata,
last_id, last_id,
0, 0,
) )
} }
/// Create and sign new SystemContract::CreateAccount transaction /// Create and sign new SystemProgram::CreateAccount transaction
pub fn system_create( pub fn system_create(
from_keypair: &Keypair, from_keypair: &Keypair,
to: Pubkey, to: Pubkey,
last_id: Hash, last_id: Hash,
tokens: i64, tokens: i64,
space: u64, space: u64,
contract_id: Pubkey, program_id: Pubkey,
fee: i64, fee: i64,
) -> Self { ) -> Self {
let create = SystemContract::CreateAccount { let create = SystemProgram::CreateAccount {
tokens, //TODO, the tokens to allocate might need to be higher then 0 in the future tokens, //TODO, the tokens to allocate might need to be higher then 0 in the future
space, space,
contract_id, program_id,
}; };
Transaction::new_with_userdata( Transaction::new_with_userdata(
from_keypair, from_keypair,
&[to], &[to],
SystemContract::id(), SystemProgram::id(),
serialize(&create).unwrap(), serialize(&create).unwrap(),
last_id, last_id,
fee, fee,
) )
} }
/// Create and sign new SystemContract::CreateAccount transaction /// Create and sign new SystemProgram::CreateAccount transaction
pub fn system_assign( pub fn system_assign(
from_keypair: &Keypair, from_keypair: &Keypair,
last_id: Hash, last_id: Hash,
contract_id: Pubkey, program_id: Pubkey,
fee: i64, fee: i64,
) -> Self { ) -> Self {
let create = SystemContract::Assign { contract_id }; let create = SystemProgram::Assign { program_id };
Transaction::new_with_userdata( Transaction::new_with_userdata(
from_keypair, from_keypair,
&[], &[],
SystemContract::id(), SystemProgram::id(),
serialize(&create).unwrap(), serialize(&create).unwrap(),
last_id, last_id,
fee, fee,
) )
} }
/// Create and sign new SystemContract::CreateAccount transaction with some defaults /// Create and sign new SystemProgram::CreateAccount transaction with some defaults
pub fn system_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { pub fn system_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self {
Transaction::system_create(from_keypair, to, last_id, tokens, 0, Pubkey::default(), 0) Transaction::system_create(from_keypair, to, last_id, tokens, 0, Pubkey::default(), 0)
} }
/// Create and sign new SystemContract::Move transaction /// Create and sign new SystemProgram::Move transaction
pub fn system_move( pub fn system_move(
from_keypair: &Keypair, from_keypair: &Keypair,
to: Pubkey, to: Pubkey,
@ -231,17 +231,17 @@ impl Transaction {
last_id: Hash, last_id: Hash,
fee: i64, fee: i64,
) -> Self { ) -> Self {
let create = SystemContract::Move { tokens }; let create = SystemProgram::Move { tokens };
Transaction::new_with_userdata( Transaction::new_with_userdata(
from_keypair, from_keypair,
&[to], &[to],
SystemContract::id(), SystemProgram::id(),
serialize(&create).unwrap(), serialize(&create).unwrap(),
last_id, last_id,
fee, fee,
) )
} }
/// Create and sign new SystemContract::Move transaction /// Create and sign new SystemProgram::Move transaction
pub fn new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { pub fn new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self {
Transaction::system_move(from_keypair, to, tokens, last_id, 0) Transaction::system_move(from_keypair, to, tokens, last_id, 0)
} }
@ -249,8 +249,8 @@ impl Transaction {
fn get_sign_data(&self) -> Vec<u8> { fn get_sign_data(&self) -> Vec<u8> {
let mut data = serialize(&(&self.keys)).expect("serialize keys"); let mut data = serialize(&(&self.keys)).expect("serialize keys");
let contract_id = serialize(&(&self.contract_id)).expect("serialize contract_id"); let program_id = serialize(&(&self.program_id)).expect("serialize program_id");
data.extend_from_slice(&contract_id); data.extend_from_slice(&program_id);
let last_id_data = serialize(&(&self.last_id)).expect("serialize last_id"); let last_id_data = serialize(&(&self.last_id)).expect("serialize last_id");
data.extend_from_slice(&last_id_data); data.extend_from_slice(&last_id_data);
@ -367,7 +367,7 @@ mod tests {
keys: vec![], keys: vec![],
last_id: Default::default(), last_id: Default::default(),
signature: Default::default(), signature: Default::default(),
contract_id: Default::default(), program_id: Default::default(),
fee: 0, fee: 0,
userdata, userdata,
}; };
@ -486,7 +486,7 @@ mod tests {
1, 1, 1, 1, 1, 1,
]); ]);
let contract = Pubkey::new(&[ let program_id = Pubkey::new(&[
2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4,
2, 2, 2, 2, 2, 2,
]); ]);
@ -494,7 +494,7 @@ mod tests {
let tx = Transaction::new_with_userdata( let tx = Transaction::new_with_userdata(
keypair, keypair,
&[keypair.pubkey(), to], &[keypair.pubkey(), to],
contract, program_id,
vec![1, 2, 3], vec![1, 2, 3],
Hash::default(), Hash::default(),
99, 99,