generated from rollkit/template-da-repo
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
891 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
package execution | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/big" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
"github.com/ethereum/go-ethereum/rpc" | ||
execution "github.com/rollkit/go-execution" | ||
rollkitTypes "github.com/rollkit/rollkit/types" | ||
) | ||
|
||
// Define necessary types and constants | ||
type PayloadStatus string | ||
|
||
const ( | ||
PayloadStatusValid PayloadStatus = "VALID" | ||
PayloadStatusInvalid PayloadStatus = "INVALID" | ||
PayloadStatusSyncing PayloadStatus = "SYNCING" | ||
) | ||
|
||
var ( | ||
ErrNilPayloadStatus = errors.New("nil payload status") | ||
ErrInvalidPayloadStatus = errors.New("invalid payload status") | ||
) | ||
|
||
type EngineAPIExecutionClient struct { | ||
ethClient *ethclient.Client | ||
engineClient *rpc.Client | ||
genesisHash common.Hash | ||
feeRecipient common.Address | ||
} | ||
|
||
// NewEngineAPIExecutionClient creates a new instance of EngineAPIExecutionClient. | ||
func NewEngineAPIExecutionClient(ethURL, engineURL string, genesisHash common.Hash, feeRecipient common.Address) (*EngineAPIExecutionClient, error) { | ||
ethClient, err := ethclient.Dial(ethURL) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to connect to Ethereum client: %w", err) | ||
} | ||
engineClient, err := rpc.Dial(engineURL) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to connect to Engine API: %w", err) | ||
} | ||
return &EngineAPIExecutionClient{ | ||
ethClient: ethClient, | ||
engineClient: engineClient, | ||
genesisHash: genesisHash, | ||
feeRecipient: feeRecipient, | ||
}, nil | ||
} | ||
|
||
var _ execution.Execute = (*EngineAPIExecutionClient)(nil) | ||
|
||
// InitChain initializes the blockchain with genesis information. | ||
func (c *EngineAPIExecutionClient) InitChain( | ||
genesisTime time.Time, | ||
initialHeight uint64, | ||
chainID string, | ||
) (rollkitTypes.Hash, uint64, error) { | ||
ctx := context.Background() | ||
var forkchoiceResult map[string]interface{} | ||
err := c.engineClient.CallContext(ctx, &forkchoiceResult, "engine_forkchoiceUpdatedV1", | ||
map[string]interface{}{ | ||
"headBlockHash": c.genesisHash, | ||
"safeBlockHash": c.genesisHash, | ||
"finalizedBlockHash": c.genesisHash, | ||
}, | ||
map[string]interface{}{ | ||
"timestamp": genesisTime.Unix(), | ||
"prevRandao": common.Hash{}, // TO-DO | ||
"suggestedFeeRecipient": c.feeRecipient, | ||
}, | ||
) | ||
if err != nil { | ||
return rollkitTypes.Hash{}, 0, fmt.Errorf("engine_forkchoiceUpdatedV1 failed: %w", err) | ||
} | ||
payloadID, ok := forkchoiceResult["payloadId"].(string) | ||
if !ok { | ||
return rollkitTypes.Hash{}, 0, ErrNilPayloadStatus | ||
} | ||
var payload map[string]interface{} | ||
err = c.engineClient.CallContext(ctx, &payload, "engine_getPayloadV1", payloadID) | ||
if err != nil { | ||
return rollkitTypes.Hash{}, 0, fmt.Errorf("engine_getPayloadV1 failed: %w", err) | ||
} | ||
stateRoot := common.HexToHash(payload["stateRoot"].(string)) | ||
gasLimit := uint64(payload["gasLimit"].(float64)) | ||
var rollkitStateRoot rollkitTypes.Hash | ||
copy(rollkitStateRoot[:], stateRoot[:]) | ||
return rollkitStateRoot, gasLimit, nil | ||
} | ||
|
||
// GetTxs retrieves transactions from the transaction pool. | ||
func (c *EngineAPIExecutionClient) GetTxs() ([]rollkitTypes.Tx, error) { | ||
ctx := context.Background() | ||
var result struct { | ||
Pending map[string]map[string]*types.Transaction `json:"pending"` | ||
Queued map[string]map[string]*types.Transaction `json:"queued"` | ||
} | ||
err := c.ethClient.Client().CallContext(ctx, &result, "txpool_content") | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get tx pool content: %w", err) | ||
} | ||
var txs []rollkitTypes.Tx | ||
for _, accountTxs := range result.Pending { | ||
for _, tx := range accountTxs { | ||
txBytes, err := tx.MarshalBinary() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to marshal transaction: %w", err) | ||
} | ||
txs = append(txs, rollkitTypes.Tx(txBytes)) | ||
} | ||
} | ||
for _, accountTxs := range result.Queued { | ||
for _, tx := range accountTxs { | ||
txBytes, err := tx.MarshalBinary() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to marshal transaction: %w", err) | ||
} | ||
txs = append(txs, rollkitTypes.Tx(txBytes)) | ||
} | ||
} | ||
return txs, nil | ||
} | ||
|
||
// ExecuteTxs executes the given transactions and returns the new state root and gas used. | ||
func (c *EngineAPIExecutionClient) ExecuteTxs( | ||
txs []rollkitTypes.Tx, | ||
blockHeight uint64, | ||
timestamp time.Time, | ||
prevStateRoot rollkitTypes.Hash, | ||
) (rollkitTypes.Hash, uint64, error) { | ||
ctx := context.Background() | ||
ethTxs := make([][]byte, len(txs)) | ||
for i, tx := range txs { | ||
ethTxs[i] = tx | ||
} | ||
prevRandao := c.derivePrevRandao(blockHeight) | ||
var forkchoiceResult map[string]interface{} | ||
err := c.engineClient.CallContext(ctx, &forkchoiceResult, "engine_forkchoiceUpdatedV1", | ||
map[string]interface{}{ | ||
"headBlockHash": common.BytesToHash(prevStateRoot[:]), | ||
"safeBlockHash": common.BytesToHash(prevStateRoot[:]), | ||
"finalizedBlockHash": common.BytesToHash(prevStateRoot[:]), | ||
}, | ||
map[string]interface{}{ | ||
"timestamp": timestamp.Unix(), | ||
"prevRandao": prevRandao, | ||
"suggestedFeeRecipient": c.feeRecipient, | ||
}, | ||
) | ||
if err != nil { | ||
return rollkitTypes.Hash{}, 0, fmt.Errorf("engine_forkchoiceUpdatedV1 failed: %w", err) | ||
} | ||
payloadID, ok := forkchoiceResult["payloadId"].(string) | ||
if !ok { | ||
return rollkitTypes.Hash{}, 0, ErrNilPayloadStatus | ||
} | ||
var payload map[string]interface{} | ||
err = c.engineClient.CallContext(ctx, &payload, "engine_getPayloadV1", payloadID) | ||
if err != nil { | ||
return rollkitTypes.Hash{}, 0, fmt.Errorf("engine_getPayloadV1 failed: %w", err) | ||
} | ||
payload["transactions"] = ethTxs | ||
var newPayloadResult map[string]interface{} | ||
err = c.engineClient.CallContext(ctx, &newPayloadResult, "engine_newPayloadV1", payload) | ||
if err != nil { | ||
return rollkitTypes.Hash{}, 0, fmt.Errorf("engine_newPayloadV1 failed: %w", err) | ||
} | ||
status, ok := newPayloadResult["status"].(string) | ||
if !ok || PayloadStatus(status) != PayloadStatusValid { | ||
return rollkitTypes.Hash{}, 0, ErrInvalidPayloadStatus | ||
} | ||
newStateRoot := common.HexToHash(payload["stateRoot"].(string)) | ||
gasUsed := uint64(payload["gasUsed"].(float64)) | ||
var rollkitNewStateRoot rollkitTypes.Hash | ||
copy(rollkitNewStateRoot[:], newStateRoot[:]) | ||
return rollkitNewStateRoot, gasUsed, nil | ||
} | ||
|
||
// SetFinal marks a block at the given height as final. | ||
func (c *EngineAPIExecutionClient) SetFinal(blockHeight uint64) error { | ||
ctx := context.Background() | ||
block, err := c.ethClient.BlockByNumber(ctx, big.NewInt(int64(blockHeight))) | ||
if err != nil { | ||
return fmt.Errorf("failed to get block at height %d: %w", blockHeight, err) | ||
} | ||
var result map[string]interface{} | ||
err = c.engineClient.CallContext(ctx, &result, "engine_forkchoiceUpdatedV1", | ||
map[string]interface{}{ | ||
"headBlockHash": block.Hash(), | ||
"safeBlockHash": block.Hash(), | ||
"finalizedBlockHash": block.Hash(), | ||
}, | ||
nil, // No payload attributes for finalization | ||
) | ||
if err != nil { | ||
return fmt.Errorf("engine_forkchoiceUpdatedV1 failed for finalization: %w", err) | ||
} | ||
payloadStatus, ok := result["payloadStatus"].(map[string]interface{}) | ||
if !ok { | ||
return ErrNilPayloadStatus | ||
} | ||
status, ok := payloadStatus["status"].(string) | ||
if !ok || PayloadStatus(status) != PayloadStatusValid { | ||
return ErrInvalidPayloadStatus | ||
} | ||
return nil | ||
} | ||
|
||
// derivePrevRandao generates a deterministic prevRandao value based on block height. | ||
func (c *EngineAPIExecutionClient) derivePrevRandao(blockHeight uint64) common.Hash { | ||
// TO-DO | ||
return common.BigToHash(big.NewInt(int64(blockHeight))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,107 @@ | ||
module github.com/rollkit/template-da-repo | ||
module github.com/rollkit/go-execution-evm | ||
|
||
go 1.21.0 | ||
go 1.22.8 | ||
|
||
replace github.com/rollkit/go-execution => github.com/lastdotnet/go-execution v0.0.0-20241029045146-b7513b533b24 | ||
|
||
require ( | ||
github.com/ethereum/go-ethereum v1.14.11 | ||
github.com/rollkit/go-execution v0.0.0-00010101000000-000000000000 | ||
github.com/rollkit/rollkit v0.13.7 | ||
) | ||
|
||
require ( | ||
github.com/Microsoft/go-winio v0.6.2 // indirect | ||
github.com/StackExchange/wmi v1.2.1 // indirect | ||
github.com/beorn7/perks v1.0.1 // indirect | ||
github.com/bits-and-blooms/bitset v1.13.0 // indirect | ||
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect | ||
github.com/celestiaorg/go-header v0.6.2 // indirect | ||
github.com/cespare/xxhash v1.1.0 // indirect | ||
github.com/cespare/xxhash/v2 v2.3.0 // indirect | ||
github.com/cometbft/cometbft v0.38.7 // indirect | ||
github.com/cometbft/cometbft-db v0.8.0 // indirect | ||
github.com/consensys/bavard v0.1.13 // indirect | ||
github.com/consensys/gnark-crypto v0.12.1 // indirect | ||
github.com/cosmos/gogoproto v1.5.0 // indirect | ||
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect | ||
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect | ||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | ||
github.com/deckarep/golang-set/v2 v2.6.0 // indirect | ||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect | ||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect | ||
github.com/dgraph-io/ristretto v0.1.1 // indirect | ||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect | ||
github.com/dustin/go-humanize v1.0.1 // indirect | ||
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect | ||
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect | ||
github.com/go-kit/kit v0.13.0 // indirect | ||
github.com/go-kit/log v0.2.1 // indirect | ||
github.com/go-logfmt/logfmt v0.6.0 // indirect | ||
github.com/go-ole/go-ole v1.3.0 // indirect | ||
github.com/gogo/protobuf v1.3.2 // indirect | ||
github.com/golang/glog v1.2.1 // indirect | ||
github.com/golang/protobuf v1.5.4 // indirect | ||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect | ||
github.com/google/btree v1.1.2 // indirect | ||
github.com/google/go-cmp v0.6.0 // indirect | ||
github.com/gorilla/websocket v1.5.3 // indirect | ||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect | ||
github.com/holiman/uint256 v1.3.1 // indirect | ||
github.com/ipfs/go-cid v0.4.1 // indirect | ||
github.com/ipfs/go-log/v2 v2.5.1 // indirect | ||
github.com/jmhodges/levigo v1.0.0 // indirect | ||
github.com/klauspost/compress v1.17.8 // indirect | ||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect | ||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect | ||
github.com/libp2p/go-libp2p v0.35.0 // indirect | ||
github.com/libp2p/go-libp2p-pubsub v0.11.0 // indirect | ||
github.com/libp2p/go-msgio v0.3.0 // indirect | ||
github.com/linxGnu/grocksdb v1.7.16 // indirect | ||
github.com/mattn/go-isatty v0.0.20 // indirect | ||
github.com/minio/sha256-simd v1.0.1 // indirect | ||
github.com/mmcloughlin/addchain v0.4.0 // indirect | ||
github.com/mr-tron/base58 v1.2.0 // indirect | ||
github.com/multiformats/go-base32 v0.1.0 // indirect | ||
github.com/multiformats/go-base36 v0.2.0 // indirect | ||
github.com/multiformats/go-multiaddr v0.13.0 // indirect | ||
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect | ||
github.com/multiformats/go-multibase v0.2.0 // indirect | ||
github.com/multiformats/go-multicodec v0.9.0 // indirect | ||
github.com/multiformats/go-multihash v0.2.3 // indirect | ||
github.com/multiformats/go-multistream v0.5.0 // indirect | ||
github.com/multiformats/go-varint v0.0.7 // indirect | ||
github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae // indirect | ||
github.com/onsi/ginkgo v1.16.5 // indirect | ||
github.com/onsi/gomega v1.30.0 // indirect | ||
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect | ||
github.com/pkg/errors v0.9.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect | ||
github.com/prometheus/client_golang v1.19.1 // indirect | ||
github.com/prometheus/client_model v0.6.1 // indirect | ||
github.com/prometheus/common v0.48.0 // indirect | ||
github.com/prometheus/procfs v0.12.0 // indirect | ||
github.com/sasha-s/go-deadlock v0.3.1 // indirect | ||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect | ||
github.com/spaolacci/murmur3 v1.1.0 // indirect | ||
github.com/stretchr/testify v1.9.0 // indirect | ||
github.com/supranational/blst v0.3.13 // indirect | ||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect | ||
github.com/tklauser/go-sysconf v0.3.12 // indirect | ||
github.com/tklauser/numcpus v0.6.1 // indirect | ||
go.etcd.io/bbolt v1.3.7 // indirect | ||
go.uber.org/multierr v1.11.0 // indirect | ||
go.uber.org/zap v1.27.0 // indirect | ||
golang.org/x/crypto v0.25.0 // indirect | ||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect | ||
golang.org/x/net v0.27.0 // indirect | ||
golang.org/x/sync v0.7.0 // indirect | ||
golang.org/x/sys v0.22.0 // indirect | ||
golang.org/x/text v0.16.0 // indirect | ||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect | ||
google.golang.org/grpc v1.65.0 // indirect | ||
google.golang.org/protobuf v1.34.2 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
lukechampine.com/blake3 v1.2.1 // indirect | ||
rsc.io/tmplfunc v0.0.3 // indirect | ||
) |
Oops, something went wrong.