Skip to content

Commit

Permalink
require sigs for some pos txs in validator VP
Browse files Browse the repository at this point in the history
  • Loading branch information
brentstone committed Nov 14, 2023
1 parent e89a5a9 commit 5bed8aa
Show file tree
Hide file tree
Showing 6 changed files with 346 additions and 28 deletions.
38 changes: 34 additions & 4 deletions proof_of_stake/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,19 +191,28 @@ pub fn validator_commission_rate_key(validator: &Address) -> Key {
.expect("Cannot obtain a storage key")
}

/// Is storage key for validator's commissionr ate?
pub fn is_validator_commission_rate_key(key: &Key) -> Option<&Address> {
/// Is storage key for validator's commission rate?
pub fn is_validator_commission_rate_key(
key: &Key,
) -> Option<(&Address, Epoch)> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::StringSeg(prefix),
DbKeySeg::AddressSeg(validator),
DbKeySeg::StringSeg(key),
DbKeySeg::StringSeg(lazy_map),
DbKeySeg::StringSeg(data),
DbKeySeg::StringSeg(epoch),
] if addr == &ADDRESS
&& prefix == VALIDATOR_STORAGE_PREFIX
&& key == VALIDATOR_COMMISSION_RATE_STORAGE_KEY =>
&& key == VALIDATOR_COMMISSION_RATE_STORAGE_KEY
&& lazy_map == LAZY_MAP_SUB_KEY
&& data == lazy_map::DATA_SUBKEY =>
{
Some(validator)
let epoch = Epoch::parse(epoch.clone())
.expect("Should be able to parse the epoch");
Some((validator, epoch))
}
_ => None,
}
Expand Down Expand Up @@ -236,6 +245,27 @@ pub fn is_validator_max_commission_rate_change_key(
}
}

/// Is storage key for some piece of validator metadata?
pub fn is_validator_metadata_key(key: &Key) -> Option<&Address> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::StringSeg(prefix),
DbKeySeg::AddressSeg(validator),
DbKeySeg::StringSeg(metadata),
] if addr == &ADDRESS
&& prefix == VALIDATOR_STORAGE_PREFIX
&& matches!(
metadata.as_str(),
"email" | "description" | "website" | "discord_handle"
) =>
{
Some(validator)
}
_ => None,
}
}

