pass Pubkeys as refs, copy only where values needed (#3213)
* pass Pubkeys as refs, copy only where values needed * Pubkey is pervasive * fixup
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
//! The `budget_expr` module provides a domain-specific language for payment plans. Users create BudgetExpr objects that
|
||||
//! The `budget_expr` module provides a domain-specific language for pa&yment plans. Users create BudgetExpr objects that
|
||||
//! are given to an interpreter. The interpreter listens for `Witness` transactions,
|
||||
//! which it uses to reduce the payment plan. When the budget is reduced to a
|
||||
//! `Payment`, the payment is executed.
|
||||
@ -52,36 +52,41 @@ pub enum BudgetExpr {
|
||||
|
||||
impl BudgetExpr {
|
||||
/// Create the simplest budget - one that pays `lamports` to Pubkey.
|
||||
pub fn new_payment(lamports: u64, to: Pubkey) -> Self {
|
||||
BudgetExpr::Pay(Payment { lamports, to })
|
||||
pub fn new_payment(lamports: u64, to: &Pubkey) -> Self {
|
||||
BudgetExpr::Pay(Payment { lamports, to: *to })
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
pub fn new_authorized_payment(from: &Pubkey, lamports: u64, to: &Pubkey) -> Self {
|
||||
BudgetExpr::After(
|
||||
Condition::Signature(from),
|
||||
Condition::Signature(*from),
|
||||
Box::new(Self::new_payment(lamports, to)),
|
||||
)
|
||||
}
|
||||
|
||||
/// 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,
|
||||
from0: &Pubkey,
|
||||
from1: &Pubkey,
|
||||
lamports: u64,
|
||||
to: Pubkey,
|
||||
to: &Pubkey,
|
||||
) -> Self {
|
||||
BudgetExpr::And(
|
||||
Condition::Signature(from0),
|
||||
Condition::Signature(from1),
|
||||
Condition::Signature(*from0),
|
||||
Condition::Signature(*from1),
|
||||
Box::new(Self::new_payment(lamports, to)),
|
||||
)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
pub fn new_future_payment(
|
||||
dt: DateTime<Utc>,
|
||||
from: &Pubkey,
|
||||
lamports: u64,
|
||||
to: &Pubkey,
|
||||
) -> Self {
|
||||
BudgetExpr::After(
|
||||
Condition::Timestamp(dt, from),
|
||||
Condition::Timestamp(dt, *from),
|
||||
Box::new(Self::new_payment(lamports, to)),
|
||||
)
|
||||
}
|
||||
@ -90,17 +95,17 @@ impl BudgetExpr {
|
||||
/// unless cancelled by `from`.
|
||||
pub fn new_cancelable_future_payment(
|
||||
dt: DateTime<Utc>,
|
||||
from: Pubkey,
|
||||
from: &Pubkey,
|
||||
lamports: u64,
|
||||
to: Pubkey,
|
||||
to: &Pubkey,
|
||||
) -> Self {
|
||||
BudgetExpr::Or(
|
||||
(
|
||||
Condition::Timestamp(dt, from),
|
||||
Condition::Timestamp(dt, *from),
|
||||
Box::new(Self::new_payment(lamports, to)),
|
||||
),
|
||||
(
|
||||
Condition::Signature(from),
|
||||
Condition::Signature(*from),
|
||||
Box::new(Self::new_payment(lamports, to)),
|
||||
),
|
||||
)
|
||||
@ -183,10 +188,10 @@ mod tests {
|
||||
let dt = Utc.ymd(2014, 11, 14).and_hms(8, 9, 10);
|
||||
let from = Pubkey::default();
|
||||
let to = Pubkey::default();
|
||||
assert!(BudgetExpr::new_payment(42, to).verify(42));
|
||||
assert!(BudgetExpr::new_authorized_payment(from, 42, to).verify(42));
|
||||
assert!(BudgetExpr::new_future_payment(dt, from, 42, to).verify(42));
|
||||
assert!(BudgetExpr::new_cancelable_future_payment(dt, from, 42, to).verify(42));
|
||||
assert!(BudgetExpr::new_payment(42, &to).verify(42));
|
||||
assert!(BudgetExpr::new_authorized_payment(&from, 42, &to).verify(42));
|
||||
assert!(BudgetExpr::new_future_payment(dt, &from, 42, &to).verify(42));
|
||||
assert!(BudgetExpr::new_cancelable_future_payment(dt, &from, 42, &to).verify(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -194,9 +199,9 @@ mod tests {
|
||||
let from = Pubkey::default();
|
||||
let to = Pubkey::default();
|
||||
|
||||
let mut expr = BudgetExpr::new_authorized_payment(from, 42, to);
|
||||
let mut expr = BudgetExpr::new_authorized_payment(&from, 42, &to);
|
||||
expr.apply_witness(&Witness::Signature, &from);
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, to));
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, &to));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -205,9 +210,9 @@ mod tests {
|
||||
let from = Keypair::new().pubkey();
|
||||
let to = Keypair::new().pubkey();
|
||||
|
||||
let mut expr = BudgetExpr::new_future_payment(dt, from, 42, to);
|
||||
let mut expr = BudgetExpr::new_future_payment(dt, &from, 42, &to);
|
||||
expr.apply_witness(&Witness::Timestamp(dt), &from);
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, to));
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, &to));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -218,7 +223,7 @@ mod tests {
|
||||
let from = Keypair::new().pubkey();
|
||||
let to = Keypair::new().pubkey();
|
||||
|
||||
let mut expr = BudgetExpr::new_future_payment(dt, from, 42, to);
|
||||
let mut expr = BudgetExpr::new_future_payment(dt, &from, 42, &to);
|
||||
let orig_expr = expr.clone();
|
||||
expr.apply_witness(&Witness::Timestamp(dt), &to); // <-- Attack!
|
||||
assert_eq!(expr, orig_expr);
|
||||
@ -230,13 +235,13 @@ mod tests {
|
||||
let from = Pubkey::default();
|
||||
let to = Pubkey::default();
|
||||
|
||||
let mut expr = BudgetExpr::new_cancelable_future_payment(dt, from, 42, to);
|
||||
let mut expr = BudgetExpr::new_cancelable_future_payment(dt, &from, 42, &to);
|
||||
expr.apply_witness(&Witness::Timestamp(dt), &from);
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, to));
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, &to));
|
||||
|
||||
let mut expr = BudgetExpr::new_cancelable_future_payment(dt, from, 42, to);
|
||||
let mut expr = BudgetExpr::new_cancelable_future_payment(dt, &from, 42, &to);
|
||||
expr.apply_witness(&Witness::Signature, &from);
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, from));
|
||||
assert_eq!(expr, BudgetExpr::new_payment(42, &from));
|
||||
}
|
||||
#[test]
|
||||
fn test_2_2_multisig_payment() {
|
||||
@ -244,9 +249,9 @@ mod tests {
|
||||
let from1 = Keypair::new().pubkey();
|
||||
let to = Pubkey::default();
|
||||
|
||||
let mut expr = BudgetExpr::new_2_2_multisig_payment(from0, from1, 42, to);
|
||||
let mut expr = BudgetExpr::new_2_2_multisig_payment(&from0, &from1, 42, &to);
|
||||
expr.apply_witness(&Witness::Signature, &from0);
|
||||
assert_eq!(expr, BudgetExpr::new_authorized_payment(from1, 42, to));
|
||||
assert_eq!(expr, BudgetExpr::new_authorized_payment(&from1, 42, &to));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -256,12 +261,12 @@ mod tests {
|
||||
let from2 = Keypair::new().pubkey();
|
||||
let to = Pubkey::default();
|
||||
|
||||
let expr = BudgetExpr::new_2_2_multisig_payment(from0, from1, 42, to);
|
||||
let expr = BudgetExpr::new_2_2_multisig_payment(&from0, &from1, 42, &to);
|
||||
let mut expr = BudgetExpr::After(Condition::Signature(from2), Box::new(expr));
|
||||
|
||||
expr.apply_witness(&Witness::Signature, &from2);
|
||||
expr.apply_witness(&Witness::Signature, &from0);
|
||||
assert_eq!(expr, BudgetExpr::new_authorized_payment(from1, 42, to));
|
||||
assert_eq!(expr, BudgetExpr::new_authorized_payment(&from1, 42, &to));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -271,16 +276,16 @@ mod tests {
|
||||
let dt = Utc.ymd(2014, 11, 11).and_hms(7, 7, 7);
|
||||
let to = Pubkey::default();
|
||||
|
||||
let expr = BudgetExpr::new_2_2_multisig_payment(from0, from1, 42, to);
|
||||
let expr = BudgetExpr::new_2_2_multisig_payment(&from0, &from1, 42, &to);
|
||||
let mut expr = BudgetExpr::After(Condition::Timestamp(dt, from0), Box::new(expr));
|
||||
|
||||
expr.apply_witness(&Witness::Timestamp(dt), &from0);
|
||||
assert_eq!(
|
||||
expr,
|
||||
BudgetExpr::new_2_2_multisig_payment(from0, from1, 42, to)
|
||||
BudgetExpr::new_2_2_multisig_payment(&from0, &from1, 42, &to)
|
||||
);
|
||||
|
||||
expr.apply_witness(&Witness::Signature, &from0);
|
||||
assert_eq!(expr, BudgetExpr::new_authorized_payment(from1, 42, to));
|
||||
assert_eq!(expr, BudgetExpr::new_authorized_payment(&from1, 42, &to));
|
||||
}
|
||||
}
|
||||
|
@ -28,32 +28,36 @@ pub enum BudgetInstruction {
|
||||
}
|
||||
|
||||
impl BudgetInstruction {
|
||||
pub fn new_initialize_account(contract: Pubkey, expr: BudgetExpr) -> BuilderInstruction {
|
||||
pub fn new_initialize_account(contract: &Pubkey, expr: BudgetExpr) -> BuilderInstruction {
|
||||
let mut keys = vec![];
|
||||
if let BudgetExpr::Pay(payment) = &expr {
|
||||
keys.push((payment.to, false));
|
||||
}
|
||||
keys.push((contract, false));
|
||||
keys.push((*contract, false));
|
||||
BuilderInstruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys)
|
||||
}
|
||||
|
||||
pub fn new_apply_timestamp(
|
||||
from: Pubkey,
|
||||
contract: Pubkey,
|
||||
to: Pubkey,
|
||||
from: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
to: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
) -> BuilderInstruction {
|
||||
let mut keys = vec![(from, true), (contract, false)];
|
||||
let mut keys = vec![(*from, true), (*contract, false)];
|
||||
if from != to {
|
||||
keys.push((to, false));
|
||||
keys.push((*to, false));
|
||||
}
|
||||
BuilderInstruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), keys)
|
||||
}
|
||||
|
||||
pub fn new_apply_signature(from: Pubkey, contract: Pubkey, to: Pubkey) -> BuilderInstruction {
|
||||
let mut keys = vec![(from, true), (contract, false)];
|
||||
pub fn new_apply_signature(
|
||||
from: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
to: &Pubkey,
|
||||
) -> BuilderInstruction {
|
||||
let mut keys = vec![(*from, true), (*contract, false)];
|
||||
if from != to {
|
||||
keys.push((to, false));
|
||||
keys.push((*to, false));
|
||||
}
|
||||
BuilderInstruction::new(id(), &BudgetInstruction::ApplySignature, keys)
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_serializer() {
|
||||
let mut a = Account::new(0, 512, id());
|
||||
let mut a = Account::new(0, 512, &id());
|
||||
let b = BudgetState::default();
|
||||
b.serialize(&mut a.userdata).unwrap();
|
||||
let c = BudgetState::deserialize(&a.userdata).unwrap();
|
||||
@ -63,7 +63,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_serializer_userdata_too_small() {
|
||||
let mut a = Account::new(0, 1, id());
|
||||
let mut a = Account::new(0, 1, &id());
|
||||
let b = BudgetState::default();
|
||||
assert_eq!(
|
||||
b.serialize(&mut a.userdata),
|
||||
|
@ -20,7 +20,7 @@ impl BudgetTransaction {
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(
|
||||
from_keypair: &Keypair,
|
||||
contract: Pubkey,
|
||||
contract: &Pubkey,
|
||||
expr: BudgetExpr,
|
||||
lamports: u64,
|
||||
recent_blockhash: Hash,
|
||||
@ -30,11 +30,11 @@ impl BudgetTransaction {
|
||||
let space = serialized_size(&BudgetState::new(expr.clone())).unwrap();
|
||||
TransactionBuilder::new(fee)
|
||||
.push(SystemInstruction::new_program_account(
|
||||
from,
|
||||
&from,
|
||||
contract,
|
||||
lamports,
|
||||
space,
|
||||
id(),
|
||||
&id(),
|
||||
))
|
||||
.push(BudgetInstruction::new_initialize_account(contract, expr))
|
||||
.sign(&[from_keypair], recent_blockhash)
|
||||
@ -43,7 +43,7 @@ impl BudgetTransaction {
|
||||
/// Create and sign a new Transaction. Used for unit-testing.
|
||||
pub fn new_payment(
|
||||
from_keypair: &Keypair,
|
||||
to: Pubkey,
|
||||
to: &Pubkey,
|
||||
lamports: u64,
|
||||
recent_blockhash: Hash,
|
||||
fee: u64,
|
||||
@ -52,7 +52,7 @@ impl BudgetTransaction {
|
||||
let expr = BudgetExpr::new_payment(lamports, to);
|
||||
Self::new(
|
||||
from_keypair,
|
||||
contract,
|
||||
&contract,
|
||||
expr,
|
||||
lamports,
|
||||
recent_blockhash,
|
||||
@ -63,15 +63,15 @@ impl BudgetTransaction {
|
||||
/// Create and sign a new Witness Timestamp. Used for unit-testing.
|
||||
pub fn new_timestamp(
|
||||
from_keypair: &Keypair,
|
||||
contract: Pubkey,
|
||||
to: Pubkey,
|
||||
contract: &Pubkey,
|
||||
to: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
recent_blockhash: Hash,
|
||||
) -> Transaction {
|
||||
let from = from_keypair.pubkey();
|
||||
TransactionBuilder::default()
|
||||
.push(BudgetInstruction::new_apply_timestamp(
|
||||
from, contract, to, dt,
|
||||
&from, contract, to, dt,
|
||||
))
|
||||
.sign(&[from_keypair], recent_blockhash)
|
||||
}
|
||||
@ -79,23 +79,23 @@ impl BudgetTransaction {
|
||||
/// Create and sign a new Witness Signature. Used for unit-testing.
|
||||
pub fn new_signature(
|
||||
from_keypair: &Keypair,
|
||||
contract: Pubkey,
|
||||
to: Pubkey,
|
||||
contract: &Pubkey,
|
||||
to: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
) -> Transaction {
|
||||
let from = from_keypair.pubkey();
|
||||
TransactionBuilder::default()
|
||||
.push(BudgetInstruction::new_apply_signature(from, contract, to))
|
||||
.push(BudgetInstruction::new_apply_signature(&from, contract, to))
|
||||
.sign(&[from_keypair], recent_blockhash)
|
||||
}
|
||||
|
||||
/// Create and sign a postdated Transaction. Used for unit-testing.
|
||||
pub fn new_on_date(
|
||||
from_keypair: &Keypair,
|
||||
to: Pubkey,
|
||||
contract: Pubkey,
|
||||
to: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
dt_pubkey: Pubkey,
|
||||
dt_pubkey: &Pubkey,
|
||||
cancelable: Option<Pubkey>,
|
||||
lamports: u64,
|
||||
recent_blockhash: Hash,
|
||||
@ -103,17 +103,17 @@ impl BudgetTransaction {
|
||||
let expr = if let Some(from) = cancelable {
|
||||
BudgetExpr::Or(
|
||||
(
|
||||
Condition::Timestamp(dt, dt_pubkey),
|
||||
Condition::Timestamp(dt, *dt_pubkey),
|
||||
Box::new(BudgetExpr::new_payment(lamports, to)),
|
||||
),
|
||||
(
|
||||
Condition::Signature(from),
|
||||
Box::new(BudgetExpr::new_payment(lamports, from)),
|
||||
Box::new(BudgetExpr::new_payment(lamports, &from)),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
BudgetExpr::After(
|
||||
Condition::Timestamp(dt, dt_pubkey),
|
||||
Condition::Timestamp(dt, *dt_pubkey),
|
||||
Box::new(BudgetExpr::new_payment(lamports, to)),
|
||||
)
|
||||
};
|
||||
@ -123,9 +123,9 @@ impl BudgetTransaction {
|
||||
/// Create and sign a multisig Transaction.
|
||||
pub fn new_when_signed(
|
||||
from_keypair: &Keypair,
|
||||
to: Pubkey,
|
||||
contract: Pubkey,
|
||||
witness: Pubkey,
|
||||
to: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
witness: &Pubkey,
|
||||
cancelable: Option<Pubkey>,
|
||||
lamports: u64,
|
||||
recent_blockhash: Hash,
|
||||
@ -133,17 +133,17 @@ impl BudgetTransaction {
|
||||
let expr = if let Some(from) = cancelable {
|
||||
BudgetExpr::Or(
|
||||
(
|
||||
Condition::Signature(witness),
|
||||
Condition::Signature(*witness),
|
||||
Box::new(BudgetExpr::new_payment(lamports, to)),
|
||||
),
|
||||
(
|
||||
Condition::Signature(from),
|
||||
Box::new(BudgetExpr::new_payment(lamports, from)),
|
||||
Box::new(BudgetExpr::new_payment(lamports, &from)),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
BudgetExpr::After(
|
||||
Condition::Signature(witness),
|
||||
Condition::Signature(*witness),
|
||||
Box::new(BudgetExpr::new_payment(lamports, to)),
|
||||
)
|
||||
};
|
||||
@ -184,7 +184,7 @@ mod tests {
|
||||
fn test_claim() {
|
||||
let keypair = Keypair::new();
|
||||
let zero = Hash::default();
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair, keypair.pubkey(), 42, zero, 0);
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair, &keypair.pubkey(), 42, zero, 0);
|
||||
assert!(BudgetTransaction::verify_plan(&tx0));
|
||||
}
|
||||
|
||||
@ -194,7 +194,7 @@ mod tests {
|
||||
let keypair0 = Keypair::new();
|
||||
let keypair1 = Keypair::new();
|
||||
let pubkey1 = keypair1.pubkey();
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair0, pubkey1, 42, zero, 0);
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair0, &pubkey1, 42, zero, 0);
|
||||
assert!(BudgetTransaction::verify_plan(&tx0));
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ mod tests {
|
||||
let zero = Hash::default();
|
||||
let keypair0 = Keypair::new();
|
||||
let pubkey1 = Keypair::new().pubkey();
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair0, pubkey1, 1, zero, 1);
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair0, &pubkey1, 1, zero, 1);
|
||||
assert!(BudgetTransaction::verify_plan(&tx0));
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ mod tests {
|
||||
let zero = Hash::default();
|
||||
let keypair0 = Keypair::new();
|
||||
let pubkey1 = Keypair::new().pubkey();
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair0, pubkey1, 1, zero, 1);
|
||||
let tx0 = BudgetTransaction::new_payment(&keypair0, &pubkey1, 1, zero, 1);
|
||||
let buf = serialize(&tx0).unwrap();
|
||||
let tx1: Transaction = deserialize(&buf).unwrap();
|
||||
assert_eq!(tx1, tx0);
|
||||
@ -223,7 +223,7 @@ mod tests {
|
||||
let zero = Hash::default();
|
||||
let keypair = Keypair::new();
|
||||
let pubkey = keypair.pubkey();
|
||||
let mut tx = BudgetTransaction::new_payment(&keypair, pubkey, 42, zero, 0);
|
||||
let mut tx = BudgetTransaction::new_payment(&keypair, &pubkey, 42, zero, 0);
|
||||
let mut system_instruction = BudgetTransaction::system_instruction(&tx, 0).unwrap();
|
||||
if let SystemInstruction::CreateAccount {
|
||||
ref mut lamports, ..
|
||||
@ -250,7 +250,7 @@ mod tests {
|
||||
let thief_keypair = Keypair::new();
|
||||
let pubkey1 = keypair1.pubkey();
|
||||
let zero = Hash::default();
|
||||
let mut tx = BudgetTransaction::new_payment(&keypair0, pubkey1, 42, zero, 0);
|
||||
let mut tx = BudgetTransaction::new_payment(&keypair0, &pubkey1, 42, zero, 0);
|
||||
let mut instruction = BudgetTransaction::instruction(&tx, 1);
|
||||
if let Some(BudgetInstruction::InitializeAccount(ref mut expr)) = instruction {
|
||||
if let BudgetExpr::Pay(ref mut payment) = expr {
|
||||
@ -267,7 +267,7 @@ mod tests {
|
||||
let keypair0 = Keypair::new();
|
||||
let keypair1 = Keypair::new();
|
||||
let zero = Hash::default();
|
||||
let mut tx = BudgetTransaction::new_payment(&keypair0, keypair1.pubkey(), 1, zero, 0);
|
||||
let mut tx = BudgetTransaction::new_payment(&keypair0, &keypair1.pubkey(), 1, zero, 0);
|
||||
let mut instruction = BudgetTransaction::instruction(&tx, 1).unwrap();
|
||||
if let BudgetInstruction::InitializeAccount(ref mut expr) = instruction {
|
||||
if let BudgetExpr::Pay(ref mut payment) = expr {
|
||||
|
Reference in New Issue
Block a user