mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Add method to include Bundles
This commit is contained in:
parent
9b2bee565d
commit
93ef61bfad
6 changed files with 133 additions and 0 deletions
|
|
@ -2,11 +2,22 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Bundle struct {
|
||||||
|
BlockNumber *big.Int `json:"blockNumber,omitempty"` // if BlockNumber is set it must match DecryptionCondition!
|
||||||
|
MaxBlock *big.Int `json:"maxBlock,omitempty"`
|
||||||
|
Txs types.Transactions `json:"txs"`
|
||||||
|
RevertingHashes []common.Hash `json:"revertingHashes,omitempty"`
|
||||||
|
RefundPercent *int `json:"percent,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type API interface {
|
type API interface {
|
||||||
NewSession(ctx context.Context) (string, error)
|
NewSession(ctx context.Context) (string, error)
|
||||||
AddTransaction(ctx context.Context, sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error)
|
AddTransaction(ctx context.Context, sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error)
|
||||||
|
AddBundle(ctx context.Context, sessionId string, bundle Bundle) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,7 @@ func (a *APIClient) AddTransaction(ctx context.Context, sessionId string, tx *ty
|
||||||
err := a.rpc.CallContext(ctx, &receipt, "suavex_addTransaction", sessionId, tx)
|
err := a.rpc.CallContext(ctx, &receipt, "suavex_addTransaction", sessionId, tx)
|
||||||
return receipt, err
|
return receipt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *APIClient) AddBundle(ctx context.Context, sessionId string, bundle Bundle) error {
|
||||||
|
return a.rpc.CallContext(ctx, nil, "suavex_addBundle", sessionId, bundle)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
type SessionManager interface {
|
type SessionManager interface {
|
||||||
NewSession(context.Context) (string, error)
|
NewSession(context.Context) (string, error)
|
||||||
AddTransaction(sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error)
|
AddTransaction(sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error)
|
||||||
|
AddBundle(sessionId string, bundle Bundle) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(s SessionManager) *Server {
|
func NewServer(s SessionManager) *Server {
|
||||||
|
|
@ -31,6 +32,10 @@ func (s *Server) AddTransaction(ctx context.Context, sessionId string, tx *types
|
||||||
return s.sessionMngr.AddTransaction(sessionId, tx)
|
return s.sessionMngr.AddTransaction(sessionId, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddBundle(ctx context.Context, sessionId string, bundle Bundle) error {
|
||||||
|
return s.sessionMngr.AddBundle(sessionId, bundle)
|
||||||
|
}
|
||||||
|
|
||||||
type MockServer struct {
|
type MockServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,3 +46,7 @@ func (s *MockServer) NewSession(ctx context.Context) (string, error) {
|
||||||
func (s *MockServer) AddTransaction(ctx context.Context, sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error) {
|
func (s *MockServer) AddTransaction(ctx context.Context, sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error) {
|
||||||
return &types.SimulateTransactionResult{}, nil
|
return &types.SimulateTransactionResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MockServer) AddBundle(ctx context.Context, sessionId string, bundle Bundle) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,7 @@ func (nullSessionManager) NewSession(ctx context.Context) (string, error) {
|
||||||
func (nullSessionManager) AddTransaction(sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error) {
|
func (nullSessionManager) AddTransaction(sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error) {
|
||||||
return &types.SimulateTransactionResult{Logs: []*types.SimulatedLog{}}, nil
|
return &types.SimulateTransactionResult{Logs: []*types.SimulatedLog{}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (nullSessionManager) AddBundle(sessionId string, bundle Bundle) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
package builder
|
package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/suave/builder/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type builder struct {
|
type builder struct {
|
||||||
|
|
@ -16,6 +20,7 @@ type builder struct {
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
gasPool *core.GasPool
|
gasPool *core.GasPool
|
||||||
gasUsed *uint64
|
gasUsed *uint64
|
||||||
|
signer types.Signer
|
||||||
}
|
}
|
||||||
|
|
||||||
type builderConfig struct {
|
type builderConfig struct {
|
||||||
|
|
@ -34,9 +39,100 @@ func newBuilder(config *builderConfig) *builder {
|
||||||
state: config.preState.Copy(),
|
state: config.preState.Copy(),
|
||||||
gasPool: &gp,
|
gasPool: &gp,
|
||||||
gasUsed: &gasUsed,
|
gasUsed: &gasUsed,
|
||||||
|
signer: types.MakeSigner(config.config, config.header.Number, config.header.Time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *builder) takeSnapshot() func() {
|
||||||
|
indx := len(b.txns)
|
||||||
|
snap := b.state.Snapshot()
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
b.txns = b.txns[:indx]
|
||||||
|
b.receipts = b.receipts[:indx]
|
||||||
|
b.state.RevertToSnapshot(snap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) AddBundle(bundle api.Bundle) error {
|
||||||
|
revertFn := b.takeSnapshot()
|
||||||
|
|
||||||
|
// create ephemeral addr and private key for payment txn
|
||||||
|
ephemeralPrivKey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ephemeralAddr := crypto.PubkeyToAddress(ephemeralPrivKey.PublicKey)
|
||||||
|
|
||||||
|
// Assume static 28000 gas transfers for both mev-share and proposer payments
|
||||||
|
refundTransferCost := new(big.Int).Mul(big.NewInt(28000), b.config.header.BaseFee)
|
||||||
|
|
||||||
|
// apply bundle
|
||||||
|
profitPreBundle := b.state.GetBalance(b.config.header.Coinbase)
|
||||||
|
if err := b.AddTransactions(bundle.Txs); err != nil {
|
||||||
|
revertFn()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
profitPostBundle := b.state.GetBalance(b.config.header.Coinbase)
|
||||||
|
|
||||||
|
// calc & refund user if bundle has multiple txns and wants refund
|
||||||
|
if len(bundle.Txs) > 1 && bundle.RefundPercent != nil {
|
||||||
|
// Note: PoC logic, this could be gamed by not sending any eth to coinbase
|
||||||
|
refundPrct := *bundle.RefundPercent
|
||||||
|
if refundPrct == 0 {
|
||||||
|
// default refund
|
||||||
|
refundPrct = 10
|
||||||
|
}
|
||||||
|
bundleProfit := new(big.Int).Sub(profitPostBundle, profitPreBundle)
|
||||||
|
refundAmt := new(big.Int).Div(bundleProfit, big.NewInt(int64(refundPrct)))
|
||||||
|
// subtract payment txn transfer costs
|
||||||
|
refundAmt = new(big.Int).Sub(refundAmt, refundTransferCost)
|
||||||
|
|
||||||
|
currNonce := b.state.GetNonce(ephemeralAddr)
|
||||||
|
|
||||||
|
// HACK to include payment txn
|
||||||
|
// multi refund block untested
|
||||||
|
userTx := bundle.Txs[0] // NOTE : assumes first txn is refund recipient
|
||||||
|
refundAddr, err := types.Sender(types.LatestSignerForChainID(userTx.ChainId()), userTx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
paymentTx, err := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||||
|
Nonce: currNonce,
|
||||||
|
To: &refundAddr,
|
||||||
|
Value: refundAmt,
|
||||||
|
Gas: 28000,
|
||||||
|
GasPrice: b.config.header.BaseFee,
|
||||||
|
}), b.signer, ephemeralPrivKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// commit payment txn
|
||||||
|
if _, err := b.AddTransaction(paymentTx); err != nil {
|
||||||
|
revertFn()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) AddTransactions(txns types.Transactions) error {
|
||||||
|
revertFn := b.takeSnapshot()
|
||||||
|
|
||||||
|
for _, txn := range txns {
|
||||||
|
if _, err := b.AddTransaction(txn); err != nil {
|
||||||
|
revertFn()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *builder) AddTransaction(txn *types.Transaction) (*types.SimulateTransactionResult, error) {
|
func (b *builder) AddTransaction(txn *types.Transaction) (*types.SimulateTransactionResult, error) {
|
||||||
dummyAuthor := common.Address{}
|
dummyAuthor := common.Address{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/suave/builder/api"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -162,6 +163,14 @@ func (s *SessionManager) AddTransaction(sessionId string, tx *types.Transaction)
|
||||||
return builder.AddTransaction(tx)
|
return builder.AddTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SessionManager) AddBundle(sessionId string, bundle api.Bundle) error {
|
||||||
|
builder, err := s.getSession(sessionId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return builder.AddBundle(bundle)
|
||||||
|
}
|
||||||
|
|
||||||
// CalcBaseFee calculates the basefee of the header.
|
// CalcBaseFee calculates the basefee of the header.
|
||||||
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||||
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue