Skip to content

Commit

Permalink
refactor: eth_send_raw_transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
enitrat committed Oct 4, 2024
1 parent f6c15f5 commit 94329d9
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 84 deletions.
13 changes: 4 additions & 9 deletions crates/contracts/src/account_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub mod AccountContract {
use crate::storage::StorageBytecode;
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
use super::OutsideExecution;
use utils::eth_transaction::transaction::TransactionUnsignedTrait;
use utils::eth_transaction::transaction::TransactionTrait;
use utils::serialization::{deserialize_signature, deserialize_bytes, serialize_bytes};
use utils::traits::DefaultSignature;

Expand Down Expand Up @@ -249,18 +249,13 @@ pub mod AccountContract {
let mut encoded_tx_data = deserialize_bytes((*outside_execution.calls[0]).calldata)
.expect('conversion to Span<u8> failed')
.span();
let unsigned_transaction = TransactionUnsignedTrait::decode_enveloped(
ref encoded_tx_data
)
.expect('EOA: could not decode tx');
let unsigned_transaction_hash = TransactionTrait::compute_hash(encoded_tx_data);

let address = self.Account_evm_address.read();
verify_eth_signature(unsigned_transaction.hash, signature, address);
verify_eth_signature(unsigned_transaction_hash, signature, address);

//TODO: refactor this to call eth_send_raw_unsigned_tx. Only the transactions bytes are
//passed.
let (success, return_data, gas_used) = kakarot
.eth_send_transaction(unsigned_transaction.transaction);
.eth_send_raw_unsigned_tx(encoded_tx_data);
let return_data = serialize_bytes(return_data).span();

// See Argent account
Expand Down
16 changes: 9 additions & 7 deletions crates/contracts/src/kakarot_core/eth_rpc.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use evm::model::{TransactionResult, Address};
use evm::{EVMTrait};
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
use utils::constants::POW_2_53;
use utils::eth_transaction::transaction::Transaction;
use utils::eth_transaction::transaction::{Transaction, TransactionTrait};

#[starknet::interface]
pub trait IEthRPC<T> {
Expand Down Expand Up @@ -175,6 +175,14 @@ pub impl EthRPC<
fn eth_send_transaction(
ref self: TContractState, mut tx: Transaction
) -> (bool, Span<u8>, u64) {
panic!("unimplemented")
}

fn eth_send_raw_unsigned_tx(
ref self: TContractState, mut tx_data: Span<u8>
) -> (bool, Span<u8>, u64) {
let tx = TransactionTrait::decode_enveloped(ref tx_data).expect('EOA: could not decode tx');

let mut kakarot_state = KakarotState::get_state();
let intrinsic_gas = validate_eth_tx(@kakarot_state, tx);

Expand All @@ -189,12 +197,6 @@ pub impl EthRPC<
starknet_backend::commit(ref state).expect('Committing state failed');
(success, return_data, gas_used)
}

fn eth_send_raw_unsigned_tx(
ref self: TContractState, tx_data: Span<u8>
) -> (bool, Span<u8>, u64) {
panic!("unimplemented")
}
}

trait IEthRPCInternal<T> {
Expand Down
114 changes: 46 additions & 68 deletions crates/utils/src/eth_transaction/transaction.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -173,19 +173,8 @@ pub impl _Transasction of TransactionTrait {
Transaction::Eip1559(tx) => tx.input,
}
}
}


#[derive(Copy, Drop, Debug, PartialEq)]
pub struct TransactionUnsigned {
/// Transaction hash
pub hash: u256,
/// Raw transaction info
pub transaction: Transaction,
}

#[generate_trait]
pub impl _TransactionUnsigned of TransactionUnsignedTrait {
/// Decodes the "raw" format of transaction (similar to `eth_sendRawTransaction`).
///
/// This should be used for any method that accepts a raw transaction.
Expand All @@ -201,9 +190,7 @@ pub impl _TransactionUnsigned of TransactionUnsignedTrait {
///
/// Both for legacy and EIP-2718 transactions, an error will be returned if there is an excess
/// of bytes in input data.
fn decode_enveloped(
ref tx_data: Span<u8>,
) -> Result<TransactionUnsigned, EthTransactionError> {
fn decode_enveloped(ref tx_data: Span<u8>,) -> Result<Transaction, EthTransactionError> {
if tx_data.is_empty() {
return Result::Err(EthTransactionError::RLPError(RLPError::InputTooShort));
}
Expand Down Expand Up @@ -233,9 +220,7 @@ pub impl _TransactionUnsigned of TransactionUnsignedTrait {
/// chainId, 0, 0]
/// Note: this function assumes that tx_type has been checked to make sure it is a legacy
/// transaction
fn decode_legacy_tx(
ref encoded_tx_data: Span<u8>
) -> Result<TransactionUnsigned, EthTransactionError> {
fn decode_legacy_tx(ref encoded_tx_data: Span<u8>) -> Result<Transaction, EthTransactionError> {
let rlp_decoded_data = RLPTrait::decode(encoded_tx_data);
let mut rlp_decoded_data = rlp_decoded_data.map_err()?;

Expand All @@ -256,11 +241,7 @@ pub impl _TransactionUnsigned of TransactionUnsignedTrait {
}
};

let tx_hash = Self::compute_hash(encoded_tx_data);

Result::Ok(
TransactionUnsigned { transaction: Transaction::Legacy(legacy_tx), hash: tx_hash, }
)
Result::Ok(Transaction::Legacy(legacy_tx))
}

/// Decodes an enveloped EIP-2718 typed transaction.
Expand All @@ -275,7 +256,7 @@ pub impl _TransactionUnsigned of TransactionUnsignedTrait {
/// CAUTION: this expects that `data` is `tx-type || rlp(tx-data)`
fn decode_enveloped_typed_transaction(
ref encoded_tx_data: Span<u8>
) -> Result<TransactionUnsigned, EthTransactionError> {
) -> Result<Transaction, EthTransactionError> {
// keep this around so we can use it to calculate the hash
let original_data = encoded_tx_data;

Expand Down Expand Up @@ -316,8 +297,7 @@ pub impl _TransactionUnsigned of TransactionUnsignedTrait {
}
};

let tx_hash = Self::compute_hash(original_data);
Result::Ok(TransactionUnsigned { transaction, hash: tx_hash })
Result::Ok(transaction)
}

/// Returns the hash of the unsigned transaction
Expand Down Expand Up @@ -355,7 +335,7 @@ mod tests {
legacy_rlp_encoded_tx, legacy_rlp_encoded_deploy_tx, eip_2930_encoded_tx,
eip_1559_encoded_tx
};
use super::{TransactionTrait, TransactionUnsignedTrait};
use super::{TransactionTrait};


#[test]
Expand All @@ -368,18 +348,18 @@ mod tests {
// message_hash: 0xcf71743e6e25fef715398915997f782b95554c8bbfb7b3f7701e007332ed31b4
// chain id used: 'KKRT'
let mut encoded_tx_data = legacy_rlp_encoded_tx();
let decoded = TransactionUnsignedTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(decoded.transaction.nonce(), 0);
assert_eq!(decoded.transaction.max_fee_per_gas(), 0x3b9aca00);
assert_eq!(decoded.transaction.gas_limit(), 0x1e8480);
let transaction = TransactionTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(transaction.nonce(), 0);
assert_eq!(transaction.max_fee_per_gas(), 0x3b9aca00);
assert_eq!(transaction.gas_limit(), 0x1e8480);
assert_eq!(
decoded.transaction.kind(),
transaction.kind(),
TxKind::Call(0x1f9840a85d5af5bf1d1762f925bdaddc4201f984.try_into().unwrap())
);
assert_eq!(decoded.transaction.value(), 0x016345785d8a0000);
assert_eq!(decoded.transaction.input(), [0xab, 0xcd, 0xef].span());
assert_eq!(decoded.transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(decoded.transaction.transaction_type(), TxType::Legacy);
assert_eq!(transaction.value(), 0x016345785d8a0000);
assert_eq!(transaction.input(), [0xab, 0xcd, 0xef].span());
assert_eq!(transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(transaction.transaction_type(), TxType::Legacy);
}

#[test]
Expand All @@ -389,18 +369,18 @@ mod tests {
// expected rlp decoding:
// ["0x","0x0a","0x061a80","0x","0x0186a0","0x600160010a5060006000f3","0x4b4b5254","0x","0x"]
let mut encoded_tx_data = legacy_rlp_encoded_deploy_tx();
let decoded = TransactionUnsignedTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(decoded.transaction.nonce(), 0);
assert_eq!(decoded.transaction.max_fee_per_gas(), 0x0a);
assert_eq!(decoded.transaction.gas_limit(), 0x061a80);
assert_eq!(decoded.transaction.kind(), TxKind::Create);
assert_eq!(decoded.transaction.value(), 0x0186a0);
let transaction = TransactionTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(transaction.nonce(), 0);
assert_eq!(transaction.max_fee_per_gas(), 0x0a);
assert_eq!(transaction.gas_limit(), 0x061a80);
assert_eq!(transaction.kind(), TxKind::Create);
assert_eq!(transaction.value(), 0x0186a0);
assert_eq!(
decoded.transaction.input(),
transaction.input(),
[0x60, 0x01, 0x60, 0x01, 0x0a, 0x50, 0x60, 0x00, 0x60, 0x00, 0xf3].span()
);
assert_eq!(decoded.transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(decoded.transaction.transaction_type(), TxType::Legacy);
assert_eq!(transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(transaction.transaction_type(), TxType::Legacy);
}

#[test]
Expand All @@ -416,18 +396,18 @@ mod tests {
// chain id used: 'KKRT'

let mut encoded_tx_data = eip_2930_encoded_tx();
let decoded = TransactionUnsignedTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(decoded.transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(decoded.transaction.nonce(), 0);
assert_eq!(decoded.transaction.max_fee_per_gas(), 0x3b9aca00);
assert_eq!(decoded.transaction.gas_limit(), 0x1e8480);
let transaction = TransactionTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(transaction.nonce(), 0);
assert_eq!(transaction.max_fee_per_gas(), 0x3b9aca00);
assert_eq!(transaction.gas_limit(), 0x1e8480);
assert_eq!(
decoded.transaction.kind(),
transaction.kind(),
TxKind::Call(0x1f9840a85d5af5bf1d1762f925bdaddc4201f984.try_into().unwrap())
);
assert_eq!(decoded.transaction.value(), 0x016345785d8a0000);
assert_eq!(decoded.transaction.input(), [0xab, 0xcd, 0xef].span());
assert_eq!(decoded.transaction.transaction_type(), TxType::Eip2930);
assert_eq!(transaction.value(), 0x016345785d8a0000);
assert_eq!(transaction.input(), [0xab, 0xcd, 0xef].span());
assert_eq!(transaction.transaction_type(), TxType::Eip2930);
}

#[test]
Expand All @@ -443,17 +423,17 @@ mod tests {
// chain id used: 'KKRT'

let mut encoded_tx_data = eip_1559_encoded_tx();
let decoded = TransactionUnsignedTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(decoded.transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(decoded.transaction.nonce(), 0);
assert_eq!(decoded.transaction.max_fee_per_gas(), 0x3b9aca00);
assert_eq!(decoded.transaction.gas_limit(), 0x1e8480);
let transaction = TransactionTrait::decode_enveloped(ref encoded_tx_data).unwrap();
assert_eq!(transaction.chain_id(), Option::Some(0x4b4b5254));
assert_eq!(transaction.nonce(), 0);
assert_eq!(transaction.max_fee_per_gas(), 0x3b9aca00);
assert_eq!(transaction.gas_limit(), 0x1e8480);
assert_eq!(
decoded.transaction.kind(),
transaction.kind(),
TxKind::Call(0x1f9840a85d5af5bf1d1762f925bdaddc4201f984.try_into().unwrap())
);
assert_eq!(decoded.transaction.value(), 0x016345785d8a0000);
assert_eq!(decoded.transaction.input(), [0xab, 0xcd, 0xef].span());
assert_eq!(transaction.value(), 0x016345785d8a0000);
assert_eq!(transaction.input(), [0xab, 0xcd, 0xef].span());
let expected_access_list = [
AccessListItem {
ethereum_address: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984.try_into().unwrap(),
Expand All @@ -463,32 +443,30 @@ mod tests {
].span()
}
].span();
assert_eq!(
decoded.transaction.access_list().expect('access_list is none'), expected_access_list
);
assert_eq!(decoded.transaction.transaction_type(), TxType::Eip1559);
assert_eq!(transaction.access_list().expect('access_list is none'), expected_access_list);
assert_eq!(transaction.transaction_type(), TxType::Eip1559);
}

#[test]
fn test_is_legacy_tx_eip_155_tx() {
let encoded_tx_data = legacy_rlp_encoded_tx();
let result = TransactionUnsignedTrait::is_legacy_tx(encoded_tx_data);
let result = TransactionTrait::is_legacy_tx(encoded_tx_data);

assert(result, 'is_legacy_tx expected true');
}

#[test]
fn test_is_legacy_tx_eip_1559_tx() {
let encoded_tx_data = eip_1559_encoded_tx();
let result = TransactionUnsignedTrait::is_legacy_tx(encoded_tx_data);
let result = TransactionTrait::is_legacy_tx(encoded_tx_data);

assert(!result, 'is_legacy_tx expected false');
}

#[test]
fn test_is_legacy_tx_eip_2930_tx() {
let encoded_tx_data = eip_2930_encoded_tx();
let result = TransactionUnsignedTrait::is_legacy_tx(encoded_tx_data);
let result = TransactionTrait::is_legacy_tx(encoded_tx_data);

assert(!result, 'is_legacy_tx expected false');
}
Expand Down

0 comments on commit 94329d9

Please sign in to comment.