s/contract/program
This commit is contained in:
		
				
					committed by
					
						 Michael Vines
						Michael Vines
					
				
			
			
				
	
			
			
			
						parent
						
							6073cd57fa
						
					
				
				
					commit
					9bfead2e01
				
			
							
								
								
									
										56
									
								
								src/bank.rs
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								src/bank.rs
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | ||||
|  | ||||
| use bincode::deserialize; | ||||
| use bincode::serialize; | ||||
| use budget_contract::BudgetContract; | ||||
| use budget_program::BudgetProgram; | ||||
| use counter::Counter; | ||||
| use entry::Entry; | ||||
| use hash::{hash, Hash}; | ||||
| @@ -21,7 +21,7 @@ use std::result; | ||||
| use std::sync::atomic::{AtomicUsize, Ordering}; | ||||
| use std::sync::RwLock; | ||||
| use std::time::Instant; | ||||
| use system_contract::SystemContract; | ||||
| use system_program::SystemProgram; | ||||
| use timing::{duration_as_us, timestamp}; | ||||
| use transaction::Transaction; | ||||
| use window::WINDOW_SIZE; | ||||
| @@ -35,14 +35,14 @@ pub struct Account { | ||||
|     /// A transaction can write to its userdata | ||||
|     pub userdata: Vec<u8>, | ||||
|     /// contract id this contract belongs to | ||||
|     pub contract_id: Pubkey, | ||||
|     pub program_id: Pubkey, | ||||
| } | ||||
| 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 { | ||||
|             tokens, | ||||
|             userdata: vec![0u8; space], | ||||
|             contract_id, | ||||
|             program_id, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -52,7 +52,7 @@ impl Default for Account { | ||||
|         Account { | ||||
|             tokens: 0, | ||||
|             userdata: vec![], | ||||
|             contract_id: SystemContract::id(), | ||||
|             program_id: SystemProgram::id(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -284,7 +284,7 @@ impl Bank { | ||||
|             } else { | ||||
|                 error_counters.account_not_found_leader += 1; | ||||
|             } | ||||
|             if BudgetContract::check_id(&tx.contract_id) { | ||||
|             if BudgetProgram::check_id(&tx.program_id) { | ||||
|                 use instruction::Instruction; | ||||
|                 if let Some(Instruction::NewVote(_vote)) = tx.instruction() { | ||||
|                     error_counters.account_not_found_vote += 1; | ||||
| @@ -318,21 +318,21 @@ impl Bank { | ||||
|     } | ||||
|     pub fn verify_transaction( | ||||
|         tx: &Transaction, | ||||
|         pre_contract_id: &Pubkey, | ||||
|         pre_program_id: &Pubkey, | ||||
|         pre_tokens: i64, | ||||
|         account: &Account, | ||||
|     ) -> Result<()> { | ||||
|         // Verify the transaction | ||||
|         // make sure that contract_id is still the same or this was just assigned by the system call contract | ||||
|         if !((*pre_contract_id == account.contract_id) | ||||
|             || (SystemContract::check_id(&tx.contract_id) | ||||
|                 && SystemContract::check_id(&pre_contract_id))) | ||||
|         // make sure that program_id is still the same or this was just assigned by the system call contract | ||||
|         if !((*pre_program_id == account.program_id) | ||||
|             || (SystemProgram::check_id(&tx.program_id) | ||||
|                 && SystemProgram::check_id(&pre_program_id))) | ||||
|         { | ||||
|             //TODO, this maybe redundant bpf should be able to guarantee this property | ||||
|             return Err(BankError::ModifiedContractId(tx.signature)); | ||||
|         } | ||||
|         // 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)); | ||||
|         } | ||||
|         if account.tokens < 0 { | ||||
| @@ -348,23 +348,23 @@ impl Bank { | ||||
|         let pre_total: i64 = accounts.iter().map(|a| a.tokens).sum(); | ||||
|         let pre_data: Vec<_> = accounts | ||||
|             .iter_mut() | ||||
|             .map(|a| (a.contract_id, a.tokens)) | ||||
|             .map(|a| (a.program_id, a.tokens)) | ||||
|             .collect(); | ||||
|  | ||||
|         // Call the contract method | ||||
|         // It's up to the contract to implement its own rules on moving funds | ||||
|         if SystemContract::check_id(&tx.contract_id) { | ||||
|             SystemContract::process_transaction(&tx, accounts) | ||||
|         } else if BudgetContract::check_id(&tx.contract_id) { | ||||
|         if SystemProgram::check_id(&tx.program_id) { | ||||
|             SystemProgram::process_transaction(&tx, accounts) | ||||
|         } else if BudgetProgram::check_id(&tx.program_id) { | ||||
|             // TODO: the runtime should be checking read/write access to memory | ||||
|             // we are trusting the hard coded contracts not to clobber or allocate | ||||
|             BudgetContract::process_transaction(&tx, accounts) | ||||
|             BudgetProgram::process_transaction(&tx, accounts) | ||||
|         } else { | ||||
|             return Err(BankError::UnknownContractId(tx.contract_id)); | ||||
|             return Err(BankError::UnknownContractId(tx.program_id)); | ||||
|         } | ||||
|         // Verify the transaction | ||||
|         for ((pre_contract_id, pre_tokens), post_account) in pre_data.iter().zip(accounts.iter()) { | ||||
|             Self::verify_transaction(&tx, pre_contract_id, *pre_tokens, post_account)?; | ||||
|         for ((pre_program_id, pre_tokens), post_account) in pre_data.iter().zip(accounts.iter()) { | ||||
|             Self::verify_transaction(&tx, pre_program_id, *pre_tokens, post_account)?; | ||||
|         } | ||||
|         // The total sum of all the tokens in all the pages cannot change. | ||||
|         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"); | ||||
|         { | ||||
|             let tx = &entry1.transactions[0]; | ||||
|             assert!(SystemContract::check_id(&tx.contract_id), "Invalid ledger"); | ||||
|             let instruction: SystemContract = deserialize(&tx.userdata).unwrap(); | ||||
|             let deposit = if let SystemContract::Move { tokens } = instruction { | ||||
|             assert!(SystemProgram::check_id(&tx.program_id), "Invalid ledger"); | ||||
|             let instruction: SystemProgram = deserialize(&tx.userdata).unwrap(); | ||||
|             let deposit = if let SystemProgram::Move { tokens } = instruction { | ||||
|                 Some(tokens) | ||||
|             } else { | ||||
|                 None | ||||
| @@ -607,10 +607,10 @@ impl Bank { | ||||
|     } | ||||
|  | ||||
|     pub fn read_balance(account: &Account) -> i64 { | ||||
|         if SystemContract::check_id(&account.contract_id) { | ||||
|             SystemContract::get_balance(account) | ||||
|         } else if BudgetContract::check_id(&account.contract_id) { | ||||
|             BudgetContract::get_balance(account) | ||||
|         if SystemProgram::check_id(&account.program_id) { | ||||
|             SystemProgram::get_balance(account) | ||||
|         } else if BudgetProgram::check_id(&account.program_id) { | ||||
|             BudgetProgram::get_balance(account) | ||||
|         } else { | ||||
|             account.tokens | ||||
|         } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| //! budget contract
 | ||||
| //! budget program
 | ||||
| use bank::Account; | ||||
| use bincode::{self, deserialize, serialize_into, serialized_size}; | ||||
| use budget::Budget; | ||||
| @@ -23,24 +23,24 @@ pub enum BudgetError { | ||||
| } | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] | ||||
| pub struct BudgetContract { | ||||
| pub struct BudgetProgram { | ||||
|     pub initialized: bool, | ||||
|     pub pending_budget: Option<Budget>, | ||||
|     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, | ||||
| ]; | ||||
| impl BudgetContract { | ||||
| impl BudgetProgram { | ||||
|     fn is_pending(&self) -> bool { | ||||
|         self.pending_budget != None | ||||
|     } | ||||
|     pub fn id() -> Pubkey { | ||||
|         Pubkey::new(&BUDGET_CONTRACT_ID) | ||||
|         Pubkey::new(&BUDGET_PROGRAM_ID) | ||||
|     } | ||||
|     pub fn check_id(contract_id: &Pubkey) -> bool { | ||||
|         contract_id.as_ref() == BUDGET_CONTRACT_ID | ||||
|     pub fn check_id(program_id: &Pubkey) -> bool { | ||||
|         program_id.as_ref() == BUDGET_PROGRAM_ID | ||||
|     } | ||||
| 
 | ||||
|     /// Process a Witness Signature. Any payment plans waiting on this signature
 | ||||
| @@ -145,7 +145,7 @@ impl BudgetContract { | ||||
|                         trace!("contract already exists"); | ||||
|                         Err(BudgetError::ContractAlreadyExists(tx.keys[1])) | ||||
|                     } else { | ||||
|                         let mut state = BudgetContract::default(); | ||||
|                         let mut state = BudgetProgram::default(); | ||||
|                         state.pending_budget = Some(budget); | ||||
|                         accounts[1].tokens += contract.tokens; | ||||
|                         state.initialized = true; | ||||
| @@ -231,7 +231,7 @@ impl BudgetContract { | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
|             state.last_error = Some(e); | ||||
|             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
 | ||||
|     pub fn get_balance(account: &Account) -> i64 { | ||||
|         if let Ok(state) = deserialize(&account.userdata) { | ||||
|             let state: BudgetContract = state; | ||||
|             let state: BudgetProgram = state; | ||||
|             if state.is_pending() { | ||||
|                 0 | ||||
|             } else { | ||||
| @@ -277,19 +277,19 @@ impl BudgetContract { | ||||
| mod test { | ||||
|     use bank::Account; | ||||
|     use bincode::serialize; | ||||
|     use budget_contract::{BudgetContract, BudgetError}; | ||||
|     use budget_program::{BudgetError, BudgetProgram}; | ||||
|     use chrono::prelude::{DateTime, NaiveDate, Utc}; | ||||
|     use hash::Hash; | ||||
|     use signature::{GenKeys, Keypair, KeypairUtil, Pubkey}; | ||||
|     use transaction::Transaction; | ||||
|     #[test] | ||||
|     fn test_serializer() { | ||||
|         let mut a = Account::new(0, 512, BudgetContract::id()); | ||||
|         let b = BudgetContract::default(); | ||||
|         let mut a = Account::new(0, 512, BudgetProgram::id()); | ||||
|         let b = BudgetProgram::default(); | ||||
|         b.serialize(&mut a.userdata).unwrap(); | ||||
|         let buf = serialize(&b).unwrap(); | ||||
|         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); | ||||
|     } | ||||
| 
 | ||||
| @@ -327,9 +327,9 @@ mod test { | ||||
|     #[test] | ||||
|     fn test_transfer_on_date() { | ||||
|         let mut accounts = vec![ | ||||
|             Account::new(1, 0, BudgetContract::id()), | ||||
|             Account::new(0, 512, BudgetContract::id()), | ||||
|             Account::new(0, 0, BudgetContract::id()), | ||||
|             Account::new(1, 0, BudgetProgram::id()), | ||||
|             Account::new(0, 512, BudgetProgram::id()), | ||||
|             Account::new(0, 0, BudgetProgram::id()), | ||||
|         ]; | ||||
|         let from_account = 0; | ||||
|         let contract_account = 1; | ||||
| @@ -347,10 +347,10 @@ mod test { | ||||
|             1, | ||||
|             Hash::default(), | ||||
|         ); | ||||
|         BudgetContract::process_transaction(&tx, &mut accounts); | ||||
|         BudgetProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         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!(state.is_pending()); | ||||
| 
 | ||||
| @@ -362,12 +362,12 @@ mod test { | ||||
|             dt, | ||||
|             Hash::default(), | ||||
|         ); | ||||
|         BudgetContract::process_transaction(&tx, &mut accounts); | ||||
|         BudgetProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         assert_eq!(accounts[contract_account].tokens, 1); | ||||
|         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!( | ||||
|             state.last_error, | ||||
|             Some(BudgetError::DestinationMissing(to.pubkey())) | ||||
| @@ -383,20 +383,20 @@ mod test { | ||||
|             dt, | ||||
|             Hash::default(), | ||||
|         ); | ||||
|         BudgetContract::process_transaction(&tx, &mut accounts); | ||||
|         BudgetProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         assert_eq!(accounts[contract_account].tokens, 0); | ||||
|         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()); | ||||
| 
 | ||||
|         // 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[contract_account].tokens, 0); | ||||
|         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!( | ||||
|             state.last_error, | ||||
|             Some(BudgetError::ContractNotPending(contract.pubkey())) | ||||
| @@ -405,9 +405,9 @@ mod test { | ||||
|     #[test] | ||||
|     fn test_cancel_transfer() { | ||||
|         let mut accounts = vec![ | ||||
|             Account::new(1, 0, BudgetContract::id()), | ||||
|             Account::new(0, 512, BudgetContract::id()), | ||||
|             Account::new(0, 0, BudgetContract::id()), | ||||
|             Account::new(1, 0, BudgetProgram::id()), | ||||
|             Account::new(0, 512, BudgetProgram::id()), | ||||
|             Account::new(0, 0, BudgetProgram::id()), | ||||
|         ]; | ||||
|         let from_account = 0; | ||||
|         let contract_account = 1; | ||||
| @@ -424,10 +424,10 @@ mod test { | ||||
|             1, | ||||
|             Hash::default(), | ||||
|         ); | ||||
|         BudgetContract::process_transaction(&tx, &mut accounts); | ||||
|         BudgetProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         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!(state.is_pending()); | ||||
| 
 | ||||
| @@ -436,7 +436,7 @@ mod test { | ||||
|             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
 | ||||
|         // 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
 | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         assert_eq!(accounts[contract_account].tokens, 1); | ||||
| @@ -450,7 +450,7 @@ mod test { | ||||
|             from.pubkey(), | ||||
|             Hash::default(), | ||||
|         ); | ||||
|         BudgetContract::process_transaction(&tx, &mut accounts); | ||||
|         BudgetProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         assert_eq!(accounts[contract_account].tokens, 0); | ||||
|         assert_eq!(accounts[pay_account].tokens, 1); | ||||
| @@ -462,12 +462,12 @@ mod test { | ||||
|             from.pubkey(), | ||||
|             Hash::default(), | ||||
|         ); | ||||
|         BudgetContract::process_transaction(&tx, &mut accounts); | ||||
|         BudgetProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[from_account].tokens, 0); | ||||
|         assert_eq!(accounts[contract_account].tokens, 0); | ||||
|         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!( | ||||
|             state.last_error, | ||||
|             Some(BudgetError::ContractNotPending(contract.pubkey())) | ||||
| @@ -19,7 +19,7 @@ pub mod client; | ||||
| pub mod instruction; | ||||
| #[macro_use] | ||||
| pub mod crdt; | ||||
| pub mod budget_contract; | ||||
| pub mod budget_program; | ||||
| pub mod drone; | ||||
| pub mod entry; | ||||
| pub mod entry_writer; | ||||
| @@ -55,7 +55,7 @@ pub mod signature; | ||||
| pub mod sigverify; | ||||
| pub mod sigverify_stage; | ||||
| pub mod streamer; | ||||
| pub mod system_contract; | ||||
| pub mod system_program; | ||||
| pub mod thin_client; | ||||
| pub mod timing; | ||||
| pub mod tpu; | ||||
|   | ||||
| @@ -68,15 +68,15 @@ mod tests { | ||||
|     use super::*; | ||||
|     use bincode::deserialize; | ||||
|     use ledger::Block; | ||||
|     use system_contract::SystemContract; | ||||
|     use system_program::SystemProgram; | ||||
|  | ||||
|     #[test] | ||||
|     fn test_create_transactions() { | ||||
|         let mut transactions = Mint::new(100).create_transactions().into_iter(); | ||||
|         let tx = transactions.next().unwrap(); | ||||
|         assert!(SystemContract::check_id(&tx.contract_id)); | ||||
|         let instruction: SystemContract = deserialize(&tx.userdata).unwrap(); | ||||
|         if let SystemContract::Move { tokens } = instruction { | ||||
|         assert!(SystemProgram::check_id(&tx.program_id)); | ||||
|         let instruction: SystemProgram = deserialize(&tx.userdata).unwrap(); | ||||
|         if let SystemProgram::Move { tokens } = instruction { | ||||
|             assert_eq!(tokens, 100); | ||||
|         } | ||||
|         assert_eq!(transactions.next(), None); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| //! system smart contract
 | ||||
| //! system program
 | ||||
| 
 | ||||
| use bank::Account; | ||||
| use bincode::deserialize; | ||||
| @@ -6,74 +6,73 @@ use signature::Pubkey; | ||||
| use transaction::Transaction; | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Debug, Clone)] | ||||
| pub enum SystemContract { | ||||
| pub enum SystemProgram { | ||||
|     /// Create a new account
 | ||||
|     /// * Transaction::keys[0] - source
 | ||||
|     /// * Transaction::keys[1] - new account key
 | ||||
|     /// * tokens - number of tokens to transfer to the new account
 | ||||
|     /// * 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 { | ||||
|         tokens: i64, | ||||
|         space: u64, | ||||
|         contract_id: Pubkey, | ||||
|         program_id: Pubkey, | ||||
|     }, | ||||
|     /// Assign account to a contract
 | ||||
|     /// Assign account to a program
 | ||||
|     /// * Transaction::keys[0] - account to assign
 | ||||
|     Assign { contract_id: Pubkey }, | ||||
|     Assign { program_id: Pubkey }, | ||||
|     /// Move tokens
 | ||||
|     /// * Transaction::keys[0] - source
 | ||||
|     /// * Transaction::keys[1] - destination
 | ||||
|     Move { tokens: i64 }, | ||||
| } | ||||
| 
 | ||||
| pub const SYSTEM_CONTRACT_ID: [u8; 32] = [0u8; 32]; | ||||
| pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32]; | ||||
| 
 | ||||
| impl SystemContract { | ||||
|     pub fn check_id(contract_id: &Pubkey) -> bool { | ||||
|         contract_id.as_ref() == SYSTEM_CONTRACT_ID | ||||
| impl SystemProgram { | ||||
|     pub fn check_id(program_id: &Pubkey) -> bool { | ||||
|         program_id.as_ref() == SYSTEM_PROGRAM_ID | ||||
|     } | ||||
| 
 | ||||
|     pub fn id() -> Pubkey { | ||||
|         Pubkey::new(&SYSTEM_CONTRACT_ID) | ||||
|         Pubkey::new(&SYSTEM_PROGRAM_ID) | ||||
|     } | ||||
|     pub fn get_balance(account: &Account) -> i64 { | ||||
|         account.tokens | ||||
|     } | ||||
|     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); | ||||
|             match syscall { | ||||
|                 SystemContract::CreateAccount { | ||||
|                 SystemProgram::CreateAccount { | ||||
|                     tokens, | ||||
|                     space, | ||||
|                     contract_id, | ||||
|                     program_id, | ||||
|                 } => { | ||||
|                     if !Self::check_id(&accounts[0].contract_id) { | ||||
|                     if !Self::check_id(&accounts[0].program_id) { | ||||
|                         return; | ||||
|                     } | ||||
|                     if space > 0 | ||||
|                         && (!accounts[1].userdata.is_empty() | ||||
|                             || !Self::check_id(&accounts[1].contract_id)) | ||||
|                             || !Self::check_id(&accounts[1].program_id)) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                     accounts[0].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]; | ||||
|                 } | ||||
|                 SystemContract::Assign { contract_id } => { | ||||
|                     if !Self::check_id(&accounts[0].contract_id) { | ||||
|                 SystemProgram::Assign { program_id } => { | ||||
|                     if !Self::check_id(&accounts[0].program_id) { | ||||
|                         return; | ||||
|                     } | ||||
|                     accounts[0].contract_id = contract_id; | ||||
|                     accounts[0].program_id = program_id; | ||||
|                 } | ||||
|                 SystemContract::Move { tokens } => { | ||||
|                 SystemProgram::Move { tokens } => { | ||||
|                     //bank should be verifying correctness
 | ||||
|                     accounts[0].tokens -= tokens; | ||||
|                     accounts[1].tokens += tokens; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             info!("Invalid transaction userdata: {:?}", tx.userdata); | ||||
| @@ -85,7 +84,7 @@ mod test { | ||||
|     use bank::Account; | ||||
|     use hash::Hash; | ||||
|     use signature::{Keypair, KeypairUtil, Pubkey}; | ||||
|     use system_contract::SystemContract; | ||||
|     use system_program::SystemProgram; | ||||
|     use transaction::Transaction; | ||||
|     #[test] | ||||
|     fn test_create_noop() { | ||||
| @@ -93,7 +92,7 @@ mod test { | ||||
|         let to = Keypair::new(); | ||||
|         let mut accounts = vec![Account::default(), Account::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[1].tokens, 0); | ||||
|     } | ||||
| @@ -104,7 +103,7 @@ mod test { | ||||
|         let mut accounts = vec![Account::default(), Account::default()]; | ||||
|         accounts[0].tokens = 1; | ||||
|         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[1].tokens, 1); | ||||
|     } | ||||
| @@ -114,9 +113,9 @@ mod test { | ||||
|         let to = Keypair::new(); | ||||
|         let mut accounts = vec![Account::default(), Account::default()]; | ||||
|         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()); | ||||
|         SystemContract::process_transaction(&tx, &mut accounts); | ||||
|         SystemProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[0].tokens, 1); | ||||
|         assert_eq!(accounts[1].tokens, 0); | ||||
|     } | ||||
| @@ -130,10 +129,10 @@ mod test { | ||||
|         SystemContract::process_transaction(&tx, &mut accounts); | ||||
|         assert!(accounts[0].userdata.is_empty()); | ||||
|         assert_eq!(accounts[1].userdata.len(), 1); | ||||
|         assert_eq!(accounts[1].contract_id, to.pubkey()); | ||||
|         assert_eq!(accounts[1].program_id, to.pubkey()); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_create_allocate_wrong_dest_contract() { | ||||
|     fn test_create_allocate_wrong_dest_program() { | ||||
|         let from = Keypair::new(); | ||||
|         let to = Keypair::new(); | ||||
|         let mut accounts = vec![Account::default(), Account::default()]; | ||||
| @@ -151,11 +150,11 @@ mod test { | ||||
|         assert!(accounts[1].userdata.is_empty()); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_create_allocate_wrong_source_contract() { | ||||
|     fn test_create_allocate_wrong_source_program() { | ||||
|         let from = Keypair::new(); | ||||
|         let to = Keypair::new(); | ||||
|         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( | ||||
|             &from, | ||||
|             to.pubkey(), | ||||
| @@ -189,11 +188,11 @@ mod test { | ||||
|     #[test] | ||||
|     fn test_create_assign() { | ||||
|         let from = Keypair::new(); | ||||
|         let contract = Keypair::new(); | ||||
|         let program = Keypair::new(); | ||||
|         let mut accounts = vec![Account::default()]; | ||||
|         let tx = Transaction::system_assign(&from, Hash::default(), contract.pubkey(), 0); | ||||
|         SystemContract::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[0].contract_id, contract.pubkey()); | ||||
|         let tx = Transaction::system_assign(&from, Hash::default(), program.pubkey(), 0); | ||||
|         SystemProgram::process_transaction(&tx, &mut accounts); | ||||
|         assert_eq!(accounts[0].program_id, program.pubkey()); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_move() { | ||||
| @@ -202,17 +201,17 @@ mod test { | ||||
|         let mut accounts = vec![Account::default(), Account::default()]; | ||||
|         accounts[0].tokens = 1; | ||||
|         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[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
 | ||||
|     #[test] | ||||
|     fn test_sdk_serialize() { | ||||
|         let keypair = Keypair::new(); | ||||
|         use budget_contract::BUDGET_CONTRACT_ID; | ||||
|         use budget_program::BUDGET_PROGRAM_ID; | ||||
| 
 | ||||
|         // CreateAccount
 | ||||
|         let tx = Transaction::system_create( | ||||
| @@ -221,7 +220,7 @@ mod test { | ||||
|             Hash::default(), | ||||
|             111, | ||||
|             222, | ||||
|             Pubkey::new(&BUDGET_CONTRACT_ID), | ||||
|             Pubkey::new(&BUDGET_PROGRAM_ID), | ||||
|             0, | ||||
|         ); | ||||
| 
 | ||||
| @@ -256,7 +255,7 @@ mod test { | ||||
|         let tx = Transaction::system_assign( | ||||
|             &keypair, | ||||
|             Hash::default(), | ||||
|             Pubkey::new(&BUDGET_CONTRACT_ID), | ||||
|             Pubkey::new(&BUDGET_PROGRAM_ID), | ||||
|             0, | ||||
|         ); | ||||
|         assert_eq!( | ||||
| @@ -428,7 +428,7 @@ mod tests { | ||||
|     use mint::Mint; | ||||
|     use signature::{Keypair, KeypairUtil}; | ||||
|     use std::fs::remove_dir_all; | ||||
|     use system_contract::SystemContract; | ||||
|     use system_program::SystemProgram; | ||||
|  | ||||
|     fn tmp_ledger(name: &str, mint: &Mint) -> String { | ||||
|         use std::env; | ||||
| @@ -536,7 +536,7 @@ mod tests { | ||||
|  | ||||
|         let mut tr2 = Transaction::new(&alice.keypair(), bob_pubkey, 501, last_id); | ||||
|         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; | ||||
|         } | ||||
|         tr2.userdata = serialize(&instruction2).unwrap(); | ||||
|   | ||||
| @@ -2,14 +2,14 @@ | ||||
|  | ||||
| use bincode::{deserialize, serialize}; | ||||
| use budget::{Budget, Condition}; | ||||
| use budget_contract::BudgetContract; | ||||
| use budget_program::BudgetProgram; | ||||
| use chrono::prelude::*; | ||||
| use hash::Hash; | ||||
| use instruction::{Contract, Instruction, Vote}; | ||||
| use payment_plan::Payment; | ||||
| use signature::{Keypair, KeypairUtil, Pubkey, Signature}; | ||||
| use std::mem::size_of; | ||||
| use system_contract::SystemContract; | ||||
| use system_program::SystemProgram; | ||||
|  | ||||
| pub const SIGNED_DATA_OFFSET: usize = size_of::<Signature>(); | ||||
| 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`. | ||||
| #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] | ||||
| 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, | ||||
|  | ||||
|     /// 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]. | ||||
|     /// 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>, | ||||
|  | ||||
|     /// the contract id to execute | ||||
|     pub contract_id: Pubkey, | ||||
|     /// The program code that executes this transaction is identified by the program_id. | ||||
|     pub program_id: Pubkey, | ||||
|  | ||||
|     /// The ID of a recent ledger entry. | ||||
|     pub last_id: Hash, | ||||
| @@ -44,15 +44,15 @@ pub struct Transaction { | ||||
| impl Transaction { | ||||
|     /// Create a signed transaction from the given `Instruction`. | ||||
|     /// * `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. | ||||
|     /// * `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. | ||||
|     /// * `fee` - The transaction fee. | ||||
|     pub fn new_with_userdata( | ||||
|         from_keypair: &Keypair, | ||||
|         transaction_keys: &[Pubkey], | ||||
|         contract_id: Pubkey, | ||||
|         program_id: Pubkey, | ||||
|         userdata: Vec<u8>, | ||||
|         last_id: Hash, | ||||
|         fee: i64, | ||||
| @@ -63,7 +63,7 @@ impl Transaction { | ||||
|         let mut tx = Transaction { | ||||
|             signature: Signature::default(), | ||||
|             keys, | ||||
|             contract_id, | ||||
|             program_id, | ||||
|             last_id, | ||||
|             fee, | ||||
|             userdata, | ||||
| @@ -74,22 +74,22 @@ impl Transaction { | ||||
|     /// Create and sign a new Transaction. Used for unit-testing. | ||||
|     pub fn budget_new_taxed( | ||||
|         from_keypair: &Keypair, | ||||
|         contract: Pubkey, | ||||
|         to: Pubkey, | ||||
|         tokens: i64, | ||||
|         fee: i64, | ||||
|         last_id: Hash, | ||||
|     ) -> Self { | ||||
|         let payment = Payment { | ||||
|             tokens: tokens - fee, | ||||
|             to: contract, | ||||
|             to: to, | ||||
|         }; | ||||
|         let budget = Budget::Pay(payment); | ||||
|         let instruction = Instruction::NewContract(Contract { budget, tokens }); | ||||
|         let userdata = serialize(&instruction).unwrap(); | ||||
|         Self::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[contract], | ||||
|             BudgetContract::id(), | ||||
|             &[to], | ||||
|             BudgetProgram::id(), | ||||
|             userdata, | ||||
|             last_id, | ||||
|             fee, | ||||
| @@ -114,7 +114,7 @@ impl Transaction { | ||||
|         Self::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[contract, to], | ||||
|             BudgetContract::id(), | ||||
|             BudgetProgram::id(), | ||||
|             userdata, | ||||
|             last_id, | ||||
|             0, | ||||
| @@ -133,7 +133,7 @@ impl Transaction { | ||||
|         Self::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[contract, to], | ||||
|             BudgetContract::id(), | ||||
|             BudgetProgram::id(), | ||||
|             userdata, | ||||
|             last_id, | ||||
|             0, | ||||
| @@ -146,7 +146,7 @@ impl Transaction { | ||||
|         Self::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[], | ||||
|             BudgetContract::id(), | ||||
|             BudgetProgram::id(), | ||||
|             userdata, | ||||
|             last_id, | ||||
|             fee, | ||||
| @@ -172,58 +172,58 @@ impl Transaction { | ||||
|         Self::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[contract], | ||||
|             BudgetContract::id(), | ||||
|             BudgetProgram::id(), | ||||
|             userdata, | ||||
|             last_id, | ||||
|             0, | ||||
|         ) | ||||
|     } | ||||
|     /// Create and sign new SystemContract::CreateAccount transaction | ||||
|     /// Create and sign new SystemProgram::CreateAccount transaction | ||||
|     pub fn system_create( | ||||
|         from_keypair: &Keypair, | ||||
|         to: Pubkey, | ||||
|         last_id: Hash, | ||||
|         tokens: i64, | ||||
|         space: u64, | ||||
|         contract_id: Pubkey, | ||||
|         program_id: Pubkey, | ||||
|         fee: i64, | ||||
|     ) -> 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 | ||||
|             space, | ||||
|             contract_id, | ||||
|             program_id, | ||||
|         }; | ||||
|         Transaction::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[to], | ||||
|             SystemContract::id(), | ||||
|             SystemProgram::id(), | ||||
|             serialize(&create).unwrap(), | ||||
|             last_id, | ||||
|             fee, | ||||
|         ) | ||||
|     } | ||||
|     /// Create and sign new SystemContract::CreateAccount transaction | ||||
|     /// Create and sign new SystemProgram::CreateAccount transaction | ||||
|     pub fn system_assign( | ||||
|         from_keypair: &Keypair, | ||||
|         last_id: Hash, | ||||
|         contract_id: Pubkey, | ||||
|         program_id: Pubkey, | ||||
|         fee: i64, | ||||
|     ) -> Self { | ||||
|         let create = SystemContract::Assign { contract_id }; | ||||
|         let create = SystemProgram::Assign { program_id }; | ||||
|         Transaction::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[], | ||||
|             SystemContract::id(), | ||||
|             SystemProgram::id(), | ||||
|             serialize(&create).unwrap(), | ||||
|             last_id, | ||||
|             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 { | ||||
|         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( | ||||
|         from_keypair: &Keypair, | ||||
|         to: Pubkey, | ||||
| @@ -231,17 +231,17 @@ impl Transaction { | ||||
|         last_id: Hash, | ||||
|         fee: i64, | ||||
|     ) -> Self { | ||||
|         let create = SystemContract::Move { tokens }; | ||||
|         let create = SystemProgram::Move { tokens }; | ||||
|         Transaction::new_with_userdata( | ||||
|             from_keypair, | ||||
|             &[to], | ||||
|             SystemContract::id(), | ||||
|             SystemProgram::id(), | ||||
|             serialize(&create).unwrap(), | ||||
|             last_id, | ||||
|             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 { | ||||
|         Transaction::system_move(from_keypair, to, tokens, last_id, 0) | ||||
|     } | ||||
| @@ -249,8 +249,8 @@ impl Transaction { | ||||
|     fn get_sign_data(&self) -> Vec<u8> { | ||||
|         let mut data = serialize(&(&self.keys)).expect("serialize keys"); | ||||
|  | ||||
|         let contract_id = serialize(&(&self.contract_id)).expect("serialize contract_id"); | ||||
|         data.extend_from_slice(&contract_id); | ||||
|         let program_id = serialize(&(&self.program_id)).expect("serialize program_id"); | ||||
|         data.extend_from_slice(&program_id); | ||||
|  | ||||
|         let last_id_data = serialize(&(&self.last_id)).expect("serialize last_id"); | ||||
|         data.extend_from_slice(&last_id_data); | ||||
| @@ -367,7 +367,7 @@ mod tests { | ||||
|             keys: vec![], | ||||
|             last_id: Default::default(), | ||||
|             signature: Default::default(), | ||||
|             contract_id: Default::default(), | ||||
|             program_id: Default::default(), | ||||
|             fee: 0, | ||||
|             userdata, | ||||
|         }; | ||||
| @@ -486,7 +486,7 @@ mod tests { | ||||
|             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, | ||||
|         ]); | ||||
| @@ -494,7 +494,7 @@ mod tests { | ||||
|         let tx = Transaction::new_with_userdata( | ||||
|             keypair, | ||||
|             &[keypair.pubkey(), to], | ||||
|             contract, | ||||
|             program_id, | ||||
|             vec![1, 2, 3], | ||||
|             Hash::default(), | ||||
|             99, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user