Hoist program static methods to top-level functions

This commit is contained in:
Greg Fitzgerald
2018-11-23 13:45:34 -07:00
parent e2373ff51a
commit cd488b7d07
16 changed files with 379 additions and 384 deletions

View File

@ -6,7 +6,7 @@
use bincode::deserialize; use bincode::deserialize;
use bincode::serialize; use bincode::serialize;
use bpf_loader; use bpf_loader;
use budget_program::BudgetProgram; use budget_program;
use counter::Counter; use counter::Counter;
use entry::Entry; use entry::Entry;
use itertools::Itertools; use itertools::Itertools;
@ -34,13 +34,13 @@ use std::result;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::time::Instant; use std::time::Instant;
use storage_program::StorageProgram; use storage_program;
use system_program::{Error, SystemProgram}; use system_program;
use system_transaction::SystemTransaction; use system_transaction::SystemTransaction;
use token_program; use token_program;
use tokio::prelude::Future; use tokio::prelude::Future;
use transaction::Transaction; use transaction::Transaction;
use vote_program::VoteProgram; use vote_program;
/// The number of most recent `last_id` values that the bank will track the signatures /// The number of most recent `last_id` values that the bank will track the signatures
/// of. Once the bank discards a `last_id`, it will reject any transactions that use /// of. Once the bank discards a `last_id`, it will reject any transactions that use
@ -736,7 +736,7 @@ impl Bank {
// Verify the transaction // Verify the transaction
// Make sure that program_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_program_id != account.owner && !SystemProgram::check_id(&program_id) { if *pre_program_id != account.owner && !system_program::check_id(&program_id) {
return Err(BankError::ModifiedContractId(instruction_index as u8)); return Err(BankError::ModifiedContractId(instruction_index as u8));
} }
// 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.
@ -817,29 +817,33 @@ impl Bank {
// 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 SystemProgram::check_id(&program_id) { if system_program::check_id(&program_id) {
if let Err(err) = if let Err(err) =
SystemProgram::process_transaction(&tx, instruction_index, program_accounts) system_program::process_transaction(&tx, instruction_index, program_accounts)
{ {
let err = match err { let err = match err {
Error::ResultWithNegativeTokens(i) => BankError::ResultWithNegativeTokens(i), system_program::Error::ResultWithNegativeTokens(i) => {
BankError::ResultWithNegativeTokens(i)
}
_ => BankError::ProgramRuntimeError(instruction_index as u8), _ => BankError::ProgramRuntimeError(instruction_index as u8),
}; };
return Err(err); return Err(err);
} }
} else if BudgetProgram::check_id(&program_id) { } else if budget_program::check_id(&program_id) {
if BudgetProgram::process_transaction(&tx, instruction_index, program_accounts).is_err() if budget_program::process_transaction(&tx, instruction_index, program_accounts)
{
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
}
} else if StorageProgram::check_id(&program_id) {
if StorageProgram::process_transaction(&tx, instruction_index, program_accounts)
.is_err() .is_err()
{ {
return Err(BankError::ProgramRuntimeError(instruction_index as u8)); return Err(BankError::ProgramRuntimeError(instruction_index as u8));
} }
} else if VoteProgram::check_id(&program_id) { } else if storage_program::check_id(&program_id) {
if VoteProgram::process_transaction(&tx, instruction_index, program_accounts).is_err() { if storage_program::process_transaction(&tx, instruction_index, program_accounts)
.is_err()
{
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
}
} else if vote_program::check_id(&program_id) {
if vote_program::process_transaction(&tx, instruction_index, program_accounts).is_err()
{
return Err(BankError::ProgramRuntimeError(instruction_index as u8)); return Err(BankError::ProgramRuntimeError(instruction_index as u8));
} }
} else { } else {
@ -1233,8 +1237,8 @@ impl Bank {
{ {
// Process the first transaction // Process the first transaction
let tx = &entry1.transactions[0]; let tx = &entry1.transactions[0];
assert!(SystemProgram::check_id(tx.program_id(0)), "Invalid ledger"); assert!(system_program::check_id(tx.program_id(0)), "Invalid ledger");
assert!(SystemProgram::check_id(tx.program_id(1)), "Invalid ledger"); assert!(system_program::check_id(tx.program_id(1)), "Invalid ledger");
let mut instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap(); let mut instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap();
let mint_deposit = if let SystemInstruction::Move { tokens } = instruction { let mint_deposit = if let SystemInstruction::Move { tokens } = instruction {
Some(tokens) Some(tokens)
@ -1309,10 +1313,10 @@ impl Bank {
} }
pub fn read_balance(account: &Account) -> u64 { pub fn read_balance(account: &Account) -> u64 {
if SystemProgram::check_id(&account.owner) { if system_program::check_id(&account.owner) {
SystemProgram::get_balance(account) system_program::get_balance(account)
} else if BudgetProgram::check_id(&account.owner) { } else if budget_program::check_id(&account.owner) {
BudgetProgram::get_balance(account) budget_program::get_balance(account)
} else { } else {
account.tokens account.tokens
} }
@ -1498,7 +1502,6 @@ impl Bank {
mod tests { mod tests {
use super::*; use super::*;
use bincode::serialize; use bincode::serialize;
use budget_program::BudgetProgram;
use entry::next_entry; use entry::next_entry;
use entry::Entry; use entry::Entry;
use jsonrpc_macros::pubsub::{Subscriber, SubscriptionId}; use jsonrpc_macros::pubsub::{Subscriber, SubscriptionId};
@ -1598,7 +1601,7 @@ mod tests {
&[key1, key2], &[key1, key2],
mint.last_id(), mint.last_id(),
0, 0,
vec![SystemProgram::id()], vec![system_program::id()],
instructions, instructions,
); );
let res = bank.process_transactions(&vec![t1.clone()]); let res = bank.process_transactions(&vec![t1.clone()]);
@ -2021,7 +2024,7 @@ mod tests {
last_id, last_id,
1, 1,
16, 16,
BudgetProgram::id(), budget_program::id(),
0, 0,
); );
bank.process_transaction(&tx).unwrap(); bank.process_transaction(&tx).unwrap();
@ -2253,26 +2256,26 @@ mod tests {
0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
assert_eq!(SystemProgram::id(), system); assert_eq!(system_program::id(), system);
assert_eq!(native_loader::id(), native); assert_eq!(native_loader::id(), native);
assert_eq!(bpf_loader::id(), bpf); assert_eq!(bpf_loader::id(), bpf);
assert_eq!(BudgetProgram::id(), budget); assert_eq!(budget_program::id(), budget);
assert_eq!(StorageProgram::id(), storage); assert_eq!(storage_program::id(), storage);
assert_eq!(token_program::id(), token); assert_eq!(token_program::id(), token);
assert_eq!(VoteProgram::id(), vote); assert_eq!(vote_program::id(), vote);
} }
#[test] #[test]
fn test_program_id_uniqueness() { fn test_program_id_uniqueness() {
let mut unique = HashSet::new(); let mut unique = HashSet::new();
let ids = vec![ let ids = vec![
SystemProgram::id(), system_program::id(),
native_loader::id(), native_loader::id(),
bpf_loader::id(), bpf_loader::id(),
BudgetProgram::id(), budget_program::id(),
StorageProgram::id(), storage_program::id(),
token_program::id(), token_program::id(),
VoteProgram::id(), vote_program::id(),
]; ];
assert!(ids.into_iter().all(move |id| unique.insert(id))); assert!(ids.into_iter().all(move |id| unique.insert(id)));
} }

View File

@ -35,17 +35,122 @@ const BUDGET_PROGRAM_ID: [u8; 32] = [
0, 0,
]; ];
pub fn id() -> Pubkey {
Pubkey::new(&BUDGET_PROGRAM_ID)
}
pub fn check_id(program_id: &Pubkey) -> bool {
program_id.as_ref() == BUDGET_PROGRAM_ID
}
fn apply_debits(
tx: &Transaction,
instruction_index: usize,
accounts: &mut [&mut Account],
instruction: &Instruction,
) -> Result<(), BudgetError> {
if !accounts[0].userdata.is_empty() {
trace!("source is pending");
return Err(BudgetError::SourceIsPendingContract);
}
match instruction {
Instruction::NewBudget(expr) => {
let expr = expr.clone();
if let Some(payment) = expr.final_payment() {
accounts[1].tokens += payment.tokens;
Ok(())
} else {
let existing = BudgetProgram::deserialize(&accounts[1].userdata).ok();
if Some(true) == existing.map(|x| x.initialized) {
trace!("contract already exists");
Err(BudgetError::ContractAlreadyExists)
} else {
let mut program = BudgetProgram::default();
program.pending_budget = Some(expr);
accounts[1].tokens += accounts[0].tokens;
accounts[0].tokens = 0;
program.initialized = true;
program.serialize(&mut accounts[1].userdata)
}
}
}
Instruction::ApplyTimestamp(dt) => {
if let Ok(mut program) = BudgetProgram::deserialize(&accounts[1].userdata) {
if !program.is_pending() {
Err(BudgetError::ContractNotPending)
} else if !program.initialized {
trace!("contract is uninitialized");
Err(BudgetError::UninitializedContract)
} else {
trace!("apply timestamp");
program.apply_timestamp(tx, instruction_index, accounts, *dt)?;
trace!("apply timestamp committed");
program.serialize(&mut accounts[1].userdata)
}
} else {
Err(BudgetError::UninitializedContract)
}
}
Instruction::ApplySignature => {
if let Ok(mut program) = BudgetProgram::deserialize(&accounts[1].userdata) {
if !program.is_pending() {
Err(BudgetError::ContractNotPending)
} else if !program.initialized {
trace!("contract is uninitialized");
Err(BudgetError::UninitializedContract)
} else {
trace!("apply signature");
program.apply_signature(tx, instruction_index, accounts)?;
trace!("apply signature committed");
program.serialize(&mut accounts[1].userdata)
}
} else {
Err(BudgetError::UninitializedContract)
}
}
}
}
/// Budget DSL contract interface
/// * tx - the transaction
/// * accounts[0] - The source of the tokens
/// * accounts[1] - The contract context. Once the contract has been completed, the tokens can
/// be spent from this account .
pub fn process_transaction(
tx: &Transaction,
instruction_index: usize,
accounts: &mut [&mut Account],
) -> Result<(), BudgetError> {
if let Ok(instruction) = deserialize(tx.userdata(instruction_index)) {
trace!("process_transaction: {:?}", instruction);
apply_debits(tx, instruction_index, accounts, &instruction)
} else {
info!(
"Invalid transaction userdata: {:?}",
tx.userdata(instruction_index)
);
Err(BudgetError::UserdataDeserializeFailure)
}
}
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
pub fn get_balance(account: &Account) -> u64 {
if let Ok(program) = deserialize(&account.userdata) {
let program: BudgetProgram = program;
if program.is_pending() {
0
} else {
account.tokens
}
} else {
account.tokens
}
}
impl BudgetProgram { impl BudgetProgram {
fn is_pending(&self) -> bool { fn is_pending(&self) -> bool {
self.pending_budget != None self.pending_budget != None
} }
pub fn id() -> Pubkey {
Pubkey::new(&BUDGET_PROGRAM_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 /// Process a Witness Signature. Any payment plans waiting on this signature
/// will progress one step. /// will progress one step.
fn apply_signature( fn apply_signature(
@ -109,73 +214,6 @@ impl BudgetProgram {
Ok(()) Ok(())
} }
fn apply_debits(
tx: &Transaction,
instruction_index: usize,
accounts: &mut [&mut Account],
instruction: &Instruction,
) -> Result<(), BudgetError> {
if !accounts[0].userdata.is_empty() {
trace!("source is pending");
return Err(BudgetError::SourceIsPendingContract);
}
match instruction {
Instruction::NewBudget(expr) => {
let expr = expr.clone();
if let Some(payment) = expr.final_payment() {
accounts[1].tokens += payment.tokens;
Ok(())
} else {
let existing = Self::deserialize(&accounts[1].userdata).ok();
if Some(true) == existing.map(|x| x.initialized) {
trace!("contract already exists");
Err(BudgetError::ContractAlreadyExists)
} else {
let mut program = BudgetProgram::default();
program.pending_budget = Some(expr);
accounts[1].tokens += accounts[0].tokens;
accounts[0].tokens = 0;
program.initialized = true;
program.serialize(&mut accounts[1].userdata)
}
}
}
Instruction::ApplyTimestamp(dt) => {
if let Ok(mut program) = Self::deserialize(&accounts[1].userdata) {
if !program.is_pending() {
Err(BudgetError::ContractNotPending)
} else if !program.initialized {
trace!("contract is uninitialized");
Err(BudgetError::UninitializedContract)
} else {
trace!("apply timestamp");
program.apply_timestamp(tx, instruction_index, accounts, *dt)?;
trace!("apply timestamp committed");
program.serialize(&mut accounts[1].userdata)
}
} else {
Err(BudgetError::UninitializedContract)
}
}
Instruction::ApplySignature => {
if let Ok(mut program) = Self::deserialize(&accounts[1].userdata) {
if !program.is_pending() {
Err(BudgetError::ContractNotPending)
} else if !program.initialized {
trace!("contract is uninitialized");
Err(BudgetError::UninitializedContract)
} else {
trace!("apply signature");
program.apply_signature(tx, instruction_index, accounts)?;
trace!("apply signature committed");
program.serialize(&mut accounts[1].userdata)
}
} else {
Err(BudgetError::UninitializedContract)
}
}
}
}
fn serialize(&self, output: &mut [u8]) -> Result<(), BudgetError> { fn serialize(&self, output: &mut [u8]) -> Result<(), BudgetError> {
let len = serialized_size(self).unwrap() as u64; let len = serialized_size(self).unwrap() as u64;
if output.len() < len as usize { if output.len() < len as usize {
@ -211,47 +249,11 @@ impl BudgetProgram {
} }
deserialize(&input[8..8 + len as usize]) deserialize(&input[8..8 + len as usize])
} }
/// Budget DSL contract interface
/// * tx - the transaction
/// * accounts[0] - The source of the tokens
/// * accounts[1] - The contract context. Once the contract has been completed, the tokens can
/// be spent from this account .
pub fn process_transaction(
tx: &Transaction,
instruction_index: usize,
accounts: &mut [&mut Account],
) -> Result<(), BudgetError> {
if let Ok(instruction) = deserialize(tx.userdata(instruction_index)) {
trace!("process_transaction: {:?}", instruction);
Self::apply_debits(tx, instruction_index, accounts, &instruction)
} else {
info!(
"Invalid transaction userdata: {:?}",
tx.userdata(instruction_index)
);
Err(BudgetError::UserdataDeserializeFailure)
}
}
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
pub fn get_balance(account: &Account) -> u64 {
if let Ok(program) = deserialize(&account.userdata) {
let program: BudgetProgram = program;
if program.is_pending() {
0
} else {
account.tokens
}
} else {
account.tokens
}
}
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*;
use bincode::serialize; use bincode::serialize;
use budget_program::{BudgetError, BudgetProgram};
use budget_transaction::BudgetTransaction; use budget_transaction::BudgetTransaction;
use chrono::prelude::{DateTime, NaiveDate, Utc}; use chrono::prelude::{DateTime, NaiveDate, Utc};
use signature::{GenKeys, Keypair, KeypairUtil}; use signature::{GenKeys, Keypair, KeypairUtil};
@ -262,11 +264,11 @@ mod test {
fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<(), BudgetError> { fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<(), BudgetError> {
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect(); let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
BudgetProgram::process_transaction(&tx, 0, &mut refs[..]) super::process_transaction(&tx, 0, &mut refs[..])
} }
#[test] #[test]
fn test_serializer() { fn test_serializer() {
let mut a = Account::new(0, 512, BudgetProgram::id()); let mut a = Account::new(0, 512, id());
let b = BudgetProgram::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();
@ -277,7 +279,7 @@ mod test {
#[test] #[test]
fn test_serializer_userdata_too_small() { fn test_serializer_userdata_too_small() {
let mut a = Account::new(0, 1, BudgetProgram::id()); let mut a = Account::new(0, 1, id());
let b = BudgetProgram::default(); let b = BudgetProgram::default();
assert_eq!( assert_eq!(
b.serialize(&mut a.userdata), b.serialize(&mut a.userdata),
@ -286,17 +288,14 @@ mod test {
} }
#[test] #[test]
fn test_invalid_instruction() { fn test_invalid_instruction() {
let mut accounts = vec![ let mut accounts = vec![Account::new(1, 0, id()), Account::new(0, 512, id())];
Account::new(1, 0, BudgetProgram::id()),
Account::new(0, 512, BudgetProgram::id()),
];
let from = Keypair::new(); let from = Keypair::new();
let contract = Keypair::new(); let contract = Keypair::new();
let userdata = (1u8, 2u8, 3u8); let userdata = (1u8, 2u8, 3u8);
let tx = Transaction::new( let tx = Transaction::new(
&from, &from,
&[contract.pubkey()], &[contract.pubkey()],
BudgetProgram::id(), id(),
&userdata, &userdata,
Hash::default(), Hash::default(),
0, 0,
@ -307,9 +306,9 @@ mod test {
#[test] #[test]
fn test_unsigned_witness_key() { fn test_unsigned_witness_key() {
let mut accounts = vec![ let mut accounts = vec![
Account::new(1, 0, BudgetProgram::id()), Account::new(1, 0, id()),
Account::new(0, 512, BudgetProgram::id()), Account::new(0, 512, id()),
Account::new(0, 0, BudgetProgram::id()), Account::new(0, 0, id()),
]; ];
// Initialize BudgetProgram // Initialize BudgetProgram
@ -346,9 +345,9 @@ mod test {
#[test] #[test]
fn test_unsigned_timestamp() { fn test_unsigned_timestamp() {
let mut accounts = vec![ let mut accounts = vec![
Account::new(1, 0, BudgetProgram::id()), Account::new(1, 0, id()),
Account::new(0, 512, BudgetProgram::id()), Account::new(0, 512, id()),
Account::new(0, 0, BudgetProgram::id()), Account::new(0, 0, id()),
]; ];
// Initialize BudgetProgram // Initialize BudgetProgram
@ -386,9 +385,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, BudgetProgram::id()), Account::new(1, 0, id()),
Account::new(0, 512, BudgetProgram::id()), Account::new(0, 512, id()),
Account::new(0, 0, BudgetProgram::id()), Account::new(0, 0, id()),
]; ];
let from_account = 0; let from_account = 0;
let contract_account = 1; let contract_account = 1;
@ -462,9 +461,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, BudgetProgram::id()), Account::new(1, 0, id()),
Account::new(0, 512, BudgetProgram::id()), Account::new(0, 512, id()),
Account::new(0, 0, BudgetProgram::id()), Account::new(0, 0, id()),
]; ];
let from_account = 0; let from_account = 0;
let contract_account = 1; let contract_account = 1;
@ -532,9 +531,9 @@ mod test {
#[test] #[test]
fn test_userdata_too_small() { fn test_userdata_too_small() {
let mut accounts = vec![ let mut accounts = vec![
Account::new(1, 0, BudgetProgram::id()), Account::new(1, 0, id()),
Account::new(1, 0, BudgetProgram::id()), // <== userdata is 0, which is not enough Account::new(1, 0, id()), // <== userdata is 0, which is not enough
Account::new(1, 0, BudgetProgram::id()), Account::new(1, 0, id()),
]; ];
let from = Keypair::new(); let from = Keypair::new();
let contract = Keypair::new(); let contract = Keypair::new();

View File

@ -3,7 +3,7 @@
use bincode::deserialize; use bincode::deserialize;
use budget_expr::{BudgetExpr, Condition}; use budget_expr::{BudgetExpr, Condition};
use budget_instruction::Instruction; use budget_instruction::Instruction;
use budget_program::BudgetProgram; use budget_program;
use chrono::prelude::*; use chrono::prelude::*;
use payment_plan::Payment; use payment_plan::Payment;
use signature::{Keypair, KeypairUtil}; use signature::{Keypair, KeypairUtil};
@ -85,7 +85,7 @@ impl BudgetTransaction for Transaction {
}; };
let budget_instruction = Instruction::NewBudget(BudgetExpr::Pay(payment)); let budget_instruction = Instruction::NewBudget(BudgetExpr::Pay(payment));
let program_ids = vec![Pubkey::new(&SYSTEM_PROGRAM_ID), BudgetProgram::id()]; let program_ids = vec![Pubkey::new(&SYSTEM_PROGRAM_ID), budget_program::id()];
let instructions = vec![ let instructions = vec![
transaction::Instruction::new(0, &system_instruction, vec![0, 1]), transaction::Instruction::new(0, &system_instruction, vec![0, 1]),
@ -119,7 +119,7 @@ impl BudgetTransaction for Transaction {
Self::new( Self::new(
from_keypair, from_keypair,
&[contract, to], &[contract, to],
BudgetProgram::id(), budget_program::id(),
&instruction, &instruction,
last_id, last_id,
0, 0,
@ -137,7 +137,7 @@ impl BudgetTransaction for Transaction {
Self::new( Self::new(
from_keypair, from_keypair,
&[contract, to], &[contract, to],
BudgetProgram::id(), budget_program::id(),
&instruction, &instruction,
last_id, last_id,
0, 0,
@ -167,7 +167,7 @@ impl BudgetTransaction for Transaction {
Self::new( Self::new(
from_keypair, from_keypair,
&[contract], &[contract],
BudgetProgram::id(), budget_program::id(),
&instruction, &instruction,
last_id, last_id,
0, 0,
@ -195,7 +195,7 @@ impl BudgetTransaction for Transaction {
Self::new( Self::new(
from_keypair, from_keypair,
&[contract], &[contract],
BudgetProgram::id(), budget_program::id(),
&instruction, &instruction,
last_id, last_id,
0, 0,

View File

@ -13,7 +13,7 @@ use std::sync::Arc;
use std::thread::sleep; use std::thread::sleep;
use std::thread::{self, Builder, JoinHandle}; use std::thread::{self, Builder, JoinHandle};
use std::time::Duration; use std::time::Duration;
use vote_program::VoteProgram; use vote_program::{self, VoteProgram};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum FinalityError { pub enum FinalityError {
@ -46,7 +46,7 @@ impl ComputeLeaderFinalityService {
.filter_map(|account| { .filter_map(|account| {
// Filter out any accounts that don't belong to the VoteProgram // Filter out any accounts that don't belong to the VoteProgram
// by returning None // by returning None
if VoteProgram::check_id(&account.owner) { if vote_program::check_id(&account.owner) {
if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) { if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) {
let validator_stake = bank.get_stake(&vote_state.node_id); let validator_stake = bank.get_stake(&vote_state.node_id);
total_stake += validator_stake; total_stake += validator_stake;

View File

@ -14,7 +14,7 @@ use std::collections::HashSet;
use std::io::Cursor; use std::io::Cursor;
use system_transaction::SystemTransaction; use system_transaction::SystemTransaction;
use transaction::Transaction; use transaction::Transaction;
use vote_program::{Vote, VoteProgram}; use vote_program::{self, Vote, VoteProgram};
use vote_transaction::VoteTransaction; use vote_transaction::VoteTransaction;
pub const DEFAULT_BOOTSTRAP_HEIGHT: u64 = 1000; pub const DEFAULT_BOOTSTRAP_HEIGHT: u64 = 1000;
@ -309,7 +309,7 @@ impl LeaderScheduler {
.accounts .accounts
.values() .values()
.filter_map(|account| { .filter_map(|account| {
if VoteProgram::check_id(&account.owner) { if vote_program::check_id(&account.owner) {
if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) { if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) {
return vote_state return vote_state
.votes .votes

View File

@ -109,14 +109,14 @@ mod tests {
use bincode::deserialize; use bincode::deserialize;
use ledger::Block; use ledger::Block;
use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::system_instruction::SystemInstruction;
use system_program::SystemProgram; use system_program;
#[test] #[test]
fn test_create_transactions() { fn test_create_transactions() {
let mut transactions = Mint::new(100).create_transaction().into_iter(); let mut transactions = Mint::new(100).create_transaction().into_iter();
let tx = transactions.next().unwrap(); let tx = transactions.next().unwrap();
assert_eq!(tx.instructions.len(), 1); assert_eq!(tx.instructions.len(), 1);
assert!(SystemProgram::check_id(tx.program_id(0))); assert!(system_program::check_id(tx.program_id(0)));
let instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap(); let instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap();
if let SystemInstruction::Move { tokens } = instruction { if let SystemInstruction::Move { tokens } = instruction {
assert_eq!(tokens, 100); assert_eq!(tokens, 100);
@ -133,8 +133,8 @@ mod tests {
.into_iter(); .into_iter();
let tx = transactions.next().unwrap(); let tx = transactions.next().unwrap();
assert_eq!(tx.instructions.len(), 2); assert_eq!(tx.instructions.len(), 2);
assert!(SystemProgram::check_id(tx.program_id(0))); assert!(system_program::check_id(tx.program_id(0)));
assert!(SystemProgram::check_id(tx.program_id(1))); assert!(system_program::check_id(tx.program_id(1)));
let instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap(); let instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap();
if let SystemInstruction::Move { tokens } = instruction { if let SystemInstruction::Move { tokens } = instruction {
assert_eq!(tokens, 100); assert_eq!(tokens, 100);

View File

@ -246,7 +246,7 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use budget_program::BudgetProgram; use budget_program;
use budget_transaction::BudgetTransaction; use budget_transaction::BudgetTransaction;
use jsonrpc_core::futures::sync::mpsc; use jsonrpc_core::futures::sync::mpsc;
use mint::Mint; use mint::Mint;
@ -400,7 +400,7 @@ mod tests {
let witness = Keypair::new(); let witness = Keypair::new();
let contract_funds = Keypair::new(); let contract_funds = Keypair::new();
let contract_state = Keypair::new(); let contract_state = Keypair::new();
let budget_program_id = BudgetProgram::id(); let budget_program_id = budget_program::id();
let loader = Pubkey::default(); // TODO let loader = Pubkey::default(); // TODO
let executable = false; // TODO let executable = false; // TODO
let bank = Bank::new(&alice); let bank = Bank::new(&alice);

View File

@ -323,13 +323,13 @@ pub fn make_packet_from_transaction(tx: Transaction) -> Packet {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use bincode::serialize; use bincode::serialize;
use budget_program::BudgetProgram; use budget_program;
use packet::{Packet, SharedPackets}; use packet::{Packet, SharedPackets};
use signature::{Keypair, KeypairUtil}; use signature::{Keypair, KeypairUtil};
use sigverify; use sigverify;
use solana_sdk::hash::Hash; use solana_sdk::hash::Hash;
use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::system_instruction::SystemInstruction;
use system_program::SystemProgram; use system_program;
use system_transaction::{memfind, test_tx}; use system_transaction::{memfind, test_tx};
use transaction; use transaction;
use transaction::Transaction; use transaction::Transaction;
@ -429,7 +429,7 @@ mod tests {
let system_instruction = SystemInstruction::Move { tokens }; let system_instruction = SystemInstruction::Move { tokens };
let program_ids = vec![SystemProgram::id(), BudgetProgram::id()]; let program_ids = vec![system_program::id(), budget_program::id()];
let instructions = vec![transaction::Instruction::new( let instructions = vec![transaction::Instruction::new(
0, 0,

View File

@ -22,34 +22,32 @@ const STORAGE_PROGRAM_ID: [u8; 32] = [
0, 0,
]; ];
impl StorageProgram { pub fn check_id(program_id: &Pubkey) -> bool {
pub fn check_id(program_id: &Pubkey) -> bool { program_id.as_ref() == STORAGE_PROGRAM_ID
program_id.as_ref() == STORAGE_PROGRAM_ID }
}
pub fn id() -> Pubkey { pub fn id() -> Pubkey {
Pubkey::new(&STORAGE_PROGRAM_ID) Pubkey::new(&STORAGE_PROGRAM_ID)
} }
pub fn get_balance(account: &Account) -> u64 { pub fn get_balance(account: &Account) -> u64 {
account.tokens account.tokens
} }
pub fn process_transaction( pub fn process_transaction(
tx: &Transaction, tx: &Transaction,
pix: usize, pix: usize,
_accounts: &mut [&mut Account], _accounts: &mut [&mut Account],
) -> Result<(), StorageError> { ) -> Result<(), StorageError> {
if let Ok(syscall) = deserialize(tx.userdata(pix)) { if let Ok(syscall) = deserialize(tx.userdata(pix)) {
match syscall { match syscall {
StorageProgram::SubmitMiningProof { sha_state } => { StorageProgram::SubmitMiningProof { sha_state } => {
info!("Mining proof submitted with state {:?}", sha_state); info!("Mining proof submitted with state {:?}", sha_state);
return Ok(()); return Ok(());
}
} }
} else {
return Err(StorageError::InvalidUserData);
} }
} else {
return Err(StorageError::InvalidUserData);
} }
} }
@ -62,14 +60,7 @@ mod test {
#[test] #[test]
fn test_storage_tx() { fn test_storage_tx() {
let keypair = Keypair::new(); let keypair = Keypair::new();
let tx = Transaction::new( let tx = Transaction::new(&keypair, &[], id(), &(), Default::default(), 0);
&keypair, assert!(process_transaction(&tx, 0, &mut []).is_err());
&[],
StorageProgram::id(),
&(),
Default::default(),
0,
);
assert!(StorageProgram::process_transaction(&tx, 0, &mut []).is_err());
} }
} }

View File

@ -18,7 +18,7 @@ use std::sync::mpsc::RecvTimeoutError;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::thread::{self, Builder, JoinHandle}; use std::thread::{self, Builder, JoinHandle};
use std::time::Duration; use std::time::Duration;
use vote_program::VoteProgram; use vote_program;
// Block of hash answers to validate against // Block of hash answers to validate against
// Vec of [ledger blocks] x [keys] // Vec of [ledger blocks] x [keys]
@ -215,7 +215,7 @@ impl StorageStage {
// the storage_keys with their signatures. // the storage_keys with their signatures.
for tx in entry.transactions { for tx in entry.transactions {
for program_id in tx.program_ids { for program_id in tx.program_ids {
if VoteProgram::check_id(&program_id) { if vote_program::check_id(&program_id) {
debug!( debug!(
"generating storage_keys from votes current_key_idx: {}", "generating storage_keys from votes current_key_idx: {}",
*current_key_idx *current_key_idx

View File

@ -1,6 +1,6 @@
use signature::{Keypair, KeypairUtil}; use signature::{Keypair, KeypairUtil};
use solana_sdk::hash::Hash; use solana_sdk::hash::Hash;
use storage_program::StorageProgram; use storage_program::{self, StorageProgram};
use transaction::Transaction; use transaction::Transaction;
pub trait StorageTransaction { pub trait StorageTransaction {
@ -13,7 +13,7 @@ impl StorageTransaction for Transaction {
Transaction::new( Transaction::new(
from_keypair, from_keypair,
&[from_keypair.pubkey()], &[from_keypair.pubkey()],
StorageProgram::id(), storage_program::id(),
&program, &program,
last_id, last_id,
0, 0,

View File

@ -23,86 +23,82 @@ impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
pub struct SystemProgram {}
pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32]; pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32];
impl SystemProgram { pub fn check_id(program_id: &Pubkey) -> bool {
pub fn check_id(program_id: &Pubkey) -> bool { program_id.as_ref() == SYSTEM_PROGRAM_ID
program_id.as_ref() == SYSTEM_PROGRAM_ID }
}
pub fn id() -> Pubkey { pub fn id() -> Pubkey {
Pubkey::new(&SYSTEM_PROGRAM_ID) Pubkey::new(&SYSTEM_PROGRAM_ID)
} }
pub fn get_balance(account: &Account) -> u64 { pub fn get_balance(account: &Account) -> u64 {
account.tokens account.tokens
} }
pub fn process_transaction( pub fn process_transaction(
tx: &Transaction, tx: &Transaction,
pix: usize, pix: usize,
accounts: &mut [&mut Account], accounts: &mut [&mut Account],
) -> Result<()> { ) -> Result<()> {
if let Ok(syscall) = deserialize(tx.userdata(pix)) { if let Ok(syscall) = deserialize(tx.userdata(pix)) {
trace!("process_transaction: {:?}", syscall); trace!("process_transaction: {:?}", syscall);
match syscall { match syscall {
SystemInstruction::CreateAccount { SystemInstruction::CreateAccount {
tokens, tokens,
space, space,
program_id, program_id,
} => { } => {
if !Self::check_id(&accounts[0].owner) { if !check_id(&accounts[0].owner) {
info!("Invalid account[0] owner"); info!("Invalid account[0] owner");
Err(Error::InvalidArgument)?; Err(Error::InvalidArgument)?;
} }
if space > 0 if space > 0 && (!accounts[1].userdata.is_empty() || !check_id(&accounts[1].owner))
&& (!accounts[1].userdata.is_empty() || !Self::check_id(&accounts[1].owner)) {
{ info!("Invalid account[1]");
info!("Invalid account[1]"); Err(Error::InvalidArgument)?;
Err(Error::InvalidArgument)?;
}
if tokens > accounts[0].tokens {
info!("Insufficient tokens in account[0]");
Err(Error::ResultWithNegativeTokens(pix as u8))?;
}
accounts[0].tokens -= tokens;
accounts[1].tokens += tokens;
accounts[1].owner = program_id;
accounts[1].userdata = vec![0; space as usize];
accounts[1].executable = false;
accounts[1].loader = Pubkey::default();
} }
SystemInstruction::Assign { program_id } => { if tokens > accounts[0].tokens {
if !Self::check_id(&accounts[0].owner) { info!("Insufficient tokens in account[0]");
Err(Error::AssignOfUnownedAccount)?; Err(Error::ResultWithNegativeTokens(pix as u8))?;
}
accounts[0].owner = program_id;
}
SystemInstruction::Move { tokens } => {
//bank should be verifying correctness
if tokens > accounts[0].tokens {
info!("Insufficient tokens in account[0]");
Err(Error::ResultWithNegativeTokens(pix as u8))?;
}
accounts[0].tokens -= tokens;
accounts[1].tokens += tokens;
}
SystemInstruction::Spawn => {
if !accounts[0].executable || accounts[0].loader != Pubkey::default() {
Err(Error::AccountNotFinalized)?;
}
accounts[0].loader = accounts[0].owner;
accounts[0].owner = tx.account_keys[0];
} }
accounts[0].tokens -= tokens;
accounts[1].tokens += tokens;
accounts[1].owner = program_id;
accounts[1].userdata = vec![0; space as usize];
accounts[1].executable = false;
accounts[1].loader = Pubkey::default();
}
SystemInstruction::Assign { program_id } => {
if !check_id(&accounts[0].owner) {
Err(Error::AssignOfUnownedAccount)?;
}
accounts[0].owner = program_id;
}
SystemInstruction::Move { tokens } => {
//bank should be verifying correctness
if tokens > accounts[0].tokens {
info!("Insufficient tokens in account[0]");
Err(Error::ResultWithNegativeTokens(pix as u8))?;
}
accounts[0].tokens -= tokens;
accounts[1].tokens += tokens;
}
SystemInstruction::Spawn => {
if !accounts[0].executable || accounts[0].loader != Pubkey::default() {
Err(Error::AccountNotFinalized)?;
}
accounts[0].loader = accounts[0].owner;
accounts[0].owner = tx.account_keys[0];
} }
Ok(())
} else {
info!("Invalid transaction userdata: {:?}", tx.userdata(pix));
Err(Error::InvalidArgument)
} }
Ok(())
} else {
info!("Invalid transaction userdata: {:?}", tx.userdata(pix));
Err(Error::InvalidArgument)
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -110,13 +106,12 @@ mod test {
use solana_sdk::account::Account; use solana_sdk::account::Account;
use solana_sdk::hash::Hash; use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use system_program::SystemProgram;
use system_transaction::SystemTransaction; use system_transaction::SystemTransaction;
use transaction::Transaction; use transaction::Transaction;
fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<()> { fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<()> {
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect(); let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
SystemProgram::process_transaction(&tx, 0, &mut refs[..]) super::process_transaction(&tx, 0, &mut refs[..])
} }
#[test] #[test]
@ -246,7 +241,7 @@ mod test {
#[test] #[test]
fn test_sdk_serialize() { fn test_sdk_serialize() {
let keypair = Keypair::new(); let keypair = Keypair::new();
use budget_program::BudgetProgram; use budget_program;
// CreateAccount // CreateAccount
let tx = Transaction::system_create( let tx = Transaction::system_create(
@ -255,7 +250,7 @@ mod test {
Hash::default(), Hash::default(),
111, 111,
222, 222,
BudgetProgram::id(), budget_program::id(),
0, 0,
); );
@ -287,7 +282,7 @@ mod test {
); );
// Assign // Assign
let tx = Transaction::system_assign(&keypair, Hash::default(), BudgetProgram::id(), 0); let tx = Transaction::system_assign(&keypair, Hash::default(), budget_program::id(), 0);
assert_eq!( assert_eq!(
tx.userdata(0).to_vec(), tx.userdata(0).to_vec(),
vec![ vec![

View File

@ -4,7 +4,7 @@ use signature::{Keypair, KeypairUtil};
use solana_sdk::hash::Hash; use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::system_instruction::SystemInstruction;
use system_program::SystemProgram; use system_program;
use transaction::{Instruction, Transaction}; use transaction::{Instruction, Transaction};
@ -60,7 +60,7 @@ impl SystemTransaction for Transaction {
Transaction::new( Transaction::new(
from_keypair, from_keypair,
&[to], &[to],
SystemProgram::id(), system_program::id(),
&create, &create,
last_id, last_id,
fee, fee,
@ -72,7 +72,7 @@ impl SystemTransaction for Transaction {
Transaction::new( Transaction::new(
from_keypair, from_keypair,
&[], &[],
SystemProgram::id(), system_program::id(),
&assign, &assign,
last_id, last_id,
fee, fee,
@ -94,7 +94,7 @@ impl SystemTransaction for Transaction {
Transaction::new( Transaction::new(
from_keypair, from_keypair,
&[to], &[to],
SystemProgram::id(), system_program::id(),
&move_tokens, &move_tokens,
last_id, last_id,
fee, fee,
@ -116,14 +116,21 @@ impl SystemTransaction for Transaction {
&to_keys, &to_keys,
last_id, last_id,
fee, fee,
vec![SystemProgram::id()], vec![system_program::id()],
instructions, instructions,
) )
} }
/// Create and sign new SystemInstruction::Spawn transaction /// Create and sign new SystemInstruction::Spawn transaction
fn system_spawn(from_keypair: &Keypair, last_id: Hash, fee: u64) -> Self { fn system_spawn(from_keypair: &Keypair, last_id: Hash, fee: u64) -> Self {
let spawn = SystemInstruction::Spawn; let spawn = SystemInstruction::Spawn;
Transaction::new(from_keypair, &[], SystemProgram::id(), &spawn, last_id, fee) Transaction::new(
from_keypair,
&[],
system_program::id(),
&spawn,
last_id,
fee,
)
} }
} }

View File

@ -56,15 +56,77 @@ const VOTE_PROGRAM_ID: [u8; 32] = [
0, 0,
]; ];
pub fn check_id(program_id: &Pubkey) -> bool {
program_id.as_ref() == VOTE_PROGRAM_ID
}
pub fn id() -> Pubkey {
Pubkey::new(&VOTE_PROGRAM_ID)
}
pub fn process_transaction(
tx: &Transaction,
instruction_index: usize,
accounts: &mut [&mut Account],
) -> Result<()> {
match deserialize(tx.userdata(instruction_index)) {
Ok(VoteInstruction::RegisterAccount) => {
// TODO: a single validator could register multiple "vote accounts"
// which would clutter the "accounts" structure. See github issue 1654.
accounts[1].owner = id();
let mut vote_state = VoteProgram {
votes: VecDeque::new(),
node_id: *tx.from(),
};
vote_state.serialize(&mut accounts[1].userdata)?;
Ok(())
}
Ok(VoteInstruction::NewVote(vote)) => {
if !check_id(&accounts[0].owner) {
error!("accounts[0] is not assigned to the VOTE_PROGRAM");
Err(Error::InvalidArguments)?;
}
let mut vote_state = VoteProgram::deserialize(&accounts[0].userdata)?;
// TODO: Integrity checks
// a) Verify the vote's bank hash matches what is expected
// b) Verify vote is older than previous votes
// Only keep around the most recent MAX_VOTE_HISTORY votes
if vote_state.votes.len() == MAX_VOTE_HISTORY {
vote_state.votes.pop_front();
}
vote_state.votes.push_back(vote);
vote_state.serialize(&mut accounts[0].userdata)?;
Ok(())
}
Err(_) => {
info!(
"Invalid vote transaction userdata: {:?}",
tx.userdata(instruction_index)
);
Err(Error::UserdataDeserializeFailure)
}
}
}
pub fn get_max_size() -> usize {
// Upper limit on the size of the Vote State. Equal to
// sizeof(VoteProgram) + MAX_VOTE_HISTORY * sizeof(Vote) +
// 32 (the size of the Pubkey) + 2 (2 bytes for the size)
mem::size_of::<VoteProgram>()
+ MAX_VOTE_HISTORY * mem::size_of::<Vote>()
+ mem::size_of::<Pubkey>()
+ mem::size_of::<u16>()
}
impl VoteProgram { impl VoteProgram {
pub fn check_id(program_id: &Pubkey) -> bool {
program_id.as_ref() == VOTE_PROGRAM_ID
}
pub fn id() -> Pubkey {
Pubkey::new(&VOTE_PROGRAM_ID)
}
pub fn deserialize(input: &[u8]) -> Result<VoteProgram> { pub fn deserialize(input: &[u8]) -> Result<VoteProgram> {
let len = LittleEndian::read_u16(&input[0..2]) as usize; let len = LittleEndian::read_u16(&input[0..2]) as usize;
@ -95,68 +157,6 @@ impl VoteProgram {
output[2..=serialized_len as usize + 1].clone_from_slice(&self_serialized); output[2..=serialized_len as usize + 1].clone_from_slice(&self_serialized);
Ok(()) Ok(())
} }
pub fn process_transaction(
tx: &Transaction,
instruction_index: usize,
accounts: &mut [&mut Account],
) -> Result<()> {
match deserialize(tx.userdata(instruction_index)) {
Ok(VoteInstruction::RegisterAccount) => {
// TODO: a single validator could register multiple "vote accounts"
// which would clutter the "accounts" structure. See github issue 1654.
accounts[1].owner = Self::id();
let mut vote_state = VoteProgram {
votes: VecDeque::new(),
node_id: *tx.from(),
};
vote_state.serialize(&mut accounts[1].userdata)?;
Ok(())
}
Ok(VoteInstruction::NewVote(vote)) => {
if !Self::check_id(&accounts[0].owner) {
error!("accounts[0] is not assigned to the VOTE_PROGRAM");
Err(Error::InvalidArguments)?;
}
let mut vote_state = Self::deserialize(&accounts[0].userdata)?;
// TODO: Integrity checks
// a) Verify the vote's bank hash matches what is expected
// b) Verify vote is older than previous votes
// Only keep around the most recent MAX_VOTE_HISTORY votes
if vote_state.votes.len() == MAX_VOTE_HISTORY {
vote_state.votes.pop_front();
}
vote_state.votes.push_back(vote);
vote_state.serialize(&mut accounts[0].userdata)?;
Ok(())
}
Err(_) => {
info!(
"Invalid vote transaction userdata: {:?}",
tx.userdata(instruction_index)
);
Err(Error::UserdataDeserializeFailure)
}
}
}
pub fn get_max_size() -> usize {
// Upper limit on the size of the Vote State. Equal to
// sizeof(VoteProgram) + MAX_VOTE_HISTORY * sizeof(Vote) +
// 32 (the size of the Pubkey) + 2 (2 bytes for the size)
mem::size_of::<VoteProgram>()
+ MAX_VOTE_HISTORY * mem::size_of::<Vote>()
+ mem::size_of::<Pubkey>()
+ mem::size_of::<u16>()
}
} }
#[cfg(test)] #[cfg(test)]
@ -165,7 +165,7 @@ mod tests {
#[test] #[test]
fn test_serde() -> Result<()> { fn test_serde() -> Result<()> {
let mut buffer: Vec<u8> = vec![0; VoteProgram::get_max_size()]; let mut buffer: Vec<u8> = vec![0; get_max_size()];
let mut vote_program = VoteProgram::default(); let mut vote_program = VoteProgram::default();
vote_program.votes = (0..MAX_VOTE_HISTORY).map(|_| Vote::default()).collect(); vote_program.votes = (0..MAX_VOTE_HISTORY).map(|_| Vote::default()).collect();
vote_program.serialize(&mut buffer).unwrap(); vote_program.serialize(&mut buffer).unwrap();

View File

@ -12,7 +12,7 @@ use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use system_transaction::SystemTransaction; use system_transaction::SystemTransaction;
use transaction::Transaction; use transaction::Transaction;
use vote_program::{Vote, VoteInstruction, VoteProgram}; use vote_program::{self, Vote, VoteInstruction};
pub trait VoteTransaction { pub trait VoteTransaction {
fn vote_new(vote_account: &Keypair, vote: Vote, last_id: Hash, fee: u64) -> Self; fn vote_new(vote_account: &Keypair, vote: Vote, last_id: Hash, fee: u64) -> Self;
@ -37,7 +37,7 @@ impl VoteTransaction for Transaction {
Transaction::new( Transaction::new(
vote_account, vote_account,
&[], &[],
VoteProgram::id(), vote_program::id(),
&instruction, &instruction,
last_id, last_id,
fee, fee,
@ -55,8 +55,8 @@ impl VoteTransaction for Transaction {
new_vote_account_id, new_vote_account_id,
last_id, last_id,
num_tokens, num_tokens,
VoteProgram::get_max_size() as u64, vote_program::get_max_size() as u64,
VoteProgram::id(), vote_program::id(),
0, 0,
) )
} }
@ -71,7 +71,7 @@ impl VoteTransaction for Transaction {
Transaction::new( Transaction::new(
validator_id, validator_id,
&[vote_account_id], &[vote_account_id],
VoteProgram::id(), vote_program::id(),
&register_tx, &register_tx,
last_id, last_id,
fee, fee,
@ -82,7 +82,7 @@ impl VoteTransaction for Transaction {
let mut votes = vec![]; let mut votes = vec![];
for i in 0..self.instructions.len() { for i in 0..self.instructions.len() {
let tx_program_id = self.program_id(i); let tx_program_id = self.program_id(i);
if VoteProgram::check_id(&tx_program_id) { if vote_program::check_id(&tx_program_id) {
if let Ok(Some(VoteInstruction::NewVote(vote))) = deserialize(&self.userdata(i)) { if let Ok(Some(VoteInstruction::NewVote(vote))) = deserialize(&self.userdata(i)) {
votes.push((self.account_keys[0], vote, self.last_id)) votes.push((self.account_keys[0], vote, self.last_id))
} }

View File

@ -1,7 +1,7 @@
use bincode::serialize; use bincode::serialize;
use bpf_loader; use bpf_loader;
use bs58; use bs58;
use budget_program::BudgetProgram; use budget_program;
use budget_transaction::BudgetTransaction; use budget_transaction::BudgetTransaction;
use chrono::prelude::*; use chrono::prelude::*;
use clap::ArgMatches; use clap::ArgMatches;
@ -497,7 +497,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<error::Error
let contract_funds = Keypair::new(); let contract_funds = Keypair::new();
let contract_state = Keypair::new(); let contract_state = Keypair::new();
let budget_program_id = BudgetProgram::id(); let budget_program_id = budget_program::id();
// Create account for contract funds // Create account for contract funds
let tx = Transaction::system_create( let tx = Transaction::system_create(
@ -553,7 +553,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<error::Error
let contract_funds = Keypair::new(); let contract_funds = Keypair::new();
let contract_state = Keypair::new(); let contract_state = Keypair::new();
let budget_program_id = BudgetProgram::id(); let budget_program_id = budget_program::id();
// Create account for contract funds // Create account for contract funds
let tx = Transaction::system_create( let tx = Transaction::system_create(