comments (#1165)
This commit is contained in:
parent
ebcac3c2d1
commit
a89b611e9e
25
src/bank.rs
25
src/bank.rs
|
@ -63,7 +63,7 @@ pub enum BankError {
|
||||||
LedgerVerificationFailed,
|
LedgerVerificationFailed,
|
||||||
/// Contract's transaction token balance does not equal the balance after the transaction
|
/// Contract's transaction token balance does not equal the balance after the transaction
|
||||||
UnbalancedTransaction(Signature),
|
UnbalancedTransaction(Signature),
|
||||||
/// ContractAlreadyPending
|
/// Contract location Pubkey already contains userdata
|
||||||
ContractAlreadyPending(Pubkey),
|
ContractAlreadyPending(Pubkey),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,16 +232,19 @@ impl Bank {
|
||||||
last_ids.push_back(*last_id);
|
last_ids.push_back(*last_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deduct tokens from the 'from' address the account has sufficient
|
/// Deduct tokens from the source account if it has sufficient funds and the contract isn't
|
||||||
/// funds and isn't a duplicate.
|
/// pending
|
||||||
fn apply_debits(
|
fn apply_debits_to_budget_payment_plan(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
accounts: &mut [Account],
|
accounts: &mut [Account],
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
{
|
{
|
||||||
let empty = accounts[0].userdata.is_empty();
|
let tokens = if !accounts[0].userdata.is_empty() {
|
||||||
let tokens = if !empty { 0 } else { accounts[0].tokens };
|
0
|
||||||
|
} else {
|
||||||
|
accounts[0].tokens
|
||||||
|
};
|
||||||
if let Instruction::NewContract(contract) = &instruction {
|
if let Instruction::NewContract(contract) = &instruction {
|
||||||
if contract.tokens < 0 {
|
if contract.tokens < 0 {
|
||||||
return Err(BankError::NegativeTokens);
|
return Err(BankError::NegativeTokens);
|
||||||
|
@ -260,7 +263,7 @@ impl Bank {
|
||||||
|
|
||||||
/// Apply only a transaction's credits.
|
/// Apply only a transaction's credits.
|
||||||
/// 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(
|
fn apply_credits_to_budget_payment_plan(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
accounts: &mut [Account],
|
accounts: &mut [Account],
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
|
@ -276,7 +279,7 @@ impl Bank {
|
||||||
} else {
|
} else {
|
||||||
let mut pending = HashMap::new();
|
let mut pending = HashMap::new();
|
||||||
pending.insert(tx.signature, plan);
|
pending.insert(tx.signature, plan);
|
||||||
//TODO this is a temporary on demand allocaiton
|
//TODO this is a temporary on demand allocation
|
||||||
//until system contract requires explicit allocation of memory
|
//until system contract requires explicit allocation of memory
|
||||||
accounts[1].userdata = serialize(&pending).unwrap();
|
accounts[1].userdata = serialize(&pending).unwrap();
|
||||||
accounts[1].tokens += contract.tokens;
|
accounts[1].tokens += contract.tokens;
|
||||||
|
@ -308,8 +311,8 @@ impl Bank {
|
||||||
accounts: &mut [Account],
|
accounts: &mut [Account],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let instruction = tx.instruction();
|
let instruction = tx.instruction();
|
||||||
Self::apply_debits(tx, accounts, &instruction)?;
|
Self::apply_debits_to_budget_payment_plan(tx, accounts, &instruction)?;
|
||||||
Self::apply_credits(tx, accounts, &instruction)
|
Self::apply_credits_to_budget_payment_plan(tx, accounts, &instruction)
|
||||||
}
|
}
|
||||||
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
|
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
|
||||||
pub fn get_balance_of_budget_payment_plan(account: &Account) -> i64 {
|
pub fn get_balance_of_budget_payment_plan(account: &Account) -> i64 {
|
||||||
|
@ -918,7 +921,7 @@ mod tests {
|
||||||
// pubkey's balance will be 0 because the funds are locked up
|
// pubkey's balance will be 0 because the funds are locked up
|
||||||
assert_eq!(bank.get_balance(&pubkey), 0);
|
assert_eq!(bank.get_balance(&pubkey), 0);
|
||||||
|
|
||||||
// Now, cancel the trancaction. Mint gets her funds back, pubkey never sees them.
|
// Now, cancel the transaction. Mint gets her funds back, pubkey never sees them.
|
||||||
let tx = Transaction::new_signature(&mint.keypair(), pubkey, signature, bank.last_id());
|
let tx = Transaction::new_signature(&mint.keypair(), pubkey, signature, bank.last_id());
|
||||||
let res = bank.process_transaction(&tx);
|
let res = bank.process_transaction(&tx);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
|
|
|
@ -188,8 +188,8 @@ impl ThinClient {
|
||||||
self.process_response(&resp);
|
self.process_response(&resp);
|
||||||
}
|
}
|
||||||
trace!("get_balance {:?}", self.balances.get(pubkey));
|
trace!("get_balance {:?}", self.balances.get(pubkey));
|
||||||
//TODO: call the contract specific get_balance for contract_id's thin client can introspect
|
// TODO: This is a hard coded call to introspect the balance of a budget_dsl contract
|
||||||
//instead of hard coding to budget_dsl only
|
// In the future custom contracts would need their own introspection
|
||||||
self.balances
|
self.balances
|
||||||
.get(pubkey)
|
.get(pubkey)
|
||||||
.map(Bank::get_balance_of_budget_payment_plan)
|
.map(Bank::get_balance_of_budget_payment_plan)
|
||||||
|
|
|
@ -84,9 +84,9 @@ pub struct Transaction {
|
||||||
|
|
||||||
/// 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
|
||||||
/// contract-specific.
|
/// contract-specific.
|
||||||
/// * keys[0] - Typically this is the `from` public key. `signature` is verified with keys[0].
|
/// * keys[0] - Typically this is the `caller` public key. `signature` is verified with keys[0].
|
||||||
/// In the future which key pays the fee and which keys have signatures would be configurable.
|
/// In the future which key pays the fee and which keys have signatures would be configurable.
|
||||||
/// * keys[1] - Typically this is the contract context or the recepient of the tokens
|
/// * keys[1] - Typically this is the contract context or the recipient of the tokens
|
||||||
pub keys: Vec<Pubkey>,
|
pub keys: Vec<Pubkey>,
|
||||||
|
|
||||||
/// The ID of a recent ledger entry.
|
/// The ID of a recent ledger entry.
|
||||||
|
@ -103,7 +103,7 @@ impl Transaction {
|
||||||
/// Create a signed transaction from the given `Instruction`.
|
/// Create a signed transaction from the given `Instruction`.
|
||||||
/// * `from_keypair` - The key used to sign the transcation. This key is stored as keys[0]
|
/// * `from_keypair` - The key used to sign the transcation. This key is stored as keys[0]
|
||||||
/// * `transaction_keys` - The keys for the transaction. These are the contract state
|
/// * `transaction_keys` - The keys for the transaction. These are the contract state
|
||||||
/// instances or token recepient keys.
|
/// instances or token recipient keys.
|
||||||
/// * `userdata` - The input data that the contract will execute with
|
/// * `userdata` - The input data that the contract will execute with
|
||||||
/// * `last_id` - The PoH hash.
|
/// * `last_id` - The PoH hash.
|
||||||
/// * `fee` - The transaction fee.
|
/// * `fee` - The transaction fee.
|
||||||
|
@ -135,7 +135,7 @@ impl Transaction {
|
||||||
last_id: Hash,
|
last_id: Hash,
|
||||||
fee: i64,
|
fee: i64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let userdata = serialize(&instruction).expect("serealize instruction");
|
let userdata = serialize(&instruction).unwrap();
|
||||||
Self::new_with_userdata(from_keypair, &[contract], userdata, last_id, fee)
|
Self::new_with_userdata(from_keypair, &[contract], userdata, last_id, fee)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue