From f4ddf8f9b88c73e5dae119b3ea3666fc9aff67c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Thu, 27 Apr 2023 16:54:21 +0300 Subject: [PATCH] feat(evm-utils/evm-state): connect to fast_rlp feature part 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ ] merge [pull request: < fast-rlp >](https://github.com/velas/velas-chain/pull/443) ├── [ ] merge [pull request: < triedb | fast-rlp >](https://github.com/velas/triedb/pull/51) └── [ ] make minimal changes to make velas-chain compile with both libs used ├── [✓] __evm-utils/evm-state/src/types.rs__: │ ├── [✓] `Account` │ │ ├── [✓] `Encodable` stub, `Decodable` stub │ │ ├── [✓] actual impl │ │ │ └── [✓] roundtrip test │ │ └── [✓] move old impl to #[cfg(test)] │ └── [✓] `EthereumReceipt` │ ├── [✓] `Encodable` stub, `Decodable` stub │ ├── [✓] roundtrip test │ ├── [✓] move old impl to #[cfg(test)] │ └── [✓] nested │ ├── [✓] `ethbloom::Bloom` │ │ ├── [✓] `Encodable` stub, `Decodable` stub │ │ ├── [✓] nested │ │ └── [✓] roundtrip test │ └── [✓] `ethereum::Log` │ ├── [✓] `Encodable` stub, `Decodable` stub │ ├── [✓] nested │ └── [✓] roundtrip test └── [ ] __evm-utils/evm-state/src/transactions.rs__: └── [ ] `TransactionInReceipt` ├── [✓] `Encodable` stub, `Decodable` stub ├── [ ] roundtrip test ├── [ ] move old impl to #[cfg(test)] └── [ ] nested ├── [✓] `Transaction` │ ├── [✓] `Encodable` stub, `Decodable` stub │ ├── [✓] roundtrip test │ ├── [ ] move old impl to #[cfg(test)] │ └── [ ] nested │ └── [✓] `TransactionAction` │ ├── [✓] `Encodable` stub, `Decodable` stub │ └── [✓] nested └── [✓] `UnsignedTransactionWithCaller` ├── [✓] `Encodable` stub, `Decodable` stub ├── [✓] roundtrip test ├── [ ] move old impl to #[cfg(test)] └── [ ] nested └── [✓] `UnsignedTransaction` ├── [✓] `Encodable` stub, `Decodable` stub ├── [✓] roundtrip test ├── [✓] move old impl to #[cfg(test)] ├── [✓] return derived `Encodable`, `Decodable` impl └── [✓] nested └── [✓] `TransactionAction` ├── [✓] `Encodable` stub, `Decodable` stub ├── [✓] roundtrip test └── [ ] move old impl to #[cfg(test)] --- .../evm-state/src/rlp_roundtrip_tests.rs | 113 ++++++++++++++- evm-utils/evm-state/src/transactions.rs | 134 +++++++++++++++++- 2 files changed, 240 insertions(+), 7 deletions(-) diff --git a/evm-utils/evm-state/src/rlp_roundtrip_tests.rs b/evm-utils/evm-state/src/rlp_roundtrip_tests.rs index 3bd0737816..7b250bad13 100644 --- a/evm-utils/evm-state/src/rlp_roundtrip_tests.rs +++ b/evm-utils/evm-state/src/rlp_roundtrip_tests.rs @@ -1,4 +1,4 @@ -use crate::{transaction_roots::EthereumReceipt, TransactionAction, UnsignedTransaction, UnsignedTransactionWithCaller}; +use crate::{transaction_roots::EthereumReceipt, TransactionAction, UnsignedTransaction, UnsignedTransactionWithCaller, Transaction, TransactionSignature, TransactionInReceipt}; use super::types::Account; @@ -260,4 +260,115 @@ fn test_check_unsigned_transaction_with_caller_roundtrip2() { { assert_eq!(old_rlp_raw, rlp_raw); } +} + +#[test] +fn test_check_transaction_roundtrip() { + + let ta1 = TransactionAction::Create; + let tx1 = Transaction{ + nonce: U256([72; 4]), + gas_price: U256([3213;4]), + gas_limit: U256([4324; 4]), + action: ta1, + value: U256([7732; 4]), + signature: TransactionSignature { + v: 88979, + r: H256([34; 32]), + s: H256([78; 32]), + }, + input: vec![32, 31, 0, 34, 76, 173], + + }; + + check_roundtrip!(tx1 => Transaction); + + let ta2 = TransactionAction::Call(H160([56; 20])); + let tx2 = Transaction{ + nonce: U256([79; 4]), + gas_price: U256([3013;4]), + gas_limit: U256([4124; 4]), + action: ta2, + value: U256([7832; 4]), + signature: TransactionSignature { + v: 88979, + r: H256([38; 32]), + s: H256([76; 32]), + }, + input: vec![32, 31, 0, 34, 76, 173], + + }; + + check_roundtrip!(tx2 => Transaction); + +} + +#[test] +fn test_check_transaction_in_receipt_roundtrip() { + + let ta = TransactionAction::Create; + let tx = Transaction{ + nonce: U256([72; 4]), + gas_price: U256([3213;4]), + gas_limit: U256([4324; 4]), + action: ta, + value: U256([7732; 4]), + signature: TransactionSignature { + v: 88979, + r: H256([34; 32]), + s: H256([78; 32]), + }, + input: vec![32, 31, 0, 34, 76, 173], + + }; + + let tx_in_rec1 = TransactionInReceipt::Signed(tx); + + check_roundtrip!(tx_in_rec1 => TransactionInReceipt); + let ta = TransactionAction::Create; + + let ut = UnsignedTransaction { + nonce: U256([46;4]), + gas_price: U256([543; 4]), + gas_limit: U256([342;4]), + action: ta, + value: U256([23000;4]), + input: vec![34, 45, 12, 123, 243], + }; + + let ut_c = UnsignedTransactionWithCaller { + unsigned_tx: ut, + caller: H160([23; 20]), + chain_id: 24, + signed_compatible: false, + + }; + + let tx_in_rec2 = TransactionInReceipt::Unsigned(ut_c); + + + check_roundtrip!(tx_in_rec2 => TransactionInReceipt); + + let ta2 = TransactionAction::Call(H160([56; 20])); + + let ut2 = UnsignedTransaction { + nonce: U256([46;4]), + gas_price: U256([543; 4]), + gas_limit: U256([342;4]), + action: ta2, + value: U256([20000; 4]), + input: vec![34, 45, 12, 123, 243], + }; + + let ut_c2 = UnsignedTransactionWithCaller { + unsigned_tx: ut2, + caller: H160([23; 20]), + chain_id: 24, + signed_compatible: true, + + }; + let tx_in_rec3 = TransactionInReceipt::Unsigned(ut_c2); + + check_roundtrip!(tx_in_rec3 => TransactionInReceipt); + } \ No newline at end of file diff --git a/evm-utils/evm-state/src/transactions.rs b/evm-utils/evm-state/src/transactions.rs index a0075ab828..a9c113c104 100644 --- a/evm-utils/evm-state/src/transactions.rs +++ b/evm-utils/evm-state/src/transactions.rs @@ -1,5 +1,5 @@ use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; -use bytes::BufMut; +use bytes::{BufMut, Buf}; use evm::{backend::Log, ExitReason, ExitRevert}; use primitive_types::{H160, H256, U256}; use rlp::{Decodable as DecodableOld, DecoderError, Encodable as EncodableOld, Rlp, RlpStream}; @@ -385,6 +385,73 @@ impl EncodableOld for Transaction { } } +impl Encodable for Transaction { + fn encode(&self,out: &mut dyn BufMut) { + + let len = self.nonce.length() + self.gas_price.length() + + self.gas_limit.length() + self.action.length() + + self.value.length() + self.input.length() + + self.signature.v.length() + self.signature.r.length() + self.signature.s.length() ; + fastrlp::Header { + list: true, + payload_length: len, + }.encode(out); + self.nonce.encode(out); + self.gas_price.encode(out); + self.gas_limit.encode(out); + self.action.encode(out); + self.value.encode(out); + self.input.encode(out); + self.signature.v.encode(out); + self.signature.r.encode(out); + self.signature.s.encode(out); + } + + fn length(&self) -> usize { + + let len = self.nonce.length() + self.gas_price.length() + + self.gas_limit.length() + self.action.length() + + self.value.length() + self.input.length() + + self.signature.v.length() + self.signature.r.length() + self.signature.s.length() ; + fastrlp::Header { + list: true, + payload_length: len, + } + .length() + + len + + } +} + +impl<'de> Decodable<'de> for Transaction { + fn decode(buf: &mut &'de [u8]) -> Result { + let h = fastrlp::Header::decode(buf)?; + if !h.list { + return Err(fastrlp::DecodeError::UnexpectedString); + } + let payload_view = &mut &buf[..h.payload_length]; + let cnt = fastrlp::count(payload_view)?; + if cnt!= 9 { + return Err(fastrlp::DecodeError::ListLengthMismatch { expected: 9, got: cnt }); + } + + let nonce = fastrlp::Decodable::decode(payload_view)?; + let gas_price = fastrlp::Decodable::decode(payload_view)?; + let gas_limit = fastrlp::Decodable::decode(payload_view)?; + let action = fastrlp::Decodable::decode(payload_view)?; + let value = fastrlp::Decodable::decode(payload_view)?; + let input= fastrlp::Decodable::decode(payload_view)?; + let v= fastrlp::Decodable::decode(payload_view)?; + let r = fastrlp::Decodable::decode(payload_view)?; + let s = fastrlp::Decodable::decode(payload_view)?; + buf.advance(h.payload_length); + Ok(Self { + nonce, gas_price, gas_limit, action, value, input, + signature: TransactionSignature { v, r, s}, + }) + } +} + impl DecodableOld for Transaction { fn decode(rlp: &Rlp<'_>) -> Result { Ok(Self { @@ -462,19 +529,74 @@ impl TransactionInReceipt { impl Encodable for TransactionInReceipt { fn encode(&self,out: &mut dyn BufMut) { - unimplemented!(); + match self { + TransactionInReceipt::Signed(tx) => { + tx.encode(out); + }, + TransactionInReceipt::Unsigned(tx) => { + tx.encode(out); + }, + } } fn length(&self) -> usize { - unimplemented!(); - + match self { + TransactionInReceipt::Signed(tx) => { + tx.length() + }, + TransactionInReceipt::Unsigned(tx) => { + tx.length() + }, + } } } +pub fn consume(buf: &mut &[u8]) -> Result<(), triedb::rlp::decode::DecodeError> { + let h = fastrlp::Header::decode(buf)?; + + buf.advance(h.payload_length); + Ok(()) + + +} impl<'de> Decodable<'de> for TransactionInReceipt { fn decode(buf: &mut &'de [u8]) -> Result { - unimplemented!(); + let mut count_view = *buf; + let h = fastrlp::Header::decode(&mut count_view)?; + if !h.list { + return Err(fastrlp::DecodeError::UnexpectedString); + } + let count_view = &mut &count_view[..h.payload_length]; + let cnt = fastrlp::count(count_view)?; + + let res = match cnt { + 8 => { + TransactionInReceipt::Unsigned(UnsignedTransactionWithCaller::decode(buf, false)?) + }, + 9 => { + for _repeat in 0..8 { + consume(count_view)?; + } + let res: Result = fastrlp::Decodable::decode(count_view); + match (count_view.is_empty(), res) { + (true, Ok(UNSIGNED_TX_MARKER)) => { + TransactionInReceipt::Unsigned(UnsignedTransactionWithCaller::decode(buf, true)?) + }, + _ => { + TransactionInReceipt::Signed(::decode(buf)?) + } + + } + + }, + _ => return Err(fastrlp::DecodeError::Custom( + "list len must be either 8 or 9 for TransactionInReceipt" + ) ), + + }; + Ok(res) } } + impl EncodableOld for TransactionInReceipt { fn rlp_append(&self, s: &mut RlpStream) { match self { @@ -511,7 +633,7 @@ impl DecodableOld for TransactionInReceipt { rlp, true, )?) } else { - TransactionInReceipt::Signed(Transaction::decode(rlp)?) + TransactionInReceipt::Signed(::decode(rlp)?) } } _ => return Err(DecoderError::RlpInvalidLength),