Skip to content

Commit

Permalink
Pushed tests n refactored evm
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkLord017 authored and DarkLord017 committed Nov 2, 2024
1 parent b58b43e commit 89802f0
Show file tree
Hide file tree
Showing 23 changed files with 2,853 additions and 0 deletions.
64 changes: 64 additions & 0 deletions execution/evm/journal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package evm

import (
"github.com/BlocSoc-iitr/selene/common"
)

type JournaledState struct {
State EvmState
TransientStorage TransientStorage
Logs []Log[LogData]
Depth uint
Journal [][]JournalEntry
Spec SpecId
WarmPreloadedAddresses map[Address]struct{}
}

func NewJournalState(spec SpecId, warmPreloadedAddresses map[Address]struct{}) JournaledState {
return JournaledState{
State: nil,
TransientStorage: nil,
Logs: []Log[LogData]{},
Depth: 0,
Journal: [][]JournalEntry{},
Spec: spec,
WarmPreloadedAddresses: warmPreloadedAddresses,
}
}

type JournalCheckpoint struct {
Log_i uint
Journal_i uint
}

func (j *JournaledState) setSpecId(spec SpecId) {
j.Spec = spec
}

type TransientStorage map[Key]U256
type EvmState map[common.Address]Account
type Key struct {
Account common.Address
Slot U256
}
type Log[T any] struct {
// The address which emitted this log.
Address Address `json:"address"`
// The log data.
Data T `json:"data"`
}

type LogData struct {
// The indexed topic list.
Topics []B256 `json:"topics"`
// The plain data.
Data Bytes `json:"data"`
}

func (l *Log[LogData]) UnmarshalJSON(data []byte) error {
return unmarshalJSON(data, l)
}

func (l *LogData) UnmarshalJSON(data []byte) error {
return unmarshalJSON(data, l)
}
157 changes: 157 additions & 0 deletions execution/evm/journal_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package evm

import (
"encoding/json"
"fmt"
"math/big"
)

type JournalEntryType uint8

const (
AccountWarmedType JournalEntryType = iota
AccountDestroyedType
AccountTouchedType
BalanceTransferType
NonceChangeType
AccountCreatedType
StorageChangedType
StorageWarmedType
TransientStorageChangeType
CodeChangeType
)

// JournalEntry represents a journal entry with various fields.
type JournalEntry struct {
Type JournalEntryType `json:"type"`
Address Address `json:"address"`
Target Address `json:"target,omitempty"` // Used for AccountDestroyed
WasDestroyed bool `json:"was_destroyed,omitempty"` // Used for AccountDestroyed
HadBalance U256 `json:"had_balance,omitempty"` // Used for AccountDestroyed
Balance U256 `json:"balance,omitempty"` // Used for BalanceTransfer
From Address `json:"from,omitempty"` // Used for BalanceTransfer
To Address `json:"to,omitempty"` // Used for BalanceTransfer
Key U256 `json:"key,omitempty"` // Used for Storage operations
HadValue U256 `json:"had_value,omitempty"` // Used for Storage operations
}

// MarshalJSON implements the json.Marshaler interface for JournalEntry.
func (j JournalEntry) MarshalJSON() ([]byte, error) {
type Alias JournalEntry // Create an alias to avoid recursion

// Helper function to convert U256 to hex string
u256ToHex := func(u U256) string {
return fmt.Sprintf("0x%s", (*big.Int)(u).Text(16))
}

return json.Marshal(&struct {
Address string `json:"address"`
Target string `json:"target,omitempty"`
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Key string `json:"key,omitempty"`
HadBalance string `json:"had_balance,omitempty"`
Balance string `json:"balance,omitempty"`
HadValue string `json:"had_value,omitempty"`
*Alias
}{
Address: "0x" + fmt.Sprintf("%x", j.Address.Addr[:]), // Convert to hex string
Target: "0x" + fmt.Sprintf("%x", j.Target.Addr[:]), // Convert to hex string
From: "0x" + fmt.Sprintf("%x", j.From.Addr[:]), // Convert to hex string
To: "0x" + fmt.Sprintf("%x", j.To.Addr[:]), // Convert to hex string
Key: u256ToHex(j.Key), // Convert U256 to hex string
HadBalance: u256ToHex(j.HadBalance), // Convert U256 to hex string
Balance: u256ToHex(j.Balance), // Convert U256 to hex string
HadValue: u256ToHex(j.HadValue), // Convert U256 to hex string
Alias: (*Alias)(&j), // Embed the original struct
})
}

