TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135)
This commit is contained in:
@@ -762,7 +762,7 @@ mod tests {
|
||||
use triehash_ethereum::ordered_trie_root;
|
||||
use types::{
|
||||
header::Header as BlockHeader,
|
||||
transaction::{SignedTransaction, Transaction},
|
||||
transaction::{SignedTransaction, Transaction, TypedTransaction},
|
||||
};
|
||||
|
||||
fn dummy_header(number: u64, parent_hash: H256) -> BlockHeader {
|
||||
@@ -778,7 +778,7 @@ mod tests {
|
||||
|
||||
fn dummy_signed_tx() -> SignedTransaction {
|
||||
let keypair = Random.generate().unwrap();
|
||||
Transaction::default().sign(keypair.secret(), None)
|
||||
TypedTransaction::Legacy(Transaction::default()).sign(keypair.secret(), None)
|
||||
}
|
||||
|
||||
fn import_headers(
|
||||
@@ -949,8 +949,16 @@ mod tests {
|
||||
::rlp::EMPTY_LIST_RLP.to_vec()
|
||||
};
|
||||
|
||||
let txs = encode_list(&[dummy_signed_tx()]);
|
||||
let tx_root = ordered_trie_root(Rlp::new(&txs).iter().map(|r| r.as_raw()));
|
||||
let mut rlp_strem = RlpStream::new();
|
||||
SignedTransaction::rlp_append_list(&mut rlp_strem, &[dummy_signed_tx()]);
|
||||
let txs = rlp_strem.drain();
|
||||
let tx_root = ordered_trie_root(Rlp::new(&txs).iter().map(|r| {
|
||||
if r.is_list() {
|
||||
r.as_raw()
|
||||
} else {
|
||||
r.data().expect("It is expected that raw rlp list is valid")
|
||||
}
|
||||
}));
|
||||
|
||||
let mut rlp = RlpStream::new_list(2);
|
||||
rlp.append_raw(&txs, 1);
|
||||
@@ -1019,14 +1027,20 @@ mod tests {
|
||||
// Construct the receipts. Receipt root for the first two blocks is the same.
|
||||
//
|
||||
// The RLP-encoded integers are clearly not receipts, but the BlockDownloader treats
|
||||
// all receipts as byte blobs, so it does not matter.
|
||||
// all receipts as byte blobs, so it does not matter. It is just important that they are
|
||||
// represended as list (0xc1) so that they passes as legacy list
|
||||
let receipts_rlp = if i < 2 {
|
||||
encode_list(&[0u32])
|
||||
vec![0xC1, 0]
|
||||
} else {
|
||||
encode_list(&[i as u32])
|
||||
vec![0xC1, i as u8]
|
||||
};
|
||||
let receipts_root =
|
||||
ordered_trie_root(Rlp::new(&receipts_rlp).iter().map(|r| r.as_raw()));
|
||||
let receipts_root = ordered_trie_root(Rlp::new(&receipts_rlp).iter().map(|r| {
|
||||
if r.is_list() {
|
||||
r.as_raw()
|
||||
} else {
|
||||
r.data().expect("expect proper test data")
|
||||
}
|
||||
}));
|
||||
receipts.push(receipts_rlp);
|
||||
|
||||
// Construct the block header.
|
||||
|
||||
@@ -23,7 +23,10 @@ use network;
|
||||
use rlp::{DecoderError, Rlp, RlpStream};
|
||||
use std::collections::{hash_map, BTreeMap, HashMap, HashSet};
|
||||
use triehash_ethereum::ordered_trie_root;
|
||||
use types::{header::Header as BlockHeader, transaction::UnverifiedTransaction};
|
||||
use types::{
|
||||
header::Header as BlockHeader,
|
||||
transaction::{TypedTransaction, UnverifiedTransaction},
|
||||
};
|
||||
|
||||
known_heap_size!(0, HeaderId);
|
||||
|
||||
@@ -65,7 +68,7 @@ impl SyncBody {
|
||||
|
||||
let result = SyncBody {
|
||||
transactions_bytes: transactions_rlp.as_raw().to_vec(),
|
||||
transactions: transactions_rlp.as_list()?,
|
||||
transactions: TypedTransaction::decode_rlp_list(&transactions_rlp)?,
|
||||
uncles_bytes: uncles_rlp.as_raw().to_vec(),
|
||||
uncles: uncles_rlp.as_list()?,
|
||||
};
|
||||
@@ -454,11 +457,14 @@ impl BlockCollection {
|
||||
|
||||
fn insert_body(&mut self, body: SyncBody) -> Result<H256, network::Error> {
|
||||
let header_id = {
|
||||
let tx_root = ordered_trie_root(
|
||||
Rlp::new(&body.transactions_bytes)
|
||||
.iter()
|
||||
.map(|r| r.as_raw()),
|
||||
);
|
||||
let tx_root = ordered_trie_root(Rlp::new(&body.transactions_bytes).iter().map(|r| {
|
||||
if r.is_list() {
|
||||
r.as_raw()
|
||||
} else {
|
||||
// this list is already decoded and passed validation, for this we are okay to expect proper data
|
||||
r.data().expect("Expect raw transaction list to be valid")
|
||||
}
|
||||
}));
|
||||
let uncles = keccak(&body.uncles_bytes);
|
||||
HeaderId {
|
||||
transactions_root: tx_root,
|
||||
@@ -491,7 +497,22 @@ impl BlockCollection {
|
||||
fn insert_receipt(&mut self, r: Bytes) -> Result<Vec<H256>, network::Error> {
|
||||
let receipt_root = {
|
||||
let receipts = Rlp::new(&r);
|
||||
ordered_trie_root(receipts.iter().map(|r| r.as_raw()))
|
||||
//check receipts data before calculating trie root
|
||||
let mut temp_receipts: Vec<&[u8]> = Vec::new();
|
||||
for receipt_byte in receipts.iter() {
|
||||
if receipt_byte.is_list() {
|
||||
temp_receipts.push(receipt_byte.as_raw())
|
||||
} else {
|
||||
temp_receipts.push(
|
||||
receipt_byte
|
||||
.data()
|
||||
.map_err(|e| network::ErrorKind::Rlp(e))?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate trie root and use it as hash
|
||||
ordered_trie_root(temp_receipts.iter())
|
||||
};
|
||||
self.downloading_receipts.remove(&receipt_root);
|
||||
match self.receipt_ids.entry(receipt_root) {
|
||||
|
||||
@@ -837,9 +837,12 @@ impl SyncHandler {
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{:02} -> Transactions ({} entries)", peer_id, item_count);
|
||||
let mut transactions = Vec::with_capacity(item_count);
|
||||
for i in 0..item_count {
|
||||
let rlp = r.at(i)?;
|
||||
let tx = rlp.as_raw().to_vec();
|
||||
for i in r.iter() {
|
||||
let tx = if i.is_list() {
|
||||
i.as_raw().to_vec() // legacy transaction. just add it raw
|
||||
} else {
|
||||
i.data()?.to_vec() // typed transaction. remove header from start and send only payload.
|
||||
};
|
||||
transactions.push(tx);
|
||||
}
|
||||
io.chain().queue_transactions(transactions, peer_id);
|
||||
|
||||
@@ -21,7 +21,7 @@ use ethereum_types::H256;
|
||||
use fastmap::H256FastSet;
|
||||
use network::{client_version::ClientCapabilities, PeerId};
|
||||
use rand::Rng;
|
||||
use rlp::{Encodable, RlpStream};
|
||||
use rlp::RlpStream;
|
||||
use sync_io::SyncIo;
|
||||
use types::{blockchain_info::BlockChainInfo, transaction::SignedTransaction, BlockNumber};
|
||||
|
||||
@@ -121,7 +121,7 @@ impl SyncPropagator {
|
||||
let (transactions, service_transactions): (Vec<_>, Vec<_>) = transactions
|
||||
.iter()
|
||||
.map(|tx| tx.signed())
|
||||
.partition(|tx| !tx.gas_price.is_zero());
|
||||
.partition(|tx| !tx.tx().gas_price.is_zero());
|
||||
|
||||
// usual transactions could be propagated to all peers
|
||||
let mut affected_peers = HashSet::new();
|
||||
@@ -171,7 +171,7 @@ impl SyncPropagator {
|
||||
let all_transactions_rlp = {
|
||||
let mut packet = RlpStream::new_list(transactions.len());
|
||||
for tx in &transactions {
|
||||
packet.append(&**tx);
|
||||
tx.rlp_append(&mut packet);
|
||||
}
|
||||
packet.out()
|
||||
};
|
||||
@@ -238,13 +238,8 @@ impl SyncPropagator {
|
||||
for tx in &transactions {
|
||||
let hash = tx.hash();
|
||||
if to_send.contains(&hash) {
|
||||
let mut transaction = RlpStream::new();
|
||||
tx.rlp_append(&mut transaction);
|
||||
let appended = packet.append_raw_checked(
|
||||
&transaction.drain(),
|
||||
1,
|
||||
MAX_TRANSACTION_PACKET_SIZE,
|
||||
);
|
||||
let appended =
|
||||
packet.append_raw_checked(&tx.encode(), 1, MAX_TRANSACTION_PACKET_SIZE);
|
||||
if !appended {
|
||||
// Maximal packet size reached just proceed with sending
|
||||
debug!(target: "sync", "Transaction packet size limit reached. Sending incomplete set of {}/{} transactions.", pushed, to_send.len());
|
||||
@@ -373,6 +368,7 @@ mod tests {
|
||||
use rlp::Rlp;
|
||||
use std::collections::VecDeque;
|
||||
use tests::{helpers::TestIo, snapshot::TestSnapshotService};
|
||||
use types::transaction::TypedTransaction;
|
||||
|
||||
use super::{
|
||||
super::{tests::*, *},
|
||||
@@ -707,7 +703,9 @@ mod tests {
|
||||
return None;
|
||||
}
|
||||
|
||||
rlp.at(0).ok().and_then(|r| r.as_val().ok())
|
||||
rlp.at(0)
|
||||
.ok()
|
||||
.and_then(|r| TypedTransaction::decode_rlp(&r).ok())
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(sent_transactions.len(), 2);
|
||||
|
||||
@@ -26,18 +26,18 @@ use ethkey::{KeyPair, Secret};
|
||||
use hash::keccak;
|
||||
use io::{IoChannel, IoHandler};
|
||||
use std::sync::Arc;
|
||||
use types::transaction::{Action, PendingTransaction, Transaction};
|
||||
use types::transaction::{Action, PendingTransaction, Transaction, TypedTransaction};
|
||||
use SyncConfig;
|
||||
|
||||
fn new_tx(secret: &Secret, nonce: U256, chain_id: u64) -> PendingTransaction {
|
||||
let signed = Transaction {
|
||||
let signed = TypedTransaction::Legacy(Transaction {
|
||||
nonce: nonce.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 21000.into(),
|
||||
action: Action::Call(Address::default()),
|
||||
value: 0.into(),
|
||||
data: Vec::new(),
|
||||
}
|
||||
})
|
||||
.sign(secret, Some(chain_id));
|
||||
PendingTransaction::new(signed, None)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user