Compare commits
88 Commits
v3.2.2-rc.
...
main
Author | SHA1 | Date |
---|---|---|
POA | 6e06824c23 | |
Rim Rakhimov | 43d6da6b52 | |
Rim Rakhimov | 412d797a3b | |
Rim Rakhimov | 63bab44e3c | |
Rim Rakhimov | f703d01f23 | |
POA | f13fa10b8a | |
POA | 657100cebc | |
POA | d2d19ec8c2 | |
POA | 0f872aff78 | |
Rim Rakhimov | 405738c791 | |
Rim Rakhimov | 3b19a79c37 | |
POA | 64a1614769 | |
POA | b981f7beef | |
POA | caa210107e | |
POA | 88eb7d3257 | |
POA | 73895aae88 | |
POA | c5719983b2 | |
POA | f9b2db206a | |
POA | 437ba9b044 | |
uink45 | 98873fc0c0 | |
POA | 415a522429 | |
POA | 646f49fdd0 | |
POA | 25ce4b2ec8 | |
POA | ac30783c82 | |
POA | 5e9b4c58ae | |
POA | 74e709fd55 | |
POA | 3413343caa | |
sunce86 | 8bb02dd479 | |
sunce86 | 79be8f1ab8 | |
sunce86 | a049baf6b2 | |
sunce86 | d8305c52ea | |
Jochen Müller | 239d790df1 | |
Jochen Müller | 298a1a0ecc | |
Jochen Müller | 36b3f125a4 | |
sunce86 | 5d9ff63043 | |
sunce86 | 01996c8867 | |
varasev | 2ae294990a | |
sunce86 | 745c4bd00c | |
sunce86 | ecae5f1c47 | |
Dusan Stanivukovic | 87ae05d99e | |
sunce86 | a92e5e761b | |
Dusan Stanivukovic | 87603926b5 | |
Dusan Stanivukovic | eb42f0c5d9 | |
Dusan Stanivukovic | 33908e8361 | |
Dusan Stanivukovic | aa09846200 | |
Dusan Stanivukovic | 67ab600bc9 | |
Dusan Stanivukovic | 4b437428bd | |
Jochen Müller | 38e40f649c | |
Jochen Müller | 43ee520904 | |
sunce86 | fdaee51ca0 | |
Dusan Stanivukovic | eec38b30e3 | |
Dusan Stanivukovic | 287409f9f5 | |
Dusan Stanivukovic | e5ae846de4 | |
Dusan Stanivukovic | e6f3794dd4 | |
sunce86 | 5920f232d0 | |
sunce86 | 3bce814090 | |
sunce86 | 118051696e | |
Dusan Stanivukovic | 17057eeedc | |
Dusan Stanivukovic | 7aa1e987de | |
Jochen Müller | 193b25a22d | |
Jochen Müller | 99a8ddae41 | |
Dusan Stanivukovic | 93b39df02d | |
Dusan Stanivukovic | 5dec58ba9f | |
Dusan Stanivukovic | b928380b64 | |
Dusan Stanivukovic | 5e7086d54c | |
Jochen Müller | 144b2293a2 | |
Jochen Müller | f14d3e5a5c | |
Jochen Müller | f9f492638c | |
varasev | fe198ddf7d | |
Jochen Müller | 32d8b5487a | |
rakita | 6835ec53ad | |
Jochen Müller | 09ab40b956 | |
Jochen Müller | 2df74c26dd | |
varasev | ed12fffeef | |
Jochen Müller | c03cc15468 | |
rakita | 3b3ecf6676 | |
rakita | be9b16ab67 | |
varasev | 392a909cb7 | |
Jochen Müller | 6f5a00a642 | |
Jochen Müller | 2453f1a803 | |
rakita | 09967329af | |
rakita | 459a1a02a4 | |
Wei Tang | a716eb3871 | |
Wei Tang | 0fd7c59724 | |
rakita | aa41520dd1 | |
Wei Tang | 4bffab6715 | |
Wei Tang | 5709dbc3e0 | |
Wei Tang | 6ce6666cbb |
|
@ -13,7 +13,7 @@ jobs:
|
|||
platform:
|
||||
- windows2019 # custom runner
|
||||
toolchain:
|
||||
- stable
|
||||
- 1.52.1
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
|
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
- ubuntu-16.04
|
||||
- macos-latest
|
||||
toolchain:
|
||||
- stable
|
||||
- 1.52.1
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
|
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
- ubuntu-16.04
|
||||
- macos-latest
|
||||
toolchain:
|
||||
- stable
|
||||
- 1.52.1
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
|
|
|
@ -15,10 +15,10 @@ jobs:
|
|||
uses: actions/checkout@main
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install stable toolchain
|
||||
- name: Install 1.52.1 toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: 1.52.1
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Run cargo check 1/3
|
||||
|
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
- name: Install toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: 1.52.1
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Deploy to docker hub
|
||||
|
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Install toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: 1.52.1
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Deploy to docker hub
|
||||
|
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Install toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: 1.52.1
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Deploy to docker hub
|
||||
|
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
toolchain: 1.52.1
|
||||
override: true
|
||||
- run: rustup component add rustfmt
|
||||
- uses: actions-rs/cargo@v1
|
||||
|
|
165
CHANGELOG.md
165
CHANGELOG.md
|
@ -1,3 +1,165 @@
|
|||
## OpenEthereum v3.3.3
|
||||
|
||||
Enhancements:
|
||||
* Implement eip-3607 (#593)
|
||||
|
||||
Bug fixes:
|
||||
* Add type field for legacy transactions in RPC calls (#580)
|
||||
* Makes eth_mining to return False if not is not allowed to seal (#581)
|
||||
* Made nodes data concatenate as RLP sequences instead of bytes (#598)
|
||||
|
||||
## OpenEthereum v3.3.2
|
||||
|
||||
Enhancements:
|
||||
* London hardfork block: Sokol (24114400)
|
||||
|
||||
Bug fixes:
|
||||
* Fix for maxPriorityFeePerGas overflow
|
||||
|
||||
## OpenEthereum v3.3.1
|
||||
|
||||
Enhancements:
|
||||
* Add eth_maxPriorityFeePerGas implementation (#570)
|
||||
* Add a bootnode for Kovan
|
||||
|
||||
Bug fixes:
|
||||
* Fix for modexp overflow in debug mode (#578)
|
||||
|
||||
## OpenEthereum v3.3.0
|
||||
|
||||
Enhancements:
|
||||
* Add `validateServiceTransactionsTransition` spec option to be able to enable additional checking of zero gas price transactions by block verifier
|
||||
|
||||
## OpenEthereum v3.3.0-rc.15
|
||||
|
||||
* Revert eip1559BaseFeeMinValue activation on xDai at London hardfork block
|
||||
|
||||
## OpenEthereum v3.3.0-rc.14
|
||||
|
||||
Enhancements:
|
||||
* Add eip1559BaseFeeMinValue and eip1559BaseFeeMinValueTransition spec options
|
||||
* Activate eip1559BaseFeeMinValue on xDai at London hardfork block (19040000), set it to 20 GWei
|
||||
* Activate eip1559BaseFeeMinValue on POA Core at block 24199500 (November 8, 2021), set it to 10 GWei
|
||||
* Delay difficulty bomb to June 2022 for Ethereum Mainnet (EIP-4345)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.13
|
||||
|
||||
Enhancements:
|
||||
* London hardfork block: POA Core (24090200)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.12
|
||||
|
||||
Enhancements:
|
||||
* London hardfork block: xDai (19040000)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.11
|
||||
|
||||
Bug fixes:
|
||||
* Ignore GetNodeData requests only for non-AuRa chains
|
||||
|
||||
## OpenEthereum v3.3.0-rc.10
|
||||
|
||||
Enhancements:
|
||||
* Add eip1559FeeCollector and eip1559FeeCollectorTransition spec options
|
||||
|
||||
## OpenEthereum v3.3.0-rc.9
|
||||
|
||||
Bug fixes:
|
||||
* Add service transactions support for EIP-1559
|
||||
* Fix MinGasPrice config option for POSDAO and EIP-1559
|
||||
|
||||
Enhancements:
|
||||
* min_gas_price becomes min_effective_priority_fee
|
||||
* added version 4 for TxPermission contract
|
||||
|
||||
## OpenEthereum v3.3.0-rc.8
|
||||
|
||||
Bug fixes:
|
||||
* Ignore GetNodeData requests (#519)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.7
|
||||
|
||||
Bug fixes:
|
||||
* GetPooledTransactions is sent in invalid form (wrong packet id)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.6
|
||||
|
||||
Enhancements:
|
||||
* London hardfork block: kovan (26741100) (#502)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.4
|
||||
|
||||
Enhancements:
|
||||
* London hardfork block: mainnet (12,965,000) (#475)
|
||||
* Support for eth/66 protocol version (#465)
|
||||
* Bump ethereum/tests to v9.0.3
|
||||
* Add eth_feeHistory
|
||||
|
||||
Bug fixes:
|
||||
* GetNodeData from eth63 is missing (#466)
|
||||
* Effective gas price not omitting (#477)
|
||||
* London support in openethereum-evm (#479)
|
||||
* gasPrice is required field for Transaction object (#481)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.3
|
||||
|
||||
Bug fixes:
|
||||
* Add effective_gas_price to eth_getTransactionReceipt #445 (#450)
|
||||
* Update eth_gasPrice to support EIP-1559 #449 (#458)
|
||||
* eth_estimateGas returns "Requires higher than upper limit of X" after London Ropsten Hard Fork #459 (#460)
|
||||
|
||||
## OpenEthereum v3.3.0-rc.2
|
||||
|
||||
Enhancements:
|
||||
* EIP-1559: Fee market change for ETH 1.0 chain
|
||||
* EIP-3198: BASEFEE opcode
|
||||
* EIP-3529: Reduction in gas refunds
|
||||
* EIP-3541: Reject new contracts starting with the 0xEF byte
|
||||
* Delay difficulty bomb to December 2021 (EIP-3554)
|
||||
* London hardfork blocks: goerli (5,062,605), rinkeby (8,897,988), ropsten (10,499,401)
|
||||
* Add chainspecs for aleut and baikal
|
||||
* Bump ethereum/tests to v9.0.2
|
||||
|
||||
## OpenEthereum v3.2.6
|
||||
|
||||
Enhancement:
|
||||
* Berlin hardfork blocks: poacore (21,364,900), poasokol (21,050,600)
|
||||
|
||||
## OpenEthereum v3.2.5
|
||||
|
||||
Bug fixes:
|
||||
* Backport: Block sync stopped without any errors. #277 (#286)
|
||||
* Strict memory order (#306)
|
||||
|
||||
Enhancements:
|
||||
* Executable queue for ancient blocks inclusion (#208)
|
||||
* Backport AuRa commits for xdai (#330)
|
||||
* Add Nethermind to clients that accept service transactions (#324)
|
||||
* Implement the filter argument in parity_pendingTransactions (#295)
|
||||
* Ethereum-types and various libs upgraded (#315)
|
||||
* [evmbin] Omit storage output, now for std-json (#311)
|
||||
* Freeze pruning while creating snapshot (#205)
|
||||
* AuRa multi block reward (#290)
|
||||
* Improved metrics. DB read/write. prometheus prefix config (#240)
|
||||
* Send RLPx auth in EIP-8 format (#287)
|
||||
* rpc module reverted for RPC JSON api (#284)
|
||||
* Revert "Remove eth/63 protocol version (#252)"
|
||||
* Support for eth/65 protocol version (#366)
|
||||
* Berlin hardfork blocks: kovan (24,770,900), xdai (16,101,500)
|
||||
* Bump ethereum/tests to v8.0.3
|
||||
|
||||
devops:
|
||||
* Upgrade docker alpine to `v1.13.2`. for rust `v1.47`.
|
||||
* Send SIGTERM instead of SIGHUP to OE daemon (#317)
|
||||
|
||||
## OpenEthereum v3.2.4
|
||||
|
||||
* Fix for Typed transaction broadcast.
|
||||
|
||||
## OpenEthereum v3.2.3
|
||||
|
||||
* Hotfix for berlin consensus error.
|
||||
|
||||
## OpenEthereum v3.2.2-rc.1
|
||||
|
||||
Bug fixes:
|
||||
|
@ -27,6 +189,7 @@ devops:
|
|||
|
||||
Hot fix issue, related to initial sync:
|
||||
* Initial sync gets stuck. (#318)
|
||||
|
||||
## OpenEthereum v3.2.0
|
||||
|
||||
Bug fixes:
|
||||
|
@ -42,4 +205,4 @@ Enhancements:
|
|||
* Snapshot manifest block added to prometheus (#232)
|
||||
* EIP-1898: Allow default block parameter to be blockHash
|
||||
* Change ProtocolId to U64
|
||||
* Update ethereum/tests
|
||||
* Update ethereum/tests
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
|||
description = "OpenEthereum"
|
||||
name = "openethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "3.2.2-rc.1"
|
||||
version = "3.3.3"
|
||||
license = "GPL-3.0"
|
||||
authors = [
|
||||
"OpenEthereum developers",
|
||||
|
@ -22,7 +22,7 @@ number_prefix = "0.2"
|
|||
rpassword = "1.0"
|
||||
semver = "0.9"
|
||||
ansi_term = "0.10"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
regex = "1.0"
|
||||
atty = "0.2.8"
|
||||
toml = "0.4"
|
||||
|
|
|
@ -11,7 +11,7 @@ num_cpus = "1.6"
|
|||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
ethstore = { path = "../../crates/accounts/ethstore" }
|
||||
dir = { path = '../../crates/util/dir' }
|
||||
panic_hook = { path = "../../crates/util/panic-hook" }
|
||||
|
|
|
@ -46,6 +46,8 @@ use bytes::Bytes;
|
|||
use docopt::Docopt;
|
||||
use ethcore::{json_tests, spec, TrieSpec};
|
||||
use ethereum_types::{Address, U256};
|
||||
use ethjson::spec::ForkSpec;
|
||||
use evm::EnvInfo;
|
||||
use rustc_hex::FromHex;
|
||||
use std::{fmt, fs, path::PathBuf, sync::Arc};
|
||||
use vm::{ActionParams, CallType};
|
||||
|
@ -192,10 +194,18 @@ fn run_state_test(args: Args) {
|
|||
}
|
||||
|
||||
let multitransaction = test.transaction;
|
||||
let env_info = test.env.into();
|
||||
let env_info: EnvInfo = test.env.into();
|
||||
let pre = test.pre_state.into();
|
||||
|
||||
for (spec, states) in test.post_states {
|
||||
//hardcode base fee for part of the london tests, that miss base fee field in env
|
||||
let mut test_env = env_info.clone();
|
||||
if spec >= ForkSpec::London {
|
||||
if test_env.base_fee.is_none() {
|
||||
test_env.base_fee = Some(0x0a.into());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(false) = only_chain
|
||||
.as_ref()
|
||||
.map(|only_chain| &format!("{:?}", spec).to_lowercase() == only_chain)
|
||||
|
@ -218,7 +228,7 @@ fn run_state_test(args: Args) {
|
|||
&spec,
|
||||
&pre,
|
||||
post_root,
|
||||
&env_info,
|
||||
&test_env,
|
||||
transaction,
|
||||
display::json::Informant::new(config),
|
||||
trie_spec,
|
||||
|
@ -231,7 +241,7 @@ fn run_state_test(args: Args) {
|
|||
&spec,
|
||||
&pre,
|
||||
post_root,
|
||||
&env_info,
|
||||
&test_env,
|
||||
transaction,
|
||||
display::std_json::Informant::err_only(config),
|
||||
trie_spec,
|
||||
|
@ -243,7 +253,7 @@ fn run_state_test(args: Args) {
|
|||
&spec,
|
||||
&pre,
|
||||
post_root,
|
||||
&env_info,
|
||||
&test_env,
|
||||
transaction,
|
||||
display::std_json::Informant::out_only(config),
|
||||
trie_spec,
|
||||
|
@ -255,7 +265,7 @@ fn run_state_test(args: Args) {
|
|||
&spec,
|
||||
&pre,
|
||||
post_root,
|
||||
&env_info,
|
||||
&test_env,
|
||||
transaction,
|
||||
display::std_json::Informant::new_default(config),
|
||||
trie_spec,
|
||||
|
@ -268,7 +278,7 @@ fn run_state_test(args: Args) {
|
|||
&spec,
|
||||
&pre,
|
||||
post_root,
|
||||
&env_info,
|
||||
&test_env,
|
||||
transaction,
|
||||
display::simple::Informant::new(config),
|
||||
trie_spec,
|
||||
|
|
|
@ -680,7 +680,7 @@ usage! {
|
|||
|
||||
ARG arg_min_gas_price: (Option<u64>) = None, or |c: &Config| c.mining.as_ref()?.min_gas_price.clone(),
|
||||
"--min-gas-price=[STRING]",
|
||||
"Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.",
|
||||
"Minimum amount of Wei per GAS to be paid for a transaction on top of base fee, to be accepted for mining. Overrides --usd-per-tx.",
|
||||
|
||||
ARG arg_gas_price_percentile: (usize) = 50usize, or |c: &Config| c.mining.as_ref()?.gas_price_percentile,
|
||||
"--gas-price-percentile=[PCT]",
|
||||
|
|
|
@ -640,14 +640,16 @@ impl Configuration {
|
|||
|
||||
fn pool_verification_options(&self) -> Result<pool::verifier::Options, String> {
|
||||
Ok(pool::verifier::Options {
|
||||
// NOTE min_gas_price and block_gas_limit will be overwritten right after start.
|
||||
// NOTE min_gas_price,block_gas_limit block_base_fee, and allow_non_eoa_sender will be overwritten right after start.
|
||||
minimal_gas_price: U256::from(20_000_000) * 1_000u32,
|
||||
block_gas_limit: U256::max_value(),
|
||||
block_base_fee: None,
|
||||
tx_gas_limit: match self.args.arg_tx_gas_limit {
|
||||
Some(ref d) => to_u256(d)?,
|
||||
None => U256::max_value(),
|
||||
},
|
||||
no_early_reject: self.args.flag_tx_queue_no_early_reject,
|
||||
allow_non_eoa_sender: false,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,6 @@ atty = "0.2"
|
|||
lazy_static = "1.0"
|
||||
regex = "1.0"
|
||||
time = "0.1"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
arrayvec = "0.4"
|
||||
ansi_term = "0.10"
|
||||
|
|
|
@ -254,6 +254,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<RunningClient
|
|||
_ => sync::WarpSync::Disabled,
|
||||
};
|
||||
sync_config.download_old_blocks = cmd.download_old_blocks;
|
||||
sync_config.eip1559_transition = spec.params().eip1559_transition;
|
||||
|
||||
let passwords = passwords_from_files(&cmd.acc_conf.password_files)?;
|
||||
|
||||
|
@ -365,8 +366,18 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<RunningClient
|
|||
|
||||
// take handle to client
|
||||
let client = service.client();
|
||||
// Update miners block gas limit
|
||||
miner.update_transaction_queue_limits(*client.best_block_header().gas_limit());
|
||||
// Update miners block gas limit and base_fee
|
||||
let base_fee = client
|
||||
.engine()
|
||||
.calculate_base_fee(&client.best_block_header());
|
||||
let allow_non_eoa_sender = client
|
||||
.engine()
|
||||
.allow_non_eoa_sender(client.best_block_header().number() + 1);
|
||||
miner.update_transaction_queue_limits(
|
||||
*client.best_block_header().gas_limit(),
|
||||
base_fee,
|
||||
allow_non_eoa_sender,
|
||||
);
|
||||
|
||||
let connection_filter = connection_filter_address.map(|a| {
|
||||
Arc::new(NodeFilter::new(
|
||||
|
|
|
@ -13,7 +13,7 @@ ethkey = { path = "ethkey" }
|
|||
ethstore = { path = "ethstore" }
|
||||
log = "0.4"
|
||||
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
|
|
@ -15,7 +15,7 @@ serde_derive = "1.0"
|
|||
rustc-hex = "1.0"
|
||||
time = "0.1.34"
|
||||
itertools = "0.5"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
parity-crypto = { version = "0.6.2", features = [ "publickey"] }
|
||||
ethereum-types = "0.9.2"
|
||||
smallvec = "0.6"
|
||||
|
|
|
@ -12,7 +12,7 @@ keccak-hash = "0.5.0"
|
|||
tiny-keccak = "2.0.2"
|
||||
log = "0.4"
|
||||
memmap = "0.6"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
primal = "0.2.3"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -29,14 +29,14 @@ log = "0.4"
|
|||
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
|
||||
parity-runtime = { path = "../../runtime/runtime" }
|
||||
parity-util-mem = "0.7"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
price-info = { path = "./price-info", optional = true }
|
||||
rlp = { version = "0.4.6" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
trace-time = "0.1"
|
||||
transaction-pool = "2.0.1"
|
||||
txpool = { path = "../../transaction-pool" }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.5"
|
||||
|
|
|
@ -14,5 +14,5 @@ log = "0.4"
|
|||
serde_json = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
fake-fetch = { path = "../../../net/fake-fetch" }
|
||||
|
|
|
@ -35,7 +35,7 @@ extern crate parking_lot;
|
|||
#[cfg(feature = "price-info")]
|
||||
extern crate price_info;
|
||||
extern crate rlp;
|
||||
extern crate transaction_pool as txpool;
|
||||
extern crate txpool;
|
||||
|
||||
#[macro_use]
|
||||
extern crate ethabi_contract;
|
||||
|
|
|
@ -32,6 +32,8 @@ pub struct AccountDetails {
|
|||
pub nonce: U256,
|
||||
/// Current account balance
|
||||
pub balance: U256,
|
||||
/// Code hash associated with an account if any
|
||||
pub code_hash: Option<H256>,
|
||||
/// Is this account a local account?
|
||||
pub is_local: bool,
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ pub struct PendingSettings {
|
|||
pub max_len: usize,
|
||||
/// Ordering of transactions.
|
||||
pub ordering: PendingOrdering,
|
||||
/// Value of score that is a boundary between includable and non-includable transactions
|
||||
/// Before EIP1559 it should be equal to zero, after EIP1559 it should be equal to block_base_fee
|
||||
pub includable_boundary: U256,
|
||||
}
|
||||
|
||||
impl PendingSettings {
|
||||
|
@ -82,6 +85,7 @@ impl PendingSettings {
|
|||
nonce_cap: None,
|
||||
max_len: usize::max_value(),
|
||||
ordering: PendingOrdering::Priority,
|
||||
includable_boundary: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +122,7 @@ pub trait ScoredTransaction {
|
|||
fn priority(&self) -> Priority;
|
||||
|
||||
/// Gets transaction gas price.
|
||||
fn gas_price(&self) -> &U256;
|
||||
fn effective_gas_price(&self, block_base_fee: Option<U256>) -> U256;
|
||||
|
||||
/// Gets transaction nonce.
|
||||
fn nonce(&self) -> U256;
|
||||
|
@ -184,6 +188,10 @@ impl txpool::VerifiedTransaction for VerifiedTransaction {
|
|||
fn sender(&self) -> &Address {
|
||||
&self.sender
|
||||
}
|
||||
|
||||
fn has_zero_gas_price(&self) -> bool {
|
||||
self.transaction.has_zero_gas_price()
|
||||
}
|
||||
}
|
||||
|
||||
impl ScoredTransaction for VerifiedTransaction {
|
||||
|
@ -191,9 +199,8 @@ impl ScoredTransaction for VerifiedTransaction {
|
|||
self.priority
|
||||
}
|
||||
|
||||
/// Gets transaction gas price.
|
||||
fn gas_price(&self) -> &U256 {
|
||||
&self.transaction.tx().gas_price
|
||||
fn effective_gas_price(&self, block_base_fee: Option<U256>) -> U256 {
|
||||
self.transaction.effective_gas_price(block_base_fee)
|
||||
}
|
||||
|
||||
/// Gets transaction nonce.
|
||||
|
|
|
@ -26,6 +26,7 @@ use std::{
|
|||
},
|
||||
};
|
||||
|
||||
use self::scoring::ScoringEvent;
|
||||
use ethereum_types::{Address, H256, U256};
|
||||
use parking_lot::RwLock;
|
||||
use txpool::{self, Verifier};
|
||||
|
@ -245,7 +246,10 @@ impl TransactionQueue {
|
|||
insertion_id: Default::default(),
|
||||
pool: RwLock::new(txpool::Pool::new(
|
||||
Default::default(),
|
||||
scoring::NonceAndGasPrice(strategy),
|
||||
scoring::NonceAndGasPrice {
|
||||
strategy,
|
||||
block_base_fee: verification_options.block_base_fee,
|
||||
},
|
||||
limits,
|
||||
)),
|
||||
options: RwLock::new(verification_options),
|
||||
|
@ -257,6 +261,26 @@ impl TransactionQueue {
|
|||
}
|
||||
}
|
||||
|
||||
/// If latest block has different base fee than it's parent, then transaction pool scoring needs to be updated.
|
||||
pub fn update_scoring(&self, block_base_fee: U256) {
|
||||
let update_needed = match self.pool.read().scoring().block_base_fee {
|
||||
Some(base_fee) => base_fee != block_base_fee,
|
||||
None => true,
|
||||
};
|
||||
|
||||
if update_needed {
|
||||
self.pool.write().set_scoring(
|
||||
scoring::NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: Some(block_base_fee),
|
||||
},
|
||||
ScoringEvent::BlockBaseFeeChanged,
|
||||
);
|
||||
|
||||
self.cached_pending.write().clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Update verification options
|
||||
///
|
||||
/// Some parameters of verification may vary in time (like block gas limit or minimal gas price).
|
||||
|
@ -307,8 +331,11 @@ impl TransactionQueue {
|
|||
transaction_to_replace,
|
||||
);
|
||||
|
||||
let mut replace =
|
||||
replace::ReplaceByScoreAndReadiness::new(self.pool.read().scoring().clone(), client);
|
||||
let mut replace = replace::ReplaceByScoreAndReadiness::new(
|
||||
self.pool.read().scoring().clone(),
|
||||
client,
|
||||
self.options.read().block_base_fee,
|
||||
);
|
||||
|
||||
let results = transactions
|
||||
.into_iter()
|
||||
|
@ -353,7 +380,10 @@ impl TransactionQueue {
|
|||
/// Returns all transactions in the queue without explicit ordering.
|
||||
pub fn all_transactions(&self) -> Vec<Arc<pool::VerifiedTransaction>> {
|
||||
let ready = |_tx: &pool::VerifiedTransaction| txpool::Readiness::Ready;
|
||||
self.pool.read().unordered_pending(ready).collect()
|
||||
self.pool
|
||||
.read()
|
||||
.unordered_pending(ready, Default::default())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns all transaction hashes in the queue without explicit ordering.
|
||||
|
@ -361,7 +391,7 @@ impl TransactionQueue {
|
|||
let ready = |_tx: &pool::VerifiedTransaction| txpool::Readiness::Ready;
|
||||
self.pool
|
||||
.read()
|
||||
.unordered_pending(ready)
|
||||
.unordered_pending(ready, Default::default())
|
||||
.map(|tx| tx.hash)
|
||||
.collect()
|
||||
}
|
||||
|
@ -376,7 +406,7 @@ impl TransactionQueue {
|
|||
let ready = ready::OptionalState::new(nonce);
|
||||
self.pool
|
||||
.read()
|
||||
.unordered_pending(ready)
|
||||
.unordered_pending(ready, Default::default())
|
||||
.map(|tx| tx.hash)
|
||||
.collect()
|
||||
}
|
||||
|
@ -400,6 +430,7 @@ impl TransactionQueue {
|
|||
nonce_cap,
|
||||
max_len,
|
||||
ordering,
|
||||
includable_boundary,
|
||||
} = settings;
|
||||
if let Some(pending) = self.cached_pending.read().pending(
|
||||
block_number,
|
||||
|
@ -425,15 +456,19 @@ impl TransactionQueue {
|
|||
return self
|
||||
.pool
|
||||
.read()
|
||||
.unordered_pending(ready)
|
||||
.unordered_pending(ready, includable_boundary)
|
||||
.take(max_len)
|
||||
.collect();
|
||||
}
|
||||
|
||||
let pending: Vec<_> =
|
||||
self.collect_pending(client, block_number, current_timestamp, nonce_cap, |i| {
|
||||
i.take(max_len).collect()
|
||||
});
|
||||
let pending: Vec<_> = self.collect_pending(
|
||||
client,
|
||||
includable_boundary,
|
||||
block_number,
|
||||
current_timestamp,
|
||||
nonce_cap,
|
||||
|i| i.take(max_len).collect(),
|
||||
);
|
||||
|
||||
*cached_pending = CachedPending {
|
||||
block_number,
|
||||
|
@ -461,6 +496,7 @@ impl TransactionQueue {
|
|||
{
|
||||
self.collect_pending(
|
||||
client,
|
||||
settings.includable_boundary,
|
||||
settings.block_number,
|
||||
settings.current_timestamp,
|
||||
settings.nonce_cap,
|
||||
|
@ -479,6 +515,7 @@ impl TransactionQueue {
|
|||
pub fn collect_pending<C, F, T>(
|
||||
&self,
|
||||
client: C,
|
||||
includable_boundary: U256,
|
||||
block_number: u64,
|
||||
current_timestamp: u64,
|
||||
nonce_cap: Option<U256>,
|
||||
|
@ -498,7 +535,7 @@ impl TransactionQueue {
|
|||
debug!(target: "txqueue", "Re-computing pending set for block: {}", block_number);
|
||||
trace_time!("pool::collect_pending");
|
||||
let ready = Self::ready(client, block_number, current_timestamp, nonce_cap);
|
||||
collect(self.pool.read().pending(ready))
|
||||
collect(self.pool.read().pending(ready, includable_boundary))
|
||||
}
|
||||
|
||||
fn ready<C>(
|
||||
|
@ -563,7 +600,7 @@ impl TransactionQueue {
|
|||
|
||||
self.pool
|
||||
.read()
|
||||
.pending_from_sender(state_readiness, address)
|
||||
.pending_from_sender(state_readiness, address, Default::default())
|
||||
.last()
|
||||
.map(|tx| tx.signed().tx().nonce.saturating_add(U256::from(1)))
|
||||
}
|
||||
|
@ -612,18 +649,37 @@ impl TransactionQueue {
|
|||
pub fn penalize<'a, T: IntoIterator<Item = &'a Address>>(&self, senders: T) {
|
||||
let mut pool = self.pool.write();
|
||||
for sender in senders {
|
||||
pool.update_scores(sender, ());
|
||||
pool.update_scores(sender, ScoringEvent::Penalize);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns gas price of currently the worst transaction in the pool.
|
||||
pub fn current_worst_gas_price(&self) -> U256 {
|
||||
match self.pool.read().worst_transaction() {
|
||||
Some(tx) => tx.signed().tx().gas_price,
|
||||
None => self.options.read().minimal_gas_price,
|
||||
Some(tx) => tx
|
||||
.signed()
|
||||
.effective_gas_price(self.options.read().block_base_fee),
|
||||
None => {
|
||||
self.options.read().minimal_gas_price
|
||||
+ self.options.read().block_base_fee.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns effective priority fee gas price of currently the worst transaction in the pool.
|
||||
/// If the worst transaction has zero gas price, the minimal gas price is returned.
|
||||
pub fn current_worst_effective_priority_fee(&self) -> U256 {
|
||||
self.pool
|
||||
.read()
|
||||
.worst_transaction()
|
||||
.filter(|tx| !tx.signed().has_zero_gas_price())
|
||||
.map(|tx| {
|
||||
tx.signed()
|
||||
.effective_priority_fee(self.options.read().block_base_fee)
|
||||
})
|
||||
.unwrap_or(self.options.read().minimal_gas_price)
|
||||
}
|
||||
|
||||
/// Returns a status of the queue.
|
||||
pub fn status(&self) -> Status {
|
||||
let pool = self.pool.read();
|
||||
|
|
|
@ -39,12 +39,18 @@ use txpool::{
|
|||
pub struct ReplaceByScoreAndReadiness<S, C> {
|
||||
scoring: S,
|
||||
client: C,
|
||||
/// Block base fee of the latest block, exists if the EIP 1559 is activated
|
||||
block_base_fee: Option<U256>,
|
||||
}
|
||||
|
||||
impl<S, C> ReplaceByScoreAndReadiness<S, C> {
|
||||
/// Create a new `ReplaceByScoreAndReadiness`
|
||||
pub fn new(scoring: S, client: C) -> Self {
|
||||
ReplaceByScoreAndReadiness { scoring, client }
|
||||
pub fn new(scoring: S, client: C, block_base_fee: Option<U256>) -> Self {
|
||||
ReplaceByScoreAndReadiness {
|
||||
scoring,
|
||||
client,
|
||||
block_base_fee,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,8 +73,9 @@ where
|
|||
} else if both_local {
|
||||
Choice::InsertNew
|
||||
} else {
|
||||
let old_score = (old.priority(), old.gas_price());
|
||||
let new_score = (new.priority(), new.gas_price());
|
||||
let old_score = (old.priority(), old.effective_gas_price(self.block_base_fee));
|
||||
let new_score = (new.priority(), new.effective_gas_price(self.block_base_fee));
|
||||
|
||||
if new_score > old_score {
|
||||
// Check if this is a replacement transaction.
|
||||
//
|
||||
|
@ -155,9 +162,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn should_always_accept_local_transactions_unless_same_sender_and_nonce() {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
// same sender txs
|
||||
let keypair = Random.generate();
|
||||
|
@ -249,9 +259,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn should_replace_same_sender_by_nonce() {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
let tx1 = Tx {
|
||||
nonce: 1,
|
||||
|
@ -311,9 +324,12 @@ mod tests {
|
|||
#[test]
|
||||
fn should_replace_different_sender_by_priority_and_gas_price() {
|
||||
// given
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(0);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
let tx_regular_low_gas = {
|
||||
let tx = Tx {
|
||||
|
@ -406,9 +422,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn should_not_replace_ready_transaction_with_future_transaction() {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
let tx_ready_low_score = {
|
||||
let tx = Tx {
|
||||
|
@ -436,9 +455,12 @@ mod tests {
|
|||
#[test]
|
||||
fn should_compute_readiness_with_pooled_transactions_from_the_same_sender_as_the_existing_transaction(
|
||||
) {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
let old_sender = Random.generate();
|
||||
let tx_old_ready_1 = {
|
||||
|
@ -504,9 +526,12 @@ mod tests {
|
|||
#[test]
|
||||
fn should_compute_readiness_with_pooled_transactions_from_the_same_sender_as_the_new_transaction(
|
||||
) {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
// current transaction is ready but has a lower gas price than the new one
|
||||
let old_tx = {
|
||||
|
@ -572,9 +597,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn should_accept_local_tx_with_same_sender_and_nonce_with_better_gas_price() {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
// current transaction is ready
|
||||
let old_tx = {
|
||||
|
@ -627,9 +655,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn should_reject_local_tx_with_same_sender_and_nonce_with_worse_gas_price() {
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let client = TestClient::new().with_nonce(1);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
|
||||
let replace = ReplaceByScoreAndReadiness::new(scoring, client, None);
|
||||
|
||||
// current transaction is ready
|
||||
let old_tx = {
|
||||
|
|
|
@ -42,13 +42,25 @@ const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
|
|||
fn bump_gas_price(old_gp: U256) -> U256 {
|
||||
old_gp.saturating_add(old_gp >> GAS_PRICE_BUMP_SHIFT)
|
||||
}
|
||||
|
||||
/// List of events that trigger updating of scores
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum ScoringEvent {
|
||||
/// Penalize transactions
|
||||
Penalize,
|
||||
/// Every time new block is added to blockchain, block base fee is changed and triggers score change.
|
||||
BlockBaseFeeChanged,
|
||||
}
|
||||
/// Simple, gas-price based scoring for transactions.
|
||||
///
|
||||
/// NOTE: Currently penalization does not apply to new transactions that enter the pool.
|
||||
/// We might want to store penalization status in some persistent state.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NonceAndGasPrice(pub PrioritizationStrategy);
|
||||
pub struct NonceAndGasPrice {
|
||||
/// Strategy for prioritization
|
||||
pub strategy: PrioritizationStrategy,
|
||||
/// Block base fee. Exists if the EIP 1559 is activated.
|
||||
pub block_base_fee: Option<U256>,
|
||||
}
|
||||
|
||||
impl NonceAndGasPrice {
|
||||
/// Decide if the transaction should even be considered into the pool (if the pool is full).
|
||||
|
@ -67,7 +79,7 @@ impl NonceAndGasPrice {
|
|||
return true;
|
||||
}
|
||||
|
||||
&old.transaction.tx().gas_price > new.gas_price()
|
||||
old.effective_gas_price(self.block_base_fee) > new.effective_gas_price(self.block_base_fee)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +88,7 @@ where
|
|||
P: ScoredTransaction + txpool::VerifiedTransaction,
|
||||
{
|
||||
type Score = U256;
|
||||
type Event = ();
|
||||
type Event = ScoringEvent;
|
||||
|
||||
fn compare(&self, old: &P, other: &P) -> cmp::Ordering {
|
||||
old.nonce().cmp(&other.nonce())
|
||||
|
@ -87,10 +99,10 @@ where
|
|||
return scoring::Choice::InsertNew;
|
||||
}
|
||||
|
||||
let old_gp = old.gas_price();
|
||||
let new_gp = new.gas_price();
|
||||
let old_gp = old.effective_gas_price(self.block_base_fee);
|
||||
let new_gp = new.effective_gas_price(self.block_base_fee);
|
||||
|
||||
let min_required_gp = bump_gas_price(*old_gp);
|
||||
let min_required_gp = bump_gas_price(old_gp);
|
||||
|
||||
match min_required_gp.cmp(&new_gp) {
|
||||
cmp::Ordering::Greater => scoring::Choice::RejectNew,
|
||||
|
@ -102,7 +114,7 @@ where
|
|||
&self,
|
||||
txs: &[txpool::Transaction<P>],
|
||||
scores: &mut [U256],
|
||||
change: scoring::Change,
|
||||
change: scoring::Change<ScoringEvent>,
|
||||
) {
|
||||
use self::scoring::Change;
|
||||
|
||||
|
@ -113,21 +125,46 @@ where
|
|||
assert!(i < txs.len());
|
||||
assert!(i < scores.len());
|
||||
|
||||
scores[i] = *txs[i].transaction.gas_price();
|
||||
scores[i] = txs[i].effective_gas_price(self.block_base_fee);
|
||||
let boost = match txs[i].priority() {
|
||||
super::Priority::Local => 15,
|
||||
super::Priority::Retracted => 10,
|
||||
super::Priority::Regular => 0,
|
||||
};
|
||||
scores[i] = scores[i] << boost;
|
||||
|
||||
//boost local and retracted only if they are currently includable (base fee criteria)
|
||||
if self.block_base_fee.is_none() || scores[i] >= self.block_base_fee.unwrap() {
|
||||
scores[i] = scores[i] << boost;
|
||||
}
|
||||
}
|
||||
// We are only sending an event in case of penalization.
|
||||
// So just lower the priority of all non-local transactions.
|
||||
Change::Event(_) => {
|
||||
for (score, tx) in scores.iter_mut().zip(txs) {
|
||||
// Never penalize local transactions.
|
||||
if !tx.priority().is_local() {
|
||||
*score = *score >> 3;
|
||||
Change::Event(event) => {
|
||||
match event {
|
||||
ScoringEvent::Penalize => {
|
||||
for (score, tx) in scores.iter_mut().zip(txs) {
|
||||
// Never penalize local transactions.
|
||||
if !tx.priority().is_local() {
|
||||
*score = *score >> 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
ScoringEvent::BlockBaseFeeChanged => {
|
||||
for i in 0..txs.len() {
|
||||
scores[i] = txs[i].transaction.effective_gas_price(self.block_base_fee);
|
||||
let boost = match txs[i].priority() {
|
||||
super::Priority::Local => 15,
|
||||
super::Priority::Retracted => 10,
|
||||
super::Priority::Regular => 0,
|
||||
};
|
||||
|
||||
//boost local and retracted only if they are currently includable (base fee criteria)
|
||||
if self.block_base_fee.is_none()
|
||||
|| scores[i] >= self.block_base_fee.unwrap()
|
||||
{
|
||||
scores[i] = scores[i] << boost;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +187,10 @@ mod tests {
|
|||
#[test]
|
||||
fn should_calculate_score_correctly() {
|
||||
// given
|
||||
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
|
||||
let scoring = NonceAndGasPrice {
|
||||
strategy: PrioritizationStrategy::GasPriceOnly,
|
||||
block_base_fee: None,
|
||||
};
|
||||
let (tx1, tx2, tx3) = Tx::default().signed_triple();
|
||||
let transactions = vec![tx1, tx2, tx3]
|
||||
.into_iter()
|
||||
|
@ -200,7 +240,11 @@ mod tests {
|
|||
assert_eq!(scores, vec![32768.into(), 1024.into(), 1.into()]);
|
||||
|
||||
// Check penalization
|
||||
scoring.update_scores(&transactions, &mut *scores, scoring::Change::Event(()));
|
||||
scoring.update_scores(
|
||||
&transactions,
|
||||
&mut *scores,
|
||||
scoring::Change::Event(ScoringEvent::Penalize),
|
||||
);
|
||||
assert_eq!(scores, vec![32768.into(), 128.into(), 0.into()]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ impl Default for TestClient {
|
|||
account_details: AccountDetails {
|
||||
nonce: 123.into(),
|
||||
balance: 63_100.into(),
|
||||
code_hash: None,
|
||||
is_local: false,
|
||||
},
|
||||
gas_required: 21_000.into(),
|
||||
|
@ -68,6 +69,11 @@ impl TestClient {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_code_hash<T: Into<H256>>(mut self, code_hash: T) -> Self {
|
||||
self.account_details.code_hash = Some(code_hash.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_gas_required<T: Into<U256>>(mut self, gas_required: T) -> Self {
|
||||
self.gas_required = gas_required.into();
|
||||
self
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use ethereum_types::U256;
|
||||
use hash::KECCAK_EMPTY;
|
||||
use txpool;
|
||||
use types::transaction::{self, PendingTransaction};
|
||||
|
||||
|
@ -46,6 +47,8 @@ fn new_queue() -> TransactionQueue {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
)
|
||||
|
@ -64,6 +67,8 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -124,6 +129,8 @@ fn should_never_drop_local_transactions_from_different_senders() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -269,6 +276,71 @@ fn should_import_transaction_below_min_gas_price_threshold_if_local() {
|
|||
assert_eq!(txq.status().status.transaction_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_reject_transaction_from_non_eoa_if_non_eoa_sender_is_not_allowed() {
|
||||
// given
|
||||
let txq = new_queue();
|
||||
let tx = Tx::default();
|
||||
let code_hash = [
|
||||
0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f,
|
||||
0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a,
|
||||
0x0f, 0x0e,
|
||||
];
|
||||
|
||||
// when
|
||||
let res = txq.import(
|
||||
TestClient::new().with_code_hash(code_hash),
|
||||
vec![tx.signed().unverified()],
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(res, vec![Err(transaction::Error::SenderIsNotEOA)]);
|
||||
assert_eq!(txq.status().status.transaction_count, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_import_transaction_from_non_eoa_if_non_eoa_sender_is_allowed() {
|
||||
// given
|
||||
let txq = new_queue();
|
||||
let tx = Tx::default();
|
||||
let code_hash = [
|
||||
0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f,
|
||||
0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a, 0x0f, 0x0e, 0x0c, 0x0a,
|
||||
0x0f, 0x0e,
|
||||
];
|
||||
txq.set_verifier_options(verifier::Options {
|
||||
allow_non_eoa_sender: true,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// when
|
||||
let res = txq.import(
|
||||
TestClient::new().with_code_hash(code_hash),
|
||||
vec![tx.signed().unverified()],
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(res, vec![Ok(())]);
|
||||
assert_eq!(txq.status().status.transaction_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_import_transaction_if_account_code_hash_is_keccak_empty() {
|
||||
// given
|
||||
let txq = new_queue();
|
||||
let tx = Tx::default();
|
||||
|
||||
// when
|
||||
let res = txq.import(
|
||||
TestClient::new().with_code_hash(KECCAK_EMPTY),
|
||||
vec![tx.signed().unverified()],
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(res, vec![Ok(())]);
|
||||
assert_eq!(txq.status().status.transaction_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_import_txs_from_same_sender() {
|
||||
// given
|
||||
|
@ -541,6 +613,8 @@ fn should_prefer_current_transactions_when_hitting_the_limit() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -898,6 +972,7 @@ fn should_not_return_transactions_over_nonce_cap() {
|
|||
nonce_cap: Some(123.into()),
|
||||
max_len: usize::max_value(),
|
||||
ordering: PendingOrdering::Priority,
|
||||
includable_boundary: Default::default(),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -932,6 +1007,7 @@ fn should_return_cached_pending_even_if_unordered_is_requested() {
|
|||
nonce_cap: None,
|
||||
max_len: 3,
|
||||
ordering: PendingOrdering::Unordered,
|
||||
includable_boundary: Default::default(),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -960,6 +1036,7 @@ fn should_return_unordered_and_not_populate_the_cache() {
|
|||
nonce_cap: None,
|
||||
max_len: usize::max_value(),
|
||||
ordering: PendingOrdering::Unordered,
|
||||
includable_boundary: Default::default(),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1035,6 +1112,8 @@ fn should_include_local_transaction_to_a_full_pool() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -1067,6 +1146,8 @@ fn should_avoid_verifying_transaction_already_in_pool() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -1102,6 +1183,8 @@ fn should_avoid_reverifying_recently_rejected_transactions() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -1150,6 +1233,8 @@ fn should_reject_early_in_case_gas_price_is_less_than_min_effective() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: false,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
@ -1192,6 +1277,8 @@ fn should_not_reject_early_in_case_gas_price_is_less_than_min_effective() {
|
|||
block_gas_limit: 1_000_000.into(),
|
||||
tx_gas_limit: 1_000_000.into(),
|
||||
no_early_reject: true,
|
||||
block_base_fee: None,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
);
|
||||
|
|
|
@ -31,6 +31,7 @@ use std::{
|
|||
};
|
||||
|
||||
use ethereum_types::{H256, U256};
|
||||
use hash::KECCAK_EMPTY;
|
||||
use txpool;
|
||||
use types::transaction;
|
||||
|
||||
|
@ -42,14 +43,18 @@ use super::{
|
|||
/// Verification options.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Options {
|
||||
/// Minimal allowed gas price.
|
||||
/// Minimal allowed gas price (actually minimal block producer reward = effective_priority_fee).
|
||||
pub minimal_gas_price: U256,
|
||||
/// Current block gas limit.
|
||||
pub block_gas_limit: U256,
|
||||
/// Block base fee. Exists if the EIP 1559 is activated.
|
||||
pub block_base_fee: Option<U256>,
|
||||
/// Maximal gas limit for a single transaction.
|
||||
pub tx_gas_limit: U256,
|
||||
/// Skip checks for early rejection, to make sure that local transactions are always imported.
|
||||
pub no_early_reject: bool,
|
||||
/// Accept transactions from non EOAs (see EIP-3607)
|
||||
pub allow_non_eoa_sender: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -58,8 +63,10 @@ impl Default for Options {
|
|||
Options {
|
||||
minimal_gas_price: 0.into(),
|
||||
block_gas_limit: U256::max_value(),
|
||||
block_base_fee: None,
|
||||
tx_gas_limit: U256::max_value(),
|
||||
no_early_reject: false,
|
||||
allow_non_eoa_sender: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +100,7 @@ impl Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return transaction gas price
|
||||
/// Return transaction gas price for non 1559 transactions or maxFeePerGas for 1559 transactions.
|
||||
pub fn gas_price(&self) -> &U256 {
|
||||
match *self {
|
||||
Transaction::Unverified(ref tx) => &tx.tx().gas_price,
|
||||
|
@ -110,6 +117,33 @@ impl Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return actual gas price of the transaction depending on the current block base fee
|
||||
pub fn effective_gas_price(&self, block_base_fee: Option<U256>) -> U256 {
|
||||
match *self {
|
||||
Transaction::Unverified(ref tx) => tx.effective_gas_price(block_base_fee),
|
||||
Transaction::Retracted(ref tx) => tx.effective_gas_price(block_base_fee),
|
||||
Transaction::Local(ref tx) => tx.effective_gas_price(block_base_fee),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return effective fee - part of the transaction fee that goes to the miner
|
||||
pub fn effective_priority_fee(&self, block_base_fee: Option<U256>) -> U256 {
|
||||
match *self {
|
||||
Transaction::Unverified(ref tx) => tx.effective_priority_fee(block_base_fee),
|
||||
Transaction::Retracted(ref tx) => tx.effective_priority_fee(block_base_fee),
|
||||
Transaction::Local(ref tx) => tx.effective_priority_fee(block_base_fee),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if transaction has zero gas price
|
||||
pub fn has_zero_gas_price(&self) -> bool {
|
||||
match *self {
|
||||
Transaction::Unverified(ref tx) => tx.has_zero_gas_price(),
|
||||
Transaction::Retracted(ref tx) => tx.has_zero_gas_price(),
|
||||
Transaction::Local(ref tx) => tx.has_zero_gas_price(),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction(&self) -> &transaction::TypedTransaction {
|
||||
match *self {
|
||||
Transaction::Unverified(ref tx) => &*tx,
|
||||
|
@ -213,22 +247,26 @@ impl<C: Client> txpool::Verifier<Transaction>
|
|||
}
|
||||
|
||||
let is_own = tx.is_local();
|
||||
let has_zero_gas_price = tx.has_zero_gas_price();
|
||||
// Quick exit for non-service and non-local transactions
|
||||
//
|
||||
// We're checking if the transaction is below configured minimal gas price
|
||||
// or the effective minimal gas price in case the pool is full.
|
||||
if !tx.gas_price().is_zero() && !is_own {
|
||||
if tx.gas_price() < &self.options.minimal_gas_price {
|
||||
|
||||
if !has_zero_gas_price && !is_own {
|
||||
let effective_priority_fee = tx.effective_priority_fee(self.options.block_base_fee);
|
||||
|
||||
if effective_priority_fee < self.options.minimal_gas_price {
|
||||
trace!(
|
||||
target: "txqueue",
|
||||
"[{:?}] Rejected tx below minimal gas price threshold: {} < {}",
|
||||
hash,
|
||||
tx.gas_price(),
|
||||
effective_priority_fee,
|
||||
self.options.minimal_gas_price,
|
||||
);
|
||||
bail!(transaction::Error::InsufficientGasPrice {
|
||||
minimal: self.options.minimal_gas_price,
|
||||
got: *tx.gas_price(),
|
||||
got: effective_priority_fee,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -238,12 +276,15 @@ impl<C: Client> txpool::Verifier<Transaction>
|
|||
target: "txqueue",
|
||||
"[{:?}] Rejected tx early, cause it doesn't have any chance to get to the pool: (gas price: {} < {})",
|
||||
hash,
|
||||
tx.gas_price(),
|
||||
vtx.transaction.tx().gas_price,
|
||||
tx.effective_gas_price(self.options.block_base_fee),
|
||||
vtx.transaction.effective_gas_price(self.options.block_base_fee),
|
||||
);
|
||||
return Err(transaction::Error::TooCheapToReplace {
|
||||
prev: Some(vtx.transaction.tx().gas_price),
|
||||
new: Some(*tx.gas_price()),
|
||||
prev: Some(
|
||||
vtx.transaction
|
||||
.effective_gas_price(self.options.block_base_fee),
|
||||
),
|
||||
new: Some(tx.effective_gas_price(self.options.block_base_fee)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +321,24 @@ impl<C: Client> txpool::Verifier<Transaction>
|
|||
let sender = transaction.sender();
|
||||
let account_details = self.client.account_details(&sender);
|
||||
|
||||
if transaction.tx().gas_price < self.options.minimal_gas_price {
|
||||
if !self.options.allow_non_eoa_sender {
|
||||
if let Some(code_hash) = account_details.code_hash {
|
||||
if code_hash != KECCAK_EMPTY {
|
||||
debug!(
|
||||
target: "txqueue",
|
||||
"[{:?}] Rejected tx, sender is not an EOA: {}",
|
||||
hash,
|
||||
code_hash
|
||||
);
|
||||
bail!(transaction::Error::SenderIsNotEOA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let effective_priority_fee =
|
||||
transaction.effective_priority_fee(self.options.block_base_fee);
|
||||
|
||||
if effective_priority_fee < self.options.minimal_gas_price {
|
||||
let transaction_type = self.client.transaction_type(&transaction);
|
||||
if let TransactionType::Service = transaction_type {
|
||||
debug!(target: "txqueue", "Service tx {:?} below minimal gas price accepted", hash);
|
||||
|
@ -291,20 +349,26 @@ impl<C: Client> txpool::Verifier<Transaction>
|
|||
target: "txqueue",
|
||||
"[{:?}] Rejected tx below minimal gas price threshold: {} < {}",
|
||||
hash,
|
||||
transaction.tx().gas_price,
|
||||
effective_priority_fee,
|
||||
self.options.minimal_gas_price,
|
||||
);
|
||||
bail!(transaction::Error::InsufficientGasPrice {
|
||||
minimal: self.options.minimal_gas_price,
|
||||
got: transaction.tx().gas_price,
|
||||
got: effective_priority_fee,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let (full_gas_price, overflow_1) = transaction
|
||||
.tx()
|
||||
.gas_price
|
||||
.overflowing_mul(transaction.tx().gas);
|
||||
let gas_price = transaction.tx().gas_price;
|
||||
|
||||
if gas_price < transaction.max_priority_fee_per_gas() {
|
||||
bail!(transaction::Error::InsufficientGasPrice {
|
||||
minimal: transaction.max_priority_fee_per_gas(),
|
||||
got: gas_price,
|
||||
});
|
||||
}
|
||||
|
||||
let (full_gas_price, overflow_1) = gas_price.overflowing_mul(transaction.tx().gas);
|
||||
let (cost, overflow_2) = transaction.tx().value.overflowing_add(full_gas_price);
|
||||
if overflow_1 || overflow_2 {
|
||||
trace!(
|
||||
|
|
|
@ -45,7 +45,7 @@ impl ServiceTransactionChecker {
|
|||
) -> Result<bool, String> {
|
||||
let sender = tx.sender();
|
||||
// Skip checking the contract if the transaction does not have zero gas price
|
||||
if !tx.tx().gas_price.is_zero() {
|
||||
if !tx.has_zero_gas_price() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ impl ServiceTransactionChecker {
|
|||
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(),
|
||||
BlockId::Latest,
|
||||
)
|
||||
.ok_or_else(|| "contract is not configured")?;
|
||||
.ok_or_else(|| "Certifier contract is not configured")?;
|
||||
self.call_contract(client, contract_address, sender)
|
||||
.and_then(|allowed| {
|
||||
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
|
||||
|
|
|
@ -11,7 +11,7 @@ keccak-hash = "0.5.0"
|
|||
jsonrpc-core = "15.0.0"
|
||||
jsonrpc-tcp-server = "15.0.0"
|
||||
log = "0.4"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.5"
|
||||
|
|
|
@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||
[dependencies]
|
||||
byteorder = "1.2"
|
||||
ethbloom = "0.9.1"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
tiny-keccak = "1.4"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -14,7 +14,7 @@ kvdb = "0.1"
|
|||
kvdb-rocksdb = "0.1.3"
|
||||
kvdb-memorydb = "0.1"
|
||||
parity-util-mem = "0.7"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
rlp = { version = "0.4.6" }
|
||||
rlp_derive = { path = "../../util/rlp-derive" }
|
||||
stats = { path = "../../util/stats" }
|
|
@ -15,7 +15,7 @@ kvdb = "0.1"
|
|||
log = "0.4"
|
||||
memory-db = { path = "../memory-db" }
|
||||
parity-util-mem = "0.7"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
fastmap = { path = "../../util/fastmap" }
|
||||
rlp = { version = "0.4.6" }
|
||||
|
||||
|
|
|
@ -25,12 +25,14 @@ use std::{
|
|||
use super::{
|
||||
error_key_already_exists, error_negatively_reference_hash, memory_db::*, LATEST_ERA_KEY,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
|
||||
use ethereum_types::H256;
|
||||
use hash_db::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use rlp::{decode, encode};
|
||||
use traits::JournalDB;
|
||||
use DB_PREFIX_LEN;
|
||||
|
||||
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay
|
||||
/// and latent-removal semantics.
|
||||
|
@ -214,12 +216,19 @@ impl JournalDB for ArchiveDB {
|
|||
fn consolidate(&mut self, with: MemoryDB<KeccakHasher, DBValue>) {
|
||||
self.overlay.consolidate(with);
|
||||
}
|
||||
|
||||
fn state(&self, id: &H256) -> Option<Bytes> {
|
||||
self.backing
|
||||
.get_by_prefix(self.column, &id[0..DB_PREFIX_LEN])
|
||||
.map(|b| b.into_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use ethcore_db::InMemoryWithMetrics;
|
||||
use hash_db::HashDB;
|
||||
use keccak::keccak;
|
||||
use JournalDB;
|
||||
|
@ -497,4 +506,22 @@ mod tests {
|
|||
|
||||
assert!(jdb.get(&key).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_state() {
|
||||
let shared_db = Arc::new(InMemoryWithMetrics::create(0));
|
||||
|
||||
let key = {
|
||||
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
||||
let key = jdb.insert(b"foo");
|
||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
||||
key
|
||||
};
|
||||
|
||||
{
|
||||
let jdb = ArchiveDB::new(shared_db, None);
|
||||
let state = jdb.state(&key);
|
||||
assert!(state.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ use parity_util_mem::MallocSizeOf;
|
|||
use parking_lot::RwLock;
|
||||
use rlp::{decode, encode};
|
||||
use util::{DatabaseKey, DatabaseValueRef, DatabaseValueView};
|
||||
use DB_PREFIX_LEN;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)]
|
||||
struct RefInfo {
|
||||
|
@ -608,6 +609,12 @@ impl JournalDB for EarlyMergeDB {
|
|||
fn consolidate(&mut self, with: MemoryDB<KeccakHasher, DBValue>) {
|
||||
self.overlay.consolidate(with);
|
||||
}
|
||||
|
||||
fn state(&self, id: &H256) -> Option<Bytes> {
|
||||
self.backing
|
||||
.get_by_prefix(self.column, &id[0..DB_PREFIX_LEN])
|
||||
.map(|b| b.into_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -23,6 +23,7 @@ use std::{
|
|||
};
|
||||
|
||||
use super::{error_negatively_reference_hash, JournalDB, DB_PREFIX_LEN, LATEST_ERA_KEY};
|
||||
use bytes::Bytes;
|
||||
use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
|
||||
use ethereum_types::H256;
|
||||
use fastmap::H256FastMap;
|
||||
|
@ -509,6 +510,26 @@ impl JournalDB for OverlayRecentDB {
|
|||
fn consolidate(&mut self, with: MemoryDB<KeccakHasher, DBValue>) {
|
||||
self.transaction_overlay.consolidate(with);
|
||||
}
|
||||
|
||||
fn state(&self, key: &H256) -> Option<Bytes> {
|
||||
let journal_overlay = self.journal_overlay.read();
|
||||
let key = to_short_key(key);
|
||||
journal_overlay
|
||||
.backing_overlay
|
||||
.get(&key)
|
||||
.map(|v| v.into_vec())
|
||||
.or_else(|| {
|
||||
journal_overlay
|
||||
.pending_overlay
|
||||
.get(&key)
|
||||
.map(|d| d.clone().into_vec())
|
||||
})
|
||||
.or_else(|| {
|
||||
self.backing
|
||||
.get_by_prefix(self.column, &key[0..DB_PREFIX_LEN])
|
||||
.map(|b| b.into_vec())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl HashDB<KeccakHasher, DBValue> for OverlayRecentDB {
|
||||
|
|
|
@ -23,6 +23,7 @@ use std::{
|
|||
};
|
||||
|
||||
use super::{traits::JournalDB, LATEST_ERA_KEY};
|
||||
use bytes::Bytes;
|
||||
use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
|
||||
use ethereum_types::H256;
|
||||
use hash_db::HashDB;
|
||||
|
@ -32,6 +33,7 @@ use overlaydb::OverlayDB;
|
|||
use parity_util_mem::{allocators::new_malloc_size_ops, MallocSizeOf};
|
||||
use rlp::{decode, encode};
|
||||
use util::{DatabaseKey, DatabaseValueRef, DatabaseValueView};
|
||||
use DB_PREFIX_LEN;
|
||||
|
||||
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay
|
||||
/// and latent-removal semantics.
|
||||
|
@ -245,6 +247,12 @@ impl JournalDB for RefCountedDB {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn state(&self, id: &H256) -> Option<Bytes> {
|
||||
self.backing
|
||||
.get_by_prefix(self.column, &id[0..DB_PREFIX_LEN])
|
||||
.map(|b| b.into_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
use std::{io, sync::Arc};
|
||||
|
||||
use bytes::Bytes;
|
||||
use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
|
||||
use ethereum_types::H256;
|
||||
use hash_db::{AsHashDB, HashDB};
|
||||
|
@ -95,6 +96,9 @@ pub trait JournalDB: KeyedHashDB {
|
|||
/// Consolidate all the insertions and deletions in the given memory overlay.
|
||||
fn consolidate(&mut self, overlay: ::memory_db::MemoryDB<KeccakHasher, DBValue>);
|
||||
|
||||
/// State data query
|
||||
fn state(&self, id: &H256) -> Option<Bytes>;
|
||||
|
||||
/// Commit all changes in a single batch
|
||||
#[cfg(test)]
|
||||
fn commit_batch(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> io::Result<u32> {
|
||||
|
|
|
@ -52,7 +52,7 @@ parity-bytes = "0.1"
|
|||
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
|
||||
parity-snappy = "0.1"
|
||||
parity-util-mem = "0.7"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
trie-db = "0.11.0"
|
||||
patricia-trie-ethereum = { path = "../db/patricia-trie-ethereum" }
|
||||
rand = "0.7.3"
|
||||
|
|
|
@ -20,7 +20,7 @@ log = "0.4"
|
|||
parity-bytes = "0.1"
|
||||
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
|
||||
parity-util-mem = "0.7"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.11.1"
|
||||
rand = "0.7.3"
|
||||
rayon = "1.1"
|
||||
rlp = { version = "0.4.6" }
|
||||
|
|
|
@ -153,8 +153,9 @@ pub trait BlockProvider {
|
|||
|
||||
/// Get a list of uncles for a given block.
|
||||
/// Returns None if block does not exist.
|
||||
fn uncles(&self, hash: &H256) -> Option<Vec<Header>> {
|
||||
self.block_body(hash).map(|body| body.uncles())
|
||||
fn uncles(&self, hash: &H256, eip1559_transition: BlockNumber) -> Option<Vec<Header>> {
|
||||
self.block_body(hash)
|
||||
.map(|body| body.uncles(eip1559_transition))
|
||||
}
|
||||
|
||||
/// Get a list of uncle hashes for a given block.
|
||||
|
@ -272,6 +273,9 @@ pub struct BlockChain {
|
|||
pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>,
|
||||
pending_block_details: RwLock<HashMap<H256, BlockDetails>>,
|
||||
pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>,
|
||||
|
||||
/// Number of first block where EIP-1559 rules begin. New encoding/decoding block format.
|
||||
pub eip1559_transition: BlockNumber,
|
||||
}
|
||||
|
||||
impl BlockProvider for BlockChain {
|
||||
|
@ -559,7 +563,7 @@ impl<'a> Iterator for AncestryWithMetadataIter<'a> {
|
|||
} else {
|
||||
let details = self.chain.block_details(&self.current);
|
||||
let header = self.chain.block_header_data(&self.current).map(|h| {
|
||||
h.decode()
|
||||
h.decode(self.chain.eip1559_transition)
|
||||
.expect("Stored block header data is valid RLP; qed")
|
||||
});
|
||||
|
||||
|
@ -630,7 +634,12 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
|
|||
|
||||
impl BlockChain {
|
||||
/// Create new instance of blockchain from given Genesis.
|
||||
pub fn new(config: Config, genesis: &[u8], db: Arc<dyn BlockChainDB>) -> BlockChain {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
genesis: &[u8],
|
||||
db: Arc<dyn BlockChainDB>,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> BlockChain {
|
||||
// 400 is the average size of the key
|
||||
let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400);
|
||||
|
||||
|
@ -656,6 +665,7 @@ impl BlockChain {
|
|||
pending_block_hashes: RwLock::new(HashMap::new()),
|
||||
pending_block_details: RwLock::new(HashMap::new()),
|
||||
pending_transaction_addresses: RwLock::new(HashMap::new()),
|
||||
eip1559_transition,
|
||||
};
|
||||
|
||||
// load best block
|
||||
|
@ -715,7 +725,7 @@ impl BlockChain {
|
|||
let mut best_block = bc.best_block.write();
|
||||
*best_block = BestBlock {
|
||||
total_difficulty: best_block_total_difficulty,
|
||||
header: best_block_rlp.decode_header(),
|
||||
header: best_block_rlp.decode_header(eip1559_transition),
|
||||
block: best_block_rlp,
|
||||
};
|
||||
}
|
||||
|
@ -1044,7 +1054,7 @@ impl BlockChain {
|
|||
let mut best_block = self.best_block.write();
|
||||
*best_block = BestBlock {
|
||||
total_difficulty: best_block_total_difficulty,
|
||||
header: best_block_rlp.decode_header(),
|
||||
header: best_block_rlp.decode_header(self.eip1559_transition),
|
||||
block: best_block_rlp,
|
||||
};
|
||||
}
|
||||
|
@ -1463,7 +1473,7 @@ impl BlockChain {
|
|||
batch.put(db::COL_EXTRA, b"best", update.info.hash.as_bytes());
|
||||
*best_block = Some(BestBlock {
|
||||
total_difficulty: update.info.total_difficulty,
|
||||
header: update.block.decode_header(),
|
||||
header: update.block.decode_header(self.eip1559_transition),
|
||||
block: update.block,
|
||||
});
|
||||
}
|
||||
|
@ -1991,8 +2001,12 @@ mod tests {
|
|||
Arc::new(db)
|
||||
}
|
||||
|
||||
fn new_chain(genesis: encoded::Block, db: Arc<dyn BlockChainDB>) -> BlockChain {
|
||||
BlockChain::new(Config::default(), genesis.raw(), db)
|
||||
fn new_chain(
|
||||
genesis: encoded::Block,
|
||||
db: Arc<dyn BlockChainDB>,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> BlockChain {
|
||||
BlockChain::new(Config::default(), genesis.raw(), db, eip1559_transition)
|
||||
}
|
||||
|
||||
fn insert_block(
|
||||
|
@ -2058,7 +2072,11 @@ mod tests {
|
|||
let first = genesis.add_block();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
assert_eq!(bc.best_block_number(), 0);
|
||||
|
||||
// when
|
||||
|
@ -2086,7 +2104,7 @@ mod tests {
|
|||
let first_hash = first.hash();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.encoded(), db.clone());
|
||||
let bc = new_chain(genesis.encoded(), db.clone(), BlockNumber::max_value());
|
||||
|
||||
assert_eq!(bc.genesis_hash(), genesis_hash);
|
||||
assert_eq!(bc.best_block_hash(), genesis_hash);
|
||||
|
@ -2118,7 +2136,11 @@ mod tests {
|
|||
let generator = BlockGenerator::new(vec![first_10]);
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut block_hashes = vec![genesis.last().hash()];
|
||||
let mut batch = db.key_value().transaction();
|
||||
|
@ -2165,7 +2187,11 @@ mod tests {
|
|||
let generator = BlockGenerator::new(vec![b1a, b1b, b2a, b2b, b3a, b3b, b4a, b4b, b5a, b5b]);
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
for b in generator {
|
||||
insert_block(&db, &bc, b.encoded(), vec![]);
|
||||
|
@ -2204,7 +2230,11 @@ mod tests {
|
|||
let b2_hash = b2.last().hash();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
let _ = insert_block_batch(&mut batch, &bc, b1a.last().encoded(), vec![]);
|
||||
|
@ -2291,7 +2321,11 @@ mod tests {
|
|||
let t3_hash = t3.hash();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
let _ = insert_block_batch(&mut batch, &bc, b1a.last().encoded(), vec![]);
|
||||
|
@ -2364,7 +2398,11 @@ mod tests {
|
|||
let best_block_hash = b3a_hash;
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
let ir1 = insert_block_batch(&mut batch, &bc, b1.last().encoded(), vec![]);
|
||||
|
@ -2490,7 +2528,11 @@ mod tests {
|
|||
let db = new_db();
|
||||
|
||||
{
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
assert_eq!(bc.best_block_hash(), genesis_hash);
|
||||
let mut batch = db.key_value().transaction();
|
||||
insert_block_batch(&mut batch, &bc, first.last().encoded(), vec![]);
|
||||
|
@ -2500,7 +2542,11 @@ mod tests {
|
|||
}
|
||||
|
||||
{
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
assert_eq!(bc.best_block_hash(), first_hash);
|
||||
}
|
||||
|
@ -2515,7 +2561,11 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(encoded::Block::new(genesis), db.clone());
|
||||
let bc = new_chain(
|
||||
encoded::Block::new(genesis),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
let mut batch = db.key_value().transaction();
|
||||
insert_block_batch(&mut batch, &bc, encoded::Block::new(b1), vec![]);
|
||||
db.key_value().write(batch).unwrap();
|
||||
|
@ -2599,7 +2649,11 @@ mod tests {
|
|||
let b3_number = b3.last().number();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
insert_block(
|
||||
&db,
|
||||
&bc,
|
||||
|
@ -2783,7 +2837,11 @@ mod tests {
|
|||
let b2a = b1a.add_block_with_bloom(bloom_ba);
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5);
|
||||
let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5);
|
||||
|
@ -2845,7 +2903,11 @@ mod tests {
|
|||
let b1_total_difficulty = genesis.last().difficulty() + b1.last().difficulty();
|
||||
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
let mut batch = db.key_value().transaction();
|
||||
bc.insert_unordered_block(
|
||||
&mut batch,
|
||||
|
@ -2885,7 +2947,11 @@ mod tests {
|
|||
|
||||
let db = new_db();
|
||||
{
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
// create a longer fork
|
||||
|
@ -2901,7 +2967,7 @@ mod tests {
|
|||
}
|
||||
|
||||
// re-loading the blockchain should load the correct best block.
|
||||
let bc = new_chain(genesis.last().encoded(), db);
|
||||
let bc = new_chain(genesis.last().encoded(), db, BlockNumber::max_value());
|
||||
assert_eq!(bc.best_block_number(), 5);
|
||||
}
|
||||
|
||||
|
@ -2916,7 +2982,11 @@ mod tests {
|
|||
|
||||
let db = new_db();
|
||||
{
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
// create a longer fork
|
||||
|
@ -2958,7 +3028,7 @@ mod tests {
|
|||
}
|
||||
|
||||
// re-loading the blockchain should load the correct best block.
|
||||
let bc = new_chain(genesis.last().encoded(), db);
|
||||
let bc = new_chain(genesis.last().encoded(), db, BlockNumber::max_value());
|
||||
|
||||
assert_eq!(bc.best_block_number(), 5);
|
||||
assert_eq!(
|
||||
|
@ -2982,7 +3052,11 @@ mod tests {
|
|||
|
||||
let db = new_db();
|
||||
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
bc.insert_epoch_transition(
|
||||
|
@ -3067,7 +3141,11 @@ mod tests {
|
|||
|
||||
let bootstrap_chain = |blocks: Vec<&BlockBuilder>| {
|
||||
let db = new_db();
|
||||
let bc = new_chain(genesis.last().encoded(), db.clone());
|
||||
let bc = new_chain(
|
||||
genesis.last().encoded(),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
let mut batch = db.key_value().transaction();
|
||||
for block in blocks {
|
||||
insert_block_batch(&mut batch, &bc, block.last().encoded(), vec![]);
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
{
|
||||
"name": "Aleut",
|
||||
"engine": {
|
||||
"clique": {
|
||||
"params": {
|
||||
"epoch": 30000,
|
||||
"period": 15
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"accountStartNonce": "0x00",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283DisableTransition": "0x0",
|
||||
"eip1283ReenableTransition": "0x0",
|
||||
"eip1283Transition": "0x0",
|
||||
"eip1344Transition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip1706Transition": "0x0",
|
||||
"eip1884Transition": "0x0",
|
||||
"eip2028Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip2929Transition": "0x0",
|
||||
"eip2930Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip1559Transition": "0xa",
|
||||
"eip3198Transition": "0xa",
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"maximumExtraDataSize": "0xffff",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "7822",
|
||||
"chainID": "7822",
|
||||
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00"
|
||||
},
|
||||
"genesis": {
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"difficulty": "0x400",
|
||||
"extraData": "0x000000000000000000000000000000000000000000000000000000000000000036267c845cc42b57ccb869d655e5d5fb620cc69a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1312D00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce": "0x0000000000000000"
|
||||
}
|
||||
},
|
||||
"timestamp": "0x0"
|
||||
},
|
||||
"nodes": [ "enode://0c72e2b7873e4342d725b5990c17adb2b159aad2ff5853de7e4910b25522a1f9e78f9cd802a8a3225b8fae4e994e522b50d6bd5a163eb3a7b49a0a73ca9a1c7e@3.12.166.199:30303", "enode://aec88fd902744bf67705c098bf532b01017ccc3a156395508e2d9c4e7c22699ecccae1e7316614f8a2d4c5698a9be3fe6151ee25b9ed4aa052f88e112c65387a@164.90.171.157:31559"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"builtin": {
|
||||
"name": "ecrecover",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 3000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"builtin": {
|
||||
"name": "sha256",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 60,
|
||||
"word": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"builtin": {
|
||||
"name": "ripemd160",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 600,
|
||||
"word": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"builtin": {
|
||||
"name": "identity",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 15,
|
||||
"word": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"builtin": {
|
||||
"activate_at": "0x00",
|
||||
"name": "modexp",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_add",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_mul",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 6000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_pairing",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 45000,
|
||||
"pair": 34000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000009": {
|
||||
"builtin": {
|
||||
"activate_at": "0x00",
|
||||
"name": "blake2_f",
|
||||
"pricing": {
|
||||
"blake2_f": {
|
||||
"gas_per_round": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
|
||||
"balance": "90000000000000000000000"
|
||||
},
|
||||
"0x627306090abaB3A6e1400e9345bC60c78a8BEf57": {
|
||||
"balance": "90000000000000000000000"
|
||||
},
|
||||
"0xf17f52151EbEF6C7334FAD080c5704D77216b732": {
|
||||
"balance": "90000000000000000000000"
|
||||
},
|
||||
"0xb8c3bfFb71F76BeE2B2f81bdBC53Ad4C43e3f58E": {
|
||||
"balance": "90000000000000000000000"
|
||||
},
|
||||
"0x60AdC0F89a41AF237ce73554EDe170D733ec14E0": {
|
||||
"balance": "90000000000000000000000"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,953 @@
|
|||
{
|
||||
"name": "Baikal",
|
||||
"engine": {
|
||||
"clique": {
|
||||
"params": {
|
||||
"epoch": 30000,
|
||||
"period": 30
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"accountStartNonce": "0x00",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283DisableTransition": "0x0",
|
||||
"eip1283ReenableTransition": "0x0",
|
||||
"eip1283Transition": "0x0",
|
||||
"eip1344Transition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip1706Transition": "0x0",
|
||||
"eip1884Transition": "0x0",
|
||||
"eip2028Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip2929Transition": "0x0",
|
||||
"eip2930Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip1559Transition": "0x1F4",
|
||||
"eip3198Transition": "0x1F4",
|
||||
"eip3529Transition": "0x1F4",
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"maximumExtraDataSize": "0xffff",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "1642",
|
||||
"chainID": "1642",
|
||||
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00"
|
||||
},
|
||||
"genesis": {
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"difficulty": "0x1",
|
||||
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000005211cea3870c7ba7c6c44b185e62eecdb864cd8c560228ce57d31efbf64c200b2c200aacec78cf17a7148e784fe95a7a750335f8b9572ee28d72e7650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x47b760",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce": "0x0000000000000000"
|
||||
}
|
||||
},
|
||||
"timestamp": "0x6092ca7f"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://39eb08bbfad87481553c471a63ff2a4b4885fffa4ff50f1cf46744d9ad6e2f764ede146fe4df563fa9ccda1a46b9b1a88fb08135e1bf1d71b320912499da773d@3.21.156.138:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000000": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"builtin": {
|
||||
"name": "ecrecover",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 3000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"builtin": {
|
||||
"name": "sha256",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 60,
|
||||
"word": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"builtin": {
|
||||
"name": "ripemd160",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 600,
|
||||
"word": 120
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"builtin": {
|
||||
"name": "identity",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 15,
|
||||
"word": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"builtin": {
|
||||
"activate_at": "0x00",
|
||||
"name": "modexp",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_add",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_mul",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 6000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_pairing",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 45000,
|
||||
"pair": 34000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000009": {
|
||||
"builtin": {
|
||||
"activate_at": "0x00",
|
||||
"name": "blake2_f",
|
||||
"pricing": {
|
||||
"blake2_f": {
|
||||
"gas_per_round": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000010": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000011": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000012": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000013": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000014": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000015": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000016": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000017": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000018": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000019": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000020": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000021": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000022": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000023": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000024": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000025": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000026": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000027": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000028": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000029": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000030": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000031": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000032": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000033": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000034": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000035": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000036": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000037": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000038": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000039": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000040": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000041": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000042": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000043": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000044": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000045": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000046": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000047": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000048": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000049": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000050": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000051": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000052": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000053": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000054": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000055": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000056": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000057": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000058": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000059": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000060": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000061": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000062": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000063": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000064": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000065": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000066": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000067": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000068": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000069": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000070": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000071": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000072": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000073": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000074": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000075": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000076": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000077": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000078": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000079": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000080": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000081": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000082": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000083": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000084": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000085": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000086": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000087": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000088": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000089": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000090": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000091": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000092": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000093": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000094": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000095": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000096": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000097": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000098": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000099": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000aa": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ab": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ac": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ad": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ae": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000af": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ba": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000be": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bf": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ca": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ce": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cf": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000da": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000db": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000dc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000dd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000de": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000df": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ea": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000eb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ec": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ed": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ee": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ef": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fa": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fe": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ff": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0x0e89e2aedb1cfcdb9424d41a1f218f4132738172": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"0x60adc0f89a41af237ce73554ede170d733ec14e0": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"0x799d329e5f583419167cd722962485926e338f4a": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"0x7cf5b79bfe291a67ab02b393e456ccc4c266f753": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"0x8ba1f109551bd432803012645ac136ddd64dba72": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"0xb02a2eda1b317fbd16760128836b0ac59b560e9d": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -137,7 +137,9 @@
|
|||
"difficultyBombDelays": {
|
||||
"0x42ae50": "0x2dc6c0",
|
||||
"0x6f1580": "0x1e8480",
|
||||
"0x8c6180": "0x3d0900"
|
||||
"0x8c6180": "0x3d0900",
|
||||
"0xc5d488": "0xaae60",
|
||||
"0xd228c8": "0xf4240"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +173,14 @@
|
|||
"eip1884Transition": "0x8a61c8",
|
||||
"eip2028Transition": "0x8a61c8",
|
||||
"eip2929Transition": "0xbad420",
|
||||
"eip2930Transition": "0xbad420"
|
||||
"eip2930Transition": "0xbad420",
|
||||
"eip1559Transition": "0xc5d488",
|
||||
"eip3198Transition": "0xc5d488",
|
||||
"eip3541Transition": "0xc5d488",
|
||||
"eip3529Transition": "0xc5d488",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
|
|
@ -33,6 +33,13 @@
|
|||
"eip2028Transition": "0x17d433",
|
||||
"eip2929Transition": "0x441064",
|
||||
"eip2930Transition": "0x441064",
|
||||
"eip1559Transition": "0x4d3fcd",
|
||||
"eip3198Transition": "0x4d3fcd",
|
||||
"eip3541Transition": "0x4d3fcd",
|
||||
"eip3529Transition": "0x4d3fcd",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00",
|
||||
"gasLimitBoundDivisor": "0x400",
|
||||
"maxCodeSize": "0x6000",
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
"eip214Transition": "0x4d50f8",
|
||||
"eip658Transition": "0x4d50f8",
|
||||
"wasmActivationTransition": "0x64b540",
|
||||
"wasmDisableTransition": "0x198096c",
|
||||
"eip145Transition": "0x8c6180",
|
||||
"eip1014Transition": "0x8c6180",
|
||||
"eip1052Transition": "0x8c6180",
|
||||
|
@ -69,6 +70,15 @@
|
|||
"eip1706Transition": "0xd751a5",
|
||||
"eip1884Transition": "0xd751a5",
|
||||
"eip2028Transition": "0xd751a5",
|
||||
"eip2929Transition": "0x179f954",
|
||||
"eip2930Transition": "0x179f954",
|
||||
"eip1559Transition": "0x198096c",
|
||||
"eip3198Transition": "0x198096c",
|
||||
"eip3541Transition": "0x198096c",
|
||||
"eip3529Transition": "0x198096c",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00",
|
||||
"kip4Transition": "0x8c6180",
|
||||
"kip6Transition": "0x8c6180"
|
||||
},
|
||||
|
@ -157,6 +167,12 @@
|
|||
"divisor": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x179f954": {
|
||||
"info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (24_770_900)",
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +264,9 @@
|
|||
}
|
||||
},
|
||||
"nodes": [
|
||||
"enode://30499bde23362f7d310a34518a2a6ff765921870bf0c3e63d21153cfa7ba9cf39cc7c8e54e9dad2f2b3c07288b3e91b220656833cc2d843a54875c229f3f959a@8.9.8.175:30303",
|
||||
"enode://30499bde23362f7d310a34518a2a6ff765921870bf0c3e63d21153cfa7ba9cf39cc7c8e54e9dad2f2b3c07288b3e91b220656833cc2d843a54875c229f3f959a@45.33.77.29:30303",
|
||||
"enode://16898006ba2cd4fa8bf9a3dfe32684c178fa861df144bfc21fe800dc4838a03e342056951fa9fd533dcb0be1219e306106442ff2cf1f7e9f8faa5f2fc1a3aa45@116.203.116.241:30303",
|
||||
"enode://2909846f78c37510cc0e306f185323b83bb2209e5ff4fdd279d93c60e3f365e3c6e62ad1d2133ff11f9fd6d23ad9c3dad73bb974d53a22f7d1ac5b7dea79d0b0@3.217.96.11:30303",
|
||||
"enode://740e1c8ea64e71762c71a463a04e2046070a0c9394fcab5891d41301dc473c0cff00ebab5a9bc87fbcb610ab98ac18225ff897bc8b7b38def5975d5ceb0a7d7c@108.61.170.124:30303",
|
||||
"enode://2909846f78c37510cc0e306f185323b83bb2209e5ff4fdd279d93c60e3f365e3c6e62ad1d2133ff11f9fd6d23ad9c3dad73bb974d53a22f7d1ac5b7dea79d0b0@157.230.31.163:30303"
|
||||
"enode://49a0e1aa38caa12cbf31222cb4e31cef1e8794cb4dd38012f84498ac867b19584e29bbf6d53201d7dfd3b5eb0998a4d908d096ed4ddb5f9102c623852cd331ec@54.87.247.5:30303"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -45,7 +45,20 @@
|
|||
"eip1344Transition": 12598600,
|
||||
"eip1706Transition": 12598600,
|
||||
"eip1884Transition": 12598600,
|
||||
"eip2028Transition": 12598600
|
||||
"eip2028Transition": 12598600,
|
||||
"eip2929Transition": 21364900,
|
||||
"eip2930Transition": 21364900,
|
||||
"eip3198Transition": 24090200,
|
||||
"eip3529Transition": 24090200,
|
||||
"eip3541Transition": 24090200,
|
||||
"eip1559Transition": 24090200,
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3b9aca00",
|
||||
"eip1559BaseFeeMinValue": "0x2540be400",
|
||||
"eip1559BaseFeeMinValueTransition": 24199500,
|
||||
"eip1559FeeCollector": "0x517F3AcfF3aFC2fb45e574718bca6F919b798e10",
|
||||
"eip1559FeeCollectorTransition": 24090200
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -76,6 +89,12 @@
|
|||
"divisor": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"21364900": {
|
||||
"info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (May 24, 2021, ~10:00 am UTC)",
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,18 @@
|
|||
"eip1344Transition": 12095200,
|
||||
"eip1706Transition": 12095200,
|
||||
"eip1884Transition": 12095200,
|
||||
"eip2028Transition": 12095200
|
||||
"eip2028Transition": 12095200,
|
||||
"eip2929Transition": 21050600,
|
||||
"eip2930Transition": 21050600,
|
||||
"eip3198Transition": 24114400,
|
||||
"eip3529Transition": 24114400,
|
||||
"eip3541Transition": 24114400,
|
||||
"eip1559Transition": 24114400,
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3b9aca00",
|
||||
"eip1559FeeCollector": "0xE8DDc5c7A2d2F0D7a9798459c0104fDf5E987ACA",
|
||||
"eip1559FeeCollectorTransition": 24114400
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -79,6 +90,12 @@
|
|||
"divisor": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"21050600": {
|
||||
"info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (May 24, 2021, ~10:00 am UTC)",
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,13 @@
|
|||
"eip2028Transition": "0x52efd1",
|
||||
"eip2929Transition": "0x7e8270",
|
||||
"eip2930Transition": "0x7e8270",
|
||||
"eip1559Transition": "0x87c5c4",
|
||||
"eip3198Transition": "0x87c5c4",
|
||||
"eip3541Transition": "0x87c5c4",
|
||||
"eip3529Transition": "0x87c5c4",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00",
|
||||
"gasLimitBoundDivisor": "0x400",
|
||||
"maxCodeSize": "0x6000",
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
"difficultyBombDelays": {
|
||||
"0x19f0a0": "0x2dc6c0",
|
||||
"0x408b70": "0x1e8480",
|
||||
"0x6c993d": "0x3d0900"
|
||||
"0x6c993d": "0x3d0900",
|
||||
"0xa03549": "0xaae60"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +54,14 @@
|
|||
"eip1884Transition": "0x62f756",
|
||||
"eip2028Transition": "0x62f756",
|
||||
"eip2929Transition": "0x95b8dd",
|
||||
"eip2930Transition": "0x95b8dd"
|
||||
"eip2930Transition": "0x95b8dd",
|
||||
"eip1559Transition": "0xa03549",
|
||||
"eip3198Transition": "0xa03549",
|
||||
"eip3541Transition": "0xa03549",
|
||||
"eip3529Transition": "0xa03549",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00"
|
||||
|
||||
},
|
||||
"genesis": {
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
{
|
||||
"name": "BerlinToLondonAt5 (test)",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x1BC16D674EC80000",
|
||||
"homesteadTransition": "0x0",
|
||||
"eip100bTransition": "0x0",
|
||||
"difficultyBombDelays": {
|
||||
"0": 5000000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x1",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283Transition": "0x0",
|
||||
"eip1283DisableTransition": "0x0",
|
||||
"eip1283ReenableTransition": "0x0",
|
||||
"eip1344Transition": "0x0",
|
||||
"eip1706Transition": "0x0",
|
||||
"eip1884Transition": "0x0",
|
||||
"eip2028Transition": "0x0",
|
||||
"eip2929Transition": "0x0",
|
||||
"eip2930Transition": "0x0",
|
||||
"eip1559Transition": "0x5",
|
||||
"eip3198Transition": "0x5",
|
||||
"eip3541Transition": "0x5",
|
||||
"eip3529Transition": "0x5",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000042",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x400000000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
|
||||
"gasLimit": "0x1388"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "ecrecover",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 3000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "sha256",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 60,
|
||||
"word": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "ripemd160",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 600,
|
||||
"word": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "identity",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 15,
|
||||
"word": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"builtin": {
|
||||
"name": "modexp",
|
||||
"activate_at": "0x00",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_add",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 500
|
||||
}
|
||||
}
|
||||
},
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_mul",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 40000
|
||||
}
|
||||
}
|
||||
},
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 6000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_pairing",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 100000,
|
||||
"pair": 80000
|
||||
}
|
||||
}
|
||||
},
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 45000,
|
||||
"pair": 34000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000009": {
|
||||
"builtin": {
|
||||
"name": "blake2_f",
|
||||
"activate_at": "0x00",
|
||||
"pricing": {
|
||||
"blake2_f": {
|
||||
"gas_per_round": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
pragma solidity ^0.4.20;
|
||||
|
||||
// Adapted from https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f
|
||||
// and: https://github.com/poanetwork/posdao-contracts/blob/master/contracts/TxPermission.sol
|
||||
|
||||
contract TxPermission {
|
||||
/// Allowed transaction types mask
|
||||
uint32 constant None = 0;
|
||||
uint32 constant All = 0xffffffff;
|
||||
uint32 constant Basic = 0x01;
|
||||
uint32 constant Call = 0x02;
|
||||
uint32 constant Create = 0x04;
|
||||
uint32 constant Private = 0x08;
|
||||
|
||||
/// Contract name
|
||||
function contractName() public constant returns (string) {
|
||||
return "TX_PERMISSION_CONTRACT";
|
||||
}
|
||||
|
||||
/// Contract name hash
|
||||
function contractNameHash() public constant returns (bytes32) {
|
||||
return keccak256(contractName());
|
||||
}
|
||||
|
||||
/// Contract version
|
||||
function contractVersion() public constant returns (uint256) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/// @dev Defines the allowed transaction types which may be initiated by the specified sender with
|
||||
/// the specified gas price and data. Used by node's engine each time a transaction is about to be
|
||||
/// included into a block. See https://openethereum.github.io/Permissioning.html#how-it-works-1
|
||||
/// @param _sender Transaction sender address.
|
||||
/// @param _to Transaction recipient address. If creating a contract, the `_to` address is zero.
|
||||
/// @param _value Transaction amount in wei.
|
||||
/// @param _maxFeePerGas The `maxFeePerGas` in Wei for EIP-1559 transaction, or gas price for a legacy transaction.
|
||||
/// @param _maxInclusionFeePerGas The `maxInclusionFeePerGas` in Wei for EIP-1559 transaction.
|
||||
/// Equals to gas price for a legacy transaction.
|
||||
/// @param _gasLimit Gas limit for the transaction.
|
||||
/// @param _data Transaction data.
|
||||
/// @return `uint32 typesMask` - Set of allowed transactions for `_sender` depending on tx `_to` address,
|
||||
/// `_gasPrice`, and `_data`. The result is represented as a set of flags:
|
||||
/// 0x01 - basic transaction (e.g. ether transferring to user wallet);
|
||||
/// 0x02 - contract call;
|
||||
/// 0x04 - contract creation;
|
||||
/// 0x08 - private transaction.
|
||||
/// `bool cache` - If `true` is returned, the same permissions will be applied from the same
|
||||
/// `_sender` without calling this contract again.
|
||||
function allowedTxTypes(
|
||||
address _sender,
|
||||
address _to,
|
||||
uint256 _value,
|
||||
uint256 _maxFeePerGas, // equals to gasPrice for legacy transactions
|
||||
uint256 _maxInclusionFeePerGas, // equals to gasPrice for legacy transactions
|
||||
uint256 _gasLimit,
|
||||
bytes memory _data
|
||||
)
|
||||
public
|
||||
view
|
||||
returns(uint32 typesMask, bool cache)
|
||||
{
|
||||
if (_maxFeePerGas > 0 || _data.length < 4) return (All, false);
|
||||
return (None, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "TestNodeFilterContract",
|
||||
"engine": {
|
||||
"authorityRound": {
|
||||
"params": {
|
||||
"stepDuration": 1,
|
||||
"startStep": 2,
|
||||
"validators": {
|
||||
"contract": "0x0000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"accountStartNonce": "0x0",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x69",
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"transactionPermissionContract": "0xAB5b100cf7C8deFB3c8f3C48474223997A50fB13",
|
||||
"transactionPermissionContractTransition": "1"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"generic": "0xc180"
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x222222"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0xAB5b100cf7C8deFB3c8f3C48474223997A50fB13": {
|
||||
"balance": "1",
|
||||
"constructor": "608060405234801561001057600080fd5b50610370806100206000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063469ab1e31461006757806375d0c0dc1461009a578063a0a8e4601461012a578063e4e3b5e514610155575b600080fd5b34801561007357600080fd5b5061007c610251565b60405180826000191660001916815260200191505060405180910390f35b3480156100a657600080fd5b506100af6102c2565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100ef5780820151818401526020810190506100d4565b50505050905090810190601f16801561011c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013657600080fd5b5061013f6102ff565b6040518082815260200191505060405180910390f35b34801561016157600080fd5b50610224600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610308565b604051808363ffffffff1663ffffffff168152602001821515151581526020019250505060405180910390f35b600061025b6102c2565b6040518082805190602001908083835b602083101515610290578051825260208201915060208101905060208303925061026b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905090565b60606040805190810160405280601681526020017f54585f5045524d495353494f4e5f434f4e545241435400000000000000000000815250905090565b60006004905090565b600080600086118061031b575060048351105b156103305763ffffffff600091509150610338565b600080915091505b975097955050505050505600a165627a7a72305820592b45ee74cc856b6c84f99ed8ddd4790d844a9065a07c7bbfc5dfa05cc394c50029"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "Morden",
|
||||
"engine": {
|
||||
"null": {
|
||||
"params": {}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"accountStartNonce": "0x0",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x2",
|
||||
"registrar" : "0x0000000000000000000000000000000000001337",
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip3607Transition": "0x2"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x00006d6f7264656e",
|
||||
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x2fefd8"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" },
|
||||
"0x71562b71999873DB5b286dF957af199Ec94617F7": {
|
||||
"balance": "1000000000000000000",
|
||||
"nonce": "0",
|
||||
"code": "0xB0B0FACE"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
{
|
||||
"name": "London (test)",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x1BC16D674EC80000",
|
||||
"homesteadTransition": "0x0",
|
||||
"eip100bTransition": "0x0",
|
||||
"difficultyBombDelays": {
|
||||
"0": 5000000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x1",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283Transition": "0x0",
|
||||
"eip1283DisableTransition": "0x0",
|
||||
"eip1283ReenableTransition": "0x0",
|
||||
"eip1344Transition": "0x0",
|
||||
"eip1706Transition": "0x0",
|
||||
"eip1884Transition": "0x0",
|
||||
"eip2028Transition": "0x0",
|
||||
"eip2929Transition": "0x0",
|
||||
"eip2930Transition": "0x0",
|
||||
"eip1559Transition": "0x0",
|
||||
"eip3198Transition": "0x0",
|
||||
"eip3541Transition": "0x0",
|
||||
"eip3529Transition": "0x0",
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3B9ACA00"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000042",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x400000000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
|
||||
"gasLimit": "0x1388"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "ecrecover",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 3000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "sha256",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 60,
|
||||
"word": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "ripemd160",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 600,
|
||||
"word": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "identity",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 15,
|
||||
"word": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"builtin": {
|
||||
"name": "modexp",
|
||||
"activate_at": "0x00",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_add",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 500
|
||||
}
|
||||
}
|
||||
},
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_mul",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 40000
|
||||
}
|
||||
}
|
||||
},
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_const_operations": {
|
||||
"price": 6000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_pairing",
|
||||
"pricing": {
|
||||
"0": {
|
||||
"price": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 100000,
|
||||
"pair": 80000
|
||||
}
|
||||
}
|
||||
},
|
||||
"0": {
|
||||
"info": "EIP 1108 transition",
|
||||
"price": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 45000,
|
||||
"pair": 34000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000009": {
|
||||
"builtin": {
|
||||
"name": "blake2_f",
|
||||
"activate_at": "0x00",
|
||||
"pricing": {
|
||||
"blake2_f": {
|
||||
"gas_per_round": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +54,17 @@
|
|||
"eip1706Transition": 7298030,
|
||||
"eip1884Transition": 7298030,
|
||||
"eip2028Transition": 7298030,
|
||||
"eip2929Transition": 16101500,
|
||||
"eip2930Transition": 16101500,
|
||||
"eip3198Transition": 19040000,
|
||||
"eip3529Transition": 19040000,
|
||||
"eip3541Transition": 19040000,
|
||||
"eip1559Transition": 19040000,
|
||||
"eip1559BaseFeeMaxChangeDenominator": "0x8",
|
||||
"eip1559ElasticityMultiplier": "0x2",
|
||||
"eip1559BaseFeeInitialValue": "0x3b9aca00",
|
||||
"eip1559FeeCollector": "0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92",
|
||||
"eip1559FeeCollectorTransition": 19040000,
|
||||
"registrar": "0x6B53721D4f2Fb9514B85f5C49b197D857e36Cf03",
|
||||
"transactionPermissionContract": "0x7Dd7032AA75A37ea0b150f57F899119C7379A78b",
|
||||
"transactionPermissionContractTransition": 9186425
|
||||
|
@ -69,23 +80,39 @@
|
|||
"gasLimit": "0x989680"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://4716883567b5317aad93ea28e707fad0631fb4aa5ac7c5fbd485380b01d8801c21a8cbf4d6ee3a2c9b2b070a270a49d4a2a0da9e1d47a1f433dafbaf7b2edd06@157.245.92.222:30303",
|
||||
"enode://ab7f6c633ba2dc54795dfd2c739ba7d964f499541c0b8d8ba9d275bd3df1b789470a21a921a469fa515a3dfccc96a434a3fd016a169d88d0043fc6744f34288e@67.205.180.17:30303",
|
||||
"enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@67.205.145.143:30303",
|
||||
"enode://bd75111424c42c349fc255db017ac0be370b37b558627e3bbc41319071ef7642c04cdbd2b674193a99aa35d67a83016ab293b8ab87ed4a4606e69f114ac95535@157.230.185.80:30303",
|
||||
"enode://bd75111424c42c349fc255db017ac0be370b37b558627e3bbc41319071ef7642c04cdbd2b674193a99aa35d67a83016ab293b8ab87ed4a4606e69f114ac95535@161.35.51.60:30303",
|
||||
"enode://ef94ffb10c440dd990c5c4be1c85046f5f7329ba60d23db7a68c8b91b6a721081f8190369f3a32f3c02d213127b2066eb42ee0444998d354ba0923378522acb3@161.35.62.72:30303",
|
||||
"enode://4a0eadf22d6a37c5596fd2df2a53a26a5b59dd863e67246ab94e6a81b31765e08d9f70a4dd9683221e63cc2120c8a808a6a457455bd658bdf49c688c62db2011@51.81.244.170:30303",
|
||||
"enode://e75a1e9f080bd6012b39321c0f2d984567172625280b3e7362e962a42578c5e79c847b3eb83aa7e2a4cdeefbfadf0c36ed2719cad1d5e6377ccd6ebe314cc6bc@64.227.97.130:30303",
|
||||
"enode://6674773f7aac78d5527fa90c847dcbca198de4081306406a8fec5c15f7a2e141362344041291dd10d0aafa7706a3d8f21a08b6f6834a5b1aab9cccd8ca35ccee@143.110.226.15:30303",
|
||||
"enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@134.122.24.231:30303",
|
||||
"enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@67.205.145.143:30303",
|
||||
"enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@162.243.164.98:30303",
|
||||
"enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@167.99.4.175:30303",
|
||||
"enode://da2449aaba873c40c6daf764de55f4b9eae24c4738daec893ef95b6ada96463c6b9624f8e376e1073d21dd820c5bb361e14575121b09bbd7735b6b556ee1b768@67.205.176.117:30303",
|
||||
"enode://a20c13b1712d32028a277958346a5c29350e8a3e32d40de43a62cb35baa99f96f274960591e46be5a643be7ee77a15d6a4963170460156a77abcf500f0ba0ff0@104.237.150.151:30303",
|
||||
"enode://f372b16932a4ee5b6be947556bcca1cf57e498267dd78a7a643a87514a0a5ef4f112cb6934aab5775d3e8940ba535e8f53dfa704e162a72970de61e6ef9fd9aa@45.79.158.26:30303",
|
||||
"enode://fe9720c93e6335b8cacffa10df594c8c166208fa4be8dcb9275788e54111ae88899022fa9c358f2d0029ee57c2223a7fbc97eb06b294422d35ef796a49d87bff@94.237.98.201:30303",
|
||||
"enode://6d12181aa8527251dd8f9d37a2ff7eadb46f2a90c69f2282352ac7889b105d6b5787a532facee656b29599ee1ee51eb5b1eb01d2a17190e32a6cbe6dfc996828@45.79.158.8:30303",
|
||||
"enode://389a625160876776946bfea5a6ce4f4c761bd2062cf8e45e510da77595399ee50a802060868d9bf4580431fc2248cadc9ce61826b3513e090bd1cdd4ce11a9d8@161.97.172.191:30303",
|
||||
"enode://d086bfbe0d15e841e403695c151920459261dd5d5f259858b32727e2bc64d92f48bdad3cc0120703dbb0e2abd2f51c0459cff517bfa16e683ca27018d82a6dcf@66.175.215.67:30303",
|
||||
"enode://540a0bc258ba93e6fafc238f49eca0a2032b5d40b79c077dc9b9a304fd636af4167b638eb0f80aa455f5da1cf49b76c881f651ed301a1e28d6855a8a3fbe21a0@167.71.174.1:30303",
|
||||
"enode://1ceea9d3fb22247edf85102f1e78cd31c2f330ace6ac2789c82766a232d56d7c3c1b2aeb504f2f761de754da22e7dfc5bdde3b00b8b98d1d003f6dd81612f8b3@66.175.211.178:30303",
|
||||
"enode://4175e9ffd9ac9819c9c596a60b7748cc1c1846cf7e8db47ee97f8aa57e42e8cb3dad4201726498d34af94505b2c1429f9d3a508594c521080e8cd1a3fa24a3d5@37.120.245.155:30303",
|
||||
"enode://b5eba653df9c583238ea238ca7cadf5d2746f1b4da81a8cfb2c1b600f62fe37df000fa5b5292059f74faa6bbf5af01b3b81f99284a1fbd5c0971d74db7dc4a34@66.175.213.149:30303",
|
||||
"enode://2a8b64e96da7e67e525f04a157a0016b886dfb2d02553501abd0326b7b061aace7e92ad87c1225dc7d261b05e7886391552c812b386451597bff4b040eb43bec@173.212.236.163:30303",
|
||||
"enode://5f187ae73b07db889c91e8955619b1e6b799696a4b7aab306f7c500a2ec4c7f66dfbea8ac28bde65100653a2fe84b96f2079aed2d61871e06b5a1e32c0f021af@45.79.150.105:30303",
|
||||
"enode://22e442bf7b7fa9bb5960344ef5aa907b920a931bce83e14620b0378318b7eb73753f7245f0a8252590a71ad9568bcfbb9e5f03bd88ab3feb9c1096227bb8704a@168.119.136.44:30303",
|
||||
"enode://ef98bc3c9195b9f27312ac646edb6d0096b04c983f93864c30b8f2b20c699ec974a7066cfae090832679e497d23655e0e315a2c96da4a27d75cc4693e6335bba@192.155.90.129:30303",
|
||||
"enode://de1ab49beedda656976a8fcb01f91ebdb474178fd46e5ce87cf22f0eb90bc3a6721d619ec90c4a6453770a2c24a4bdbc4ef8b8111ffd49f491eb84016a3842d6@54.217.41.94:30303",
|
||||
"enode://ba04a77c7c8ac0fdd325de91536c33bce3b71095de563aafc72e6ac4111ebf093570c7bdba48b06cc83b0af5596f72fc32563547160e067fcb45a1786b8f7150@45.56.105.53:30303",
|
||||
"enode://56510b2d296000427e56eb0016d8454998c16347ec2c4ffed84cb82a996707de40ca2b9ea13c8796b4230b4c19ce46f844720ded93135d710b7bbc7352a061d3@50.35.89.213:30304",
|
||||
"enode://a68b3f3f58ea56dcc70450d371bf0b83363d74cbfdb5f982be00536ae3168aa679c7e7e93bd9ffe34b59527173d73e0ebed0a105c095af2ee16bd1cc66103c80@69.164.215.62:30303",
|
||||
"enode://e8c7a0db430429bb374c981438c0dbd95e565088a483388aa46d8377a3bd62f02cd83d7e2c7e5fc77606141bfef29d23d4285a7c1d9b7e743cf3029314506df7@80.240.16.221:30303",
|
||||
"enode://2cde5ae04ed57bba5bac8311a97be056838d5304bc3bcee698066e5fc532e846f785198f87e8b84b57b03622a22aac5dd2853c5203d1ece2c9f25b48487d145b@149.28.57.8:30303",
|
||||
"enode://90b0a0e74a9a1ad258531b4ceec25587d8b52ff2cfb36206a34bf6ba1a8d21b2abd20da13260102508a2ac67afbeb2d2ab7a5e9d6bea3bce845cd81e655585cc@45.77.110.159:30303"
|
||||
"enode://80c8f6f27f80ba91830002a8ca64771f6baf440fd134e88fbecae3a67c8bc58722d624cecbd6439e1a2d28fbd0297d489fdaa40b10c2f3e07fee1913d52b3e30@45.79.185.92:30303",
|
||||
"enode://da2449aaba873c40c6daf764de55f4b9eae24c4738daec893ef95b6ada96463c6b9624f8e376e1073d21dd820c5bb361e14575121b09bbd7735b6b556ee1b768@67.205.176.117:30303",
|
||||
"enode://481e43a8e30cdfecfe3159dde960d9e65347c3e8c64dcedea87922df875e4d47a813f53c012920b6754e43cde47302cdfb120fd409b6aa2b47c48e391494c7f5@173.255.233.100:30303",
|
||||
"enode://90b0a0e74a9a1ad258531b4ceec25587d8b52ff2cfb36206a34bf6ba1a8d21b2abd20da13260102508a2ac67afbeb2d2ab7a5e9d6bea3bce845cd81e655585cc@45.77.110.159:30303",
|
||||
"enode://6012c883efeee664847a48784459980176a22f31bc98c2aae30011ad7ef0b44011364a0a9ae5eb056db1f052cf3556757bd97485677bbaf1781b131e43204971@69.164.222.63:30303",
|
||||
"enode://5bc43a57273eb4012b59ce268f986cbeeb5f0f878aa25e3d2d71d9b7ff64029a9dd25a84303f80820a78d83ff3a2c570988d0fc68a17d355a98c20c0784aa14d@8.9.5.108:30303",
|
||||
"enode://89e046a4f10c64265941789b2e3be900adf5132ced13756aeea126cf59b516445ed8053b600aa764860f1aad552f4f4f3b4250c59b3b8a84ead3d3527c005606@172.104.24.215:30303",
|
||||
"enode://ab7f6c633ba2dc54795dfd2c739ba7d964f499541c0b8d8ba9d275bd3df1b789470a21a921a469fa515a3dfccc96a434a3fd016a169d88d0043fc6744f34288e@67.205.180.17:30303",
|
||||
"enode://6674773f7aac78d5527fa90c847dcbca198de4081306406a8fec5c15f7a2e141362344041291dd10d0aafa7706a3d8f21a08b6f6834a5b1aab9cccd8ca35ccee@143.110.226.15:30303",
|
||||
"enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@167.99.4.175:30303",
|
||||
"enode://7aa4c137b1ec078f2df3c17552e23c7213662819132821ed3aaa42f0212cb889dbb21211f9c5912c68fce577ab7fc99b0a47c0cb469ec0ad29c0acd9ce297659@45.33.84.107:30303",
|
||||
"enode://e026b1a68e8a19106d14effc0df66050c494e10a6b8a4e9f6fd196d95306d7062d129a8c9510ffdbeaf3fe0154b884c116a0e77aec876c368e507de3420fba05@149.28.32.225:30303",
|
||||
"enode://0a978bd436b850f61e31778fbbeb3e0182f91bb98a30c073674c741c182611e71842333c098d3db5108f06cd589c3a8341172e34be0421fa66d82f0dd83d8ae1@51.81.244.170:30303",
|
||||
"enode://75f05df1e5a3094ed2c9df36f122b95852206c52288f777982503946d5b273c7ffd8bb06ad60a0df7a31510906d4090c7bd5fd9bcb04a5b4ac1825a2b7212f32@45.63.18.245:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0x0000000000000000000000000000000000000005": {
|
||||
|
@ -98,6 +125,12 @@
|
|||
"divisor": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"16101500": {
|
||||
"info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (May 17, 2021, ~10:00 am UTC)",
|
||||
"price": {
|
||||
"modexp2565": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
[
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "contractNameHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "contractName",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "contractVersion",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "maxFeePerGas",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "maxPriorityFeePerGas",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "gasLimit",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "allowedTxTypes",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
|
@ -1 +1 @@
|
|||
Subproject commit ff68495eb56c382b2ddcea4020259e106353b874
|
||||
Subproject commit e20d7f39aae1e33394ae6b94590d15083e224fa5
|
|
@ -36,7 +36,7 @@
|
|||
],
|
||||
"executive": [
|
||||
{
|
||||
"path": "res/json_tests/VMTests"
|
||||
"path": "res/json_tests/LegacyTests/Constantinople/VMTests"
|
||||
}
|
||||
],
|
||||
"transaction": [
|
||||
|
|
|
@ -139,7 +139,8 @@ impl ExecutedBlock {
|
|||
difficulty: self.header.difficulty().clone(),
|
||||
last_hashes: self.last_hashes.clone(),
|
||||
gas_used: self.receipts.last().map_or(U256::zero(), |r| r.gas_used),
|
||||
gas_limit: self.header.gas_limit().clone(),
|
||||
gas_limit: *self.header.gas_limit(),
|
||||
base_fee: self.header.base_fee(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,6 +197,9 @@ impl<'x> OpenBlock<'x> {
|
|||
.header
|
||||
.set_timestamp(engine.open_block_header_timestamp(parent.timestamp()));
|
||||
r.block.header.set_extra_data(extra_data);
|
||||
r.block
|
||||
.header
|
||||
.set_base_fee(engine.calculate_base_fee(parent));
|
||||
|
||||
let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit);
|
||||
let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target);
|
||||
|
@ -227,6 +231,11 @@ impl<'x> OpenBlock<'x> {
|
|||
self.block.header.set_gas_limit(U256::max_value());
|
||||
}
|
||||
|
||||
/// Set block gas limit.
|
||||
pub fn set_gas_limit(&mut self, gas_limit: U256) {
|
||||
self.block.header.set_gas_limit(gas_limit);
|
||||
}
|
||||
|
||||
// t_nb 8.4 Add an uncle to the block, if possible.
|
||||
///
|
||||
/// NOTE Will check chain constraints and the uncle number but will NOT check
|
||||
|
@ -559,11 +568,9 @@ pub(crate) fn enact(
|
|||
)?;
|
||||
|
||||
if let Some(ref s) = trace_state {
|
||||
let env = b.env_info();
|
||||
let root = s.root();
|
||||
let author_balance = s.balance(&env.author)?;
|
||||
let author_balance = s.balance(&b.header.author())?;
|
||||
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
|
||||
b.block.header.number(), root, env.author, author_balance);
|
||||
b.block.header.number(), s.root(), b.header.author(), author_balance);
|
||||
}
|
||||
|
||||
// t_nb 8.2 transfer all field from current header to OpenBlock header that we created
|
||||
|
@ -632,7 +639,7 @@ mod tests {
|
|||
last_hashes: Arc<LastHashes>,
|
||||
factories: Factories,
|
||||
) -> Result<LockedBlock, Error> {
|
||||
let block = Unverified::from_rlp(block_bytes)?;
|
||||
let block = Unverified::from_rlp(block_bytes, engine.params().eip1559_transition)?;
|
||||
let header = block.header;
|
||||
let transactions: Result<Vec<_>, Error> = block
|
||||
.transactions
|
||||
|
@ -689,7 +696,8 @@ mod tests {
|
|||
last_hashes: Arc<LastHashes>,
|
||||
factories: Factories,
|
||||
) -> Result<SealedBlock, Error> {
|
||||
let header = Unverified::from_rlp(block_bytes.clone())?.header;
|
||||
let header =
|
||||
Unverified::from_rlp(block_bytes.clone(), engine.params().eip1559_transition)?.header;
|
||||
Ok(enact_bytes(
|
||||
block_bytes,
|
||||
engine,
|
||||
|
@ -846,7 +854,7 @@ mod tests {
|
|||
|
||||
let bytes = e.rlp_bytes();
|
||||
assert_eq!(bytes, orig_bytes);
|
||||
let uncles = view!(BlockView, &bytes).uncles();
|
||||
let uncles = view!(BlockView, &bytes).uncles(engine.params().eip1559_transition);
|
||||
assert_eq!(uncles[1].extra_data(), b"uncle2");
|
||||
|
||||
let db = e.drain().state.drop().1;
|
||||
|
|
|
@ -21,6 +21,7 @@ use ethereum_types::H256;
|
|||
use itertools::Itertools;
|
||||
use memory_cache::MemoryLruCache;
|
||||
use parking_lot::RwLock;
|
||||
use types::BlockNumber;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
/// Recently seen bad blocks.
|
||||
|
@ -38,8 +39,8 @@ impl Default for BadBlocks {
|
|||
|
||||
impl BadBlocks {
|
||||
/// Reports given RLP as invalid block.
|
||||
pub fn report(&self, raw: Bytes, message: String) {
|
||||
match Unverified::from_rlp(raw) {
|
||||
pub fn report(&self, raw: Bytes, message: String, eip1559_transition: BlockNumber) {
|
||||
match Unverified::from_rlp(raw, eip1559_transition) {
|
||||
Ok(unverified) => {
|
||||
error!(
|
||||
target: "client",
|
||||
|
@ -69,14 +70,14 @@ impl BadBlocks {
|
|||
}
|
||||
|
||||
/// Returns a list of recently detected bad blocks with error descriptions.
|
||||
pub fn bad_blocks(&self) -> Vec<(Unverified, String)> {
|
||||
pub fn bad_blocks(&self, eip1559_transition: BlockNumber) -> Vec<(Unverified, String)> {
|
||||
self.last_blocks
|
||||
.read()
|
||||
.backstore()
|
||||
.iter()
|
||||
.map(|(_k, (unverified, message))| {
|
||||
(
|
||||
Unverified::from_rlp(unverified.bytes.clone())
|
||||
Unverified::from_rlp(unverified.bytes.clone(), eip1559_transition)
|
||||
.expect("Bytes coming from UnverifiedBlock so decodable; qed"),
|
||||
message.clone(),
|
||||
)
|
||||
|
|
|
@ -355,7 +355,11 @@ impl Importer {
|
|||
.accrue_block(&header, transactions_len);
|
||||
}
|
||||
Err(err) => {
|
||||
self.bad_blocks.report(bytes, format!("{:?}", err));
|
||||
self.bad_blocks.report(
|
||||
bytes,
|
||||
format!("{:?}", err),
|
||||
self.engine.params().eip1559_transition,
|
||||
);
|
||||
invalid_blocks.insert(hash);
|
||||
}
|
||||
}
|
||||
|
@ -484,6 +488,52 @@ impl Importer {
|
|||
.epoch_transition(parent.number(), *header.parent_hash())
|
||||
.is_some();
|
||||
|
||||
if header.number() >= engine.params().validate_service_transactions_transition {
|
||||
// Check if zero gas price transactions are certified to be service transactions
|
||||
// using the Certifier contract. If they are not certified, the block is treated as invalid.
|
||||
let service_transaction_checker = self.miner.service_transaction_checker();
|
||||
if service_transaction_checker.is_some() {
|
||||
match service_transaction_checker.unwrap().refresh_cache(client) {
|
||||
Ok(true) => {
|
||||
trace!(target: "client", "Service transaction cache was refreshed successfully");
|
||||
}
|
||||
Ok(false) => {
|
||||
trace!(target: "client", "Registrar or/and service transactions contract does not exist");
|
||||
}
|
||||
Err(e) => {
|
||||
error!(target: "client", "Error occurred while refreshing service transaction cache: {}", e)
|
||||
}
|
||||
};
|
||||
};
|
||||
for t in &block.transactions {
|
||||
if t.has_zero_gas_price() {
|
||||
match self.miner.service_transaction_checker() {
|
||||
None => {
|
||||
let e = "Service transactions are not allowed. You need to enable Certifier contract.";
|
||||
warn!(target: "client", "Service tx checker error: {:?}", e);
|
||||
bail!(e);
|
||||
}
|
||||
Some(ref checker) => match checker.check(client, &t) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
let e = format!(
|
||||
"Service transactions are not allowed for the sender {:?}",
|
||||
t.sender()
|
||||
);
|
||||
warn!(target: "client", "Service tx checker error: {:?}", e);
|
||||
bail!(e);
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(target: "client", "Unable to verify service transaction: {:?}", e);
|
||||
warn!(target: "client", "Service tx checker error: {:?}", e);
|
||||
bail!(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// t_nb 8.0 Block enacting. Execution of transactions.
|
||||
let enact_result = enact_verified(
|
||||
block,
|
||||
|
@ -629,7 +679,7 @@ impl Importer {
|
|||
let header = chain
|
||||
.block_header_data(&hash)
|
||||
.expect("Best block is in the database; qed")
|
||||
.decode()
|
||||
.decode(self.engine.params().eip1559_transition)
|
||||
.expect("Stored block header is valid RLP; qed");
|
||||
let details = chain
|
||||
.block_details(&hash)
|
||||
|
@ -767,6 +817,7 @@ impl Importer {
|
|||
last_hashes: client.build_last_hashes(header.parent_hash()),
|
||||
gas_used: U256::default(),
|
||||
gas_limit: u64::max_value().into(),
|
||||
base_fee: header.base_fee(),
|
||||
};
|
||||
|
||||
let call = move |addr, data| {
|
||||
|
@ -905,7 +956,12 @@ impl Client {
|
|||
}
|
||||
|
||||
let gb = spec.genesis_block();
|
||||
let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone()));
|
||||
let chain = Arc::new(BlockChain::new(
|
||||
config.blockchain.clone(),
|
||||
&gb,
|
||||
db.clone(),
|
||||
spec.params().eip1559_transition,
|
||||
));
|
||||
let tracedb = RwLock::new(TraceDB::new(
|
||||
config.tracing.clone(),
|
||||
db.clone(),
|
||||
|
@ -1144,6 +1200,11 @@ impl Client {
|
|||
last_hashes: self.build_last_hashes(&header.parent_hash()),
|
||||
gas_used: U256::default(),
|
||||
gas_limit: header.gas_limit(),
|
||||
base_fee: if header.number() >= self.engine.params().eip1559_transition {
|
||||
Some(header.base_fee())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1646,7 +1707,9 @@ impl Client {
|
|||
BlockId::Number(number) if number == self.chain.read().best_block_number() => {
|
||||
Some(self.chain.read().best_block_header())
|
||||
}
|
||||
_ => self.block_header(id).and_then(|h| h.decode().ok()),
|
||||
_ => self
|
||||
.block_header(id)
|
||||
.and_then(|h| h.decode(self.engine.params().eip1559_transition).ok()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1673,6 +1736,7 @@ impl snapshot::DatabaseRestore for Client {
|
|||
self.config.blockchain.clone(),
|
||||
&[],
|
||||
db.clone(),
|
||||
self.engine.params().eip1559_transition,
|
||||
));
|
||||
*tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone());
|
||||
Ok(())
|
||||
|
@ -1884,9 +1948,11 @@ impl ImportBlock for Client {
|
|||
}
|
||||
// t_nb 2.5 if block is not okay print error. we only care about block errors (not import errors)
|
||||
Err((Some(block), EthcoreError(EthcoreErrorKind::Block(err), _))) => {
|
||||
self.importer
|
||||
.bad_blocks
|
||||
.report(block.bytes, err.to_string());
|
||||
self.importer.bad_blocks.report(
|
||||
block.bytes,
|
||||
err.to_string(),
|
||||
self.engine.params().eip1559_transition,
|
||||
);
|
||||
bail!(EthcoreErrorKind::Block(err))
|
||||
}
|
||||
Err((None, EthcoreError(EthcoreErrorKind::Block(err), _))) => {
|
||||
|
@ -1934,6 +2000,12 @@ impl Call for Client {
|
|||
last_hashes: self.build_last_hashes(header.parent_hash()),
|
||||
gas_used: U256::default(),
|
||||
gas_limit: U256::max_value(),
|
||||
//if gas pricing is not defined, force base_fee to zero
|
||||
base_fee: if transaction.effective_gas_price(header.base_fee()).is_zero() {
|
||||
Some(0.into())
|
||||
} else {
|
||||
header.base_fee()
|
||||
},
|
||||
};
|
||||
let machine = self.engine.machine();
|
||||
|
||||
|
@ -1954,12 +2026,20 @@ impl Call for Client {
|
|||
last_hashes: self.build_last_hashes(header.parent_hash()),
|
||||
gas_used: U256::default(),
|
||||
gas_limit: U256::max_value(),
|
||||
base_fee: header.base_fee(),
|
||||
};
|
||||
|
||||
let mut results = Vec::with_capacity(transactions.len());
|
||||
let machine = self.engine.machine();
|
||||
|
||||
for &(ref t, analytics) in transactions {
|
||||
//if gas pricing is not defined, force base_fee to zero
|
||||
if t.effective_gas_price(header.base_fee()).is_zero() {
|
||||
env_info.base_fee = Some(0.into());
|
||||
} else {
|
||||
env_info.base_fee = header.base_fee()
|
||||
}
|
||||
|
||||
let ret = Self::do_virtual_call(machine, &env_info, state, t, analytics)?;
|
||||
env_info.gas_used = ret.cumulative_gas_used;
|
||||
results.push(ret);
|
||||
|
@ -1986,6 +2066,11 @@ impl Call for Client {
|
|||
last_hashes: self.build_last_hashes(header.parent_hash()),
|
||||
gas_used: U256::default(),
|
||||
gas_limit: max,
|
||||
base_fee: if t.effective_gas_price(header.base_fee()).is_zero() {
|
||||
Some(0.into())
|
||||
} else {
|
||||
header.base_fee()
|
||||
},
|
||||
};
|
||||
|
||||
(init, max, env_info)
|
||||
|
@ -2069,7 +2154,9 @@ impl EngineInfo for Client {
|
|||
|
||||
impl BadBlocks for Client {
|
||||
fn bad_blocks(&self) -> Vec<(Unverified, String)> {
|
||||
self.importer.bad_blocks.bad_blocks()
|
||||
self.importer
|
||||
.bad_blocks
|
||||
.bad_blocks(self.engine.params().eip1559_transition)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2344,11 +2431,15 @@ impl BlockChainClient for Client {
|
|||
Some(keys)
|
||||
}
|
||||
|
||||
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> {
|
||||
fn block_transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> {
|
||||
self.transaction_address(id)
|
||||
.and_then(|address| self.chain.read().transaction(&address))
|
||||
}
|
||||
|
||||
fn queued_transaction(&self, hash: H256) -> Option<Arc<VerifiedTransaction>> {
|
||||
self.importer.miner.transaction(&hash)
|
||||
}
|
||||
|
||||
fn uncle(&self, id: UncleId) -> Option<encoded::Header> {
|
||||
let index = id.position;
|
||||
self.block_body(id.block)
|
||||
|
@ -2363,6 +2454,7 @@ impl BlockChainClient for Client {
|
|||
let chain = self.chain.read();
|
||||
let number = chain.block_number(&hash)?;
|
||||
let body = chain.block_body(&hash)?;
|
||||
let header = chain.block_header_data(&hash)?;
|
||||
let mut receipts = chain.block_receipts(&hash)?.receipts;
|
||||
receipts.truncate(address.index + 1);
|
||||
|
||||
|
@ -2375,6 +2467,11 @@ impl BlockChainClient for Client {
|
|||
.into_iter()
|
||||
.map(|receipt| receipt.logs.len())
|
||||
.sum::<usize>();
|
||||
let base_fee = if number >= self.engine().params().eip1559_transition {
|
||||
Some(header.base_fee())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let receipt = transaction_receipt(
|
||||
self.engine().machine(),
|
||||
|
@ -2382,6 +2479,7 @@ impl BlockChainClient for Client {
|
|||
receipt,
|
||||
gas_used,
|
||||
no_of_logs,
|
||||
base_fee,
|
||||
);
|
||||
Some(receipt)
|
||||
}
|
||||
|
@ -2393,7 +2491,13 @@ impl BlockChainClient for Client {
|
|||
let receipts = chain.block_receipts(&hash)?;
|
||||
let number = chain.block_number(&hash)?;
|
||||
let body = chain.block_body(&hash)?;
|
||||
let header = chain.block_header_data(&hash)?;
|
||||
let engine = self.engine.clone();
|
||||
let base_fee = if number >= engine.params().eip1559_transition {
|
||||
Some(header.base_fee())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut gas_used = 0.into();
|
||||
let mut no_of_logs = 0;
|
||||
|
@ -2410,6 +2514,7 @@ impl BlockChainClient for Client {
|
|||
receipt,
|
||||
gas_used,
|
||||
no_of_logs,
|
||||
base_fee,
|
||||
);
|
||||
gas_used = result.cumulative_gas_used;
|
||||
no_of_logs += result.logs.len();
|
||||
|
@ -2650,8 +2755,11 @@ impl BlockChainClient for Client {
|
|||
}
|
||||
|
||||
fn uncle_extra_info(&self, id: UncleId) -> Option<BTreeMap<String, String>> {
|
||||
self.uncle(id)
|
||||
.and_then(|h| h.decode().map(|dh| self.engine.extra_info(&dh)).ok())
|
||||
self.uncle(id).and_then(|h| {
|
||||
h.decode(self.engine.params().eip1559_transition)
|
||||
.map(|dh| self.engine.extra_info(&dh))
|
||||
.ok()
|
||||
})
|
||||
}
|
||||
|
||||
fn pruning_info(&self) -> PruningInfo {
|
||||
|
@ -2714,6 +2822,10 @@ impl BlockChainClient for Client {
|
|||
fn registrar_address(&self) -> Option<Address> {
|
||||
self.registrar_address.clone()
|
||||
}
|
||||
|
||||
fn state_data(&self, hash: &H256) -> Option<Bytes> {
|
||||
self.state_db.read().journal_db().state(hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl IoClient for Client {
|
||||
|
@ -2833,7 +2945,9 @@ impl ReopenBlock for Client {
|
|||
let uncle = chain
|
||||
.block_header_data(&h)
|
||||
.expect("find_uncle_hashes only returns hashes for existing headers; qed");
|
||||
let uncle = uncle.decode().expect("decoding failure");
|
||||
let uncle = uncle
|
||||
.decode(self.engine.params().eip1559_transition)
|
||||
.expect("decoding failure");
|
||||
block.push_uncle(uncle).expect(
|
||||
"pushing up to maximum_uncle_count;
|
||||
push_uncle is not ok only if more than maximum_uncle_count is pushed;
|
||||
|
@ -2885,7 +2999,10 @@ impl PrepareOpenBlock for Client {
|
|||
.take(engine.maximum_uncle_count(open_block.header.number()))
|
||||
.foreach(|h| {
|
||||
open_block
|
||||
.push_uncle(h.decode().expect("decoding failure"))
|
||||
.push_uncle(
|
||||
h.decode(engine.params().eip1559_transition)
|
||||
.expect("decoding failure"),
|
||||
)
|
||||
.expect(
|
||||
"pushing maximum_uncle_count;
|
||||
open_block was just created;
|
||||
|
@ -2921,6 +3038,7 @@ impl ImportSealedBlock for Client {
|
|||
self.importer.bad_blocks.report(
|
||||
block.rlp_bytes(),
|
||||
format!("Detected an issue with locally sealed block: {}", e),
|
||||
self.engine.params().eip1559_transition,
|
||||
);
|
||||
return Err(e.into());
|
||||
}
|
||||
|
@ -3031,11 +3149,11 @@ impl super::traits::EngineClient for Client {
|
|||
}
|
||||
|
||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
|
||||
BlockChainClient::block_number(self, id)
|
||||
<dyn BlockChainClient>::block_number(self, id)
|
||||
}
|
||||
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
|
||||
BlockChainClient::block_header(self, id)
|
||||
<dyn BlockChainClient>::block_header(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3151,7 +3269,8 @@ impl ImportExportBlocks for Client {
|
|||
};
|
||||
|
||||
let do_import = |bytes: Vec<u8>| {
|
||||
let block = Unverified::from_rlp(bytes).map_err(|_| "Invalid block rlp")?;
|
||||
let block = Unverified::from_rlp(bytes, self.engine.params().eip1559_transition)
|
||||
.map_err(|_| "Invalid block rlp")?;
|
||||
let number = block.header.number();
|
||||
while self.queue_info().is_full() {
|
||||
std::thread::sleep(Duration::from_secs(1));
|
||||
|
@ -3225,6 +3344,7 @@ fn transaction_receipt(
|
|||
receipt: TypedReceipt,
|
||||
prior_gas_used: U256,
|
||||
prior_no_of_logs: usize,
|
||||
base_fee: Option<U256>,
|
||||
) -> LocalizedReceipt {
|
||||
let sender = tx.sender();
|
||||
let transaction_hash = tx.hash();
|
||||
|
@ -3276,6 +3396,7 @@ fn transaction_receipt(
|
|||
.collect(),
|
||||
log_bloom: receipt.log_bloom,
|
||||
outcome: receipt.outcome.clone(),
|
||||
effective_gas_price: tx.effective_gas_price(base_fee),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3604,7 +3725,7 @@ mod tests {
|
|||
});
|
||||
|
||||
// when
|
||||
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1);
|
||||
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1, None);
|
||||
|
||||
// then
|
||||
assert_eq!(
|
||||
|
@ -3645,6 +3766,7 @@ mod tests {
|
|||
],
|
||||
log_bloom: Default::default(),
|
||||
outcome: TransactionOutcome::StateRoot(state_root),
|
||||
effective_gas_price: Default::default(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,8 @@ impl<'a> EvmTestClient<'a> {
|
|||
Some(ethereum::new_byzantium_to_constantinoplefixat5_test())
|
||||
}
|
||||
ForkSpec::Berlin => Some(ethereum::new_berlin_test()),
|
||||
ForkSpec::London => Some(ethereum::new_london_test()),
|
||||
ForkSpec::BerlinToLondonAt5 => Some(ethereum::new_berlin_to_london_test()),
|
||||
ForkSpec::FrontierToHomesteadAt5
|
||||
| ForkSpec::HomesteadToDaoAt5
|
||||
| ForkSpec::HomesteadToEIP150At5
|
||||
|
@ -248,6 +250,7 @@ impl<'a> EvmTestClient<'a> {
|
|||
last_hashes: Arc::new([H256::default(); 256].to_vec()),
|
||||
gas_used: 0.into(),
|
||||
gas_limit: *genesis.gas_limit(),
|
||||
base_fee: genesis.base_fee(),
|
||||
};
|
||||
self.call_envinfo(params, tracer, vm_tracer, info)
|
||||
}
|
||||
|
|
|
@ -322,7 +322,7 @@ impl TestBlockChainClient {
|
|||
rlp.append(&header);
|
||||
rlp.append_raw(&txs, 1);
|
||||
rlp.append_raw(uncles.as_raw(), 1);
|
||||
let unverified = Unverified::from_rlp(rlp.out()).unwrap();
|
||||
let unverified = Unverified::from_rlp(rlp.out(), BlockNumber::max_value()).unwrap();
|
||||
self.import_block(unverified).unwrap();
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ impl TestBlockChainClient {
|
|||
let mut header: Header = self
|
||||
.block_header(BlockId::Number(n))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.decode(BlockNumber::max_value())
|
||||
.expect("decoding failed");
|
||||
header.set_parent_hash(H256::from_low_u64_be(42));
|
||||
let mut rlp = RlpStream::new_list(3);
|
||||
|
@ -550,7 +550,7 @@ impl BlockInfo for TestBlockChainClient {
|
|||
fn best_block_header(&self) -> Header {
|
||||
self.block_header(BlockId::Hash(self.chain_info().best_block_hash))
|
||||
.expect("Best block always has header.")
|
||||
.decode()
|
||||
.decode(BlockNumber::max_value())
|
||||
.expect("decoding failed")
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,7 @@ impl ImportBlock for TestBlockChainClient {
|
|||
if number > 0 {
|
||||
match self.blocks.read().get(header.parent_hash()) {
|
||||
Some(parent) => {
|
||||
let parent = view!(BlockView, parent).header();
|
||||
let parent = view!(BlockView, parent).header(BlockNumber::max_value());
|
||||
if parent.number() != (header.number() - 1) {
|
||||
panic!("Unexpected block parent");
|
||||
}
|
||||
|
@ -638,7 +638,7 @@ impl ImportBlock for TestBlockChainClient {
|
|||
*self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone();
|
||||
n -= 1;
|
||||
parent_hash = view!(BlockView, &self.blocks.read()[&parent_hash])
|
||||
.header()
|
||||
.header(BlockNumber::max_value())
|
||||
.parent_hash()
|
||||
.clone();
|
||||
}
|
||||
|
@ -720,7 +720,7 @@ impl StateClient for TestBlockChainClient {
|
|||
|
||||
impl EngineInfo for TestBlockChainClient {
|
||||
fn engine(&self) -> &dyn EthEngine {
|
||||
unimplemented!()
|
||||
&*self.spec.engine
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -809,9 +809,12 @@ impl BlockChainClient for TestBlockChainClient {
|
|||
) -> Option<Vec<H256>> {
|
||||
None
|
||||
}
|
||||
fn transaction(&self, _id: TransactionId) -> Option<LocalizedTransaction> {
|
||||
fn block_transaction(&self, _id: TransactionId) -> Option<LocalizedTransaction> {
|
||||
None // Simple default.
|
||||
}
|
||||
fn queued_transaction(&self, _hash: H256) -> Option<Arc<VerifiedTransaction>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn uncle(&self, _id: UncleId) -> Option<encoded::Header> {
|
||||
None // Simple default.
|
||||
|
@ -879,7 +882,7 @@ impl BlockChainClient for TestBlockChainClient {
|
|||
|
||||
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>> {
|
||||
self.block(id)
|
||||
.map(|block| block.view().header())
|
||||
.map(|block| block.view().header(BlockNumber::max_value()))
|
||||
.map(|header| self.spec.engine.extra_info(&header))
|
||||
}
|
||||
|
||||
|
@ -1075,6 +1078,29 @@ impl BlockChainClient for TestBlockChainClient {
|
|||
fn registrar_address(&self) -> Option<Address> {
|
||||
None
|
||||
}
|
||||
|
||||
fn state_data(&self, hash: &H256) -> Option<Bytes> {
|
||||
let begins_with_f =
|
||||
H256::from_str("f000000000000000000000000000000000000000000000000000000000000000")
|
||||
.unwrap();
|
||||
if *hash > begins_with_f {
|
||||
let mut rlp = RlpStream::new();
|
||||
rlp.append(&hash.clone());
|
||||
return Some(rlp.out());
|
||||
} else if *hash
|
||||
== H256::from_str("000000000000000000000000000000000000000000000000000000000000000a")
|
||||
.unwrap()
|
||||
{
|
||||
// for basic `return_node_data` tests
|
||||
return Some(vec![0xaa, 0xaa]);
|
||||
} else if *hash
|
||||
== H256::from_str("000000000000000000000000000000000000000000000000000000000000000c")
|
||||
.unwrap()
|
||||
{
|
||||
return Some(vec![0xcc]);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl IoClient for TestBlockChainClient {
|
||||
|
@ -1144,11 +1170,11 @@ impl super::traits::EngineClient for TestBlockChainClient {
|
|||
}
|
||||
|
||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
|
||||
BlockChainClient::block_number(self, id)
|
||||
<dyn BlockChainClient>::block_number(self, id)
|
||||
}
|
||||
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
|
||||
BlockChainClient::block_header(self, id)
|
||||
<dyn BlockChainClient>::block_header(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ use types::{
|
|||
pruning_info::PruningInfo,
|
||||
receipt::LocalizedReceipt,
|
||||
trace_filter::Filter as TraceFilter,
|
||||
transaction::{self, Action, LocalizedTransaction, SignedTransaction},
|
||||
transaction::{self, Action, LocalizedTransaction, SignedTransaction, TypedTxId},
|
||||
BlockNumber,
|
||||
};
|
||||
use vm::LastHashes;
|
||||
|
@ -312,7 +312,10 @@ pub trait BlockChainClient:
|
|||
) -> Option<Vec<H256>>;
|
||||
|
||||
/// Get transaction with given hash.
|
||||
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>;
|
||||
fn block_transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>;
|
||||
|
||||
/// Get pool transaction with a given hash.
|
||||
fn queued_transaction(&self, hash: H256) -> Option<Arc<VerifiedTransaction>>;
|
||||
|
||||
/// Get uncle with given id.
|
||||
fn uncle(&self, id: UncleId) -> Option<encoded::Header>;
|
||||
|
@ -330,6 +333,9 @@ pub trait BlockChainClient:
|
|||
/// Get all possible uncle hashes for a block.
|
||||
fn find_uncles(&self, hash: &H256) -> Option<Vec<H256>>;
|
||||
|
||||
/// Get latest state node
|
||||
fn state_data(&self, hash: &H256) -> Option<Bytes>;
|
||||
|
||||
/// Get block receipts data by block header hash.
|
||||
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts>;
|
||||
|
||||
|
@ -392,10 +398,49 @@ pub trait BlockChainClient:
|
|||
if block.number() == 0 {
|
||||
return corpus.into();
|
||||
}
|
||||
block.transaction_views().iter().foreach(|t| {
|
||||
corpus.push(t.effective_gas_price({
|
||||
match t.transaction_type() {
|
||||
TypedTxId::Legacy => None,
|
||||
TypedTxId::AccessList => None,
|
||||
TypedTxId::EIP1559Transaction => Some(block.header().base_fee()),
|
||||
}
|
||||
}))
|
||||
});
|
||||
h = block.parent_hash().clone();
|
||||
}
|
||||
}
|
||||
corpus.into()
|
||||
}
|
||||
|
||||
/// Sorted list of transaction priority gas prices from at least last sample_size blocks.
|
||||
fn priority_gas_price_corpus(
|
||||
&self,
|
||||
sample_size: usize,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> ::stats::Corpus<U256> {
|
||||
let mut h = self.chain_info().best_block_hash;
|
||||
let mut corpus = Vec::new();
|
||||
while corpus.is_empty() {
|
||||
for _ in 0..sample_size {
|
||||
let block = match self.block(BlockId::Hash(h)) {
|
||||
Some(block) => block,
|
||||
None => return corpus.into(),
|
||||
};
|
||||
|
||||
if block.number() == 0 || block.number() < eip1559_transition {
|
||||
return corpus.into();
|
||||
}
|
||||
block
|
||||
.transaction_views()
|
||||
.iter()
|
||||
.foreach(|t| corpus.push(t.gas_price()));
|
||||
.filter(
|
||||
|t| t.gas_price() > 0.into(), /* filter zero cost transactions */
|
||||
)
|
||||
.foreach(|t| {
|
||||
// As block.number() >= eip_1559_transition, the base_fee should exist
|
||||
corpus.push(t.effective_priority_gas_price(Some(block.header().base_fee())))
|
||||
});
|
||||
h = block.parent_hash().clone();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ use self::finality::RollingFinality;
|
|||
use super::{
|
||||
signer::EngineSigner,
|
||||
validator_set::{new_validator_set_posdao, SimpleList, ValidatorSet},
|
||||
EthEngine,
|
||||
};
|
||||
use block::*;
|
||||
use bytes::Bytes;
|
||||
|
@ -692,6 +693,7 @@ struct EpochVerifier {
|
|||
empty_steps_transition: u64,
|
||||
/// First block for which a 2/3 quorum (instead of 1/2) is required.
|
||||
two_thirds_majority_transition: BlockNumber,
|
||||
eip1559_transition: BlockNumber,
|
||||
}
|
||||
|
||||
impl super::EpochVerifier<EthereumMachine> for EpochVerifier {
|
||||
|
@ -716,7 +718,9 @@ impl super::EpochVerifier<EthereumMachine> for EpochVerifier {
|
|||
RollingFinality::blank(signers, self.two_thirds_majority_transition);
|
||||
let mut finalized = Vec::new();
|
||||
|
||||
let headers: Vec<Header> = Rlp::new(proof).as_list().ok()?;
|
||||
let proof_rlp = Rlp::new(proof);
|
||||
let headers: Vec<Header> =
|
||||
Header::decode_rlp_list(&proof_rlp, self.eip1559_transition).ok()?;
|
||||
|
||||
{
|
||||
let mut push_header = |parent_header: &Header, header: Option<&Header>| {
|
||||
|
@ -1553,6 +1557,43 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||
}
|
||||
}
|
||||
|
||||
// Mostly is the same as `fn sealing_state(&self)` except that it does not
|
||||
// check whether the node is a step proposer.
|
||||
fn is_allowed_to_seal(&self) -> bool {
|
||||
let our_addr = match *self.signer.read() {
|
||||
Some(ref signer) => signer.address(),
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let client = match self.upgrade_client_or("Not preparing block") {
|
||||
Ok(client) => client,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let parent = match client.as_full_client() {
|
||||
Some(full_client) => full_client.best_block_header(),
|
||||
None => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let validators = if self.immediate_transitions {
|
||||
CowLike::Borrowed(&*self.validators)
|
||||
} else {
|
||||
let mut epoch_manager = self.epoch_manager.lock();
|
||||
if !epoch_manager.zoom_to_after(
|
||||
&*client,
|
||||
&self.machine,
|
||||
&*self.validators,
|
||||
parent.hash(),
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
CowLike::Owned(epoch_manager.validators().clone())
|
||||
};
|
||||
validators.contains(&parent.hash(), &our_addr)
|
||||
}
|
||||
|
||||
fn sealing_state(&self) -> SealingState {
|
||||
let our_addr = match *self.signer.read() {
|
||||
Some(ref signer) => signer.address(),
|
||||
|
@ -1805,7 +1846,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||
let parent = client
|
||||
.block_header(::client::BlockId::Hash(*block.header.parent_hash()))
|
||||
.expect("hash is from parent; parent header must exist; qed")
|
||||
.decode()?;
|
||||
.decode(self.params().eip1559_transition)?;
|
||||
|
||||
let parent_step = header_step(&parent, self.empty_steps_transition)?;
|
||||
let current_step = self.step.inner.load();
|
||||
|
@ -2200,6 +2241,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||
subchain_validators: list,
|
||||
empty_steps_transition: self.empty_steps_transition,
|
||||
two_thirds_majority_transition: self.two_thirds_majority_transition,
|
||||
eip1559_transition: self.params().eip1559_transition,
|
||||
});
|
||||
|
||||
match finalize {
|
||||
|
|
|
@ -316,7 +316,8 @@ impl Clique {
|
|||
return Err(BlockError::UnknownParent(last_parent_hash))?;
|
||||
}
|
||||
Some(next) => {
|
||||
chain.push_front(next.decode()?);
|
||||
chain
|
||||
.push_front(next.decode(self.machine.params().eip1559_transition)?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +333,7 @@ impl Clique {
|
|||
None => {
|
||||
return Err(EngineError::CliqueMissingCheckpoint(last_checkpoint_hash))?
|
||||
}
|
||||
Some(header) => header.decode()?,
|
||||
Some(header) => header.decode(self.machine.params().eip1559_transition)?,
|
||||
};
|
||||
|
||||
let last_checkpoint_state = match block_state_by_hash.get_mut(&last_checkpoint_hash)
|
||||
|
|
|
@ -470,6 +470,14 @@ pub trait Engine<M: Machine>: Sync + Send {
|
|||
/// Register a component which signs consensus messages.
|
||||
fn set_signer(&self, _signer: Option<Box<dyn EngineSigner>>) {}
|
||||
|
||||
/// Returns whether the current node is a validator and
|
||||
/// actually may seal a block if AuRa engine is used.
|
||||
///
|
||||
/// Used by `eth_mining` rpc call.
|
||||
fn is_allowed_to_seal(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Sign using the EngineSigner, to be used for consensus tx signing.
|
||||
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> {
|
||||
unimplemented!()
|
||||
|
@ -648,10 +656,26 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
|
|||
self.machine().decode_transaction(transaction, &schedule)
|
||||
}
|
||||
|
||||
/// Calculates base fee for the block that should be mined next.
|
||||
/// This base fee is calculated based on the parent header (last block in blockchain / best block).
|
||||
///
|
||||
/// Introduced by EIP1559 to support new market fee mechanism.
|
||||
fn calculate_base_fee(&self, parent: &Header) -> Option<U256> {
|
||||
self.machine().calc_base_fee(parent)
|
||||
}
|
||||
|
||||
/// The configured minimum gas limit. Used by AuRa Engine.
|
||||
fn min_gas_limit(&self) -> U256 {
|
||||
self.params().min_gas_limit
|
||||
}
|
||||
|
||||
/// Returns whether transactions from non externally owned accounts (EOA)
|
||||
/// are allowed in the given block number (see EIP-3607).
|
||||
///
|
||||
/// That is only possible if EIP-3607 is still not activated.
|
||||
fn allow_non_eoa_sender(&self, best_block_number: BlockNumber) -> bool {
|
||||
self.params().eip3607_transition > best_block_number
|
||||
}
|
||||
}
|
||||
|
||||
// convenience wrappers for existing functions.
|
||||
|
|
|
@ -287,8 +287,11 @@ mod tests {
|
|||
for i in 1..4 {
|
||||
sync_client
|
||||
.import_block(
|
||||
Unverified::from_rlp(client.block(BlockId::Number(i)).unwrap().into_inner())
|
||||
.unwrap(),
|
||||
Unverified::from_rlp(
|
||||
client.block(BlockId::Number(i)).unwrap().into_inner(),
|
||||
client.engine().params().eip1559_transition,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -70,8 +70,9 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
|
|||
}
|
||||
|
||||
fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> {
|
||||
let (header, state_items) = decode_first_proof(&Rlp::new(proof))
|
||||
.map_err(|e| format!("proof incorrectly encoded: {}", e))?;
|
||||
let (header, state_items) =
|
||||
decode_first_proof(&Rlp::new(proof), machine.params().eip1559_transition)
|
||||
.map_err(|e| format!("proof incorrectly encoded: {}", e))?;
|
||||
if &header != &self.header {
|
||||
return Err("wrong header in proof".into());
|
||||
}
|
||||
|
@ -129,6 +130,7 @@ fn check_first_proof(
|
|||
Arc::new(last_hashes)
|
||||
},
|
||||
gas_used: 0.into(),
|
||||
base_fee: old_header.base_fee(),
|
||||
};
|
||||
|
||||
// check state proof using given machine.
|
||||
|
@ -163,8 +165,11 @@ fn check_first_proof(
|
|||
}
|
||||
}
|
||||
|
||||
fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Error> {
|
||||
let header = rlp.val_at(0)?;
|
||||
fn decode_first_proof(
|
||||
rlp: &Rlp,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<(Header, Vec<DBValue>), ::error::Error> {
|
||||
let header = Header::decode_rlp(&rlp.at(0)?, eip1559_transition)?;
|
||||
let state_items = rlp
|
||||
.at(1)?
|
||||
.iter()
|
||||
|
@ -188,8 +193,14 @@ fn encode_proof(header: &Header, receipts: &[TypedReceipt]) -> Bytes {
|
|||
stream.drain()
|
||||
}
|
||||
|
||||
fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<TypedReceipt>), ::error::Error> {
|
||||
Ok((rlp.val_at(0)?, TypedReceipt::decode_rlp_list(&rlp.at(1)?)?))
|
||||
fn decode_proof(
|
||||
rlp: &Rlp,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<(Header, Vec<TypedReceipt>), ::error::Error> {
|
||||
Ok((
|
||||
Header::decode_rlp(&rlp.at(0)?, eip1559_transition)?,
|
||||
TypedReceipt::decode_rlp_list(&rlp.at(1)?)?,
|
||||
))
|
||||
}
|
||||
|
||||
// given a provider and caller, generate proof. this will just be a state proof
|
||||
|
@ -554,7 +565,8 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||
if first {
|
||||
trace!(target: "engine", "Recovering initial epoch set");
|
||||
|
||||
let (old_header, state_items) = decode_first_proof(&rlp)?;
|
||||
let (old_header, state_items) =
|
||||
decode_first_proof(&rlp, machine.params().eip1559_transition)?;
|
||||
let number = old_header.number();
|
||||
let old_hash = old_header.hash();
|
||||
let addresses =
|
||||
|
@ -566,7 +578,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||
|
||||
Ok((SimpleList::new(addresses), Some(old_hash)))
|
||||
} else {
|
||||
let (old_header, receipts) = decode_proof(&rlp)?;
|
||||
let (old_header, receipts) = decode_proof(&rlp, machine.params().eip1559_transition)?;
|
||||
|
||||
// ensure receipts match header.
|
||||
// TODO: optimize? these were just decoded.
|
||||
|
@ -830,8 +842,11 @@ mod tests {
|
|||
for i in 1..4 {
|
||||
sync_client
|
||||
.import_block(
|
||||
Unverified::from_rlp(client.block(BlockId::Number(i)).unwrap().into_inner())
|
||||
.unwrap(),
|
||||
Unverified::from_rlp(
|
||||
client.block(BlockId::Number(i)).unwrap().into_inner(),
|
||||
client.engine().params().eip1559_transition,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ pub enum BlockError {
|
|||
InvalidSealArity(Mismatch<usize>),
|
||||
/// Block has too much gas used.
|
||||
TooMuchGasUsed(OutOfBounds<U256>),
|
||||
/// Gas target increased too much from previous block
|
||||
GasTargetTooBig(OutOfBounds<U256>),
|
||||
/// Gas target decreased too much from previous block
|
||||
GasTargetTooSmall(OutOfBounds<U256>),
|
||||
/// Uncles hash in header is invalid.
|
||||
InvalidUnclesHash(Mismatch<H256>),
|
||||
/// An uncle is from a generation too old.
|
||||
|
@ -79,6 +83,8 @@ pub enum BlockError {
|
|||
InvalidSeal,
|
||||
/// Gas limit header field is invalid.
|
||||
InvalidGasLimit(OutOfBounds<U256>),
|
||||
/// Base fee is incorrect; base fee is different from the expected calculated value.
|
||||
IncorrectBaseFee(Mismatch<U256>),
|
||||
/// Receipts trie root header field is invalid.
|
||||
InvalidReceiptsRoot(Mismatch<H256>),
|
||||
/// Timestamp header field is invalid.
|
||||
|
@ -112,6 +118,8 @@ impl fmt::Display for BlockError {
|
|||
ExtraDataOutOfBounds(ref oob) => format!("Extra block data too long. {}", oob),
|
||||
InvalidSealArity(ref mis) => format!("Block seal in incorrect format: {}", mis),
|
||||
TooMuchGasUsed(ref oob) => format!("Block has too much gas used. {}", oob),
|
||||
GasTargetTooBig(ref oob) => format!("Gas target is bigger then expected. {}", oob),
|
||||
GasTargetTooSmall(ref oob) => format!("Gas target is smaller then expected. {}", oob),
|
||||
InvalidUnclesHash(ref mis) => format!("Block has invalid uncles hash: {}", mis),
|
||||
UncleTooOld(ref oob) => format!("Uncle block is too old. {}", oob),
|
||||
UncleIsBrother(ref oob) => format!("Uncle from same generation as block. {}", oob),
|
||||
|
@ -131,6 +139,7 @@ impl fmt::Display for BlockError {
|
|||
InvalidProofOfWork(ref oob) => format!("Block has invalid PoW: {}", oob),
|
||||
InvalidSeal => "Block has invalid seal.".into(),
|
||||
InvalidGasLimit(ref oob) => format!("Invalid gas limit: {}", oob),
|
||||
IncorrectBaseFee(ref mis) => format!("Incorrect base fee: {}", mis),
|
||||
InvalidReceiptsRoot(ref mis) => {
|
||||
format!("Invalid receipts trie root in header: {}", mis)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,12 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{cmp, collections::BTreeMap, path::Path, sync::Arc};
|
||||
use std::{
|
||||
cmp::{self},
|
||||
collections::BTreeMap,
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use ethereum_types::{H256, H64, U256};
|
||||
use ethjson::{self, uint::Uint};
|
||||
|
|
|
@ -274,6 +274,22 @@ pub fn new_berlin_test() -> Spec {
|
|||
)
|
||||
}
|
||||
|
||||
/// Create a new Foundation London era spec.
|
||||
pub fn new_london_test() -> Spec {
|
||||
load(
|
||||
None,
|
||||
include_bytes!("../../res/chainspec/test/london_test.json"),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new BerlinToLondonAt5 era spec.
|
||||
pub fn new_berlin_to_london_test() -> Spec {
|
||||
load(
|
||||
None,
|
||||
include_bytes!("../../res/chainspec/test/berlin_to_londonat5_test.json"),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new Musicoin-MCIP3-era spec.
|
||||
pub fn new_mcip3_test() -> Spec {
|
||||
load(
|
||||
|
@ -298,6 +314,11 @@ pub fn new_homestead_test_machine() -> EthereumMachine {
|
|||
))
|
||||
}
|
||||
|
||||
/// Create a new Foundation London era chain spec.
|
||||
pub fn new_london_test_machine() -> EthereumMachine {
|
||||
load_machine(include_bytes!("../../res/chainspec/test/london_test.json"))
|
||||
}
|
||||
|
||||
/// Create a new Foundation Homestead-EIP210-era chain spec as though it never changed from Homestead/Frontier.
|
||||
pub fn new_eip210_test_machine() -> EthereumMachine {
|
||||
load_machine(include_bytes!("../../res/chainspec/test/eip210_test.json"))
|
||||
|
|
|
@ -91,6 +91,13 @@ pub enum ExecutionError {
|
|||
/// Amount of gas in block.
|
||||
gas: U256,
|
||||
},
|
||||
/// Transaction's max gas price is lower then block base fee.
|
||||
GasPriceLowerThanBaseFee {
|
||||
/// Max gas price of the transaction.
|
||||
gas_price: U256,
|
||||
/// Block base fee.
|
||||
base_fee: U256,
|
||||
},
|
||||
/// Returned when transaction nonce does not match state nonce.
|
||||
InvalidNonce {
|
||||
/// Nonce expected.
|
||||
|
@ -148,6 +155,13 @@ impl fmt::Display for ExecutionError {
|
|||
already been used, and {} more is required",
|
||||
gas_limit, gas_used, gas
|
||||
),
|
||||
GasPriceLowerThanBaseFee {
|
||||
ref gas_price,
|
||||
ref base_fee,
|
||||
} => format!(
|
||||
"Max gas price is lowert than block base fee. Gas price is {}, while base fee is {}",
|
||||
gas_price, base_fee
|
||||
),
|
||||
InvalidNonce {
|
||||
ref expected,
|
||||
ref got,
|
||||
|
|
|
@ -240,7 +240,6 @@ impl<'a> CallCreateExecutive<'a> {
|
|||
if schedule.eip2929 {
|
||||
let mut substate = Substate::from_access_list(¶ms.access_list);
|
||||
substate.access_list.insert_address(params.address);
|
||||
substate.access_list.insert_address(params.sender);
|
||||
substate
|
||||
} else {
|
||||
Substate::default()
|
||||
|
@ -445,6 +444,7 @@ impl<'a> CallCreateExecutive<'a> {
|
|||
| Err(vm::Error::SubStackUnderflow { .. })
|
||||
| Err(vm::Error::OutOfSubStack { .. })
|
||||
| Err(vm::Error::InvalidSubEntry)
|
||||
| Err(vm::Error::InvalidCode)
|
||||
| Ok(FinalizationResult {
|
||||
apply_state: false, ..
|
||||
}) => {
|
||||
|
@ -1134,6 +1134,13 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
));
|
||||
}
|
||||
}
|
||||
TypedTransaction::EIP1559Transaction(_) => {
|
||||
if !schedule.eip1559 {
|
||||
return Err(ExecutionError::TransactionMalformed(
|
||||
"1559 type of transactions not enabled".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
TypedTransaction::Legacy(_) => (), //legacy transactions are allways valid
|
||||
};
|
||||
|
||||
|
@ -1145,20 +1152,21 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
let mut access_list = AccessList::new(schedule.eip2929);
|
||||
|
||||
if schedule.eip2929 {
|
||||
for (address, _) in self.machine.builtins() {
|
||||
access_list.insert_address(*address);
|
||||
access_list.insert_address(sender);
|
||||
for (address, builtin) in self.machine.builtins() {
|
||||
if builtin.is_active(self.info.number) {
|
||||
access_list.insert_address(*address);
|
||||
}
|
||||
}
|
||||
if schedule.eip2930 {
|
||||
// optional access list
|
||||
if let TypedTransaction::AccessList(al_tx) = t.as_unsigned() {
|
||||
for item in al_tx.access_list.iter() {
|
||||
access_list.insert_address(item.0);
|
||||
base_gas_required += vm::schedule::EIP2930_ACCESS_LIST_ADDRESS_COST.into();
|
||||
for key in item.1.iter() {
|
||||
access_list.insert_storage_key(item.0, *key);
|
||||
base_gas_required +=
|
||||
vm::schedule::EIP2930_ACCESS_LIST_STORAGE_KEY_COST.into();
|
||||
}
|
||||
|
||||
if let Some(al) = t.access_list() {
|
||||
for item in al.iter() {
|
||||
access_list.insert_address(item.0);
|
||||
base_gas_required += vm::schedule::EIP2930_ACCESS_LIST_ADDRESS_COST.into();
|
||||
for key in item.1.iter() {
|
||||
access_list.insert_storage_key(item.0, *key);
|
||||
base_gas_required +=
|
||||
vm::schedule::EIP2930_ACCESS_LIST_STORAGE_KEY_COST.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1198,16 +1206,35 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
});
|
||||
}
|
||||
|
||||
// ensure that the user was willing to at least pay the base fee
|
||||
if t.tx().gas_price < self.info.base_fee.unwrap_or_default() && !t.has_zero_gas_price() {
|
||||
return Err(ExecutionError::GasPriceLowerThanBaseFee {
|
||||
gas_price: t.tx().gas_price,
|
||||
base_fee: self.info.base_fee.unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
|
||||
// verify that transaction max_fee_per_gas is higher or equal to max_priority_fee_per_gas
|
||||
if t.tx().gas_price < t.max_priority_fee_per_gas() {
|
||||
return Err(ExecutionError::TransactionMalformed(
|
||||
"maxPriorityFeePerGas higher than maxFeePerGas".into(),
|
||||
));
|
||||
}
|
||||
|
||||
// TODO: we might need bigints here, or at least check overflows.
|
||||
let balance = self.state.balance(&sender)?;
|
||||
let gas_cost = t.tx().gas.full_mul(t.tx().gas_price);
|
||||
let total_cost = U512::from(t.tx().value) + gas_cost;
|
||||
let gas_cost_effective = t
|
||||
.tx()
|
||||
.gas
|
||||
.full_mul(t.effective_gas_price(self.info.base_fee));
|
||||
let gas_cost_max = t.tx().gas.full_mul(t.tx().gas_price);
|
||||
let needed_balance = U512::from(t.tx().value) + gas_cost_max;
|
||||
|
||||
// avoid unaffordable transactions
|
||||
let balance512 = U512::from(balance);
|
||||
if balance512 < total_cost {
|
||||
if balance512 < needed_balance {
|
||||
return Err(ExecutionError::NotEnoughCash {
|
||||
required: total_cost,
|
||||
required: needed_balance,
|
||||
got: balance512,
|
||||
});
|
||||
}
|
||||
|
@ -1220,7 +1247,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
}
|
||||
self.state.sub_balance(
|
||||
&sender,
|
||||
&U256::try_from(gas_cost).expect("Total cost (value + gas_cost) is lower than max allowed balance (U256); gas_cost has to fit U256; qed"),
|
||||
&U256::try_from(gas_cost_effective).expect("Total cost (value + gas_cost_effective) is lower than max allowed balance (U256); gas_cost has to fit U256; qed"),
|
||||
&mut substate.to_cleanup_mode(&schedule),
|
||||
)?;
|
||||
|
||||
|
@ -1232,6 +1259,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
&nonce,
|
||||
&t.tx().data,
|
||||
);
|
||||
access_list.insert_address(new_address);
|
||||
let params = ActionParams {
|
||||
code_address: new_address.clone(),
|
||||
code_hash: code_hash,
|
||||
|
@ -1239,7 +1267,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
sender: sender.clone(),
|
||||
origin: sender.clone(),
|
||||
gas: init_gas,
|
||||
gas_price: t.tx().gas_price,
|
||||
gas_price: t.effective_gas_price(self.info.base_fee),
|
||||
value: ActionValue::Transfer(t.tx().value),
|
||||
code: Some(Arc::new(t.tx().data.clone())),
|
||||
data: None,
|
||||
|
@ -1255,13 +1283,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
(res, out)
|
||||
}
|
||||
Action::Call(ref address) => {
|
||||
access_list.insert_address(address.clone());
|
||||
let params = ActionParams {
|
||||
code_address: address.clone(),
|
||||
address: address.clone(),
|
||||
sender: sender.clone(),
|
||||
origin: sender.clone(),
|
||||
gas: init_gas,
|
||||
gas_price: t.tx().gas_price,
|
||||
gas_price: t.effective_gas_price(self.info.base_fee),
|
||||
value: ActionValue::Transfer(t.tx().value),
|
||||
code: self.state.code(address)?,
|
||||
code_hash: self.state.code_hash(address)?,
|
||||
|
@ -1459,23 +1488,49 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len());
|
||||
let refunds_bound = sstore_refunds + suicide_refunds;
|
||||
|
||||
// real ammount to refund
|
||||
// real amount to refund
|
||||
let gas_left_prerefund = match result {
|
||||
Ok(FinalizationResult { gas_left, .. }) => gas_left,
|
||||
_ => 0.into(),
|
||||
};
|
||||
let refunded = cmp::min(refunds_bound, (t.tx().gas - gas_left_prerefund) >> 1);
|
||||
let refunded = if refunds_bound.is_zero() {
|
||||
refunds_bound
|
||||
} else {
|
||||
let gas_used = t.tx().gas - gas_left_prerefund;
|
||||
let max_refund = gas_used / schedule.max_refund_quotient;
|
||||
cmp::min(max_refund, refunds_bound)
|
||||
};
|
||||
let gas_left = gas_left_prerefund + refunded;
|
||||
|
||||
let gas_used = t.tx().gas.saturating_sub(gas_left);
|
||||
let (refund_value, overflow_1) = gas_left.overflowing_mul(t.tx().gas_price);
|
||||
let (fees_value, overflow_2) = gas_used.overflowing_mul(t.tx().gas_price);
|
||||
let (refund_value, overflow_1) =
|
||||
gas_left.overflowing_mul(t.effective_gas_price(self.info.base_fee));
|
||||
let (fees_value, overflow_2) =
|
||||
gas_used.overflowing_mul(t.effective_gas_price(self.info.base_fee));
|
||||
if overflow_1 || overflow_2 {
|
||||
return Err(ExecutionError::TransactionMalformed(
|
||||
"U256 Overflow".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
// Up until now, fees_value is calculated for each type of transaction based on their gas prices
|
||||
// Now, if eip1559 is activated, burn the base fee
|
||||
// miner only receives the inclusion fee; note that the base fee is not given to anyone (it is burned)
|
||||
let burnt_fee = if schedule.eip1559 && !t.has_zero_gas_price() {
|
||||
let (fee, overflow_3) =
|
||||
gas_used.overflowing_mul(self.info.base_fee.unwrap_or_default());
|
||||
if overflow_3 {
|
||||
return Err(ExecutionError::TransactionMalformed(
|
||||
"U256 Overflow".to_string(),
|
||||
));
|
||||
}
|
||||
fee
|
||||
} else {
|
||||
U256::from(0)
|
||||
};
|
||||
|
||||
let fees_value = fees_value.saturating_sub(burnt_fee);
|
||||
|
||||
trace!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n",
|
||||
t.tx().gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value);
|
||||
|
||||
|
@ -1499,6 +1554,17 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
substate.to_cleanup_mode(&schedule),
|
||||
)?;
|
||||
|
||||
if burnt_fee > U256::from(0)
|
||||
&& self.machine.params().eip1559_fee_collector.is_some()
|
||||
&& self.info.number >= self.machine.params().eip1559_fee_collector_transition
|
||||
{
|
||||
self.state.add_balance(
|
||||
&self.machine.params().eip1559_fee_collector.unwrap(),
|
||||
&burnt_fee,
|
||||
substate.to_cleanup_mode(&schedule),
|
||||
)?;
|
||||
};
|
||||
|
||||
// perform suicides
|
||||
for address in &substate.suicides {
|
||||
self.state.kill_account(address);
|
||||
|
@ -1508,7 +1574,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||
let min_balance = if schedule.kill_dust != CleanDustMode::Off {
|
||||
Some(
|
||||
U256::from(schedule.tx_gas)
|
||||
.overflowing_mul(t.tx().gas_price)
|
||||
.overflowing_mul(t.effective_gas_price(self.info.base_fee))
|
||||
.0,
|
||||
)
|
||||
} else {
|
||||
|
@ -1574,7 +1640,9 @@ mod tests {
|
|||
trace, ExecutiveTracer, ExecutiveVMTracer, FlatTrace, MemoryDiff, NoopTracer, NoopVMTracer,
|
||||
StorageDiff, Tracer, VMExecutedOperation, VMOperation, VMTrace, VMTracer,
|
||||
};
|
||||
use types::transaction::{Action, Transaction, TypedTransaction};
|
||||
use types::transaction::{
|
||||
AccessListTx, Action, EIP1559TransactionTx, Transaction, TypedTransaction,
|
||||
};
|
||||
use vm::{ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo};
|
||||
|
||||
fn make_frontier_machine(max_depth: usize) -> EthereumMachine {
|
||||
|
@ -1589,6 +1657,12 @@ mod tests {
|
|||
machine
|
||||
}
|
||||
|
||||
fn make_london_machine(max_depth: usize) -> EthereumMachine {
|
||||
let mut machine = ::ethereum::new_london_test_machine();
|
||||
machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = max_depth));
|
||||
machine
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contract_address() {
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
@ -2600,6 +2674,53 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
evm_test! {test_transact_eip1559: test_transact_eip1559_int}
|
||||
fn test_transact_eip1559(factory: Factory) {
|
||||
let keypair = Random.generate();
|
||||
let t = TypedTransaction::EIP1559Transaction(EIP1559TransactionTx {
|
||||
transaction: AccessListTx::new(
|
||||
Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(17),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::from(150),
|
||||
nonce: U256::zero(),
|
||||
},
|
||||
vec![
|
||||
(
|
||||
H160::from_low_u64_be(10),
|
||||
vec![H256::from_low_u64_be(102), H256::from_low_u64_be(103)],
|
||||
),
|
||||
(H160::from_low_u64_be(400), vec![]),
|
||||
],
|
||||
),
|
||||
max_priority_fee_per_gas: U256::from(30),
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
|
||||
let sender = t.sender();
|
||||
|
||||
let mut state = get_temp_state_with_factory(factory);
|
||||
state
|
||||
.add_balance(&sender, &U256::from(15000017), CleanupMode::NoEmpty)
|
||||
.unwrap();
|
||||
let mut info = EnvInfo::default();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
info.base_fee = Some(U256::from(100));
|
||||
let machine = make_london_machine(0);
|
||||
let schedule = machine.schedule(info.number);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
let opts = TransactOptions::with_no_tracing();
|
||||
ex.transact(&t, opts).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(res.gas, U256::from(100_000));
|
||||
assert_eq!(res.gas_used, U256::from(83873));
|
||||
}
|
||||
|
||||
evm_test! {test_not_enough_cash: test_not_enough_cash_int}
|
||||
fn test_not_enough_cash(factory: Factory) {
|
||||
let keypair = Random.generate();
|
||||
|
@ -2639,6 +2760,127 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
evm_test! {test_too_big_max_priority_fee_with_not_enough_cash: test_too_big_max_priority_fee_with_not_enough_cash_int}
|
||||
fn test_too_big_max_priority_fee_with_not_enough_cash(factory: Factory) {
|
||||
let keypair = Random.generate();
|
||||
let max_priority_fee_per_gas /* 2**256 - 1 */ = U256::from(340282366920938463463374607431768211455u128)
|
||||
* U256::from(340282366920938463463374607431768211455u128)
|
||||
+ U256::from(340282366920938463463374607431768211455u128)
|
||||
+ U256::from(340282366920938463463374607431768211455u128);
|
||||
let t = TypedTransaction::EIP1559Transaction(EIP1559TransactionTx {
|
||||
transaction: AccessListTx::new(
|
||||
Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(17),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: max_priority_fee_per_gas,
|
||||
nonce: U256::zero(),
|
||||
},
|
||||
vec![
|
||||
(
|
||||
H160::from_low_u64_be(10),
|
||||
vec![H256::from_low_u64_be(102), H256::from_low_u64_be(103)],
|
||||
),
|
||||
(H160::from_low_u64_be(400), vec![]),
|
||||
],
|
||||
),
|
||||
max_priority_fee_per_gas,
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
|
||||
let sender = t.sender();
|
||||
|
||||
let mut state = get_temp_state_with_factory(factory);
|
||||
state
|
||||
.add_balance(&sender, &U256::from(15000017), CleanupMode::NoEmpty)
|
||||
.unwrap();
|
||||
let mut info = EnvInfo::default();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
info.base_fee = Some(U256::from(100));
|
||||
let machine = make_london_machine(0);
|
||||
let schedule = machine.schedule(info.number);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
let opts = TransactOptions::with_no_tracing();
|
||||
ex.transact(&t, opts)
|
||||
};
|
||||
|
||||
match res {
|
||||
Err(ExecutionError::NotEnoughCash { required, got })
|
||||
if required
|
||||
== U512::from(max_priority_fee_per_gas) * U512::from(100_000)
|
||||
+ U512::from(17)
|
||||
&& got == U512::from(15000017) =>
|
||||
{
|
||||
()
|
||||
}
|
||||
_ => assert!(false, "Expected not enough cash error. {:?}", res),
|
||||
}
|
||||
}
|
||||
|
||||
evm_test! {test_too_big_max_priority_fee_with_less_max_fee_per_gas: test_too_big_max_priority_fee_with_less_max_fee_per_gas_int}
|
||||
fn test_too_big_max_priority_fee_with_less_max_fee_per_gas(factory: Factory) {
|
||||
let keypair = Random.generate();
|
||||
let max_priority_fee_per_gas /* 2**256 - 1 */ = U256::from(340282366920938463463374607431768211455u128)
|
||||
* U256::from(340282366920938463463374607431768211455u128)
|
||||
+ U256::from(340282366920938463463374607431768211455u128)
|
||||
+ U256::from(340282366920938463463374607431768211455u128);
|
||||
let t = TypedTransaction::EIP1559Transaction(EIP1559TransactionTx {
|
||||
transaction: AccessListTx::new(
|
||||
Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(17),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::from(150),
|
||||
nonce: U256::zero(),
|
||||
},
|
||||
vec![
|
||||
(
|
||||
H160::from_low_u64_be(10),
|
||||
vec![H256::from_low_u64_be(102), H256::from_low_u64_be(103)],
|
||||
),
|
||||
(H160::from_low_u64_be(400), vec![]),
|
||||
],
|
||||
),
|
||||
max_priority_fee_per_gas,
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
|
||||
let sender = t.sender();
|
||||
|
||||
let mut state = get_temp_state_with_factory(factory);
|
||||
state
|
||||
.add_balance(&sender, &U256::from(15000017), CleanupMode::NoEmpty)
|
||||
.unwrap();
|
||||
let mut info = EnvInfo::default();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
info.base_fee = Some(U256::from(100));
|
||||
let machine = make_london_machine(0);
|
||||
let schedule = machine.schedule(info.number);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
let opts = TransactOptions::with_no_tracing();
|
||||
ex.transact(&t, opts)
|
||||
};
|
||||
|
||||
match res {
|
||||
Err(ExecutionError::TransactionMalformed(err))
|
||||
if err.contains("maxPriorityFeePerGas higher than maxFeePerGas") =>
|
||||
{
|
||||
()
|
||||
}
|
||||
_ => assert!(
|
||||
false,
|
||||
"Expected maxPriorityFeePerGas higher than maxFeePerGas error. {:?}",
|
||||
res
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
evm_test! {test_keccak: test_keccak_int}
|
||||
fn test_keccak(factory: Factory) {
|
||||
let code = "6064640fffffffff20600055".from_hex().unwrap();
|
||||
|
|
|
@ -431,6 +431,12 @@ where
|
|||
false => Ok(*gas),
|
||||
};
|
||||
}
|
||||
if self.schedule.eip3541 && data.get(0) == Some(&0xefu8) {
|
||||
return match self.schedule.exceptional_failed_code_deposit {
|
||||
true => Err(vm::Error::InvalidCode),
|
||||
false => Ok(*gas),
|
||||
};
|
||||
}
|
||||
self.state
|
||||
.init_code(&self.origin_info.address, data.to_vec())?;
|
||||
Ok(*gas - return_cost)
|
||||
|
@ -582,6 +588,7 @@ mod tests {
|
|||
last_hashes: Arc::new(vec![]),
|
||||
gas_used: 0.into(),
|
||||
gas_limit: 0.into(),
|
||||
base_fee: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,4 +920,46 @@ mod tests {
|
|||
Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eip_3541() {
|
||||
let call_ret = |schedule: Schedule, data: &ReturnData| {
|
||||
let mut setup = TestSetup::default();
|
||||
setup.schedule = schedule;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin = get_test_origin();
|
||||
let ext = Externalities::new(
|
||||
&mut setup.state,
|
||||
&setup.env_info,
|
||||
&setup.machine,
|
||||
&setup.schedule,
|
||||
0,
|
||||
0,
|
||||
&origin,
|
||||
&mut setup.sub_state,
|
||||
OutputPolicy::InitContract,
|
||||
&mut tracer,
|
||||
&mut vm_tracer,
|
||||
false,
|
||||
);
|
||||
ext.ret(&U256::from(10000), &data, true)
|
||||
};
|
||||
|
||||
let data = ReturnData::new(vec![0xefu8], 0, 1);
|
||||
|
||||
let result = call_ret(Schedule::new_berlin(), &data);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let result = call_ret(Schedule::new_london(), &data);
|
||||
assert!(result.is_err());
|
||||
|
||||
let data = ReturnData::new(vec![0xefu8, 0x00u8, 0x00u8], 0, 3);
|
||||
let result = call_ret(Schedule::new_london(), &data);
|
||||
assert!(result.is_err());
|
||||
|
||||
let data = ReturnData::new(vec![0xee], 0, 1);
|
||||
let result = call_ret(Schedule::new_london(), &data);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(
|
|||
|
||||
for b in blockchain.blocks_rlp() {
|
||||
let bytes_len = b.len();
|
||||
let block = Unverified::from_rlp(b);
|
||||
let block = Unverified::from_rlp(b, spec.params().eip1559_transition);
|
||||
match block {
|
||||
Ok(block) => {
|
||||
let num = block.header.number();
|
||||
|
|
|
@ -4,7 +4,10 @@ use ethjson::{self, blockchain::Block};
|
|||
use log::warn;
|
||||
use rlp::RlpStream;
|
||||
use std::path::Path;
|
||||
use types::transaction::{TypedTransaction, TypedTxId, UnverifiedTransaction};
|
||||
use types::{
|
||||
transaction::{TypedTransaction, TypedTxId, UnverifiedTransaction},
|
||||
BlockNumber,
|
||||
};
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
pub fn json_local_block_en_de_test<H: FnMut(&str, HookType)>(
|
||||
|
@ -22,7 +25,7 @@ pub fn json_local_block_en_de_test<H: FnMut(&str, HookType)>(
|
|||
for (name, ref_block) in tests.into_iter() {
|
||||
start_stop_hook(&name, HookType::OnStart);
|
||||
|
||||
let block = Unverified::from_rlp(ref_block.rlp());
|
||||
let block = Unverified::from_rlp(ref_block.rlp(), BlockNumber::max_value());
|
||||
let block = match block {
|
||||
Ok(block) => block,
|
||||
Err(decoder_err) => {
|
||||
|
@ -131,8 +134,24 @@ pub fn is_same_block(ref_block: &Block, block: &Unverified) -> bool {
|
|||
TypedTxId::Legacy
|
||||
};
|
||||
is_ok = is_ok
|
||||
&& {
|
||||
match ref_tx.gas_price {
|
||||
Some(gas_price) => {
|
||||
test_exp(tx.tx().gas_price == gas_price.0, "Tx gas price")
|
||||
}
|
||||
None => {
|
||||
test_exp(
|
||||
tx.tx().gas_price == ref_tx.max_fee_per_gas.unwrap_or_default().0,
|
||||
"Tx max fee per gas",
|
||||
) && test_exp(
|
||||
tx.max_priority_fee_per_gas()
|
||||
== ref_tx.max_priority_fee_per_gas.unwrap_or_default().0,
|
||||
"Tx max priority fee per gas",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
&& test_exp(tx.tx().nonce == ref_tx.nonce.0, "Tx nonce")
|
||||
&& test_exp(tx.tx().gas_price == ref_tx.gas_price.0, "Tx gas price")
|
||||
&& test_exp(tx.tx().gas == ref_tx.gas_limit.0, "Tx gas")
|
||||
&& test_exp(tx.tx().value == ref_tx.value.0, "Tx value")
|
||||
&& test_exp(tx.tx().data == ref_tx.data.0, "Tx data")
|
||||
|
@ -148,10 +167,11 @@ pub fn is_same_block(ref_block: &Block, block: &Unverified) -> bool {
|
|||
TypedTxId::Legacy => {
|
||||
test_exp(tx.legacy_v() == ref_tx.v.0.as_u64(), "Original Sig V")
|
||||
}
|
||||
TypedTxId::AccessList => {
|
||||
TypedTxId::AccessList | TypedTxId::EIP1559Transaction => {
|
||||
test_exp(tx.standard_v() as u64 == ref_tx.v.0.as_u64(), "Sig V");
|
||||
let al = match tx.as_unsigned() {
|
||||
TypedTransaction::AccessList(tx) => &tx.access_list,
|
||||
TypedTransaction::EIP1559Transaction(tx) => &tx.transaction.access_list,
|
||||
_ => {
|
||||
println!("Wrong data in tx type");
|
||||
continue;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
use super::{test_common::*, HookType};
|
||||
use client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess};
|
||||
use ethjson;
|
||||
use ethjson::{self, spec::ForkSpec};
|
||||
use pod_state::PodState;
|
||||
use std::path::Path;
|
||||
use trace;
|
||||
|
@ -77,6 +77,14 @@ pub fn json_state_test<H: FnMut(&str, HookType)>(
|
|||
}
|
||||
};
|
||||
|
||||
//hardcode base fee for part of the london tests, that miss base fee field in env
|
||||
let mut test_env = env.clone();
|
||||
if spec_name >= ForkSpec::London {
|
||||
if test_env.base_fee.is_none() {
|
||||
test_env.base_fee = Some(0x0a.into());
|
||||
}
|
||||
}
|
||||
|
||||
for (i, state) in states.into_iter().enumerate() {
|
||||
let info = format!(
|
||||
"TestState/{}/{:?}/{}/trie",
|
||||
|
@ -94,7 +102,7 @@ pub fn json_state_test<H: FnMut(&str, HookType)>(
|
|||
|
||||
let result = || -> Result<_, EvmTestError> {
|
||||
Ok(EvmTestClient::from_pod_state(&spec, pre.clone())?.transact(
|
||||
&env,
|
||||
&test_env,
|
||||
transaction,
|
||||
trace::NoopTracer,
|
||||
trace::NoopVMTracer,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
//! Ethereum-like state machine definition.
|
||||
|
||||
use std::{
|
||||
cmp,
|
||||
cmp::{self, max},
|
||||
collections::{BTreeMap, HashMap},
|
||||
sync::Arc,
|
||||
};
|
||||
|
@ -47,9 +47,6 @@ use state::{CleanupMode, Substate};
|
|||
use trace::{NoopTracer, NoopVMTracer};
|
||||
use tx_filter::TransactionFilter;
|
||||
|
||||
/// Open tries to round block.gas_limit to multiple of this constant
|
||||
pub const GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
|
||||
|
||||
/// Ethash-specific extensions.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EthashExtensions {
|
||||
|
@ -269,55 +266,31 @@ impl EthereumMachine {
|
|||
gas_ceil_target: U256,
|
||||
) {
|
||||
header.set_difficulty(parent.difficulty().clone());
|
||||
let gas_limit = parent.gas_limit().clone();
|
||||
let gas_limit = parent.gas_limit() * self.schedule(header.number()).eip1559_gas_limit_bump;
|
||||
assert!(!gas_limit.is_zero(), "Gas limit should be > 0");
|
||||
|
||||
if let Some(ref ethash_params) = self.ethash_extensions {
|
||||
let gas_limit = {
|
||||
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||
let lower_limit = gas_limit - gas_limit / bound_divisor + 1;
|
||||
let upper_limit = gas_limit + gas_limit / bound_divisor - 1;
|
||||
let gas_limit = if gas_limit < gas_floor_target {
|
||||
let gas_limit = cmp::min(gas_floor_target, upper_limit);
|
||||
round_block_gas_limit(gas_limit, lower_limit, upper_limit)
|
||||
} else if gas_limit > gas_ceil_target {
|
||||
let gas_limit = cmp::max(gas_ceil_target, lower_limit);
|
||||
round_block_gas_limit(gas_limit, lower_limit, upper_limit)
|
||||
} else {
|
||||
let total_lower_limit = cmp::max(lower_limit, gas_floor_target);
|
||||
let total_upper_limit = cmp::min(upper_limit, gas_ceil_target);
|
||||
let gas_limit = cmp::max(
|
||||
gas_floor_target,
|
||||
cmp::min(
|
||||
total_upper_limit,
|
||||
lower_limit + (header.gas_used().clone() * 6u32 / 5) / bound_divisor,
|
||||
),
|
||||
);
|
||||
round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit)
|
||||
};
|
||||
// ensure that we are not violating protocol limits
|
||||
debug_assert!(gas_limit >= lower_limit);
|
||||
debug_assert!(gas_limit <= upper_limit);
|
||||
gas_limit
|
||||
};
|
||||
let gas_limit_target = if self.schedule(header.number()).eip1559 {
|
||||
gas_ceil_target
|
||||
} else {
|
||||
gas_floor_target
|
||||
};
|
||||
|
||||
header.set_gas_limit(gas_limit);
|
||||
header.set_gas_limit({
|
||||
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||
if gas_limit < gas_limit_target {
|
||||
cmp::min(gas_limit_target, gas_limit + gas_limit / bound_divisor - 1)
|
||||
} else {
|
||||
cmp::max(gas_limit_target, gas_limit - gas_limit / bound_divisor + 1)
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(ref ethash_params) = self.ethash_extensions {
|
||||
if header.number() >= ethash_params.dao_hardfork_transition
|
||||
&& header.number() <= ethash_params.dao_hardfork_transition + 9
|
||||
{
|
||||
header.set_extra_data(b"dao-hard-fork"[..].to_owned());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
header.set_gas_limit({
|
||||
let bound_divisor = self.params().gas_limit_bound_divisor;
|
||||
if gas_limit < gas_floor_target {
|
||||
cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1)
|
||||
} else {
|
||||
cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Get the general parameters of the chain.
|
||||
|
@ -400,8 +373,16 @@ impl EthereumMachine {
|
|||
pub fn verify_transaction_unordered(
|
||||
&self,
|
||||
t: UnverifiedTransaction,
|
||||
_header: &Header,
|
||||
header: &Header,
|
||||
) -> Result<SignedTransaction, transaction::Error> {
|
||||
// ensure that the user was willing to at least pay the base fee
|
||||
if t.tx().gas_price < header.base_fee().unwrap_or_default() && !t.has_zero_gas_price() {
|
||||
return Err(transaction::Error::GasPriceLowerThanBaseFee {
|
||||
gas_price: t.tx().gas_price,
|
||||
base_fee: header.base_fee().unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(SignedTransaction::new(t)?)
|
||||
}
|
||||
|
||||
|
@ -472,11 +453,80 @@ impl EthereumMachine {
|
|||
transaction::TypedTxId::AccessList if !schedule.eip2930 => {
|
||||
return Err(transaction::Error::TransactionTypeNotEnabled)
|
||||
}
|
||||
transaction::TypedTxId::EIP1559Transaction if !schedule.eip1559 => {
|
||||
return Err(transaction::Error::TransactionTypeNotEnabled)
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
/// Calculates base fee for the block that should be mined next.
|
||||
/// Base fee is calculated based on the parent header (last block in blockchain / best block).
|
||||
///
|
||||
/// Introduced by EIP1559 to support new market fee mechanism.
|
||||
///
|
||||
/// Modified for xDai chain to have an ability to set min base fee
|
||||
/// through eip1559BaseFeeMinValue spec option. The modification made
|
||||
/// in v3.3.0-rc.14
|
||||
pub fn calc_base_fee(&self, parent: &Header) -> Option<U256> {
|
||||
// Block eip1559_transition - 1 has base_fee = None
|
||||
if parent.number() + 1 < self.params().eip1559_transition {
|
||||
return None;
|
||||
}
|
||||
|
||||
let base_fee_min_value =
|
||||
if parent.number() + 1 >= self.params().eip1559_base_fee_min_value_transition {
|
||||
match self.params().eip1559_base_fee_min_value {
|
||||
None => panic!("Base fee min value must be set in spec."),
|
||||
Some(min_value) => min_value,
|
||||
}
|
||||
} else {
|
||||
U256::zero()
|
||||
};
|
||||
|
||||
// Block eip1559_transition has base_fee = self.params().eip1559_base_fee_initial_value
|
||||
if parent.number() + 1 == self.params().eip1559_transition {
|
||||
return Some(max(
|
||||
self.params().eip1559_base_fee_initial_value,
|
||||
base_fee_min_value,
|
||||
));
|
||||
}
|
||||
|
||||
// Block eip1559_transition + 1 has base_fee = calculated
|
||||
let base_fee_denominator = match self.params().eip1559_base_fee_max_change_denominator {
|
||||
None => panic!("Can't calculate base fee if base fee denominator does not exist."),
|
||||
Some(denominator) if denominator == U256::from(0) => {
|
||||
panic!("Can't calculate base fee if base fee denominator is zero.")
|
||||
}
|
||||
Some(denominator) => denominator,
|
||||
};
|
||||
|
||||
let parent_base_fee = parent.base_fee().unwrap_or_default();
|
||||
let parent_gas_target = parent.gas_limit() / self.params().eip1559_elasticity_multiplier;
|
||||
if parent_gas_target == U256::zero() {
|
||||
panic!("Can't calculate base fee if parent gas target is zero.");
|
||||
}
|
||||
|
||||
let result = if parent.gas_used() == &parent_gas_target {
|
||||
parent_base_fee
|
||||
} else if parent.gas_used() > &parent_gas_target {
|
||||
let gas_used_delta = parent.gas_used() - parent_gas_target;
|
||||
let base_fee_per_gas_delta = max(
|
||||
parent_base_fee * gas_used_delta / parent_gas_target / base_fee_denominator,
|
||||
U256::from(1),
|
||||
);
|
||||
parent_base_fee + base_fee_per_gas_delta
|
||||
} else {
|
||||
let gas_used_delta = parent_gas_target - parent.gas_used();
|
||||
let base_fee_per_gas_delta =
|
||||
parent_base_fee * gas_used_delta / parent_gas_target / base_fee_denominator;
|
||||
max(parent_base_fee - base_fee_per_gas_delta, U256::zero())
|
||||
};
|
||||
|
||||
Some(max(result, base_fee_min_value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Auxiliary data fetcher for an Ethereum machine. In Ethereum-like machines
|
||||
|
@ -525,27 +575,10 @@ impl super::Machine for EthereumMachine {
|
|||
}
|
||||
}
|
||||
|
||||
// Try to round gas_limit a bit so that:
|
||||
// 1) it will still be in desired range
|
||||
// 2) it will be a nearest (with tendency to increase) multiple of GAS_LIMIT_DETERMINANT
|
||||
fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 {
|
||||
let increased_gas_limit =
|
||||
gas_limit + (GAS_LIMIT_DETERMINANT - gas_limit % GAS_LIMIT_DETERMINANT);
|
||||
if increased_gas_limit > upper_limit {
|
||||
let decreased_gas_limit = increased_gas_limit - GAS_LIMIT_DETERMINANT;
|
||||
if decreased_gas_limit < lower_limit {
|
||||
gas_limit
|
||||
} else {
|
||||
decreased_gas_limit
|
||||
}
|
||||
} else {
|
||||
increased_gas_limit
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ethereum::new_london_test_machine;
|
||||
use ethereum_types::H160;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -585,79 +618,65 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn ethash_gas_limit_is_multiple_of_determinant() {
|
||||
use ethereum_types::U256;
|
||||
fn calculate_base_fee_success() {
|
||||
let machine = new_london_test_machine();
|
||||
let parent_base_fees = [
|
||||
U256::from(1000000000),
|
||||
U256::from(1000000000),
|
||||
U256::from(1000000000),
|
||||
U256::from(1072671875),
|
||||
U256::from(1059263476),
|
||||
U256::from(1049238967),
|
||||
U256::from(1049238967),
|
||||
U256::from(0),
|
||||
U256::from(1),
|
||||
U256::from(2),
|
||||
];
|
||||
let parent_gas_used = [
|
||||
U256::from(10000000),
|
||||
U256::from(10000000),
|
||||
U256::from(10000000),
|
||||
U256::from(9000000),
|
||||
U256::from(10001000),
|
||||
U256::from(0),
|
||||
U256::from(10000000),
|
||||
U256::from(10000000),
|
||||
U256::from(10000000),
|
||||
U256::from(10000000),
|
||||
];
|
||||
let parent_gas_limit = [
|
||||
U256::from(10000000),
|
||||
U256::from(12000000),
|
||||
U256::from(14000000),
|
||||
U256::from(10000000),
|
||||
U256::from(14000000),
|
||||
U256::from(2000000),
|
||||
U256::from(18000000),
|
||||
U256::from(18000000),
|
||||
U256::from(18000000),
|
||||
U256::from(18000000),
|
||||
];
|
||||
let expected_base_fee = [
|
||||
U256::from(1125000000),
|
||||
U256::from(1083333333),
|
||||
U256::from(1053571428),
|
||||
U256::from(1179939062),
|
||||
U256::from(1116028649),
|
||||
U256::from(918084097),
|
||||
U256::from(1063811730),
|
||||
U256::from(1),
|
||||
U256::from(2),
|
||||
U256::from(3),
|
||||
];
|
||||
|
||||
let spec = ::ethereum::new_homestead_test();
|
||||
let ethparams = get_default_ethash_extensions();
|
||||
for i in 0..parent_base_fees.len() {
|
||||
let mut parent_header = Header::default();
|
||||
parent_header.set_base_fee(Some(parent_base_fees[i]));
|
||||
parent_header.set_gas_used(parent_gas_used[i]);
|
||||
parent_header.set_gas_limit(parent_gas_limit[i]);
|
||||
|
||||
let machine = EthereumMachine::with_ethash_extensions(
|
||||
spec.params().clone(),
|
||||
Default::default(),
|
||||
ethparams,
|
||||
);
|
||||
|
||||
let mut parent = ::types::header::Header::new();
|
||||
let mut header = ::types::header::Header::new();
|
||||
header.set_number(1);
|
||||
|
||||
// this test will work for this constant only
|
||||
assert_eq!(GAS_LIMIT_DETERMINANT, U256::from(37));
|
||||
|
||||
// when parent.gas_limit < gas_floor_target:
|
||||
parent.set_gas_limit(U256::from(50_000));
|
||||
machine.populate_from_parent(
|
||||
&mut header,
|
||||
&parent,
|
||||
U256::from(100_000),
|
||||
U256::from(200_000),
|
||||
);
|
||||
assert_eq!(*header.gas_limit(), U256::from(50_024));
|
||||
|
||||
// when parent.gas_limit > gas_ceil_target:
|
||||
parent.set_gas_limit(U256::from(250_000));
|
||||
machine.populate_from_parent(
|
||||
&mut header,
|
||||
&parent,
|
||||
U256::from(100_000),
|
||||
U256::from(200_000),
|
||||
);
|
||||
assert_eq!(*header.gas_limit(), U256::from(249_787));
|
||||
|
||||
// when parent.gas_limit is in miner's range
|
||||
header.set_gas_used(U256::from(150_000));
|
||||
parent.set_gas_limit(U256::from(150_000));
|
||||
machine.populate_from_parent(
|
||||
&mut header,
|
||||
&parent,
|
||||
U256::from(100_000),
|
||||
U256::from(200_000),
|
||||
);
|
||||
assert_eq!(*header.gas_limit(), U256::from(150_035));
|
||||
|
||||
// when parent.gas_limit is in miner's range
|
||||
// && we can NOT increase it to be multiple of constant
|
||||
header.set_gas_used(U256::from(150_000));
|
||||
parent.set_gas_limit(U256::from(150_000));
|
||||
machine.populate_from_parent(
|
||||
&mut header,
|
||||
&parent,
|
||||
U256::from(100_000),
|
||||
U256::from(150_002),
|
||||
);
|
||||
assert_eq!(*header.gas_limit(), U256::from(149_998));
|
||||
|
||||
// when parent.gas_limit is in miner's range
|
||||
// && we can NOT increase it to be multiple of constant
|
||||
// && we can NOT decrease it to be multiple of constant
|
||||
header.set_gas_used(U256::from(150_000));
|
||||
parent.set_gas_limit(U256::from(150_000));
|
||||
machine.populate_from_parent(
|
||||
&mut header,
|
||||
&parent,
|
||||
U256::from(150_000),
|
||||
U256::from(150_002),
|
||||
);
|
||||
assert_eq!(*header.gas_limit(), U256::from(150_002));
|
||||
let base_fee = machine.calc_base_fee(&parent_header);
|
||||
assert_eq!(expected_base_fee[i], base_fee.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,8 +187,10 @@ impl Default for MinerOptions {
|
|||
pool_verification_options: pool::verifier::Options {
|
||||
minimal_gas_price: DEFAULT_MINIMAL_GAS_PRICE.into(),
|
||||
block_gas_limit: U256::max_value(),
|
||||
block_base_fee: None,
|
||||
tx_gas_limit: U256::max_value(),
|
||||
no_early_reject: false,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -337,8 +339,10 @@ impl Miner {
|
|||
pool_verification_options: pool::verifier::Options {
|
||||
minimal_gas_price,
|
||||
block_gas_limit: U256::max_value(),
|
||||
block_base_fee: None,
|
||||
tx_gas_limit: U256::max_value(),
|
||||
no_early_reject: false,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
reseal_min_period: Duration::from_secs(0),
|
||||
force_sealing,
|
||||
|
@ -376,7 +380,12 @@ impl Miner {
|
|||
/// Updates transaction queue verification limits.
|
||||
///
|
||||
/// Limits consist of current block gas limit and minimal gas price.
|
||||
pub fn update_transaction_queue_limits(&self, block_gas_limit: U256) {
|
||||
pub fn update_transaction_queue_limits(
|
||||
&self,
|
||||
block_gas_limit: U256,
|
||||
block_base_fee: Option<U256>,
|
||||
allow_non_eoa_sender: bool,
|
||||
) {
|
||||
trace!(target: "miner", "minimal_gas_price: recalibrating...");
|
||||
let txq = self.transaction_queue.clone();
|
||||
let mut options = self.options.pool_verification_options.clone();
|
||||
|
@ -384,8 +393,15 @@ impl Miner {
|
|||
debug!(target: "miner", "minimal_gas_price: Got gas price! {}", gas_price);
|
||||
options.minimal_gas_price = gas_price;
|
||||
options.block_gas_limit = block_gas_limit;
|
||||
options.block_base_fee = block_base_fee;
|
||||
options.allow_non_eoa_sender = allow_non_eoa_sender;
|
||||
txq.set_verifier_options(options);
|
||||
});
|
||||
|
||||
match block_base_fee {
|
||||
Some(block_base_fee) => self.transaction_queue.update_scoring(block_base_fee),
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns ServiceTransactionChecker
|
||||
|
@ -498,11 +514,9 @@ impl Miner {
|
|||
|
||||
let client = self.pool_client(chain);
|
||||
let engine_params = self.engine.params();
|
||||
let min_tx_gas: U256 = self
|
||||
.engine
|
||||
.schedule(chain_info.best_block_number)
|
||||
.tx_gas
|
||||
.into();
|
||||
let schedule = self.engine.schedule(block_number);
|
||||
let min_tx_gas: U256 = schedule.tx_gas.into();
|
||||
let gas_limit = open_block.header.gas_limit();
|
||||
let nonce_cap: Option<U256> = if chain_info.best_block_number + 1
|
||||
>= engine_params.dust_protection_transition
|
||||
{
|
||||
|
@ -515,11 +529,7 @@ impl Miner {
|
|||
usize::max_value()
|
||||
} else {
|
||||
MAX_SKIPPED_TRANSACTIONS.saturating_add(
|
||||
cmp::min(
|
||||
*open_block.header.gas_limit() / min_tx_gas,
|
||||
u64::max_value().into(),
|
||||
)
|
||||
.as_u64() as usize,
|
||||
cmp::min(gas_limit / min_tx_gas, u64::max_value().into()).as_u64() as usize,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -531,6 +541,10 @@ impl Miner {
|
|||
nonce_cap,
|
||||
max_len: max_transactions.saturating_sub(engine_txs.len()),
|
||||
ordering: miner::PendingOrdering::Priority,
|
||||
includable_boundary: self
|
||||
.engine
|
||||
.calculate_base_fee(&chain.best_block_header())
|
||||
.unwrap_or_default(),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -740,7 +754,7 @@ impl Miner {
|
|||
trace!(target: "miner", "seal_block_internally: attempting internal seal.");
|
||||
|
||||
let parent_header = match chain.block_header(BlockId::Hash(*block.header.parent_hash())) {
|
||||
Some(h) => match h.decode() {
|
||||
Some(h) => match h.decode(self.engine.params().eip1559_transition) {
|
||||
Ok(decoded_hdr) => decoded_hdr,
|
||||
Err(_) => return false,
|
||||
},
|
||||
|
@ -996,6 +1010,14 @@ impl miner::MinerService for Miner {
|
|||
self.transaction_queue.current_worst_gas_price() * 110u32 / 100
|
||||
}
|
||||
|
||||
fn sensible_max_priority_fee(&self) -> U256 {
|
||||
// 10% above our minimum.
|
||||
self.transaction_queue
|
||||
.current_worst_effective_priority_fee()
|
||||
* 110u32
|
||||
/ 100
|
||||
}
|
||||
|
||||
fn sensible_gas_limit(&self) -> U256 {
|
||||
self.params.read().gas_range_target.0 / 5
|
||||
}
|
||||
|
@ -1159,7 +1181,7 @@ impl miner::MinerService for Miner {
|
|||
ordering: miner::PendingOrdering,
|
||||
) -> Vec<Arc<VerifiedTransaction>>
|
||||
where
|
||||
C: ChainInfo + Nonce + Sync,
|
||||
C: BlockChain + Nonce + Sync,
|
||||
{
|
||||
let chain_info = chain.chain_info();
|
||||
|
||||
|
@ -1176,6 +1198,10 @@ impl miner::MinerService for Miner {
|
|||
nonce_cap,
|
||||
max_len,
|
||||
ordering,
|
||||
includable_boundary: self
|
||||
.engine
|
||||
.calculate_base_fee(&chain.best_block_header())
|
||||
.unwrap_or_default(),
|
||||
};
|
||||
|
||||
if let Some(ref f) = filter {
|
||||
|
@ -1281,6 +1307,7 @@ impl miner::MinerService for Miner {
|
|||
logs: receipt.logs.clone(),
|
||||
log_bloom: receipt.log_bloom,
|
||||
outcome: receipt.outcome.clone(),
|
||||
effective_gas_price: tx.effective_gas_price(pending.header.base_fee()),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
@ -1354,7 +1381,7 @@ impl miner::MinerService for Miner {
|
|||
}
|
||||
|
||||
fn is_currently_sealing(&self) -> bool {
|
||||
self.sealing.lock().enabled
|
||||
self.sealing.lock().enabled && self.engine.is_allowed_to_seal()
|
||||
}
|
||||
|
||||
fn work_package<C>(&self, chain: &C) -> Option<(H256, BlockNumber, u64, U256)>
|
||||
|
@ -1432,8 +1459,21 @@ impl miner::MinerService for Miner {
|
|||
}
|
||||
|
||||
// t_nb 10.1 First update gas limit in transaction queue and minimal gas price.
|
||||
let gas_limit = *chain.best_block_header().gas_limit();
|
||||
self.update_transaction_queue_limits(gas_limit);
|
||||
let base_fee = self.engine.calculate_base_fee(&chain.best_block_header());
|
||||
let gas_limit = chain.best_block_header().gas_limit()
|
||||
// multiplication neccesary only if OE nodes are the only miners in network, not really essential but wont hurt
|
||||
* if self.engine.gas_limit_override(&chain.best_block_header()).is_none() {
|
||||
self
|
||||
.engine
|
||||
.schedule(chain.best_block_header().number() + 1)
|
||||
.eip1559_gas_limit_bump
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let allow_non_eoa_sender = self
|
||||
.engine
|
||||
.allow_non_eoa_sender(chain.best_block_header().number() + 1);
|
||||
self.update_transaction_queue_limits(gas_limit, base_fee, allow_non_eoa_sender);
|
||||
|
||||
// t_nb 10.2 Then import all transactions from retracted blocks (retracted means from side chain).
|
||||
let client = self.pool_client(chain);
|
||||
|
@ -1575,7 +1615,9 @@ mod tests {
|
|||
|
||||
use client::{ChainInfo, EachBlockWith, ImportSealedBlock, TestBlockChainClient};
|
||||
use miner::{MinerService, PendingOrdering};
|
||||
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec};
|
||||
use test_helpers::{
|
||||
dummy_engine_signer_with_address, generate_dummy_client, generate_dummy_client_with_spec,
|
||||
};
|
||||
use types::transaction::{Transaction, TypedTransaction};
|
||||
|
||||
#[test]
|
||||
|
@ -1632,8 +1674,10 @@ mod tests {
|
|||
pool_verification_options: pool::verifier::Options {
|
||||
minimal_gas_price: 0.into(),
|
||||
block_gas_limit: U256::max_value(),
|
||||
block_base_fee: None,
|
||||
tx_gas_limit: U256::max_value(),
|
||||
no_early_reject: false,
|
||||
allow_non_eoa_sender: false,
|
||||
},
|
||||
},
|
||||
GasPricer::new_fixed(0u64.into()),
|
||||
|
@ -1779,6 +1823,40 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_activate_eip_3607_according_to_spec() {
|
||||
// given
|
||||
let spec = Spec::new_test_eip3607();
|
||||
let miner = Miner::new_for_tests(&spec, None);
|
||||
let client = TestBlockChainClient::new_with_spec(spec);
|
||||
|
||||
let imported = [H256::zero()];
|
||||
let empty = &[];
|
||||
|
||||
// the client best block is below EIP-3607 transition number
|
||||
miner.chain_new_blocks(&client, &imported, empty, &imported, empty, false);
|
||||
assert!(
|
||||
miner.queue_status().options.allow_non_eoa_sender,
|
||||
"The client best block is below EIP-3607 transition number. Non EOA senders should be allowed"
|
||||
);
|
||||
|
||||
// the client best block equals EIP-3607 transition number
|
||||
client.add_block(EachBlockWith::Nothing, |header| header);
|
||||
miner.chain_new_blocks(&client, &imported, empty, &imported, empty, false);
|
||||
assert!(
|
||||
!miner.queue_status().options.allow_non_eoa_sender,
|
||||
"The client best block equals EIP-3607 transition number. Non EOA senders should not be allowed"
|
||||
);
|
||||
|
||||
// the client best block is above EIP-3607 transition number
|
||||
client.add_block(EachBlockWith::Nothing, |header| header);
|
||||
miner.chain_new_blocks(&client, &imported, empty, &imported, empty, false);
|
||||
assert!(
|
||||
!miner.queue_status().options.allow_non_eoa_sender,
|
||||
"The client best block is above EIP-3607 transition number. Non EOA senders should not be allowed"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_treat_unfamiliar_locals_selectively() {
|
||||
// given
|
||||
|
@ -2044,6 +2122,31 @@ mod tests {
|
|||
assert!(miner.is_currently_sealing());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_mine_if_is_not_allowed_to_seal() {
|
||||
let spec = Spec::new_test_round();
|
||||
let miner = Miner::new_for_tests_force_sealing(&spec, None, true);
|
||||
assert!(!miner.is_currently_sealing());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_mine_if_is_allowed_to_seal() {
|
||||
let verifier: Address = [
|
||||
0x7d, 0x57, 0x7a, 0x59, 0x7b, 0x27, 0x42, 0xb4, 0x98, 0xcb, 0x5c, 0xf0, 0xc2, 0x6c,
|
||||
0xdc, 0xd7, 0x26, 0xd3, 0x9e, 0x6e,
|
||||
]
|
||||
.into();
|
||||
|
||||
let spec = Spec::new_test_round();
|
||||
let client: Arc<dyn EngineClient> = generate_dummy_client(2);
|
||||
|
||||
let miner = Miner::new_for_tests_force_sealing(&spec, None, true);
|
||||
miner.engine.register_client(Arc::downgrade(&client));
|
||||
miner.set_author(Author::Sealer(dummy_engine_signer_with_address(verifier)));
|
||||
|
||||
assert!(miner.is_currently_sealing());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_set_new_minimum_gas_price() {
|
||||
// Creates a new GasPricer::Fixed behind the scenes
|
||||
|
|
|
@ -226,7 +226,7 @@ pub trait MinerService: Send + Sync {
|
|||
ordering: PendingOrdering,
|
||||
) -> Vec<Arc<VerifiedTransaction>>
|
||||
where
|
||||
C: ChainInfo + Nonce + Sync;
|
||||
C: BlockChain + Nonce + Sync;
|
||||
|
||||
/// Get an unfiltered list of all ready transactions.
|
||||
fn ready_transactions<C>(
|
||||
|
@ -236,7 +236,7 @@ pub trait MinerService: Send + Sync {
|
|||
ordering: PendingOrdering,
|
||||
) -> Vec<Arc<VerifiedTransaction>>
|
||||
where
|
||||
C: ChainInfo + Nonce + Sync,
|
||||
C: BlockChain + Nonce + Sync,
|
||||
{
|
||||
self.ready_transactions_filtered(chain, max_len, None, ordering)
|
||||
}
|
||||
|
@ -260,6 +260,9 @@ pub trait MinerService: Send + Sync {
|
|||
/// Suggested gas price.
|
||||
fn sensible_gas_price(&self) -> U256;
|
||||
|
||||
/// Suggested max priority fee gas price
|
||||
fn sensible_max_priority_fee(&self) -> U256;
|
||||
|
||||
/// Suggested gas limit.
|
||||
fn sensible_gas_limit(&self) -> U256;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ use types::{
|
|||
};
|
||||
|
||||
use call_contract::CallContract;
|
||||
use client::{BlockInfo, Nonce, TransactionId};
|
||||
use client::{BlockId, BlockInfo, Nonce, TransactionId};
|
||||
use engines::EthEngine;
|
||||
use miner;
|
||||
use transaction_ext::Transaction;
|
||||
|
@ -155,9 +155,8 @@ where
|
|||
) -> Result<SignedTransaction, transaction::Error> {
|
||||
self.engine
|
||||
.verify_transaction_basic(&tx, &self.best_block_header)?;
|
||||
let tx = self
|
||||
.engine
|
||||
.verify_transaction_unordered(tx, &self.best_block_header)?;
|
||||
|
||||
let tx = SignedTransaction::new(tx)?;
|
||||
|
||||
self.engine
|
||||
.machine()
|
||||
|
@ -169,6 +168,7 @@ where
|
|||
pool::client::AccountDetails {
|
||||
nonce: self.cached_nonces.account_nonce(address),
|
||||
balance: self.chain.latest_balance(address),
|
||||
code_hash: self.chain.code_hash(address, BlockId::Latest),
|
||||
is_local: self.accounts.is_local(address),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,17 @@
|
|||
//! Block RLP compression.
|
||||
|
||||
use bytes::Bytes;
|
||||
use ethereum_types::H256;
|
||||
use ethereum_types::{H256, U256};
|
||||
use hash::keccak;
|
||||
use rlp::{DecoderError, Rlp, RlpStream};
|
||||
use triehash::ordered_trie_root;
|
||||
use types::{block::Block, header::Header, transaction::TypedTransaction, views::BlockView};
|
||||
use types::{
|
||||
block::Block, header::Header, transaction::TypedTransaction, views::BlockView, BlockNumber,
|
||||
};
|
||||
|
||||
const HEADER_FIELDS: usize = 8;
|
||||
const BLOCK_FIELDS: usize = 2;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AbridgedBlock {
|
||||
rlp: Bytes,
|
||||
}
|
||||
|
@ -43,12 +45,19 @@ impl AbridgedBlock {
|
|||
|
||||
/// Given a full block view, trim out the parent hash and block number,
|
||||
/// producing new rlp.
|
||||
pub fn from_block_view(block_view: &BlockView) -> Self {
|
||||
pub fn from_block_view(block_view: &BlockView, eip1559_transition: BlockNumber) -> Self {
|
||||
let header = block_view.header_view();
|
||||
let seal_fields = header.seal();
|
||||
let eip1559 = header.number() >= eip1559_transition;
|
||||
let seal_fields = header.seal(eip1559);
|
||||
|
||||
let nmb_of_elements = if eip1559 {
|
||||
HEADER_FIELDS + seal_fields.len() + BLOCK_FIELDS + 1
|
||||
} else {
|
||||
HEADER_FIELDS + seal_fields.len() + BLOCK_FIELDS
|
||||
};
|
||||
|
||||
// 10 header fields, unknown number of seal fields, and 2 block fields.
|
||||
let mut stream = RlpStream::new_list(HEADER_FIELDS + seal_fields.len() + BLOCK_FIELDS);
|
||||
let mut stream = RlpStream::new_list(nmb_of_elements);
|
||||
|
||||
// write header values.
|
||||
stream
|
||||
|
@ -64,13 +73,17 @@ impl AbridgedBlock {
|
|||
// write block values.
|
||||
|
||||
TypedTransaction::rlp_append_list(&mut stream, &block_view.transactions());
|
||||
stream.append_list(&block_view.uncles());
|
||||
stream.append_list(&block_view.uncles(eip1559_transition));
|
||||
|
||||
// write seal fields.
|
||||
for field in seal_fields {
|
||||
stream.append_raw(&field, 1);
|
||||
}
|
||||
|
||||
if eip1559 {
|
||||
stream.append(&header.base_fee());
|
||||
}
|
||||
|
||||
AbridgedBlock { rlp: stream.out() }
|
||||
}
|
||||
|
||||
|
@ -82,6 +95,7 @@ impl AbridgedBlock {
|
|||
parent_hash: H256,
|
||||
number: u64,
|
||||
receipts_root: H256,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<Block, DecoderError> {
|
||||
let rlp = Rlp::new(&self.rlp);
|
||||
|
||||
|
@ -98,7 +112,7 @@ impl AbridgedBlock {
|
|||
header.set_extra_data(rlp.val_at(7)?);
|
||||
|
||||
let transactions = TypedTransaction::decode_rlp_list(&rlp.at(8)?)?;
|
||||
let uncles: Vec<Header> = rlp.list_at(9)?;
|
||||
let uncles = Header::decode_rlp_list(&rlp.at(9)?, eip1559_transition)?;
|
||||
|
||||
header.set_transactions_root(ordered_trie_root(rlp.at(8)?.iter().map(|r| {
|
||||
if r.is_list() {
|
||||
|
@ -115,13 +129,21 @@ impl AbridgedBlock {
|
|||
header.set_uncles_hash(keccak(uncles_rlp.as_raw()));
|
||||
|
||||
let mut seal_fields = Vec::new();
|
||||
for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count()? {
|
||||
let last_seal_index = if number >= eip1559_transition {
|
||||
rlp.item_count()? - 1
|
||||
} else {
|
||||
rlp.item_count()?
|
||||
};
|
||||
for i in (HEADER_FIELDS + BLOCK_FIELDS)..last_seal_index {
|
||||
let seal_rlp = rlp.at(i)?;
|
||||
seal_fields.push(seal_rlp.as_raw().to_owned());
|
||||
}
|
||||
|
||||
header.set_seal(seal_fields);
|
||||
|
||||
if number >= eip1559_transition {
|
||||
header.set_base_fee(Some(rlp.val_at::<U256>(rlp.item_count()? - 1)?));
|
||||
}
|
||||
|
||||
Ok(Block {
|
||||
header: header,
|
||||
transactions: transactions,
|
||||
|
@ -141,6 +163,7 @@ mod tests {
|
|||
transaction::{Action, Transaction, TypedTransaction},
|
||||
view,
|
||||
views::BlockView,
|
||||
BlockNumber,
|
||||
};
|
||||
|
||||
fn encode_block(b: &Block) -> Bytes {
|
||||
|
@ -153,10 +176,29 @@ mod tests {
|
|||
let receipts_root = b.header.receipts_root().clone();
|
||||
let encoded = encode_block(&b);
|
||||
|
||||
let abridged = AbridgedBlock::from_block_view(&view!(BlockView, &encoded));
|
||||
let abridged =
|
||||
AbridgedBlock::from_block_view(&view!(BlockView, &encoded), BlockNumber::max_value());
|
||||
assert_eq!(
|
||||
abridged
|
||||
.to_block(H256::default(), 0, receipts_root)
|
||||
.to_block(H256::default(), 0, receipts_root, BlockNumber::max_value())
|
||||
.unwrap(),
|
||||
b
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eip1559_block_abridging() {
|
||||
let mut b = Block::default();
|
||||
b.header.set_base_fee(Some(U256::from(100)));
|
||||
b.header.set_seal(vec![vec![50u8], vec![60u8]]);
|
||||
let receipts_root = b.header.receipts_root().clone();
|
||||
let encoded = encode_block(&b);
|
||||
|
||||
let abridged =
|
||||
AbridgedBlock::from_block_view(&view!(BlockView, &encoded), BlockNumber::default());
|
||||
assert_eq!(
|
||||
abridged
|
||||
.to_block(H256::default(), 0, receipts_root, BlockNumber::default())
|
||||
.unwrap(),
|
||||
b
|
||||
);
|
||||
|
@ -169,10 +211,11 @@ mod tests {
|
|||
let receipts_root = b.header.receipts_root().clone();
|
||||
let encoded = encode_block(&b);
|
||||
|
||||
let abridged = AbridgedBlock::from_block_view(&view!(BlockView, &encoded));
|
||||
let abridged =
|
||||
AbridgedBlock::from_block_view(&view!(BlockView, &encoded), BlockNumber::max_value());
|
||||
assert_eq!(
|
||||
abridged
|
||||
.to_block(H256::default(), 2, receipts_root)
|
||||
.to_block(H256::default(), 2, receipts_root, BlockNumber::max_value())
|
||||
.unwrap(),
|
||||
b
|
||||
);
|
||||
|
@ -213,10 +256,13 @@ mod tests {
|
|||
|
||||
let encoded = encode_block(&b);
|
||||
|
||||
let abridged = AbridgedBlock::from_block_view(&view!(BlockView, &encoded[..]));
|
||||
let abridged = AbridgedBlock::from_block_view(
|
||||
&view!(BlockView, &encoded[..]),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
assert_eq!(
|
||||
abridged
|
||||
.to_block(H256::default(), 0, receipts_root)
|
||||
.to_block(H256::default(), 0, receipts_root, BlockNumber::max_value())
|
||||
.unwrap(),
|
||||
b
|
||||
);
|
||||
|
|
|
@ -38,6 +38,7 @@ use itertools::{Itertools, Position};
|
|||
use rlp::{Rlp, RlpStream};
|
||||
use types::{
|
||||
encoded, header::Header, ids::BlockId, receipt::TypedReceipt, transaction::TypedTransaction,
|
||||
BlockNumber,
|
||||
};
|
||||
|
||||
/// Snapshot creation and restoration for PoA chains.
|
||||
|
@ -61,6 +62,7 @@ impl SnapshotComponents for PoaSnapshot {
|
|||
sink: &mut ChunkSink,
|
||||
_progress: &Progress,
|
||||
preferred_size: usize,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<(), Error> {
|
||||
let number = chain
|
||||
.block_number(&block_at)
|
||||
|
@ -107,7 +109,7 @@ impl SnapshotComponents for PoaSnapshot {
|
|||
.block(&block_at)
|
||||
.and_then(|b| chain.block_receipts(&block_at).map(|r| (b, r)))
|
||||
.ok_or_else(|| Error::BlockNotFound(block_at))?;
|
||||
let block = block.decode()?;
|
||||
let block = block.decode(eip1559_transition)?;
|
||||
|
||||
let parent_td = chain
|
||||
.block_details(block.header.parent_hash())
|
||||
|
@ -200,7 +202,8 @@ impl ChunkRebuilder {
|
|||
use engines::ConstructedVerifier;
|
||||
|
||||
// decode.
|
||||
let header: Header = transition_rlp.val_at(0)?;
|
||||
let header =
|
||||
Header::decode_rlp(&transition_rlp.at(0)?, engine.params().eip1559_transition)?;
|
||||
let epoch_data: Bytes = transition_rlp.val_at(1)?;
|
||||
|
||||
trace!(target: "snapshot", "verifying transition to epoch at block {}", header.number());
|
||||
|
@ -350,9 +353,12 @@ impl Rebuilder for ChunkRebuilder {
|
|||
|
||||
let last_rlp = rlp.at(num_items - 1)?;
|
||||
let block = Block {
|
||||
header: last_rlp.val_at(0)?,
|
||||
header: Header::decode_rlp(&last_rlp.at(0)?, engine.params().eip1559_transition)?,
|
||||
transactions: TypedTransaction::decode_rlp_list(&last_rlp.at(1)?)?,
|
||||
uncles: last_rlp.list_at(2)?,
|
||||
uncles: Header::decode_rlp_list(
|
||||
&last_rlp.at(2)?,
|
||||
engine.params().eip1559_transition,
|
||||
)?,
|
||||
};
|
||||
let block_data = block.rlp_bytes();
|
||||
let receipts = TypedReceipt::decode_rlp_list(&last_rlp.at(3)?)?;
|
||||
|
|
|
@ -22,6 +22,7 @@ use std::sync::{atomic::AtomicBool, Arc};
|
|||
use blockchain::{BlockChain, BlockChainDB};
|
||||
use engines::EthEngine;
|
||||
use snapshot::{Error, ManifestData, Progress};
|
||||
use types::BlockNumber;
|
||||
|
||||
use ethereum_types::H256;
|
||||
|
||||
|
@ -49,6 +50,7 @@ pub trait SnapshotComponents: Send {
|
|||
chunk_sink: &mut ChunkSink,
|
||||
progress: &Progress,
|
||||
preferred_size: usize,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// Create a rebuilder, which will have chunks fed into it in aribtrary
|
||||
|
|
|
@ -38,7 +38,7 @@ use ethereum_types::H256;
|
|||
use rand::rngs::OsRng;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use snapshot::{block::AbridgedBlock, Error, ManifestData, Progress};
|
||||
use types::encoded;
|
||||
use types::{encoded, BlockNumber};
|
||||
|
||||
/// Snapshot creation and restoration for PoW chains.
|
||||
/// This includes blocks from the head of the chain as a
|
||||
|
@ -70,6 +70,7 @@ impl SnapshotComponents for PowSnapshot {
|
|||
chunk_sink: &mut ChunkSink,
|
||||
progress: &Progress,
|
||||
preferred_size: usize,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<(), Error> {
|
||||
PowWorker {
|
||||
chain: chain,
|
||||
|
@ -79,7 +80,7 @@ impl SnapshotComponents for PowSnapshot {
|
|||
progress: progress,
|
||||
preferred_size: preferred_size,
|
||||
}
|
||||
.chunk_all(self.blocks)
|
||||
.chunk_all(self.blocks, eip1559_transition)
|
||||
}
|
||||
|
||||
fn rebuilder(
|
||||
|
@ -119,7 +120,11 @@ struct PowWorker<'a> {
|
|||
impl<'a> PowWorker<'a> {
|
||||
// Repeatedly fill the buffers and writes out chunks, moving backwards from starting block hash.
|
||||
// Loops until we reach the first desired block, and writes out the remainder.
|
||||
fn chunk_all(&mut self, snapshot_blocks: u64) -> Result<(), Error> {
|
||||
fn chunk_all(
|
||||
&mut self,
|
||||
snapshot_blocks: u64,
|
||||
eip1559_transition: BlockNumber,
|
||||
) -> Result<(), Error> {
|
||||
let mut loaded_size = 0;
|
||||
let mut last = self.current_hash;
|
||||
|
||||
|
@ -140,7 +145,8 @@ impl<'a> PowWorker<'a> {
|
|||
})
|
||||
.ok_or_else(|| Error::BlockNotFound(self.current_hash))?;
|
||||
|
||||
let abridged_rlp = AbridgedBlock::from_block_view(&block.view()).into_inner();
|
||||
let abridged_rlp =
|
||||
AbridgedBlock::from_block_view(&block.view(), eip1559_transition).into_inner();
|
||||
|
||||
let pair = {
|
||||
let mut pair_stream = RlpStream::new_list(2);
|
||||
|
@ -301,7 +307,12 @@ impl Rebuilder for PowRebuilder {
|
|||
}
|
||||
}));
|
||||
|
||||
let block = abridged_block.to_block(parent_hash, cur_number, receipts_root)?;
|
||||
let block = abridged_block.to_block(
|
||||
parent_hash,
|
||||
cur_number,
|
||||
receipts_root,
|
||||
engine.params().eip1559_transition,
|
||||
)?;
|
||||
let block_bytes = encoded::Block::new(block.rlp_bytes());
|
||||
let is_best = cur_number == self.best_number;
|
||||
|
||||
|
|
|
@ -273,6 +273,7 @@ pub fn chunk_secondary<'a>(
|
|||
&mut chunk_sink,
|
||||
progress,
|
||||
PREFERRED_CHUNK_SIZE,
|
||||
chain.eip1559_transition,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
@ -621,7 +622,8 @@ pub fn verify_old_block(
|
|||
if always || rng.gen::<f32>() <= POW_VERIFY_RATE {
|
||||
engine.verify_block_unordered(header)?;
|
||||
match chain.block_header_data(header.parent_hash()) {
|
||||
Some(parent) => engine.verify_block_family(header, &parent.decode()?),
|
||||
Some(parent) => engine
|
||||
.verify_block_family(header, &parent.decode(engine.params().eip1559_transition)?),
|
||||
None => Ok(()),
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -117,7 +117,12 @@ impl Restoration {
|
|||
|
||||
let raw_db = params.db;
|
||||
|
||||
let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone());
|
||||
let chain = BlockChain::new(
|
||||
Default::default(),
|
||||
params.genesis,
|
||||
raw_db.clone(),
|
||||
params.engine.params().eip1559_transition,
|
||||
);
|
||||
let components = params
|
||||
.engine
|
||||
.snapshot_components()
|
||||
|
@ -386,7 +391,12 @@ impl Service {
|
|||
let cur_chain_info = self.client.chain_info();
|
||||
|
||||
let next_db = self.restoration_db_handler.open(&rest_db)?;
|
||||
let next_chain = BlockChain::new(Default::default(), &[], next_db.clone());
|
||||
let next_chain = BlockChain::new(
|
||||
Default::default(),
|
||||
&[],
|
||||
next_db.clone(),
|
||||
self.engine.params().eip1559_transition,
|
||||
);
|
||||
let next_chain_info = next_chain.chain_info();
|
||||
|
||||
// The old database looks like this:
|
||||
|
|
|
@ -171,7 +171,12 @@ pub fn restore(
|
|||
|
||||
let mut state = StateRebuilder::new(db.key_value().clone(), journaldb::Algorithm::Archive);
|
||||
let mut secondary = {
|
||||
let chain = BlockChain::new(Default::default(), genesis, db.clone());
|
||||
let chain = BlockChain::new(
|
||||
Default::default(),
|
||||
genesis,
|
||||
db.clone(),
|
||||
engine.params().eip1559_transition,
|
||||
);
|
||||
components.rebuilder(chain, db, manifest).unwrap()
|
||||
};
|
||||
|
||||
|
|
|
@ -51,7 +51,12 @@ fn chunk_and_restore(amount: u64) {
|
|||
let snapshot_path = tempdir.path().join("SNAP");
|
||||
|
||||
let old_db = test_helpers::new_db();
|
||||
let bc = BlockChain::new(Default::default(), genesis.encoded().raw(), old_db.clone());
|
||||
let bc = BlockChain::new(
|
||||
Default::default(),
|
||||
genesis.encoded().raw(),
|
||||
old_db.clone(),
|
||||
engine.params().eip1559_transition,
|
||||
);
|
||||
|
||||
// build the blockchain.
|
||||
let mut batch = DBTransaction::new();
|
||||
|
@ -96,7 +101,12 @@ fn chunk_and_restore(amount: u64) {
|
|||
|
||||
// restore it.
|
||||
let new_db = test_helpers::new_db();
|
||||
let new_chain = BlockChain::new(Default::default(), genesis.encoded().raw(), new_db.clone());
|
||||
let new_chain = BlockChain::new(
|
||||
Default::default(),
|
||||
genesis.encoded().raw(),
|
||||
new_db.clone(),
|
||||
engine.params().eip1559_transition,
|
||||
);
|
||||
let mut rebuilder = SNAPSHOT_MODE
|
||||
.rebuilder(new_chain, new_db.clone(), &manifest)
|
||||
.unwrap();
|
||||
|
@ -113,7 +123,12 @@ fn chunk_and_restore(amount: u64) {
|
|||
drop(rebuilder);
|
||||
|
||||
// and test it.
|
||||
let new_chain = BlockChain::new(Default::default(), genesis.encoded().raw(), new_db);
|
||||
let new_chain = BlockChain::new(
|
||||
Default::default(),
|
||||
genesis.encoded().raw(),
|
||||
new_db,
|
||||
engine.params().eip1559_transition,
|
||||
);
|
||||
assert_eq!(new_chain.best_block_hash(), best_hash);
|
||||
}
|
||||
|
||||
|
@ -150,6 +165,7 @@ fn checks_flag() {
|
|||
Default::default(),
|
||||
genesis.last().encoded().raw(),
|
||||
db.clone(),
|
||||
engine.params().eip1559_transition,
|
||||
);
|
||||
|
||||
let manifest = ::snapshot::ManifestData {
|
||||
|
|
|
@ -240,7 +240,9 @@ fn keep_ancient_blocks() {
|
|||
let block_hash = bc.block_hash(block_number).unwrap();
|
||||
let block = bc.block(&block_hash).unwrap();
|
||||
client2
|
||||
.import_block(Unverified::from_rlp(block.into_inner()).unwrap())
|
||||
.import_block(
|
||||
Unverified::from_rlp(block.into_inner(), spec.params().eip1559_transition).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ pub struct Genesis {
|
|||
pub gas_used: U256,
|
||||
/// Extra data.
|
||||
pub extra_data: Vec<u8>,
|
||||
/// Base fee.
|
||||
pub base_fee: Option<U256>,
|
||||
}
|
||||
|
||||
impl From<ethjson::spec::Genesis> for Genesis {
|
||||
|
@ -63,6 +65,7 @@ impl From<ethjson::spec::Genesis> for Genesis {
|
|||
state_root: g.state_root.map(Into::into),
|
||||
gas_used: g.gas_used.map_or_else(U256::zero, Into::into),
|
||||
extra_data: g.extra_data.map_or_else(Vec::new, Into::into),
|
||||
base_fee: g.base_fee_per_gas.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,16 @@ pub struct CommonParams {
|
|||
pub eip2929_transition: BlockNumber,
|
||||
/// Number of first block where EIP-2930 rules begin.
|
||||
pub eip2930_transition: BlockNumber,
|
||||
/// Number of first block where EIP-1559 rules begin.
|
||||
pub eip1559_transition: BlockNumber,
|
||||
/// Number of first block where EIP-3198 rules begin. Basefee opcode.
|
||||
pub eip3198_transition: BlockNumber,
|
||||
/// Number of first block where EIP-3529 rules begin.
|
||||
pub eip3529_transition: BlockNumber,
|
||||
/// Number of first block where EIP-3541 rule begins.
|
||||
pub eip3541_transition: BlockNumber,
|
||||
/// Number of first block where EIP-3607 rule begins.
|
||||
pub eip3607_transition: BlockNumber,
|
||||
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||
pub dust_protection_transition: BlockNumber,
|
||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
||||
|
@ -169,6 +179,22 @@ pub struct CommonParams {
|
|||
pub transaction_permission_contract_transition: BlockNumber,
|
||||
/// Maximum size of transaction's RLP payload
|
||||
pub max_transaction_size: usize,
|
||||
/// Base fee max change denominator
|
||||
pub eip1559_base_fee_max_change_denominator: Option<U256>,
|
||||
/// Elasticity multiplier
|
||||
pub eip1559_elasticity_multiplier: U256,
|
||||
/// Default value for the block base fee
|
||||
pub eip1559_base_fee_initial_value: U256,
|
||||
/// Min value for the block base fee.
|
||||
pub eip1559_base_fee_min_value: Option<U256>,
|
||||
/// Block at which the min value for the base fee starts to be used.
|
||||
pub eip1559_base_fee_min_value_transition: BlockNumber,
|
||||
/// Address where EIP-1559 burnt fee will be accrued to.
|
||||
pub eip1559_fee_collector: Option<Address>,
|
||||
/// Block at which the fee collector should start being used.
|
||||
pub eip1559_fee_collector_transition: BlockNumber,
|
||||
/// Block at which zero gas price transactions start being checked with Certifier contract.
|
||||
pub validate_service_transactions_transition: BlockNumber,
|
||||
}
|
||||
|
||||
impl CommonParams {
|
||||
|
@ -215,6 +241,18 @@ impl CommonParams {
|
|||
schedule.have_subs = block_number >= self.eip2315_transition;
|
||||
schedule.eip2929 = block_number >= self.eip2929_transition;
|
||||
schedule.eip2930 = block_number >= self.eip2930_transition;
|
||||
schedule.eip3541 = block_number >= self.eip3541_transition;
|
||||
schedule.eip1559 = block_number >= self.eip1559_transition;
|
||||
schedule.eip3198 = block_number >= self.eip3198_transition;
|
||||
if schedule.eip1559 {
|
||||
schedule.eip1559_elasticity_multiplier = self.eip1559_elasticity_multiplier.as_usize();
|
||||
|
||||
schedule.eip1559_gas_limit_bump = if block_number == self.eip1559_transition {
|
||||
schedule.eip1559_elasticity_multiplier
|
||||
} else {
|
||||
1
|
||||
};
|
||||
}
|
||||
|
||||
if block_number >= self.eip1884_transition {
|
||||
schedule.have_selfbalance = true;
|
||||
|
@ -245,6 +283,11 @@ impl CommonParams {
|
|||
schedule.sload_gas = ::vm::schedule::EIP2929_WARM_STORAGE_READ_COST;
|
||||
schedule.sstore_reset_gas = ::vm::schedule::EIP2929_SSTORE_RESET_GAS;
|
||||
}
|
||||
if block_number >= self.eip3529_transition {
|
||||
schedule.suicide_refund_gas = 0;
|
||||
schedule.sstore_refund_gas = ::vm::schedule::EIP3529_SSTORE_CLEARS_SCHEDULE;
|
||||
schedule.max_refund_quotient = ::vm::schedule::EIP3529_MAX_REFUND_QUOTIENT;
|
||||
}
|
||||
|
||||
if block_number >= self.dust_protection_transition {
|
||||
schedule.kill_dust = match self.remove_dust_contracts {
|
||||
|
@ -378,9 +421,22 @@ impl From<ethjson::spec::Params> for CommonParams {
|
|||
eip2930_transition: p
|
||||
.eip2930_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip1559_transition: p
|
||||
.eip1559_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip3198_transition: p
|
||||
.eip3198_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip3529_transition: p
|
||||
.eip3529_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip3541_transition: p
|
||||
.eip3541_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
dust_protection_transition: p
|
||||
.dust_protection_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip3607_transition: p.eip3607_transition.map_or(0, Into::into),
|
||||
nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
|
||||
remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false),
|
||||
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
||||
|
@ -407,6 +463,26 @@ impl From<ethjson::spec::Params> for CommonParams {
|
|||
kip6_transition: p
|
||||
.kip6_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip1559_base_fee_max_change_denominator: p
|
||||
.eip1559_base_fee_max_change_denominator
|
||||
.map(Into::into),
|
||||
eip1559_elasticity_multiplier: p
|
||||
.eip1559_elasticity_multiplier
|
||||
.map_or_else(U256::zero, Into::into),
|
||||
eip1559_base_fee_initial_value: p
|
||||
.eip1559_base_fee_initial_value
|
||||
.map_or_else(U256::zero, Into::into),
|
||||
eip1559_base_fee_min_value: p.eip1559_base_fee_min_value.map(Into::into),
|
||||
eip1559_base_fee_min_value_transition: p
|
||||
.eip1559_base_fee_min_value_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip1559_fee_collector: p.eip1559_fee_collector.map(Into::into),
|
||||
eip1559_fee_collector_transition: p
|
||||
.eip1559_fee_collector_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
validate_service_transactions_transition: p
|
||||
.validate_service_transactions_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,6 +557,8 @@ pub struct Spec {
|
|||
pub extra_data: Bytes,
|
||||
/// Each seal field, expressed as RLP, concatenated.
|
||||
pub seal_rlp: Bytes,
|
||||
/// Base fee,
|
||||
pub base_fee: Option<U256>,
|
||||
|
||||
/// List of hard forks in the network.
|
||||
pub hard_forks: BTreeSet<BlockNumber>,
|
||||
|
@ -517,6 +595,7 @@ impl Clone for Spec {
|
|||
constructors: self.constructors.clone(),
|
||||
state_root_memo: RwLock::new(*self.state_root_memo.read()),
|
||||
genesis_state: self.genesis_state.clone(),
|
||||
base_fee: self.base_fee.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -575,6 +654,7 @@ fn load_from(spec_params: SpecParams, s: ethjson::spec::Spec) -> Result<Spec, Er
|
|||
timestamp: g.timestamp,
|
||||
extra_data: g.extra_data,
|
||||
seal_rlp: seal_rlp,
|
||||
base_fee: g.base_fee,
|
||||
hard_forks,
|
||||
constructors: s
|
||||
.accounts
|
||||
|
@ -667,6 +747,10 @@ impl Spec {
|
|||
params.eip2315_transition,
|
||||
params.eip2929_transition,
|
||||
params.eip2930_transition,
|
||||
params.eip1559_transition,
|
||||
params.eip3198_transition,
|
||||
params.eip3529_transition,
|
||||
params.eip3541_transition,
|
||||
params.dust_protection_transition,
|
||||
params.wasm_activation_transition,
|
||||
params.wasm_disable_transition,
|
||||
|
@ -674,6 +758,9 @@ impl Spec {
|
|||
params.kip6_transition,
|
||||
params.max_code_size_transition,
|
||||
params.transaction_permission_contract_transition,
|
||||
params.eip1559_fee_collector_transition,
|
||||
params.eip1559_base_fee_min_value_transition,
|
||||
params.validate_service_transactions_transition,
|
||||
];
|
||||
// BUG: Rinkeby has homestead transition at block 1 but we can't reflect that in specs for non-Ethash networks
|
||||
if params.network_id == 0x4 {
|
||||
|
@ -771,6 +858,7 @@ impl Spec {
|
|||
last_hashes: Default::default(),
|
||||
gas_used: U256::zero(),
|
||||
gas_limit: U256::max_value(),
|
||||
base_fee: None,
|
||||
};
|
||||
|
||||
if !self.constructors.is_empty() {
|
||||
|
@ -879,6 +967,7 @@ impl Spec {
|
|||
let r = Rlp::new(&self.seal_rlp);
|
||||
r.iter().map(|f| f.as_raw().to_vec()).collect()
|
||||
});
|
||||
header.set_base_fee(self.base_fee.clone());
|
||||
trace!(target: "spec", "Header hash is {}", header.hash());
|
||||
header
|
||||
}
|
||||
|
@ -907,6 +996,7 @@ impl Spec {
|
|||
self.timestamp = g.timestamp;
|
||||
self.extra_data = g.extra_data;
|
||||
self.seal_rlp = seal_rlp;
|
||||
self.base_fee = g.base_fee;
|
||||
}
|
||||
|
||||
/// Alter the value of the genesis state.
|
||||
|
@ -990,6 +1080,7 @@ impl Spec {
|
|||
gas_limit: U256::max_value(),
|
||||
last_hashes: Arc::new(Vec::new()),
|
||||
gas_used: 0.into(),
|
||||
base_fee: genesis.base_fee(),
|
||||
};
|
||||
|
||||
let from = Address::default();
|
||||
|
@ -1063,6 +1154,13 @@ impl Spec {
|
|||
load_bundled!("test/constructor")
|
||||
}
|
||||
|
||||
/// Create a new Spec which is a NullEngine consensus with EIP3607 transition equal to 2,
|
||||
/// and with a contract at address '0x71562b71999873DB5b286dF957af199Ec94617F7'.
|
||||
#[cfg(any(test, feature = "test-helpers"))]
|
||||
pub fn new_test_eip3607() -> Self {
|
||||
load_bundled!("test/eip3607_test")
|
||||
}
|
||||
|
||||
/// Create a new Spec with Autority Round randomness contract
|
||||
#[cfg(any(test, feature = "test-helpers"))]
|
||||
pub fn new_test_round_randomness_contract() -> Spec {
|
||||
|
|
|
@ -39,12 +39,15 @@ use types::{
|
|||
transaction::{Action, SignedTransaction, Transaction, TypedTransaction},
|
||||
view,
|
||||
views::BlockView,
|
||||
BlockNumber,
|
||||
};
|
||||
|
||||
use block::{Drain, OpenBlock};
|
||||
use client::{
|
||||
ChainInfo, ChainMessageType, ChainNotify, Client, ClientConfig, ImportBlock, PrepareOpenBlock,
|
||||
};
|
||||
use engines::EngineSigner;
|
||||
use ethjson::crypto::publickey::{Public, Signature};
|
||||
use factory::Factories;
|
||||
use miner::Miner;
|
||||
use spec::Spec;
|
||||
|
@ -222,14 +225,17 @@ where
|
|||
.seal(test_engine, vec![])
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = client.import_block(Unverified::from_rlp(b.rlp_bytes()).unwrap()) {
|
||||
if let Err(e) = client.import_block(
|
||||
Unverified::from_rlp(b.rlp_bytes(), test_engine.params().eip1559_transition).unwrap(),
|
||||
) {
|
||||
panic!(
|
||||
"error importing block which is valid by definition: {:?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
last_header = view!(BlockView, &b.rlp_bytes()).header();
|
||||
last_header =
|
||||
view!(BlockView, &b.rlp_bytes()).header(test_engine.params().eip1559_transition);
|
||||
db = b.drain().state.drop().1;
|
||||
}
|
||||
client.flush_queue();
|
||||
|
@ -266,9 +272,13 @@ pub fn push_blocks_to_client(
|
|||
rolling_block_number = rolling_block_number + 1;
|
||||
rolling_timestamp = rolling_timestamp + 10;
|
||||
|
||||
if let Err(e) =
|
||||
client.import_block(Unverified::from_rlp(create_test_block(&header)).unwrap())
|
||||
{
|
||||
if let Err(e) = client.import_block(
|
||||
Unverified::from_rlp(
|
||||
create_test_block(&header),
|
||||
test_spec.params().eip1559_transition,
|
||||
)
|
||||
.unwrap(),
|
||||
) {
|
||||
panic!(
|
||||
"error importing block which is valid by definition: {:?}",
|
||||
e
|
||||
|
@ -297,7 +307,9 @@ pub fn push_block_with_transactions(client: &Arc<Client>, transactions: &[Signed
|
|||
.seal(test_engine, vec![])
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = client.import_block(Unverified::from_rlp(b.rlp_bytes()).unwrap()) {
|
||||
if let Err(e) = client.import_block(
|
||||
Unverified::from_rlp(b.rlp_bytes(), test_spec.params().eip1559_transition).unwrap(),
|
||||
) {
|
||||
panic!(
|
||||
"error importing block which is valid by definition: {:?}",
|
||||
e
|
||||
|
@ -323,7 +335,9 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> Arc<Client> {
|
|||
.unwrap();
|
||||
|
||||
for block in blocks {
|
||||
if let Err(e) = client.import_block(Unverified::from_rlp(block).unwrap()) {
|
||||
if let Err(e) = client.import_block(
|
||||
Unverified::from_rlp(block, test_spec.params().eip1559_transition).unwrap(),
|
||||
) {
|
||||
panic!("error importing block which is well-formed: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
@ -456,6 +470,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain {
|
|||
BlockChainConfig::default(),
|
||||
&create_unverifiable_block(0, H256::zero()),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
|
@ -483,6 +498,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> BlockChain {
|
|||
BlockChainConfig::default(),
|
||||
&create_unverifiable_block(0, H256::zero()),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
|
||||
let mut batch = db.key_value().transaction();
|
||||
|
@ -514,6 +530,7 @@ pub fn generate_dummy_empty_blockchain() -> BlockChain {
|
|||
BlockChainConfig::default(),
|
||||
&create_unverifiable_block(0, H256::zero()),
|
||||
db.clone(),
|
||||
BlockNumber::max_value(),
|
||||
);
|
||||
bc
|
||||
}
|
||||
|
@ -629,3 +646,38 @@ impl ChainNotify for TestNotify {
|
|||
self.messages.write().push(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns engine signer with specified address
|
||||
pub fn dummy_engine_signer_with_address(addr: Address) -> Box<dyn EngineSigner> {
|
||||
struct TestEngineSigner(Address);
|
||||
|
||||
impl TestEngineSigner {
|
||||
fn with_address(addr: Address) -> Self {
|
||||
Self(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl EngineSigner for TestEngineSigner {
|
||||
fn sign(&self, _hash: H256) -> Result<Signature, ethjson::crypto::publickey::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn address(&self) -> Address {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn decrypt(
|
||||
&self,
|
||||
_auth_data: &[u8],
|
||||
_cipher: &[u8],
|
||||
) -> Result<Vec<u8>, parity_crypto::publickey::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn public(&self) -> Option<Public> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(TestEngineSigner::with_address(addr))
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ fn imports_good_block() {
|
|||
.unwrap();
|
||||
let good_block = get_good_dummy_block();
|
||||
if client
|
||||
.import_block(Unverified::from_rlp(good_block).unwrap())
|
||||
.import_block(Unverified::from_rlp(good_block, spec.params().eip1559_transition).unwrap())
|
||||
.is_err()
|
||||
{
|
||||
panic!("error importing block being good by definition");
|
||||
|
@ -147,7 +147,12 @@ fn returns_chain_info() {
|
|||
let client = get_test_client_with_blocks(vec![dummy_block.clone()]);
|
||||
let block = view!(BlockView, &dummy_block);
|
||||
let info = client.chain_info();
|
||||
assert_eq!(info.best_block_hash, block.header().hash());
|
||||
assert_eq!(
|
||||
info.best_block_hash,
|
||||
block
|
||||
.header(client.engine().params().eip1559_transition)
|
||||
.hash()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -188,7 +193,11 @@ fn returns_block_body() {
|
|||
let client = get_test_client_with_blocks(vec![dummy_block.clone()]);
|
||||
let block = view!(BlockView, &dummy_block);
|
||||
let body = client
|
||||
.block_body(BlockId::Hash(block.header().hash()))
|
||||
.block_body(BlockId::Hash(
|
||||
block
|
||||
.header(client.engine().params().eip1559_transition)
|
||||
.hash(),
|
||||
))
|
||||
.unwrap();
|
||||
let body = body.rlp();
|
||||
assert_eq!(body.item_count().unwrap(), 2);
|
||||
|
@ -582,3 +591,12 @@ fn import_export_binary() {
|
|||
assert!(client.block_header(BlockId::Number(17)).is_some());
|
||||
assert!(client.block_header(BlockId::Number(16)).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_state_root_basic() {
|
||||
let client = generate_dummy_client(6);
|
||||
let test_spec = Spec::new_test();
|
||||
let genesis_header = test_spec.genesis_header();
|
||||
|
||||
assert!(client.state_data(genesis_header.state_root()).is_some());
|
||||
}
|
||||
|
|
|
@ -100,14 +100,17 @@ fn can_trace_block_and_uncle_reward() {
|
|||
.seal(engine, vec![])
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = client.import_block(Unverified::from_rlp(root_block.rlp_bytes()).unwrap()) {
|
||||
if let Err(e) = client.import_block(
|
||||
Unverified::from_rlp(root_block.rlp_bytes(), spec.params().eip1559_transition).unwrap(),
|
||||
) {
|
||||
panic!(
|
||||
"error importing block which is valid by definition: {:?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
last_header = view!(BlockView, &root_block.rlp_bytes()).header();
|
||||
last_header =
|
||||
view!(BlockView, &root_block.rlp_bytes()).header(spec.params().eip1559_transition);
|
||||
let root_header = last_header.clone();
|
||||
db = root_block.drain().state.drop().1;
|
||||
|
||||
|
@ -137,14 +140,17 @@ fn can_trace_block_and_uncle_reward() {
|
|||
.seal(engine, vec![])
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = client.import_block(Unverified::from_rlp(parent_block.rlp_bytes()).unwrap()) {
|
||||
if let Err(e) = client.import_block(
|
||||
Unverified::from_rlp(parent_block.rlp_bytes(), spec.params().eip1559_transition).unwrap(),
|
||||
) {
|
||||
panic!(
|
||||
"error importing block which is valid by definition: {:?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
last_header = view!(BlockView, &parent_block.rlp_bytes()).header();
|
||||
last_header =
|
||||
view!(BlockView, &parent_block.rlp_bytes()).header(spec.params().eip1559_transition);
|
||||
db = parent_block.drain().state.drop().1;
|
||||
|
||||
last_hashes.push(last_header.hash());
|
||||
|
@ -201,7 +207,9 @@ fn can_trace_block_and_uncle_reward() {
|
|||
.seal(engine, vec![])
|
||||
.unwrap();
|
||||
|
||||
let res = client.import_block(Unverified::from_rlp(block.rlp_bytes()).unwrap());
|
||||
let res = client.import_block(
|
||||
Unverified::from_rlp(block.rlp_bytes(), spec.params().eip1559_transition).unwrap(),
|
||||
);
|
||||
if res.is_err() {
|
||||
panic!("error importing block: {:#?}", res.err().unwrap());
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue