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

@ -51,52 +51,57 @@ pub enum BudgetExpr {
}
impl BudgetExpr {
/// Create the simplest budget - one that pays `tokens` to Pubkey.
pub fn new_payment(tokens: u64, to: Pubkey) -> Self {
BudgetExpr::Pay(Payment { tokens, to })
/// Create the simplest budget - one that pays `lamports` to Pubkey.
pub fn new_payment(lamports: u64, to: Pubkey) -> Self {
BudgetExpr::Pay(Payment { lamports, to })
}
/// Create a budget that pays `tokens` to `to` after being witnessed by `from`.
pub fn new_authorized_payment(from: Pubkey, tokens: u64, to: Pubkey) -> Self {
/// Create a budget that pays `lamports` to `to` after being witnessed by `from`.
pub fn new_authorized_payment(from: Pubkey, lamports: u64, to: Pubkey) -> Self {
BudgetExpr::After(
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
pub fn new_2_2_multisig_payment(from0: Pubkey, from1: Pubkey, tokens: u64, to: Pubkey) -> Self {
/// 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,
lamports: u64,
to: Pubkey,
) -> Self {
BudgetExpr::And(
Condition::Signature(from0),
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.
pub fn new_future_payment(dt: DateTime<Utc>, from: Pubkey, tokens: u64, to: Pubkey) -> Self {
/// Create a budget that pays `lamports` to `to` after the given DateTime.
pub fn new_future_payment(dt: DateTime<Utc>, from: Pubkey, lamports: u64, to: Pubkey) -> Self {
BudgetExpr::After(
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`.
pub fn new_cancelable_future_payment(
dt: DateTime<Utc>,
from: Pubkey,
tokens: u64,
lamports: u64,
to: Pubkey,
) -> Self {
BudgetExpr::Or(
(
Condition::Timestamp(dt, from),
Box::new(Self::new_payment(tokens, to)),
Box::new(Self::new_payment(lamports, to)),
),
(
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`.
pub fn verify(&self, spendable_tokens: u64) -> bool {
/// Return true if the budget spends exactly `spendable_lamports`.
pub fn verify(&self, spendable_lamports: u64) -> bool {
match self {
BudgetExpr::Pay(payment) => payment.tokens == spendable_tokens,
BudgetExpr::Pay(payment) => payment.lamports == spendable_lamports,
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.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Contract {
/// The number of tokens allocated to the `BudgetExpr` and any transaction fees.
pub tokens: u64,
/// The number of lamports allocated to the `BudgetExpr` and any transaction fees.
pub lamports: u64,
pub budget_expr: BudgetExpr,
}

View File

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

View File

@ -20,19 +20,19 @@ impl BudgetTransaction {
pub fn new_payment(
from_keypair: &Keypair,
to: Pubkey,
tokens: u64,
lamports: u64,
recent_blockhash: Hash,
fee: u64,
) -> Transaction {
let contract = Keypair::new().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();
TransactionBuilder::new(fee)
.push(SystemInstruction::new_program_account(
from,
contract,
tokens,
lamports,
space,
id(),
))
@ -45,10 +45,10 @@ impl BudgetTransaction {
pub fn new(
from_keypair: &Keypair,
to: Pubkey,
tokens: u64,
lamports: u64,
recent_blockhash: Hash,
) -> 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.
@ -93,24 +93,24 @@ impl BudgetTransaction {
dt: DateTime<Utc>,
dt_pubkey: Pubkey,
cancelable: Option<Pubkey>,
tokens: u64,
lamports: u64,
recent_blockhash: Hash,
) -> Transaction {
let expr = if let Some(from) = cancelable {
BudgetExpr::Or(
(
Condition::Timestamp(dt, dt_pubkey),
Box::new(BudgetExpr::new_payment(tokens, to)),
Box::new(BudgetExpr::new_payment(lamports, to)),
),
(
Condition::Signature(from),
Box::new(BudgetExpr::new_payment(tokens, from)),
Box::new(BudgetExpr::new_payment(lamports, from)),
),
)
} else {
BudgetExpr::After(
Condition::Timestamp(dt, dt_pubkey),
Box::new(BudgetExpr::new_payment(tokens, to)),
Box::new(BudgetExpr::new_payment(lamports, to)),
)
};
let instruction = BudgetInstruction::InitializeAccount(expr);
@ -130,24 +130,24 @@ impl BudgetTransaction {
contract: Pubkey,
witness: Pubkey,
cancelable: Option<Pubkey>,
tokens: u64,
lamports: u64,
recent_blockhash: Hash,
) -> Transaction {
let expr = if let Some(from) = cancelable {
BudgetExpr::Or(
(
Condition::Signature(witness),
Box::new(BudgetExpr::new_payment(tokens, to)),
Box::new(BudgetExpr::new_payment(lamports, to)),
),
(
Condition::Signature(from),
Box::new(BudgetExpr::new_payment(tokens, from)),
Box::new(BudgetExpr::new_payment(lamports, from)),
),
)
} else {
BudgetExpr::After(
Condition::Signature(witness),
Box::new(BudgetExpr::new_payment(tokens, to)),
Box::new(BudgetExpr::new_payment(lamports, to)),
)
};
let instruction = BudgetInstruction::InitializeAccount(expr);
@ -230,7 +230,7 @@ mod tests {
}
#[test]
fn test_token_attack() {
fn test_lamport_attack() {
let zero = Hash::default();
let keypair = Keypair::new();
let pubkey = keypair.pubkey();
@ -244,7 +244,7 @@ mod tests {
let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap();
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
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();
@ -282,17 +282,17 @@ mod tests {
let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap();
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
if let BudgetExpr::Pay(ref mut payment) = expr {
payment.tokens = 2; // <-- attack!
payment.lamports = 2; // <-- attack!
}
}
tx.instructions[1].userdata = serialize(&instruction).unwrap();
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();
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
if let BudgetExpr::Pay(ref mut payment) = expr {
payment.tokens = 0; // <-- whoops!
payment.lamports = 0; // <-- whoops!
}
}
tx.instructions[1].userdata = serialize(&instruction).unwrap();

View File

@ -17,12 +17,12 @@ pub enum Witness {
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)]
pub struct Payment {
/// 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,
}