Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expose validator information as host functions #2504

Merged
merged 18 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/chain-configs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ pub use genesis_config::{
};

/// Current latest version of the protocol
pub const PROTOCOL_VERSION: u32 = 10;
pub const PROTOCOL_VERSION: u32 = 11;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update after #2574

2 changes: 1 addition & 1 deletion neard/res/genesis_config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"config_version": 1,
"protocol_version": 10,
"protocol_version": 11,
"genesis_time": "1970-01-01T00:00:00.000000000Z",
"chain_id": "sample",
"genesis_height": 0,
Expand Down
37 changes: 35 additions & 2 deletions neard/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,27 @@ impl NightshadeRuntime {
(self.store.clone(), store_update, state_roots)
}

fn get_epoch_validators(
&self,
epoch_id: &EpochId,
last_block_hash: &CryptoHash,
) -> Result<HashMap<AccountId, Balance>, Error> {
let mut epoch_manager = self.epoch_manager.write().expect(POISONED_LOCK_ERR);
frol marked this conversation as resolved.
Show resolved Hide resolved
let slashed = epoch_manager.get_slashed_validators(last_block_hash)?.clone();
let epoch_info = epoch_manager.get_epoch_info(&epoch_id)?;
Ok(epoch_info
.validators
.iter()
.filter_map(|info| {
if slashed.contains_key(&info.account_id) {
None
} else {
Some((info.account_id.clone(), info.stake))
}
})
.collect::<HashMap<_, _>>())
}

