Compare commits

...

15 Commits

Author SHA1 Message Date
POA
6e06824c23 Bump to v3.3.3 2022-01-13 12:34:02 +03:00
Rim Rakhimov
43d6da6b52
Made nodes data concatenate as RLP sequences instead of bytes (#598)
* Made nodes data concatenate as RLP sequences instead of bytes

* Add test for getNodeData dispatch

* Update getNodeData to return data for non-aura networks
2022-01-13 12:26:33 +03:00
Rim Rakhimov
412d797a3b
Implements eip-3607 (#593)
* implements eip-3607

* Tests fixed

* Added tests for eip3607 functionality

* rast fmt
2022-01-10 18:01:46 +03:00
Rim Rakhimov
63bab44e3c
Makes eth_mining to return False if not is not allowed to seal (#581) 2021-12-10 14:25:39 +03:00
Rim Rakhimov
f703d01f23
Add type field for legacy transactions in RPC calls (#580)
* Added type field for legacy transactions when returned as rpc call response

* Remove invalid test
2021-12-09 11:17:42 +03:00
POA
f13fa10b8a Bump to v3.3.2, London on Sokol, effective_gas_price function enhancement 2021-12-07 14:03:48 +03:00
POA
657100cebc Bump to v3.3.1 2021-11-30 10:55:54 +03:00
POA
d2d19ec8c2 Merge branch 'dev' of https://github.com/openethereum/openethereum into dev 2021-11-30 10:39:06 +03:00
POA
0f872aff78 Add a bootnode for Kovan 2021-11-30 10:38:55 +03:00
Rim Rakhimov
405738c791
Fix for modexp overflow in debug mode (#578)
* fix modexp overflow panic in debug mode

* Added one more unit test for modexp

* Remove redundant bytes from modexp unit test

Co-authored-by: POA <33550681+poa@users.noreply.github.com>
2021-11-30 10:33:40 +03:00
Rim Rakhimov
3b19a79c37
Adds eth_maxPriorityFeePerGas implementaiton (#570)
* added eth_maxPriorityFeePerGas rpc call

* cargo fmt

* moved block_base_fee implementation into the trait

* added basic test for eth_maxPriorityFeePerGas

* added test for eth_maxPriorityFeePerGas calculation

* Added support for zero-cost transactions

* Added 'eip1559_not_activated' error

* Fixes 'chain::supplier::test::return_nodes' test

* cargo fmt

* cargo fmt

* made calculation of fallback priority fee to ignore zero-cost transactions

* cargo fmt

* made use of 'saturating_sub' instead of minus
2021-11-25 10:43:00 +03:00
POA
64a1614769 Bump to v3.3.0 2021-11-17 12:05:58 +03:00
POA
b981f7beef Add validateServiceTransactionsTransition spec option 2021-11-12 13:06:19 +03:00
POA
caa210107e Add additional service transactions checking to block verifier 2021-11-10 16:36:17 +03:00
POA
88eb7d3257 Revert eip1559BaseFeeMinValue activation on xDai 2021-11-04 15:50:48 +03:00
53 changed files with 1035 additions and 102 deletions

View File

@ -1,3 +1,39 @@
## 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 ## OpenEthereum v3.3.0-rc.14
Enhancements: Enhancements:

4
Cargo.lock generated
View File

@ -2932,7 +2932,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]] [[package]]
name = "openethereum" name = "openethereum"
version = "3.3.0-rc.14" version = "3.3.3"
dependencies = [ dependencies = [
"ansi_term 0.10.2", "ansi_term 0.10.2",
"atty", "atty",
@ -3282,7 +3282,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-version" name = "parity-version"
version = "3.3.0-rc.14" version = "3.3.3"
dependencies = [ dependencies = [
"parity-bytes", "parity-bytes",
"rlp", "rlp",

View File

@ -2,7 +2,7 @@
description = "OpenEthereum" description = "OpenEthereum"
name = "openethereum" name = "openethereum"
# NOTE Make sure to update util/version/Cargo.toml as well # NOTE Make sure to update util/version/Cargo.toml as well
version = "3.3.0-rc.14" version = "3.3.3"
license = "GPL-3.0" license = "GPL-3.0"
authors = [ authors = [
"OpenEthereum developers", "OpenEthereum developers",

View File

@ -640,7 +640,7 @@ impl Configuration {
fn pool_verification_options(&self) -> Result<pool::verifier::Options, String> { fn pool_verification_options(&self) -> Result<pool::verifier::Options, String> {
Ok(pool::verifier::Options { Ok(pool::verifier::Options {
// NOTE min_gas_price,block_gas_limit and block_base_fee 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, minimal_gas_price: U256::from(20_000_000) * 1_000u32,
block_gas_limit: U256::max_value(), block_gas_limit: U256::max_value(),
block_base_fee: None, block_base_fee: None,
@ -649,6 +649,7 @@ impl Configuration {
None => U256::max_value(), None => U256::max_value(),
}, },
no_early_reject: self.args.flag_tx_queue_no_early_reject, no_early_reject: self.args.flag_tx_queue_no_early_reject,
allow_non_eoa_sender: false,
}) })
} }

View File

@ -370,7 +370,14 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<RunningClient
let base_fee = client let base_fee = client
.engine() .engine()
.calculate_base_fee(&client.best_block_header()); .calculate_base_fee(&client.best_block_header());
miner.update_transaction_queue_limits(*client.best_block_header().gas_limit(), base_fee); 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| { let connection_filter = connection_filter_address.map(|a| {
Arc::new(NodeFilter::new( Arc::new(NodeFilter::new(

View File

@ -32,6 +32,8 @@ pub struct AccountDetails {
pub nonce: U256, pub nonce: U256,
/// Current account balance /// Current account balance
pub balance: U256, pub balance: U256,
/// Code hash associated with an account if any
pub code_hash: Option<H256>,
/// Is this account a local account? /// Is this account a local account?
pub is_local: bool, pub is_local: bool,
} }

View File

@ -189,8 +189,8 @@ impl txpool::VerifiedTransaction for VerifiedTransaction {
&self.sender &self.sender
} }
fn is_service(&self) -> bool { fn has_zero_gas_price(&self) -> bool {
self.transaction.is_service() self.transaction.has_zero_gas_price()
} }
} }

View File

@ -666,6 +666,20 @@ impl TransactionQueue {
} }
} }
/// 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. /// Returns a status of the queue.
pub fn status(&self) -> Status { pub fn status(&self) -> Status {
let pool = self.pool.read(); let pool = self.pool.read();

View File

@ -43,6 +43,7 @@ impl Default for TestClient {
account_details: AccountDetails { account_details: AccountDetails {
nonce: 123.into(), nonce: 123.into(),
balance: 63_100.into(), balance: 63_100.into(),
code_hash: None,
is_local: false, is_local: false,
}, },
gas_required: 21_000.into(), gas_required: 21_000.into(),
@ -68,6 +69,11 @@ impl TestClient {
self 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 { pub fn with_gas_required<T: Into<U256>>(mut self, gas_required: T) -> Self {
self.gas_required = gas_required.into(); self.gas_required = gas_required.into();
self self

View File

@ -15,6 +15,7 @@
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>. // along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::U256; use ethereum_types::U256;
use hash::KECCAK_EMPTY;
use txpool; use txpool;
use types::transaction::{self, PendingTransaction}; use types::transaction::{self, PendingTransaction};
@ -47,6 +48,7 @@ fn new_queue() -> TransactionQueue {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
) )
@ -66,6 +68,7 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -127,6 +130,7 @@ fn should_never_drop_local_transactions_from_different_senders() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -272,6 +276,71 @@ fn should_import_transaction_below_min_gas_price_threshold_if_local() {
assert_eq!(txq.status().status.transaction_count, 1); 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] #[test]
fn should_import_txs_from_same_sender() { fn should_import_txs_from_same_sender() {
// given // given
@ -545,6 +614,7 @@ fn should_prefer_current_transactions_when_hitting_the_limit() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -1043,6 +1113,7 @@ fn should_include_local_transaction_to_a_full_pool() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -1076,6 +1147,7 @@ fn should_avoid_verifying_transaction_already_in_pool() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -1112,6 +1184,7 @@ fn should_avoid_reverifying_recently_rejected_transactions() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -1161,6 +1234,7 @@ fn should_reject_early_in_case_gas_price_is_less_than_min_effective() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );
@ -1204,6 +1278,7 @@ fn should_not_reject_early_in_case_gas_price_is_less_than_min_effective() {
tx_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(),
no_early_reject: true, no_early_reject: true,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
PrioritizationStrategy::GasPriceOnly, PrioritizationStrategy::GasPriceOnly,
); );

View File

@ -31,6 +31,7 @@ use std::{
}; };
use ethereum_types::{H256, U256}; use ethereum_types::{H256, U256};
use hash::KECCAK_EMPTY;
use txpool; use txpool;
use types::transaction; use types::transaction;
@ -52,6 +53,8 @@ pub struct Options {
pub tx_gas_limit: U256, pub tx_gas_limit: U256,
/// Skip checks for early rejection, to make sure that local transactions are always imported. /// Skip checks for early rejection, to make sure that local transactions are always imported.
pub no_early_reject: bool, pub no_early_reject: bool,
/// Accept transactions from non EOAs (see EIP-3607)
pub allow_non_eoa_sender: bool,
} }
#[cfg(test)] #[cfg(test)]
@ -63,6 +66,7 @@ impl Default for Options {
block_base_fee: None, block_base_fee: None,
tx_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(),
no_early_reject: false, no_early_reject: false,
allow_non_eoa_sender: false,
} }
} }
} }
@ -131,12 +135,12 @@ impl Transaction {
} }
} }
/// Cheeck if transaction is service transaction /// Check if transaction has zero gas price
pub fn is_service(&self) -> bool { pub fn has_zero_gas_price(&self) -> bool {
match *self { match *self {
Transaction::Unverified(ref tx) => tx.is_service(), Transaction::Unverified(ref tx) => tx.has_zero_gas_price(),
Transaction::Retracted(ref tx) => tx.is_service(), Transaction::Retracted(ref tx) => tx.has_zero_gas_price(),
Transaction::Local(ref tx) => tx.is_service(), Transaction::Local(ref tx) => tx.has_zero_gas_price(),
} }
} }
@ -243,13 +247,13 @@ impl<C: Client> txpool::Verifier<Transaction>
} }
let is_own = tx.is_local(); let is_own = tx.is_local();
let is_service = tx.is_service(); let has_zero_gas_price = tx.has_zero_gas_price();
// Quick exit for non-service and non-local transactions // Quick exit for non-service and non-local transactions
// //
// We're checking if the transaction is below configured minimal gas price // We're checking if the transaction is below configured minimal gas price
// or the effective minimal gas price in case the pool is full. // or the effective minimal gas price in case the pool is full.
if !is_service && !is_own { if !has_zero_gas_price && !is_own {
let effective_priority_fee = tx.effective_priority_fee(self.options.block_base_fee); let effective_priority_fee = tx.effective_priority_fee(self.options.block_base_fee);
if effective_priority_fee < self.options.minimal_gas_price { if effective_priority_fee < self.options.minimal_gas_price {
@ -317,6 +321,20 @@ impl<C: Client> txpool::Verifier<Transaction>
let sender = transaction.sender(); let sender = transaction.sender();
let account_details = self.client.account_details(&sender); let account_details = self.client.account_details(&sender);
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 = let effective_priority_fee =
transaction.effective_priority_fee(self.options.block_base_fee); transaction.effective_priority_fee(self.options.block_base_fee);

View File

@ -45,7 +45,7 @@ impl ServiceTransactionChecker {
) -> Result<bool, String> { ) -> Result<bool, String> {
let sender = tx.sender(); let sender = tx.sender();
// Skip checking the contract if the transaction does not have zero gas price // 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); return Ok(false);
} }
@ -72,7 +72,7 @@ impl ServiceTransactionChecker {
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(),
BlockId::Latest, BlockId::Latest,
) )
.ok_or_else(|| "contract is not configured")?; .ok_or_else(|| "Certifier contract is not configured")?;
self.call_contract(client, contract_address, sender) self.call_contract(client, contract_address, sender)
.and_then(|allowed| { .and_then(|allowed| {
if let Some(mut cache) = self.certified_addresses_cache.try_write() { if let Some(mut cache) = self.certified_addresses_cache.try_write() {

View File

@ -265,6 +265,7 @@
}, },
"nodes": [ "nodes": [
"enode://30499bde23362f7d310a34518a2a6ff765921870bf0c3e63d21153cfa7ba9cf39cc7c8e54e9dad2f2b3c07288b3e91b220656833cc2d843a54875c229f3f959a@8.9.8.175:30303", "enode://30499bde23362f7d310a34518a2a6ff765921870bf0c3e63d21153cfa7ba9cf39cc7c8e54e9dad2f2b3c07288b3e91b220656833cc2d843a54875c229f3f959a@8.9.8.175:30303",
"enode://30499bde23362f7d310a34518a2a6ff765921870bf0c3e63d21153cfa7ba9cf39cc7c8e54e9dad2f2b3c07288b3e91b220656833cc2d843a54875c229f3f959a@45.33.77.29:30303",
"enode://16898006ba2cd4fa8bf9a3dfe32684c178fa861df144bfc21fe800dc4838a03e342056951fa9fd533dcb0be1219e306106442ff2cf1f7e9f8faa5f2fc1a3aa45@116.203.116.241:30303", "enode://16898006ba2cd4fa8bf9a3dfe32684c178fa861df144bfc21fe800dc4838a03e342056951fa9fd533dcb0be1219e306106442ff2cf1f7e9f8faa5f2fc1a3aa45@116.203.116.241:30303",
"enode://49a0e1aa38caa12cbf31222cb4e31cef1e8794cb4dd38012f84498ac867b19584e29bbf6d53201d7dfd3b5eb0998a4d908d096ed4ddb5f9102c623852cd331ec@54.87.247.5:30303" "enode://49a0e1aa38caa12cbf31222cb4e31cef1e8794cb4dd38012f84498ac867b19584e29bbf6d53201d7dfd3b5eb0998a4d908d096ed4ddb5f9102c623852cd331ec@54.87.247.5:30303"
] ]

View File

@ -52,7 +52,16 @@
"eip1884Transition": 12095200, "eip1884Transition": 12095200,
"eip2028Transition": 12095200, "eip2028Transition": 12095200,
"eip2929Transition": 21050600, "eip2929Transition": 21050600,
"eip2930Transition": 21050600 "eip2930Transition": 21050600,
"eip3198Transition": 24114400,
"eip3529Transition": 24114400,
"eip3541Transition": 24114400,
"eip1559Transition": 24114400,
"eip1559BaseFeeMaxChangeDenominator": "0x8",
"eip1559ElasticityMultiplier": "0x2",
"eip1559BaseFeeInitialValue": "0x3b9aca00",
"eip1559FeeCollector": "0xE8DDc5c7A2d2F0D7a9798459c0104fDf5E987ACA",
"eip1559FeeCollectorTransition": 24114400
}, },
"genesis": { "genesis": {
"seal": { "seal": {

View File

@ -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"
}
}
}

View File

@ -62,9 +62,7 @@
"eip1559Transition": 19040000, "eip1559Transition": 19040000,
"eip1559BaseFeeMaxChangeDenominator": "0x8", "eip1559BaseFeeMaxChangeDenominator": "0x8",
"eip1559ElasticityMultiplier": "0x2", "eip1559ElasticityMultiplier": "0x2",
"eip1559BaseFeeInitialValue": "0x4a817c800", "eip1559BaseFeeInitialValue": "0x3b9aca00",
"eip1559BaseFeeMinValue": "0x4a817c800",
"eip1559BaseFeeMinValueTransition": 19040000,
"eip1559FeeCollector": "0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92", "eip1559FeeCollector": "0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92",
"eip1559FeeCollectorTransition": 19040000, "eip1559FeeCollectorTransition": 19040000,
"registrar": "0x6B53721D4f2Fb9514B85f5C49b197D857e36Cf03", "registrar": "0x6B53721D4f2Fb9514B85f5C49b197D857e36Cf03",

View File

@ -488,6 +488,52 @@ impl Importer {
.epoch_transition(parent.number(), *header.parent_hash()) .epoch_transition(parent.number(), *header.parent_hash())
.is_some(); .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. // t_nb 8.0 Block enacting. Execution of transactions.
let enact_result = enact_verified( let enact_result = enact_verified(
block, block,
@ -2234,11 +2280,6 @@ impl BlockChainClient for Client {
} }
} }
fn is_aura(&self) -> bool {
let engine = self.engine.clone();
engine.name() == "AuthorityRound"
}
fn is_processing_fork(&self) -> bool { fn is_processing_fork(&self) -> bool {
let chain = self.chain.read(); let chain = self.chain.read();
self.importer self.importer

View File

@ -1087,6 +1087,17 @@ impl BlockChainClient for TestBlockChainClient {
let mut rlp = RlpStream::new(); let mut rlp = RlpStream::new();
rlp.append(&hash.clone()); rlp.append(&hash.clone());
return Some(rlp.out()); 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 None
} }

View File

@ -258,9 +258,6 @@ pub trait BlockChainClient:
/// Get block total difficulty. /// Get block total difficulty.
fn block_total_difficulty(&self, id: BlockId) -> Option<U256>; fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
/// Is it AuRa engine?
fn is_aura(&self) -> bool;
/// Attempt to get address storage root at given block. /// Attempt to get address storage root at given block.
/// May not fail on BlockId::Latest. /// May not fail on BlockId::Latest.
fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256>; fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256>;
@ -416,6 +413,40 @@ pub trait BlockChainClient:
corpus.into() 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()
.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();
}
}
corpus.into()
}
/// Get the preferred chain ID to sign on /// Get the preferred chain ID to sign on
fn signing_chain_id(&self) -> Option<u64>; fn signing_chain_id(&self) -> Option<u64>;

View File

@ -1557,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 { fn sealing_state(&self) -> SealingState {
let our_addr = match *self.signer.read() { let our_addr = match *self.signer.read() {
Some(ref signer) => signer.address(), Some(ref signer) => signer.address(),

View File

@ -470,6 +470,14 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Register a component which signs consensus messages. /// Register a component which signs consensus messages.
fn set_signer(&self, _signer: Option<Box<dyn EngineSigner>>) {} 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. /// Sign using the EngineSigner, to be used for consensus tx signing.
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> { fn sign(&self, _hash: H256) -> Result<Signature, M::Error> {
unimplemented!() unimplemented!()
@ -660,6 +668,14 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
fn min_gas_limit(&self) -> U256 { fn min_gas_limit(&self) -> U256 {
self.params().min_gas_limit 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. // convenience wrappers for existing functions.

View File

@ -1207,7 +1207,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
} }
// ensure that the user was willing to at least pay the base fee // 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.is_service() { if t.tx().gas_price < self.info.base_fee.unwrap_or_default() && !t.has_zero_gas_price() {
return Err(ExecutionError::GasPriceLowerThanBaseFee { return Err(ExecutionError::GasPriceLowerThanBaseFee {
gas_price: t.tx().gas_price, gas_price: t.tx().gas_price,
base_fee: self.info.base_fee.unwrap_or_default(), base_fee: self.info.base_fee.unwrap_or_default(),
@ -1516,7 +1516,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// Up until now, fees_value is calculated for each type of transaction based on their gas prices // 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 // 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) // 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.is_service() { let burnt_fee = if schedule.eip1559 && !t.has_zero_gas_price() {
let (fee, overflow_3) = let (fee, overflow_3) =
gas_used.overflowing_mul(self.info.base_fee.unwrap_or_default()); gas_used.overflowing_mul(self.info.base_fee.unwrap_or_default());
if overflow_3 { if overflow_3 {
@ -2760,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} evm_test! {test_keccak: test_keccak_int}
fn test_keccak(factory: Factory) { fn test_keccak(factory: Factory) {
let code = "6064640fffffffff20600055".from_hex().unwrap(); let code = "6064640fffffffff20600055".from_hex().unwrap();

View File

@ -376,7 +376,7 @@ impl EthereumMachine {
header: &Header, header: &Header,
) -> Result<SignedTransaction, transaction::Error> { ) -> Result<SignedTransaction, transaction::Error> {
// ensure that the user was willing to at least pay the base fee // 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.is_service() { if t.tx().gas_price < header.base_fee().unwrap_or_default() && !t.has_zero_gas_price() {
return Err(transaction::Error::GasPriceLowerThanBaseFee { return Err(transaction::Error::GasPriceLowerThanBaseFee {
gas_price: t.tx().gas_price, gas_price: t.tx().gas_price,
base_fee: header.base_fee().unwrap_or_default(), base_fee: header.base_fee().unwrap_or_default(),

View File

@ -190,6 +190,7 @@ impl Default for MinerOptions {
block_base_fee: None, block_base_fee: None,
tx_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(),
no_early_reject: false, no_early_reject: false,
allow_non_eoa_sender: false,
}, },
} }
} }
@ -341,6 +342,7 @@ impl Miner {
block_base_fee: None, block_base_fee: None,
tx_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(),
no_early_reject: false, no_early_reject: false,
allow_non_eoa_sender: false,
}, },
reseal_min_period: Duration::from_secs(0), reseal_min_period: Duration::from_secs(0),
force_sealing, force_sealing,
@ -382,6 +384,7 @@ impl Miner {
&self, &self,
block_gas_limit: U256, block_gas_limit: U256,
block_base_fee: Option<U256>, block_base_fee: Option<U256>,
allow_non_eoa_sender: bool,
) { ) {
trace!(target: "miner", "minimal_gas_price: recalibrating..."); trace!(target: "miner", "minimal_gas_price: recalibrating...");
let txq = self.transaction_queue.clone(); let txq = self.transaction_queue.clone();
@ -391,6 +394,7 @@ impl Miner {
options.minimal_gas_price = gas_price; options.minimal_gas_price = gas_price;
options.block_gas_limit = block_gas_limit; options.block_gas_limit = block_gas_limit;
options.block_base_fee = block_base_fee; options.block_base_fee = block_base_fee;
options.allow_non_eoa_sender = allow_non_eoa_sender;
txq.set_verifier_options(options); txq.set_verifier_options(options);
}); });
@ -1006,6 +1010,14 @@ impl miner::MinerService for Miner {
self.transaction_queue.current_worst_gas_price() * 110u32 / 100 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 { fn sensible_gas_limit(&self) -> U256 {
self.params.read().gas_range_target.0 / 5 self.params.read().gas_range_target.0 / 5
} }
@ -1369,7 +1381,7 @@ impl miner::MinerService for Miner {
} }
fn is_currently_sealing(&self) -> bool { 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)> fn work_package<C>(&self, chain: &C) -> Option<(H256, BlockNumber, u64, U256)>
@ -1458,7 +1470,10 @@ impl miner::MinerService for Miner {
} else { } else {
1 1
}; };
self.update_transaction_queue_limits(gas_limit, base_fee); 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). // t_nb 10.2 Then import all transactions from retracted blocks (retracted means from side chain).
let client = self.pool_client(chain); let client = self.pool_client(chain);
@ -1600,7 +1615,9 @@ mod tests {
use client::{ChainInfo, EachBlockWith, ImportSealedBlock, TestBlockChainClient}; use client::{ChainInfo, EachBlockWith, ImportSealedBlock, TestBlockChainClient};
use miner::{MinerService, PendingOrdering}; 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}; use types::transaction::{Transaction, TypedTransaction};
#[test] #[test]
@ -1660,6 +1677,7 @@ mod tests {
block_base_fee: None, block_base_fee: None,
tx_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(),
no_early_reject: false, no_early_reject: false,
allow_non_eoa_sender: false,
}, },
}, },
GasPricer::new_fixed(0u64.into()), GasPricer::new_fixed(0u64.into()),
@ -1805,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] #[test]
fn should_treat_unfamiliar_locals_selectively() { fn should_treat_unfamiliar_locals_selectively() {
// given // given
@ -2070,6 +2122,31 @@ mod tests {
assert!(miner.is_currently_sealing()); 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] #[test]
fn should_set_new_minimum_gas_price() { fn should_set_new_minimum_gas_price() {
// Creates a new GasPricer::Fixed behind the scenes // Creates a new GasPricer::Fixed behind the scenes

View File

@ -260,6 +260,9 @@ pub trait MinerService: Send + Sync {
/// Suggested gas price. /// Suggested gas price.
fn sensible_gas_price(&self) -> U256; fn sensible_gas_price(&self) -> U256;
/// Suggested max priority fee gas price
fn sensible_max_priority_fee(&self) -> U256;
/// Suggested gas limit. /// Suggested gas limit.
fn sensible_gas_limit(&self) -> U256; fn sensible_gas_limit(&self) -> U256;

View File

@ -30,7 +30,7 @@ use types::{
}; };
use call_contract::CallContract; use call_contract::CallContract;
use client::{BlockInfo, Nonce, TransactionId}; use client::{BlockId, BlockInfo, Nonce, TransactionId};
use engines::EthEngine; use engines::EthEngine;
use miner; use miner;
use transaction_ext::Transaction; use transaction_ext::Transaction;
@ -168,6 +168,7 @@ where
pool::client::AccountDetails { pool::client::AccountDetails {
nonce: self.cached_nonces.account_nonce(address), nonce: self.cached_nonces.account_nonce(address),
balance: self.chain.latest_balance(address), balance: self.chain.latest_balance(address),
code_hash: self.chain.code_hash(address, BlockId::Latest),
is_local: self.accounts.is_local(address), is_local: self.accounts.is_local(address),
} }
} }

View File

@ -147,6 +147,8 @@ pub struct CommonParams {
pub eip3529_transition: BlockNumber, pub eip3529_transition: BlockNumber,
/// Number of first block where EIP-3541 rule begins. /// Number of first block where EIP-3541 rule begins.
pub eip3541_transition: BlockNumber, 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. /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
pub dust_protection_transition: BlockNumber, pub dust_protection_transition: BlockNumber,
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
@ -191,6 +193,8 @@ pub struct CommonParams {
pub eip1559_fee_collector: Option<Address>, pub eip1559_fee_collector: Option<Address>,
/// Block at which the fee collector should start being used. /// Block at which the fee collector should start being used.
pub eip1559_fee_collector_transition: BlockNumber, 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 { impl CommonParams {
@ -432,6 +436,7 @@ impl From<ethjson::spec::Params> for CommonParams {
dust_protection_transition: p dust_protection_transition: p
.dust_protection_transition .dust_protection_transition
.map_or_else(BlockNumber::max_value, Into::into), .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), nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false),
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
@ -475,6 +480,9 @@ impl From<ethjson::spec::Params> for CommonParams {
eip1559_fee_collector_transition: p eip1559_fee_collector_transition: p
.eip1559_fee_collector_transition .eip1559_fee_collector_transition
.map_or_else(BlockNumber::max_value, Into::into), .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),
} }
} }
} }
@ -752,6 +760,7 @@ impl Spec {
params.transaction_permission_contract_transition, params.transaction_permission_contract_transition,
params.eip1559_fee_collector_transition, params.eip1559_fee_collector_transition,
params.eip1559_base_fee_min_value_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 // 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 { if params.network_id == 0x4 {
@ -1145,6 +1154,13 @@ impl Spec {
load_bundled!("test/constructor") 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 /// Create a new Spec with Autority Round randomness contract
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
pub fn new_test_round_randomness_contract() -> Spec { pub fn new_test_round_randomness_contract() -> Spec {

View File

@ -46,6 +46,8 @@ use block::{Drain, OpenBlock};
use client::{ use client::{
ChainInfo, ChainMessageType, ChainNotify, Client, ClientConfig, ImportBlock, PrepareOpenBlock, ChainInfo, ChainMessageType, ChainNotify, Client, ClientConfig, ImportBlock, PrepareOpenBlock,
}; };
use engines::EngineSigner;
use ethjson::crypto::publickey::{Public, Signature};
use factory::Factories; use factory::Factories;
use miner::Miner; use miner::Miner;
use spec::Spec; use spec::Spec;
@ -644,3 +646,38 @@ impl ChainNotify for TestNotify {
self.messages.write().push(data); 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))
}

View File

@ -1704,6 +1704,14 @@ pub mod tests {
assert!(!sync_status(SyncState::Idle).is_syncing(queue_info(0, 0))); assert!(!sync_status(SyncState::Idle).is_syncing(queue_info(0, 0)));
} }
pub fn dummy_sync(client: &dyn BlockChainClient) -> ChainSync {
ChainSync::new(
SyncConfig::default(),
client,
ForkFilterApi::new_dummy(client),
)
}
pub fn dummy_sync_with_peer( pub fn dummy_sync_with_peer(
peer_latest_hash: H256, peer_latest_hash: H256,
client: &dyn BlockChainClient, client: &dyn BlockChainClient,

View File

@ -351,36 +351,34 @@ impl SyncSupplier {
} }
fn return_node_data(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult { fn return_node_data(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult {
if io.chain().is_aura() { let count = cmp::min(rlp.item_count().unwrap_or(0), MAX_NODE_DATA_TO_SEND);
let count = cmp::min(rlp.item_count().unwrap_or(0), MAX_NODE_DATA_TO_SEND); trace!(target: "sync", "{} -> GetNodeData: {} entries", peer_id, count);
if count == 0 { if count == 0 {
debug!(target: "sync", "Empty GetNodeData request, ignoring."); debug!(target: "sync", "Empty GetNodeData request, ignoring.");
return Ok(None); return Ok(None);
}
let mut data = Bytes::new();
let mut added = 0usize;
for i in 0..count {
if let Some(ref mut node_data) = io.chain().state_data(&rlp.val_at::<H256>(i)?) {
data.append(node_data);
added += 1;
if data.len() > PAYLOAD_SOFT_LIMIT {
break;
}
}
}
let mut rlp = RlpStream::new_list(added);
rlp.append_raw(&data, added);
trace!(target: "sync", "{} -> GetNodeData: returned {} entries", peer_id, added);
Ok(Some((NodeDataPacket, rlp)))
} else {
// GetNodeData requests are ignored since we don't have a correct
// implementation of the NodeData response, see issue #508
debug!("Ignoring GetNodeData request");
Ok(None)
} }
let mut added = 0usize;
let mut data = Vec::new();
let mut total_bytes = 0;
for i in 0..count {
if let Some(node_data) = io.chain().state_data(&rlp.val_at::<H256>(i)?) {
total_bytes += node_data.len();
// Check that the packet won't be oversized
if total_bytes > PAYLOAD_SOFT_LIMIT {
break;
}
data.push(node_data);
added += 1;
}
}
let mut rlp = RlpStream::new_list(added);
for d in data {
rlp.append(&d);
}
trace!(target: "sync", "{} -> GetNodeData: returned {} entries", peer_id, added);
Ok(Some((NodeDataPacket, rlp)))
} }
fn return_receipts(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult { fn return_receipts(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult {
@ -504,7 +502,10 @@ mod test {
use super::{super::tests::*, *}; use super::{super::tests::*, *};
use blocks::SyncHeader; use blocks::SyncHeader;
use bytes::Bytes; use bytes::Bytes;
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; use ethcore::{
client::{BlockChainClient, EachBlockWith, TestBlockChainClient},
spec::Spec,
};
use ethereum_types::H256; use ethereum_types::H256;
use parking_lot::RwLock; use parking_lot::RwLock;
use rlp::{Rlp, RlpStream}; use rlp::{Rlp, RlpStream};
@ -769,7 +770,7 @@ mod test {
#[test] #[test]
fn return_nodes() { fn return_nodes() {
let mut client = TestBlockChainClient::new(); let mut client = TestBlockChainClient::new_with_spec(Spec::new_test_round());
let queue = RwLock::new(VecDeque::new()); let queue = RwLock::new(VecDeque::new());
let sync = dummy_sync_with_peer(H256::zero(), &client); let sync = dummy_sync_with_peer(H256::zero(), &client);
let ss = TestSnapshotService::new(); let ss = TestSnapshotService::new();
@ -813,4 +814,48 @@ mod test {
); );
assert_eq!(1, io.packets.len()); assert_eq!(1, io.packets.len());
} }
#[test]
fn dispatch_get_node_data_request() {
let mut client = TestBlockChainClient::new_with_spec(Spec::new_test_round());
let queue = RwLock::new(VecDeque::new());
let sync = dummy_sync(&client);
let ss = TestSnapshotService::new();
let mut io = TestIo::new(&mut client, &ss, &queue, None);
let mut node_list = RlpStream::new_list(3);
node_list.append(
&H256::from_str("000000000000000000000000000000000000000000000000000000000000000a")
.unwrap(),
);
node_list.append(
&H256::from_str("000000000000000000000000000000000000000000000000000000000000000b")
.unwrap(),
);
node_list.append(
&H256::from_str("000000000000000000000000000000000000000000000000000000000000000c")
.unwrap(),
);
let node_request = node_list;
let node_request = prepend_request_id(node_request, Some(0x0b3a73ce2ff2));
io.sender = Some(2usize);
// it returns rlp ONLY for hashes ending with "a" and "c"
SyncSupplier::dispatch_packet(
&RwLock::new(sync),
&mut io,
0usize,
GetNodeDataPacket.id(),
&node_request.out(),
);
assert_eq!(1, io.packets.len());
assert_eq!(
&io.packets[0].data,
&vec![
0xcd, 0x86, 0x0b, 0x3a, 0x73, 0xce, 0x2f, 0xf2, 0xc5, 0x82, 0xaa, 0xaa, 0x81, 0xcc
]
);
}
} }

View File

@ -93,6 +93,8 @@ pub enum Error {
InvalidRlp(String), InvalidRlp(String),
/// Transaciton is still not enabled. /// Transaciton is still not enabled.
TransactionTypeNotEnabled, TransactionTypeNotEnabled,
/// Transaction sender is not an EOA (see EIP-3607)
SenderIsNotEOA,
} }
impl From<crypto::publickey::Error> for Error { impl From<crypto::publickey::Error> for Error {
@ -154,6 +156,7 @@ impl fmt::Display for Error {
TransactionTypeNotEnabled => { TransactionTypeNotEnabled => {
format!("Transaction type is not enabled for current block") format!("Transaction type is not enabled for current block")
} }
SenderIsNotEOA => "Transaction sender is not an EOA (see EIP-3607)".into(),
}; };
f.write_fmt(format_args!("Transaction error ({})", msg)) f.write_fmt(format_args!("Transaction error ({})", msg))

View File

@ -634,10 +634,16 @@ impl TypedTransaction {
pub fn effective_gas_price(&self, block_base_fee: Option<U256>) -> U256 { pub fn effective_gas_price(&self, block_base_fee: Option<U256>) -> U256 {
match self { match self {
Self::EIP1559Transaction(tx) => min( Self::EIP1559Transaction(tx) => {
self.tx().gas_price, let (v2, overflow) = tx
tx.max_priority_fee_per_gas + block_base_fee.unwrap_or_default(), .max_priority_fee_per_gas
), .overflowing_add(block_base_fee.unwrap_or_default());
if overflow {
self.tx().gas_price
} else {
min(self.tx().gas_price, v2)
}
}
Self::AccessList(_) => self.tx().gas_price, Self::AccessList(_) => self.tx().gas_price,
Self::Legacy(_) => self.tx().gas_price, Self::Legacy(_) => self.tx().gas_price,
} }
@ -657,7 +663,7 @@ impl TypedTransaction {
.unwrap_or_default() .unwrap_or_default()
} }
pub fn is_service(&self) -> bool { pub fn has_zero_gas_price(&self) -> bool {
match self { match self {
Self::EIP1559Transaction(tx) => { Self::EIP1559Transaction(tx) => {
tx.tx().gas_price.is_zero() && tx.max_priority_fee_per_gas.is_zero() tx.tx().gas_price.is_zero() && tx.max_priority_fee_per_gas.is_zero()
@ -1337,4 +1343,41 @@ mod tests {
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "9bddad43f934d313c2b79ca28a432dd2b7281029"); test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "9bddad43f934d313c2b79ca28a432dd2b7281029");
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "3c24d7329e92f84f08556ceb6df1cdb0104ca49f"); test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "3c24d7329e92f84f08556ceb6df1cdb0104ca49f");
} }
#[test]
fn should_not_panic_on_effective_gas_price_overflow() {
use self::publickey::{Generator, Random};
let key = Random.generate();
let gas_price /* 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,
nonce: U256::from(42),
gas_price,
gas: U256::from(50_000),
value: U256::from(1),
data: b"Hello!".to_vec(),
},
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: gas_price,
})
.sign(&key.secret(), Some(69));
let result = t.transaction.effective_gas_price(Some(124.into()));
assert_eq!(
gas_price, result,
"Invalid effective gas price, when max_priority_fee_per_gas is U256::max"
);
}
} }

View File

@ -51,6 +51,7 @@ impl TypedTxId {
pub fn from_U64_option_id(n: Option<U64>) -> Option<Self> { pub fn from_U64_option_id(n: Option<U64>) -> Option<Self> {
match n.map(|t| t.as_u64()) { match n.map(|t| t.as_u64()) {
None => Some(Self::Legacy), None => Some(Self::Legacy),
Some(0x00) => Some(Self::Legacy),
Some(0x01) => Some(Self::AccessList), Some(0x01) => Some(Self::AccessList),
Some(0x02) => Some(Self::EIP1559Transaction), Some(0x02) => Some(Self::EIP1559Transaction),
_ => None, _ => None,
@ -59,10 +60,7 @@ impl TypedTxId {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn to_U64_option_id(self) -> Option<U64> { pub fn to_U64_option_id(self) -> Option<U64> {
match self { Some(U64::from(self as u8))
Self::Legacy => None,
_ => Some(U64::from(self as u8)),
}
} }
} }
@ -93,7 +91,7 @@ mod tests {
#[test] #[test]
fn typed_tx_id_to_u64_option_id() { fn typed_tx_id_to_u64_option_id() {
assert_eq!(None, TypedTxId::Legacy.to_U64_option_id()); assert_eq!(Some(U64::from(0x00)), TypedTxId::Legacy.to_U64_option_id());
assert_eq!( assert_eq!(
Some(U64::from(0x01)), Some(U64::from(0x01)),
TypedTxId::AccessList.to_U64_option_id() TypedTxId::AccessList.to_U64_option_id()

View File

@ -137,6 +137,29 @@ impl<'a> TypedTransactionView<'a> {
} }
} }
/// Get the actual priority gas price paid to the miner
pub fn effective_priority_gas_price(&self, block_base_fee: Option<U256>) -> U256 {
match self.transaction_type {
TypedTxId::Legacy => self
.gas_price()
.saturating_sub(block_base_fee.unwrap_or_default()),
TypedTxId::AccessList => self
.gas_price()
.saturating_sub(block_base_fee.unwrap_or_default()),
TypedTxId::EIP1559Transaction => {
let max_priority_fee_per_gas: U256 =
view!(Self, &self.rlp.rlp.data().unwrap()[1..])
.rlp
.val_at(2);
min(
max_priority_fee_per_gas,
self.gas_price()
.saturating_sub(block_base_fee.unwrap_or_default()),
)
}
}
}
/// Get the gas field of the transaction. /// Get the gas field of the transaction.
pub fn gas(&self) -> U256 { pub fn gas(&self) -> U256 {
match self.transaction_type { match self.transaction_type {
@ -260,6 +283,7 @@ mod tests {
assert_eq!(view.nonce(), 0.into()); assert_eq!(view.nonce(), 0.into());
assert_eq!(view.gas_price(), 1.into()); assert_eq!(view.gas_price(), 1.into());
assert_eq!(view.effective_gas_price(None), 1.into()); assert_eq!(view.effective_gas_price(None), 1.into());
assert_eq!(view.effective_priority_gas_price(None), 1.into());
assert_eq!(view.gas(), 0x61a8.into()); assert_eq!(view.gas(), 0x61a8.into());
assert_eq!(view.value(), 0xa.into()); assert_eq!(view.value(), 0xa.into());
assert_eq!( assert_eq!(
@ -285,6 +309,7 @@ mod tests {
let view = view!(TypedTransactionView, &rlp); let view = view!(TypedTransactionView, &rlp);
assert_eq!(view.nonce(), 0x1.into()); assert_eq!(view.nonce(), 0x1.into());
assert_eq!(view.gas_price(), 0xa.into()); assert_eq!(view.gas_price(), 0xa.into());
assert_eq!(view.effective_priority_gas_price(None), 0xa.into());
assert_eq!(view.gas(), 0x1e241.into()); assert_eq!(view.gas(), 0x1e241.into());
assert_eq!(view.value(), 0x0.into()); assert_eq!(view.value(), 0x0.into());
assert_eq!(view.data(), "".from_hex().unwrap()); assert_eq!(view.data(), "".from_hex().unwrap());
@ -306,6 +331,10 @@ mod tests {
assert_eq!(view.nonce(), 0x1.into()); assert_eq!(view.nonce(), 0x1.into());
assert_eq!(view.gas_price(), 0xa.into()); assert_eq!(view.gas_price(), 0xa.into());
assert_eq!(view.effective_gas_price(Some(0x07.into())), 0x08.into()); assert_eq!(view.effective_gas_price(Some(0x07.into())), 0x08.into());
assert_eq!(
view.effective_priority_gas_price(Some(0x07.into())),
0x01.into()
);
assert_eq!(view.gas(), 0x1e241.into()); assert_eq!(view.gas(), 0x1e241.into());
assert_eq!(view.value(), 0x0.into()); assert_eq!(view.value(), 0x0.into());
assert_eq!(view.data(), "".from_hex().unwrap()); assert_eq!(view.data(), "".from_hex().unwrap());

View File

@ -120,6 +120,8 @@ pub struct Params {
/// See `CommonParams` docs. /// See `CommonParams` docs.
pub eip3541_transition: Option<Uint>, pub eip3541_transition: Option<Uint>,
/// See `CommonParams` docs. /// See `CommonParams` docs.
pub eip3607_transition: Option<Uint>,
/// See `CommonParams` docs.
pub dust_protection_transition: Option<Uint>, pub dust_protection_transition: Option<Uint>,
/// See `CommonParams` docs. /// See `CommonParams` docs.
pub nonce_cap_increment: Option<Uint>, pub nonce_cap_increment: Option<Uint>,
@ -166,6 +168,8 @@ pub struct Params {
pub eip1559_fee_collector: Option<Address>, pub eip1559_fee_collector: Option<Address>,
/// Block at which the fee collector should start being used. /// Block at which the fee collector should start being used.
pub eip1559_fee_collector_transition: Option<Uint>, pub eip1559_fee_collector_transition: Option<Uint>,
/// Block at which zero gas price transactions start being checked with Certifier contract.
pub validate_service_transactions_transition: Option<Uint>,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -91,7 +91,10 @@ use ethcore::{client::BlockChainClient, miner::MinerService};
use ethereum_types::{Address, H256, H520, U256}; use ethereum_types::{Address, H256, H520, U256};
use ethkey::Password; use ethkey::Password;
use hash::keccak; use hash::keccak;
use types::transaction::{PendingTransaction, SignedTransaction}; use types::{
transaction::{PendingTransaction, SignedTransaction},
BlockNumber,
};
use jsonrpc_core::{ use jsonrpc_core::{
futures::{future, Future, IntoFuture}, futures::{future, Future, IntoFuture},
@ -397,6 +400,24 @@ where
.unwrap_or_else(|| miner.sensible_gas_price()) .unwrap_or_else(|| miner.sensible_gas_price())
} }
/// Extract the default priority gas price from a client and miner.
pub fn default_max_priority_fee_per_gas<C, M>(
client: &C,
miner: &M,
percentile: usize,
eip1559_transition: BlockNumber,
) -> U256
where
C: BlockChainClient,
M: MinerService,
{
client
.priority_gas_price_corpus(100, eip1559_transition)
.percentile(percentile)
.cloned()
.unwrap_or_else(|| miner.sensible_max_priority_fee())
}
/// Convert RPC confirmation payload to signer confirmation payload. /// Convert RPC confirmation payload to signer confirmation payload.
/// May need to resolve in the future to fetch things like gas price. /// May need to resolve in the future to fetch things like gas price.
pub fn from_rpc<D>( pub fn from_rpc<D>(

View File

@ -273,6 +273,10 @@ where
} }
} }
pub fn eip1559_not_activated() -> Error {
unsupported("EIP-1559 is not activated", None)
}
pub fn not_enough_data() -> Error { pub fn not_enough_data() -> Error {
Error { Error {
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
@ -404,6 +408,7 @@ pub fn transaction_message(error: &TransactionError) -> String {
TooBig => "Transaction is too big, see chain specification for the limit.".into(), TooBig => "Transaction is too big, see chain specification for the limit.".into(),
InvalidRlp(ref descr) => format!("Invalid RLP data: {}", descr), InvalidRlp(ref descr) => format!("Invalid RLP data: {}", descr),
TransactionTypeNotEnabled => format!("Transaction type is not enabled for current block"), TransactionTypeNotEnabled => format!("Transaction type is not enabled for current block"),
SenderIsNotEOA => "Transaction sender is not an EOA (see EIP-3607)".into(),
} }
} }

View File

@ -52,7 +52,7 @@ use v1::{
self, self,
block_import::is_major_importing, block_import::is_major_importing,
deprecated::{self, DeprecationNotice}, deprecated::{self, DeprecationNotice},
dispatch::{default_gas_price, FullDispatcher}, dispatch::{default_gas_price, default_max_priority_fee_per_gas, FullDispatcher},
errors, fake_sign, limit_logs, errors, fake_sign, limit_logs,
}, },
metadata::Metadata, metadata::Metadata,
@ -696,6 +696,22 @@ where
))) )))
} }
fn max_priority_fee_per_gas(&self) -> BoxFuture<U256> {
let latest_block = self.client.chain_info().best_block_number;
let eip1559_transition = self.client.engine().params().eip1559_transition;
if latest_block + 1 >= eip1559_transition {
Box::new(future::ok(default_max_priority_fee_per_gas(
&*self.client,
&*self.miner,
self.options.gas_price_percentile,
eip1559_transition,
)))
} else {
Box::new(future::done(Err(errors::eip1559_not_activated())))
}
}
fn fee_history( fn fee_history(
&self, &self,
mut block_count: U256, mut block_count: U256,
@ -805,8 +821,11 @@ where
gas_and_reward.push(( gas_and_reward.push((
gas_used, gas_used,
txs[i].effective_gas_price(base_fee) txs[i]
- base_fee.unwrap_or_default(), .effective_gas_price(base_fee)
.saturating_sub(
base_fee.unwrap_or_default(),
),
)); ));
} }
} }

View File

@ -19,7 +19,7 @@ use std::{env, sync::Arc};
use accounts::AccountProvider; use accounts::AccountProvider;
use ethcore::{ use ethcore::{
client::{BlockChainClient, ChainInfo, Client, ClientConfig, ImportBlock}, client::{BlockChainClient, ChainInfo, Client, ClientConfig, EvmTestClient, ImportBlock},
ethereum, ethereum,
miner::Miner, miner::Miner,
spec::{Genesis, Spec}, spec::{Genesis, Spec},
@ -67,7 +67,7 @@ fn snapshot_service() -> Arc<TestSnapshotService> {
fn make_spec(chain: &BlockChain) -> Spec { fn make_spec(chain: &BlockChain) -> Spec {
let genesis = Genesis::from(chain.genesis()); let genesis = Genesis::from(chain.genesis());
let mut spec = ethereum::new_frontier_test(); let mut spec = EvmTestClient::spec_from_json(&chain.network).unwrap();
let state = chain.pre_state.clone().into(); let state = chain.pre_state.clone().into();
spec.set_genesis_state(state) spec.set_genesis_state(state)
.expect("unable to set genesis state"); .expect("unable to set genesis state");
@ -281,6 +281,26 @@ fn eth_get_block() {
); );
} }
#[test]
fn eth_get_max_priority_fee_per_gas() {
let chain = extract_non_legacy_chain!(
"BlockchainTests/ValidBlocks/bcEIP1559/transType",
ForkSpec::London
);
let tester = EthTester::from_chain(&chain);
let request = r#"{"method":"eth_maxPriorityFeePerGas","params":[],"id":1,"jsonrpc":"2.0"}"#;
// We are expecting for 50-th percentile of the previous 100 blocks transactions priority fees.
//
// Sorted priority fees: 0x64 0x64 0x64 0x7d 0x7d 0xea 0x149.
// Currently, the way 50-th percentile is calculated, the 3rd fee would be the result.
let response = r#"{"jsonrpc":"2.0","result":"0x64","id":1}"#;
assert_eq!(
tester.handler.handle_request_sync(request).unwrap(),
response
)
}
#[test] #[test]
fn eth_get_block_by_hash() { fn eth_get_block_by_hash() {
let chain = extract_chain!("BlockchainTests/ValidBlocks/bcGasPricerTest/RPC_API_Test"); let chain = extract_chain!("BlockchainTests/ValidBlocks/bcGasPricerTest/RPC_API_Test");

View File

@ -335,6 +335,7 @@ impl MinerService for TestMinerService {
tx_gas_limit: 5_000_000.into(), tx_gas_limit: 5_000_000.into(),
no_early_reject: false, no_early_reject: false,
block_base_fee: None, block_base_fee: None,
allow_non_eoa_sender: false,
}, },
status: txpool::LightStatus { status: txpool::LightStatus {
mem_usage: 1_000, mem_usage: 1_000,
@ -359,6 +360,10 @@ impl MinerService for TestMinerService {
20_000_000_000u64.into() 20_000_000_000u64.into()
} }
fn sensible_max_priority_fee(&self) -> U256 {
2_000_000_000u64.into()
}
fn sensible_gas_limit(&self) -> U256 { fn sensible_gas_limit(&self) -> U256 {
0x5208.into() 0x5208.into()
} }

View File

@ -23,7 +23,7 @@ use std::{
use accounts::AccountProvider; use accounts::AccountProvider;
use ethcore::{ use ethcore::{
client::{BlockChainClient, EachBlockWith, Executed, TestBlockChainClient}, client::{BlockChainClient, EachBlockWith, EvmTestClient, Executed, TestBlockChainClient},
miner::{self, MinerService}, miner::{self, MinerService},
}; };
use ethereum_types::{Address, Bloom, H160, H256, U256}; use ethereum_types::{Address, Bloom, H160, H256, U256};
@ -51,6 +51,12 @@ fn blockchain_client() -> Arc<TestBlockChainClient> {
Arc::new(client) Arc::new(client)
} }
fn eip1559_blockchain_client() -> Arc<TestBlockChainClient> {
let spec = EvmTestClient::spec_from_json(&ethjson::spec::ForkSpec::London).unwrap();
let client = TestBlockChainClient::new_with_spec(spec);
Arc::new(client)
}
fn accounts_provider() -> Arc<AccountProvider> { fn accounts_provider() -> Arc<AccountProvider> {
Arc::new(AccountProvider::transient_provider()) Arc::new(AccountProvider::transient_provider())
} }
@ -89,8 +95,25 @@ impl Default for EthTester {
impl EthTester { impl EthTester {
pub fn new_with_options(options: EthClientOptions) -> Self { pub fn new_with_options(options: EthClientOptions) -> Self {
let runtime = Runtime::with_thread_count(1);
let client = blockchain_client(); let client = blockchain_client();
EthTester::new_with_client_and_options(client, options)
}
fn new_eip1559_with_options(options: EthClientOptions) -> Self {
let client = eip1559_blockchain_client();
EthTester::new_with_client_and_options(client, options)
}
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
self.client.add_blocks(count, with);
self.sync.increase_imported_block_number(count as u64);
}
fn new_with_client_and_options(
client: Arc<TestBlockChainClient>,
options: EthClientOptions,
) -> Self {
let runtime = Runtime::with_thread_count(1);
let sync = sync_provider(); let sync = sync_provider();
let ap = accounts_provider(); let ap = accounts_provider();
let ap2 = ap.clone(); let ap2 = ap.clone();
@ -126,11 +149,6 @@ impl EthTester {
hashrates, hashrates,
} }
} }
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
self.client.add_blocks(count, with);
self.sync.increase_imported_block_number(count as u64);
}
} }
#[test] #[test]
@ -537,6 +555,33 @@ fn rpc_eth_gas_price() {
); );
} }
#[test]
fn rpc_eth_get_max_priority_fee_per_gas() {
let tester = EthTester::new_eip1559_with_options(Default::default());
let request = r#"{"method":"eth_maxPriorityFeePerGas","params":[],"id":1,"jsonrpc":"2.0"}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x77359400","id":1}"#; // 2 GWei
assert_eq!(
tester.io.handle_request_sync(request),
Some(response.to_owned())
);
}
#[test]
fn rpc_eth_get_max_priority_fee_per_gas_error() {
let tester = EthTester::default();
let request = r#"{"method":"eth_maxPriorityFeePerGas","params":[],"id":1,"jsonrpc":"2.0"}"#;
let response =
r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"EIP-1559 is not activated"},"id":1}"#;
assert_eq!(
tester.io.handle_request_sync(request),
Some(response.to_owned())
);
}
#[test] #[test]
fn rpc_eth_accounts() { fn rpc_eth_accounts() {
let tester = EthTester::default(); let tester = EthTester::default();
@ -720,7 +765,7 @@ fn rpc_eth_pending_transaction_by_hash() {
.insert(H256::zero(), tx); .insert(H256::zero(), tx);
} }
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"type":"0x0","v":"0x1b","value":"0xa"},"id":1}"#;
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_getTransactionByHash", "method": "eth_getTransactionByHash",
@ -1200,7 +1245,7 @@ fn rpc_eth_transaction_receipt() {
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
"id": 1 "id": 1
}"#; }"#;
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","effectiveGasPrice":"0x0","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","removed":false,"topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","effectiveGasPrice":"0x0","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","removed":false,"topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"0x0"},"id":1}"#;
assert_eq!( assert_eq!(
tester.io.handle_request_sync(request), tester.io.handle_request_sync(request),
@ -1255,7 +1300,7 @@ fn rpc_eth_pending_receipt() {
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
"id": 1 "id": 1
}"#; }"#;
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"contractAddress":null,"cumulativeGasUsed":"0x20","effectiveGasPrice":"0x0","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238","transactionIndex":"0x0"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"contractAddress":null,"cumulativeGasUsed":"0x20","effectiveGasPrice":"0x0","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238","transactionIndex":"0x0","type":"0x0"},"id":1}"#;
assert_eq!( assert_eq!(
tester.io.handle_request_sync(request), tester.io.handle_request_sync(request),
Some(response.to_owned()) Some(response.to_owned())

View File

@ -572,7 +572,7 @@ fn rpc_parity_block_receipts() {
"params": [], "params": [],
"id": 1 "id": 1
}"#; }"#;
let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","effectiveGasPrice":"0x0","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0"}],"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","effectiveGasPrice":"0x0","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0","type":"0x0"}],"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }

View File

@ -202,7 +202,7 @@ fn rpc_parity_remove_transaction() {
.to_owned() .to_owned()
+ &format!("0x{:x}", hash) + &format!("0x{:x}", hash)
+ r#""], "id": 1}"#; + r#""], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x1f","value":"0x9184e72a"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"type":"0x0","v":"0x1f","value":"0x9184e72a"},"id":1}"#;
miner.pending_transactions.lock().insert(hash, signed); miner.pending_transactions.lock().insert(hash, signed);
assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(&request), Some(response.to_owned()));

View File

@ -656,6 +656,7 @@ fn should_confirm_sign_transaction_with_rlp() {
+ &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s()))
+ &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v()))
+ r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"#
+ r#""type":"0x0","#
+ &format!("\"v\":\"0x{:x}\",", U256::from(t.v())) + &format!("\"v\":\"0x{:x}\",", U256::from(t.v()))
+ r#""value":"0x1""# + r#""value":"0x1""#
+ r#"}},"id":1}"#; + r#"}},"id":1}"#;

View File

@ -427,6 +427,7 @@ fn should_add_sign_transaction_to_the_queue() {
+ &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s()))
+ &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v()))
+ r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"#
+ r#""type":"0x0","#
+ &format!("\"v\":\"0x{:x}\",", U256::from(t.v())) + &format!("\"v\":\"0x{:x}\",", U256::from(t.v()))
+ r#""value":"0x9184e72a""# + r#""value":"0x9184e72a""#
+ r#"}},"id":1}"#; + r#"}},"id":1}"#;

View File

@ -227,6 +227,7 @@ fn rpc_eth_sign_transaction() {
+ &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s()))
+ &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v()))
+ r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"#
+ r#""type":"0x0","#
+ &format!("\"v\":\"0x{:x}\",", U256::from(t.v())) + &format!("\"v\":\"0x{:x}\",", U256::from(t.v()))
+ r#""value":"0x9184e72a""# + r#""value":"0x9184e72a""#
+ r#"}},"id":1}"#; + r#"}},"id":1}"#;

View File

@ -51,6 +51,23 @@ macro_rules! register_test {
}; };
} }
macro_rules! extract_non_legacy_chain {
($file: expr, $network: expr) => {{
const RAW_DATA: &'static [u8] = include_bytes!(concat!(
"../../../../ethcore/res/json_tests/",
$file,
".json"
));
::ethjson::blockchain::Test::load(RAW_DATA)
.unwrap()
.into_iter()
.filter(|&(_, ref t)| t.network == $network)
.next()
.unwrap()
.1
}};
}
#[cfg(test)] #[cfg(test)]
mod eth; mod eth;
#[cfg(test)] #[cfg(test)]

View File

@ -60,6 +60,10 @@ pub trait Eth {
#[rpc(name = "eth_gasPrice")] #[rpc(name = "eth_gasPrice")]
fn gas_price(&self) -> BoxFuture<U256>; fn gas_price(&self) -> BoxFuture<U256>;
/// Returns current max_priority_fee
#[rpc(name = "eth_maxPriorityFeePerGas")]
fn max_priority_fee_per_gas(&self) -> BoxFuture<U256>;
/// Returns transaction fee history. /// Returns transaction fee history.
#[rpc(name = "eth_feeHistory")] #[rpc(name = "eth_feeHistory")]
fn fee_history(&self, _: U256, _: BlockNumber, _: Option<Vec<f64>>) fn fee_history(&self, _: U256, _: BlockNumber, _: Option<Vec<f64>>)

View File

@ -114,6 +114,6 @@ pub trait VerifiedTransaction: fmt::Debug {
/// Transaction sender /// Transaction sender
fn sender(&self) -> &Self::Sender; fn sender(&self) -> &Self::Sender;
/// Is it a service transaction? /// Does it have zero gas price?
fn is_service(&self) -> bool; fn has_zero_gas_price(&self) -> bool;
} }

View File

@ -651,7 +651,7 @@ where
Readiness::Ready => { Readiness::Ready => {
//return transaction with score higher or equal to desired //return transaction with score higher or equal to desired
if score >= &self.includable_boundary if score >= &self.includable_boundary
|| tx.transaction.is_service() || tx.transaction.has_zero_gas_price()
{ {
return Some(tx.transaction.clone()); return Some(tx.transaction.clone());
} }
@ -740,7 +740,7 @@ where
if tx_state == Readiness::Ready { if tx_state == Readiness::Ready {
//return transaction with score higher or equal to desired //return transaction with score higher or equal to desired
if best.score >= self.includable_boundary if best.score >= self.includable_boundary
|| best.transaction.transaction.is_service() || best.transaction.transaction.has_zero_gas_price()
{ {
return Some(best.transaction.transaction); return Some(best.transaction.transaction);
} }

View File

@ -50,7 +50,7 @@ impl VerifiedTransaction for Transaction {
fn sender(&self) -> &Address { fn sender(&self) -> &Address {
&self.sender &self.sender
} }
fn is_service(&self) -> bool { fn has_zero_gas_price(&self) -> bool {
false false
} }
} }

View File

@ -1,7 +1,7 @@
[package] [package]
name = "parity-version" name = "parity-version"
# NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION) # NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION)
version = "3.3.0-rc.14" version = "3.3.3"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs" build = "build.rs"

View File

@ -203,11 +203,11 @@ impl ModexpPricer {
let (base_len, exp_len) = (base_len_u256.low_u64(), exp_len_u256.low_u64()); let (base_len, exp_len) = (base_len_u256.low_u64(), exp_len_u256.low_u64());
// read fist 32-byte word of the exponent. // read fist 32-byte word of the exponent.
let exp_low = if base_len + 96 >= input.len() as u64 { let exp_low = if base_len.wrapping_add(96) >= input.len() as u64 {
U256::zero() U256::zero()
} else { } else {
buf.iter_mut().for_each(|b| *b = 0); buf.iter_mut().for_each(|b| *b = 0);
let mut reader = input[(96 + base_len as usize)..].chain(io::repeat(0)); let mut reader = input[(base_len as usize).wrapping_add(96)..].chain(io::repeat(0));
let len = min(exp_len, 32) as usize; let len = min(exp_len, 32) as usize;
reader reader
.read_exact(&mut buf[(32 - len)..]) .read_exact(&mut buf[(32 - len)..])
@ -1728,6 +1728,33 @@ mod tests {
native: EthereumBuiltin::from_str("modexp").unwrap(), native: EthereumBuiltin::from_str("modexp").unwrap(),
}; };
// test for potential base len overflow
{
let input = hex!(
"
00000000000000000000000000000000ffffffffffffffffffffffffffffffff
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000001
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
03
ff"
);
let expected_cost = U256::max_value();
assert_eq!(f.cost(&input[..], 0), expected_cost);
}
// another test for potential base len overflow
{
let input = hex!(
"
00000000000000000000000000000000ffffffffffffffffffffffffffffffff
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000020"
);
let expected_cost = U256::max_value();
assert_eq!(f.cost(&input[..], 0), expected_cost);
}
// test for potential gas cost multiplication overflow // test for potential gas cost multiplication overflow
{ {
let input = hex!("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3"); let input = hex!("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3");
@ -1840,6 +1867,38 @@ mod tests {
} }
} }
#[test]
fn modexp2565() {
let pricer = Modexp2565Pricer {};
// test for potential base len overflow
{
let input = hex!(
"
00000000000000000000000000000000ffffffffffffffffffffffffffffffff
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000001
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
03
ff"
);
let expected_cost = U256::max_value();
assert_eq!(pricer.cost(&input[..]), expected_cost);
}
// another test for potential base len overflow
{
let input = hex!(
"
00000000000000000000000000000000ffffffffffffffffffffffffffffffff
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000020"
);
let expected_cost = U256::max_value();
assert_eq!(pricer.cost(&input[..]), expected_cost);
}
}
#[test] #[test]
fn bn128_add() { fn bn128_add() {
let f = Builtin { let f = Builtin {