Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 195dbeb

Browse files
committed
Additional validity requirements
1 parent d82afbe commit 195dbeb

File tree

4 files changed

+32
-24
lines changed

4 files changed

+32
-24
lines changed

ethcore/res/ethereum/tests

Submodule tests updated 5857 files

ethcore/src/evm/schedule.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ impl Schedule {
165165
}
166166
}
167167

168+
/// Schedule for the Metropolis of the Ethereum main net.
169+
pub fn new_metropolis() -> Schedule {
170+
Self::new_post_eip150(24576, true, true, true, true)
171+
}
172+
168173
fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
169174
Schedule {
170175
exceptional_failed_code_deposit: efcd,

ethcore/src/json_tests/transaction.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,37 @@ use super::test_common::*;
1818
use evm;
1919
use ethjson;
2020
use rlp::UntrustedRlp;
21-
use transaction::{Action, UnverifiedTransaction};
22-
use ethstore::ethkey::public_to_address;
21+
use transaction::{Action, UnverifiedTransaction, SignedTransaction};
2322

2423
fn do_json_test(json_data: &[u8]) -> Vec<String> {
2524
let tests = ethjson::transaction::Test::load(json_data).unwrap();
2625
let mut failed = Vec::new();
27-
let old_schedule = evm::Schedule::new_frontier();
28-
let new_schedule = evm::Schedule::new_homestead();
26+
let frontier_schedule = evm::Schedule::new_frontier();
27+
let homestead_schedule = evm::Schedule::new_homestead();
28+
let metropolis_schedule = evm::Schedule::new_metropolis();
2929
for (name, test) in tests.into_iter() {
3030
let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); };
3131

3232
let number: Option<u64> = test.block_number.map(Into::into);
3333
let schedule = match number {
34-
None => &old_schedule,
35-
Some(x) if x < 1_150_000 => &old_schedule,
36-
Some(_) => &new_schedule
34+
None => &frontier_schedule,
35+
Some(x) if x < 1_150_000 => &frontier_schedule,
36+
Some(x) if x < 3_000_000 => &homestead_schedule,
37+
Some(_) => &metropolis_schedule
3738
};
3839
let allow_network_id_of_one = number.map_or(false, |n| n >= 2_675_000);
40+
let allow_unsigned = number.map_or(false, |n| n >= 3_000_000);
3941

4042
let rlp: Vec<u8> = test.rlp.into();
4143
let res = UntrustedRlp::new(&rlp)
4244
.as_val()
4345
.map_err(From::from)
44-
.and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one));
46+
.and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one, allow_unsigned));
4547

4648
fail_unless(test.transaction.is_none() == res.is_err(), "Validity different");
4749
if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
4850
let t = res.unwrap();
49-
fail_unless(public_to_address(&t.recover_public().unwrap()) == sender.into(), "sender mismatch");
51+
fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch");
5052
let is_acceptable_network_id = match t.network_id() {
5153
None => true,
5254
Some(1) if allow_network_id_of_one => true,
@@ -84,3 +86,7 @@ declare_test!{TransactionTests_Homestead_ttTransactionTestEip155VitaliksTests, "
8486
declare_test!{TransactionTests_EIP155_ttTransactionTest, "TransactionTests/EIP155/ttTransactionTest"}
8587
declare_test!{TransactionTests_EIP155_ttTransactionTestEip155VitaliksTests, "TransactionTests/EIP155/ttTransactionTestEip155VitaliksTests"}
8688
declare_test!{TransactionTests_EIP155_ttTransactionTestVRule, "TransactionTests/EIP155/ttTransactionTestVRule"}
89+
90+
declare_test!{TransactionTests_Metropolis_ttMetropolisTest, "TransactionTests/Metropolis/ttMetropolisTest"}
91+
declare_test!{TransactionTests_Metropolis_ttTransactionTest, "TransactionTests/Metropolis/ttTransactionTest"}
92+
declare_test!{TransactionTests_Metropolis_ttTransactionTestZeroSig, "TransactionTests/Metropolis/ttTransactionTestZeroSig"}

ethcore/src/types/transaction.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ impl UnverifiedTransaction {
315315
/// The network ID, or `None` if this is a global transaction.
316316
pub fn network_id(&self) -> Option<u64> {
317317
match self.v {
318+
v if self.is_unsigned() => Some(v),
318319
v if v > 36 => Some((v - 35) / 2),
319320
_ => None,
320321
}
@@ -348,29 +349,25 @@ impl UnverifiedTransaction {
348349
// TODO: consider use in block validation.
349350
#[cfg(test)]
350351
#[cfg(feature = "json-tests")]
351-
pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool) -> Result<UnverifiedTransaction, Error> {
352-
if require_low && !self.signature().is_low_s() {
353-
return Err(EthkeyError::InvalidSignature.into())
354-
}
355-
match self.network_id() {
356-
None => {},
357-
Some(1) if allow_network_id_of_one => {},
358-
_ => return Err(TransactionError::InvalidNetworkId.into()),
352+
pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool, allow_empty_signature: bool) -> Result<UnverifiedTransaction, Error> {
353+
let chain_id = if allow_network_id_of_one { Some(1) } else { None };
354+
self.verify_basic(require_low, chain_id, allow_empty_signature)?;
355+
if !allow_empty_signature || !self.is_unsigned() {
356+
self.recover_public()?;
359357
}
360-
self.recover_public()?;
361358
if self.gas < U256::from(self.gas_required(&schedule)) {
362-
Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into())
363-
} else {
364-
Ok(self)
359+
return Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into())
365360
}
361+
Ok(self)
366362
}
367363

368364
/// Verify basic signature params. Does not attempt sender recovery.
369365
pub fn verify_basic(&self, check_low_s: bool, chain_id: Option<u64>, allow_empty_signature: bool) -> Result<(), Error> {
370-
if check_low_s && !allow_empty_signature {
366+
if check_low_s && !(allow_empty_signature && self.is_unsigned()) {
371367
self.check_low_s()?;
372368
}
373-
if !allow_empty_signature && self.is_unsigned() {
369+
// EIP-86: Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account 0.
370+
if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) {
374371
return Err(EthkeyError::InvalidSignature.into())
375372
}
376373
match (self.network_id(), chain_id) {

0 commit comments

Comments
 (0)