diff --git a/README.md b/README.md
index c6183f6ab6183e..e2b9007b3dbd50 100644
--- a/README.md
+++ b/README.md
@@ -1,147 +1,2 @@
-
-
-
-
-
-[](https://crates.io/crates/solana-core)
-[](https://docs.rs/solana-core)
-[](https://buildkite.com/solana-labs/solana/builds?branch=master)
-[](https://codecov.io/gh/solana-labs/solana)
-
-# Building
-
-## **1. Install rustc, cargo and rustfmt.**
-
-```bash
-$ curl https://sh.rustup.rs -sSf | sh
-$ source $HOME/.cargo/env
-$ rustup component add rustfmt
-```
-
-When building the master branch, please make sure you are using the latest stable rust version by running:
-
-```bash
-$ rustup update
-```
-
-When building a specific release branch, you should check the rust version in `ci/rust-version.sh` and if necessary, install that version by running:
-```bash
-$ rustup install VERSION
-```
-Note that if this is not the latest rust version on your machine, cargo commands may require an [override](https://rust-lang.github.io/rustup/overrides.html) in order to use the correct version.
-
-On Linux systems you may need to install libssl-dev, pkg-config, zlib1g-dev, protobuf etc.
-
-On Ubuntu:
-```bash
-$ sudo apt-get update
-$ sudo apt-get install libssl-dev libudev-dev pkg-config zlib1g-dev llvm clang cmake make libprotobuf-dev protobuf-compiler
-```
-
-On Fedora:
-```bash
-$ sudo dnf install openssl-devel systemd-devel pkg-config zlib-devel llvm clang cmake make protobuf-devel protobuf-compiler perl-core
-```
-
-## **2. Download the source code.**
-
-```bash
-$ git clone https://github.com/solana-labs/solana.git
-$ cd solana
-```
-
-## **3. Build.**
-
-```bash
-$ ./cargo build
-```
-
-# Testing
-
-**Run the test suite:**
-
-```bash
-$ ./cargo test
-```
-
-### Starting a local testnet
-
-Start your own testnet locally, instructions are in the [online docs](https://docs.solanalabs.com/clusters/benchmark).
-
-### Accessing the remote development cluster
-
-* `devnet` - stable public cluster for development accessible via
-devnet.solana.com. Runs 24/7. Learn more about the [public clusters](https://docs.solanalabs.com/clusters)
-
-# Benchmarking
-
-First, install the nightly build of rustc. `cargo bench` requires the use of the
-unstable features only available in the nightly build.
-
-```bash
-$ rustup install nightly
-```
-
-Run the benchmarks:
-
-```bash
-$ cargo +nightly bench
-```
-
-# Release Process
-
-The release process for this project is described [here](RELEASE.md).
-
-# Code coverage
-
-To generate code coverage statistics:
-
-```bash
-$ scripts/coverage.sh
-$ open target/cov/lcov-local/index.html
-```
-
-Why coverage? While most see coverage as a code quality metric, we see it primarily as a developer
-productivity metric. When a developer makes a change to the codebase, presumably it's a *solution* to
-some problem. Our unit-test suite is how we encode the set of *problems* the codebase solves. Running
-the test suite should indicate that your change didn't *infringe* on anyone else's solutions. Adding a
-test *protects* your solution from future changes. Say you don't understand why a line of code exists,
-try deleting it and running the unit-tests. The nearest test failure should tell you what problem
-was solved by that code. If no test fails, go ahead and submit a Pull Request that asks, "what
-problem is solved by this code?" On the other hand, if a test does fail and you can think of a
-better way to solve the same problem, a Pull Request with your solution would most certainly be
-welcome! Likewise, if rewriting a test can better communicate what code it's protecting, please
-send us that patch!
-
-# Disclaimer
-
-All claims, content, designs, algorithms, estimates, roadmaps,
-specifications, and performance measurements described in this project
-are done with the Solana Labs, Inc. (“SL”) good faith efforts. It is up to
-the reader to check and validate their accuracy and truthfulness.
-Furthermore, nothing in this project constitutes a solicitation for
-investment.
-
-Any content produced by SL or developer resources that SL provides are
-for educational and inspirational purposes only. SL does not encourage,
-induce or sanction the deployment, integration or use of any such
-applications (including the code comprising the Solana blockchain
-protocol) in violation of applicable laws or regulations and hereby
-prohibits any such deployment, integration or use. This includes the use of
-any such applications by the reader (a) in violation of export control
-or sanctions laws of the United States or any other applicable
-jurisdiction, (b) if the reader is located in or ordinarily resident in
-a country or territory subject to comprehensive sanctions administered
-by the U.S. Office of Foreign Assets Control (OFAC), or (c) if the
-reader is or is working on behalf of a Specially Designated National
-(SDN) or a person subject to similar blocking or denied party
-prohibitions.
-
-The reader should be aware that U.S. export control and sanctions laws prohibit
-U.S. persons (and other persons that are subject to such laws) from transacting
-with persons in certain countries and territories or that are on the SDN list.
-Accordingly, there is a risk to individuals that other persons using any of the
-code contained in this repo, or a derivation thereof, may be sanctioned persons
-and that transactions with such persons would be a violation of U.S. export
-controls and sanctions law.
+***THIS PROJECT IS ARCHIVED. PLEASE USE https://github.com/x1-labs/tachyon***
diff --git a/genesis/src/genesis_accounts.rs b/genesis/src/genesis_accounts.rs
index 0704985913838f..007effb2102149 100644
--- a/genesis/src/genesis_accounts.rs
+++ b/genesis/src/genesis_accounts.rs
@@ -1,3 +1,4 @@
+#![allow(warnings)]
use {
crate::{
stakes::{create_and_add_stakes, StakerInfo},
@@ -7,22 +8,22 @@ use {
};
// 9 month schedule is 100% after 9 months
-const UNLOCKS_ALL_AT_9_MONTHS: UnlockInfo = UnlockInfo {
- cliff_fraction: 1.0,
- cliff_years: 0.75,
- unlocks: 0,
- unlock_years: 0.0,
- custodian: "Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8",
-};
+// const UNLOCKS_ALL_AT_9_MONTHS: UnlockInfo = UnlockInfo {
+// cliff_fraction: 1.0,
+// cliff_years: 0.75,
+// unlocks: 0,
+// unlock_years: 0.0,
+// custodian: "Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8",
+// };
// 9 month schedule is 50% after 9 months, then monthly for 2 years
-const UNLOCKS_HALF_AT_9_MONTHS: UnlockInfo = UnlockInfo {
- cliff_fraction: 0.5,
- cliff_years: 0.75,
- unlocks: 24,
- unlock_years: 2.0,
- custodian: "Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8",
-};
+// const UNLOCKS_HALF_AT_9_MONTHS: UnlockInfo = UnlockInfo {
+// cliff_fraction: 0.5,
+// cliff_years: 0.75,
+// unlocks: 24,
+// unlock_years: 2.0,
+// custodian: "Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8",
+// };
// no lockups
const UNLOCKS_ALL_DAY_ZERO: UnlockInfo = UnlockInfo {
@@ -37,91 +38,91 @@ pub const CREATOR_STAKER_INFOS: &[StakerInfo] = &[
StakerInfo {
name: "impossible pizza",
staker: "uE3TVEffRp69mrgknYr71M18GDqL7GxCNGYYRjb3oUt",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("59SLqk4ete5QttM1WmjfMA7uNJnJVFLQqXJSy9rvuj7c"),
},
StakerInfo {
name: "nutritious examination",
staker: "9noVEZreMmgQvE8iyKmxy7CGTJ2enELyuJ1qxFtXrfJB",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("ERnx3Csgu3LjrGGrCeCUZzuHguRu6XabT1kufSB1NDWi"),
},
StakerInfo {
name: "tidy impression",
staker: "BU7LA4kYvicfPCp22EM2Tth3eaeWAXYo6yCgWXQFJ42z",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("5eKcGy7ZCPJdQSQGVnfmT7kGz6MKPMKaNaMEYJbmwhuT"),
},
StakerInfo {
name: "dramatic treatment",
staker: "BrNFrFeuev8TosKhRe2kvVZTYrcUuYaqCfptWutxs17B",
- lamports: 1_205_602 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("2pKqwFKfKj2nGrknPNDSP8vXGYrgAjd28fT6yLew8sT3"),
},
StakerInfo {
name: "angry noise",
staker: "34HCVh8Yx4jNkaeLUQEKibFKUZDPQMjWzkXy8qUfdhS4",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("Hw3sP6PreBtFCnwXbNvUypMhty62GXibjfiZ1zHBXFk6"),
},
StakerInfo {
name: "hard cousin",
staker: "AyZb3xrZE8wnS6gYBdsJg5v8CjyrX2ZGXU2zMakCFyYd",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("9j3WzBSZRHrD2DbzFTUVVi81QX6boVvUTpGWcSiMwD5W"),
},
StakerInfo {
name: "lopsided skill",
staker: "7SbpY8LmZUb5XRqDbyoreUrSVVV9c39wkpEz81kEAXu5",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("EJyZGbQ1PmpcWxfqGME6SUNHfurh1zggDqCT7rV9xLzL"),
},
StakerInfo {
name: "red snake",
staker: "C9CfFpmLDsQsz6wt7MrrZquNB5oS4QkpJkmDAiboVEZZ",
- lamports: 3_655_292 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("JBGnGdLyo7V2z9hz51mnnbyDp9sBACtw5WYH9YRG8n7e"),
},
StakerInfo {
name: "jolly year",
staker: "5WbxKiW7bghkr8JN6ZAv2TQt4PfJFvtuqNaN8gyQ5UzU",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("43XAfG3AFiF1ockdh7xp91fpFyZkbWSZq9ZFBCGUVV41"),
},
StakerInfo {
name: "typical initiative",
staker: "Gc8XnHU6Nnriwt9RbEwi7PTosx4YanLyXak9GTbB8VaH",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("7s2GVwFo8VSrCwX9Tztt42ueiEaUtJ6zCEHU8XGvuf5E"),
},
StakerInfo {
name: "deserted window",
staker: "AMmYEynkd78uNTZDFFrMw6NKjWTgqW7M8EFjvajk23VR",
- lamports: 3_655_292 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("23PJYLS1WFLqhXnXq2Hobc17DbvZaoinoTZYLyGRT8E2"),
},
StakerInfo {
name: "eight nation",
staker: "4qWoqt71p7h6siSDS6osu4oVWpw8R7E6uYYiY7Z6oJbH",
- lamports: 103_519 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("6bFjx3egMjVsGKFb445564a4bwgibwbUB2tVFsJcdPv7"),
},
StakerInfo {
name: "earsplitting meaning",
staker: "GYitoBY53E9awc56NWHJ2kxMwj4do5GSmvTRowjGaRDw",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("jXMEkVQQpoqebVMGN7DfpvdRLwJDEkoVNrwPVphNm7i"),
},
StakerInfo {
name: "alike cheese",
staker: "Drg9uSvSEfjtn15jqmmrEQnA4pvU1ToYSGSa1Dv9C6Fk",
- lamports: 3_880_295 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("BxmwgfnyAqZnqRCJGdsEea35pcc92GFTcyGeSj4RNfJJ"),
},
StakerInfo {
name: "noisy honey",
staker: "95HsPFFvwbWpk42MKzenauSoULNzk8Tg6fc6EiJhLsUZ",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("Aj3K933zdRQhYEJi2Yjz8hJWXN3Z3hrKJQtPtE8VmUnq"),
},
];
@@ -130,37 +131,37 @@ pub const SERVICE_STAKER_INFOS: &[StakerInfo] = &[
StakerInfo {
name: "wretched texture",
staker: "B1hegzthtfNQxyEPzkESySxRjMidNqaxrzbQ28GaEwn8",
- lamports: 225_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("HWzeqw1Yk5uiLgT2uGUim5ocFJNCwYUFbeCtDVpx9yUb"),
},
StakerInfo {
name: "unbecoming silver",
staker: "4AcoZa1P8fF5XK21RJsiuMRZPEScbbWNc75oakRFHiBz",
- lamports: 28_800 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: None,
},
StakerInfo {
name: "inexpensive uncle",
staker: "AkJ7yssRqS3X4UWLUsPTxbP6LfVgdPYBWH4Jgk5EETgZ",
- lamports: 300_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("6mudxxoe5VyXXNXsJ3NSGSTGESfG2t86PBCQGbouHpXX"),
},
StakerInfo {
name: "hellish money",
staker: "4DVkqvRP8y26JvzNwsnQEQuC7HASwpGs58GsAT9XJMVg",
- lamports: 200_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("ASJpWZAxY96kbciLqzb7sg45gsH32yPzGcxjn7HPcARn"),
},
StakerInfo {
name: "full grape",
staker: "B2EWnwgmNd3KMpD71yZMijhML1jd4TYp96zJdhMiWZ7b",
- lamports: 450_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("9oaCkokBBhgBsgyg4sL7fMJyQseaJb1TbADZeoPdpWdc"),
},
StakerInfo {
name: "nice ghost",
staker: "HtQS1CH3nsUHmnLpenj5W6KHzFWTf3mzCn1mTqK7LkB7",
- lamports: 650_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("4YnNnycEZXCkuVs2hDthdNxMD4E8wc7ZPgyAK7Lm1uZc"),
},
];
@@ -169,13 +170,13 @@ pub const FOUNDATION_STAKER_INFOS: &[StakerInfo] = &[
StakerInfo {
name: "lyrical supermarket",
staker: "4xh7vtQCTim3vgpQ1dQQWjtKrBSkbtL3s15FimXVJAAP",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("C7WS9ic7KN9XNcLsNoMvzTvbzURM3rFGDEQN7qJMWNLn"),
},
StakerInfo {
name: "frequent description",
staker: "95Nf8XfoecteSXU9nbcvzkrFQdu6FqPaH3EvhwLaC83t",
- lamports: 57_500_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("FdGYQdiRky8NZzN9wZtczTBcWLYYRXrJ3LMDhqDPn5rM"),
},
];
@@ -184,13 +185,13 @@ pub const GRANTS_STAKER_INFOS: &[StakerInfo] = &[
StakerInfo {
name: "rightful agreement",
staker: "8w5cgUQfXAZZWyVgenPHpQ1uABXUVLnymqXbuZPx7yqt",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("EDwSQShtUWQtmFfN9SpUUd6hgonL7tRdxngAsNKv9Pe6"),
},
StakerInfo {
name: "tasty location",
staker: "9eyXtP43dCp59oyvWG2R7WQCeJ2bA6TWoLzXg1KTDfQQ",
- lamports: 15_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("9BgvWHerNACjnx6ZpK51k2LEsnwBP3gFwWDzhKkHKH1m"),
},
];
@@ -199,19 +200,19 @@ pub const COMMUNITY_STAKER_INFOS: &[StakerInfo] = &[
StakerInfo {
name: "shrill charity",
staker: "Eo1iDtrZZiAkQFA8u431hedChaSUnPbU8MWg849MFvEZ",
- lamports: 5_000_000 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK"),
},
StakerInfo {
name: "legal gate",
staker: "7KCzZCbZz6V1U1YXUpBNaqQzQCg2DKo8JsNhKASKtYxe",
- lamports: 30_301_032 * LAMPORTS_PER_SOL,
+ lamports: 1,
withdrawer: Some("92viKFftk1dJjqJwreFqT2qHXxjSUuEE9VyHvTdY1mpY"),
},
StakerInfo {
name: "cluttered complaint",
staker: "2J8mJU6tWg78DdQVEqMfpN3rMeNbcRT9qGL3yLbmSXYL",
- lamports: 153_333_633 * LAMPORTS_PER_SOL + 41 * LAMPORTS_PER_SOL / 100,
+ lamports: 1,
withdrawer: Some("7kgfDmgbEfypBujqn4tyApjf8H7ZWuaL3F6Ah9vQHzgR"),
},
];
@@ -231,24 +232,24 @@ pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig, mut issued_lampo
// add_stakes() and add_validators() award tokens for rent exemption and
// to cover an initial transfer-free period of the network
- issued_lamports += add_stakes(
- genesis_config,
- CREATOR_STAKER_INFOS,
- &UNLOCKS_HALF_AT_9_MONTHS,
- ) + add_stakes(
- genesis_config,
- SERVICE_STAKER_INFOS,
- &UNLOCKS_ALL_AT_9_MONTHS,
- ) + add_stakes(
- genesis_config,
- FOUNDATION_STAKER_INFOS,
- &UNLOCKS_ALL_DAY_ZERO,
- ) + add_stakes(genesis_config, GRANTS_STAKER_INFOS, &UNLOCKS_ALL_DAY_ZERO)
- + add_stakes(
- genesis_config,
- COMMUNITY_STAKER_INFOS,
- &UNLOCKS_ALL_DAY_ZERO,
- );
+ // issued_lamports += add_stakes(
+ // genesis_config,
+ // CREATOR_STAKER_INFOS,
+ // &UNLOCKS_HALF_AT_9_MONTHS,
+ // ) + add_stakes(
+ // genesis_config,
+ // SERVICE_STAKER_INFOS,
+ // &UNLOCKS_ALL_AT_9_MONTHS,
+ // ) + add_stakes(
+ // genesis_config,
+ // FOUNDATION_STAKER_INFOS,
+ // &UNLOCKS_ALL_DAY_ZERO,
+ // ) + add_stakes(genesis_config, GRANTS_STAKER_INFOS, &UNLOCKS_ALL_DAY_ZERO)
+ // + add_stakes(
+ // genesis_config,
+ // COMMUNITY_STAKER_INFOS,
+ // &UNLOCKS_ALL_DAY_ZERO,
+ // );
// "one thanks" (community pool) gets 500_000_000SOL (total) - above distributions
create_and_add_stakes(
@@ -256,7 +257,8 @@ pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig, mut issued_lampo
&StakerInfo {
name: "one thanks",
staker: "7vEAL3nS9CWmy1q6njUUyHE7Cf5RmyQpND6CsoHjzPiR",
- lamports: (500_000_000 * LAMPORTS_PER_SOL).saturating_sub(issued_lamports),
+ //lamports: (500_000_000 * LAMPORTS_PER_SOL).saturating_sub(issued_lamports),
+ lamports: (100 * LAMPORTS_PER_SOL).saturating_sub(issued_lamports),
withdrawer: Some("3FFaheyqtyAXZSYxDzsr5CVKvJuvZD1WE1VEsBtDbRqB"),
},
&UNLOCKS_ALL_DAY_ZERO,
diff --git a/genesis/src/stakes.rs b/genesis/src/stakes.rs
index b1f545b218fa6f..3c628e5f2916a6 100644
--- a/genesis/src/stakes.rs
+++ b/genesis/src/stakes.rs
@@ -1,4 +1,7 @@
//! stakes generator
+#![allow(warnings)]
+#![allow(unused)]
+
use {
crate::{
address_generator::AddressGenerator,
@@ -34,10 +37,10 @@ pub struct StakerInfo {
fn calculate_staker_fees(genesis_config: &GenesisConfig, years: f64) -> u64 {
genesis_config.fee_rate_governor.max_lamports_per_signature
* genesis_config.epoch_schedule.get_epoch(years_as_slots(
- years,
- &genesis_config.poh_config.target_tick_duration,
- genesis_config.ticks_per_slot,
- ) as Slot)
+ years,
+ &genesis_config.poh_config.target_tick_duration,
+ genesis_config.ticks_per_slot,
+ ) as Slot)
}
/// create stake accounts for lamports with at most stake_granularity in each
@@ -51,6 +54,7 @@ pub fn create_and_add_stakes(
// the largest each stake account should be, in lamports
granularity: Option,
) -> u64 {
+ /*
let granularity = granularity.unwrap_or(std::u64::MAX);
let staker = &staker_info
.staker
@@ -161,6 +165,8 @@ pub fn create_and_add_stakes(
}
}
total_lamports
+ */
+ 10000
}
#[cfg(test)]
diff --git a/sdk/src/fee.rs b/sdk/src/fee.rs
index f3377b5254f0a6..9fbf5fd925d75e 100644
--- a/sdk/src/fee.rs
+++ b/sdk/src/fee.rs
@@ -1,8 +1,431 @@
//! Fee structures.
+//use std::time::{SystemTime, UNIX_EPOCH};
+use std::collections::{HashMap, HashSet};
+use std::str::FromStr;
+
+use lazy_static::lazy_static;
use crate::native_token::sol_to_lamports;
+use log::trace;
+use solana_program::borsh1::try_from_slice_unchecked;
+use solana_program::clock::{Epoch, Slot};
+use solana_program::epoch_schedule::EpochSchedule;
+use solana_program::instruction::{CompiledInstruction, InstructionError};
+
#[cfg(not(target_os = "solana"))]
use solana_program::message::SanitizedMessage;
+use solana_program::pubkey::Pubkey;
+use crate::{compute_budget, feature_set};
+use crate::compute_budget::ComputeBudgetInstruction;
+use crate::feature_set::{FEATURE_NAMES, full_inflation, FULL_INFLATION_FEATURE_PAIRS, include_loaded_accounts_data_size_in_fee_calculation, reduce_stake_warmup_cooldown};
+use crate::transaction::{TransactionError};
+// use crate::transaction::{SanitizedTransaction, TransactionError};
+
+pub const COMPUTE_UNIT_TO_US_RATIO: u64 = 30;
+pub const SIGNATURE_COST: u64 = COMPUTE_UNIT_TO_US_RATIO * 24;
+/// Number of compute units for one secp256k1 signature verification.
+pub const SECP256K1_VERIFY_COST: u64 = COMPUTE_UNIT_TO_US_RATIO * 223;
+/// Number of compute units for one ed25519 signature verification.
+pub const ED25519_VERIFY_COST: u64 = COMPUTE_UNIT_TO_US_RATIO * 76;
+pub const WRITE_LOCK_UNITS: u64 = COMPUTE_UNIT_TO_US_RATIO * 10;
+pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000;
+pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000;
+pub const HEAP_LENGTH: usize = 32 * 1024;
+const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
+pub const MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES: u32 = 64 * 1024 * 1024;
+pub const DEFAULT_HEAP_COST: u64 = 8;
+pub const INSTRUCTION_DATA_BYTES_COST: u64 = 140 /*bytes per us*/ / COMPUTE_UNIT_TO_US_RATIO;
+
+
+/// Value used to indicate that a serialized account is not a duplicate
+pub const NON_DUP_MARKER: u8 = u8::MAX;
+
+lazy_static! {
+ pub static ref BUILT_IN_INSTRUCTION_COSTS: HashMap = [
+ (Pubkey::from_str("Stake11111111111111111111111111111111111111").unwrap(), 750u64),
+ (Pubkey::from_str("Config1111111111111111111111111111111111111").unwrap(), 450u64),
+ (Pubkey::from_str("Vote111111111111111111111111111111111111111").unwrap(), 2_100u64),
+ (Pubkey::from_str("11111111111111111111111111111111").unwrap(), 150u64),
+ (Pubkey::from_str("ComputeBudget111111111111111111111111111111").unwrap(), 150u64),
+ (Pubkey::from_str("AddressLookupTab1e1111111111111111111111111").unwrap(), 750u64),
+ (Pubkey::from_str("BPFLoaderUpgradeab1e11111111111111111111111").unwrap(), 2_370u64),
+ (Pubkey::from_str("BPFLoader1111111111111111111111111111111111").unwrap(), 1_140u64),
+ (Pubkey::from_str("BPFLoader2111111111111111111111111111111111").unwrap(), 570u64),
+ (Pubkey::from_str("LoaderV411111111111111111111111111111111111").unwrap(), 2_000u64),
+ // Note: These are precompile, run directly in bank during sanitizing;
+ (Pubkey::from_str("KeccakSecp256k11111111111111111111111111111").unwrap(), 0u64),
+ (Pubkey::from_str("Ed25519SigVerify111111111111111111111111111").unwrap(), 0u64)
+ ]
+ .iter()
+ .cloned()
+ .collect();
+}
+
+#[derive(AbiExample, Debug, Clone, Eq, PartialEq)]
+pub struct FeatureSet {
+ pub active: HashMap,
+ pub inactive: HashSet,
+}
+impl Default for FeatureSet {
+ fn default() -> Self {
+ // All features disabled
+ Self {
+ active: HashMap::new(),
+ inactive: FEATURE_NAMES.keys().cloned().collect(),
+ }
+ }
+}
+impl FeatureSet {
+ pub fn is_active(&self, feature_id: &Pubkey) -> bool {
+ self.active.contains_key(feature_id)
+ }
+
+ pub fn activated_slot(&self, feature_id: &Pubkey) -> Option {
+ self.active.get(feature_id).copied()
+ }
+
+ /// List of enabled features that trigger full inflation
+ pub fn full_inflation_features_enabled(&self) -> HashSet {
+ let mut hash_set = FULL_INFLATION_FEATURE_PAIRS
+ .iter()
+ .filter_map(|pair| {
+ if self.is_active(&pair.vote_id) && self.is_active(&pair.enable_id) {
+ Some(pair.enable_id)
+ } else {
+ None
+ }
+ })
+ .collect::>();
+
+ if self.is_active(&full_inflation::devnet_and_testnet::id()) {
+ hash_set.insert(full_inflation::devnet_and_testnet::id());
+ }
+ hash_set
+ }
+
+ /// All features enabled, useful for testing
+ pub fn all_enabled() -> Self {
+ Self {
+ active: FEATURE_NAMES.keys().cloned().map(|key| (key, 0)).collect(),
+ inactive: HashSet::new(),
+ }
+ }
+
+ /// Activate a feature
+ pub fn activate(&mut self, feature_id: &Pubkey, slot: u64) {
+ self.inactive.remove(feature_id);
+ self.active.insert(*feature_id, slot);
+ }
+
+ /// Deactivate a feature
+ pub fn deactivate(&mut self, feature_id: &Pubkey) {
+ self.active.remove(feature_id);
+ self.inactive.insert(*feature_id);
+ }
+
+ pub fn new_warmup_cooldown_rate_epoch(&self, epoch_schedule: &EpochSchedule) -> Option {
+ self.activated_slot(&reduce_stake_warmup_cooldown::id())
+ .map(|slot| epoch_schedule.get_epoch(slot))
+ }
+}
+
+pub fn get_signature_cost_from_message(tx_cost: &mut UsageCostDetails, message: &SanitizedMessage) {
+ // Get the signature details from the message
+ let signatures_count_detail = message.get_signature_details();
+
+ // Set the details to the tx_cost structure
+ tx_cost.num_transaction_signatures = signatures_count_detail.num_transaction_signatures();
+ tx_cost.num_secp256k1_instruction_signatures = signatures_count_detail.num_secp256k1_instruction_signatures();
+ tx_cost.num_ed25519_instruction_signatures = signatures_count_detail.num_ed25519_instruction_signatures();
+
+ // Calculate the signature cost based on the number of signatures
+ tx_cost.signature_cost = signatures_count_detail
+ .num_transaction_signatures()
+ .saturating_mul(SIGNATURE_COST)
+ .saturating_add(
+ signatures_count_detail
+ .num_secp256k1_instruction_signatures()
+ .saturating_mul(SECP256K1_VERIFY_COST),
+ )
+ .saturating_add(
+ signatures_count_detail
+ .num_ed25519_instruction_signatures()
+ .saturating_mul(ED25519_VERIFY_COST),
+ );
+}
+
+/*
+fn get_writable_accounts(message: &SanitizedMessage) -> Vec {
+ message
+ .account_keys()
+ .iter()
+ .enumerate()
+ .filter_map(|(i, k)| {
+ if message.is_writable(i) {
+ Some(*k)
+ } else {
+ None
+ }
+ })
+ .collect()
+}
+*/
+
+fn get_write_lock_cost(
+ tx_cost: &mut UsageCostDetails,
+ message: &SanitizedMessage,
+ feature_set: &FeatureSet,
+) {
+ tx_cost.writable_accounts = vec![]; //get_writable_accounts(transaction);
+ let num_write_locks =
+ if feature_set.is_active(&feature_set::cost_model_requested_write_lock_cost::id()) {
+ message.num_write_locks()
+ } else {
+ tx_cost.writable_accounts.len() as u64
+ };
+ tx_cost.write_lock_cost = WRITE_LOCK_UNITS.saturating_mul(num_write_locks);
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ComputeBudgetLimits {
+ pub updated_heap_bytes: u32,
+ pub compute_unit_limit: u32,
+ pub compute_unit_price: u64,
+ pub loaded_accounts_bytes: u32,
+}
+
+fn sanitize_requested_heap_size(bytes: u32) -> bool {
+ (u32::try_from(HEAP_LENGTH).unwrap()..=MAX_HEAP_FRAME_BYTES).contains(&bytes)
+ && bytes % 1024 == 0
+}
+pub fn process_compute_budget_instructions<'a>(
+ instructions: impl Iterator- ,
+) -> Result {
+ let mut num_non_compute_budget_instructions: u32 = 0;
+ let mut updated_compute_unit_limit = None;
+ let mut updated_compute_unit_price = None;
+ let mut requested_heap_size = None;
+ let mut updated_loaded_accounts_data_size_limit = None;
+
+ for (i, (program_id, instruction)) in instructions.enumerate() {
+ if compute_budget::check_id(program_id) {
+ let invalid_instruction_data_error = TransactionError::InstructionError(
+ i as u8,
+ InstructionError::InvalidInstructionData,
+ );
+ let duplicate_instruction_error = TransactionError::DuplicateInstruction(i as u8);
+
+ match try_from_slice_unchecked(&instruction.data) {
+ Ok(ComputeBudgetInstruction::RequestHeapFrame(bytes)) => {
+ if requested_heap_size.is_some() {
+ return Err(duplicate_instruction_error);
+ }
+ if sanitize_requested_heap_size(bytes) {
+ requested_heap_size = Some(bytes);
+ } else {
+ return Err(invalid_instruction_data_error);
+ }
+ }
+ Ok(ComputeBudgetInstruction::SetComputeUnitLimit(compute_unit_limit)) => {
+ if updated_compute_unit_limit.is_some() {
+ return Err(duplicate_instruction_error);
+ }
+ updated_compute_unit_limit = Some(compute_unit_limit);
+ }
+ Ok(ComputeBudgetInstruction::SetComputeUnitPrice(micro_lamports)) => {
+ if updated_compute_unit_price.is_some() {
+ return Err(duplicate_instruction_error);
+ }
+ updated_compute_unit_price = Some(micro_lamports);
+ }
+ Ok(ComputeBudgetInstruction::SetLoadedAccountsDataSizeLimit(bytes)) => {
+ if updated_loaded_accounts_data_size_limit.is_some() {
+ return Err(duplicate_instruction_error);
+ }
+ updated_loaded_accounts_data_size_limit = Some(bytes);
+ }
+ _ => return Err(invalid_instruction_data_error),
+ }
+ } else {
+ // only include non-request instructions in default max calc
+ num_non_compute_budget_instructions =
+ num_non_compute_budget_instructions.saturating_add(1);
+ }
+ }
+
+ // sanitize limits
+ let updated_heap_bytes = requested_heap_size
+ .unwrap_or(u32::try_from(HEAP_LENGTH).unwrap()) // loader's default heap_size
+ .min(MAX_HEAP_FRAME_BYTES);
+
+ let compute_unit_limit = updated_compute_unit_limit
+ .unwrap_or_else(|| {
+ num_non_compute_budget_instructions
+ .saturating_mul(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT)
+ })
+ .min(MAX_COMPUTE_UNIT_LIMIT);
+
+ let compute_unit_price = updated_compute_unit_price.unwrap_or(0);
+
+ let loaded_accounts_bytes = updated_loaded_accounts_data_size_limit
+ .unwrap_or(MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES)
+ .min(MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES);
+
+ Ok(ComputeBudgetLimits {
+ updated_heap_bytes,
+ compute_unit_limit,
+ compute_unit_price,
+ loaded_accounts_bytes,
+ })
+}
+
+fn get_compute_unit_price_from_message(
+ tx_cost: &mut UsageCostDetails,
+ message: &SanitizedMessage,
+) {
+ // Iterate through instructions and search for ComputeBudgetInstruction::SetComputeUnitPrice
+ for (program_id, instruction) in message.program_instructions_iter() {
+ if compute_budget::check_id(program_id) {
+ if let Ok(ComputeBudgetInstruction::SetComputeUnitPrice(price)) =
+ try_from_slice_unchecked(&instruction.data)
+ {
+ // Set the compute unit price in tx_cost
+ tx_cost.compute_unit_price = price;
+ }
+ }
+ }
+}
+
+
+fn get_transaction_cost(
+ tx_cost: &mut UsageCostDetails,
+ message: &SanitizedMessage,
+ feature_set: &FeatureSet,
+) {
+ let mut builtin_costs = 0u64;
+ let mut bpf_costs = 0u64;
+ let mut loaded_accounts_data_size_cost = 0u64;
+ let mut data_bytes_len_total = 0u64;
+ let mut compute_unit_limit_is_set = false;
+
+ for (program_id, instruction) in message.program_instructions_iter() {
+ // to keep the same behavior, look for builtin first
+ if let Some(builtin_cost) = BUILT_IN_INSTRUCTION_COSTS.get(program_id) {
+ builtin_costs = builtin_costs.saturating_add(*builtin_cost);
+ } else {
+ bpf_costs = bpf_costs
+ .saturating_add(u64::from(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT))
+ .min(u64::from(MAX_COMPUTE_UNIT_LIMIT));
+ }
+ data_bytes_len_total =
+ data_bytes_len_total.saturating_add(instruction.data.len() as u64);
+
+ if compute_budget::check_id(program_id) {
+ if let Ok(ComputeBudgetInstruction::SetComputeUnitLimit(_)) =
+ try_from_slice_unchecked(&instruction.data)
+ {
+ compute_unit_limit_is_set = true;
+ }
+ }
+ }
+
+ // calculate bpf cost based on compute budget instructions
+
+ // if failed to process compute_budget instructions, the transaction will not be executed
+ // by `bank`, therefore it should be considered as no execution cost by cost model.
+ match process_compute_budget_instructions(message.program_instructions_iter())
+ {
+ Ok(compute_budget_limits) => {
+ // if tx contained user-space instructions and a more accurate estimate available correct it,
+ // where "user-space instructions" must be specifically checked by
+ // 'compute_unit_limit_is_set' flag, because compute_budget does not distinguish
+ // builtin and bpf instructions when calculating default compute-unit-limit. (see
+ // compute_budget.rs test `test_process_mixed_instructions_without_compute_budget`)
+ if bpf_costs > 0 && compute_unit_limit_is_set {
+ bpf_costs = u64::from(compute_budget_limits.compute_unit_limit);
+ }
+
+ if feature_set
+ .is_active(&include_loaded_accounts_data_size_in_fee_calculation::id())
+ {
+ loaded_accounts_data_size_cost = FeeStructure::calculate_memory_usage_cost(
+ usize::try_from(compute_budget_limits.loaded_accounts_bytes).unwrap(),
+ DEFAULT_HEAP_COST,
+ )
+ }
+ }
+ Err(_) => {
+ builtin_costs = 0;
+ bpf_costs = 0;
+ }
+ }
+
+ tx_cost.builtins_execution_cost = builtin_costs;
+ tx_cost.bpf_execution_cost = bpf_costs;
+ tx_cost.loaded_accounts_data_size_cost = loaded_accounts_data_size_cost;
+ tx_cost.data_bytes_cost = data_bytes_len_total / INSTRUCTION_DATA_BYTES_COST;
+}
+
+const MAX_WRITABLE_ACCOUNTS: usize = 256;
+
+// costs are stored in number of 'compute unit's
+#[derive(Debug)]
+pub struct UsageCostDetails {
+ pub writable_accounts: Vec,
+ pub signature_cost: u64,
+ pub write_lock_cost: u64,
+ pub data_bytes_cost: u64,
+ pub builtins_execution_cost: u64,
+ pub bpf_execution_cost: u64,
+ pub loaded_accounts_data_size_cost: u64,
+ pub account_data_size: u64,
+ pub num_transaction_signatures: u64,
+ pub num_secp256k1_instruction_signatures: u64,
+ pub num_ed25519_instruction_signatures: u64,
+ pub compute_unit_price: u64,
+}
+
+impl Default for UsageCostDetails {
+ fn default() -> Self {
+ Self {
+ writable_accounts: Vec::with_capacity(MAX_WRITABLE_ACCOUNTS),
+ signature_cost: 0u64,
+ write_lock_cost: 0u64,
+ data_bytes_cost: 0u64,
+ builtins_execution_cost: 0u64,
+ bpf_execution_cost: 0u64,
+ loaded_accounts_data_size_cost: 0u64,
+ account_data_size: 0u64,
+ num_transaction_signatures: 0u64,
+ num_secp256k1_instruction_signatures: 0u64,
+ num_ed25519_instruction_signatures: 0u64,
+ compute_unit_price: 0u64,
+ }
+ }
+}
+
+#[cfg(test)]
+impl PartialEq for UsageCostDetails {
+ fn eq(&self, other: &Self) -> bool {
+ fn to_hash_set(v: &[Pubkey]) -> std::collections::HashSet<&Pubkey> {
+ v.iter().collect()
+ }
+
+ self.signature_cost == other.signature_cost
+ && self.write_lock_cost == other.write_lock_cost
+ && self.data_bytes_cost == other.data_bytes_cost
+ && self.builtins_execution_cost == other.builtins_execution_cost
+ && self.bpf_execution_cost == other.bpf_execution_cost
+ && self.loaded_accounts_data_size_cost == other.loaded_accounts_data_size_cost
+ && self.account_data_size == other.account_data_size
+ && self.num_transaction_signatures == other.num_transaction_signatures
+ && self.num_secp256k1_instruction_signatures
+ == other.num_secp256k1_instruction_signatures
+ && self.num_ed25519_instruction_signatures == other.num_ed25519_instruction_signatures
+ && to_hash_set(&self.writable_accounts) == to_hash_set(&other.writable_accounts)
+ }
+}
+
/// A fee and its associated compute unit limit
#[derive(Debug, Default, Clone, Eq, PartialEq)]
@@ -39,6 +462,7 @@ impl FeeStructure {
sol_per_write_lock: f64,
compute_fee_bins: Vec<(u64, f64)>,
) -> Self {
+ trace!("Creating FeeStructure with sol_per_signature: {}", sol_per_signature);
let compute_fee_bins = compute_fee_bins
.iter()
.map(|(limit, sol)| FeeBin {
@@ -84,19 +508,38 @@ impl FeeStructure {
budget_limits: &FeeBudgetLimits,
include_loaded_account_data_size_in_fee: bool,
) -> u64 {
- // Fee based on compute units and signatures
- let congestion_multiplier = if lamports_per_signature == 0 {
- 0.0 // test only
- } else {
- 1.0 // multiplier that has no effect
- };
+ trace!("Calculating fee with lamports_per_signature: {} and self.lamports_per_signature {} ", lamports_per_signature, self.lamports_per_signature);
+ trace!("Dump message: {:?}", message);
+ trace!("Dump keys: {:?}", message.account_keys());
+
+ let vote_program_id = &solana_sdk::vote::program::id();
+ let contains_vote_program = message.account_keys().iter().any(|key| key == vote_program_id);
+
+
+ // Query the current Unix time and reduce it to a value between 1 and 100
+ // let current_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards");
+ // let unix_time = current_time.as_secs(); // You can use `as_millis()` if higher precision is needed
+
+ // Use mod 100 and add 1 to ensure the result is between 1 and 100
+ // let congestion_multiplier = (unix_time % 100 + 1) as f64 / 1.0;
+
+ let mut tx_cost = UsageCostDetails::default();
+ get_signature_cost_from_message(&mut tx_cost, &message);
+ get_write_lock_cost(&mut tx_cost, message, &FeatureSet::default());
+ get_transaction_cost(&mut tx_cost, message, &FeatureSet::default());
+ get_compute_unit_price_from_message(&mut tx_cost, &message);
+
+ trace!("UsageCostDetails {:?}", tx_cost);
let signature_fee = message
.num_signatures()
- .saturating_mul(self.lamports_per_signature);
+ .saturating_mul(lamports_per_signature);
+ trace!("Calculated signature_fee: {}", signature_fee);
+
let write_lock_fee = message
.num_write_locks()
.saturating_mul(self.lamports_per_write_lock);
+ trace!("Calculated write_lock_fee: {}", write_lock_fee);
// `compute_fee` covers costs for both requested_compute_units and
// requested_loaded_account_data_size
@@ -108,8 +551,13 @@ impl FeeStructure {
} else {
0_u64
};
+ trace!("Calculated loaded_accounts_data_size_cost: {}", loaded_accounts_data_size_cost);
+
let total_compute_units =
loaded_accounts_data_size_cost.saturating_add(budget_limits.compute_unit_limit);
+
+ trace!("total_compute_units {}", total_compute_units);
+
let compute_fee = self
.compute_fee_bins
.iter()
@@ -121,20 +569,56 @@ impl FeeStructure {
.map(|bin| bin.fee)
.unwrap_or_default()
});
+ trace!("Calculated compute_fee: {}", compute_fee);
- ((budget_limits
+ /*
+ let mut total_fee = ((budget_limits
.prioritization_fee
.saturating_add(signature_fee)
.saturating_add(write_lock_fee)
.saturating_add(compute_fee) as f64)
* congestion_multiplier)
- .round() as u64
+ .round() as u64;
+ */
+
+ let derived_cu = tx_cost.builtins_execution_cost
+ .saturating_add(tx_cost.bpf_execution_cost);
+
+ //let mut total_fee = (derived_cu * 10) // base fee calculation CU * M (10)
+ // .saturating_add (derived_cu * budget_limits.prioritization_fee)
+ // as u64;
+
+
+ let adjusted_compute_unit_price = if derived_cu < 1000 && tx_cost.compute_unit_price < 1_000_000 {
+ 1_000_000
+ } else {
+ tx_cost.compute_unit_price
+ };
+
+ let mut total_fee = derived_cu
+ .saturating_mul(10) // ensures multiplication doesn't overflow
+ .saturating_add(derived_cu.saturating_mul(adjusted_compute_unit_price as u64)
+ .saturating_div(1_000_000)); // change to 1_000_000 to convert to micro lamports
+
+
+ // derived_cu * (10 + budget_limits.prioritization_fee)
+
+ // If the message contains the vote program, set the total fee to 0
+ if contains_vote_program {
+ trace!("Vote program detected, setting total_fee to 0");
+ total_fee = 0;
+ } else {
+ trace!("Calculated total_fee: {} with compute units: {} compute unit price {}", total_fee, derived_cu, tx_cost.compute_unit_price);
+ }
+
+
+ total_fee
}
}
impl Default for FeeStructure {
fn default() -> Self {
- Self::new(0.000005, 0.0, vec![(1_400_000, 0.0)])
+ Self::new(0.000000005, 0.0, vec![(1_400_000, 0.0)])
}
}