Sunce86/eip 1559 (#393)

* eip1559 hard fork activation

* eip1559 hard fork activation 2

* added new transaction type for eip1559

* added base fee field to block header

* fmt fix

* added base fee calculation. added block header validation against base fee

* fmt

* temporarily added modified transaction pool

* tx pool fix of PendingIterator

* tx pool fix of UnorderedIterator

* tx pool added test for set_scoring

* transaction pool changes

* added tests for eip1559 transaction and eip1559 receipt

* added test for eip1559 transaction execution

* block gas limit / block gas target handling

* base fee verification moved out of engine

* calculate_base_fee moved to EthereumMachine

* handling of base_fee_per_gas as part of seal

* handling of base_fee_per_gas changed. Different encoding/decoding of block header

* eip1559 transaction execution - gas price handling

* eip1559 transaction execution - verification, fee burning

* effectiveGasPrice removed from the receipt payload (specs)

* added support for 1559 txs in tx pool verification

* added Aleut test network configuration

* effective_tip_scaled replaced by typed_gas_price

* eip 3198 - Basefee opcode

* rpc - updated structs Block and Header

* rpc changes for 1559

* variable renaming according to spec

* - typed_gas_price renamed to effective_gas_price
- elasticity_multiplier definition moved to update_schedule()

* calculate_base_fee simplified

* Evm environment context temporary fix for gas limit

* fmt fix

* fixed fake_sign::sign_call

* temporary fix for GASLIMIT opcode to provide gas_target actually

* gas_target removed from block header according to spec change: https://github.com/ethereum/EIPs/pull/3566

* tx pool verification fix

* env_info base fee changed to Option

* fmt fix

* pretty format

* updated ethereum tests

* cache_pending refresh on each update of score

* code review fixes

* fmt fix

* code review fix - changed handling of eip1559_base_fee_max_change_denominator

* code review fix - modification.gas_price

* Skip gas_limit_bump for Aura

* gas_limit calculation changed to target ceil

* gas_limit calculation will target ceil on 1559 activation block

* transaction verification updated according spec: https://github.com/ethereum/EIPs/pull/3594

* updated json tests

* ethereum json tests fix for base_fee
This commit is contained in:
Dusan Stanivukovic
2021-06-04 12:12:24 +02:00
committed by GitHub
parent 144b2293a2
commit 5e7086d54c
122 changed files with 6666 additions and 660 deletions

View File

@@ -110,6 +110,8 @@ pub struct SyncConfig {
pub fork_block: Option<(BlockNumber, H256)>,
/// Enable snapshot sync
pub warp_sync: WarpSync,
/// Number of first block where EIP-1559 rules begin. New encoding/decoding block format.
pub eip1559_transition: BlockNumber,
}
impl Default for SyncConfig {
@@ -121,6 +123,7 @@ impl Default for SyncConfig {
subprotocol_name: ETH_PROTOCOL,
fork_block: None,
warp_sync: WarpSync::Disabled,
eip1559_transition: BlockNumber::max_value(),
}
}
}

View File

@@ -250,6 +250,7 @@ impl BlockDownloader {
io: &mut dyn SyncIo,
r: &Rlp,
expected_hash: H256,
eip1559_transition: BlockNumber,
) -> Result<DownloadAction, BlockDownloaderImportError> {
let item_count = r.item_count().unwrap_or(0);
if self.state == State::Idle {
@@ -276,7 +277,7 @@ impl BlockDownloader {
let mut hashes = Vec::new();
let mut last_header = None;
for i in 0..item_count {
let info = SyncHeader::from_rlp(r.at(i)?.as_raw().to_vec())?;
let info = SyncHeader::from_rlp(r.at(i)?.as_raw().to_vec(), eip1559_transition)?;
let number = BlockNumber::from(info.header.number());
let hash = info.header.hash();
@@ -421,6 +422,7 @@ impl BlockDownloader {
&mut self,
r: &Rlp,
expected_hashes: &[H256],
eip1559_transition: BlockNumber,
) -> Result<(), BlockDownloaderImportError> {
let item_count = r.item_count().unwrap_or(0);
if item_count == 0 {
@@ -430,7 +432,7 @@ impl BlockDownloader {
} else {
let mut bodies = Vec::with_capacity(item_count);
for i in 0..item_count {
let body = SyncBody::from_rlp(r.at(i)?.as_raw())?;
let body = SyncBody::from_rlp(r.at(i)?.as_raw(), eip1559_transition)?;
bodies.push(body);
}
@@ -796,21 +798,23 @@ mod tests {
headers: &[BlockHeader],
downloader: &mut BlockDownloader,
io: &mut dyn SyncIo,
eip1559_transition: BlockNumber,
) -> Result<DownloadAction, BlockDownloaderImportError> {
let mut stream = RlpStream::new();
stream.append_list(headers);
let bytes = stream.out();
let rlp = Rlp::new(&bytes);
let expected_hash = headers.first().unwrap().hash();
downloader.import_headers(io, &rlp, expected_hash)
downloader.import_headers(io, &rlp, expected_hash, eip1559_transition)
}
fn import_headers_ok(
headers: &[BlockHeader],
downloader: &mut BlockDownloader,
io: &mut dyn SyncIo,
eip1559_transition: BlockNumber,
) {
let res = import_headers(headers, downloader, io);
let res = import_headers(headers, downloader, io, eip1559_transition);
assert!(res.is_ok());
}
@@ -838,7 +842,12 @@ mod tests {
let rlp_data = encode_list(&valid_headers);
let valid_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &valid_rlp, genesis_hash) {
match downloader.import_headers(
&mut io,
&valid_rlp,
genesis_hash,
spec.params().eip1559_transition,
) {
Ok(DownloadAction::Reset) => assert_eq!(downloader.state, State::Blocks),
_ => panic!("expected transition to Blocks state"),
};
@@ -852,7 +861,12 @@ mod tests {
let rlp_data = encode_list(&invalid_start_block_headers);
let invalid_start_block_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &invalid_start_block_rlp, genesis_hash) {
match downloader.import_headers(
&mut io,
&invalid_start_block_rlp,
genesis_hash,
spec.params().eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -866,7 +880,12 @@ mod tests {
let rlp_data = encode_list(&invalid_skip_headers);
let invalid_skip_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &invalid_skip_rlp, genesis_hash) {
match downloader.import_headers(
&mut io,
&invalid_skip_rlp,
genesis_hash,
spec.params().eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -883,7 +902,12 @@ mod tests {
let rlp_data = encode_list(&too_many_headers);
let too_many_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &too_many_rlp, genesis_hash) {
match downloader.import_headers(
&mut io,
&too_many_rlp,
genesis_hash,
spec.params().eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -894,6 +918,7 @@ mod tests {
::env_logger::try_init().ok();
let mut chain = TestBlockChainClient::new();
let eip1559_transition = BlockNumber::default();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
@@ -913,7 +938,12 @@ mod tests {
let rlp_data = encode_list(&headers);
let headers_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()) {
match downloader.import_headers(
&mut io,
&headers_rlp,
headers[0].hash(),
eip1559_transition,
) {
Ok(DownloadAction::None) => (),
_ => panic!("expected successful import"),
};
@@ -923,7 +953,12 @@ mod tests {
let rlp_data = encode_list(&headers);
let headers_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()) {
match downloader.import_headers(
&mut io,
&headers_rlp,
headers[0].hash(),
eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -933,7 +968,12 @@ mod tests {
let rlp_data = encode_list(&headers);
let headers_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()) {
match downloader.import_headers(
&mut io,
&headers_rlp,
headers[0].hash(),
eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -944,6 +984,7 @@ mod tests {
::env_logger::try_init().ok();
let mut chain = TestBlockChainClient::new();
let eip1559_transition = chain.spec.params().eip1559_transition;
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
@@ -992,7 +1033,7 @@ mod tests {
let rlp_data = encode_list(&headers[0..3]);
let headers_rlp = Rlp::new(&rlp_data);
assert!(downloader
.import_headers(&mut io, &headers_rlp, headers[0].hash())
.import_headers(&mut io, &headers_rlp, headers[0].hash(), eip1559_transition)
.is_ok());
// Import first body successfully.
@@ -1000,7 +1041,11 @@ mod tests {
rlp_data.append_raw(&bodies[0], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
assert!(downloader
.import_bodies(&bodies_rlp, &[headers[0].hash(), headers[1].hash()])
.import_bodies(
&bodies_rlp,
&[headers[0].hash(), headers[1].hash()],
eip1559_transition
)
.is_ok());
// Import second body successfully.
@@ -1008,14 +1053,22 @@ mod tests {
rlp_data.append_raw(&bodies[1], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
assert!(downloader
.import_bodies(&bodies_rlp, &[headers[0].hash(), headers[1].hash()])
.import_bodies(
&bodies_rlp,
&[headers[0].hash(), headers[1].hash()],
eip1559_transition
)
.is_ok());
// Import unexpected third body.
let mut rlp_data = RlpStream::new_list(1);
rlp_data.append_raw(&bodies[2], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
match downloader.import_bodies(&bodies_rlp, &[headers[0].hash(), headers[1].hash()]) {
match downloader.import_bodies(
&bodies_rlp,
&[headers[0].hash(), headers[1].hash()],
eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -1026,6 +1079,7 @@ mod tests {
::env_logger::try_init().ok();
let mut chain = TestBlockChainClient::new();
let eip1559_transition = chain.spec.params().eip1559_transition;
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
@@ -1069,7 +1123,7 @@ mod tests {
let rlp_data = encode_list(&headers[0..3]);
let headers_rlp = Rlp::new(&rlp_data);
assert!(downloader
.import_headers(&mut io, &headers_rlp, headers[0].hash())
.import_headers(&mut io, &headers_rlp, headers[0].hash(), eip1559_transition)
.is_ok());
// Import second and third receipts successfully.
@@ -1085,7 +1139,11 @@ mod tests {
let mut rlp_data = RlpStream::new_list(1);
rlp_data.append_raw(&receipts[3], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
match downloader.import_bodies(&bodies_rlp, &[headers[1].hash(), headers[2].hash()]) {
match downloader.import_bodies(
&bodies_rlp,
&[headers[1].hash(), headers[2].hash()],
eip1559_transition,
) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
@@ -1114,8 +1172,18 @@ mod tests {
let short_subchain = [dummy_header(1, genesis_hash)];
import_headers_ok(&heads, &mut downloader, &mut io);
import_headers_ok(&short_subchain, &mut downloader, &mut io);
import_headers_ok(
&heads,
&mut downloader,
&mut io,
spec.params().eip1559_transition,
);
import_headers_ok(
&short_subchain,
&mut downloader,
&mut io,
spec.params().eip1559_transition,
);
assert_eq!(downloader.state, State::Blocks);
assert!(!downloader.blocks.is_empty());
@@ -1123,7 +1191,12 @@ mod tests {
// simulate receiving useless headers
let head = vec![short_subchain.last().unwrap().clone()];
for _ in 0..MAX_USELESS_HEADERS_PER_ROUND {
let res = import_headers(&head, &mut downloader, &mut io);
let res = import_headers(
&head,
&mut downloader,
&mut io,
spec.params().eip1559_transition,
);
assert!(res.is_err());
}
@@ -1150,8 +1223,18 @@ mod tests {
let short_subchain = [dummy_header(1, genesis_hash)];
import_headers_ok(&heads, &mut downloader, &mut io);
import_headers_ok(&short_subchain, &mut downloader, &mut io);
import_headers_ok(
&heads,
&mut downloader,
&mut io,
spec.params().eip1559_transition,
);
import_headers_ok(
&short_subchain,
&mut downloader,
&mut io,
spec.params().eip1559_transition,
);
assert_eq!(downloader.state, State::Blocks);
assert!(!downloader.blocks.is_empty());
@@ -1159,7 +1242,12 @@ mod tests {
// simulate receiving useless headers
let head = vec![short_subchain.last().unwrap().clone()];
for _ in 0..MAX_USELESS_HEADERS_PER_ROUND {
let res = import_headers(&head, &mut downloader, &mut io);
let res = import_headers(
&head,
&mut downloader,
&mut io,
spec.params().eip1559_transition,
);
assert!(res.is_err());
}

View File

@@ -26,6 +26,7 @@ use triehash_ethereum::ordered_trie_root;
use types::{
header::Header as BlockHeader,
transaction::{TypedTransaction, UnverifiedTransaction},
BlockNumber,
};
malloc_size_of_is_0!(HeaderId);
@@ -37,9 +38,10 @@ pub struct SyncHeader {
}
impl SyncHeader {
pub fn from_rlp(bytes: Bytes) -> Result<Self, DecoderError> {
pub fn from_rlp(bytes: Bytes, eip1559_transition: BlockNumber) -> Result<Self, DecoderError> {
let rlp = Rlp::new(&bytes);
let result = SyncHeader {
header: ::rlp::decode(&bytes)?,
header: BlockHeader::decode_rlp(&rlp, eip1559_transition)?,
bytes,
};
@@ -56,7 +58,7 @@ pub struct SyncBody {
}
impl SyncBody {
pub fn from_rlp(bytes: &[u8]) -> Result<Self, DecoderError> {
pub fn from_rlp(bytes: &[u8], eip1559_transition: BlockNumber) -> Result<Self, DecoderError> {
let rlp = Rlp::new(bytes);
let transactions_rlp = rlp.at(0)?;
let uncles_rlp = rlp.at(1)?;
@@ -65,7 +67,7 @@ impl SyncBody {
transactions_bytes: transactions_rlp.as_raw().to_vec(),
transactions: TypedTransaction::decode_rlp_list(&transactions_rlp)?,
uncles_bytes: uncles_rlp.as_raw().to_vec(),
uncles: uncles_rlp.as_list()?,
uncles: BlockHeader::decode_rlp_list(&uncles_rlp, eip1559_transition)?,
};
Ok(result)
@@ -672,7 +674,13 @@ mod test {
.collect();
let headers: Vec<_> = blocks
.iter()
.map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap())
.map(|b| {
SyncHeader::from_rlp(
Rlp::new(b).at(0).unwrap().as_raw().to_vec(),
client.spec.params().eip1559_transition,
)
.unwrap()
})
.collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let heads: Vec<_> = hashes
@@ -707,7 +715,10 @@ mod test {
bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>(),
blocks[0..6]
.iter()
.map(|b| Unverified::from_rlp(b.to_vec()).unwrap())
.map(
|b| Unverified::from_rlp(b.to_vec(), client.spec.params().eip1559_transition)
.unwrap()
)
.collect::<Vec<_>>()
);
assert!(!bc.contains(&hashes[0]));
@@ -724,7 +735,10 @@ mod test {
bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>(),
blocks[6..16]
.iter()
.map(|b| Unverified::from_rlp(b.to_vec()).unwrap())
.map(
|b| Unverified::from_rlp(b.to_vec(), client.spec.params().eip1559_transition)
.unwrap()
)
.collect::<Vec<_>>()
);
@@ -752,7 +766,13 @@ mod test {
.collect();
let headers: Vec<_> = blocks
.iter()
.map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap())
.map(|b| {
SyncHeader::from_rlp(
Rlp::new(b).at(0).unwrap().as_raw().to_vec(),
client.spec.params().eip1559_transition,
)
.unwrap()
})
.collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let heads: Vec<_> = hashes
@@ -788,7 +808,13 @@ mod test {
.collect();
let headers: Vec<_> = blocks
.iter()
.map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap())
.map(|b| {
SyncHeader::from_rlp(
Rlp::new(b).at(0).unwrap().as_raw().to_vec(),
client.spec.params().eip1559_transition,
)
.unwrap()
})
.collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let heads: Vec<_> = hashes

View File

@@ -159,7 +159,7 @@ impl SyncHandler {
return Ok(());
}
// t_nb 1.0 decode RLP
let block = Unverified::from_rlp(r.at(0)?.as_raw().to_vec())?;
let block = Unverified::from_rlp(r.at(0)?.as_raw().to_vec(), sync.eip1559_transition)?;
let hash = block.header.hash();
let number = block.header.number();
trace!(target: "sync", "{} -> NewBlock ({})", peer_id, hash);
@@ -360,7 +360,7 @@ impl SyncHandler {
Some(ref mut blocks) => blocks,
},
};
downloader.import_bodies(r, expected_blocks.as_slice())?;
downloader.import_bodies(r, expected_blocks.as_slice(), sync.eip1559_transition)?;
}
sync.collect_blocks(io, block_set);
Ok(())
@@ -479,7 +479,7 @@ impl SyncHandler {
Some(ref mut blocks) => blocks,
},
};
downloader.import_headers(io, r, expected_hash)?
downloader.import_headers(io, r, expected_hash, sync.eip1559_transition)?
};
if result == DownloadAction::Reset {

View File

@@ -693,6 +693,8 @@ pub struct ChainSync {
download_old_blocks: bool,
/// Enable warp sync.
warp_sync: WarpSync,
/// New block encoding/decoding format is introduced by the EIP1559
eip1559_transition: BlockNumber,
}
#[derive(Debug, Default)]
@@ -778,6 +780,7 @@ impl ChainSync {
sync_start_time: None,
transactions_stats: TransactionsStats::default(),
warp_sync: config.warp_sync,
eip1559_transition: config.eip1559_transition,
};
sync.update_targets(chain);
sync

View File

@@ -464,14 +464,18 @@ mod test {
rlp.append(&if reverse { 1u32 } else { 0u32 });
rlp.out()
}
fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<SyncHeader> {
fn to_header_vec(
rlp: ::chain::RlpResponseResult,
eip1559_transition: BlockNumber,
) -> Vec<SyncHeader> {
Rlp::new(&rlp.unwrap().unwrap().1.out())
.iter()
.map(|r| SyncHeader::from_rlp(r.as_raw().to_vec()).unwrap())
.map(|r| SyncHeader::from_rlp(r.as_raw().to_vec(), eip1559_transition).unwrap())
.collect()
}
let mut client = TestBlockChainClient::new();
let eip1559_transition = client.spec.params().eip1559_transition;
client.add_blocks(100, EachBlockWith::Nothing);
let blocks: Vec<_> = (0..100)
.map(|i| {
@@ -483,7 +487,13 @@ mod test {
.collect();
let headers: Vec<_> = blocks
.iter()
.map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap())
.map(|b| {
SyncHeader::from_rlp(
Rlp::new(b).at(0).unwrap().as_raw().to_vec(),
eip1559_transition,
)
.unwrap()
})
.collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
@@ -497,27 +507,33 @@ mod test {
&Rlp::new(&make_hash_req(&unknown, 1, 0, false)),
0,
);
assert!(to_header_vec(result).is_empty());
assert!(to_header_vec(result, eip1559_transition).is_empty(),);
let result = SyncSupplier::return_block_headers(
&io,
&Rlp::new(&make_hash_req(&unknown, 1, 0, true)),
0,
);
assert!(to_header_vec(result).is_empty());
assert!(to_header_vec(result, eip1559_transition).is_empty());
let result = SyncSupplier::return_block_headers(
&io,
&Rlp::new(&make_hash_req(&hashes[2], 1, 0, true)),
0,
);
assert_eq!(to_header_vec(result), vec![headers[2].clone()]);
assert_eq!(
to_header_vec(result, eip1559_transition),
vec![headers[2].clone()]
);
let result = SyncSupplier::return_block_headers(
&io,
&Rlp::new(&make_hash_req(&hashes[2], 1, 0, false)),
0,
);
assert_eq!(to_header_vec(result), vec![headers[2].clone()]);
assert_eq!(
to_header_vec(result, eip1559_transition),
vec![headers[2].clone()]
);
let result = SyncSupplier::return_block_headers(
&io,
@@ -525,7 +541,7 @@ mod test {
0,
);
assert_eq!(
to_header_vec(result),
to_header_vec(result, eip1559_transition),
vec![
headers[50].clone(),
headers[56].clone(),
@@ -539,7 +555,7 @@ mod test {
0,
);
assert_eq!(
to_header_vec(result),
to_header_vec(result, eip1559_transition),
vec![
headers[50].clone(),
headers[44].clone(),
@@ -549,16 +565,22 @@ mod test {
let result =
SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(2, 1, 0, true)), 0);
assert_eq!(to_header_vec(result), vec![headers[2].clone()]);
assert_eq!(
to_header_vec(result, eip1559_transition),
vec![headers[2].clone()]
);
let result =
SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(2, 1, 0, false)), 0);
assert_eq!(to_header_vec(result), vec![headers[2].clone()]);
assert_eq!(
to_header_vec(result, eip1559_transition),
vec![headers[2].clone()]
);
let result =
SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(50, 3, 5, false)), 0);
assert_eq!(
to_header_vec(result),
to_header_vec(result, eip1559_transition),
vec![
headers[50].clone(),
headers[56].clone(),
@@ -569,7 +591,7 @@ mod test {
let result =
SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(50, 3, 5, true)), 0);
assert_eq!(
to_header_vec(result),
to_header_vec(result, eip1559_transition),
vec![
headers[50].clone(),
headers[44].clone(),