Cleanup field names
This commit is contained in:
68
src/bank.rs
68
src/bank.rs
@ -412,7 +412,7 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_transaction(
|
pub fn verify_transaction(
|
||||||
program_index: usize,
|
instruction_index: usize,
|
||||||
tx_program_id: &Pubkey,
|
tx_program_id: &Pubkey,
|
||||||
pre_program_id: &Pubkey,
|
pre_program_id: &Pubkey,
|
||||||
pre_tokens: i64,
|
pre_tokens: i64,
|
||||||
@ -425,14 +425,16 @@ impl Bank {
|
|||||||
&& SystemProgram::check_id(&pre_program_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(program_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.
|
||||||
if *tx_program_id != account.program_id && pre_tokens > account.tokens {
|
if *tx_program_id != account.program_id && pre_tokens > account.tokens {
|
||||||
return Err(BankError::ExternalAccountTokenSpend(program_index as u8));
|
return Err(BankError::ExternalAccountTokenSpend(
|
||||||
|
instruction_index as u8,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if account.tokens < 0 {
|
if account.tokens < 0 {
|
||||||
return Err(BankError::ResultWithNegativeTokens(program_index as u8));
|
return Err(BankError::ResultWithNegativeTokens(instruction_index as u8));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -484,10 +486,10 @@ impl Bank {
|
|||||||
fn execute_instruction(
|
fn execute_instruction(
|
||||||
&self,
|
&self,
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
program_index: usize,
|
instruction_index: usize,
|
||||||
program_accounts: &mut [&mut Account],
|
program_accounts: &mut [&mut Account],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let tx_program_id = tx.program_id(program_index);
|
let tx_program_id = tx.program_id(instruction_index);
|
||||||
// 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
|
||||||
let pre_total: i64 = program_accounts.iter().map(|a| a.tokens).sum();
|
let pre_total: i64 = program_accounts.iter().map(|a| a.tokens).sum();
|
||||||
@ -501,39 +503,45 @@ impl Bank {
|
|||||||
if SystemProgram::check_id(&tx_program_id) {
|
if SystemProgram::check_id(&tx_program_id) {
|
||||||
SystemProgram::process_transaction(
|
SystemProgram::process_transaction(
|
||||||
&tx,
|
&tx,
|
||||||
program_index,
|
instruction_index,
|
||||||
program_accounts,
|
program_accounts,
|
||||||
&self.loaded_contracts,
|
&self.loaded_contracts,
|
||||||
)
|
)
|
||||||
} else if BudgetState::check_id(&tx_program_id) {
|
} else if BudgetState::check_id(&tx_program_id) {
|
||||||
if BudgetState::process_transaction(&tx, program_index, program_accounts).is_err() {
|
if BudgetState::process_transaction(&tx, instruction_index, program_accounts).is_err() {
|
||||||
return Err(BankError::ProgramRuntimeError(program_index as u8));
|
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||||
}
|
}
|
||||||
} else if StorageProgram::check_id(&tx_program_id) {
|
} else if StorageProgram::check_id(&tx_program_id) {
|
||||||
if StorageProgram::process_transaction(&tx, program_index, program_accounts).is_err() {
|
if StorageProgram::process_transaction(&tx, instruction_index, program_accounts)
|
||||||
return Err(BankError::ProgramRuntimeError(program_index as u8));
|
|
||||||
}
|
|
||||||
} else if TicTacToeProgram::check_id(&tx_program_id) {
|
|
||||||
if TicTacToeProgram::process_transaction(&tx, program_index, program_accounts).is_err()
|
|
||||||
{
|
|
||||||
return Err(BankError::ProgramRuntimeError(program_index as u8));
|
|
||||||
}
|
|
||||||
} else if TicTacToeDashboardProgram::check_id(&tx_program_id) {
|
|
||||||
if TicTacToeDashboardProgram::process_transaction(&tx, program_index, program_accounts)
|
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
return Err(BankError::ProgramRuntimeError(program_index as u8));
|
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||||
}
|
}
|
||||||
} else if self.loaded_contract(tx_program_id, tx, program_index, program_accounts) {
|
} else if TicTacToeProgram::check_id(&tx_program_id) {
|
||||||
|
if TicTacToeProgram::process_transaction(&tx, instruction_index, program_accounts)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||||
|
}
|
||||||
|
} else if TicTacToeDashboardProgram::check_id(&tx_program_id) {
|
||||||
|
if TicTacToeDashboardProgram::process_transaction(
|
||||||
|
&tx,
|
||||||
|
instruction_index,
|
||||||
|
program_accounts,
|
||||||
|
).is_err()
|
||||||
|
{
|
||||||
|
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||||
|
}
|
||||||
|
} else if self.loaded_contract(tx_program_id, tx, instruction_index, program_accounts) {
|
||||||
} else {
|
} else {
|
||||||
return Err(BankError::UnknownContractId(program_index as u8));
|
return Err(BankError::UnknownContractId(instruction_index as u8));
|
||||||
}
|
}
|
||||||
// Verify the transaction
|
// Verify the transaction
|
||||||
for ((pre_program_id, pre_tokens), post_account) in
|
for ((pre_program_id, pre_tokens), post_account) in
|
||||||
pre_data.iter().zip(program_accounts.iter())
|
pre_data.iter().zip(program_accounts.iter())
|
||||||
{
|
{
|
||||||
Self::verify_transaction(
|
Self::verify_transaction(
|
||||||
program_index,
|
instruction_index,
|
||||||
&tx_program_id,
|
&tx_program_id,
|
||||||
pre_program_id,
|
pre_program_id,
|
||||||
*pre_tokens,
|
*pre_tokens,
|
||||||
@ -543,7 +551,7 @@ impl Bank {
|
|||||||
// 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 = program_accounts.iter().map(|a| a.tokens).sum();
|
let post_total: i64 = program_accounts.iter().map(|a| a.tokens).sum();
|
||||||
if pre_total != post_total {
|
if pre_total != post_total {
|
||||||
Err(BankError::UnbalancedTransaction(program_index as u8))
|
Err(BankError::UnbalancedTransaction(instruction_index as u8))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -552,9 +560,9 @@ impl Bank {
|
|||||||
/// This method calls each instruction in the transaction over the set of loaded Accounts
|
/// This method calls each instruction in the transaction over the set of loaded Accounts
|
||||||
/// The accounts are committed back to the bank only if every instruction succeeds
|
/// The accounts are committed back to the bank only if every instruction succeeds
|
||||||
fn execute_transaction(&self, tx: &Transaction, tx_accounts: &mut [Account]) -> Result<()> {
|
fn execute_transaction(&self, tx: &Transaction, tx_accounts: &mut [Account]) -> Result<()> {
|
||||||
for (program_index, prog) in tx.instructions.iter().enumerate() {
|
for (instruction_index, prog) in tx.instructions.iter().enumerate() {
|
||||||
Self::with_subset(tx_accounts, &prog.accounts, |program_accounts| {
|
Self::with_subset(tx_accounts, &prog.accounts, |program_accounts| {
|
||||||
self.execute_instruction(tx, program_index, program_accounts)
|
self.execute_instruction(tx, instruction_index, program_accounts)
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1005,12 +1013,12 @@ mod tests {
|
|||||||
let spend = SystemProgram::Move { tokens: 1 };
|
let spend = SystemProgram::Move { tokens: 1 };
|
||||||
let instructions = vec![
|
let instructions = vec![
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata: serialize(&spend).unwrap(),
|
userdata: serialize(&spend).unwrap(),
|
||||||
accounts: vec![0, 1],
|
accounts: vec![0, 1],
|
||||||
},
|
},
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata: serialize(&spend).unwrap(),
|
userdata: serialize(&spend).unwrap(),
|
||||||
accounts: vec![0, 2],
|
accounts: vec![0, 2],
|
||||||
},
|
},
|
||||||
@ -1045,12 +1053,12 @@ mod tests {
|
|||||||
let spend = SystemProgram::Move { tokens: 1 };
|
let spend = SystemProgram::Move { tokens: 1 };
|
||||||
let instructions = vec![
|
let instructions = vec![
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata: serialize(&spend).unwrap(),
|
userdata: serialize(&spend).unwrap(),
|
||||||
accounts: vec![0, 1],
|
accounts: vec![0, 1],
|
||||||
},
|
},
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata: serialize(&spend).unwrap(),
|
userdata: serialize(&spend).unwrap(),
|
||||||
accounts: vec![0, 2],
|
accounts: vec![0, 2],
|
||||||
},
|
},
|
||||||
|
@ -48,18 +48,18 @@ impl BudgetState {
|
|||||||
fn apply_signature(
|
fn apply_signature(
|
||||||
&mut self,
|
&mut self,
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
program_index: usize,
|
instruction_index: usize,
|
||||||
account: &mut [&mut Account],
|
account: &mut [&mut Account],
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
let mut final_payment = None;
|
let mut final_payment = None;
|
||||||
if let Some(ref mut budget) = self.pending_budget {
|
if let Some(ref mut budget) = self.pending_budget {
|
||||||
let key = tx.key(program_index, 0).unwrap();
|
let key = tx.key(instruction_index, 0).unwrap();
|
||||||
budget.apply_witness(&Witness::Signature, key);
|
budget.apply_witness(&Witness::Signature, key);
|
||||||
final_payment = budget.final_payment();
|
final_payment = budget.final_payment();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(payment) = final_payment {
|
if let Some(payment) = final_payment {
|
||||||
if Some(&payment.to) != tx.key(program_index, 2) {
|
if Some(&payment.to) != tx.key(instruction_index, 2) {
|
||||||
trace!("destination missing");
|
trace!("destination missing");
|
||||||
return Err(BudgetError::DestinationMissing);
|
return Err(BudgetError::DestinationMissing);
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ impl BudgetState {
|
|||||||
fn apply_timestamp(
|
fn apply_timestamp(
|
||||||
&mut self,
|
&mut self,
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
program_index: usize,
|
instruction_index: usize,
|
||||||
accounts: &mut [&mut Account],
|
accounts: &mut [&mut Account],
|
||||||
dt: DateTime<Utc>,
|
dt: DateTime<Utc>,
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
@ -83,13 +83,13 @@ impl BudgetState {
|
|||||||
let mut final_payment = None;
|
let mut final_payment = None;
|
||||||
|
|
||||||
if let Some(ref mut budget) = self.pending_budget {
|
if let Some(ref mut budget) = self.pending_budget {
|
||||||
let key = tx.key(program_index, 0).unwrap();
|
let key = tx.key(instruction_index, 0).unwrap();
|
||||||
budget.apply_witness(&Witness::Timestamp(dt), key);
|
budget.apply_witness(&Witness::Timestamp(dt), key);
|
||||||
final_payment = budget.final_payment();
|
final_payment = budget.final_payment();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(payment) = final_payment {
|
if let Some(payment) = final_payment {
|
||||||
if Some(&payment.to) != tx.key(program_index, 2) {
|
if Some(&payment.to) != tx.key(instruction_index, 2) {
|
||||||
trace!("destination missing");
|
trace!("destination missing");
|
||||||
return Err(BudgetError::DestinationMissing);
|
return Err(BudgetError::DestinationMissing);
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ impl BudgetState {
|
|||||||
/// Note: It is safe to apply credits from multiple transactions in parallel.
|
/// Note: It is safe to apply credits from multiple transactions in parallel.
|
||||||
fn apply_credits_to_budget_state(
|
fn apply_credits_to_budget_state(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
program_index: usize,
|
instruction_index: usize,
|
||||||
accounts: &mut [&mut Account],
|
accounts: &mut [&mut Account],
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
@ -166,7 +166,7 @@ impl BudgetState {
|
|||||||
Err(BudgetError::UninitializedContract)
|
Err(BudgetError::UninitializedContract)
|
||||||
} else {
|
} else {
|
||||||
trace!("apply timestamp");
|
trace!("apply timestamp");
|
||||||
state.apply_timestamp(tx, program_index, accounts, *dt)?;
|
state.apply_timestamp(tx, instruction_index, accounts, *dt)?;
|
||||||
trace!("apply timestamp committed");
|
trace!("apply timestamp committed");
|
||||||
state.serialize(&mut accounts[1].userdata)
|
state.serialize(&mut accounts[1].userdata)
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ impl BudgetState {
|
|||||||
Err(BudgetError::UninitializedContract)
|
Err(BudgetError::UninitializedContract)
|
||||||
} else {
|
} else {
|
||||||
trace!("apply signature");
|
trace!("apply signature");
|
||||||
state.apply_signature(tx, program_index, accounts)?;
|
state.apply_signature(tx, instruction_index, accounts)?;
|
||||||
trace!("apply signature committed");
|
trace!("apply signature committed");
|
||||||
state.serialize(&mut accounts[1].userdata)
|
state.serialize(&mut accounts[1].userdata)
|
||||||
}
|
}
|
||||||
@ -241,18 +241,18 @@ impl BudgetState {
|
|||||||
/// be spent from this account .
|
/// be spent from this account .
|
||||||
pub fn process_transaction(
|
pub fn process_transaction(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
program_index: usize,
|
instruction_index: usize,
|
||||||
accounts: &mut [&mut Account],
|
accounts: &mut [&mut Account],
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
if let Ok(instruction) = deserialize(tx.userdata(program_index)) {
|
if let Ok(instruction) = deserialize(tx.userdata(instruction_index)) {
|
||||||
trace!("process_transaction: {:?}", instruction);
|
trace!("process_transaction: {:?}", instruction);
|
||||||
Self::apply_debits_to_budget_state(accounts, &instruction).and_then(|_| {
|
Self::apply_debits_to_budget_state(accounts, &instruction).and_then(|_| {
|
||||||
Self::apply_credits_to_budget_state(tx, program_index, accounts, &instruction)
|
Self::apply_credits_to_budget_state(tx, instruction_index, accounts, &instruction)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
info!(
|
info!(
|
||||||
"Invalid transaction userdata: {:?}",
|
"Invalid transaction userdata: {:?}",
|
||||||
tx.userdata(program_index)
|
tx.userdata(instruction_index)
|
||||||
);
|
);
|
||||||
Err(BudgetError::UserdataDeserializeFailure)
|
Err(BudgetError::UserdataDeserializeFailure)
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ mod tests {
|
|||||||
let instruction = Instruction::NewContract(Contract { budget, tokens: 0 });
|
let instruction = Instruction::NewContract(Contract { budget, tokens: 0 });
|
||||||
let userdata = serialize(&instruction).unwrap();
|
let userdata = serialize(&instruction).unwrap();
|
||||||
let instructions = vec![transaction::Instruction {
|
let instructions = vec![transaction::Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata,
|
userdata,
|
||||||
accounts: vec![],
|
accounts: vec![],
|
||||||
}];
|
}];
|
||||||
@ -286,7 +286,7 @@ mod tests {
|
|||||||
account_keys: vec![],
|
account_keys: vec![],
|
||||||
last_id: Default::default(),
|
last_id: Default::default(),
|
||||||
signature: Default::default(),
|
signature: Default::default(),
|
||||||
program_keys: vec![],
|
program_ids: vec![],
|
||||||
instructions,
|
instructions,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
};
|
};
|
||||||
|
@ -10,13 +10,13 @@ pub const SIGNED_DATA_OFFSET: usize = size_of::<Signature>();
|
|||||||
pub const SIG_OFFSET: usize = 0;
|
pub const SIG_OFFSET: usize = 0;
|
||||||
pub const PUB_KEY_OFFSET: usize = size_of::<Signature>() + size_of::<u64>();
|
pub const PUB_KEY_OFFSET: usize = size_of::<Signature>() + size_of::<u64>();
|
||||||
|
|
||||||
/// An instruction to execute a program under `program_id` with the
|
/// An instruction to execute a program under the `program_id` of `program_ids_index` with the
|
||||||
/// specified accounts and userdata
|
/// specified accounts and userdata
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Instruction {
|
pub struct Instruction {
|
||||||
/// The program code that executes this transaction is identified by the program_id.
|
/// The program code that executes this transaction is identified by the program_id.
|
||||||
/// this is an offset into the Transaction::program_keys field
|
/// this is an offset into the Transaction::program_ids field
|
||||||
pub program_id: u8,
|
pub program_ids_index: u8,
|
||||||
/// Indices into the keys array of which accounts to load
|
/// Indices into the keys array of which accounts to load
|
||||||
pub accounts: Vec<u8>,
|
pub accounts: Vec<u8>,
|
||||||
/// Userdata to be stored in the account
|
/// Userdata to be stored in the account
|
||||||
@ -26,7 +26,7 @@ pub struct Instruction {
|
|||||||
/// An atomic transaction
|
/// An atomic transaction
|
||||||
#[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`, `program_id`, `last_id`, `fee` and `userdata`, signed by `Pubkey`.
|
/// A digital signature of `account_keys`, `program_ids`, `last_id`, `fee` and `instructions`, 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
|
||||||
@ -42,8 +42,8 @@ pub struct Transaction {
|
|||||||
/// The number of tokens paid for processing and storage of this transaction.
|
/// The number of tokens paid for processing and storage of this transaction.
|
||||||
pub fee: i64,
|
pub fee: i64,
|
||||||
|
|
||||||
/// Keys indentifying programs in the instructions vector.
|
/// Keys identifying programs in the instructions vector.
|
||||||
pub program_keys: Vec<Pubkey>,
|
pub program_ids: Vec<Pubkey>,
|
||||||
/// Programs that will be executed in sequence and commited in one atomic transaction if all
|
/// Programs that will be executed in sequence and commited in one atomic transaction if all
|
||||||
/// succeed.
|
/// succeed.
|
||||||
pub instructions: Vec<Instruction>,
|
pub instructions: Vec<Instruction>,
|
||||||
@ -58,9 +58,9 @@ impl Transaction {
|
|||||||
last_id: Hash,
|
last_id: Hash,
|
||||||
fee: i64,
|
fee: i64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let program_keys = vec![program_id];
|
let program_ids = vec![program_id];
|
||||||
let instructions = vec![Instruction {
|
let instructions = vec![Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata,
|
userdata,
|
||||||
accounts: (0..(transaction_keys.len() as u8 + 1))
|
accounts: (0..(transaction_keys.len() as u8 + 1))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -71,7 +71,7 @@ impl Transaction {
|
|||||||
transaction_keys,
|
transaction_keys,
|
||||||
last_id,
|
last_id,
|
||||||
fee,
|
fee,
|
||||||
program_keys,
|
program_ids,
|
||||||
instructions,
|
instructions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -81,14 +81,14 @@ impl Transaction {
|
|||||||
/// instances or token recipient keys.
|
/// instances or token recipient keys.
|
||||||
/// * `last_id` - The PoH hash.
|
/// * `last_id` - The PoH hash.
|
||||||
/// * `fee` - The transaction fee.
|
/// * `fee` - The transaction fee.
|
||||||
/// * `program_keys` - The keys that identify programs used in the `instruction` vector.
|
/// * `program_ids` - The keys that identify programs used in the `instruction` vector.
|
||||||
/// * `instructions` - The programs and their arguments that the transaction will execute atomically
|
/// * `instructions` - The programs and their arguments that the transaction will execute atomically
|
||||||
pub fn new_with_instructions(
|
pub fn new_with_instructions(
|
||||||
from_keypair: &Keypair,
|
from_keypair: &Keypair,
|
||||||
keys: &[Pubkey],
|
keys: &[Pubkey],
|
||||||
last_id: Hash,
|
last_id: Hash,
|
||||||
fee: i64,
|
fee: i64,
|
||||||
program_keys: Vec<Pubkey>,
|
program_ids: Vec<Pubkey>,
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let from = from_keypair.pubkey();
|
let from = from_keypair.pubkey();
|
||||||
@ -99,23 +99,24 @@ impl Transaction {
|
|||||||
account_keys,
|
account_keys,
|
||||||
last_id,
|
last_id,
|
||||||
fee,
|
fee,
|
||||||
program_keys,
|
program_ids,
|
||||||
instructions,
|
instructions,
|
||||||
};
|
};
|
||||||
tx.sign(from_keypair);
|
tx.sign(from_keypair);
|
||||||
tx
|
tx
|
||||||
}
|
}
|
||||||
pub fn userdata(&self, program_index: usize) -> &[u8] {
|
pub fn userdata(&self, instruction_index: usize) -> &[u8] {
|
||||||
&self.instructions[program_index].userdata
|
&self.instructions[instruction_index].userdata
|
||||||
}
|
}
|
||||||
pub fn key(&self, program_index: usize, kix: usize) -> Option<&Pubkey> {
|
pub fn key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
|
||||||
self.instructions
|
self.instructions
|
||||||
.get(program_index)
|
.get(instruction_index)
|
||||||
.and_then(|p| p.accounts.get(kix))
|
.and_then(|instruction| instruction.accounts.get(accounts_index))
|
||||||
.and_then(|ai| self.account_keys.get(*ai as usize))
|
.and_then(|ai| self.account_keys.get(*ai as usize))
|
||||||
}
|
}
|
||||||
pub fn program_id(&self, program_index: usize) -> &Pubkey {
|
pub fn program_id(&self, instruction_index: usize) -> &Pubkey {
|
||||||
&self.program_keys[self.instructions[program_index].program_id as usize]
|
let program_ids_index = self.instructions[instruction_index].program_ids_index;
|
||||||
|
&self.program_ids[program_ids_index as usize]
|
||||||
}
|
}
|
||||||
/// Get the transaction data to sign.
|
/// Get the transaction data to sign.
|
||||||
pub fn get_sign_data(&self) -> Vec<u8> {
|
pub fn get_sign_data(&self) -> Vec<u8> {
|
||||||
@ -124,11 +125,11 @@ impl Transaction {
|
|||||||
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);
|
||||||
|
|
||||||
let fee_data = serialize(&self.fee).expect("serialize last_id");
|
let fee_data = serialize(&self.fee).expect("serialize fee");
|
||||||
data.extend_from_slice(&fee_data);
|
data.extend_from_slice(&fee_data);
|
||||||
|
|
||||||
let program_keys = serialize(&self.program_keys).expect("serialize program_keys");
|
let program_ids = serialize(&self.program_ids).expect("serialize program_ids");
|
||||||
data.extend_from_slice(&program_keys);
|
data.extend_from_slice(&program_ids);
|
||||||
|
|
||||||
let instructions = serialize(&self.instructions).expect("serialize instructions");
|
let instructions = serialize(&self.instructions).expect("serialize instructions");
|
||||||
data.extend_from_slice(&instructions);
|
data.extend_from_slice(&instructions);
|
||||||
@ -151,7 +152,7 @@ impl Transaction {
|
|||||||
/// Verify that references in the instructions are valid
|
/// Verify that references in the instructions are valid
|
||||||
pub fn verify_refs(&self) -> bool {
|
pub fn verify_refs(&self) -> bool {
|
||||||
for instruction in &self.instructions {
|
for instruction in &self.instructions {
|
||||||
if (instruction.program_id as usize) >= self.program_keys.len() {
|
if (instruction.program_ids_index as usize) >= self.program_ids.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for account_index in &instruction.accounts {
|
for account_index in &instruction.accounts {
|
||||||
@ -192,12 +193,12 @@ mod tests {
|
|||||||
let prog2 = Keypair::new().pubkey();
|
let prog2 = Keypair::new().pubkey();
|
||||||
let instructions = vec![
|
let instructions = vec![
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata: vec![],
|
userdata: vec![],
|
||||||
accounts: vec![0, 1],
|
accounts: vec![0, 1],
|
||||||
},
|
},
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: 1,
|
program_ids_index: 1,
|
||||||
userdata: vec![],
|
userdata: vec![],
|
||||||
accounts: vec![0, 2],
|
accounts: vec![0, 2],
|
||||||
},
|
},
|
||||||
@ -224,7 +225,7 @@ mod tests {
|
|||||||
fn test_refs_invalid_program_id() {
|
fn test_refs_invalid_program_id() {
|
||||||
let key = Keypair::new();
|
let key = Keypair::new();
|
||||||
let instructions = vec![Instruction {
|
let instructions = vec![Instruction {
|
||||||
program_id: 1,
|
program_ids_index: 1,
|
||||||
userdata: vec![],
|
userdata: vec![],
|
||||||
accounts: vec![],
|
accounts: vec![],
|
||||||
}];
|
}];
|
||||||
@ -242,7 +243,7 @@ mod tests {
|
|||||||
fn test_refs_invalid_account() {
|
fn test_refs_invalid_account() {
|
||||||
let key = Keypair::new();
|
let key = Keypair::new();
|
||||||
let instructions = vec![Instruction {
|
let instructions = vec![Instruction {
|
||||||
program_id: 0,
|
program_ids_index: 0,
|
||||||
userdata: vec![],
|
userdata: vec![],
|
||||||
accounts: vec![1],
|
accounts: vec![1],
|
||||||
}];
|
}];
|
||||||
|
Reference in New Issue
Block a user