TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135)
This commit is contained in:
@@ -48,10 +48,10 @@ use verification::PreverifiedBlock;
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
|
||||
use hash::keccak;
|
||||
use rlp::{encode_list, Encodable, RlpStream};
|
||||
use rlp::{encode_list, RlpStream};
|
||||
use types::{
|
||||
header::{ExtendedHeader, Header},
|
||||
receipt::{Receipt, TransactionOutcome},
|
||||
receipt::{TransactionOutcome, TypedReceipt},
|
||||
transaction::{Error as TransactionError, SignedTransaction},
|
||||
};
|
||||
|
||||
@@ -99,7 +99,7 @@ pub struct ExecutedBlock {
|
||||
/// Uncles.
|
||||
pub uncles: Vec<Header>,
|
||||
/// Transaction receipts.
|
||||
pub receipts: Vec<Receipt>,
|
||||
pub receipts: Vec<TypedReceipt>,
|
||||
/// Hashes of already executed transactions.
|
||||
pub transactions_set: HashSet<H256>,
|
||||
/// Underlaying state.
|
||||
@@ -253,7 +253,7 @@ impl<'x> OpenBlock<'x> {
|
||||
&mut self,
|
||||
t: SignedTransaction,
|
||||
h: Option<H256>,
|
||||
) -> Result<&Receipt, Error> {
|
||||
) -> Result<&TypedReceipt, Error> {
|
||||
if self.block.transactions_set.contains(&t.hash()) {
|
||||
return Err(TransactionError::AlreadyImported.into());
|
||||
}
|
||||
@@ -360,13 +360,13 @@ impl<'x> OpenBlock<'x> {
|
||||
|
||||
// t_nb 8.5.3 fill open block header with all other fields
|
||||
s.block.header.set_transactions_root(ordered_trie_root(
|
||||
s.block.transactions.iter().map(|e| e.rlp_bytes()),
|
||||
s.block.transactions.iter().map(|e| e.encode()),
|
||||
));
|
||||
let uncle_bytes = encode_list(&s.block.uncles);
|
||||
s.block.header.set_uncles_hash(keccak(&uncle_bytes));
|
||||
s.block.header.set_state_root(s.block.state.root().clone());
|
||||
s.block.header.set_receipts_root(ordered_trie_root(
|
||||
s.block.receipts.iter().map(|r| r.rlp_bytes()),
|
||||
s.block.receipts.iter().map(|r| r.encode()),
|
||||
));
|
||||
s.block
|
||||
.header
|
||||
@@ -453,7 +453,7 @@ impl LockedBlock {
|
||||
receipt.outcome = TransactionOutcome::Unknown;
|
||||
}
|
||||
self.block.header.set_receipts_root(ordered_trie_root(
|
||||
self.block.receipts.iter().map(|r| r.rlp_bytes()),
|
||||
self.block.receipts.iter().map(|r| r.encode()),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ impl SealedBlock {
|
||||
pub fn rlp_bytes(&self) -> Bytes {
|
||||
let mut block_rlp = RlpStream::new_list(3);
|
||||
block_rlp.append(&self.block.header);
|
||||
block_rlp.append_list(&self.block.transactions);
|
||||
SignedTransaction::rlp_append_list(&mut block_rlp, &self.block.transactions);
|
||||
block_rlp.append_list(&self.block.uncles);
|
||||
block_rlp.out()
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ use itertools::Itertools;
|
||||
use kvdb::{DBTransaction, DBValue, KeyValueDB};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use rand::OsRng;
|
||||
use rlp::PayloadInfo;
|
||||
use rlp::{PayloadInfo, Rlp};
|
||||
use rustc_hex::FromHex;
|
||||
use trie::{Trie, TrieFactory, TrieSpec};
|
||||
use types::{
|
||||
@@ -51,8 +51,11 @@ use types::{
|
||||
filter::Filter,
|
||||
header::{ExtendedHeader, Header},
|
||||
log_entry::LocalizedLogEntry,
|
||||
receipt::{LocalizedReceipt, Receipt},
|
||||
transaction::{self, Action, LocalizedTransaction, SignedTransaction, UnverifiedTransaction},
|
||||
receipt::{LocalizedReceipt, TypedReceipt},
|
||||
transaction::{
|
||||
self, Action, LocalizedTransaction, SignedTransaction, TypedTransaction,
|
||||
UnverifiedTransaction,
|
||||
},
|
||||
BlockNumber,
|
||||
};
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
@@ -524,7 +527,8 @@ impl Importer {
|
||||
db: &dyn KeyValueDB,
|
||||
chain: &BlockChain,
|
||||
) -> EthcoreResult<()> {
|
||||
let receipts = ::rlp::decode_list(receipts_bytes);
|
||||
let receipts = TypedReceipt::decode_rlp_list(&Rlp::new(receipts_bytes))
|
||||
.unwrap_or_else(|e| panic!("Receipt bytes should be valid: {:?}", e));
|
||||
let _import_lock = self.import_lock.lock();
|
||||
|
||||
{
|
||||
@@ -714,7 +718,7 @@ impl Importer {
|
||||
&self,
|
||||
header: &Header,
|
||||
block_bytes: &[u8],
|
||||
receipts: &[Receipt],
|
||||
receipts: &[TypedReceipt],
|
||||
state_db: &StateDB,
|
||||
client: &Client,
|
||||
) -> EthcoreResult<Option<PendingTransition>> {
|
||||
@@ -1436,7 +1440,7 @@ impl Client {
|
||||
data: Bytes,
|
||||
) -> SignedTransaction {
|
||||
let from = Address::default();
|
||||
transaction::Transaction {
|
||||
TypedTransaction::Legacy(transaction::Transaction {
|
||||
nonce: self
|
||||
.nonce(&from, block_id)
|
||||
.unwrap_or_else(|| self.engine.account_start_nonce(0)),
|
||||
@@ -1445,7 +1449,7 @@ impl Client {
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data: data,
|
||||
}
|
||||
})
|
||||
.fake_sign(from)
|
||||
}
|
||||
|
||||
@@ -1889,7 +1893,7 @@ impl Call for Client {
|
||||
|
||||
let exec = |gas| {
|
||||
let mut tx = t.as_unsigned().clone();
|
||||
tx.gas = gas;
|
||||
tx.tx_mut().gas = gas;
|
||||
let tx = tx.fake_sign(sender);
|
||||
|
||||
let mut clone = state.clone();
|
||||
@@ -1920,6 +1924,7 @@ impl Call for Client {
|
||||
}
|
||||
}
|
||||
let lower = t
|
||||
.tx()
|
||||
.gas_required(&self.engine.schedule(env_info.number))
|
||||
.into();
|
||||
if cond(lower) {
|
||||
@@ -2571,18 +2576,18 @@ impl BlockChainClient for Client {
|
||||
} else {
|
||||
self.importer.miner.sensible_gas_price()
|
||||
};
|
||||
let transaction = transaction::Transaction {
|
||||
let transaction = TypedTransaction::Legacy(transaction::Transaction {
|
||||
nonce: self.latest_nonce(&authoring_params.author),
|
||||
action: Action::Call(address),
|
||||
gas: self.importer.miner.sensible_gas_limit(),
|
||||
gas_price,
|
||||
value: U256::zero(),
|
||||
data: data,
|
||||
};
|
||||
});
|
||||
let chain_id = self.engine.signing_chain_id(&self.latest_env_info());
|
||||
let signature = self
|
||||
.engine
|
||||
.sign(transaction.hash(chain_id))
|
||||
.sign(transaction.signature_hash(chain_id))
|
||||
.map_err(|e| transaction::Error::InvalidSignature(e.to_string()))?;
|
||||
let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?;
|
||||
self.importer
|
||||
@@ -2602,10 +2607,15 @@ impl IoClient for Client {
|
||||
self.queue_transactions
|
||||
.queue(&self.io_channel.read(), len, move |client| {
|
||||
trace_time!("import_queued_transactions");
|
||||
|
||||
let best_block_number = client.best_block_header().number();
|
||||
let txs: Vec<UnverifiedTransaction> = transactions
|
||||
.iter()
|
||||
.filter_map(|bytes| client.engine.decode_transaction(bytes).ok())
|
||||
.filter_map(|bytes| {
|
||||
client
|
||||
.engine
|
||||
.decode_transaction(bytes, best_block_number)
|
||||
.ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
client.notify(|notify| {
|
||||
@@ -2954,7 +2964,7 @@ impl ProvingBlockChainClient for Client {
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
env_info.gas_limit = transaction.gas.clone();
|
||||
env_info.gas_limit = transaction.tx().gas.clone();
|
||||
let mut jdb = self.state_db.read().journal_db().boxed_clone();
|
||||
|
||||
state::prove_transaction_virtual(
|
||||
@@ -3112,7 +3122,7 @@ impl ImportExportBlocks for Client {
|
||||
fn transaction_receipt(
|
||||
machine: &::machine::EthereumMachine,
|
||||
mut tx: LocalizedTransaction,
|
||||
receipt: Receipt,
|
||||
receipt: TypedReceipt,
|
||||
prior_gas_used: U256,
|
||||
prior_no_of_logs: usize,
|
||||
) -> LocalizedReceipt {
|
||||
@@ -3121,27 +3131,31 @@ fn transaction_receipt(
|
||||
let block_hash = tx.block_hash;
|
||||
let block_number = tx.block_number;
|
||||
let transaction_index = tx.transaction_index;
|
||||
let transaction_type = tx.tx_type();
|
||||
|
||||
let receipt = receipt.receipt().clone();
|
||||
|
||||
LocalizedReceipt {
|
||||
from: sender,
|
||||
to: match tx.action {
|
||||
to: match tx.tx().action {
|
||||
Action::Create => None,
|
||||
Action::Call(ref address) => Some(address.clone().into()),
|
||||
},
|
||||
transaction_hash: transaction_hash,
|
||||
transaction_index: transaction_index,
|
||||
transaction_type: transaction_type,
|
||||
block_hash: block_hash,
|
||||
block_number: block_number,
|
||||
cumulative_gas_used: receipt.gas_used,
|
||||
gas_used: receipt.gas_used - prior_gas_used,
|
||||
contract_address: match tx.action {
|
||||
contract_address: match tx.tx().action {
|
||||
Action::Call(_) => None,
|
||||
Action::Create => Some(
|
||||
contract_address(
|
||||
machine.create_address_scheme(block_number),
|
||||
&sender,
|
||||
&tx.nonce,
|
||||
&tx.data,
|
||||
&tx.tx().nonce,
|
||||
&tx.tx().data,
|
||||
)
|
||||
.0,
|
||||
),
|
||||
@@ -3161,7 +3175,7 @@ fn transaction_receipt(
|
||||
})
|
||||
.collect(),
|
||||
log_bloom: receipt.log_bloom,
|
||||
outcome: receipt.outcome,
|
||||
outcome: receipt.outcome.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3457,8 +3471,8 @@ mod tests {
|
||||
use hash::keccak;
|
||||
use types::{
|
||||
log_entry::{LocalizedLogEntry, LogEntry},
|
||||
receipt::{LocalizedReceipt, Receipt, TransactionOutcome},
|
||||
transaction::{Action, LocalizedTransaction, Transaction},
|
||||
receipt::{LegacyReceipt, LocalizedReceipt, TransactionOutcome, TypedReceipt},
|
||||
transaction::{Action, LocalizedTransaction, Transaction, TypedTransaction},
|
||||
};
|
||||
|
||||
// given
|
||||
@@ -3470,14 +3484,14 @@ mod tests {
|
||||
let block_hash = 5.into();
|
||||
let state_root = 99.into();
|
||||
let gas_used = 10.into();
|
||||
let raw_tx = Transaction {
|
||||
let raw_tx = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 21000.into(),
|
||||
action: Action::Call(10.into()),
|
||||
value: 0.into(),
|
||||
data: vec![],
|
||||
};
|
||||
});
|
||||
let tx1 = raw_tx.clone().sign(secret, None);
|
||||
let transaction = LocalizedTransaction {
|
||||
signed: tx1.clone().into(),
|
||||
@@ -3498,12 +3512,12 @@ mod tests {
|
||||
data: vec![],
|
||||
},
|
||||
];
|
||||
let receipt = Receipt {
|
||||
let receipt = TypedReceipt::Legacy(LegacyReceipt {
|
||||
outcome: TransactionOutcome::StateRoot(state_root),
|
||||
gas_used: gas_used,
|
||||
log_bloom: Default::default(),
|
||||
logs: logs.clone(),
|
||||
};
|
||||
});
|
||||
|
||||
// when
|
||||
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1);
|
||||
@@ -3513,12 +3527,13 @@ mod tests {
|
||||
receipt,
|
||||
LocalizedReceipt {
|
||||
from: tx1.sender().into(),
|
||||
to: match tx1.action {
|
||||
to: match tx1.tx().action {
|
||||
Action::Create => None,
|
||||
Action::Call(ref address) => Some(address.clone().into()),
|
||||
},
|
||||
transaction_hash: tx1.hash(),
|
||||
transaction_index: 1,
|
||||
transaction_type: tx1.tx_type(),
|
||||
block_hash: block_hash,
|
||||
block_number: block_number,
|
||||
cumulative_gas_used: gas_used,
|
||||
|
||||
@@ -281,7 +281,7 @@ impl<'a> EvmTestClient<'a> {
|
||||
tracer: T,
|
||||
vm_tracer: V,
|
||||
) -> std::result::Result<TransactSuccess<T::Output, V::Output>, TransactErr> {
|
||||
let initial_gas = transaction.gas;
|
||||
let initial_gas = transaction.tx().gas;
|
||||
// Verify transaction
|
||||
let is_ok = transaction.verify_basic(true, None);
|
||||
if let Err(error) = is_ok {
|
||||
@@ -342,18 +342,18 @@ impl<'a> EvmTestClient<'a> {
|
||||
Ok(result) => Ok(TransactSuccess {
|
||||
state_root,
|
||||
gas_left: initial_gas - result.receipt.gas_used,
|
||||
outcome: result.receipt.outcome,
|
||||
outcome: result.receipt.outcome.clone(),
|
||||
output: result.output,
|
||||
trace: result.trace,
|
||||
vm_trace: result.vm_trace,
|
||||
logs: result.receipt.logs,
|
||||
contract_address: if let transaction::Action::Create = transaction.action {
|
||||
logs: result.receipt.logs.clone(),
|
||||
contract_address: if let transaction::Action::Create = transaction.tx().action {
|
||||
Some(
|
||||
executive::contract_address(
|
||||
scheme,
|
||||
&transaction.sender(),
|
||||
&transaction.nonce,
|
||||
&transaction.data,
|
||||
&transaction.tx().nonce,
|
||||
&transaction.tx().data,
|
||||
)
|
||||
.0,
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ use itertools::Itertools;
|
||||
use kvdb::DBValue;
|
||||
use kvdb_memorydb;
|
||||
use parking_lot::RwLock;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use rlp::RlpStream;
|
||||
use rustc_hex::FromHex;
|
||||
use types::{
|
||||
basic_account::BasicAccount,
|
||||
@@ -45,8 +45,11 @@ use types::{
|
||||
header::Header,
|
||||
log_entry::LocalizedLogEntry,
|
||||
pruning_info::PruningInfo,
|
||||
receipt::{LocalizedReceipt, Receipt, TransactionOutcome},
|
||||
transaction::{self, Action, LocalizedTransaction, SignedTransaction, Transaction},
|
||||
receipt::{LegacyReceipt, LocalizedReceipt, TransactionOutcome, TypedReceipt},
|
||||
transaction::{
|
||||
self, Action, LocalizedTransaction, SignedTransaction, Transaction, TypedTransaction,
|
||||
TypedTxId,
|
||||
},
|
||||
view,
|
||||
views::BlockView,
|
||||
BlockNumber,
|
||||
@@ -296,16 +299,16 @@ impl TestBlockChainClient {
|
||||
|
||||
for _ in 0..num_transactions {
|
||||
// Update nonces value
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(100),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::from(200_000_000_000u64),
|
||||
nonce: nonce,
|
||||
};
|
||||
});
|
||||
let signed_tx = tx.sign(keypair.secret(), None);
|
||||
txs.append(&signed_tx);
|
||||
signed_tx.rlp_append(&mut txs);
|
||||
nonce += U256::one();
|
||||
}
|
||||
|
||||
@@ -369,14 +372,14 @@ impl TestBlockChainClient {
|
||||
/// Inserts a transaction with given gas price to miners transactions queue.
|
||||
pub fn insert_transaction_with_gas_price_to_queue(&self, gas_price: U256) -> H256 {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(100),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: gas_price,
|
||||
nonce: U256::zero(),
|
||||
};
|
||||
});
|
||||
let signed_tx = tx.sign(keypair.secret(), None);
|
||||
self.set_balance(signed_tx.sender(), 10_000_000_000_000_000_000u64.into());
|
||||
let hash = signed_tx.hash();
|
||||
@@ -938,10 +941,13 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
|
||||
// starts with 'f' ?
|
||||
if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") {
|
||||
let receipt = BlockReceipts::new(vec![Receipt::new(
|
||||
TransactionOutcome::StateRoot(H256::zero()),
|
||||
U256::zero(),
|
||||
vec![],
|
||||
let receipt = BlockReceipts::new(vec![TypedReceipt::new(
|
||||
TypedTxId::Legacy,
|
||||
LegacyReceipt::new(
|
||||
TransactionOutcome::StateRoot(H256::zero()),
|
||||
U256::zero(),
|
||||
vec![],
|
||||
),
|
||||
)]);
|
||||
return Some(receipt);
|
||||
}
|
||||
@@ -1027,16 +1033,20 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}
|
||||
|
||||
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> {
|
||||
let transaction = Transaction {
|
||||
let transaction = TypedTransaction::Legacy(Transaction {
|
||||
nonce: self.latest_nonce(&self.miner.authoring_params().author),
|
||||
action: Action::Call(address),
|
||||
gas: self.spec.gas_limit,
|
||||
gas_price: U256::zero(),
|
||||
value: U256::default(),
|
||||
data: data,
|
||||
};
|
||||
});
|
||||
let chain_id = Some(self.spec.chain_id());
|
||||
let sig = self.spec.engine.sign(transaction.hash(chain_id)).unwrap();
|
||||
let sig = self
|
||||
.spec
|
||||
.engine
|
||||
.sign(transaction.signature_hash(chain_id))
|
||||
.unwrap();
|
||||
let signed = SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap();
|
||||
self.miner.import_own_transaction(self, signed.into())
|
||||
}
|
||||
@@ -1051,7 +1061,7 @@ impl IoClient for TestBlockChainClient {
|
||||
// import right here
|
||||
let txs = transactions
|
||||
.into_iter()
|
||||
.filter_map(|bytes| Rlp::new(&bytes).as_val().ok())
|
||||
.filter_map(|bytes| TypedTransaction::decode(&bytes).ok())
|
||||
.collect();
|
||||
self.miner.import_external_transactions(self, txs);
|
||||
}
|
||||
|
||||
@@ -1765,7 +1765,7 @@ mod tests {
|
||||
use test_helpers::{generate_dummy_client_with_spec, get_temp_state_db, TestNotify};
|
||||
use types::{
|
||||
header::Header,
|
||||
transaction::{Action, Transaction},
|
||||
transaction::{Action, Transaction, TypedTransaction},
|
||||
};
|
||||
|
||||
fn aura<F>(f: F) -> Arc<AuthorityRound>
|
||||
@@ -2287,14 +2287,14 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
b2.push_transaction(
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
nonce: U256::from(0),
|
||||
gas_price: U256::from(3000),
|
||||
gas: U256::from(53_000),
|
||||
value: U256::from(1),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.fake_sign(addr2),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -605,8 +605,10 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
|
||||
fn decode_transaction(
|
||||
&self,
|
||||
transaction: &[u8],
|
||||
best_block_number: BlockNumber,
|
||||
) -> Result<UnverifiedTransaction, transaction::Error> {
|
||||
self.machine().decode_transaction(transaction)
|
||||
let schedule = self.schedule(best_block_number);
|
||||
self.machine().decode_transaction(transaction, &schedule)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use kvdb::DBValue;
|
||||
use memory_cache::MemoryLruCache;
|
||||
use parking_lot::RwLock;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use types::{header::Header, ids::BlockId, log_entry::LogEntry, receipt::Receipt};
|
||||
use types::{header::Header, ids::BlockId, log_entry::LogEntry, receipt::TypedReceipt};
|
||||
use unexpected::Mismatch;
|
||||
|
||||
use super::{simple_list::SimpleList, SystemCall, ValidatorSet};
|
||||
@@ -91,7 +91,7 @@ fn check_first_proof(
|
||||
old_header: Header,
|
||||
state_items: &[DBValue],
|
||||
) -> Result<Vec<Address>, String> {
|
||||
use types::transaction::{Action, Transaction};
|
||||
use types::transaction::{Action, Transaction, TypedTransaction};
|
||||
|
||||
// TODO: match client contract_call_tx more cleanly without duplication.
|
||||
const PROVIDED_GAS: u64 = 50_000_000;
|
||||
@@ -116,14 +116,14 @@ fn check_first_proof(
|
||||
let (data, decoder) = validator_set::functions::get_validators::call();
|
||||
|
||||
let from = Address::default();
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
nonce: machine.account_start_nonce(number),
|
||||
action: Action::Call(contract_address),
|
||||
gas: PROVIDED_GAS.into(),
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data,
|
||||
}
|
||||
})
|
||||
.fake_sign(from);
|
||||
|
||||
let res = ::state::check_proof(
|
||||
@@ -161,14 +161,15 @@ fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Erro
|
||||
// inter-contract proofs are a header and receipts.
|
||||
// checking will involve ensuring that the receipts match the header and
|
||||
// extracting the validator set from the receipts.
|
||||
fn encode_proof(header: &Header, receipts: &[Receipt]) -> Bytes {
|
||||
fn encode_proof(header: &Header, receipts: &[TypedReceipt]) -> Bytes {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(header).append_list(receipts);
|
||||
stream.append(header);
|
||||
TypedReceipt::rlp_append_list(&mut stream, receipts);
|
||||
stream.drain()
|
||||
}
|
||||
|
||||
fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {
|
||||
Ok((rlp.val_at(0)?, rlp.list_at(1)?))
|
||||
fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<TypedReceipt>), ::error::Error> {
|
||||
Ok((rlp.val_at(0)?, TypedReceipt::decode_rlp_list(&rlp.at(1)?)?))
|
||||
}
|
||||
|
||||
// given a provider and caller, generate proof. this will just be a state proof
|
||||
@@ -265,7 +266,7 @@ impl ValidatorSafeContract {
|
||||
&self,
|
||||
bloom: Bloom,
|
||||
header: &Header,
|
||||
receipts: &[Receipt],
|
||||
receipts: &[TypedReceipt],
|
||||
) -> Option<SimpleList> {
|
||||
let check_log = |log: &LogEntry| {
|
||||
log.address == self.contract_address
|
||||
@@ -406,7 +407,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
|
||||
// ensure receipts match header.
|
||||
// TODO: optimize? these were just decoded.
|
||||
let found_root = ::triehash::ordered_trie_root(receipts.iter().map(::rlp::encode));
|
||||
let found_root = ::triehash::ordered_trie_root(receipts.iter().map(|r| r.encode()));
|
||||
if found_root != *old_header.receipts_root() {
|
||||
return Err(::error::BlockError::InvalidReceiptsRoot(Mismatch {
|
||||
expected: *old_header.receipts_root(),
|
||||
@@ -491,7 +492,7 @@ mod tests {
|
||||
use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data};
|
||||
use types::{
|
||||
ids::BlockId,
|
||||
transaction::{Action, Transaction},
|
||||
transaction::{Action, Transaction, TypedTransaction},
|
||||
};
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
@@ -537,7 +538,7 @@ mod tests {
|
||||
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
// Remove "1" validator.
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 500_000.into(),
|
||||
@@ -546,7 +547,7 @@ mod tests {
|
||||
data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1"
|
||||
.from_hex()
|
||||
.unwrap(),
|
||||
}
|
||||
})
|
||||
.sign(&s0, Some(chain_id));
|
||||
client
|
||||
.miner()
|
||||
@@ -555,7 +556,7 @@ mod tests {
|
||||
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
// Add "1" validator back in.
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 1.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 500_000.into(),
|
||||
@@ -564,7 +565,7 @@ mod tests {
|
||||
data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1"
|
||||
.from_hex()
|
||||
.unwrap(),
|
||||
}
|
||||
})
|
||||
.sign(&s0, Some(chain_id));
|
||||
client
|
||||
.miner()
|
||||
@@ -582,14 +583,14 @@ mod tests {
|
||||
// Switch back to the added validator, since the state is updated.
|
||||
let signer = Box::new((tap.clone(), v1, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 2.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 21000.into(),
|
||||
action: Action::Call(Address::default()),
|
||||
value: 0.into(),
|
||||
data: Vec::new(),
|
||||
}
|
||||
})
|
||||
.sign(&s0, Some(chain_id));
|
||||
client
|
||||
.miner()
|
||||
|
||||
@@ -28,7 +28,7 @@ use state::{Backend as StateBackend, CleanupMode, State, Substate};
|
||||
use std::{cmp, sync::Arc};
|
||||
use trace::{self, Tracer, VMTracer};
|
||||
use transaction_ext::Transaction;
|
||||
use types::transaction::{Action, SignedTransaction};
|
||||
use types::transaction::{Action, SignedTransaction, TypedTransaction};
|
||||
use vm::{
|
||||
self, AccessList, ActionParams, ActionValue, CleanDustMode, CreateContractAddress, EnvInfo,
|
||||
ResumeCall, ResumeCreate, ReturnData, Schedule, TrapError,
|
||||
@@ -1109,7 +1109,10 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
{
|
||||
let sender = t.sender();
|
||||
let balance = self.state.balance(&sender)?;
|
||||
let needed_balance = t.value.saturating_add(t.gas.saturating_mul(t.gas_price));
|
||||
let needed_balance = t
|
||||
.tx()
|
||||
.value
|
||||
.saturating_add(t.tx().gas.saturating_mul(t.tx().gas_price));
|
||||
if balance < needed_balance {
|
||||
// give the sender a sufficient balance
|
||||
self.state
|
||||
@@ -1132,16 +1135,51 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
T: Tracer,
|
||||
V: VMTracer,
|
||||
{
|
||||
let schedule = self.schedule;
|
||||
|
||||
// check if particualar transaction type is enabled at this block number in schedule
|
||||
match t.as_unsigned() {
|
||||
TypedTransaction::AccessList(_) => {
|
||||
if !schedule.eip2930 {
|
||||
return Err(ExecutionError::TransactionMalformed(
|
||||
"OptionalAccessList EIP-2930 or EIP-2929 not enabled".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
TypedTransaction::Legacy(_) => (), //legacy transactions are allways valid
|
||||
};
|
||||
|
||||
let sender = t.sender();
|
||||
let nonce = self.state.nonce(&sender)?;
|
||||
|
||||
let schedule = self.schedule;
|
||||
let base_gas_required = U256::from(t.gas_required(&schedule));
|
||||
let mut base_gas_required = U256::from(t.tx().gas_required(&schedule));
|
||||
|
||||
if t.gas < base_gas_required {
|
||||
let mut access_list = AccessList::new(schedule.eip2929);
|
||||
|
||||
if schedule.eip2929 {
|
||||
for (address, _) in self.machine.builtins() {
|
||||
access_list.insert_address(*address);
|
||||
}
|
||||
if schedule.eip2930 {
|
||||
// optional access list
|
||||
if let TypedTransaction::AccessList(al_tx) = t.as_unsigned() {
|
||||
for item in al_tx.access_list.iter() {
|
||||
access_list.insert_address(item.0);
|
||||
base_gas_required += vm::schedule::EIP2930_ACCESS_LIST_ADDRESS_COST.into();
|
||||
for key in item.1.iter() {
|
||||
access_list.insert_storage_key(item.0, *key);
|
||||
base_gas_required +=
|
||||
vm::schedule::EIP2930_ACCESS_LIST_STORAGE_KEY_COST.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if t.tx().gas < base_gas_required {
|
||||
return Err(ExecutionError::NotEnoughBaseGas {
|
||||
required: base_gas_required,
|
||||
got: t.gas,
|
||||
got: t.tx().gas,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1153,29 +1191,29 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
return Err(ExecutionError::SenderMustExist);
|
||||
}
|
||||
|
||||
let init_gas = t.gas - base_gas_required;
|
||||
let init_gas = t.tx().gas - base_gas_required;
|
||||
|
||||
// validate transaction nonce
|
||||
if check_nonce && t.nonce != nonce {
|
||||
if check_nonce && t.tx().nonce != nonce {
|
||||
return Err(ExecutionError::InvalidNonce {
|
||||
expected: nonce,
|
||||
got: t.nonce,
|
||||
got: t.tx().nonce,
|
||||
});
|
||||
}
|
||||
|
||||
// validate if transaction fits into given block
|
||||
if self.info.gas_used + t.gas > self.info.gas_limit {
|
||||
if self.info.gas_used + t.tx().gas > self.info.gas_limit {
|
||||
return Err(ExecutionError::BlockGasLimitReached {
|
||||
gas_limit: self.info.gas_limit,
|
||||
gas_used: self.info.gas_used,
|
||||
gas: t.gas,
|
||||
gas: t.tx().gas,
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: we might need bigints here, or at least check overflows.
|
||||
let balance = self.state.balance(&sender)?;
|
||||
let gas_cost = t.gas.full_mul(t.gas_price);
|
||||
let total_cost = U512::from(t.value) + gas_cost;
|
||||
let gas_cost = t.tx().gas.full_mul(t.tx().gas_price);
|
||||
let total_cost = U512::from(t.tx().value) + gas_cost;
|
||||
|
||||
// avoid unaffordable transactions
|
||||
let balance512 = U512::from(balance);
|
||||
@@ -1186,13 +1224,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
});
|
||||
}
|
||||
|
||||
let mut access_list = AccessList::new(schedule.eip2929);
|
||||
if schedule.eip2929 {
|
||||
for (address, _) in self.machine.builtins() {
|
||||
access_list.insert_address(*address);
|
||||
}
|
||||
}
|
||||
|
||||
let mut substate = Substate::from_access_list(&access_list);
|
||||
|
||||
// NOTE: there can be no invalid transactions from this point.
|
||||
@@ -1205,13 +1236,13 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
&mut substate.to_cleanup_mode(&schedule),
|
||||
)?;
|
||||
|
||||
let (result, output) = match t.action {
|
||||
let (result, output) = match t.tx().action {
|
||||
Action::Create => {
|
||||
let (new_address, code_hash) = contract_address(
|
||||
self.machine.create_address_scheme(self.info.number),
|
||||
&sender,
|
||||
&nonce,
|
||||
&t.data,
|
||||
&t.tx().data,
|
||||
);
|
||||
let params = ActionParams {
|
||||
code_address: new_address.clone(),
|
||||
@@ -1220,9 +1251,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
sender: sender.clone(),
|
||||
origin: sender.clone(),
|
||||
gas: init_gas,
|
||||
gas_price: t.gas_price,
|
||||
value: ActionValue::Transfer(t.value),
|
||||
code: Some(Arc::new(t.data.clone())),
|
||||
gas_price: t.tx().gas_price,
|
||||
value: ActionValue::Transfer(t.tx().value),
|
||||
code: Some(Arc::new(t.tx().data.clone())),
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: vm::ParamsType::Embedded,
|
||||
@@ -1242,11 +1273,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
sender: sender.clone(),
|
||||
origin: sender.clone(),
|
||||
gas: init_gas,
|
||||
gas_price: t.gas_price,
|
||||
value: ActionValue::Transfer(t.value),
|
||||
gas_price: t.tx().gas_price,
|
||||
value: ActionValue::Transfer(t.tx().value),
|
||||
code: self.state.code(address)?,
|
||||
code_hash: self.state.code_hash(address)?,
|
||||
data: Some(t.data.clone()),
|
||||
data: Some(t.tx().data.clone()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
access_list: access_list,
|
||||
@@ -1445,12 +1476,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
Ok(FinalizationResult { gas_left, .. }) => gas_left,
|
||||
_ => 0.into(),
|
||||
};
|
||||
let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) >> 1);
|
||||
let refunded = cmp::min(refunds_bound, (t.tx().gas - gas_left_prerefund) >> 1);
|
||||
let gas_left = gas_left_prerefund + refunded;
|
||||
|
||||
let gas_used = t.gas.saturating_sub(gas_left);
|
||||
let (refund_value, overflow_1) = gas_left.overflowing_mul(t.gas_price);
|
||||
let (fees_value, overflow_2) = gas_used.overflowing_mul(t.gas_price);
|
||||
let gas_used = t.tx().gas.saturating_sub(gas_left);
|
||||
let (refund_value, overflow_1) = gas_left.overflowing_mul(t.tx().gas_price);
|
||||
let (fees_value, overflow_2) = gas_used.overflowing_mul(t.tx().gas_price);
|
||||
if overflow_1 || overflow_2 {
|
||||
return Err(ExecutionError::TransactionMalformed(
|
||||
"U256 Overflow".to_string(),
|
||||
@@ -1458,7 +1489,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
}
|
||||
|
||||
trace!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n",
|
||||
t.gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value);
|
||||
t.tx().gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value);
|
||||
|
||||
let sender = t.sender();
|
||||
trace!(
|
||||
@@ -1487,7 +1518,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
|
||||
// perform garbage-collection
|
||||
let min_balance = if schedule.kill_dust != CleanDustMode::Off {
|
||||
Some(U256::from(schedule.tx_gas).overflowing_mul(t.gas_price).0)
|
||||
Some(
|
||||
U256::from(schedule.tx_gas)
|
||||
.overflowing_mul(t.tx().gas_price)
|
||||
.0,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -1502,10 +1537,10 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
Err(vm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)),
|
||||
Err(exception) => Ok(Executed {
|
||||
exception: Some(exception),
|
||||
gas: t.gas,
|
||||
gas_used: t.gas,
|
||||
gas: t.tx().gas,
|
||||
gas_used: t.tx().gas,
|
||||
refunded: U256::zero(),
|
||||
cumulative_gas_used: self.info.gas_used + t.gas,
|
||||
cumulative_gas_used: self.info.gas_used + t.tx().gas,
|
||||
logs: vec![],
|
||||
contracts_created: vec![],
|
||||
output: output,
|
||||
@@ -1519,7 +1554,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
} else {
|
||||
Some(vm::Error::Reverted)
|
||||
},
|
||||
gas: t.gas,
|
||||
gas: t.tx().gas,
|
||||
gas_used: gas_used,
|
||||
refunded: refunded,
|
||||
cumulative_gas_used: self.info.gas_used + gas_used,
|
||||
@@ -1551,7 +1586,7 @@ mod tests {
|
||||
trace, ExecutiveTracer, ExecutiveVMTracer, FlatTrace, MemoryDiff, NoopTracer, NoopVMTracer,
|
||||
StorageDiff, Tracer, VMExecutedOperation, VMOperation, VMTrace, VMTracer,
|
||||
};
|
||||
use types::transaction::{Action, Transaction};
|
||||
use types::transaction::{Action, Transaction, TypedTransaction};
|
||||
use vm::{ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo};
|
||||
|
||||
fn make_frontier_machine(max_depth: usize) -> EthereumMachine {
|
||||
@@ -2445,14 +2480,14 @@ mod tests {
|
||||
evm_test_ignore! {test_transact_simple: test_transact_simple_int}
|
||||
fn test_transact_simple(factory: Factory) {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(17),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::zero(),
|
||||
nonce: U256::zero(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
let sender = t.sender();
|
||||
let contract = contract_address(
|
||||
@@ -2496,14 +2531,14 @@ mod tests {
|
||||
evm_test! {test_transact_invalid_nonce: test_transact_invalid_nonce_int}
|
||||
fn test_transact_invalid_nonce(factory: Factory) {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(17),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::zero(),
|
||||
nonce: U256::one(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
let sender = t.sender();
|
||||
|
||||
@@ -2535,14 +2570,14 @@ mod tests {
|
||||
evm_test! {test_transact_gas_limit_reached: test_transact_gas_limit_reached_int}
|
||||
fn test_transact_gas_limit_reached(factory: Factory) {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(17),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(80_001),
|
||||
gas_price: U256::zero(),
|
||||
nonce: U256::zero(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
let sender = t.sender();
|
||||
|
||||
@@ -2580,14 +2615,14 @@ mod tests {
|
||||
evm_test! {test_not_enough_cash: test_not_enough_cash_int}
|
||||
fn test_not_enough_cash(factory: Factory) {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(18),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::one(),
|
||||
nonce: U256::zero(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
let sender = t.sender();
|
||||
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
use super::test_common::*;
|
||||
use client::EvmTestClient;
|
||||
use ethjson;
|
||||
use rlp::Rlp;
|
||||
use std::path::Path;
|
||||
use transaction_ext::Transaction;
|
||||
use types::{header::Header, transaction::UnverifiedTransaction};
|
||||
use types::{
|
||||
header::Header,
|
||||
transaction::{TypedTransaction, UnverifiedTransaction},
|
||||
};
|
||||
|
||||
pub fn json_transaction_test<H: FnMut(&str, HookType)>(
|
||||
path: &Path,
|
||||
@@ -65,8 +67,7 @@ pub fn json_transaction_test<H: FnMut(&str, HookType)>(
|
||||
};
|
||||
|
||||
let rlp: Vec<u8> = test.rlp.clone().into();
|
||||
let res = Rlp::new(&rlp)
|
||||
.as_val()
|
||||
let res = TypedTransaction::decode(&rlp)
|
||||
.map_err(::error::Error::from)
|
||||
.and_then(|t: UnverifiedTransaction| {
|
||||
let mut header: Header = Default::default();
|
||||
@@ -74,12 +75,13 @@ pub fn json_transaction_test<H: FnMut(&str, HookType)>(
|
||||
header.set_number(BLOCK_NUMBER);
|
||||
|
||||
let minimal = t
|
||||
.tx()
|
||||
.gas_required(&spec.engine.schedule(header.number()))
|
||||
.into();
|
||||
if t.gas < minimal {
|
||||
if t.tx().gas < minimal {
|
||||
return Err(::types::transaction::Error::InsufficientGas {
|
||||
minimal,
|
||||
got: t.gas,
|
||||
got: t.tx().gas,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ use std::{
|
||||
};
|
||||
|
||||
use ethereum_types::{Address, H256, U256};
|
||||
use rlp::Rlp;
|
||||
use types::{
|
||||
header::Header,
|
||||
transaction::{
|
||||
self, SignedTransaction, UnverifiedTransaction, SYSTEM_ADDRESS, UNSIGNED_SENDER,
|
||||
self, SignedTransaction, TypedTransaction, UnverifiedTransaction, SYSTEM_ADDRESS,
|
||||
UNSIGNED_SENDER,
|
||||
},
|
||||
BlockNumber,
|
||||
};
|
||||
@@ -455,17 +455,27 @@ impl EthereumMachine {
|
||||
pub fn decode_transaction(
|
||||
&self,
|
||||
transaction: &[u8],
|
||||
schedule: &Schedule,
|
||||
) -> Result<UnverifiedTransaction, transaction::Error> {
|
||||
let rlp = Rlp::new(&transaction);
|
||||
if rlp.as_raw().len() > self.params().max_transaction_size {
|
||||
if transaction.len() > self.params().max_transaction_size {
|
||||
debug!(
|
||||
"Rejected oversized transaction of {} bytes",
|
||||
rlp.as_raw().len()
|
||||
transaction.len()
|
||||
);
|
||||
return Err(transaction::Error::TooBig);
|
||||
}
|
||||
rlp.as_val()
|
||||
.map_err(|e| transaction::Error::InvalidRlp(e.to_string()))
|
||||
|
||||
let tx = TypedTransaction::decode(transaction)
|
||||
.map_err(|e| transaction::Error::InvalidRlp(e.to_string()))?;
|
||||
|
||||
match tx.tx_type() {
|
||||
transaction::TypedTxId::AccessList if schedule.eip2930 => {
|
||||
return Err(transaction::Error::TransactionTypeNotEnabled)
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
Ok(tx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +486,7 @@ pub struct AuxiliaryData<'a> {
|
||||
/// The full block bytes, including the header.
|
||||
pub bytes: Option<&'a [u8]>,
|
||||
/// The block receipts.
|
||||
pub receipts: Option<&'a [::types::receipt::Receipt]>,
|
||||
pub receipts: Option<&'a [::types::receipt::TypedReceipt]>,
|
||||
}
|
||||
|
||||
/// Type alias for a function we can make calls through synchronously.
|
||||
@@ -550,7 +560,7 @@ mod tests {
|
||||
fn should_disallow_unsigned_transactions() {
|
||||
let rlp = "ea80843b9aca0083015f90948921ebb5f79e9e3920abe571004d0b1d5119c154865af3107a400080038080";
|
||||
let transaction: UnverifiedTransaction =
|
||||
::rlp::decode(&::rustc_hex::FromHex::from_hex(rlp).unwrap()).unwrap();
|
||||
TypedTransaction::decode(&::rustc_hex::FromHex::from_hex(rlp).unwrap()).unwrap();
|
||||
let spec = ::ethereum::new_ropsten_test();
|
||||
let ethparams = get_default_ethash_extensions();
|
||||
|
||||
|
||||
@@ -1195,15 +1195,16 @@ impl miner::MinerService for Miner {
|
||||
let receipt = &receipts[index];
|
||||
RichReceipt {
|
||||
from: tx.sender(),
|
||||
to: match tx.action {
|
||||
to: match tx.tx().action {
|
||||
Action::Create => None,
|
||||
Action::Call(ref address) => Some(*address),
|
||||
},
|
||||
transaction_hash: tx.hash(),
|
||||
transaction_type: tx.tx_type(),
|
||||
transaction_index: index,
|
||||
cumulative_gas_used: receipt.gas_used,
|
||||
gas_used: receipt.gas_used - prev_gas,
|
||||
contract_address: match tx.action {
|
||||
contract_address: match tx.tx().action {
|
||||
Action::Call(_) => None,
|
||||
Action::Create => {
|
||||
let sender = tx.sender();
|
||||
@@ -1212,8 +1213,8 @@ impl miner::MinerService for Miner {
|
||||
self.engine
|
||||
.create_address_scheme(pending.header.number()),
|
||||
&sender,
|
||||
&tx.nonce,
|
||||
&tx.data,
|
||||
&tx.tx().nonce,
|
||||
&tx.tx().data,
|
||||
)
|
||||
.0,
|
||||
)
|
||||
@@ -1509,7 +1510,7 @@ mod tests {
|
||||
use client::{ChainInfo, EachBlockWith, ImportSealedBlock, TestBlockChainClient};
|
||||
use miner::{MinerService, PendingOrdering};
|
||||
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec};
|
||||
use types::transaction::Transaction;
|
||||
use types::transaction::{Transaction, TypedTransaction};
|
||||
|
||||
#[test]
|
||||
fn should_prepare_block_to_seal() {
|
||||
@@ -1583,14 +1584,14 @@ mod tests {
|
||||
|
||||
fn transaction_with_chain_id(chain_id: u64) -> SignedTransaction {
|
||||
let keypair = Random.generate().unwrap();
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::zero(),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::zero(),
|
||||
nonce: U256::zero(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), Some(chain_id))
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,8 @@ where
|
||||
&self,
|
||||
transaction: &[u8],
|
||||
) -> Result<UnverifiedTransaction, transaction::Error> {
|
||||
self.engine.decode_transaction(transaction)
|
||||
let number = self.chain.best_block_header().number();
|
||||
self.engine.decode_transaction(transaction, number)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use ethereum_types::H256;
|
||||
use hash::keccak;
|
||||
use rlp::{DecoderError, Rlp, RlpStream};
|
||||
use triehash::ordered_trie_root;
|
||||
use types::{block::Block, header::Header, views::BlockView};
|
||||
use types::{block::Block, header::Header, transaction::TypedTransaction, views::BlockView};
|
||||
|
||||
const HEADER_FIELDS: usize = 8;
|
||||
const BLOCK_FIELDS: usize = 2;
|
||||
@@ -62,9 +62,9 @@ impl AbridgedBlock {
|
||||
.append(&header.extra_data());
|
||||
|
||||
// write block values.
|
||||
stream
|
||||
.append_list(&block_view.transactions())
|
||||
.append_list(&block_view.uncles());
|
||||
|
||||
TypedTransaction::rlp_append_list(&mut stream, &block_view.transactions());
|
||||
stream.append_list(&block_view.uncles());
|
||||
|
||||
// write seal fields.
|
||||
for field in seal_fields {
|
||||
@@ -97,10 +97,17 @@ impl AbridgedBlock {
|
||||
header.set_timestamp(rlp.val_at(6)?);
|
||||
header.set_extra_data(rlp.val_at(7)?);
|
||||
|
||||
let transactions = rlp.list_at(8)?;
|
||||
let transactions = TypedTransaction::decode_rlp_list(&rlp.at(8)?)?;
|
||||
let uncles: Vec<Header> = rlp.list_at(9)?;
|
||||
|
||||
header.set_transactions_root(ordered_trie_root(rlp.at(8)?.iter().map(|r| r.as_raw())));
|
||||
header.set_transactions_root(ordered_trie_root(rlp.at(8)?.iter().map(|r| {
|
||||
if r.is_list() {
|
||||
r.as_raw()
|
||||
} else {
|
||||
// We already checked if list is valid with decode_rlp_list above
|
||||
r.data().expect("To raw rlp list to be valid")
|
||||
}
|
||||
})));
|
||||
header.set_receipts_root(receipts_root);
|
||||
|
||||
let mut uncles_rlp = RlpStream::new();
|
||||
@@ -131,7 +138,7 @@ mod tests {
|
||||
use ethereum_types::{Address, H256, U256};
|
||||
use types::{
|
||||
block::Block,
|
||||
transaction::{Action, Transaction},
|
||||
transaction::{Action, Transaction, TypedTransaction},
|
||||
view,
|
||||
views::BlockView,
|
||||
};
|
||||
@@ -165,24 +172,24 @@ mod tests {
|
||||
fn with_transactions() {
|
||||
let mut b = Block::default();
|
||||
|
||||
let t1 = Transaction {
|
||||
let t1 = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
nonce: U256::from(42),
|
||||
gas_price: U256::from(3000),
|
||||
gas: U256::from(50_000),
|
||||
value: U256::from(1),
|
||||
data: b"Hello!".to_vec(),
|
||||
}
|
||||
})
|
||||
.fake_sign(Address::from(0x69));
|
||||
|
||||
let t2 = Transaction {
|
||||
let t2 = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
nonce: U256::from(88),
|
||||
gas_price: U256::from(12345),
|
||||
gas: U256::from(300000),
|
||||
value: U256::from(1000000000),
|
||||
data: "Eep!".into(),
|
||||
}
|
||||
})
|
||||
.fake_sign(Address::from(0x55));
|
||||
|
||||
b.transactions.push(t1.into());
|
||||
@@ -191,7 +198,7 @@ mod tests {
|
||||
let receipts_root = b.header.receipts_root().clone();
|
||||
b.header
|
||||
.set_transactions_root(::triehash::ordered_trie_root(
|
||||
b.transactions.iter().map(::rlp::encode),
|
||||
b.transactions.iter().map(|tx| tx.encode()),
|
||||
));
|
||||
|
||||
let encoded = encode_block(&b);
|
||||
|
||||
@@ -36,7 +36,9 @@ use ethereum_types::{H256, U256};
|
||||
use itertools::{Itertools, Position};
|
||||
use kvdb::KeyValueDB;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use types::{encoded, header::Header, ids::BlockId, receipt::Receipt};
|
||||
use types::{
|
||||
encoded, header::Header, ids::BlockId, receipt::TypedReceipt, transaction::TypedTransaction,
|
||||
};
|
||||
|
||||
/// Snapshot creation and restoration for PoA chains.
|
||||
/// Chunk format:
|
||||
@@ -114,9 +116,9 @@ impl SnapshotComponents for PoaSnapshot {
|
||||
|
||||
rlps.push({
|
||||
let mut stream = RlpStream::new_list(5);
|
||||
stream.append(&block.header);
|
||||
TypedTransaction::rlp_append_list(&mut stream, &block.transactions);
|
||||
stream
|
||||
.append(&block.header)
|
||||
.append_list(&block.transactions)
|
||||
.append_list(&block.uncles)
|
||||
.append(&receipts)
|
||||
.append(&parent_td);
|
||||
@@ -349,11 +351,11 @@ impl Rebuilder for ChunkRebuilder {
|
||||
let last_rlp = rlp.at(num_items - 1)?;
|
||||
let block = Block {
|
||||
header: last_rlp.val_at(0)?,
|
||||
transactions: last_rlp.list_at(1)?,
|
||||
transactions: TypedTransaction::decode_rlp_list(&last_rlp.at(1)?)?,
|
||||
uncles: last_rlp.list_at(2)?,
|
||||
};
|
||||
let block_data = block.rlp_bytes();
|
||||
let receipts: Vec<Receipt> = last_rlp.list_at(3)?;
|
||||
let receipts = TypedReceipt::decode_rlp_list(&last_rlp.at(3)?)?;
|
||||
|
||||
{
|
||||
let hash = block.header.hash();
|
||||
|
||||
@@ -291,8 +291,15 @@ impl Rebuilder for PowRebuilder {
|
||||
let pair = rlp.at(idx)?;
|
||||
let abridged_rlp = pair.at(0)?.as_raw().to_owned();
|
||||
let abridged_block = AbridgedBlock::from_raw(abridged_rlp);
|
||||
let receipts: Vec<::types::receipt::Receipt> = pair.list_at(1)?;
|
||||
let receipts_root = ordered_trie_root(pair.at(1)?.iter().map(|r| r.as_raw()));
|
||||
let receipts = ::types::receipt::TypedReceipt::decode_rlp_list(&pair.at(1)?)?;
|
||||
let receipts_root = ordered_trie_root(pair.at(1)?.iter().map(|r| {
|
||||
if r.is_list() {
|
||||
r.as_raw()
|
||||
} else {
|
||||
// We have allready checked validity by decoding rlp list in line above
|
||||
r.data().expect("Expect for raw receipts list to be valid.")
|
||||
}
|
||||
}));
|
||||
|
||||
let block = abridged_block.to_block(parent_hash, cur_number, receipts_root)?;
|
||||
let block_bytes = encoded::Block::new(block.rlp_bytes());
|
||||
|
||||
@@ -25,7 +25,7 @@ use snapshot::tests::helpers as snapshot_helpers;
|
||||
use spec::Spec;
|
||||
use tempdir::TempDir;
|
||||
use test_helpers::generate_dummy_client_with_spec;
|
||||
use types::transaction::{Action, SignedTransaction, Transaction};
|
||||
use types::transaction::{Action, SignedTransaction, Transaction, TypedTransaction};
|
||||
|
||||
use ethereum_types::Address;
|
||||
use test_helpers;
|
||||
@@ -128,14 +128,14 @@ fn make_chain(
|
||||
// and force sealing.
|
||||
let make_useless_transactions = || {
|
||||
let mut nonce = nonce.borrow_mut();
|
||||
let transaction = Transaction {
|
||||
let transaction = TypedTransaction::Legacy(Transaction {
|
||||
nonce: *nonce,
|
||||
gas_price: 1.into(),
|
||||
gas: 21_000.into(),
|
||||
action: Action::Call(Address::new()),
|
||||
value: 1.into(),
|
||||
data: Vec::new(),
|
||||
}
|
||||
})
|
||||
.sign(&*RICH_SECRET, client.signing_chain_id());
|
||||
|
||||
*nonce = *nonce + 1;
|
||||
@@ -171,14 +171,14 @@ fn make_chain(
|
||||
let data =
|
||||
test_validator_set::functions::set_validators::encode_input(new_set.clone());
|
||||
let mut nonce = nonce.borrow_mut();
|
||||
let transaction = Transaction {
|
||||
let transaction = TypedTransaction::Legacy(Transaction {
|
||||
nonce: *nonce,
|
||||
gas_price: 0.into(),
|
||||
gas: 1_000_000.into(),
|
||||
action: Action::Call(*address),
|
||||
value: 0.into(),
|
||||
data,
|
||||
}
|
||||
})
|
||||
.sign(&*RICH_SECRET, client.signing_chain_id());
|
||||
|
||||
*nonce = *nonce + 1;
|
||||
|
||||
@@ -301,7 +301,7 @@ fn recover_aborted_recovery() {
|
||||
generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, 5, &gas_prices);
|
||||
|
||||
let spec = Spec::new_null();
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let tempdir = TempDir::new("oe_snapshot").unwrap();
|
||||
let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
|
||||
let client_db = new_db();
|
||||
let client2 = Client::new(
|
||||
|
||||
@@ -137,6 +137,8 @@ pub struct CommonParams {
|
||||
pub eip2315_transition: BlockNumber,
|
||||
/// Number of first block where EIP-2929 rules begin.
|
||||
pub eip2929_transition: BlockNumber,
|
||||
/// Number of first block where EIP-2930 rules begin.
|
||||
pub eip2930_transition: BlockNumber,
|
||||
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||
pub dust_protection_transition: BlockNumber,
|
||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
||||
@@ -212,6 +214,7 @@ impl CommonParams {
|
||||
schedule.eip1706 = block_number >= self.eip1706_transition;
|
||||
schedule.have_subs = block_number >= self.eip2315_transition;
|
||||
schedule.eip2929 = block_number >= self.eip2929_transition;
|
||||
schedule.eip2930 = block_number >= self.eip2930_transition;
|
||||
|
||||
if block_number >= self.eip1884_transition {
|
||||
schedule.have_selfbalance = true;
|
||||
@@ -370,6 +373,9 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
eip2929_transition: p
|
||||
.eip2929_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip2930_transition: p
|
||||
.eip2930_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
dust_protection_transition: p
|
||||
.dust_protection_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
@@ -956,7 +962,7 @@ impl Spec {
|
||||
/// initialize genesis epoch data, using in-memory database for
|
||||
/// constructor.
|
||||
pub fn genesis_epoch_data(&self) -> Result<Vec<u8>, String> {
|
||||
use types::transaction::{Action, Transaction};
|
||||
use types::transaction::{Action, Transaction, TypedTransaction};
|
||||
|
||||
let genesis = self.genesis_header();
|
||||
|
||||
@@ -983,14 +989,14 @@ impl Spec {
|
||||
};
|
||||
|
||||
let from = Address::default();
|
||||
let tx = Transaction {
|
||||
let tx = TypedTransaction::Legacy(Transaction {
|
||||
nonce: self.engine.account_start_nonce(0),
|
||||
action: Action::Call(a),
|
||||
gas: U256::max_value(),
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data: d,
|
||||
}
|
||||
})
|
||||
.fake_sign(from);
|
||||
|
||||
let res = ::state::prove_transaction_virtual(
|
||||
|
||||
@@ -38,10 +38,11 @@ use state_db::StateDB;
|
||||
use trace::{self, FlatTrace, VMTrace};
|
||||
use types::{
|
||||
basic_account::BasicAccount,
|
||||
receipt::{Receipt, TransactionOutcome},
|
||||
receipt::{LegacyReceipt, TransactionOutcome, TypedReceipt},
|
||||
state_diff::StateDiff,
|
||||
transaction::SignedTransaction,
|
||||
};
|
||||
|
||||
use vm::EnvInfo;
|
||||
|
||||
use bytes::Bytes;
|
||||
@@ -63,7 +64,7 @@ pub use self::{account::Account, backend::Backend, substate::Substate};
|
||||
/// Used to return information about an `State::apply` operation.
|
||||
pub struct ApplyOutcome<T, V> {
|
||||
/// The receipt for the applied transaction.
|
||||
pub receipt: Receipt,
|
||||
pub receipt: TypedReceipt,
|
||||
/// The output of the applied transaction.
|
||||
pub output: Bytes,
|
||||
/// The trace for the applied transaction, empty if tracing was not produced.
|
||||
@@ -955,7 +956,10 @@ impl<B: Backend> State<B> {
|
||||
};
|
||||
|
||||
let output = e.output;
|
||||
let receipt = Receipt::new(outcome, e.cumulative_gas_used, e.logs);
|
||||
let receipt = TypedReceipt::new(
|
||||
t.tx_type(),
|
||||
LegacyReceipt::new(outcome, e.cumulative_gas_used, e.logs),
|
||||
);
|
||||
trace!(target: "state", "Transaction receipt: {:?}", receipt);
|
||||
|
||||
Ok(ApplyOutcome {
|
||||
@@ -1602,7 +1606,7 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
@@ -1610,7 +1614,7 @@ mod tests {
|
||||
value: 100.into(),
|
||||
data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555")
|
||||
.unwrap(),
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -1667,14 +1671,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Create,
|
||||
value: 100.into(),
|
||||
data: FromHex::from_hex("5b600056").unwrap(),
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -1706,14 +1710,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -1753,14 +1757,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -1797,14 +1801,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = Spec::new_test_machine();
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0x1.into()),
|
||||
value: 0.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
let result = state.apply(&info, &machine, &t, true).unwrap();
|
||||
@@ -1839,14 +1843,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = Spec::new_test_machine();
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 0.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -1887,14 +1891,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = Spec::new_test_machine();
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 0.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -1957,14 +1961,14 @@ mod tests {
|
||||
info.number = 0x789b0;
|
||||
let machine = Spec::new_test_machine();
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 0.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2029,14 +2033,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2073,14 +2077,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2145,14 +2149,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2210,14 +2214,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2260,14 +2264,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![], //600480600b6000396000f35b600056
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2328,14 +2332,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2421,14 +2425,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![], //600480600b6000396000f35b600056
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
@@ -2512,14 +2516,14 @@ mod tests {
|
||||
info.gas_limit = 1_000_000.into();
|
||||
let machine = make_frontier_machine(5);
|
||||
|
||||
let t = Transaction {
|
||||
let t = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 100_000.into(),
|
||||
action: Action::Call(0xa.into()),
|
||||
value: 100.into(),
|
||||
data: vec![],
|
||||
}
|
||||
})
|
||||
.sign(&secret(), None);
|
||||
|
||||
state
|
||||
|
||||
@@ -36,7 +36,7 @@ use tempdir::TempDir;
|
||||
use types::{
|
||||
encoded,
|
||||
header::Header,
|
||||
transaction::{Action, SignedTransaction, Transaction},
|
||||
transaction::{Action, SignedTransaction, Transaction, TypedTransaction},
|
||||
view,
|
||||
views::BlockView,
|
||||
};
|
||||
@@ -104,7 +104,7 @@ pub fn create_test_block_with_data(
|
||||
rlp.append(header);
|
||||
rlp.begin_list(transactions.len());
|
||||
for t in transactions {
|
||||
rlp.append_raw(&rlp::encode(t), 1);
|
||||
t.rlp_append(&mut rlp);
|
||||
}
|
||||
rlp.append_list(&uncles);
|
||||
rlp.out()
|
||||
@@ -197,14 +197,14 @@ where
|
||||
// first block we don't have any balance, so can't send any transactions.
|
||||
for _ in 0..txs_per_block {
|
||||
b.push_transaction(
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
nonce: n.into(),
|
||||
gas_price: tx_gas_prices[n % tx_gas_prices.len()],
|
||||
gas: 100000.into(),
|
||||
action: Action::Create,
|
||||
data: vec![],
|
||||
value: U256::zero(),
|
||||
}
|
||||
})
|
||||
.sign(kp.secret(), Some(test_spec.chain_id())),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -45,7 +45,7 @@ use types::{
|
||||
data_format::DataFormat,
|
||||
filter::Filter,
|
||||
ids::BlockId,
|
||||
transaction::{Action, Condition, PendingTransaction, Transaction},
|
||||
transaction::{Action, Condition, PendingTransaction, Transaction, TypedTransaction},
|
||||
view,
|
||||
views::BlockView,
|
||||
};
|
||||
@@ -362,26 +362,26 @@ fn does_not_propagate_delayed_transactions() {
|
||||
let key = KeyPair::from_secret(keccak("test").into()).unwrap();
|
||||
let secret = key.secret();
|
||||
let tx0 = PendingTransaction::new(
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 21000.into(),
|
||||
action: Action::Call(Address::default()),
|
||||
value: 0.into(),
|
||||
data: Vec::new(),
|
||||
}
|
||||
})
|
||||
.sign(secret, None),
|
||||
Some(Condition::Number(2)),
|
||||
);
|
||||
let tx1 = PendingTransaction::new(
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
nonce: 1.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 21000.into(),
|
||||
action: Action::Call(Address::default()),
|
||||
value: 0.into(),
|
||||
data: Vec::new(),
|
||||
}
|
||||
})
|
||||
.sign(secret, None),
|
||||
None,
|
||||
);
|
||||
@@ -443,14 +443,14 @@ fn transaction_proof() {
|
||||
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
||||
}
|
||||
|
||||
let transaction = Transaction {
|
||||
let transaction = TypedTransaction::Legacy(Transaction {
|
||||
nonce: 0.into(),
|
||||
gas_price: 0.into(),
|
||||
gas: 21000.into(),
|
||||
action: Action::Call(Address::default()),
|
||||
value: 5.into(),
|
||||
data: Vec::new(),
|
||||
}
|
||||
})
|
||||
.fake_sign(address);
|
||||
|
||||
let proof = client
|
||||
|
||||
@@ -29,7 +29,7 @@ use test_helpers::{self, get_temp_state_db};
|
||||
use trace::{trace::Action::Reward, LocalizedTrace, RewardType};
|
||||
use types::{
|
||||
header::Header,
|
||||
transaction::{Action, Transaction},
|
||||
transaction::{Action, Transaction, TypedTransaction},
|
||||
view,
|
||||
views::BlockView,
|
||||
};
|
||||
@@ -171,14 +171,14 @@ fn can_trace_block_and_uncle_reward() {
|
||||
for _ in 0..1 {
|
||||
block
|
||||
.push_transaction(
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
nonce: n.into(),
|
||||
gas_price: 10000.into(),
|
||||
gas: 100000.into(),
|
||||
action: Action::Create,
|
||||
data: vec![],
|
||||
value: U256::zero(),
|
||||
}
|
||||
})
|
||||
.sign(kp.secret(), Some(spec.network_id())),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -83,7 +83,7 @@ impl TransactionFilter {
|
||||
let mut permission_cache = self.permission_cache.lock();
|
||||
let mut contract_version_cache = self.contract_version_cache.lock();
|
||||
|
||||
let (tx_type, to) = match transaction.action {
|
||||
let (tx_type, to) = match transaction.tx().action {
|
||||
Action::Create => (tx_permissions::CREATE, Address::new()),
|
||||
Action::Call(address) => {
|
||||
if client
|
||||
@@ -98,7 +98,7 @@ impl TransactionFilter {
|
||||
};
|
||||
|
||||
let sender = transaction.sender();
|
||||
let value = transaction.value;
|
||||
let value = transaction.tx().value;
|
||||
let key = (*parent_hash, sender);
|
||||
|
||||
if let Some(permissions) = permission_cache.get_mut(&key) {
|
||||
@@ -181,7 +181,7 @@ mod test {
|
||||
use std::sync::Arc;
|
||||
use tempdir::TempDir;
|
||||
use test_helpers;
|
||||
use types::transaction::{Action, Transaction};
|
||||
use types::transaction::{Action, Transaction, TypedTransaction};
|
||||
|
||||
/// Contract code: https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f
|
||||
#[test]
|
||||
@@ -230,28 +230,30 @@ mod test {
|
||||
.unwrap();
|
||||
|
||||
let filter = TransactionFilter::from_params(spec.params()).unwrap();
|
||||
let mut basic_tx = Transaction::default();
|
||||
basic_tx.action = Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb"));
|
||||
let create_tx = Transaction::default();
|
||||
let mut call_tx = Transaction::default();
|
||||
call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005"));
|
||||
|
||||
let mut basic_tx_with_ether_and_to_key7 = Transaction::default();
|
||||
basic_tx_with_ether_and_to_key7.action =
|
||||
let mut basic_tx = TypedTransaction::Legacy(Transaction::default());
|
||||
basic_tx.tx_mut().action =
|
||||
Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb"));
|
||||
basic_tx_with_ether_and_to_key7.value = U256::from(123123);
|
||||
let mut call_tx_with_ether = Transaction::default();
|
||||
call_tx_with_ether.action =
|
||||
let create_tx = TypedTransaction::Legacy(Transaction::default());
|
||||
let mut call_tx = TypedTransaction::Legacy(Transaction::default());
|
||||
call_tx.tx_mut().action =
|
||||
Action::Call(Address::from("0000000000000000000000000000000000000005"));
|
||||
call_tx_with_ether.value = U256::from(123123);
|
||||
|
||||
let mut basic_tx_to_key6 = Transaction::default();
|
||||
basic_tx_to_key6.action =
|
||||
let mut basic_tx_with_ether_and_to_key7 = TypedTransaction::Legacy(Transaction::default());
|
||||
basic_tx_with_ether_and_to_key7.tx_mut().action =
|
||||
Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb"));
|
||||
basic_tx_with_ether_and_to_key7.tx_mut().value = U256::from(123123);
|
||||
let mut call_tx_with_ether = TypedTransaction::Legacy(Transaction::default());
|
||||
call_tx_with_ether.tx_mut().action =
|
||||
Action::Call(Address::from("0000000000000000000000000000000000000005"));
|
||||
call_tx_with_ether.tx_mut().value = U256::from(123123);
|
||||
|
||||
let mut basic_tx_to_key6 = TypedTransaction::Legacy(Transaction::default());
|
||||
basic_tx_to_key6.tx_mut().action =
|
||||
Action::Call(Address::from("e57bfe9f44b819898f47bf37e5af72a0783e1141"));
|
||||
let mut basic_tx_with_ether_and_to_key6 = Transaction::default();
|
||||
basic_tx_with_ether_and_to_key6.action =
|
||||
let mut basic_tx_with_ether_and_to_key6 = TypedTransaction::Legacy(Transaction::default());
|
||||
basic_tx_with_ether_and_to_key6.tx_mut().action =
|
||||
Action::Call(Address::from("e57bfe9f44b819898f47bf37e5af72a0783e1141"));
|
||||
basic_tx_with_ether_and_to_key6.value = U256::from(123123);
|
||||
basic_tx_with_ether_and_to_key6.tx_mut().value = U256::from(123123);
|
||||
|
||||
let genesis = client.block_hash(BlockId::Latest).unwrap();
|
||||
let block_number = 1;
|
||||
@@ -444,11 +446,13 @@ mod test {
|
||||
.unwrap();
|
||||
|
||||
let filter = TransactionFilter::from_params(spec.params()).unwrap();
|
||||
let mut basic_tx = Transaction::default();
|
||||
basic_tx.action = Action::Call(Address::from("000000000000000000000000000000000000032"));
|
||||
let create_tx = Transaction::default();
|
||||
let mut call_tx = Transaction::default();
|
||||
call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005"));
|
||||
let mut basic_tx = TypedTransaction::Legacy(Transaction::default());
|
||||
basic_tx.tx_mut().action =
|
||||
Action::Call(Address::from("000000000000000000000000000000000000032"));
|
||||
let create_tx = TypedTransaction::Legacy(Transaction::default());
|
||||
let mut call_tx = TypedTransaction::Legacy(Transaction::default());
|
||||
call_tx.tx_mut().action =
|
||||
Action::Call(Address::from("0000000000000000000000000000000000000005"));
|
||||
|
||||
let genesis = client.block_hash(BlockId::Latest).unwrap();
|
||||
let block_number = 1;
|
||||
|
||||
@@ -80,7 +80,10 @@ pub mod blocks {
|
||||
|
||||
use engines::EthEngine;
|
||||
use error::{BlockError, Error, ErrorKind};
|
||||
use types::{header::Header, transaction::UnverifiedTransaction};
|
||||
use types::{
|
||||
header::Header,
|
||||
transaction::{TypedTransaction, UnverifiedTransaction},
|
||||
};
|
||||
use verification::{verify_block_basic, verify_block_unordered, PreverifiedBlock};
|
||||
|
||||
use bytes::Bytes;
|
||||
@@ -151,7 +154,7 @@ pub mod blocks {
|
||||
let (header, transactions, uncles) = {
|
||||
let rlp = Rlp::new(&bytes);
|
||||
let header = rlp.val_at(0)?;
|
||||
let transactions = rlp.list_at(1)?;
|
||||
let transactions = TypedTransaction::decode_rlp_list(&rlp.at(1)?)?;
|
||||
let uncles = rlp.list_at(2)?;
|
||||
(header, transactions, uncles)
|
||||
};
|
||||
|
||||
@@ -133,7 +133,7 @@ pub fn verify_block_unordered(
|
||||
let t = engine.verify_transaction_unordered(t, &header)?;
|
||||
// t_nb 5.3.2 check if nonce is more then max nonce (EIP-168 and EIP169)
|
||||
if let Some(max_nonce) = nonce_cap {
|
||||
if t.nonce >= max_nonce {
|
||||
if t.tx().nonce >= max_nonce {
|
||||
return Err(BlockError::TooManyTransactions(t.sender()).into());
|
||||
}
|
||||
}
|
||||
@@ -493,7 +493,16 @@ fn verify_parent(header: &Header, parent: &Header, engine: &dyn EthEngine) -> Re
|
||||
fn verify_block_integrity(block: &Unverified) -> Result<(), Error> {
|
||||
let block_rlp = Rlp::new(&block.bytes);
|
||||
let tx = block_rlp.at(1)?;
|
||||
let expected_root = ordered_trie_root(tx.iter().map(|r| r.as_raw()));
|
||||
let expected_root = ordered_trie_root(tx.iter().map(|r| {
|
||||
if r.is_list() {
|
||||
r.as_raw()
|
||||
} else {
|
||||
// This is already checked in Unverified structure and that is why we are okay to asume that data is valid.
|
||||
r.data().expect(
|
||||
"Unverified block should already check if raw list of transactions is valid",
|
||||
)
|
||||
}
|
||||
}));
|
||||
if &expected_root != block.header.transactions_root() {
|
||||
bail!(BlockError::InvalidTransactionsRoot(Mismatch {
|
||||
expected: expected_root,
|
||||
@@ -531,7 +540,7 @@ mod tests {
|
||||
use types::{
|
||||
encoded,
|
||||
log_entry::{LocalizedLogEntry, LogEntry},
|
||||
transaction::{Action, SignedTransaction, Transaction, UnverifiedTransaction},
|
||||
transaction::{Action, SignedTransaction, Transaction, TypedTransaction},
|
||||
};
|
||||
|
||||
fn check_ok(result: Result<(), Error>) {
|
||||
@@ -764,34 +773,34 @@ mod tests {
|
||||
|
||||
let keypair = Random.generate().unwrap();
|
||||
|
||||
let tr1 = Transaction {
|
||||
let tr1 = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(0),
|
||||
data: Bytes::new(),
|
||||
gas: U256::from(30_000),
|
||||
gas_price: U256::from(40_000),
|
||||
nonce: U256::one(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
|
||||
let tr2 = Transaction {
|
||||
let tr2 = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(0),
|
||||
data: Bytes::new(),
|
||||
gas: U256::from(30_000),
|
||||
gas_price: U256::from(40_000),
|
||||
nonce: U256::from(2),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None);
|
||||
|
||||
let tr3 = Transaction {
|
||||
let tr3 = TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Call(0x0.into()),
|
||||
value: U256::from(0),
|
||||
data: Bytes::new(),
|
||||
gas: U256::from(30_000),
|
||||
gas_price: U256::from(0),
|
||||
nonce: U256::zero(),
|
||||
}
|
||||
})
|
||||
.null_sign(0);
|
||||
|
||||
let good_transactions = [tr1.clone(), tr2.clone()];
|
||||
@@ -834,16 +843,10 @@ mod tests {
|
||||
let mut uncles_rlp = RlpStream::new();
|
||||
uncles_rlp.append_list(&good_uncles);
|
||||
let good_uncles_hash = keccak(uncles_rlp.as_raw());
|
||||
let good_transactions_root = ordered_trie_root(
|
||||
good_transactions
|
||||
.iter()
|
||||
.map(|t| ::rlp::encode::<UnverifiedTransaction>(t)),
|
||||
);
|
||||
let eip86_transactions_root = ordered_trie_root(
|
||||
eip86_transactions
|
||||
.iter()
|
||||
.map(|t| ::rlp::encode::<UnverifiedTransaction>(t)),
|
||||
);
|
||||
let good_transactions_root =
|
||||
ordered_trie_root(good_transactions.iter().map(|t| t.encode()));
|
||||
let eip86_transactions_root =
|
||||
ordered_trie_root(eip86_transactions.iter().map(|t| t.encode()));
|
||||
|
||||
let mut parent = good.clone();
|
||||
parent.set_number(9);
|
||||
@@ -1114,14 +1117,14 @@ mod tests {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let bad_transactions: Vec<_> = (0..3)
|
||||
.map(|i| {
|
||||
Transaction {
|
||||
TypedTransaction::Legacy(Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::zero(),
|
||||
data: Vec::new(),
|
||||
gas: 0.into(),
|
||||
gas_price: U256::zero(),
|
||||
nonce: i.into(),
|
||||
}
|
||||
})
|
||||
.sign(keypair.secret(), None)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Reference in New Issue
Block a user