Skip to content

Commit

Permalink
feat: create first version of skeleton for kakarot ssj
Browse files Browse the repository at this point in the history
  • Loading branch information
Eikix committed Jul 28, 2023
1 parent 2ac9e10 commit 947640a
Show file tree
Hide file tree
Showing 17 changed files with 151 additions and 97 deletions.
6 changes: 6 additions & 0 deletions src/contract_account/contract_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Migrate https://github.com/kkrt-labs/kakarot/blob/7ec7a96074394ddb592a2b6fbea279c6c5cb25a6/src/kakarot/accounts/contract/contract_account.cairo#L4
// Note that we don't need proxies anymore with the new idiomatic way to replace implementations.
// For now, as discussed with Shahar Papini, we can still use storage slots to store bytecode.
// That being said, we can modify the way we store it with new mappings and storage outlays to optimize steps.
// Use Traits, impls blocks and idiomatic Cairo 1.0

61 changes: 61 additions & 0 deletions src/eoa/eth_transaction.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use array::ArrayTrait;

struct EthereumTransaction {
nonce: felt252,
gas_price: felt252,
gas_limit: felt252,
destination: felt252,
amount: felt252,
payload: @Array<felt252>,
tx_hash: u256,
v: felt252,
r: u256,
s: u256,
}

trait EthTransaction {
/// Decode a legacy Ethereum transaction
/// This function decodes a legacy Ethereum transaction in accordance with EIP-155.
/// It returns transaction details including nonce, gas price, gas limit, destination address, amount, payload,
/// transaction hash, and signature (v, r, s). The transaction hash is computed by keccak hashing the signed
/// transaction data, which includes the chain ID in accordance with EIP-155.
/// # Arguments
/// tx_data The raw transaction data
fn decode_legacy_tx(tx_data: @Array<u8>) -> EthereumTransaction;

/// Decode a modern Ethereum transaction
/// This function decodes a modern Ethereum transaction in accordance with EIP-2718.
/// It returns transaction details including nonce, gas price, gas limit, destination address, amount, payload,
/// transaction hash, and signature (v, r, s). The transaction hash is computed by keccak hashing the signed
/// transaction data, which includes the chain ID as part of the transaction data itself.
/// # Arguments
/// tx_data The raw transaction data
fn decode_tx(tx_data: @Array<u8>) -> EthereumTransaction;

/// Check if a raw transaction is a legacy Ethereum transaction
/// This function checks if a raw transaction is a legacy Ethereum transaction by checking the transaction type
/// according to EIP-2718. If the transaction type is less than or equal to 0xc0, it's a legacy transaction.
/// # Arguments
/// - `tx_data` The raw transaction data
fn is_legacy_tx(tx_data: @Array<u8>) -> bool;

/// Decode a raw Ethereum transaction
/// This function decodes a raw Ethereum transaction. It checks if the transaction
/// is a legacy transaction or a modern transaction, and calls the appropriate decode function
/// resp. `decode_legacy_tx` or `decode_tx` based on the result.
/// # Arguments
/// - `tx_data` The raw transaction data
fn decode(tx_data: @Array<u8>) -> EthereumTransaction;

/// Validate an Ethereum transaction
/// This function validates an Ethereum transaction by checking if the transaction
/// is correctly signed by the given address, and if the nonce in the transaction
/// matches the nonce of the account.
/// It decodes the transaction using the decode function,
/// and then verifies the Ethereum signature on the transaction hash.
/// # Arguments
/// - `address` The ethereum address that is supposed to have signed the transaction
/// - `account_nonce` The nonce of the account
/// - `param tx_data` The raw transaction data
fn validate_eth_tx(address: felt252, account_nonce: felt252, tx_data: @Array<u8>) -> bool;
}
2 changes: 2 additions & 0 deletions src/eoa/externally_owned_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Migrate https://github.com/kkrt-labs/kakarot/blob/7ec7a96074394ddb592a2b6fbea279c6c5cb25a6/src/kakarot/accounts/eoa/externally_owned_account.cairo#L4

3 changes: 3 additions & 0 deletions src/eoa/rlp.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Reproduce the original rlp.cairo from https://github.com/kkrt-labs/kakarot/blob/7ec7a96074394ddb592a2b6fbea279c6c5cb25a6/src/utils/rlp.cairo#L18
// By using new Cairo idiomatic ways: Traits, Struct and impl blocks.

4 changes: 2 additions & 2 deletions src/instructions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use traits::Into;
use kakarot::context::ExecutionContext;
use kakarot::context::CallContextTrait;
use kakarot::context::ExecutionSummary;
use kakarot::utils;
use kakarot::utils::helpers;