func NewAccountWarmedEntry(address Address) *JournalEntry {
return &JournalEntry{
Type: AccountWarmedType,
Address: address,
}
}

// NewAccountDestroyedEntry creates a new journal entry for destroying an account
func NewAccountDestroyedEntry(address, target Address, wasDestroyed bool, hadBalance U256) *JournalEntry {
return &JournalEntry{
Type: AccountDestroyedType,
Address: address,
Target: target,
WasDestroyed: wasDestroyed,
HadBalance: new(big.Int).Set(hadBalance), //to avoid mutating the original value (had balance not written directly)
}
}

// NewAccountTouchedEntry creates a new journal entry for touching an account
func NewAccountTouchedEntry(address Address) *JournalEntry {
return &JournalEntry{
Type: AccountTouchedType,
Address: address,
}
}

// NewBalanceTransferEntry creates a new journal entry for balance transfer
func NewBalanceTransferEntry(from, to Address, balance U256) *JournalEntry {
return &JournalEntry{
Type: BalanceTransferType,
From: from,
To: to,
Balance: new(big.Int).Set(balance),
}
}

// NewNonceChangeEntry creates a new journal entry for nonce change
func NewNonceChangeEntry(address Address) *JournalEntry {
return &JournalEntry{
Type: NonceChangeType,
Address: address,
}
}

// NewAccountCreatedEntry creates a new journal entry for account creation
func NewAccountCreatedEntry(address Address) *JournalEntry {
return &JournalEntry{
Type: AccountCreatedType,
Address: address,
}
}

// NewStorageChangedEntry creates a new journal entry for storage change
func NewStorageChangedEntry(address Address, key, hadValue U256) *JournalEntry {
return &JournalEntry{
Type: StorageChangedType,
Address: address,
Key: new(big.Int).Set(key),
HadValue: new(big.Int).Set(hadValue),
}
}

// NewStorageWarmedEntry creates a new journal entry for storage warming
func NewStorageWarmedEntry(address Address, key U256) *JournalEntry {
return &JournalEntry{
Type: StorageWarmedType,
Address: address,
Key: new(big.Int).Set(key),
}
}

// NewTransientStorageChangeEntry creates a new journal entry for transient storage change
func NewTransientStorageChangeEntry(address Address, key, hadValue U256) *JournalEntry {
return &JournalEntry{
Type: TransientStorageChangeType,
Address: address,
Key: new(big.Int).Set(key),
HadValue: new(big.Int).Set(hadValue),
}
}

// NewCodeChangeEntry creates a new journal entry for code change
func NewCodeChangeEntry(address Address) *JournalEntry {
return &JournalEntry{
Type: CodeChangeType,
Address: address,
}
}
164 changes: 164 additions & 0 deletions execution/evm/journal_entry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package evm

