Skip to content

Commit

Permalink
Contract rewards (#1258)
Browse files Browse the repository at this point in the history
Introduce execution rewards for every burnt_gas.
Refunds are free, meaining no gas cost to create/send or execute.
Return burnt_gas as part of TransactionResult.
Fixing tests by fixing tests.
Increase fees 10X to properly check rewards.
Fix view call infinite loops
  • Loading branch information
Evgeny Kuzyakov authored Sep 12, 2019
1 parent 3483659 commit a7960e9
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 183 deletions.
1 change: 1 addition & 0 deletions chain/chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ impl RuntimeAdapter for KeyValueRuntime {
logs: vec![],
receipts: new_receipt_hashes,
result: None,
gas_burnt: 0,
},
});
}
Expand Down
9 changes: 6 additions & 3 deletions core/primitives/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,16 @@ impl Default for TransactionStatus {

#[derive(BorshSerialize, BorshDeserialize, PartialEq, Clone, Default)]
pub struct TransactionResult {
/// Transaction status.
/// Execution status.
pub status: TransactionStatus,
/// Logs from this transaction.
/// Logs from this transaction or receipt.
pub logs: Vec<LogEntry>,
/// Receipt ids generated by this transaction.
/// Receipt ids generated by this transaction or receipt.
pub receipts: Vec<CryptoHash>,
/// Execution Result
pub result: Option<Vec<u8>>,
/// The amount of the gas burnt by the given transaction or receipt.
pub gas_burnt: Gas,
}

impl fmt::Debug for TransactionResult {
Expand All @@ -210,6 +212,7 @@ impl fmt::Debug for TransactionResult {
.field("logs", &format_args!("{}", logging::pretty_vec(&self.logs)))
.field("receipts", &format_args!("{}", logging::pretty_vec(&self.receipts)))
.field("result", &format_args!("{}", logging::pretty_result(&self.result)))
.field("burnt_gas", &self.gas_burnt)
.finish()
}
}
Expand Down
3 changes: 3 additions & 0 deletions core/primitives/src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,7 @@ pub struct TransactionResultView {
pub logs: Vec<LogEntry>,
pub receipts: Vec<CryptoHashView>,
pub result: Option<String>,
pub gas_burnt: Gas,
}

impl From<TransactionResult> for TransactionResultView {
Expand All @@ -623,6 +624,7 @@ impl From<TransactionResult> for TransactionResultView {
logs: result.logs,
receipts: result.receipts.into_iter().map(|h| h.into()).collect(),
result: result.result.map(|v| to_base64(&v)),
gas_burnt: result.gas_burnt,
}
}
}
Expand All @@ -634,6 +636,7 @@ impl From<TransactionResultView> for TransactionResult {
logs: view.logs,
receipts: view.receipts.into_iter().map(|h| h.into()).collect(),
result: view.result.map(|v| from_base64(&v).unwrap()),
gas_burnt: view.gas_burnt,
}
}
}
Expand Down
49 changes: 34 additions & 15 deletions runtime/near-runtime-fees/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
use serde::{Deserialize, Serialize};
pub type Gas = u64;

#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct Fraction {
pub numerator: u64,
pub denominator: u64,
}

/// Costs associated with an object that can only be sent over the network (and executed
/// by the receiver).
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -44,6 +50,9 @@ pub struct RuntimeFeesConfig {
pub action_creation_config: ActionCreationConfig,

pub storage_usage_config: StorageUsageConfig,

/// Fraction of the burnt gas to reward to the contract account for execution.
pub burnt_gas_reward: Fraction,
}

/// Describes the cost of creating a data receipt, `DataReceipt`.
Expand Down Expand Up @@ -115,26 +124,34 @@ pub struct StorageUsageConfig {
impl Default for RuntimeFeesConfig {
fn default() -> Self {
Self {
action_receipt_creation_config: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
action_receipt_creation_config: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
data_receipt_creation_config: DataReceiptCreationConfig {
base_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
cost_per_byte: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
base_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
cost_per_byte: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
},
action_creation_config: ActionCreationConfig {
create_account_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
deploy_contract_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
deploy_contract_cost_per_byte: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
function_call_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
function_call_cost_per_byte: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
transfer_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
stake_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
create_account_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
deploy_contract_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
deploy_contract_cost_per_byte: Fee {
send_sir: 10,
send_not_sir: 10,
execution: 10,
},
function_call_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
function_call_cost_per_byte: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
transfer_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
stake_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
add_key_cost: AccessKeyCreationConfig {
full_access_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
function_call_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
function_call_cost_per_byte: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
full_access_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
function_call_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
function_call_cost_per_byte: Fee {
send_sir: 10,
send_not_sir: 10,
execution: 10,
},
},
delete_key_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
delete_account_cost: Fee { send_sir: 1, send_not_sir: 1, execution: 1 },
delete_key_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
delete_account_cost: Fee { send_sir: 10, send_not_sir: 10, execution: 10 },
},
storage_usage_config: StorageUsageConfig {
account_cost: 100,
Expand All @@ -143,6 +160,7 @@ impl Default for RuntimeFeesConfig {
value_cost_per_byte: 1,
code_cost_per_byte: 1,
},
burnt_gas_reward: Fraction { numerator: 3, denominator: 10 },
}
}
}
Expand Down Expand Up @@ -179,6 +197,7 @@ impl RuntimeFeesConfig {
value_cost_per_byte: 0,
code_cost_per_byte: 0,
},
burnt_gas_reward: Fraction { numerator: 0, denominator: 1 },
}
}
}
13 changes: 6 additions & 7 deletions runtime/near-vm-logic/src/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,25 +820,24 @@ impl<'a> VMLogic<'a> {
self.burnt_gas.checked_add(burn_gas as _).ok_or(HostError::IntegerOverflow)?;
let new_used_gas =
self.used_gas.checked_add(use_gas as _).ok_or(HostError::IntegerOverflow)?;
if self.context.free_of_charge
|| (new_burnt_gas < self.config.max_gas_burnt
&& new_used_gas < self.context.prepaid_gas)
if new_burnt_gas <= self.config.max_gas_burnt
&& (self.context.free_of_charge || new_used_gas <= self.context.prepaid_gas)
{
self.burnt_gas = new_burnt_gas;
self.used_gas = new_used_gas;
Ok(())
} else {
use std::cmp::min;
let res = if new_burnt_gas >= self.config.max_gas_burnt {
let res = if new_burnt_gas > self.config.max_gas_burnt {
Err(HostError::GasLimitExceeded)
} else if new_used_gas >= self.context.prepaid_gas {
} else if new_used_gas > self.context.prepaid_gas {
Err(HostError::GasExceeded)
} else {
unreachable!()
};

self.burnt_gas =
min(self.context.prepaid_gas, min(new_burnt_gas, self.config.max_gas_burnt));
let max_burnt_gas = min(self.config.max_gas_burnt, self.context.prepaid_gas);
self.burnt_gas = min(new_burnt_gas, max_burnt_gas);
self.used_gas = min(new_used_gas, self.context.prepaid_gas);

res
Expand Down
Loading

0 comments on commit a7960e9

Please sign in to comment.