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

remove null signatures #11335

Merged
merged 9 commits into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ethcore/machine/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ impl Machine {
} else {
None
};
t.verify_basic(check_low_s, chain_id, false)?;
t.verify_basic(check_low_s, chain_id)?;

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/test_helpers/evm_test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl<'a> EvmTestClient<'a> {
) -> std::result::Result<TransactSuccess<T::Output, V::Output>, TransactErr> {
let initial_gas = transaction.gas;
// Verify transaction
let is_ok = transaction.verify_basic(true, None, false);
let is_ok = transaction.verify_basic(true, None);
if let Err(error) = is_ok {
return Err(
TransactErr{
Expand Down
62 changes: 37 additions & 25 deletions ethcore/types/src/transaction/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ impl Transaction {
}
}

#[cfg(any(test, feature = "test-helpers"))]
impl From<ethjson::transaction::Transaction> for SignedTransaction {
fn from(t: ethjson::transaction::Transaction) -> Self {
let to: Option<ethjson::hash::Address> = t.to.into();
Expand Down Expand Up @@ -237,7 +238,10 @@ impl Transaction {
}
}

/// Add EIP-86 compatible empty signature.
/// Legacy EIP-86 compatible empty signature.
/// This method is used in json tests as well as
/// signature verification tests.
#[cfg(any(test, feature = "test-helpers"))]
pub fn null_sign(self, chain_id: u64) -> SignedTransaction {
ordian marked this conversation as resolved.
Show resolved Hide resolved
SignedTransaction {
transaction: UnverifiedTransaction {
Expand Down Expand Up @@ -295,7 +299,7 @@ impl rlp::Decodable for UnverifiedTransaction {
v: d.val_at(6)?,
r: d.val_at(7)?,
s: d.val_at(8)?,
hash: hash,
hash,
})
}
}
Expand Down Expand Up @@ -369,7 +373,7 @@ impl UnverifiedTransaction {
/// Checks whether the signature has a low 's' value.
pub fn check_low_s(&self) -> Result<(), parity_crypto::publickey::Error> {
if !self.signature().is_low_s() {
Err(parity_crypto::publickey::Error::InvalidSignature.into())
Err(parity_crypto::publickey::Error::InvalidSignature)
} else {
Ok(())
}
Expand All @@ -386,17 +390,12 @@ impl UnverifiedTransaction {
}

/// Verify basic signature params. Does not attempt sender recovery.
pub fn verify_basic(&self, check_low_s: bool, chain_id: Option<u64>, allow_empty_signature: bool) -> Result<(), error::Error> {
if check_low_s && !(allow_empty_signature && self.is_unsigned()) {
self.check_low_s()?;
}
// Disallow unsigned transactions in case EIP-86 is disabled.
if !allow_empty_signature && self.is_unsigned() {
pub fn verify_basic(&self, check_low_s: bool, chain_id: Option<u64>) -> Result<(), error::Error> {
if self.is_unsigned() {
return Err(parity_crypto::publickey::Error::InvalidSignature.into());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a Error::Unsigned you think?

}
// EIP-86: Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account 0.
if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) {
return Err(parity_crypto::publickey::Error::InvalidSignature.into())
if check_low_s {
self.check_low_s()?;
}
match (self.chain_id(), chain_id) {
(None, _) => {},
Expand Down Expand Up @@ -441,20 +440,15 @@ impl SignedTransaction {
/// Try to verify transaction and recover sender.
pub fn new(transaction: UnverifiedTransaction) -> Result<Self, parity_crypto::publickey::Error> {
if transaction.is_unsigned() {
Ok(SignedTransaction {
transaction: transaction,
sender: UNSIGNED_SENDER,
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
public: None,
})
} else {
let public = transaction.recover_public()?;
let sender = public_to_address(&public);
Ok(SignedTransaction {
transaction: transaction,
sender: sender,
public: Some(public),
})
return Err(parity_crypto::publickey::Error::InvalidSignature);
}
let public = transaction.recover_public()?;
let sender = public_to_address(&public);
Ok(SignedTransaction {
transaction,
sender,
public: Some(public),
})
}

/// Returns transaction sender.
Expand Down Expand Up @@ -645,6 +639,24 @@ mod tests {
assert_eq!(t.chain_id(), None);
}

#[test]
fn should_reject_null_signature() {
let t = Transaction {
nonce: U256::zero(),
gas_price: U256::from(10000000000u64),
gas: U256::from(21000),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(1),
data: vec![]
}.null_sign(1);

let res = SignedTransaction::new(t.transaction);
match res {
Err(parity_crypto::publickey::Error::InvalidSignature) => {}
_ => panic!("null signature should be rejected"),
}
}

#[test]
fn should_recover_from_chain_specific_signing() {
use parity_crypto::publickey::{Random, Generator};
Expand Down
2 changes: 1 addition & 1 deletion evmbin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ path = "./src/main.rs"

[dependencies]
account-state = { path = "../ethcore/account-state" }
common-types = { path = "../ethcore/types" }
common-types = { path = "../ethcore/types", features = ["test-helpers"] }
docopt = "1.0"
env_logger = "0.5"
ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests"] }
Expand Down
22 changes: 22 additions & 0 deletions json/src/spec/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ mod tests {
]);
}

#[test]
fn deserialization_alt_bn128_const_operations() {
ordian marked this conversation as resolved.
Show resolved Hide resolved
let s = r#"{
"name": "alt_bn128_mul",
"pricing": {
"100500": {
"price": { "alt_bn128_const_operations": { "price": 123 }}
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "alt_bn128_mul");
assert_eq!(builtin.pricing, map![
100500 => PricingAt {
info: None,
price: Pricing::AltBn128ConstOperations(AltBn128ConstOperations {
price: 123,
}),
}
]);
}

#[test]
fn activate_at() {
let s = r#"{
Expand Down
1 change: 0 additions & 1 deletion json/src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ pub fn validate_optional_non_zero<'de, D>(d: D) -> Result<Option<Uint>, D::Error
mod test {
use super::Uint;
use ethereum_types::U256;
use serde_json::error::Category;

#[test]
fn uint_deserialization() {
Expand Down