Rename tokens to lamports in sdk/
This commit is contained in:
@ -396,11 +396,11 @@ impl AccountsDB {
|
||||
let start = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
let mut id = self.get_storage_id(start, std::usize::MAX);
|
||||
|
||||
// Even if no tokens, need to preserve the account owner so
|
||||
// Even if no lamports, need to preserve the account owner so
|
||||
// we can update the vote_accounts correctly if this account is purged
|
||||
// when squashing.
|
||||
let acc = &mut account.clone();
|
||||
if account.tokens == 0 {
|
||||
if account.lamports == 0 {
|
||||
acc.userdata.resize(0, 0);
|
||||
}
|
||||
|
||||
@ -480,7 +480,7 @@ impl AccountsDB {
|
||||
|
||||
/// Store the account update.
|
||||
fn store_account(&self, fork: Fork, pubkey: &Pubkey, account: &Account) {
|
||||
if account.tokens == 0 && self.is_squashed(fork) {
|
||||
if account.lamports == 0 && self.is_squashed(fork) {
|
||||
// purge if balance is 0 and no checkpoints
|
||||
let account_maps = self.account_index.account_maps.read().unwrap();
|
||||
let map = account_maps.get(&pubkey).unwrap();
|
||||
@ -576,14 +576,14 @@ impl AccountsDB {
|
||||
for key in &tx.account_keys {
|
||||
called_accounts.push(self.load(fork, key, true).unwrap_or_default());
|
||||
}
|
||||
if called_accounts.is_empty() || called_accounts[0].tokens == 0 {
|
||||
if called_accounts.is_empty() || called_accounts[0].lamports == 0 {
|
||||
error_counters.account_not_found += 1;
|
||||
Err(BankError::AccountNotFound)
|
||||
} else if called_accounts[0].tokens < tx.fee {
|
||||
} else if called_accounts[0].lamports < tx.fee {
|
||||
error_counters.insufficient_funds += 1;
|
||||
Err(BankError::InsufficientFundsForFee)
|
||||
} else {
|
||||
called_accounts[0].tokens -= tx.fee;
|
||||
called_accounts[0].lamports -= tx.fee;
|
||||
Ok(called_accounts)
|
||||
}
|
||||
}
|
||||
@ -735,7 +735,7 @@ impl AccountsDB {
|
||||
self.insert_account_entry(fork, id, offset, &map);
|
||||
} else {
|
||||
let account = self.get_account(id, offset);
|
||||
if account.tokens == 0 {
|
||||
if account.lamports == 0 {
|
||||
if self.remove_account_entries(&[fork], &map) {
|
||||
keys.push(pubkey.clone());
|
||||
}
|
||||
@ -803,14 +803,14 @@ impl Accounts {
|
||||
pub fn load_slow(&self, fork: Fork, pubkey: &Pubkey) -> Option<Account> {
|
||||
self.accounts_db
|
||||
.load(fork, pubkey, true)
|
||||
.filter(|acc| acc.tokens != 0)
|
||||
.filter(|acc| acc.lamports != 0)
|
||||
}
|
||||
|
||||
/// Slow because lock is held for 1 operation insted of many
|
||||
pub fn load_slow_no_parent(&self, fork: Fork, pubkey: &Pubkey) -> Option<Account> {
|
||||
self.accounts_db
|
||||
.load(fork, pubkey, false)
|
||||
.filter(|acc| acc.tokens != 0)
|
||||
.filter(|acc| acc.lamports != 0)
|
||||
}
|
||||
|
||||
/// Slow because lock is held for 1 operation insted of many
|
||||
@ -943,7 +943,7 @@ impl Accounts {
|
||||
self.accounts_db
|
||||
.get_vote_accounts(fork)
|
||||
.into_iter()
|
||||
.filter(|(_, acc)| acc.tokens != 0)
|
||||
.filter(|(_, acc)| acc.lamports != 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1402,11 +1402,11 @@ mod tests {
|
||||
|
||||
// now we have:
|
||||
//
|
||||
// root0 -> key.tokens==1
|
||||
// root0 -> key.lamports==1
|
||||
// / \
|
||||
// / \
|
||||
// key.tokens==0 <- fork1 \
|
||||
// fork2 -> key.tokens==1
|
||||
// key.lamports==0 <- fork1 \
|
||||
// fork2 -> key.lamports==1
|
||||
// (via root0)
|
||||
|
||||
// store value 0 in one child
|
||||
@ -1426,11 +1426,11 @@ mod tests {
|
||||
|
||||
// now we should have:
|
||||
//
|
||||
// root0 -> key.tokens==1
|
||||
// root0 -> key.lamports==1
|
||||
// \
|
||||
// \
|
||||
// key.tokens==ANF <- root1 \
|
||||
// fork2 -> key.tokens==1 (from root0)
|
||||
// key.lamports==ANF <- root1 \
|
||||
// fork2 -> key.lamports==1 (from root0)
|
||||
//
|
||||
assert_eq!(db.load(1, &key, true), None); // purged
|
||||
assert_eq!(&db.load(2, &key, true).unwrap(), &account0); // original value
|
||||
@ -1447,17 +1447,17 @@ mod tests {
|
||||
let idx = thread_rng().gen_range(0, 99);
|
||||
let account = db.load(0, &pubkeys[idx], true).unwrap();
|
||||
let mut default_account = Account::default();
|
||||
default_account.tokens = (idx + 1) as u64;
|
||||
default_account.lamports = (idx + 1) as u64;
|
||||
assert_eq!(compare_account(&default_account, &account), true);
|
||||
}
|
||||
db.add_fork(1, Some(0));
|
||||
|
||||
// now we have:
|
||||
//
|
||||
// root0 -> key[X].tokens==X
|
||||
// root0 -> key[X].lamports==X
|
||||
// /
|
||||
// /
|
||||
// key[X].tokens==X <- fork1
|
||||
// key[X].lamports==X <- fork1
|
||||
// (via root0)
|
||||
//
|
||||
|
||||
@ -1468,7 +1468,7 @@ mod tests {
|
||||
// root0 -> purged ??
|
||||
//
|
||||
//
|
||||
// key[X].tokens==X <- root1
|
||||
// key[X].lamports==X <- root1
|
||||
//
|
||||
|
||||
// check that all the accounts appear in parent after a squash ???
|
||||
@ -1477,7 +1477,7 @@ mod tests {
|
||||
let account0 = db.load(0, &pubkeys[idx], true).unwrap();
|
||||
let account1 = db.load(1, &pubkeys[idx], true).unwrap();
|
||||
let mut default_account = Account::default();
|
||||
default_account.tokens = (idx + 1) as u64;
|
||||
default_account.lamports = (idx + 1) as u64;
|
||||
assert_eq!(&default_account, &account0);
|
||||
assert_eq!(&default_account, &account1);
|
||||
}
|
||||
@ -1494,7 +1494,7 @@ mod tests {
|
||||
db0.store(0, &key, &account0);
|
||||
|
||||
db0.add_fork(1, Some(0));
|
||||
// 0 tokens in the child
|
||||
// 0 lamports in the child
|
||||
let account1 = Account::new(0, 0, key);
|
||||
db0.store(1, &key, &account1);
|
||||
|
||||
@ -1518,7 +1518,7 @@ mod tests {
|
||||
let pubkey = Keypair::new().pubkey();
|
||||
let mut default_account = Account::default();
|
||||
pubkeys.push(pubkey.clone());
|
||||
default_account.tokens = (t + 1) as u64;
|
||||
default_account.lamports = (t + 1) as u64;
|
||||
assert!(accounts.load(0, &pubkey, true).is_none());
|
||||
accounts.store(0, &pubkey, &default_account);
|
||||
}
|
||||
@ -1527,7 +1527,7 @@ mod tests {
|
||||
let mut default_account = Account::default();
|
||||
pubkeys.push(pubkey.clone());
|
||||
default_account.owner = solana_vote_api::id();
|
||||
default_account.tokens = (num + t + 1) as u64;
|
||||
default_account.lamports = (num + t + 1) as u64;
|
||||
assert!(accounts.load(0, &pubkey, true).is_none());
|
||||
accounts.store(0, &pubkey, &default_account);
|
||||
}
|
||||
@ -1537,13 +1537,13 @@ mod tests {
|
||||
for _ in 1..1000 {
|
||||
let idx = thread_rng().gen_range(0, range);
|
||||
if let Some(mut account) = accounts.load(0, &pubkeys[idx], true) {
|
||||
account.tokens = account.tokens + 1;
|
||||
account.lamports = account.lamports + 1;
|
||||
accounts.store(0, &pubkeys[idx], &account);
|
||||
if account.tokens == 0 {
|
||||
if account.lamports == 0 {
|
||||
assert!(accounts.load(0, &pubkeys[idx], true).is_none());
|
||||
} else {
|
||||
let mut default_account = Account::default();
|
||||
default_account.tokens = account.tokens;
|
||||
default_account.lamports = account.lamports;
|
||||
assert_eq!(compare_account(&default_account, &account), true);
|
||||
}
|
||||
}
|
||||
@ -1554,7 +1554,7 @@ mod tests {
|
||||
if account1.userdata != account2.userdata
|
||||
|| account1.owner != account2.owner
|
||||
|| account1.executable != account2.executable
|
||||
|| account1.tokens != account2.tokens
|
||||
|| account1.lamports != account2.lamports
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1569,7 +1569,7 @@ mod tests {
|
||||
create_account(&accounts, &mut pubkeys, 1, 0);
|
||||
let account = accounts.load(0, &pubkeys[0], true).unwrap();
|
||||
let mut default_account = Account::default();
|
||||
default_account.tokens = 1;
|
||||
default_account.lamports = 1;
|
||||
assert_eq!(compare_account(&default_account, &account), true);
|
||||
}
|
||||
|
||||
@ -1583,7 +1583,7 @@ mod tests {
|
||||
let idx = thread_rng().gen_range(0, 99);
|
||||
let account = accounts.load(0, &pubkeys[idx], true).unwrap();
|
||||
let mut default_account = Account::default();
|
||||
default_account.tokens = (idx + 1) as u64;
|
||||
default_account.lamports = (idx + 1) as u64;
|
||||
assert_eq!(compare_account(&default_account, &account), true);
|
||||
}
|
||||
}
|
||||
@ -1669,7 +1669,7 @@ mod tests {
|
||||
let mut vote_accounts: Vec<_> = accounts.get_vote_accounts(1).collect();
|
||||
assert_eq!(vote_accounts.len(), 1);
|
||||
|
||||
vote_account.tokens = 0;
|
||||
vote_account.lamports = 0;
|
||||
accounts.store_slow(1, &key, &vote_account);
|
||||
|
||||
vote_accounts = accounts.get_vote_accounts(1).collect();
|
||||
@ -1685,7 +1685,7 @@ mod tests {
|
||||
vote_accounts = accounts.get_vote_accounts(1).collect();
|
||||
assert_eq!(vote_accounts.len(), 1);
|
||||
|
||||
vote_account1.tokens = 0;
|
||||
vote_account1.lamports = 0;
|
||||
accounts.store_slow(1, &key1, &vote_account1);
|
||||
accounts.store_slow(0, &key, &vote_account);
|
||||
|
||||
@ -1716,11 +1716,11 @@ mod tests {
|
||||
accounts_db.get_vote_accounts(0)
|
||||
);
|
||||
|
||||
info!("storing tokens=0 to fork 1");
|
||||
// should store a tokens=0 account in 1
|
||||
lastaccount.tokens = 0;
|
||||
info!("storing lamports=0 to fork 1");
|
||||
// should store a lamports=0 account in 1
|
||||
lastaccount.lamports = 0;
|
||||
accounts_db.store(1, &lastkey, &lastaccount);
|
||||
// len == 2 because tokens=0 accounts are filtered at the Accounts interface.
|
||||
// len == 2 because lamports=0 accounts are filtered at the Accounts interface.
|
||||
assert_eq!(accounts_db.get_vote_accounts(1).len(), 2);
|
||||
|
||||
accounts_db.squash(1);
|
||||
|
@ -40,7 +40,7 @@ pub fn serialize_account(dst_slice: &mut [u8], account: &Account, len: usize) {
|
||||
let mut at = 0;
|
||||
|
||||
write_u64(&mut at, dst_slice, len as u64);
|
||||
write_u64(&mut at, dst_slice, account.tokens);
|
||||
write_u64(&mut at, dst_slice, account.lamports);
|
||||
write_bytes(&mut at, dst_slice, &account.userdata);
|
||||
write_bytes(&mut at, dst_slice, account.owner.as_ref());
|
||||
write_bytes(&mut at, dst_slice, &[account.executable as u8]);
|
||||
@ -81,7 +81,7 @@ pub fn deserialize_account(
|
||||
let len = size as usize;
|
||||
assert!(current_offset >= at + len);
|
||||
|
||||
let tokens = read_u64(&mut at, &src_slice);
|
||||
let lamports = read_u64(&mut at, &src_slice);
|
||||
|
||||
let userdata_len = len - get_account_size_static();
|
||||
let mut userdata = vec![0; userdata_len];
|
||||
@ -96,7 +96,7 @@ pub fn deserialize_account(
|
||||
let executable: bool = exec[0] != 0;
|
||||
|
||||
Ok(Account {
|
||||
tokens,
|
||||
lamports,
|
||||
userdata,
|
||||
owner,
|
||||
executable,
|
||||
@ -255,7 +255,7 @@ pub mod tests {
|
||||
let av: AppendVec<Account> = AppendVec::new(path, true, START_SIZE, INC_SIZE);
|
||||
let v1 = vec![1u8; 32];
|
||||
let mut account1 = Account {
|
||||
tokens: 1,
|
||||
lamports: 1,
|
||||
userdata: v1,
|
||||
owner: Pubkey::default(),
|
||||
executable: false,
|
||||
@ -266,7 +266,7 @@ pub mod tests {
|
||||
|
||||
let v2 = vec![4u8; 32];
|
||||
let mut account2 = Account {
|
||||
tokens: 1,
|
||||
lamports: 1,
|
||||
userdata: v2,
|
||||
owner: Pubkey::default(),
|
||||
executable: false,
|
||||
|
@ -240,24 +240,27 @@ impl Bank {
|
||||
assert!(genesis_block.mint_id != Pubkey::default());
|
||||
assert!(genesis_block.bootstrap_leader_id != Pubkey::default());
|
||||
assert!(genesis_block.bootstrap_leader_vote_account_id != Pubkey::default());
|
||||
assert!(genesis_block.tokens >= genesis_block.bootstrap_leader_tokens);
|
||||
assert!(genesis_block.bootstrap_leader_tokens >= 3);
|
||||
assert!(genesis_block.lamports >= genesis_block.bootstrap_leader_lamports);
|
||||
assert!(genesis_block.bootstrap_leader_lamports >= 3);
|
||||
|
||||
// Bootstrap leader collects fees until `new_from_parent` is called.
|
||||
self.collector_id = genesis_block.bootstrap_leader_id;
|
||||
|
||||
let mint_tokens = genesis_block.tokens - genesis_block.bootstrap_leader_tokens;
|
||||
self.deposit(&genesis_block.mint_id, mint_tokens);
|
||||
let mint_lamports = genesis_block.lamports - genesis_block.bootstrap_leader_lamports;
|
||||
self.deposit(&genesis_block.mint_id, mint_lamports);
|
||||
|
||||
let bootstrap_leader_tokens = 2;
|
||||
let bootstrap_leader_lamports = 2;
|
||||
let bootstrap_leader_stake =
|
||||
genesis_block.bootstrap_leader_tokens - bootstrap_leader_tokens;
|
||||
self.deposit(&genesis_block.bootstrap_leader_id, bootstrap_leader_tokens);
|
||||
genesis_block.bootstrap_leader_lamports - bootstrap_leader_lamports;
|
||||
self.deposit(
|
||||
&genesis_block.bootstrap_leader_id,
|
||||
bootstrap_leader_lamports,
|
||||
);
|
||||
|
||||
// Construct a vote account for the bootstrap_leader such that the leader_scheduler
|
||||
// will be forced to select it as the leader for height 0
|
||||
let mut bootstrap_leader_vote_account = Account {
|
||||
tokens: bootstrap_leader_stake,
|
||||
lamports: bootstrap_leader_stake,
|
||||
userdata: vec![0; VoteState::max_size() as usize],
|
||||
owner: solana_vote_api::id(),
|
||||
executable: false,
|
||||
@ -645,7 +648,7 @@ impl Bank {
|
||||
}
|
||||
|
||||
/// Create, sign, and process a Transaction from `keypair` to `to` of
|
||||
/// `n` tokens where `blockhash` is the last Entry ID observed by the client.
|
||||
/// `n` lamports where `blockhash` is the last Entry ID observed by the client.
|
||||
pub fn transfer(
|
||||
&self,
|
||||
n: u64,
|
||||
@ -659,7 +662,7 @@ impl Bank {
|
||||
}
|
||||
|
||||
pub fn read_balance(account: &Account) -> u64 {
|
||||
account.tokens
|
||||
account.lamports
|
||||
}
|
||||
/// Each program would need to be able to introspect its own state
|
||||
/// this is hard-coded to the Budget language
|
||||
@ -680,14 +683,14 @@ impl Bank {
|
||||
parents
|
||||
}
|
||||
|
||||
pub fn withdraw(&self, pubkey: &Pubkey, tokens: u64) -> Result<()> {
|
||||
pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
|
||||
match self.get_account(pubkey) {
|
||||
Some(mut account) => {
|
||||
if tokens > account.tokens {
|
||||
if lamports > account.lamports {
|
||||
return Err(BankError::InsufficientFundsForFee);
|
||||
}
|
||||
|
||||
account.tokens -= tokens;
|
||||
account.lamports -= lamports;
|
||||
self.accounts()
|
||||
.store_slow(self.accounts_id, pubkey, &account);
|
||||
Ok(())
|
||||
@ -696,9 +699,9 @@ impl Bank {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deposit(&self, pubkey: &Pubkey, tokens: u64) {
|
||||
pub fn deposit(&self, pubkey: &Pubkey, lamports: u64) {
|
||||
let mut account = self.get_account(pubkey).unwrap_or_default();
|
||||
account.tokens += tokens;
|
||||
account.lamports += lamports;
|
||||
self.accounts()
|
||||
.store_slow(self.accounts_id, pubkey, &account);
|
||||
}
|
||||
@ -798,7 +801,7 @@ mod tests {
|
||||
use super::*;
|
||||
use bincode::serialize;
|
||||
use hashbrown::HashSet;
|
||||
use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_TOKENS};
|
||||
use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_LAMPORTS};
|
||||
use solana_sdk::native_program::ProgramError;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
@ -815,18 +818,21 @@ mod tests {
|
||||
#[test]
|
||||
fn test_bank_new_with_leader() {
|
||||
let dummy_leader_id = Keypair::new().pubkey();
|
||||
let dummy_leader_tokens = BOOTSTRAP_LEADER_TOKENS;
|
||||
let dummy_leader_lamports = BOOTSTRAP_LEADER_LAMPORTS;
|
||||
let (genesis_block, _) =
|
||||
GenesisBlock::new_with_leader(10_000, dummy_leader_id, dummy_leader_tokens);
|
||||
assert_eq!(genesis_block.bootstrap_leader_tokens, dummy_leader_tokens);
|
||||
GenesisBlock::new_with_leader(10_000, dummy_leader_id, dummy_leader_lamports);
|
||||
assert_eq!(
|
||||
genesis_block.bootstrap_leader_lamports,
|
||||
dummy_leader_lamports
|
||||
);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
assert_eq!(
|
||||
bank.get_balance(&genesis_block.mint_id),
|
||||
10_000 - dummy_leader_tokens
|
||||
10_000 - dummy_leader_lamports
|
||||
);
|
||||
assert_eq!(
|
||||
bank.get_balance(&dummy_leader_id),
|
||||
dummy_leader_tokens - 1 /* 1 token goes to the vote account associated with dummy_leader_tokens */
|
||||
dummy_leader_lamports - 1 /* 1 token goes to the vote account associated with dummy_leader_lamports */
|
||||
);
|
||||
}
|
||||
|
||||
@ -878,7 +884,7 @@ mod tests {
|
||||
let key1 = Keypair::new().pubkey();
|
||||
let key2 = Keypair::new().pubkey();
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let spend = SystemInstruction::Move { tokens: 1 };
|
||||
let spend = SystemInstruction::Move { lamports: 1 };
|
||||
let instructions = vec![
|
||||
Instruction {
|
||||
program_ids_index: 0,
|
||||
@ -909,7 +915,7 @@ mod tests {
|
||||
bank.get_signature_status(&t1.signatures[0]),
|
||||
Some(Err(BankError::ProgramError(
|
||||
1,
|
||||
ProgramError::ResultWithNegativeTokens
|
||||
ProgramError::ResultWithNegativeLamports
|
||||
)))
|
||||
);
|
||||
}
|
||||
@ -957,11 +963,11 @@ mod tests {
|
||||
bank.process_transaction(&tx),
|
||||
Err(BankError::ProgramError(
|
||||
0,
|
||||
ProgramError::ResultWithNegativeTokens
|
||||
ProgramError::ResultWithNegativeLamports
|
||||
))
|
||||
);
|
||||
|
||||
// The tokens didn't move, but the from address paid the transaction fee.
|
||||
// The lamports didn't move, but the from address paid the transaction fee.
|
||||
assert_eq!(bank.get_balance(&dest.pubkey()), 0);
|
||||
|
||||
// This should be the original balance minus the transaction fee.
|
||||
@ -993,7 +999,7 @@ mod tests {
|
||||
bank.transfer(10_001, &mint_keypair, pubkey, genesis_block.hash()),
|
||||
Err(BankError::ProgramError(
|
||||
0,
|
||||
ProgramError::ResultWithNegativeTokens
|
||||
ProgramError::ResultWithNegativeLamports
|
||||
))
|
||||
);
|
||||
assert_eq!(bank.transaction_count(), 1);
|
||||
@ -1094,7 +1100,7 @@ mod tests {
|
||||
Ok(()),
|
||||
Err(BankError::ProgramError(
|
||||
1,
|
||||
ProgramError::ResultWithNegativeTokens,
|
||||
ProgramError::ResultWithNegativeLamports,
|
||||
)),
|
||||
];
|
||||
|
||||
@ -1135,9 +1141,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_process_genesis() {
|
||||
let dummy_leader_id = Keypair::new().pubkey();
|
||||
let dummy_leader_tokens = 3;
|
||||
let dummy_leader_lamports = 3;
|
||||
let (genesis_block, _) =
|
||||
GenesisBlock::new_with_leader(5, dummy_leader_id, dummy_leader_tokens);
|
||||
GenesisBlock::new_with_leader(5, dummy_leader_id, dummy_leader_lamports);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
assert_eq!(bank.get_balance(&genesis_block.mint_id), 2);
|
||||
assert_eq!(bank.get_balance(&dummy_leader_id), 2);
|
||||
@ -1418,8 +1424,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_bank_epoch_vote_accounts() {
|
||||
let leader_id = Keypair::new().pubkey();
|
||||
let leader_tokens = 3;
|
||||
let (mut genesis_block, _) = GenesisBlock::new_with_leader(5, leader_id, leader_tokens);
|
||||
let leader_lamports = 3;
|
||||
let (mut genesis_block, _) = GenesisBlock::new_with_leader(5, leader_id, leader_lamports);
|
||||
|
||||
// set this up weird, forces:
|
||||
// 1. genesis bank to cover epochs 0, 1, *and* 2
|
||||
@ -1485,13 +1491,13 @@ mod tests {
|
||||
let bank = Arc::new(Bank::new(&genesis_block));
|
||||
let key = Keypair::new();
|
||||
|
||||
let move_tokens = SystemInstruction::Move { tokens: 1 };
|
||||
let move_lamports = SystemInstruction::Move { lamports: 1 };
|
||||
|
||||
let mut tx = Transaction::new_unsigned(
|
||||
&mint_keypair.pubkey(),
|
||||
&[key.pubkey()],
|
||||
system_program::id(),
|
||||
&move_tokens,
|
||||
&move_lamports,
|
||||
bank.last_blockhash(),
|
||||
2,
|
||||
);
|
||||
|
@ -57,7 +57,7 @@ fn process_instruction(
|
||||
fn verify_instruction(
|
||||
program_id: &Pubkey,
|
||||
pre_program_id: &Pubkey,
|
||||
pre_tokens: u64,
|
||||
pre_lamports: u64,
|
||||
pre_userdata: &[u8],
|
||||
account: &Account,
|
||||
) -> Result<(), ProgramError> {
|
||||
@ -68,8 +68,8 @@ fn verify_instruction(
|
||||
return Err(ProgramError::ModifiedProgramId);
|
||||
}
|
||||
// For accounts unassigned to the program, the individual balance of each accounts cannot decrease.
|
||||
if *program_id != account.owner && pre_tokens > account.tokens {
|
||||
return Err(ProgramError::ExternalAccountTokenSpend);
|
||||
if *program_id != account.owner && pre_lamports > account.lamports {
|
||||
return Err(ProgramError::ExternalAccountLamportSpend);
|
||||
}
|
||||
// For accounts unassigned to the program, the userdata may not change.
|
||||
if *program_id != account.owner
|
||||
@ -95,10 +95,10 @@ fn execute_instruction(
|
||||
let program_id = tx.program_id(instruction_index);
|
||||
// TODO: the runtime should be checking read/write access to memory
|
||||
// we are trusting the hard-coded programs not to clobber or allocate
|
||||
let pre_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
|
||||
let pre_total: u64 = program_accounts.iter().map(|a| a.lamports).sum();
|
||||
let pre_data: Vec<_> = program_accounts
|
||||
.iter_mut()
|
||||
.map(|a| (a.owner, a.tokens, a.userdata.clone()))
|
||||
.map(|a| (a.owner, a.lamports, a.userdata.clone()))
|
||||
.collect();
|
||||
|
||||
process_instruction(
|
||||
@ -110,19 +110,19 @@ fn execute_instruction(
|
||||
)?;
|
||||
|
||||
// Verify the instruction
|
||||
for ((pre_program_id, pre_tokens, pre_userdata), post_account) in
|
||||
for ((pre_program_id, pre_lamports, pre_userdata), post_account) in
|
||||
pre_data.iter().zip(program_accounts.iter())
|
||||
{
|
||||
verify_instruction(
|
||||
&program_id,
|
||||
pre_program_id,
|
||||
*pre_tokens,
|
||||
*pre_lamports,
|
||||
pre_userdata,
|
||||
post_account,
|
||||
)?;
|
||||
}
|
||||
// The total sum of all the tokens in all the accounts cannot change.
|
||||
let post_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
|
||||
// The total sum of all the lamports in all the accounts cannot change.
|
||||
let post_total: u64 = program_accounts.iter().map(|a| a.lamports).sum();
|
||||
if pre_total != post_total {
|
||||
return Err(ProgramError::UnbalancedInstruction);
|
||||
}
|
||||
|
Reference in New Issue
Block a user