Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testsnrefactoringof gevm #101

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions execution/evm/journal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
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

Check failure on line 39 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / test

undefined: U256

Check failure on line 39 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: U256

Check failure on line 39 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: U256
type EvmState map[common.Address]Account

Check failure on line 40 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / test

undefined: Account

Check failure on line 40 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: Account

Check failure on line 40 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: Account
type Key struct {
Account common.Address
Slot U256

Check failure on line 43 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / test

undefined: U256

Check failure on line 43 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: U256

Check failure on line 43 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: U256
}
type Log[T any] struct {
// The address which emitted this log.
Address Address `json:"address"`

Check failure on line 47 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / test

undefined: Address

Check failure on line 47 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: Address

Check failure on line 47 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: Address
// The log data.
Data T `json:"data"`
}

type LogData struct {
// The indexed topic list.
Topics []B256 `json:"topics"`

Check failure on line 54 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / test

undefined: B256

Check failure on line 54 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: B256

Check failure on line 54 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: B256
// The plain data.
Data Bytes `json:"data"`

Check failure on line 56 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / test

undefined: Bytes

Check failure on line 56 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: Bytes

Check failure on line 56 in execution/evm/journal.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: Bytes
}

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"`

Check failure on line 27 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / test

undefined: Address

Check failure on line 27 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: Address

Check failure on line 27 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: Address
Target Address `json:"target,omitempty"` // Used for AccountDestroyed

Check failure on line 28 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / test

undefined: Address

Check failure on line 28 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: Address

Check failure on line 28 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: Address
WasDestroyed bool `json:"was_destroyed,omitempty"` // Used for AccountDestroyed
HadBalance U256 `json:"had_balance,omitempty"` // Used for AccountDestroyed

Check failure on line 30 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / test

undefined: U256

Check failure on line 30 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: U256

Check failure on line 30 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: U256
Balance U256 `json:"balance,omitempty"` // Used for BalanceTransfer

Check failure on line 31 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / test

undefined: U256

Check failure on line 31 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / build (1.22.3)

undefined: U256

Check failure on line 31 in execution/evm/journal_entry.go

View workflow job for this annotation

GitHub Actions / golangci-lint (/home/runner/work/selene/selene)

undefined: U256
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
Loading