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 (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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 {
|
||||
NewSession(ctx context.Context) (string, 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)
|
||||
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 {
|
||||
NewSession(context.Context) (string, error)
|
||||
AddTransaction(sessionId string, tx *types.Transaction) (*types.SimulateTransactionResult, error)
|
||||
AddBundle(sessionId string, bundle Bundle) error
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (s *Server) AddBundle(ctx context.Context, sessionId string, bundle Bundle) error {
|
||||
return s.sessionMngr.AddBundle(sessionId, bundle)
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
return &types.SimulateTransactionResult{Logs: []*types.SimulatedLog{}}, nil
|
||||
}
|
||||
|
||||
func (nullSessionManager) AddBundle(sessionId string, bundle Bundle) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
package builder
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/suave/builder/api"
|
||||
)
|
||||
|
||||
type builder struct {
|
||||
|
|
@ -16,6 +20,7 @@ type builder struct {
|
|||
state *state.StateDB
|
||||
gasPool *core.GasPool
|
||||
gasUsed *uint64
|
||||
signer types.Signer
|
||||
}
|
||||
|
||||
type builderConfig struct {
|
||||
|
|
@ -34,9 +39,100 @@ func newBuilder(config *builderConfig) *builder {
|
|||
state: config.preState.Copy(),
|
||||
gasPool: &gp,
|
||||
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) {
|
||||
dummyAuthor := common.Address{}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/suave/builder/api"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
|
|
@ -162,6 +163,14 @@ func (s *SessionManager) AddTransaction(sessionId string, tx *types.Transaction)
|
|||
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.
|
||||
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
||||
|
|
|
|||
Loading…
Reference in a new issue