mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 00:58:02 +00:00
Allow spending all available gas. (#2947)
* Allow spending all gas. * Bump node runtime version
This commit is contained in:
committed by
Gavin Wood
parent
846941550d
commit
183931a8a2
@@ -58,8 +58,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("node"),
|
||||
impl_name: create_runtime_str!("substrate-node"),
|
||||
authoring_version: 10,
|
||||
spec_version: 97,
|
||||
impl_version: 99,
|
||||
spec_version: 98,
|
||||
impl_version: 100,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
|
||||
@@ -127,7 +127,6 @@ impl<T: Trait> GasMeter<T> {
|
||||
let amount = token.calculate_amount(metadata);
|
||||
let new_value = match self.gas_left.checked_sub(&amount) {
|
||||
None => None,
|
||||
Some(val) if val.is_zero() => None,
|
||||
Some(val) => Some(val),
|
||||
};
|
||||
|
||||
@@ -304,25 +303,25 @@ mod tests {
|
||||
use super::{GasMeter, Token};
|
||||
use crate::tests::Test;
|
||||
|
||||
/// A trivial token that charges 1 unit of gas.
|
||||
/// A trivial token that charges the specified number of gas units.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct UnitToken;
|
||||
impl Token<Test> for UnitToken {
|
||||
struct SimpleToken(u64);
|
||||
impl Token<Test> for SimpleToken {
|
||||
type Metadata = ();
|
||||
fn calculate_amount(&self, _metadata: &()) -> u64 { 1 }
|
||||
fn calculate_amount(&self, _metadata: &()) -> u64 { self.0 }
|
||||
}
|
||||
|
||||
struct DoubleTokenMetadata {
|
||||
struct MultiplierTokenMetadata {
|
||||
multiplier: u64,
|
||||
}
|
||||
/// A simple token that charges for the given amount multiplied to
|
||||
/// a multiplier taken from a given metadata.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct DoubleToken(u64);
|
||||
struct MultiplierToken(u64);
|
||||
|
||||
impl Token<Test> for DoubleToken {
|
||||
type Metadata = DoubleTokenMetadata;
|
||||
fn calculate_amount(&self, metadata: &DoubleTokenMetadata) -> u64 {
|
||||
impl Token<Test> for MultiplierToken {
|
||||
type Metadata = MultiplierTokenMetadata;
|
||||
fn calculate_amount(&self, metadata: &MultiplierTokenMetadata) -> u64 {
|
||||
// Probably you want to use saturating mul in production code.
|
||||
self.0 * metadata.multiplier
|
||||
}
|
||||
@@ -338,7 +337,8 @@ mod tests {
|
||||
fn simple() {
|
||||
let mut gas_meter = GasMeter::<Test>::with_limit(50000, 10);
|
||||
|
||||
let result = gas_meter.charge(&DoubleTokenMetadata { multiplier: 3 }, DoubleToken(10));
|
||||
let result = gas_meter
|
||||
.charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10));
|
||||
assert!(!result.is_out_of_gas());
|
||||
|
||||
assert_eq!(gas_meter.gas_left(), 49_970);
|
||||
@@ -349,12 +349,44 @@ mod tests {
|
||||
#[test]
|
||||
fn tracing() {
|
||||
let mut gas_meter = GasMeter::<Test>::with_limit(50000, 10);
|
||||
assert!(!gas_meter.charge(&(), UnitToken).is_out_of_gas());
|
||||
assert!(!gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
|
||||
assert!(!gas_meter
|
||||
.charge(&DoubleTokenMetadata { multiplier: 3 }, DoubleToken(10))
|
||||
.charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10))
|
||||
.is_out_of_gas());
|
||||
|
||||
let mut tokens = gas_meter.tokens()[0..2].iter();
|
||||
match_tokens!(tokens, UnitToken, DoubleToken(10),);
|
||||
match_tokens!(tokens, SimpleToken(1), MultiplierToken(10),);
|
||||
}
|
||||
|
||||
// This test makes sure that nothing can be executed if there is no gas.
|
||||
#[test]
|
||||
fn refuse_to_execute_anything_if_zero() {
|
||||
let mut gas_meter = GasMeter::<Test>::with_limit(0, 10);
|
||||
assert!(gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
|
||||
}
|
||||
|
||||
// Make sure that if the gas meter is charged by exceeding amount then not only an error
|
||||
// returned for that charge, but also for all consequent charges.
|
||||
//
|
||||
// This is not striclty necessary, because the execution should be interrupred immediatelly
|
||||
// if the gas meter runs out of gas. However, this is just a nice property to have.
|
||||
#[test]
|
||||
fn overcharge_is_unrecoverable() {
|
||||
let mut gas_meter = GasMeter::<Test>::with_limit(200, 10);
|
||||
|
||||
// The first charge is should lead to OOG.
|
||||
assert!(gas_meter.charge(&(), SimpleToken(300)).is_out_of_gas());
|
||||
|
||||
// The gas meter is emptied at this moment, so this should also fail.
|
||||
assert!(gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
|
||||
}
|
||||
|
||||
|
||||
// Charging the exact amount that the user paid for should be
|
||||
// possible.
|
||||
#[test]
|
||||
fn charge_exact_amount() {
|
||||
let mut gas_meter = GasMeter::<Test>::with_limit(25, 10);
|
||||
assert!(!gas_meter.charge(&(), SimpleToken(25)).is_out_of_gas());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,14 +230,17 @@ impl ExtBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// Perform a simple transfer to a non-existent account supplying way more gas than needed.
|
||||
// Then we check that the all unused gas is refunded.
|
||||
#[test]
|
||||
fn refunds_unused_gas() {
|
||||
with_externalities(&mut ExtBuilder::default().build(), || {
|
||||
Balances::deposit_creating(&0, 100_000_000);
|
||||
with_externalities(&mut ExtBuilder::default().gas_price(2).build(), || {
|
||||
Balances::deposit_creating(&ALICE, 100_000_000);
|
||||
|
||||
assert_ok!(Contract::call(Origin::signed(0), 1, 0, 100_000, Vec::new()));
|
||||
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new()));
|
||||
|
||||
assert_eq!(Balances::free_balance(&0), 100_000_000 - (2 * 135));
|
||||
// 2 * 135 - gas price multiplied by the call base fee.
|
||||
assert_eq!(Balances::free_balance(&ALICE), 100_000_000 - (2 * 135));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user