Skip to content

Commit

Permalink
[language] On-chain definition of gas schedule
Browse files Browse the repository at this point in the history
The gas schedule within the VM is defined on-chain, and is read in once
per-block. Normal transactions initiatied from the association account
can add, or update the costs within this gas schedule.

Closes: #1406
Approved by: dariorussi
  • Loading branch information
Tim Zakian authored and bors-libra committed Nov 6, 2019
1 parent fe2653a commit be90eea
Show file tree
Hide file tree
Showing 38 changed files with 788 additions and 300 deletions.
3 changes: 1 addition & 2 deletions executor/src/mock_vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#[cfg(test)]
mod mock_vm_test;

use failure::Result;
use lazy_static::lazy_static;
use libra_config::config::VMConfig;
use libra_crypto::ed25519::compat;
Expand Down Expand Up @@ -54,7 +53,7 @@ impl VMExecutor for MockVM {
transactions: Vec<Transaction>,
_config: &VMConfig,
state_view: &dyn StateView,
) -> Result<Vec<TransactionOutput>> {
) -> Result<Vec<TransactionOutput>, VMStatus> {
if state_view.is_genesis() {
assert_eq!(
transactions.len(),
Expand Down
4 changes: 3 additions & 1 deletion language/benchmarks/src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ impl TransactionBenchState {
fn execute(self) {
// The output is ignored here since we're just testing transaction performance, not trying
// to assert correctness.
self.executor.execute_block(self.transactions);
self.executor
.execute_block(self.transactions)
.expect("VM should not fail to start");
}
}

Expand Down
10 changes: 7 additions & 3 deletions language/e2e-tests/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ impl FakeExecutor {
///
/// Typical tests will call this method and check that the output matches what was expected.
/// However, this doesn't apply the results of successful transactions to the data store.
pub fn execute_block(&self, txn_block: Vec<SignedTransaction>) -> Vec<TransactionOutput> {
pub fn execute_block(
&self,
txn_block: Vec<SignedTransaction>,
) -> Result<Vec<TransactionOutput>, VMStatus> {
MoveVM::execute_block(
txn_block
.into_iter()
Expand All @@ -159,12 +162,13 @@ impl FakeExecutor {
&self.config.vm_config,
&self.data_store,
)
.expect("The VM should not fail to start")
}

pub fn execute_transaction(&self, txn: SignedTransaction) -> TransactionOutput {
let txn_block = vec![txn];
let mut outputs = self.execute_block(txn_block);
let mut outputs = self
.execute_block(txn_block)
.expect("The VM should not fail to startup");
outputs
.pop()
.expect("A block with one transaction should have one output")
Expand Down
12 changes: 6 additions & 6 deletions language/e2e-tests/src/gas_costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ lazy_static! {
create_account_txn(sender.account(), &Account::new(), 10, 20_000),
create_account_txn(sender.account(), &Account::new(), 11, 20_000),
];
let output = &executor.execute_block(txns);
let output = &executor.execute_block(txns).expect("The VM should not fail to startup");
output[1].gas_used()
};

Expand Down Expand Up @@ -83,7 +83,7 @@ lazy_static! {
create_account_txn(sender.account(), &Account::new(), 10, 10),
create_account_txn(sender.account(), &Account::new(), 11, balance),
];
let output = &executor.execute_block(txns);
let output = &executor.execute_block(txns).expect("The VM should not fail to startup");
output[1].gas_used()
};

Expand Down Expand Up @@ -118,7 +118,7 @@ lazy_static! {
create_account_txn(sender.account(), &Account::new(), 10, 20_000),
create_account_txn(sender.account(), receiver.account(), 11, 20_000),
];
let output = &executor.execute_block(txns);
let output = &executor.execute_block(txns).expect("The VM should not fail to startup");
output[1].gas_used()
};

Expand Down Expand Up @@ -184,7 +184,7 @@ lazy_static! {
peer_to_peer_txn(sender.account(), &Account::new(), 10, 20_000),
peer_to_peer_txn(sender.account(), &Account::new(), 11, 20_000),
];
let output = &executor.execute_block(txns);
let output = &executor.execute_block(txns).expect("The VM should not fail to startup");
output[1].gas_used()
};

Expand Down Expand Up @@ -224,7 +224,7 @@ lazy_static! {
peer_to_peer_txn(sender.account(), &Account::new(), 10, 10_000),
peer_to_peer_txn(sender.account(), &Account::new(), 11, balance),
];
let output = &executor.execute_block(txns);
let output = &executor.execute_block(txns).expect("The VM should not fail to startup");
output[1].gas_used()
};

Expand All @@ -244,6 +244,6 @@ lazy_static! {
}

fn compute_gas_used(txn: SignedTransaction, executor: &mut FakeExecutor) -> u64 {
let output = &executor.execute_block(vec![txn])[0];
let output = &executor.execute_transaction(txn);
output.gas_used()
}
3 changes: 2 additions & 1 deletion language/e2e-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use bytecode_verifier::{VerifiedModule, VerifiedScript};
use compiler::Compiler;
use data_store::FakeDataStore;
use data_store::{FakeDataStore, GENESIS_WRITE_SET};
use libra_types::{
access_path::AccessPath,
account_address::AccountAddress,
Expand Down Expand Up @@ -55,6 +55,7 @@ pub fn execute(
) -> VMResult<()> {
// set up the DB
let mut data_view = FakeDataStore::default();
data_view.add_write_set(&GENESIS_WRITE_SET);
data_view.set(
AccessPath::new(AccountAddress::random(), vec![]),
vec![0, 0],
Expand Down
4 changes: 2 additions & 2 deletions language/e2e-tests/src/tests/account_universe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub(crate) fn run_and_assert_gas_cost_stability(
.iter()
.map(|transaction_gen| transaction_gen.clone().apply(&mut universe))
.unzip();
let outputs = executor.execute_block(transactions);
let outputs = executor.execute_block(transactions).unwrap();

for (idx, (output, expected_value)) in outputs.iter().zip(&expected_values).enumerate()
{
Expand Down Expand Up @@ -142,7 +142,7 @@ pub(crate) fn run_and_assert_universe(
.iter()
.map(|transaction_gen| transaction_gen.clone().apply(&mut universe))
.unzip();
let outputs = executor.execute_block(transactions);
let outputs = executor.execute_block(transactions).unwrap();

prop_assert_eq!(outputs.len(), expected_values.len());

Expand Down
26 changes: 11 additions & 15 deletions language/e2e-tests/src/tests/create_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
executor::test_all_genesis,
};
use libra_types::{
transaction::{SignedTransaction, TransactionStatus},
transaction::TransactionStatus,
vm_error::{StatusCode, VMStatus},
};

Expand All @@ -23,18 +23,16 @@ fn create_account() {
let txn = create_account_txn(sender.account(), &new_account, 10, initial_amount);

// execute transaction
let txns: Vec<SignedTransaction> = vec![txn];
let output = executor.execute_block(txns);
let txn_output = output.get(0).expect("must have a transaction output");
let output = executor.execute_transaction(txn);
assert_eq!(
output[0].status(),
output.status(),
&TransactionStatus::Keep(VMStatus::new(StatusCode::EXECUTED))
);
println!("write set {:?}", txn_output.write_set());
executor.apply_write_set(txn_output.write_set());
println!("write set {:?}", output.write_set());
executor.apply_write_set(output.write_set());

// check that numbers in stored DB are correct
let gas = txn_output.gas_used();
let gas = output.gas_used();
let sender_balance = 1_000_000 - initial_amount - gas;
let updated_sender = executor
.read_account_resource(sender.account())
Expand Down Expand Up @@ -62,18 +60,16 @@ fn create_account_zero_balance() {
let txn = create_account_txn(sender.account(), &new_account, 10, initial_amount);

// execute transaction
let txns: Vec<SignedTransaction> = vec![txn];
let output = executor.execute_block(txns);
let txn_output = output.get(0).expect("must have a transaction output");
let output = executor.execute_transaction(txn);
assert_eq!(
output[0].status(),
output.status(),
&TransactionStatus::Keep(VMStatus::new(StatusCode::EXECUTED))
);
println!("write set {:?}", txn_output.write_set());
executor.apply_write_set(txn_output.write_set());
println!("write set {:?}", output.write_set());
executor.apply_write_set(output.write_set());

// check that numbers in stored DB are correct
let gas = txn_output.gas_used();
let gas = output.gas_used();
let sender_balance = 1_000_000 - initial_amount - gas;
let updated_sender = executor
.read_account_resource(sender.account())
Expand Down
3 changes: 2 additions & 1 deletion language/e2e-tests/src/tests/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use libra_types::{
account_config,
test_helpers::transaction_test_helpers,
transaction::TransactionStatus,
vm_error::{StatusCode, VMStatus},
vm_error::StatusCode,
vm_error::VMStatus,
write_set::{WriteOp, WriteSetMut},
};

Expand Down
29 changes: 12 additions & 17 deletions language/e2e-tests/src/tests/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
transaction_status_eq,
};
use libra_types::{
transaction::{SignedTransaction, TransactionStatus},
transaction::TransactionStatus,
vm_error::{StatusCode, VMStatus},
};

Expand All @@ -29,18 +29,16 @@ fn mint_to_existing() {
let txn = mint_txn(&genesis_account, receiver.account(), 1, mint_amount);

// execute transaction
let txns: Vec<SignedTransaction> = vec![txn];
let output = executor.execute_block(txns);
let txn_output = output.get(0).expect("must have a transaction output");
let output = executor.execute_transaction(txn);
assert_eq!(
output[0].status(),
output.status(),
&TransactionStatus::Keep(VMStatus::new(StatusCode::EXECUTED))
);
println!("write set {:?}", txn_output.write_set());
executor.apply_write_set(txn_output.write_set());
println!("write set {:?}", output.write_set());
executor.apply_write_set(output.write_set());

// check that numbers in stored DB are correct
let gas = txn_output.gas_used();
let gas = output.gas_used();
let sender_balance = 1_000_000_000 - gas;
let receiver_balance = 1_000_000 + mint_amount;

Expand Down Expand Up @@ -72,17 +70,15 @@ fn mint_to_new_account() {
let txn = mint_txn(&genesis_account, &new_account, 1, mint_amount);

// execute transaction
let txns: Vec<SignedTransaction> = vec![txn];
let output = executor.execute_block(txns);
let txn_output = output.get(0).expect("must have a transaction output");
let output = executor.execute_transaction(txn);
assert!(transaction_status_eq(
&output[0].status(),
&output.status(),
&TransactionStatus::Keep(VMStatus::new(StatusCode::EXECUTED))
));
executor.apply_write_set(txn_output.write_set());
executor.apply_write_set(output.write_set());

// check that numbers in stored DB are correct
let gas = txn_output.gas_used();
let gas = output.gas_used();
let sender_balance = 1_000_000_000 - gas;
let receiver_balance = mint_amount;

Expand All @@ -99,11 +95,10 @@ fn mint_to_new_account() {

// Mint can only be called from genesis address;
let txn = mint_txn(&new_account, &new_account, 0, mint_amount);
let txns: Vec<SignedTransaction> = vec![txn];
let output = executor.execute_block(txns);
let output = executor.execute_transaction(txn);

assert!(transaction_status_eq(
&output[0].status(),
&output.status(),
&TransactionStatus::Keep(VMStatus::new(StatusCode::MISSING_DATA))
));
}

0 comments on commit be90eea

Please sign in to comment.