Rename tokens to lamports in programs/

This commit is contained in:
Michael Vines 2019-03-05 17:27:25 -08:00
parent 0604bbb473
commit 3129e299e4
11 changed files with 77 additions and 71 deletions

View File

@ -24,13 +24,13 @@ extern bool entrypoint(const uint8_t *input) {
return false; return false;
} }
int64_t tokens = *(int64_t *)params.data; int64_t lamports = *(int64_t *)params.data;
if (*params.ka[0].tokens >= tokens) { if (*params.ka[0].lamports >= lamports) {
*params.ka[0].tokens -= tokens; *params.ka[0].lamports -= lamports;
*params.ka[2].tokens += tokens; *params.ka[2].lamports += lamports;
// sol_log_64(0, 0, *ka[0].tokens, *ka[2].tokens, tokens); // sol_log_64(0, 0, *ka[0].lamports, *ka[2].lamports, lamports);
} else { } else {
// sol_log_64(0, 0, 0xFF, *ka[0].tokens, tokens); // sol_log_64(0, 0, 0xFF, *ka[0].lamports, lamports);
} }
return true; return true;
} }

View File

@ -27,8 +27,8 @@ fn apply_signature(
if let Some(key) = keyed_accounts[0].signer_key() { if let Some(key) = keyed_accounts[0].signer_key() {
if &payment.to == key { if &payment.to == key {
budget_state.pending_budget = None; budget_state.pending_budget = None;
keyed_accounts[1].account.lamports -= payment.tokens; keyed_accounts[1].account.lamports -= payment.lamports;
keyed_accounts[0].account.lamports += payment.tokens; keyed_accounts[0].account.lamports += payment.lamports;
return Ok(()); return Ok(());
} }
} }
@ -37,8 +37,8 @@ fn apply_signature(
return Err(BudgetError::DestinationMissing); return Err(BudgetError::DestinationMissing);
} }
budget_state.pending_budget = None; budget_state.pending_budget = None;
keyed_accounts[1].account.lamports -= payment.tokens; keyed_accounts[1].account.lamports -= payment.lamports;
keyed_accounts[2].account.lamports += payment.tokens; keyed_accounts[2].account.lamports += payment.lamports;
} }
Ok(()) Ok(())
} }
@ -68,8 +68,8 @@ fn apply_timestamp(
return Err(BudgetError::DestinationMissing); return Err(BudgetError::DestinationMissing);
} }
budget_state.pending_budget = None; budget_state.pending_budget = None;
keyed_accounts[1].account.lamports -= payment.tokens; keyed_accounts[1].account.lamports -= payment.lamports;
keyed_accounts[2].account.lamports += payment.tokens; keyed_accounts[2].account.lamports += payment.lamports;
} }
Ok(()) Ok(())
} }
@ -87,7 +87,7 @@ fn apply_debits(
let expr = expr.clone(); let expr = expr.clone();
if let Some(payment) = expr.final_payment() { if let Some(payment) = expr.final_payment() {
keyed_accounts[1].account.lamports = 0; keyed_accounts[1].account.lamports = 0;
keyed_accounts[0].account.lamports += payment.tokens; keyed_accounts[0].account.lamports += payment.lamports;
Ok(()) Ok(())
} else { } else {
let existing = BudgetState::deserialize(&keyed_accounts[1].account.userdata).ok(); let existing = BudgetState::deserialize(&keyed_accounts[1].account.userdata).ok();

View File

@ -51,52 +51,57 @@ pub enum BudgetExpr {
} }
impl BudgetExpr { impl BudgetExpr {
/// Create the simplest budget - one that pays `tokens` to Pubkey. /// Create the simplest budget - one that pays `lamports` to Pubkey.
pub fn new_payment(tokens: u64, to: Pubkey) -> Self { pub fn new_payment(lamports: u64, to: Pubkey) -> Self {
BudgetExpr::Pay(Payment { tokens, to }) BudgetExpr::Pay(Payment { lamports, to })
} }
/// Create a budget that pays `tokens` to `to` after being witnessed by `from`. /// Create a budget that pays `lamports` to `to` after being witnessed by `from`.
pub fn new_authorized_payment(from: Pubkey, tokens: u64, to: Pubkey) -> Self { pub fn new_authorized_payment(from: Pubkey, lamports: u64, to: Pubkey) -> Self {
BudgetExpr::After( BudgetExpr::After(
Condition::Signature(from), Condition::Signature(from),
Box::new(Self::new_payment(tokens, to)), Box::new(Self::new_payment(lamports, to)),
) )
} }
/// Create a budget that pays tokens` to `to` after being witnessed by 2x `from`s /// Create a budget that pays lamports` to `to` after being witnessed by 2x `from`s
pub fn new_2_2_multisig_payment(from0: Pubkey, from1: Pubkey, tokens: u64, to: Pubkey) -> Self { pub fn new_2_2_multisig_payment(
from0: Pubkey,
from1: Pubkey,
lamports: u64,
to: Pubkey,
) -> Self {
BudgetExpr::And( BudgetExpr::And(
Condition::Signature(from0), Condition::Signature(from0),
Condition::Signature(from1), Condition::Signature(from1),
Box::new(Self::new_payment(tokens, to)), Box::new(Self::new_payment(lamports, to)),
) )
} }
/// Create a budget that pays `tokens` to `to` after the given DateTime. /// Create a budget that pays `lamports` to `to` after the given DateTime.
pub fn new_future_payment(dt: DateTime<Utc>, from: Pubkey, tokens: u64, to: Pubkey) -> Self { pub fn new_future_payment(dt: DateTime<Utc>, from: Pubkey, lamports: u64, to: Pubkey) -> Self {
BudgetExpr::After( BudgetExpr::After(
Condition::Timestamp(dt, from), Condition::Timestamp(dt, from),
Box::new(Self::new_payment(tokens, to)), Box::new(Self::new_payment(lamports, to)),
) )
} }
/// Create a budget that pays `tokens` to `to` after the given DateTime /// Create a budget that pays `lamports` to `to` after the given DateTime
/// unless cancelled by `from`. /// unless cancelled by `from`.
pub fn new_cancelable_future_payment( pub fn new_cancelable_future_payment(
dt: DateTime<Utc>, dt: DateTime<Utc>,
from: Pubkey, from: Pubkey,
tokens: u64, lamports: u64,
to: Pubkey, to: Pubkey,
) -> Self { ) -> Self {
BudgetExpr::Or( BudgetExpr::Or(
( (
Condition::Timestamp(dt, from), Condition::Timestamp(dt, from),
Box::new(Self::new_payment(tokens, to)), Box::new(Self::new_payment(lamports, to)),
), ),
( (
Condition::Signature(from), Condition::Signature(from),
Box::new(Self::new_payment(tokens, to)), Box::new(Self::new_payment(lamports, to)),
), ),
) )
} }
@ -109,14 +114,16 @@ impl BudgetExpr {
} }
} }
/// Return true if the budget spends exactly `spendable_tokens`. /// Return true if the budget spends exactly `spendable_lamports`.
pub fn verify(&self, spendable_tokens: u64) -> bool { pub fn verify(&self, spendable_lamports: u64) -> bool {
match self { match self {
BudgetExpr::Pay(payment) => payment.tokens == spendable_tokens, BudgetExpr::Pay(payment) => payment.lamports == spendable_lamports,
BudgetExpr::After(_, sub_expr) | BudgetExpr::And(_, _, sub_expr) => { BudgetExpr::After(_, sub_expr) | BudgetExpr::And(_, _, sub_expr) => {
sub_expr.verify(spendable_tokens) sub_expr.verify(spendable_lamports)
}
BudgetExpr::Or(a, b) => {
a.1.verify(spendable_lamports) && b.1.verify(spendable_lamports)
} }
BudgetExpr::Or(a, b) => a.1.verify(spendable_tokens) && b.1.verify(spendable_tokens),
} }
} }

View File

@ -8,8 +8,8 @@ use solana_sdk::transaction_builder::BuilderInstruction;
/// A smart contract. /// A smart contract.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Contract { pub struct Contract {
/// The number of tokens allocated to the `BudgetExpr` and any transaction fees. /// The number of lamports allocated to the `BudgetExpr` and any transaction fees.
pub tokens: u64, pub lamports: u64,
pub budget_expr: BudgetExpr, pub budget_expr: BudgetExpr,
} }

View File

@ -10,7 +10,6 @@ pub enum BudgetError {
ContractNotPending, ContractNotPending,
SourceIsPendingContract, SourceIsPendingContract,
UninitializedContract, UninitializedContract,
NegativeTokens,
DestinationMissing, DestinationMissing,
FailedWitness, FailedWitness,
UserdataTooSmall, UserdataTooSmall,

View File

@ -20,19 +20,19 @@ impl BudgetTransaction {
pub fn new_payment( pub fn new_payment(
from_keypair: &Keypair, from_keypair: &Keypair,
to: Pubkey, to: Pubkey,
tokens: u64, lamports: u64,
recent_blockhash: Hash, recent_blockhash: Hash,
fee: u64, fee: u64,
) -> Transaction { ) -> Transaction {
let contract = Keypair::new().pubkey(); let contract = Keypair::new().pubkey();
let from = from_keypair.pubkey(); let from = from_keypair.pubkey();
let payment = BudgetExpr::new_payment(tokens - fee, to); let payment = BudgetExpr::new_payment(lamports - fee, to);
let space = serialized_size(&BudgetState::new(payment.clone())).unwrap(); let space = serialized_size(&BudgetState::new(payment.clone())).unwrap();
TransactionBuilder::new(fee) TransactionBuilder::new(fee)
.push(SystemInstruction::new_program_account( .push(SystemInstruction::new_program_account(
from, from,
contract, contract,
tokens, lamports,
space, space,
id(), id(),
)) ))
@ -45,10 +45,10 @@ impl BudgetTransaction {
pub fn new( pub fn new(
from_keypair: &Keypair, from_keypair: &Keypair,
to: Pubkey, to: Pubkey,
tokens: u64, lamports: u64,
recent_blockhash: Hash, recent_blockhash: Hash,
) -> Transaction { ) -> Transaction {
Self::new_payment(from_keypair, to, tokens, recent_blockhash, 0) Self::new_payment(from_keypair, to, lamports, recent_blockhash, 0)
} }
/// Create and sign a new Witness Timestamp. Used for unit-testing. /// Create and sign a new Witness Timestamp. Used for unit-testing.
@ -93,24 +93,24 @@ impl BudgetTransaction {
dt: DateTime<Utc>, dt: DateTime<Utc>,
dt_pubkey: Pubkey, dt_pubkey: Pubkey,
cancelable: Option<Pubkey>, cancelable: Option<Pubkey>,
tokens: u64, lamports: u64,
recent_blockhash: Hash, recent_blockhash: Hash,
) -> Transaction { ) -> Transaction {
let expr = if let Some(from) = cancelable { let expr = if let Some(from) = cancelable {
BudgetExpr::Or( BudgetExpr::Or(
( (
Condition::Timestamp(dt, dt_pubkey), Condition::Timestamp(dt, dt_pubkey),
Box::new(BudgetExpr::new_payment(tokens, to)), Box::new(BudgetExpr::new_payment(lamports, to)),
), ),
( (
Condition::Signature(from), Condition::Signature(from),
Box::new(BudgetExpr::new_payment(tokens, from)), Box::new(BudgetExpr::new_payment(lamports, from)),
), ),
) )
} else { } else {
BudgetExpr::After( BudgetExpr::After(
Condition::Timestamp(dt, dt_pubkey), Condition::Timestamp(dt, dt_pubkey),
Box::new(BudgetExpr::new_payment(tokens, to)), Box::new(BudgetExpr::new_payment(lamports, to)),
) )
}; };
let instruction = BudgetInstruction::InitializeAccount(expr); let instruction = BudgetInstruction::InitializeAccount(expr);
@ -130,24 +130,24 @@ impl BudgetTransaction {
contract: Pubkey, contract: Pubkey,
witness: Pubkey, witness: Pubkey,
cancelable: Option<Pubkey>, cancelable: Option<Pubkey>,
tokens: u64, lamports: u64,
recent_blockhash: Hash, recent_blockhash: Hash,
) -> Transaction { ) -> Transaction {
let expr = if let Some(from) = cancelable { let expr = if let Some(from) = cancelable {
BudgetExpr::Or( BudgetExpr::Or(
( (
Condition::Signature(witness), Condition::Signature(witness),
Box::new(BudgetExpr::new_payment(tokens, to)), Box::new(BudgetExpr::new_payment(lamports, to)),
), ),
( (
Condition::Signature(from), Condition::Signature(from),
Box::new(BudgetExpr::new_payment(tokens, from)), Box::new(BudgetExpr::new_payment(lamports, from)),
), ),
) )
} else { } else {
BudgetExpr::After( BudgetExpr::After(
Condition::Signature(witness), Condition::Signature(witness),
Box::new(BudgetExpr::new_payment(tokens, to)), Box::new(BudgetExpr::new_payment(lamports, to)),
) )
}; };
let instruction = BudgetInstruction::InitializeAccount(expr); let instruction = BudgetInstruction::InitializeAccount(expr);
@ -230,7 +230,7 @@ mod tests {
} }
#[test] #[test]
fn test_token_attack() { fn test_lamport_attack() {
let zero = Hash::default(); let zero = Hash::default();
let keypair = Keypair::new(); let keypair = Keypair::new();
let pubkey = keypair.pubkey(); let pubkey = keypair.pubkey();
@ -244,7 +244,7 @@ mod tests {
let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap(); let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap();
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction { if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
if let BudgetExpr::Pay(ref mut payment) = expr { if let BudgetExpr::Pay(ref mut payment) = expr {
payment.tokens = *lamports; // <-- attack, part 2! payment.lamports = *lamports; // <-- attack, part 2!
} }
} }
tx.instructions[1].userdata = serialize(&instruction).unwrap(); tx.instructions[1].userdata = serialize(&instruction).unwrap();
@ -282,17 +282,17 @@ mod tests {
let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap(); let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap();
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction { if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
if let BudgetExpr::Pay(ref mut payment) = expr { if let BudgetExpr::Pay(ref mut payment) = expr {
payment.tokens = 2; // <-- attack! payment.lamports = 2; // <-- attack!
} }
} }
tx.instructions[1].userdata = serialize(&instruction).unwrap(); tx.instructions[1].userdata = serialize(&instruction).unwrap();
assert!(!BudgetTransaction::verify_plan(&tx)); assert!(!BudgetTransaction::verify_plan(&tx));
// Also, ensure all branchs of the plan spend all tokens // Also, ensure all branchs of the plan spend all lamports
let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap(); let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap();
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction { if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
if let BudgetExpr::Pay(ref mut payment) = expr { if let BudgetExpr::Pay(ref mut payment) = expr {
payment.tokens = 0; // <-- whoops! payment.lamports = 0; // <-- whoops!
} }
} }
tx.instructions[1].userdata = serialize(&instruction).unwrap(); tx.instructions[1].userdata = serialize(&instruction).unwrap();

View File

@ -17,12 +17,12 @@ pub enum Witness {
Signature, Signature,
} }
/// Some amount of tokens that should be sent to the `to` `Pubkey`. /// Some amount of lamports that should be sent to the `to` `Pubkey`.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Payment { pub struct Payment {
/// Amount to be paid. /// Amount to be paid.
pub tokens: u64, pub lamports: u64,
/// The `Pubkey` that `tokens` should be paid to. /// The `Pubkey` that `lamports` should be paid to.
pub to: Pubkey, pub to: Pubkey,
} }

View File

@ -64,7 +64,7 @@ fn test_redeem_vote_credits_via_bank() {
let bank = Bank::new(&genesis_block); let bank = Bank::new(&genesis_block);
let rewards_bank = RewardsBank::new(&bank); let rewards_bank = RewardsBank::new(&bank);
// Create a rewards account to hold all rewards pool tokens. // Create a rewards account to hold all rewards pool lamports.
let rewards_keypair = Keypair::new(); let rewards_keypair = Keypair::new();
let rewards_id = rewards_keypair.pubkey(); let rewards_id = rewards_keypair.pubkey();
rewards_bank rewards_bank
@ -91,13 +91,13 @@ fn test_redeem_vote_credits_via_bank() {
// TODO: Add VoteInstruction::RegisterStakerId so that we don't need to point the "to" // TODO: Add VoteInstruction::RegisterStakerId so that we don't need to point the "to"
// account to the "from" account. // account to the "from" account.
let to_id = vote_id; let to_id = vote_id;
let to_tokens = bank.get_balance(&vote_id); let to_lamports = bank.get_balance(&vote_id);
// Periodically, the staker sumbits its vote account to the rewards pool // Periodically, the staker sumbits its vote account to the rewards pool
// to exchange its credits for lamports. // to exchange its credits for lamports.
let vote_state = rewards_bank let vote_state = rewards_bank
.redeem_credits(rewards_id, &vote_keypair) .redeem_credits(rewards_id, &vote_keypair)
.unwrap(); .unwrap();
assert!(bank.get_balance(&to_id) > to_tokens); assert!(bank.get_balance(&to_id) > to_lamports);
assert_eq!(vote_state.credits(), 0); assert_eq!(vote_state.credits(), 0);
} }

View File

@ -19,14 +19,14 @@ impl RewardsTransaction {
from_keypair: &Keypair, from_keypair: &Keypair,
rewards_id: Pubkey, rewards_id: Pubkey,
blockhash: Hash, blockhash: Hash,
num_tokens: u64, lamports: u64,
fee: u64, fee: u64,
) -> Transaction { ) -> Transaction {
SystemTransaction::new_program_account( SystemTransaction::new_program_account(
from_keypair, from_keypair,
rewards_id, rewards_id,
blockhash, blockhash,
num_tokens, lamports,
RewardsState::max_size() as u64, RewardsState::max_size() as u64,
id(), id(),
fee, fee,

View File

@ -229,9 +229,9 @@ pub fn clear_credits(keyed_accounts: &mut [KeyedAccount]) -> Result<(), ProgramE
Ok(()) Ok(())
} }
pub fn create_vote_account(tokens: u64) -> Account { pub fn create_vote_account(lamports: u64) -> Account {
let space = VoteState::max_size(); let space = VoteState::max_size();
Account::new(tokens, space, id()) Account::new(lamports, space, id())
} }
pub fn initialize_and_deserialize( pub fn initialize_and_deserialize(

View File

@ -26,12 +26,12 @@ impl VoteTransaction {
.sign(&[voting_keypair], recent_blockhash) .sign(&[voting_keypair], recent_blockhash)
} }
/// Fund or create the staking account with tokens /// Fund or create the staking account with lamports
pub fn new_account( pub fn new_account(
from_keypair: &Keypair, from_keypair: &Keypair,
voter_id: Pubkey, voter_id: Pubkey,
recent_blockhash: Hash, recent_blockhash: Hash,
num_tokens: u64, lamports: u64,
fee: u64, fee: u64,
) -> Transaction { ) -> Transaction {
let from_id = from_keypair.pubkey(); let from_id = from_keypair.pubkey();
@ -40,7 +40,7 @@ impl VoteTransaction {
.push(SystemInstruction::new_program_account( .push(SystemInstruction::new_program_account(
from_id, from_id,
voter_id, voter_id,
num_tokens, lamports,
space, space,
id(), id(),
)) ))
@ -48,13 +48,13 @@ impl VoteTransaction {
.sign(&[from_keypair], recent_blockhash) .sign(&[from_keypair], recent_blockhash)
} }
/// Fund or create the staking account with tokens /// Fund or create the staking account with lamports
pub fn new_account_with_delegate( pub fn new_account_with_delegate(
from_keypair: &Keypair, from_keypair: &Keypair,
voter_keypair: &Keypair, voter_keypair: &Keypair,
delegate_id: Pubkey, delegate_id: Pubkey,
recent_blockhash: Hash, recent_blockhash: Hash,
num_tokens: u64, lamports: u64,
fee: u64, fee: u64,
) -> Transaction { ) -> Transaction {
let from_id = from_keypair.pubkey(); let from_id = from_keypair.pubkey();
@ -64,7 +64,7 @@ impl VoteTransaction {
.push(SystemInstruction::new_program_account( .push(SystemInstruction::new_program_account(
from_id, from_id,
voter_id, voter_id,
num_tokens, lamports,
space, space,
id(), id(),
)) ))