/// Processes state update.
fn process_state_update(
&self,
Expand Down Expand Up @@ -294,11 +315,17 @@ impl NightshadeRuntime {
};

let epoch_height = self.get_epoch_height_from_prev_block(prev_block_hash)?;
let epoch_id = {
let mut epoch_manager = self.epoch_manager.write().expect(POISONED_LOCK_ERR);
frol marked this conversation as resolved.
Show resolved Hide resolved
epoch_manager.get_block_info(block_hash)?.epoch_id.clone()
};
let epoch_validators = self.get_epoch_validators(&epoch_id, block_hash)?;

let apply_state = ApplyState {
block_index: block_height,
epoch_length: self.genesis.config.epoch_length,
epoch_height,
validators: epoch_validators,
gas_price,
block_timestamp,
gas_limit: Some(gas_limit),
Expand Down Expand Up @@ -943,13 +970,17 @@ impl RuntimeAdapter for NightshadeRuntime {
}
QueryRequest::CallFunction { account_id, method_name, args } => {
let mut logs = vec![];
let mut epoch_manager = self.epoch_manager.write().expect(POISONED_LOCK_ERR);
let epoch_height = epoch_manager.get_epoch_info(&epoch_id)?.epoch_height;
let epoch_height = {
let mut epoch_manager = self.epoch_manager.write().expect(POISONED_LOCK_ERR);
epoch_manager.get_epoch_info(&epoch_id)?.epoch_height
};
let epoch_validators = self.get_epoch_validators(epoch_id, block_hash)?;
match self.call_function(
*state_root,
block_height,
block_timestamp,
epoch_height,
epoch_validators,
account_id,
method_name,
args.as_ref(),
Expand Down Expand Up @@ -1144,6 +1175,7 @@ impl node_runtime::adapter::ViewRuntimeAdapter for NightshadeRuntime {
height: BlockHeight,
block_timestamp: u64,
epoch_height: EpochHeight,
epoch_validators: HashMap<AccountId, Balance>,
contract_id: &AccountId,
method_name: &str,
args: &[u8],
Expand All @@ -1155,6 +1187,7 @@ impl node_runtime::adapter::ViewRuntimeAdapter for NightshadeRuntime {
height,
block_timestamp,
epoch_height,
epoch_validators,
contract_id,
method_name,
args,
Expand Down
2 changes: 1 addition & 1 deletion runtime/near-vm-logic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-vm-logic"
version = "0.8.0"
version = "0.9.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update version of all crates in nearcore/runtime. We currently keep them in sync, until we decide to split them in the future.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see

authors = ["Near Inc <hello@nearprotocol.com>"]
edition = "2018"
license = "Apache-2.0"
Expand Down
5 changes: 5 additions & 0 deletions runtime/near-vm-logic/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::types::{AccountId, Balance, BlockHeight, EpochHeight, Gas, PublicKey, StorageUsage};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Serialize, Deserialize, Clone)]
/// Context for the contract execution.
Expand Down Expand Up @@ -29,6 +30,10 @@ pub struct VMContext {
pub block_timestamp: u64,
/// The current epoch height.
pub epoch_height: EpochHeight,
/// Current epoch validators and their stake
pub validators: HashMap<AccountId, Balance>,
/// Total stake of this epoch.
pub epoch_total_stake: Balance,

/// The balance attached to the given account. Excludes the `attached_deposit` that was
/// attached to the transaction.
Expand Down
31 changes: 31 additions & 0 deletions runtime/near-vm-logic/src/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,37 @@ impl<'a> VMLogic<'a> {
Ok(self.context.epoch_height)
}

/// Returns the stake of an account, if the account is currently a validator. Otherwise returns 0.
bowenwang1996 marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Cost
///
/// For not nul-terminated account id:
/// `base + read_memory_base + read_memory_byte * num_bytes + utf8_decoding_base + utf8_decoding_byte * num_bytes + memory_write_base + memory_write_size * 16`
///
/// For nul-terminated account id :
/// `base + (read_memory_base + read_memory_byte) * num_bytes + utf8_decoding_base + utf8_decoding_byte * num_bytes + memory_write_base + memory_write_size * 16`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? How do we end up in this weird state?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to how get_utf8_string works.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just reference get_utf8_string for costs here. I am as a reader was confused.

pub fn validator_stake(
frol marked this conversation as resolved.
Show resolved Hide resolved
&mut self,
account_len: u64,
account_ptr: u64,
stake_ptr: u64,
) -> Result<()> {
self.gas_counter.pay_base(base)?;
let account_id = self.get_utf8_string(account_len, account_ptr)?;
bowenwang1996 marked this conversation as resolved.
Show resolved Hide resolved
let balance = *self.context.validators.get(&account_id).unwrap_or(&0);
self.memory_set_u128(stake_ptr, balance)
}

/// Returns the total validator stake of the current epoch.
///
/// # Cost
///
/// `base + memory_write_base + memory_write_size * 16`
pub fn validator_total_stake(&mut self, stake_ptr: u64) -> Result<()> {
self.gas_counter.pay_base(base)?;
self.memory_set_u128(stake_ptr, self.context.epoch_total_stake)
}

/// Returns the number of bytes used by the contract if it was saved to the trie as of the
/// invocation. This includes:
/// * The data written with storage_* functions during current and previous execution;
Expand Down
2 changes: 2 additions & 0 deletions runtime/near-vm-logic/tests/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub fn get_context(input: Vec<u8>, is_view: bool) -> VMContext {
block_index: 0,
block_timestamp: 0,
epoch_height: 0,
validators: Default::default(),
epoch_total_stake: 0,
account_balance: 100,
storage_usage: 0,
account_locked_balance: 0,
Expand Down
2 changes: 2 additions & 0 deletions runtime/near-vm-logic/tests/test_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub fn create_context() -> VMContext {
block_index: 10,
block_timestamp: 42,
epoch_height: 1,
validators: Default::default(),
epoch_total_stake: 0,
account_balance: 2u128,
account_locked_balance: 1u128,
storage_usage: 12,
Expand Down
4 changes: 2 additions & 2 deletions runtime/near-vm-runner-standalone/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ serde_json = "1"
clap = "2.33.0"
base64 = "0.11"

near-vm-logic = { path = "../near-vm-logic", version = "0.8.0"}
near-vm-runner = { path = "../near-vm-runner", version = "0.8.0" }
near-vm-logic = { path = "../near-vm-logic", version = "0.9.0"}
near-vm-runner = { path = "../near-vm-runner", version = "0.9.0" }
near-runtime-fees = { path = "../near-runtime-fees", version = "0.8.0" }
2 changes: 2 additions & 0 deletions runtime/near-vm-runner-standalone/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ fn default_vm_context() -> VMContext {
is_view: false,
output_data_receivers: vec![],
epoch_height: 1,
validators: Default::default(),
epoch_total_stake: 0,
};
}

Expand Down
4 changes: 2 additions & 2 deletions runtime/near-vm-runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-vm-runner"
version = "0.8.0"
version = "0.9.0"
authors = ["Near Inc <hello@nearprotocol.com>"]
edition = "2018"
license = "Apache-2.0"
Expand All @@ -20,7 +20,7 @@ pwasm-utils = "0.12"
parity-wasm = "0.41"

near-runtime-fees = { path="../near-runtime-fees", version = "0.8.0" }
near-vm-logic = { path="../near-vm-logic", version = "0.8.0", default-features = false, features = []}
near-vm-logic = { path="../near-vm-logic", version = "0.9.0", default-features = false, features = []}
near-vm-errors = { path = "../near-vm-errors", version = "0.8.0" }

[dev-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions runtime/near-vm-runner/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fn setup(
predecessor_account_id: "carol".to_owned(),
input,
epoch_height: 0,
validators: Default::default(),
block_index: 0,
block_timestamp: 0,
account_balance: 0,
Expand All @@ -35,6 +36,7 @@ fn setup(
random_seed: vec![0, 1, 2],
is_view: false,
output_data_receivers: vec![],
epoch_total_stake: 0,
};
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("tests/res/test_contract_rs.wasm");
Expand Down
2 changes: 2 additions & 0 deletions runtime/near-vm-runner/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ wrapped_imports! {
block_index<[] -> [u64]>,
block_timestamp<[] -> [u64]>,
epoch_height<[] -> [u64]>,
validator_stake<[account_len: u64, account_ptr: u64, stake_ptr: u64] -> []>,
validator_total_stake<[stake_ptr: u64] -> []>,
storage_usage<[] -> [u64]>,
// #################
// # Economics API #
Expand Down
2 changes: 2 additions & 0 deletions runtime/near-vm-runner/tests/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub fn create_context(input: Vec<u8>) -> VMContext {
block_index: 10,
block_timestamp: 42,
epoch_height: 1,
validators: Default::default(),
epoch_total_stake: 0,
account_balance: 2u128,
account_locked_balance: 0,
storage_usage: 12,
Expand Down
2 changes: 2 additions & 0 deletions runtime/runtime-params-estimator/src/testbed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use near_vm_logic::VMLimitConfig;
use neard::get_store_path;
use node_runtime::config::RuntimeConfig;
use node_runtime::{ApplyState, Runtime};
use std::collections::HashMap;

const STATE_DUMP_FILE: &str = "state_dump";
const GENESIS_ROOTS_FILE: &str = "genesis_roots";
Expand Down Expand Up @@ -78,6 +79,7 @@ impl RuntimeTestbed {
// Epoch length is long enough to avoid corner cases.
epoch_length: 4,
epoch_height: 0,
validators: HashMap::default(),
gas_price: 1,
block_timestamp: 0,
gas_limit: None,
Expand Down
3 changes: 3 additions & 0 deletions runtime/runtime-params-estimator/src/wasmer_estimator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use near_vm_logic::mocks::mock_external::MockedExternal;
use near_vm_logic::{VMConfig, VMContext, VMOutcome};
use near_vm_runner::VMError;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};

const CURRENT_ACCOUNT_ID: &str = "alice";
Expand All @@ -23,6 +24,8 @@ fn create_context(input: Vec<u8>) -> VMContext {
block_index: 10,
block_timestamp: 42,
epoch_height: 0,
validators: HashMap::default(),
epoch_total_stake: 0,
account_balance: 2u128,
account_locked_balance: 1u128,
storage_usage: 12,
Expand Down
2 changes: 2 additions & 0 deletions runtime/runtime-standalone/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ impl RuntimeStandalone {
block_index: self.cur_block.block_height,
epoch_length: 0, // TODO: support for epochs
epoch_height: self.cur_block.block_height,
validators: Default::default(),
gas_price: self.cur_block.gas_price,
block_timestamp: self.cur_block.block_timestamp,
gas_limit: None,
Expand Down Expand Up @@ -281,6 +282,7 @@ impl RuntimeStandalone {
self.cur_block.block_height,
self.cur_block.block_timestamp,
self.cur_block.epoch_height,
HashMap::default(),
account_id,
method_name,
args,
Expand Down
2 changes: 2 additions & 0 deletions runtime/runtime/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ pub(crate) fn action_function_call(
block_index: apply_state.block_index,
block_timestamp: apply_state.block_timestamp,
epoch_height: apply_state.epoch_height,
validators: apply_state.validators.clone(),
epoch_total_stake: apply_state.validators.iter().map(|(_, s)| s).sum(),
account_balance: account.amount,
account_locked_balance: account.locked,
storage_usage: account.storage_usage,
Expand Down
3 changes: 3 additions & 0 deletions runtime/runtime/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use near_crypto::PublicKey;
use near_primitives::account::{AccessKey, Account};
use near_primitives::types::{AccountId, BlockHeight, EpochHeight, MerkleHash};
use near_primitives::views::ViewStateResult;
use near_vm_logic::types::Balance;
use std::collections::HashMap;

/// Adapter for querying runtime.
pub trait ViewRuntimeAdapter {
Expand All @@ -17,6 +19,7 @@ pub trait ViewRuntimeAdapter {
height: BlockHeight,
block_timestamp: u64,
epoch_height: EpochHeight,
epoch_validators: HashMap<AccountId, Balance>,
contract_id: &AccountId,
method_name: &str,
args: &[u8],
Expand Down
Loading