1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
use crate::types::ProtocolVersion;
/// New Protocol features should go here. Features are guarded by their corresponding feature flag.
/// For example, if we have `ProtocolFeature::EVM` and a corresponding feature flag `evm`, it will look
/// like
///
/// #[cfg(feature = "protocol_feature_evm")]
/// EVM code
///
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
pub enum ProtocolFeature {
// stable features
ImplicitAccountCreation,
RectifyInflation,
/// Add `AccessKey` nonce range by setting nonce to `(block_height - 1) * 1e6`, see
/// <https://github.com/utnet-org/utility/issues/3779>.
AccessKeyNonceRange,
/// Don't process any receipts for shard when chunk is not present.
/// Always use gas price computed in the previous block.
FixApplyChunks,
LowerStorageCost,
DeleteActionRestriction,
/// Add versions to `Account` data structure
AccountVersions,
TransactionSizeLimit,
/// Fix a bug in `storage_usage` for account caused by #3824
FixStorageUsage,
/// Cap maximum gas price to 2,000,000,000 attoUNC
CapMaxGasPrice,
CountRefundReceiptsInGasLimit,
/// Add `ripemd60` and `ecrecover` host function
MathExtension,
/// Restore receipts that were previously stuck because of
/// <https://github.com/utnet-org/utility/pull/4228>.
RestoreReceiptsAfterFixApplyChunks,
/// This feature switch our WASM engine implementation from wasmer 0.* to
/// wasmer 2.*, bringing better performance and reliability.
///
/// The implementations should be sufficiently similar for this to not be a
/// protocol upgrade, but we conservatively do a protocol upgrade to be on
/// the safe side.
///
/// Although wasmer2 is faster, we don't change fees with this protocol
/// version -- we can safely do that in a separate step.
Wasmer2,
SimpleNightshade,
LowerDataReceiptAndEcrecoverBaseCost,
/// Lowers the cost of wasm instruction due to switch to wasmer2.
LowerRegularOpCost,
/// Lowers the cost of wasm instruction due to switch to faster,
/// compiler-intrinsics based gas counter.
LowerRegularOpCost2,
/// Limit number of wasm functions in one contract. See
/// <https://github.com/utnet-org/utility/pull/4954> for more details.
LimitContractFunctionsNumber,
BlockHeaderV3,
/// Changes how we select validators for epoch and how we select validators
/// within epoch. See <https://github.com/Utility/UEPs/pull/167> for general
/// description, note that we would not introduce chunk-only validators with
/// this feature
AliasValidatorSelectionAlgorithm,
/// Make block producers produce chunks for the same block they would later produce to avoid
/// network delays
SynchronizeBlockChunkProduction,
/// Change the algorithm to count WASM stack usage to avoid undercounting in
/// some cases.
CorrectStackLimit,
/// Add `AccessKey` nonce range for implicit accounts, as in `AccessKeyNonceRange` feature.
AccessKeyNonceForImplicitAccounts,
/// Increase cost per deployed code byte to cover for the compilation steps
/// that a deployment triggers. Only affects the action execution cost.
IncreaseDeploymentCost,
FunctionCallWeight,
/// This feature enforces a global limit on the function local declarations in a WebAssembly
/// contract. See <...> for more information.
LimitContractLocals,
/// Ensure caching all nodes in the chunk for which touching trie node cost was charged. Charge for each such node
/// only once per chunk at the first access time.
ChunkNodesCache,
/// Lower `max_length_storage_key` limit, which itself limits trie node sizes.
LowerStorageKeyLimit,
// alt_bn128_g1_multiexp, alt_bn128_g1_sum, alt_bn128_pairing_check host functions
AltBn128,
ChunkOnlyProducers,
/// Ensure the total pledge of validators that are kicked out does not exceed a percentage of total pledges
MaxKickoutPledge,
/// Validate account id for function call access keys.
AccountIdInFunctionCallPermission,
/// Zero Balance Account NEP 448: https://github.com/Utility/UEPs/pull/448
ZeroBalanceAccount,
/// Execute a set of actions on behalf of another account.
///
/// Meta Transaction NEP-366: https://github.com/Utility/UEPs/blob/master/neps/nep-0366.md
DelegateAction,
Ed25519Verify,
/// Decouple compute and gas costs of operations to safely limit the compute time it takes to
/// process the chunk.
///
/// Compute Costs NEP-455: https://github.com/Utility/UEPs/blob/master/neps/nep-0455.md
ComputeCosts,
/// Enable flat storage for reads, reducing number of DB accesses from `2 * key.len()` in
/// the worst case to 2.
///
/// Flat Storage NEP-399: https://github.com/Utility/UEPs/blob/master/neps/nep-0399.md
FlatStorageReads,
/// Enables preparation V2. Note that this setting is not supported in production settings
/// without NearVmRuntime enabled alongside it, as the VM runner would be too slow.
PreparationV2,
/// Enables unc-Vm. Note that this setting is not at all supported without PreparationV2,
/// as it hardcodes preparation v2 code into the generated assembly.
NearVmRuntime,
BlockHeaderV4,
/// Resharding V2. A new implementation for resharding and a new shard
/// layout for the production networks.
SimpleNightshadeV2,
/// In case not all validator seats are occupied our algorithm provide incorrect minimal seat
/// price - it reports as alpha * sum_pledge instead of alpha * sum_pledge / (1 - alpha), where
/// alpha is min pledge ratio
#[cfg(feature = "protocol_feature_fix_staking_threshold")]
FixStakingThreshold,
/// Charge for contract loading before it happens.
#[cfg(feature = "protocol_feature_fix_contract_loading_cost")]
FixContractLoadingCost,
#[cfg(feature = "protocol_feature_reject_blocks_with_outdated_protocol_version")]
RejectBlocksWithOutdatedProtocolVersions,
RestrictTla,
/// Increases the number of chunk producers.
TestnetFewerBlockProducers,
/// Enables chunk validation which is introduced with stateless validation.
/// NEP: https://github.com/Utility/UEPs/pull/509
ChunkValidation,
EthImplicitAccounts,
}
impl ProtocolFeature {
pub const fn protocol_version(self) -> ProtocolVersion {
match self {
// Stable features
ProtocolFeature::ImplicitAccountCreation => 35,
ProtocolFeature::LowerStorageCost => 42,
ProtocolFeature::DeleteActionRestriction => 43,
ProtocolFeature::FixApplyChunks => 44,
ProtocolFeature::RectifyInflation | ProtocolFeature::AccessKeyNonceRange => 45,
ProtocolFeature::AccountVersions
| ProtocolFeature::TransactionSizeLimit
| ProtocolFeature::FixStorageUsage
| ProtocolFeature::CapMaxGasPrice
| ProtocolFeature::CountRefundReceiptsInGasLimit
| ProtocolFeature::MathExtension => 46,
ProtocolFeature::RestoreReceiptsAfterFixApplyChunks => 47,
ProtocolFeature::Wasmer2
| ProtocolFeature::LowerDataReceiptAndEcrecoverBaseCost
| ProtocolFeature::LowerRegularOpCost
| ProtocolFeature::SimpleNightshade => 48,
ProtocolFeature::LowerRegularOpCost2
| ProtocolFeature::LimitContractFunctionsNumber
| ProtocolFeature::BlockHeaderV3
| ProtocolFeature::AliasValidatorSelectionAlgorithm => 49,
ProtocolFeature::SynchronizeBlockChunkProduction
| ProtocolFeature::CorrectStackLimit => 50,
ProtocolFeature::AccessKeyNonceForImplicitAccounts => 51,
ProtocolFeature::IncreaseDeploymentCost
| ProtocolFeature::FunctionCallWeight
| ProtocolFeature::LimitContractLocals
| ProtocolFeature::ChunkNodesCache
| ProtocolFeature::LowerStorageKeyLimit => 53,
ProtocolFeature::AltBn128 => 55,
ProtocolFeature::ChunkOnlyProducers | ProtocolFeature::MaxKickoutPledge => 56,
ProtocolFeature::AccountIdInFunctionCallPermission => 57,
ProtocolFeature::Ed25519Verify
| ProtocolFeature::ZeroBalanceAccount
| ProtocolFeature::DelegateAction => 59,
ProtocolFeature::ComputeCosts | ProtocolFeature::FlatStorageReads => 61,
ProtocolFeature::PreparationV2 | ProtocolFeature::NearVmRuntime => 62,
ProtocolFeature::BlockHeaderV4 => 63,
ProtocolFeature::RestrictTla
| ProtocolFeature::TestnetFewerBlockProducers
| ProtocolFeature::SimpleNightshadeV2 => 64,
// Nightly features
#[cfg(feature = "protocol_feature_fix_staking_threshold")]
ProtocolFeature::FixStakingThreshold => 126,
#[cfg(feature = "protocol_feature_fix_contract_loading_cost")]
ProtocolFeature::FixContractLoadingCost => 129,
#[cfg(feature = "protocol_feature_reject_blocks_with_outdated_protocol_version")]
ProtocolFeature::RejectBlocksWithOutdatedProtocolVersions => 132,
ProtocolFeature::ChunkValidation => 137,
ProtocolFeature::EthImplicitAccounts => 138,
}
}
}
/// Current protocol version used on the mainnet.
/// Some features (e. g. FixStorageUsage) require that there is at least one epoch with exactly
/// the corresponding version
const STABLE_PROTOCOL_VERSION: ProtocolVersion = 64;
/// Largest protocol version supported by the current binary.
pub const PROTOCOL_VERSION: ProtocolVersion = if cfg!(feature = "nightly_protocol") {
// On nightly, pick big enough version to support all features.
139
} else {
// Enable all stable features.
STABLE_PROTOCOL_VERSION
};
/// Both, outgoing and incoming tcp connections to peers, will be rejected if `peer's`
/// protocol version is lower than this.
pub const PEER_MIN_ALLOWED_PROTOCOL_VERSION: ProtocolVersion = STABLE_PROTOCOL_VERSION - 2;
#[macro_export]
macro_rules! checked_feature {
("stable", $feature:ident, $current_protocol_version:expr) => {{
$crate::version::ProtocolFeature::$feature.protocol_version() <= $current_protocol_version
}};
($feature_name:tt, $feature:ident, $current_protocol_version:expr) => {{
#[cfg(feature = $feature_name)]
let is_feature_enabled = $crate::version::ProtocolFeature::$feature.protocol_version()
<= $current_protocol_version;
#[cfg(not(feature = $feature_name))]
let is_feature_enabled = {
// Workaround unused variable warning
let _ = $current_protocol_version;
false
};
is_feature_enabled
}};
($feature_name:tt, $feature:ident, $current_protocol_version:expr, $feature_block:block) => {{
checked_feature!($feature_name, $feature, $current_protocol_version, $feature_block, {})
}};
($feature_name:tt, $feature:ident, $current_protocol_version:expr, $feature_block:block, $non_feature_block:block) => {{
#[cfg(feature = $feature_name)]
{
if checked_feature!($feature_name, $feature, $current_protocol_version) {
$feature_block
} else {
$non_feature_block
}
}
// Workaround unused variable warning
#[cfg(not(feature = $feature_name))]
{
let _ = $current_protocol_version;
$non_feature_block
}
}};
}