Skip to content

Commit 4fdd3c8

Browse files
committed
Add test for transaction rlp and add message hash function
1 parent 07439ed commit 4fdd3c8

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ sha3 = { version = "0.8", default-features = false }
1717

1818
[dev-dependencies]
1919
rand = "0.7"
20+
hex-literal = "0.2"
2021

2122
[features]
2223
default = ["std", "codec"]

src/transaction.rs

+50-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use core::ops::Deref;
22
use alloc::vec::Vec;
33
use rlp::{Rlp, DecoderError, RlpStream, Encodable, Decodable};
4+
use sha3::{Keccak256, Digest};
45
use ethereum_types::{H160, U256, H256};
56

67
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -25,13 +26,15 @@ impl Encodable for TransactionAction {
2526

2627
impl Decodable for TransactionAction {
2728
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
28-
let action = if rlp.is_empty() {
29-
TransactionAction::Create
29+
if rlp.is_empty() {
30+
if rlp.is_data() {
31+
Ok(TransactionAction::Create)
32+
} else {
33+
Err(DecoderError::RlpExpectedToBeData)
34+
}
3035
} else {
31-
TransactionAction::Call(rlp.as_val()?)
32-
};
33-
34-
Ok(action)
36+
Ok(TransactionAction::Call(rlp.as_val()?))
37+
}
3538
}
3639
}
3740

@@ -159,6 +162,30 @@ pub struct Transaction {
159162
pub input: Vec<u8>,
160163
}
161164

165+
impl Transaction {
166+
fn message_rlp_append(&self, s: &mut RlpStream, chain_id: Option<u64>) {
167+
s.begin_list(if chain_id.is_some() { 9 } else { 6 });
168+
s.append(&self.nonce);
169+
s.append(&self.gas_price);
170+
s.append(&self.gas_limit);
171+
s.append(&self.action);
172+
s.append(&self.value);
173+
s.append(&self.input);
174+
175+
if let Some(chain_id) = chain_id {
176+
s.append(&chain_id);
177+
s.append(&0u8);
178+
s.append(&0u8);
179+
}
180+
}
181+
182+
pub fn message_hash(&self, chain_id: Option<u64>) -> H256 {
183+
let mut stream = RlpStream::new();
184+
self.message_rlp_append(&mut stream, chain_id);
185+
H256::from_slice(Keccak256::digest(&stream.drain()).as_slice())
186+
}
187+
}
188+
162189
impl Encodable for Transaction {
163190
fn rlp_append(&self, s: &mut RlpStream) {
164191
s.begin_list(9);
@@ -176,6 +203,10 @@ impl Encodable for Transaction {
176203

177204
impl Decodable for Transaction {
178205
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
206+
if rlp.item_count()? != 9 {
207+
return Err(DecoderError::RlpIncorrectListLen)
208+
}
209+
179210
let v = rlp.val_at(6)?;
180211
let r = rlp.val_at(7)?;
181212
let s = rlp.val_at(8)?;
@@ -193,3 +224,16 @@ impl Decodable for Transaction {
193224
})
194225
}
195226
}
227+
228+
#[cfg(test)]
229+
mod tests {
230+
use super::*;
231+
use hex_literal::hex;
232+
233+
#[test]
234+
fn can_decode_raw_transaction() {
235+
let bytes = hex!("f901e48080831000008080b90196608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc68045c3c562488255b55aa2c4c7849de001859ff0d8a36a75c2d5ed80100fb660405180806020018281038252600d8152602001807f48656c6c6f2c20776f726c64210000000000000000000000000000000000000081525060200191505060405180910390a160cf806100c76000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80638da5cb5b14602d575b600080fd5b60336075565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea265627a7a72315820fae816ad954005c42bea7bc7cb5b19f7fd5d3a250715ca2023275c9ca7ce644064736f6c634300050f003278a04cab43609092a99cf095d458b61b47189d1bbab64baed10a0fd7b7d2de2eb960a011ab1bcda76dfed5e733219beb83789f9887b2a7b2e61759c7c90f7d40403201");
236+
237+
assert!(rlp::decode::<Transaction>(&bytes[..]).is_ok());
238+
}
239+
}

0 commit comments

Comments
 (0)