/// Sub modules.
mod block_information;
Expand Down Expand Up @@ -69,7 +69,7 @@ impl EVMInstructionsImpl of EVMInstructionsTrait {

// Check if PC is not out of bounds.
if pc >= bytecode_len {
utils::panic_with_code(0);
helpers::panic_with_code(0);
}

let opcode: u8 = *bytecode.at(pc);
Expand Down
36 changes: 18 additions & 18 deletions src/memory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl MemoryImpl of MemoryTrait {
// |-- mask = 256 ** offset_in_chunk

let mask: u256 = helpers::pow256_rev(offset_in_chunk);
let mask_c: u256 = utils::pow(256, 16).into() / mask;
let mask_c: u256 = helpers::pow(256, 16).into() / mask;

// Split the 2 input bytes16 chunks at offset_in_chunk.

Expand Down Expand Up @@ -256,22 +256,22 @@ impl MemoryImpl of MemoryTrait {
break ();
}

let current: felt252 = ((*elements[0]).into() * utils::pow(256, 15)
+ (*elements[1]).into() * utils::pow(256, 14)
+ (*elements[2]).into() * utils::pow(256, 13)
+ (*elements[3]).into() * utils::pow(256, 12)
+ (*elements[4]).into() * utils::pow(256, 11)
+ (*elements[5]).into() * utils::pow(256, 10)
+ (*elements[6]).into() * utils::pow(256, 9)
+ (*elements[7]).into() * utils::pow(256, 8)
+ (*elements[8]).into() * utils::pow(256, 7)
+ (*elements[9]).into() * utils::pow(256, 6)
+ (*elements[10]).into() * utils::pow(256, 5)
+ (*elements[11]).into() * utils::pow(256, 4)
+ (*elements[12]).into() * utils::pow(256, 3)
+ (*elements[13]).into() * utils::pow(256, 2)
+ (*elements[14]).into() * utils::pow(256, 1)
+ (*elements[15]).into() * utils::pow(256, 0));
let current: felt252 = ((*elements[0]).into() * helpers::pow(256, 15)
+ (*elements[1]).into() * helpers::pow(256, 14)
+ (*elements[2]).into() * helpers::pow(256, 13)
+ (*elements[3]).into() * helpers::pow(256, 12)
+ (*elements[4]).into() * helpers::pow(256, 11)
+ (*elements[5]).into() * helpers::pow(256, 10)
+ (*elements[6]).into() * helpers::pow(256, 9)
+ (*elements[7]).into() * helpers::pow(256, 8)
+ (*elements[8]).into() * helpers::pow(256, 7)
+ (*elements[9]).into() * helpers::pow(256, 6)
+ (*elements[10]).into() * helpers::pow(256, 5)
+ (*elements[11]).into() * helpers::pow(256, 4)
+ (*elements[12]).into() * helpers::pow(256, 3)
+ (*elements[13]).into() * helpers::pow(256, 2)
+ (*elements[14]).into() * helpers::pow(256, 1)
+ (*elements[15]).into() * helpers::pow(256, 0));

self.items.insert(chunk_index.into(), current.try_into().unwrap());
chunk_index += 1;
Expand Down Expand Up @@ -302,7 +302,7 @@ impl MemoryImpl of MemoryTrait {
// Compute mask.

let mask: u256 = helpers::pow256_rev(offset_in_chunk);
let mask_c: u256 = utils::pow(2, 128).into() / mask;
let mask_c: u256 = helpers::pow(2, 128).into() / mask;

// Read the words at chunk_index, +1, +2.
let w0: u128 = self.items.get(chunk_index.into());
Expand Down
3 changes: 3 additions & 0 deletions src/tests/contract_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// import modules tests/contract_account folder


2 changes: 2 additions & 0 deletions src/tests/contract_account/test_contract_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// tests go here

3 changes: 3 additions & 0 deletions src/tests/eoa.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// import modules from tests/eoa folder here


2 changes: 2 additions & 0 deletions src/tests/eoa/test_eth_transaction.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// tests go here

2 changes: 2 additions & 0 deletions src/tests/eoa/test_externally_owned_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// tests go here

2 changes: 2 additions & 0 deletions src/tests/eoa/test_rlp.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// tests go here

3 changes: 3 additions & 0 deletions src/tests/instructions.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// import modules from tests/instructions folder here


Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// tests for stop and arithmetic operations go here

14 changes: 9 additions & 5 deletions src/tests/test_memory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -120,36 +120,40 @@ fn _load_should_load_an_element_from_the_memory_with_offset(offset: usize, low:
#[available_gas(200000000)]
fn test__load__should_load_an_element_from_the_memory_with_offset_1() {
_load_should_load_an_element_from_the_memory_with_offset(
8, 2 * utils::pow(256, 8).try_into().unwrap(), utils::pow(256, 8).try_into().unwrap()
8, 2 * helpers::pow(256, 8).try_into().unwrap(), helpers::pow(256, 8).try_into().unwrap()
);
}
#[test]
#[available_gas(200000000)]
fn test__load__should_load_an_element_from_the_memory_with_offset_2() {
_load_should_load_an_element_from_the_memory_with_offset(
7, 2 * utils::pow(256, 7).try_into().unwrap(), utils::pow(256, 7).try_into().unwrap()
7, 2 * helpers::pow(256, 7).try_into().unwrap(), helpers::pow(256, 7).try_into().unwrap()
);
}
#[test]
#[available_gas(200000000)]
fn test__load__should_load_an_element_from_the_memory_with_offset_3() {
_load_should_load_an_element_from_the_memory_with_offset(
23, 3 * utils::pow(256, 7).try_into().unwrap(), 2 * utils::pow(256, 7).try_into().unwrap()
23,
3 * helpers::pow(256, 7).try_into().unwrap(),
2 * helpers::pow(256, 7).try_into().unwrap()
);
}

#[test]
#[available_gas(200000000)]
fn test__load__should_load_an_element_from_the_memory_with_offset_4() {
_load_should_load_an_element_from_the_memory_with_offset(
33, 4 * utils::pow(256, 1).try_into().unwrap(), 3 * utils::pow(256, 1).try_into().unwrap()
33,
4 * helpers::pow(256, 1).try_into().unwrap(),
3 * helpers::pow(256, 1).try_into().unwrap()
);
}
#[test]
#[available_gas(200000000)]
fn test__load__should_load_an_element_from_the_memory_with_offset_5() {
_load_should_load_an_element_from_the_memory_with_offset(
63, 0, 4 * utils::pow(256, 15).try_into().unwrap()
63, 0, 4 * helpers::pow(256, 15).try_into().unwrap()
);
}

Expand Down
72 changes: 0 additions & 72 deletions src/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,75 +5,3 @@ use option::OptionTrait;
mod helpers;
mod constants;

/// Panic with a custom message.
/// # Arguments
/// * `msg` - The message to panic with. Must be a short string to fit in a felt252.
fn panic_with(err: felt252) {
let mut data = ArrayTrait::new();
data.append(err);
panic(data);
}

/// Convert a `felt252` to a `NonZero` type.
/// # Arguments
/// * `felt252` - The `felt252` to convert.
/// # Returns
/// * `Option::<NonZero::<felt252>>` - The `felt252` as a `NonZero` type.
/// * `Option::<NonZero::<felt252>>::None` - If `felt252` is 0.
fn to_non_zero(felt252: felt252) -> Option::<NonZero<felt252>> {
let res = felt252_is_zero(felt252);
match res {
zeroable::IsZeroResult::Zero(()) => Option::<NonZero<felt252>>::None(()),
zeroable::IsZeroResult::NonZero(val) => Option::<NonZero<felt252>>::Some(val),
}
}


/// Force conversion from `felt252` to `u128`.
fn unsafe_felt252_to_u128(a: felt252) -> u128 {
let res = integer::u128_try_from_felt252(a);
res.unwrap()
}

/// Perform euclidean division on `felt252` types.
fn unsafe_euclidean_div_no_remainder(a: felt252, b: felt252) -> felt252 {
let a_u128 = unsafe_felt252_to_u128(a);
let b_u128 = unsafe_felt252_to_u128(b);
integer::u128_to_felt252(a_u128 / b_u128)
}

fn unsafe_euclidean_div(a: felt252, b: felt252) -> (felt252, felt252) {
let a_u128 = unsafe_felt252_to_u128(a);
let b_u128 = unsafe_felt252_to_u128(b);
(integer::u128_to_felt252(a_u128 / b_u128), integer::u128_to_felt252(a_u128 % b_u128))
}

fn max(a: usize, b: usize) -> usize {
if a > b {
return a;
} else {
return b;
}
}

// Raise a number to a power.
/// * `base` - The number to raise.
/// * `exp` - The exponent.
/// # Returns
/// * `felt252` - The result of base raised to the power of exp.
fn pow(base: felt252, exp: felt252) -> felt252 {
if exp == 0 {
return 1;
} else {
return base * pow(base, exp - 1);
}
}

/// Panic with a custom code.
/// # Arguments
/// * `code` - The code to panic with. Must be a short string to fit in a felt252.
fn panic_with_code(code: felt252) {
let mut data = ArrayTrait::new();
data.append(code);
panic(data);
}
31 changes: 31 additions & 0 deletions src/utils/helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,34 @@ impl U256TryIntoU128 of TryInto<u256, u128> {
Option::Some(self.low)
}
}


fn max(a: usize, b: usize) -> usize {
if a > b {
return a;
} else {
return b;
}
}

// Raise a number to a power.
/// * `base` - The number to raise.
/// * `exp` - The exponent.
/// # Returns
/// * `felt252` - The result of base raised to the power of exp.
fn pow(base: felt252, exp: felt252) -> felt252 {
if exp == 0 {
return 1;
} else {
return base * pow(base, exp - 1);
}
}

/// Panic with a custom code.
/// # Arguments
/// * `code` - The code to panic with. Must be a short string to fit in a felt252.
fn panic_with_code(code: felt252) {
let mut data = ArrayTrait::new();
data.append(code);
panic(data);
}

0 comments on commit 947640a

Please sign in to comment.