import (
"encoding/hex"
"encoding/json"
"math/big"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

// HexToAddress converts a hex string to an Address type
func HexToAddress(hexStr string) Address {
var addr Address
bytes, err := hex.DecodeString(hexStr[2:]) // Remove '0x' prefix
if err == nil && len(bytes) == 20 {
var bytesNew [20]byte
copy(bytesNew[:], bytes)
addr = Address{
Addr: bytesNew,
}
}
return addr
}

// Helper function to create U256 values
func newU256(value int64) *big.Int {
return big.NewInt(value)
}

func TestNewAccountWarmedEntry(t *testing.T) {
address := Address{}
entry := NewAccountWarmedEntry(address)

assert.Equal(t, AccountWarmedType, entry.Type, "Type should be AccountWarmedType")
assert.Equal(t, address, entry.Address, "Address should match")
}

func TestNewAccountDestroyedEntry(t *testing.T) {
address := HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
target := HexToAddress("0x5678567856785678567856785678567856785678")
hadBalance := newU256(100)
entry := NewAccountDestroyedEntry(address, target, true, hadBalance)

assert.Equal(t, AccountDestroyedType, entry.Type, "Type should be AccountDestroyedType")
assert.Equal(t, address, entry.Address, "Address should match")
assert.Equal(t, target, entry.Target, "Target should match")
assert.True(t, entry.WasDestroyed, "WasDestroyed should be true")
assert.Equal(t, hadBalance, entry.HadBalance, "HadBalance should match")
}

func TestNewAccountTouchedEntry(t *testing.T) {
address := HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
entry := NewAccountTouchedEntry(address)

assert.Equal(t, AccountTouchedType, entry.Type, "Type should be AccountTouchedType")
assert.Equal(t, address, entry.Address, "Address should match")
}

func TestNewBalanceTransferEntry(t *testing.T) {
from := HexToAddress("0x1111111111111111111111111111111111111111")
to := HexToAddress("0x2222222222222222222222222222222222222222")
balance := newU256(50)
entry := NewBalanceTransferEntry(from, to, balance)

assert.Equal(t, BalanceTransferType, entry.Type, "Type should be BalanceTransferType")
assert.Equal(t, from, entry.From, "From address should match")
assert.Equal(t, to, entry.To, "To address should match")
assert.Equal(t, balance, entry.Balance, "Balance should match")
}

func TestNewNonceChangeEntry(t *testing.T) {
address := HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
entry := NewNonceChangeEntry(address)

assert.Equal(t, NonceChangeType, entry.Type, "Type should be NonceChangeType")
assert.Equal(t, address, entry.Address, "Address should match")
}

func TestNewAccountCreatedEntry(t *testing.T) {
address := HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
entry := NewAccountCreatedEntry(address)

assert.Equal(t, AccountCreatedType, entry.Type, "Type should be AccountCreatedType")
assert.Equal(t, address, entry.Address, "Address should match")
}

func TestNewStorageChangedEntry(t *testing.T) {
address := HexToAddress("0x3333333333333333333333333333333333333333")
key := newU256(1)
hadValue := newU256(10)
entry := NewStorageChangedEntry(address, key, hadValue)

assert.Equal(t, StorageChangedType, entry.Type, "Type should be StorageChangedType")
assert.Equal(t, address, entry.Address, "Address should match")
assert.Equal(t, key, entry.Key, "Key should match")
assert.Equal(t, hadValue, entry.HadValue, "HadValue should match")
}

func TestNewStorageWarmedEntry(t *testing.T) {
address := HexToAddress("0x3333333333333333333333333333333333333333")
key := newU256(1)
entry := NewStorageWarmedEntry(address, key)

assert.Equal(t, StorageWarmedType, entry.Type, "Type should be StorageWarmedType")
assert.Equal(t, address, entry.Address, "Address should match")
assert.Equal(t, key, entry.Key, "Key should match")
}

func TestNewTransientStorageChangeEntry(t *testing.T) {
address := HexToAddress("0x4444444444444444444444444444444444444444")
key := newU256(5)
hadValue := newU256(20)
entry := NewTransientStorageChangeEntry(address, key, hadValue)

assert.Equal(t, TransientStorageChangeType, entry.Type, "Type should be TransientStorageChangeType")
assert.Equal(t, address, entry.Address, "Address should match")
assert.Equal(t, key, entry.Key, "Key should match")
assert.Equal(t, hadValue, entry.HadValue, "HadValue should match")
}

func TestNewCodeChangeEntry(t *testing.T) {
address := HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
entry := NewCodeChangeEntry(address)

assert.Equal(t, CodeChangeType, entry.Type, "Type should be CodeChangeType")
assert.Equal(t, address, entry.Address, "Address should match")
}

func TestJournalEntryMarshalJSON(t *testing.T) {
// Create an example JournalEntry object
entry := JournalEntry{
Type: 1,
Address: Address{Addr: [20]byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}},
Target: Address{Addr: [20]byte{0x56, 0x78, 0x56, 0x78, 0x56, 0x78, 0x56, 0x78}},
WasDestroyed: true,
HadBalance: big.NewInt(100),
Balance: big.NewInt(200),
From: Address{Addr: [20]byte{0x00, 0x00, 0x00, 0x00}},
To: Address{Addr: [20]byte{0x00, 0x00, 0x00, 0x00}},
Key: big.NewInt(300),
HadValue: big.NewInt(400),
}

// Marshal the entry to JSON
actualJSON, err := json.Marshal(entry)
if err != nil {
t.Fatalf("Failed to marshal JournalEntry to JSON: %v", err)
}

// Define the expected JSON output with hex strings
expectedJSON := `{"address":"0x1234567890abcdef000000000000000000000000","target":"0x5678567856785678000000000000000000000000","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","key":"0x12c","had_balance":"0x64","balance":"0xc8","had_value":"0x190","type":1,"was_destroyed":true}`

// Compare actual JSON with expected JSON
if string(actualJSON) != expectedJSON {
t.Errorf("Expected JSON does not match actual JSON.\nExpected: %s\nActual: %s", expectedJSON, actualJSON)
}
}

// Helper function to compare two JSON objects
func compareJSON(a, b map[string]interface{}) bool {
return reflect.DeepEqual(a, b)
}
Loading

0 comments on commit 89802f0

Please sign in to comment.