Skip to content

Commit

Permalink
Merge pull request #2 from rahul0tripathi/ft-block-producer
Browse files Browse the repository at this point in the history
Ft block producer
  • Loading branch information
rahul0tripathi authored May 31, 2024
2 parents bf0b54e + 60f620a commit 040d0b4
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 30 deletions.
24 changes: 12 additions & 12 deletions entity/dirty_state.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package entity

import "github.com/ethereum/go-ethereum/core/types"

type DirtyState struct {
accountStorage *AccountsStorage
accountState *AccountsState
transactionsState *TransactionStorage
blockStorage *BlockStorage
accountStorage *AccountsStorage
accountState *AccountsState
logs LogStorage
}

func NewDirtyState() *DirtyState {
return &DirtyState{
accountStorage: NewAccountsStorage(),
accountState: NewAccountsState(),
transactionsState: NewTransactionStorage(),
blockStorage: NewBlockStorage(),
accountStorage: NewAccountsStorage(),
accountState: NewAccountsState(),
logs: make(LogStorage, 0),
}
}

Expand All @@ -24,10 +24,10 @@ func (ds *DirtyState) GetAccountState() *AccountsState {
return ds.accountState
}

func (ds *DirtyState) GetTransactionsState() *TransactionStorage {
return ds.transactionsState
func (ds *DirtyState) AddLog(log *types.Log) {
ds.logs = append(ds.logs, log)
}

func (ds *DirtyState) GetBlockStorage() *BlockStorage {
return ds.blockStorage
func (ds *DirtyState) Logs() LogStorage {
return ds.logs
}
2 changes: 2 additions & 0 deletions entity/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ func (ts *TransactionStorage) Apply(s *TransactionStorage) {
ts.receipts[hash] = v
}
}

type LogStorage []*types.Log
101 changes: 89 additions & 12 deletions executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,76 @@ package executor

import (
"context"
"fmt"
"math/big"
"sync"
"time"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/holiman/uint256"
"github.com/rahul0tripathi/smelter/config"
"github.com/rahul0tripathi/smelter/entity"
"github.com/rahul0tripathi/smelter/fork"
"github.com/rahul0tripathi/smelter/producer"
"github.com/rahul0tripathi/smelter/statedb"
"github.com/rahul0tripathi/smelter/vm"
)

type SerialExecutor struct {
mu sync.RWMutex
db *fork.DB
cfg *config.Config
provider entity.ChainStateReader
mu sync.RWMutex
db *fork.DB
cfg *config.Config
provider entity.ChainStateReader
txn *entity.TransactionStorage
blocks *entity.BlockStorage
prevBlockHash common.Hash
prevBlockNum uint64
}

func NewExecutor(cfg *config.Config, db *fork.DB, provider entity.ChainStateReader) *SerialExecutor {
return &SerialExecutor{
func NewExecutor(
ctx context.Context,
cfg *config.Config,
db *fork.DB,
provider entity.ChainStateReader,
) (*SerialExecutor, error) {
e := &SerialExecutor{
db: db,
cfg: cfg,
provider: provider,
txn: entity.NewTransactionStorage(),
blocks: entity.NewBlockStorage(),
}

blockNum, err := provider.BlockNumber(ctx)
if err != nil {
return nil, err
}

block, err := provider.BlockByNumber(ctx, new(big.Int).SetUint64(blockNum))
if err != nil {
return nil, err
}

e.prevBlockNum = blockNum
e.prevBlockHash = block.Hash()
return e, nil
}

func (e *SerialExecutor) CallAndPersist(
ctx context.Context,
tx ethereum.CallMsg,
hooks *tracing.Hooks,
overrides entity.StateOverrides,
) (ret []byte, leftOverGas uint64, err error) {
) (txHash *common.Hash, ret []byte, leftOverGas uint64, err error) {
e.mu.Lock()
defer e.mu.Unlock()
// TODO: use block from state

executionDB := statedb.NewDB(ctx, e.db)
chainCfg, evmCfg := e.cfg.ExecutionConfig(hooks)
if err = executionDB.ApplyOverrides(overrides); err != nil {
return nil, 0, err
return nil, nil, 0, err
}

env := vm.NewEVM(e.cfg.BlockContext(new(big.Int).Add(e.cfg.ForkConfig.ForkBlock, new(big.Int).SetUint64(1)),
Expand All @@ -61,14 +89,51 @@ func (e *SerialExecutor) CallAndPersist(
tx.Gas,
value,
)

if err != nil {
return
}

txHash = e.roll(ctx, tx, leftOverGas, executionDB)
return
}

func (e *SerialExecutor) roll(
ctx context.Context,
msg ethereum.CallMsg,
left uint64,
executionDB *statedb.StateDB,
) *common.Hash {
e.db.ApplyStorage(executionDB.Dirty().GetAccountStorage())
e.db.ApplyState(executionDB.Dirty().GetAccountState())
return

nonce, err := e.db.GetNonce(ctx, msg.From)
if err != nil {
fmt.Println(err)
nonce = 0
}
if err = e.db.SetNonce(ctx, msg.From, nonce+1); err != nil {
fmt.Println(err)
}

tx := producer.NewTransactionContext(nonce+1, msg)

hash, block, err := producer.MineBlockWithSignleTransaction(
tx,
left,
new(big.Int).SetUint64(e.prevBlockNum),
e.prevBlockHash,
executionDB.Dirty(),
e.txn, e.blocks)
if err != nil {
fmt.Println(err)
return nil
}

e.prevBlockHash = hash
e.prevBlockNum = block.Uint64()

txHash := tx.Hash()
return &txHash
}

func (e *SerialExecutor) Call(
Expand All @@ -79,7 +144,7 @@ func (e *SerialExecutor) Call(
) (ret []byte, leftOverGas uint64, err error) {
e.mu.Lock()
defer e.mu.Unlock()
// TODO: use block from state

executionDB := statedb.NewDB(ctx, e.db)
if err = executionDB.ApplyOverrides(overrides); err != nil {
return nil, 0, err
Expand All @@ -104,3 +169,15 @@ func (e *SerialExecutor) Call(

return
}

func (e *SerialExecutor) TxnStorage() *entity.TransactionStorage {
return e.txn
}

func (e *SerialExecutor) BlockStorage() *entity.BlockStorage {
return e.blocks
}

func (e *SerialExecutor) Latest() (common.Hash, uint64) {
return e.prevBlockHash, e.prevBlockNum
}
8 changes: 8 additions & 0 deletions fork/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ func (db *DB) GetNonce(ctx context.Context, addr common.Address) (uint64, error)
return db.accountState.GetNonce(addr), nil
}

func (db *DB) SetNonce(ctx context.Context, addr common.Address, nonce uint64) error {
if err := db.CreateState(ctx, addr); err != nil {
return err
}
db.accountState.SetNonce(addr, nonce)
return nil
}

func (db *DB) GetCodeHash(ctx context.Context, addr common.Address) (common.Hash, error) {
code, err := db.GetCode(ctx, addr)
if err != nil {
Expand Down
54 changes: 54 additions & 0 deletions producer/block_producer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package producer

import (
"math/big"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/rahul0tripathi/smelter/entity"
)

func NewTransactionContext(nonce uint64, msg ethereum.CallMsg) *types.Transaction {
return types.NewTx(&types.LegacyTx{
Nonce: nonce,
GasPrice: msg.GasPrice,
Gas: msg.Gas,
To: msg.To,
Value: msg.Value,
Data: msg.Data,
})
}

func MineBlockWithSignleTransaction(
tx *types.Transaction,
left uint64,
prevBlockNumber *big.Int,
prevBlockHash common.Hash,
db postExecutionStateFetcher,
txStore transactionStorage,
blockStore blockStorage,
) (common.Hash, *big.Int, error) {
blockNumber := new(big.Int).Add(prevBlockNumber, new(big.Int).SetUint64(1))
receipt := &types.Receipt{
Type: tx.Type(),
Status: 1,
CumulativeGasUsed: tx.Gas() - left,
// TODO: create logs bloom
Bloom: types.Bloom{},
Logs: db.Logs(),
TxHash: tx.Hash(),
ContractAddress: *tx.To(),
GasUsed: tx.Gas() - left,
EffectiveGasPrice: tx.GasPrice(),
BlockNumber: blockNumber,
TransactionIndex: 0,
}

block := entity.NewBlock(prevBlockHash, blockNumber, types.Transactions{tx}, types.Receipts{receipt})
receipt.BlockHash = block.Hash()
txStore.AddTransaction(tx)
txStore.AddReceipt(receipt)
blockStore.AddBlock(block)
return block.Hash(), blockNumber, nil
}
19 changes: 19 additions & 0 deletions producer/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package producer

import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/rahul0tripathi/smelter/entity"
)

type transactionStorage interface {
AddTransaction(tx *types.Transaction)
AddReceipt(receipt *types.Receipt)
}

type postExecutionStateFetcher interface {
Logs() entity.LogStorage
}

type blockStorage interface {
AddBlock(block *types.Block)
}
2 changes: 1 addition & 1 deletion statedb/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (s *StateDB) Snapshot() int {
}

func (s *StateDB) AddLog(log *types.Log) {
s.errorStack = append(s.errorStack, errors.New("unimplemented AddLog()"))
s.dirty.AddLog(log)
}

func (s *StateDB) AddPreimage(hash common.Hash, data []byte) {
Expand Down
Loading

0 comments on commit 040d0b4

Please sign in to comment.