* Runtime feature activation framework (cherry picked from commit93259f0bae
) # Conflicts: # runtime/src/bank.rs * Add feature set identifier to gossiped version information (cherry picked from commit35f5f9fc7b
) # Conflicts: # Cargo.lock # version/Cargo.toml * Port instructions sysvar and secp256k1 program activation to FeatureSet (cherry picked from commitc10da16d7b
) # Conflicts: # runtime/src/bank.rs # runtime/src/message_processor.rs * Add feature management commands (cherry picked from commit93ed0ab2bb
) # Conflicts: # Cargo.lock # cli/Cargo.toml * Make test_process_rest_api less fragile (cherry picked from commit7526bb96f3
) * Remove id field (cherry picked from commitcc6ba1e131
) * FeatureSet test (cherry picked from commit92406cf9a0
) * cargo fmt (cherry picked from commit199940d683
) * cli review feedback (cherry picked from commit3a2b8c5e5b
) * Rename active() to is_active() (cherry picked from commite39fac9f01
) * Resolve merge conflicts * Remove continues from compute_active_feature_set() Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
@@ -30,10 +30,9 @@ use solana_runtime::{
|
||||
};
|
||||
use solana_sdk::{
|
||||
clock::{
|
||||
Epoch, Slot, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
|
||||
Slot, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
|
||||
MAX_TRANSACTION_FORWARDING_DELAY_GPU,
|
||||
},
|
||||
genesis_config::ClusterType,
|
||||
poh_config::PohConfig,
|
||||
pubkey::Pubkey,
|
||||
timing::{duration_as_ms, timestamp},
|
||||
@@ -737,8 +736,7 @@ impl BankingStage {
|
||||
fn transactions_from_packets(
|
||||
msgs: &Packets,
|
||||
transaction_indexes: &[usize],
|
||||
cluster_type: ClusterType,
|
||||
epoch: Epoch,
|
||||
secp256k1_program_enabled: bool,
|
||||
) -> (Vec<Transaction>, Vec<usize>) {
|
||||
let packets = Packets::new(
|
||||
transaction_indexes
|
||||
@@ -748,25 +746,24 @@ impl BankingStage {
|
||||
);
|
||||
|
||||
let transactions = Self::deserialize_transactions(&packets);
|
||||
let maybe_secp_verified_transactions: Vec<_> =
|
||||
if solana_sdk::secp256k1::is_enabled(cluster_type, epoch) {
|
||||
transactions
|
||||
.into_iter()
|
||||
.map(|tx| {
|
||||
if let Some(tx) = tx {
|
||||
if tx.verify_precompiles().is_ok() {
|
||||
Some(tx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let maybe_secp_verified_transactions: Vec<_> = if secp256k1_program_enabled {
|
||||
transactions
|
||||
.into_iter()
|
||||
.map(|tx| {
|
||||
if let Some(tx) = tx {
|
||||
if tx.verify_precompiles().is_ok() {
|
||||
Some(tx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
transactions
|
||||
};
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
transactions
|
||||
};
|
||||
|
||||
Self::filter_transaction_indexes(maybe_secp_verified_transactions, &transaction_indexes)
|
||||
}
|
||||
@@ -820,8 +817,7 @@ impl BankingStage {
|
||||
let (transactions, transaction_to_packet_indexes) = Self::transactions_from_packets(
|
||||
msgs,
|
||||
&packet_indexes,
|
||||
bank.cluster_type(),
|
||||
bank.epoch(),
|
||||
bank.secp256k1_program_enabled(),
|
||||
);
|
||||
debug!(
|
||||
"bank: {} filtered transactions {}",
|
||||
@@ -874,8 +870,7 @@ impl BankingStage {
|
||||
let (transactions, transaction_to_packet_indexes) = Self::transactions_from_packets(
|
||||
msgs,
|
||||
&transaction_indexes,
|
||||
bank.cluster_type(),
|
||||
bank.epoch(),
|
||||
bank.secp256k1_program_enabled(),
|
||||
);
|
||||
|
||||
let tx_count = transaction_to_packet_indexes.len();
|
||||
|
@@ -359,7 +359,7 @@ pub fn make_accounts_hashes_message(
|
||||
}
|
||||
|
||||
// TODO These messages should go through the gpu pipeline for spam filtering
|
||||
#[frozen_abi(digest = "CnN1gW2K2TRydGc84eYnQJwdTADPjQf6LJLZ4RP1QeoH")]
|
||||
#[frozen_abi(digest = "3ZHQscZ9SgxKh45idzHv3hiagyyPRtDgeySmJn171PTi")]
|
||||
#[derive(Serialize, Deserialize, Debug, AbiEnumVisitor, AbiExample)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum Protocol {
|
||||
@@ -573,7 +573,7 @@ impl ClusterInfo {
|
||||
}
|
||||
let ip_addr = node.gossip.ip();
|
||||
Some(format!(
|
||||
"{:15} {:2}| {:5} | {:44} |{:^15}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
|
||||
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
|
||||
if ContactInfo::is_valid_address(&node.gossip) {
|
||||
ip_addr.to_string()
|
||||
} else {
|
||||
@@ -605,8 +605,8 @@ impl ClusterInfo {
|
||||
|
||||
format!(
|
||||
"IP Address |Age(ms)| Node identifier \
|
||||
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR| RPC |PubSub|ShredVer\n\
|
||||
------------------+-------+----------------------------------------------+---------------+\
|
||||
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR| RPC |PubSub|ShredVer\n\
|
||||
------------------+-------+----------------------------------------------+---------+\
|
||||
------+------+------+------+------+------+------+------+------+--------\n\
|
||||
{}\
|
||||
Nodes: {}{}{}",
|
||||
@@ -894,7 +894,8 @@ impl ClusterInfo {
|
||||
}
|
||||
|
||||
pub fn get_node_version(&self, pubkey: &Pubkey) -> Option<solana_version::Version> {
|
||||
self.gossip
|
||||
let version = self
|
||||
.gossip
|
||||
.read()
|
||||
.unwrap()
|
||||
.crds
|
||||
@@ -902,7 +903,21 @@ impl ClusterInfo {
|
||||
.get(&CrdsValueLabel::Version(*pubkey))
|
||||
.map(|x| x.value.version())
|
||||
.flatten()
|
||||
.map(|version| version.version.clone())
|
||||
.map(|version| version.version.clone());
|
||||
|
||||
if version.is_none() {
|
||||
self.gossip
|
||||
.read()
|
||||
.unwrap()
|
||||
.crds
|
||||
.table
|
||||
.get(&CrdsValueLabel::LegacyVersion(*pubkey))
|
||||
.map(|x| x.value.legacy_version())
|
||||
.flatten()
|
||||
.map(|version| version.version.clone().into())
|
||||
} else {
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
/// all validators that have a valid rpc port regardless of `shred_version`.
|
||||
|
@@ -75,6 +75,7 @@ pub enum CrdsData {
|
||||
SnapshotHashes(SnapshotHash),
|
||||
AccountsHashes(SnapshotHash),
|
||||
EpochSlots(EpochSlotsIndex, EpochSlots),
|
||||
LegacyVersion(LegacyVersion),
|
||||
Version(Version),
|
||||
}
|
||||
|
||||
@@ -102,6 +103,7 @@ impl Sanitize for CrdsData {
|
||||
}
|
||||
val.sanitize()
|
||||
}
|
||||
CrdsData::LegacyVersion(version) => version.sanitize(),
|
||||
CrdsData::Version(version) => version.sanitize(),
|
||||
}
|
||||
}
|
||||
@@ -208,6 +210,23 @@ impl Vote {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)]
|
||||
pub struct LegacyVersion {
|
||||
pub from: Pubkey,
|
||||
pub wallclock: u64,
|
||||
pub version: solana_version::LegacyVersion,
|
||||
}
|
||||
|
||||
impl Sanitize for LegacyVersion {
|
||||
fn sanitize(&self) -> Result<(), SanitizeError> {
|
||||
if self.wallclock >= MAX_WALLCLOCK {
|
||||
return Err(SanitizeError::ValueOutOfBounds);
|
||||
}
|
||||
self.from.sanitize()?;
|
||||
self.version.sanitize()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, AbiExample)]
|
||||
pub struct Version {
|
||||
pub from: Pubkey,
|
||||
@@ -245,6 +264,7 @@ pub enum CrdsValueLabel {
|
||||
SnapshotHashes(Pubkey),
|
||||
EpochSlots(EpochSlotsIndex, Pubkey),
|
||||
AccountsHashes(Pubkey),
|
||||
LegacyVersion(Pubkey),
|
||||
Version(Pubkey),
|
||||
}
|
||||
|
||||
@@ -257,6 +277,7 @@ impl fmt::Display for CrdsValueLabel {
|
||||
CrdsValueLabel::SnapshotHashes(_) => write!(f, "SnapshotHash({})", self.pubkey()),
|
||||
CrdsValueLabel::EpochSlots(ix, _) => write!(f, "EpochSlots({}, {})", ix, self.pubkey()),
|
||||
CrdsValueLabel::AccountsHashes(_) => write!(f, "AccountsHashes({})", self.pubkey()),
|
||||
CrdsValueLabel::LegacyVersion(_) => write!(f, "LegacyVersion({})", self.pubkey()),
|
||||
CrdsValueLabel::Version(_) => write!(f, "Version({})", self.pubkey()),
|
||||
}
|
||||
}
|
||||
@@ -271,6 +292,7 @@ impl CrdsValueLabel {
|
||||
CrdsValueLabel::SnapshotHashes(p) => *p,
|
||||
CrdsValueLabel::EpochSlots(_, p) => *p,
|
||||
CrdsValueLabel::AccountsHashes(p) => *p,
|
||||
CrdsValueLabel::LegacyVersion(p) => *p,
|
||||
CrdsValueLabel::Version(p) => *p,
|
||||
}
|
||||
}
|
||||
@@ -300,6 +322,7 @@ impl CrdsValue {
|
||||
CrdsData::SnapshotHashes(hash) => hash.wallclock,
|
||||
CrdsData::AccountsHashes(hash) => hash.wallclock,
|
||||
CrdsData::EpochSlots(_, p) => p.wallclock,
|
||||
CrdsData::LegacyVersion(version) => version.wallclock,
|
||||
CrdsData::Version(version) => version.wallclock,
|
||||
}
|
||||
}
|
||||
@@ -311,6 +334,7 @@ impl CrdsValue {
|
||||
CrdsData::SnapshotHashes(hash) => hash.from,
|
||||
CrdsData::AccountsHashes(hash) => hash.from,
|
||||
CrdsData::EpochSlots(_, p) => p.from,
|
||||
CrdsData::LegacyVersion(version) => version.from,
|
||||
CrdsData::Version(version) => version.from,
|
||||
}
|
||||
}
|
||||
@@ -322,6 +346,7 @@ impl CrdsValue {
|
||||
CrdsData::SnapshotHashes(_) => CrdsValueLabel::SnapshotHashes(self.pubkey()),
|
||||
CrdsData::AccountsHashes(_) => CrdsValueLabel::AccountsHashes(self.pubkey()),
|
||||
CrdsData::EpochSlots(ix, _) => CrdsValueLabel::EpochSlots(*ix, self.pubkey()),
|
||||
CrdsData::LegacyVersion(_) => CrdsValueLabel::LegacyVersion(self.pubkey()),
|
||||
CrdsData::Version(_) => CrdsValueLabel::Version(self.pubkey()),
|
||||
}
|
||||
}
|
||||
@@ -373,6 +398,13 @@ impl CrdsValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn legacy_version(&self) -> Option<&LegacyVersion> {
|
||||
match &self.data {
|
||||
CrdsData::LegacyVersion(legacy_version) => Some(legacy_version),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn version(&self) -> Option<&Version> {
|
||||
match &self.data {
|
||||
CrdsData::Version(version) => Some(version),
|
||||
@@ -387,6 +419,7 @@ impl CrdsValue {
|
||||
CrdsValueLabel::LowestSlot(*key),
|
||||
CrdsValueLabel::SnapshotHashes(*key),
|
||||
CrdsValueLabel::AccountsHashes(*key),
|
||||
CrdsValueLabel::LegacyVersion(*key),
|
||||
CrdsValueLabel::Version(*key),
|
||||
];
|
||||
labels.extend((0..MAX_VOTES).map(|ix| CrdsValueLabel::Vote(ix, *key)));
|
||||
@@ -438,7 +471,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_labels() {
|
||||
let mut hits = [false; 5 + MAX_VOTES as usize + MAX_EPOCH_SLOTS as usize];
|
||||
let mut hits = [false; 6 + MAX_VOTES as usize + MAX_EPOCH_SLOTS as usize];
|
||||
// this method should cover all the possible labels
|
||||
for v in &CrdsValue::record_labels(&Pubkey::default()) {
|
||||
match v {
|
||||
@@ -446,10 +479,11 @@ mod test {
|
||||
CrdsValueLabel::LowestSlot(_) => hits[1] = true,
|
||||
CrdsValueLabel::SnapshotHashes(_) => hits[2] = true,
|
||||
CrdsValueLabel::AccountsHashes(_) => hits[3] = true,
|
||||
CrdsValueLabel::Version(_) => hits[4] = true,
|
||||
CrdsValueLabel::Vote(ix, _) => hits[*ix as usize + 5] = true,
|
||||
CrdsValueLabel::LegacyVersion(_) => hits[4] = true,
|
||||
CrdsValueLabel::Version(_) => hits[5] = true,
|
||||
CrdsValueLabel::Vote(ix, _) => hits[*ix as usize + 6] = true,
|
||||
CrdsValueLabel::EpochSlots(ix, _) => {
|
||||
hits[*ix as usize + MAX_VOTES as usize + 5] = true
|
||||
hits[*ix as usize + MAX_VOTES as usize + 6] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1950,14 +1950,19 @@ impl RpcSol for RpcSolImpl {
|
||||
if my_shred_version == contact_info.shred_version
|
||||
&& ContactInfo::is_valid_address(&contact_info.gossip)
|
||||
{
|
||||
let (version, feature_set) =
|
||||
if let Some(version) = cluster_info.get_node_version(&contact_info.id) {
|
||||
(Some(version.to_string()), Some(version.feature_set))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
Some(RpcContactInfo {
|
||||
pubkey: contact_info.id.to_string(),
|
||||
gossip: Some(contact_info.gossip),
|
||||
tpu: valid_address_or_none(&contact_info.tpu),
|
||||
rpc: valid_address_or_none(&contact_info.rpc),
|
||||
version: cluster_info
|
||||
.get_node_version(&contact_info.id)
|
||||
.map(|v| v.to_string()),
|
||||
version,
|
||||
feature_set,
|
||||
})
|
||||
} else {
|
||||
None // Exclude spy nodes
|
||||
@@ -2304,8 +2309,10 @@ impl RpcSol for RpcSolImpl {
|
||||
|
||||
fn get_version(&self, _: Self::Metadata) -> Result<RpcVersionInfo> {
|
||||
debug!("get_version rpc request received");
|
||||
let version = solana_version::Version::default();
|
||||
Ok(RpcVersionInfo {
|
||||
solana_core: solana_version::Version::default().to_string(),
|
||||
solana_core: version.to_string(),
|
||||
feature_set: Some(version.feature_set),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2853,7 +2860,7 @@ pub mod tests {
|
||||
.expect("actual response deserialization");
|
||||
|
||||
let expected = format!(
|
||||
r#"{{"jsonrpc":"2.0","result":[{{"pubkey": "{}", "gossip": "127.0.0.1:1235", "tpu": "127.0.0.1:1234", "rpc": "127.0.0.1:{}", "version": null}}],"id":1}}"#,
|
||||
r#"{{"jsonrpc":"2.0","result":[{{"pubkey": "{}", "gossip": "127.0.0.1:1235", "tpu": "127.0.0.1:1234", "rpc": "127.0.0.1:{}", "version": null, "featureSet": null}}],"id":1}}"#,
|
||||
leader_pubkey,
|
||||
rpc_port::DEFAULT_RPC_PORT
|
||||
);
|
||||
@@ -4404,10 +4411,12 @@ pub mod tests {
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getVersion"}"#;
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let version = solana_version::Version::default();
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"solana-core": solana_version::version!().to_string()
|
||||
"solana-core": version.to_string(),
|
||||
"feature-set": version.feature_set,
|
||||
},
|
||||
"id": 1
|
||||
});
|
||||
|
@@ -480,11 +480,7 @@ mod tests {
|
||||
|
||||
assert_eq!(None, process_rest(&bank_forks, "not-a-supported-rest-api"));
|
||||
assert_eq!(
|
||||
Some("0.000010127".to_string()),
|
||||
process_rest(&bank_forks, "/v0/circulating-supply")
|
||||
);
|
||||
assert_eq!(
|
||||
Some("0.000010127".to_string()),
|
||||
process_rest(&bank_forks, "/v0/circulating-supply"),
|
||||
process_rest(&bank_forks, "/v0/total-supply")
|
||||
);
|
||||
}
|
||||
|
@@ -80,10 +80,7 @@ impl TransactionStatusService {
|
||||
_ => bank.get_fee_calculator(&transaction.message().recent_blockhash),
|
||||
}
|
||||
.expect("FeeCalculator must exist");
|
||||
let fee = fee_calculator.calculate_fee(
|
||||
transaction.message(),
|
||||
solana_sdk::secp256k1::get_fee_config(bank.cluster_type(), bank.epoch()),
|
||||
);
|
||||
let fee = fee_calculator.calculate_fee(transaction.message());
|
||||
let (writable_keys, readonly_keys) =
|
||||
transaction.message.get_account_keys_by_lock_type();
|
||||
|
||||
|
Reference in New Issue
Block a user