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 7 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