/// Storage key for validator's rewards products.
pub fn validator_rewards_product_key(validator: &Address) -> Key {
validator_prefix(validator)
Expand Down
208 changes: 208 additions & 0 deletions tests/src/e2e/ledger_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3457,3 +3457,211 @@ fn change_validator_metadata() -> Result<()> {

Ok(())
}

#[test]
fn test_invalid_validator_txs() -> Result<()> {
let pipeline_len = 2;
let unbonding_len = 4;
let test = setup::network(
|mut genesis, base_dir: &_| {
genesis.parameters.pos_params.pipeline_len = pipeline_len;
genesis.parameters.pos_params.unbonding_len = unbonding_len;
// genesis.parameters.parameters.min_num_of_blocks = 6;
// genesis.parameters.parameters.max_expected_time_per_block = 1;
// genesis.parameters.parameters.epochs_per_year = 31_536_000;
let mut genesis = setup::set_validators(
2,
genesis,
base_dir,
default_port_offset,
);
let bonds = genesis.transactions.bond.unwrap();
genesis.transactions.bond = Some(
bonds
.into_iter()
.filter(|bond| {
(&bond.data.validator).as_ref() != "validator-1"
})
.collect(),
);
genesis
},
None,
)?;

set_ethereum_bridge_mode(
&test,
&test.net.chain_id,
&Who::Validator(0),
ethereum_bridge::ledger::Mode::Off,
None,
);

// 1. Run the ledger node
let _bg_validator_0 =
start_namada_ledger_node_wait_wasm(&test, Some(0), Some(40))?
.background();

let _bg_validator_1 =
start_namada_ledger_node_wait_wasm(&test, Some(1), Some(40))?
.background();

let validator_0_rpc = get_actor_rpc(&test, &Who::Validator(0));
let validator_1_rpc = get_actor_rpc(&test, &Who::Validator(1));

// put money in the validator-1 account from its balance account so that it
// can deactivate and reactivate
let tx_args = vec![
"transfer",
"--source",
"validator-1-balance-key",
"--target",
"validator-1-validator-key",
"--amount",
"100.0",
"--token",
"NAM",
"--node",
&validator_1_rpc,
];
let mut client =
run_as!(test, Who::Validator(1), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is valid.")?;
client.assert_success();

// put money in the validator-0 account from its balance account so that it
// can deactivate and reactivate
let tx_args = vec![
"transfer",
"--source",
"validator-0-balance-key",
"--target",
"validator-0-validator-key",
"--amount",
"100.0",
"--token",
"NAM",
"--node",
&validator_0_rpc,
];
let mut client =
run_as!(test, Who::Validator(0), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is valid.")?;
client.assert_success();

// Try to change validator-1 commission rate as validator-0
let tx_args = vec![
"change-commission-rate",
"--validator",
"validator-1",
"--commission-rate",
"0.06",
"--signing-keys",
"validator-0-validator-key",
"--node",
&validator_0_rpc,
];
let mut client =
run_as!(test, Who::Validator(0), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is invalid.")?;
client.assert_success();

// Try to deactivate validator-1 as validator-0
let tx_args = vec![
"deactivate-validator",
"--validator",
"validator-1",
"--signing-keys",
"validator-0-validator-key",
"--node",
&validator_0_rpc,
];
let mut client =
run_as!(test, Who::Validator(0), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is invalid.")?;
client.assert_success();

// Try to change the validator-1 website as validator-0
let tx_args = vec![
"change-metadata",
"--validator",
"validator-1",
"--website",
"[email protected]",
"--signing-keys",
"validator-0-validator-key",
"--node",
&validator_0_rpc,
];
let mut client =
run_as!(test, Who::Validator(0), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is invalid.")?;
client.assert_success();

// Deactivate validator-1
let tx_args = vec![
"deactivate-validator",
"--validator",
"validator-1",
"--signing-keys",
"validator-1-validator-key",
"--node",
&validator_1_rpc,
];
let mut client =
run_as!(test, Who::Validator(1), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is valid.")?;
client.assert_success();

let deactivate_epoch = get_epoch(&test, &validator_1_rpc)?;
let start = Instant::now();
let loop_timeout = Duration::new(120, 0);
loop {
if Instant::now().duration_since(start) > loop_timeout {
panic!(
"Timed out waiting for epoch: {}",
deactivate_epoch + pipeline_len
);
}
let epoch = epoch_sleep(&test, &validator_1_rpc, 40)?;
if epoch >= deactivate_epoch + pipeline_len {
break;
}
}

// Check the state of validator-1
let tx_args = vec![
"validator-state",
"--validator",
"validator-1",
"--node",
&validator_1_rpc,
];
let mut client = run!(test, Bin::Client, tx_args, Some(40))?;
client.exp_regex(r"Validator [a-z0-9]+ is inactive")?;
client.assert_success();

// Try to reactivate validator-1 as validator-0
let tx_args = vec![
"reactivate-validator",
"--validator",
"validator-1",
"--signing-keys",
"validator-0-validator-key",
"--node",
&validator_0_rpc,
];
let mut client =
run_as!(test, Who::Validator(0), Bin::Client, tx_args, Some(40))?;
client.exp_string("Transaction applied with result:")?;
client.exp_string("Transaction is invalid.")?;
client.assert_success();

Ok(())
}
3 changes: 1 addition & 2 deletions vp_prelude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use std::convert::TryFrom;
use std::marker::PhantomData;

pub use borsh::{BorshDeserialize, BorshSerialize};
pub use borsh_ext;
use borsh_ext::BorshSerializeExt;
pub use namada_core::ledger::governance::storage as gov_storage;
pub use namada_core::ledger::parameters;
Expand All @@ -34,10 +33,10 @@ use namada_core::types::storage::{
};
pub use namada_core::types::*;
pub use namada_macros::validity_predicate;
pub use namada_proof_of_stake::storage as proof_of_stake;
use namada_vm_env::vp::*;
use namada_vm_env::{read_from_buffer, read_key_val_bytes_from_buffer};
pub use sha2::{Digest, Sha256, Sha384, Sha512};
pub use {borsh_ext, namada_proof_of_stake as proof_of_stake};

pub fn sha256(bytes: &[u8]) -> Hash {
let digest = Sha256::digest(bytes);
Expand Down
6 changes: 3 additions & 3 deletions wasm/wasm_source/src/vp_implicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<'a> From<&'a storage::Key> for KeyType<'a> {
Self::Pk(address)
} else if let Some([_, owner]) = token::is_any_token_balance_key(key) {
Self::Token { owner }
} else if proof_of_stake::is_pos_key(key) {
} else if proof_of_stake::storage::is_pos_key(key) {
Self::PoS
} else if gov_storage::keys::is_vote_key(key) {
let voter_address = gov_storage::keys::get_voter_address(key);
Expand Down Expand Up @@ -132,10 +132,10 @@ fn validate_tx(
}
KeyType::PoS => {
// Allow the account to be used in PoS
let bond_id = proof_of_stake::is_bond_key(key)
let bond_id = proof_of_stake::storage::is_bond_key(key)
.map(|(bond_id, _)| bond_id)
.or_else(|| {
proof_of_stake::is_unbond_key(key)
proof_of_stake::storage::is_unbond_key(key)
.map(|(bond_id, _, _)| bond_id)
});
let valid = match bond_id {
Expand Down
6 changes: 3 additions & 3 deletions wasm/wasm_source/src/vp_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<'a> From<&'a storage::Key> for KeyType<'a> {
fn from(key: &'a storage::Key) -> KeyType<'a> {
if let Some([_, owner]) = token::is_any_token_balance_key(key) {
Self::Token { owner }
} else if proof_of_stake::is_pos_key(key) {
} else if proof_of_stake::storage::is_pos_key(key) {
Self::PoS
} else if gov_storage::keys::is_vote_key(key) {
let voter_address = gov_storage::keys::get_voter_address(key);
Expand Down Expand Up @@ -107,10 +107,10 @@ fn validate_tx(
}
KeyType::PoS => {
// Allow the account to be used in PoS
let bond_id = proof_of_stake::is_bond_key(key)
let bond_id = proof_of_stake::storage::is_bond_key(key)
.map(|(bond_id, _)| bond_id)
.or_else(|| {
proof_of_stake::is_unbond_key(key)
proof_of_stake::storage::is_unbond_key(key)
.map(|(bond_id, _, _)| bond_id)
});
let valid = match bond_id {
Expand Down
Loading

0 comments on commit 5bed8aa

Please sign in to comment.