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

Add files via upload #98

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
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
55 changes: 55 additions & 0 deletions execution/journal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package evm

Check failure on line 1 in execution/journal.go

View workflow job for this annotation

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

package evm; expected package execution

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"`
}
148 changes: 148 additions & 0 deletions execution/journal_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package evm

Check failure on line 1 in execution/journal_entry.go

View workflow job for this annotation

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

package evm; expected package execution
import(
"encoding/json"
"math/big"
)
type JournalEntryType uint8
const (
AccountWarmedType JournalEntryType = iota
AccountDestroyedType
AccountTouchedType
BalanceTransferType
NonceChangeType
AccountCreatedType
StorageChangedType
StorageWarmedType
TransientStorageChangeType
CodeChangeType
)

// Creating a struct for JournalEntry containing all possible fields that might be needed
type JournalEntry struct {
Type JournalEntryType
Address Address
Target Address // Used for AccountDestroyed
WasDestroyed bool // Used for AccountDestroyed
HadBalance U256 // Used for AccountDestroyed
Balance U256 // Used for BalanceTransfer
From Address // Used for BalanceTransfer
To Address // Used for BalanceTransfer
Key U256 // Used for Storage operations
HadValue U256 // Used for Storage operations
}

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,
}
}

// MarshalJSON implements the json.Marshaler interface
func (j JournalEntry) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type JournalEntryType `json:"type"`
Address Address `json:"address"`
Target Address `json:"target,omitempty"`
WasDestroyed bool `json:"was_destroyed,omitempty"`
HadBalance U256 `json:"had_balance,omitempty"`
Balance U256 `json:"balance,omitempty"`
From Address `json:"from,omitempty"`
To Address `json:"to,omitempty"`
Key U256 `json:"key,omitempty"`
HadValue U256 `json:"had_value,omitempty"`
}{
Type: j.Type,
Address: j.Address,
Target: j.Target,
WasDestroyed: j.WasDestroyed,
HadBalance: j.HadBalance,
Balance: j.Balance,
From: j.From,
To: j.To,
Key: j.Key,
HadValue: j.HadValue,
})
}
183 changes: 183 additions & 0 deletions execution/journal_entry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
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 TestMarshalJSON(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 JSON: %v", err)
}

// Define the expected JSON output
expectedJSON := `{
"type": 1,
"address": {"Addr": [18, 52, 86, 120, 144, 171, 205, 239, 0 , 0 , 0 , 0 , 0 ,0 , 0 ,0 ,0, 0, 0, 0]},
"target": {"Addr": [86, 120, 86, 120, 86, 120, 86, 120, 0 ,0 ,0,0,0,0,0,0,0,0,0,0]},
"was_destroyed": true,
"had_balance": 100,
"balance": 200,
"from": {"Addr": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
"to": {"Addr": [0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
"key": 300,
"had_value": 400
}`

// Compare the actual JSON output to the expected JSON
var expected, actual map[string]interface{}
if err := json.Unmarshal([]byte(expectedJSON), &expected); err != nil {
t.Fatalf("Failed to unmarshal expected JSON: %v", err)
}
if err := json.Unmarshal(actualJSON, &actual); err != nil {
t.Fatalf("Failed to unmarshal actual JSON: %v", err)
}

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

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