Merge pull request #23 from jinmel/add_bundle

adds AddTransactions, AddBundle, AddBundles to the builder API
This commit is contained in:
Ferran Borreguero 2024-03-14 14:45:33 +00:00 committed by GitHub
commit cebeb5dad1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 381 additions and 21 deletions

View file

@ -22,6 +22,13 @@ import (
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
var (
ErrInvalidInclusionRange = errors.New("invalid inclusion range")
ErrInvalidBlockNumber = errors.New("invalid block number")
ErrExceedsMaxBlock = errors.New("block number exceeds max block")
ErrEmptyTxs = errors.New("empty transactions")
)
type BuilderConfig struct { type BuilderConfig struct {
ChainConfig *params.ChainConfig ChainConfig *params.ChainConfig
Engine consensus.Engine Engine consensus.Engine
@ -77,26 +84,92 @@ func NewBuilder(config *BuilderConfig, args *BuilderArgs) (*Builder, error) {
return b, nil return b, nil
} }
type SBundle struct { func (b *Builder) addTransaction(txn *types.Transaction, env *environment) (*suavextypes.SimulateTransactionResult, error) {
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"`
}
func (b *Builder) AddTransaction(txn *types.Transaction) (*suavextypes.SimulateTransactionResult, error) {
// If the context is not set, the logs will not be recorded // If the context is not set, the logs will not be recorded
b.env.state.SetTxContext(txn.Hash(), b.env.tcount) b.env.state.SetTxContext(txn.Hash(), b.env.tcount)
logs, err := b.wrk.commitTransaction(b.env, txn) prevGas := env.header.GasUsed
logs, err := b.wrk.commitTransaction(env, txn)
if err != nil { if err != nil {
return &suavextypes.SimulateTransactionResult{ return &suavextypes.SimulateTransactionResult{
Error: err.Error(), Error: err.Error(),
Success: false, Success: false,
}, nil }, err
} }
return receiptToSimResult(&types.Receipt{Logs: logs}), nil egp := env.header.GasUsed - prevGas
return receiptToSimResult(&types.Receipt{Logs: logs}, egp), nil
}
func (b *Builder) AddTransaction(txn *types.Transaction) (*suavextypes.SimulateTransactionResult, error) {
res, _ := b.addTransaction(txn, b.env)
return res, nil
}
func (b *Builder) AddTransactions(txns types.Transactions) ([]*suavextypes.SimulateTransactionResult, error) {
results := make([]*suavextypes.SimulateTransactionResult, 0)
snap := b.env.copy()
for _, txn := range txns {
res, err := b.addTransaction(txn, snap)
results = append(results, res)
if err != nil {
return results, nil
}
}
b.env = snap
return results, nil
}
func (b *Builder) addBundle(bundle *suavextypes.Bundle, env *environment) (*suavextypes.SimulateBundleResult, error) {
if err := checkBundleParams(b.env.header.Number, bundle); err != nil {
return &suavextypes.SimulateBundleResult{
Error: err.Error(),
Success: false,
}, err
}
revertingHashes := bundle.RevertingHashesMap()
egp := uint64(0)
var results []*suavextypes.SimulateTransactionResult
for _, txn := range bundle.Txs {
result, err := b.addTransaction(txn, env)
results = append(results, result)
if err != nil {
if _, ok := revertingHashes[txn.Hash()]; ok {
// continue if the transaction is in the reverting hashes
continue
}
return &suavextypes.SimulateBundleResult{
Error: err.Error(),
SimulateTransactionResults: results,
Success: false,
}, err
}
egp += result.Egp
}
return &suavextypes.SimulateBundleResult{
Egp: egp,
SimulateTransactionResults: results,
Success: true,
}, nil
}
func (b *Builder) AddBundles(bundles []*suavextypes.Bundle) ([]*suavextypes.SimulateBundleResult, error) {
var results []*suavextypes.SimulateBundleResult
snap := b.env.copy()
for _, bundle := range bundles {
result, err := b.addBundle(bundle, snap)
results = append(results, result)
if err != nil {
return results, nil
}
}
b.env = snap
return results, nil
} }
func (b *Builder) FillPending() error { func (b *Builder) FillPending() error {
@ -139,8 +212,8 @@ func (b *Builder) Bid(builderPubKey phase0.BLSPubKey) (*suavextypes.SubmitBlockR
blockBidMsg := builderV1.BidTrace{ blockBidMsg := builderV1.BidTrace{
Slot: b.args.Slot, Slot: b.args.Slot,
ParentHash: phase0.Hash32(payload.ParentHash), ParentHash: payload.ParentHash,
BlockHash: phase0.Hash32(payload.BlockHash), BlockHash: payload.BlockHash,
BuilderPubkey: builderPubKey, BuilderPubkey: builderPubKey,
ProposerPubkey: phase0.BLSPubKey(proposerPubkey), ProposerPubkey: phase0.BLSPubKey(proposerPubkey),
ProposerFeeRecipient: bellatrix.ExecutionAddress(b.args.FeeRecipient), ProposerFeeRecipient: bellatrix.ExecutionAddress(b.args.FeeRecipient),
@ -169,8 +242,9 @@ func (b *Builder) Bid(builderPubKey phase0.BLSPubKey) (*suavextypes.SubmitBlockR
return &bidRequest, nil return &bidRequest, nil
} }
func receiptToSimResult(receipt *types.Receipt) *suavextypes.SimulateTransactionResult { func receiptToSimResult(receipt *types.Receipt, egp uint64) *suavextypes.SimulateTransactionResult {
result := &suavextypes.SimulateTransactionResult{ result := &suavextypes.SimulateTransactionResult{
Egp: egp,
Success: true, Success: true,
Logs: []*suavextypes.SimulatedLog{}, Logs: []*suavextypes.SimulatedLog{},
} }
@ -223,3 +297,33 @@ func executableDataToDenebExecutionPayload(data *engine.ExecutableData) (*deneb.
Withdrawals: withdrawalData, Withdrawals: withdrawalData,
}, nil }, nil
} }
func checkBundleParams(currentBlockNumber *big.Int, bundle *suavextypes.Bundle) error {
if bundle.BlockNumber != nil && bundle.MaxBlock != nil && bundle.BlockNumber.Cmp(bundle.MaxBlock) > 0 {
return ErrInvalidInclusionRange
}
// check inclusion target if BlockNumber is set
if bundle.BlockNumber != nil {
if bundle.MaxBlock == nil && currentBlockNumber.Cmp(bundle.BlockNumber) != 0 {
return ErrInvalidBlockNumber
}
if bundle.MaxBlock != nil {
if currentBlockNumber.Cmp(bundle.MaxBlock) > 0 {
return ErrExceedsMaxBlock
}
if currentBlockNumber.Cmp(bundle.BlockNumber) < 0 {
return ErrInvalidBlockNumber
}
}
}
// check if the bundle has transactions
if bundle.Txs == nil || bundle.Txs.Len() == 0 {
return ErrEmptyTxs
}
return nil
}

View file

@ -12,9 +12,12 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
suavextypes "github.com/ethereum/go-ethereum/suave/builder/api"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -25,12 +28,13 @@ func TestBuilder_AddTxn_Simple(t *testing.T) {
builder, err := NewBuilder(config, &BuilderArgs{}) builder, err := NewBuilder(config, &BuilderArgs{})
require.NoError(t, err) require.NoError(t, err)
tx1 := backend.newRandomTx(true) tx1 := backend.newRandomTx(false)
res, err := builder.AddTransaction(tx1) res, err := builder.AddTransaction(tx1)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Success) require.True(t, res.Success)
require.Len(t, builder.env.receipts, 1) require.Len(t, builder.env.receipts, 1)
require.Equal(t, big.NewInt(1000), builder.env.state.GetBalance(testUserAddress))
// we cannot add the same transaction again. Note that by design the // we cannot add the same transaction again. Note that by design the
// function does not error but returns the SimulateTransactionResult.success = false // function does not error but returns the SimulateTransactionResult.success = false
@ -38,6 +42,150 @@ func TestBuilder_AddTxn_Simple(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.False(t, res.Success) require.False(t, res.Success)
require.Len(t, builder.env.receipts, 1) require.Len(t, builder.env.receipts, 1)
require.Equal(t, big.NewInt(1000), builder.env.state.GetBalance(testUserAddress))
}
func TestBuilder_AddTxns_Simple(t *testing.T) {
t.Parallel()
config, backend := newMockBuilderConfig(t)
builder, err := NewBuilder(config, &BuilderArgs{})
require.NoError(t, err)
tx1 := backend.newRandomTx(false)
tx2 := backend.newRandomTxWithNonce(1)
res, err := builder.AddTransactions([]*types.Transaction{tx1, tx2})
require.NoError(t, err)
require.Len(t, res, 2)
for _, r := range res {
require.True(t, r.Success)
}
require.Equal(t, big.NewInt(2000), builder.env.state.GetBalance(testUserAddress))
tx3 := backend.newRandomTxWithNonce(2)
tx4 := backend.newRandomTxWithNonce(1000) // fails with nonce too high
res, err = builder.AddTransactions([]*types.Transaction{tx3, tx4})
require.NoError(t, err)
require.Len(t, res, 2)
require.True(t, res[0].Success)
require.False(t, res[1].Success)
require.Len(t, builder.env.txs, 2)
require.Equal(t, big.NewInt(2000), builder.env.state.GetBalance(testUserAddress))
}
func TestBuilder_AddBundles_Simple(t *testing.T) {
t.Parallel()
config, backend := newMockBuilderConfig(t)
builder, err := NewBuilder(config, &BuilderArgs{})
require.NoError(t, err)
tx1 := backend.newRandomTx(false)
tx2 := backend.newRandomTxWithNonce(1)
bundle1 := &suavextypes.Bundle{
Txs: []*types.Transaction{tx1, tx2},
}
tx3 := backend.newRandomTxWithNonce(2)
tx4 := backend.newRandomTxWithNonce(3)
bundle2 := &suavextypes.Bundle{
Txs: []*types.Transaction{tx3, tx4},
}
res, err := builder.AddBundles([]*suavextypes.Bundle{bundle1, bundle2})
require.NoError(t, err)
require.Len(t, res, 2)
require.True(t, res[0].Success)
require.True(t, res[1].Success)
require.Equal(t, big.NewInt(4000), builder.env.state.GetBalance(testUserAddress))
}
func TestBuilder_AddBundles_RevertHashes(t *testing.T) {
t.Parallel()
config, backend := newMockBuilderConfig(t)
builder, err := NewBuilder(config, &BuilderArgs{})
require.NoError(t, err)
tx1 := backend.newRandomTx(false)
tx2 := backend.newRandomTxWithNonce(3) // fails with nonce too high
bundle := &suavextypes.Bundle{
Txs: []*types.Transaction{tx1, tx2},
}
res, err := builder.AddBundles([]*suavextypes.Bundle{bundle})
require.NoError(t, err)
require.Len(t, res, 1)
require.False(t, res[0].Success)
require.Len(t, res[0].SimulateTransactionResults, 2)
require.True(t, res[0].SimulateTransactionResults[0].Success)
require.False(t, res[0].SimulateTransactionResults[1].Success)
require.Equal(t, big.NewInt(0), builder.env.state.GetBalance(testUserAddress))
bundle.RevertingHashes = []common.Hash{tx2.Hash()}
res, err = builder.AddBundles([]*suavextypes.Bundle{bundle})
require.NoError(t, err)
require.Len(t, res, 1)
require.True(t, res[0].Success)
require.Len(t, res[0].SimulateTransactionResults, 2)
require.True(t, res[0].SimulateTransactionResults[0].Success)
require.False(t, res[0].SimulateTransactionResults[1].Success)
require.Equal(t, big.NewInt(1000), builder.env.state.GetBalance(testUserAddress))
}
func TestBuilder_AddBundles_InvalidParams(t *testing.T) {
t.Parallel()
config, backend := newMockBuilderConfig(t)
// set builder target block number to 10
backend.insertRandomBlocks(9)
builder, err := NewBuilder(config, &BuilderArgs{})
require.Equal(t, uint64(10), builder.env.header.Number.Uint64())
require.NoError(t, err)
tx1 := backend.newRandomTx(false)
tx2 := backend.newRandomTx(false)
bundle := &suavextypes.Bundle{
Txs: []*types.Transaction{tx1, tx2},
BlockNumber: big.NewInt(20),
}
res, err := builder.AddBundles([]*suavextypes.Bundle{bundle})
require.NoError(t, err)
require.Len(t, res, 1)
require.False(t, res[0].Success)
require.Equal(t, ErrInvalidBlockNumber.Error(), res[0].Error)
require.Len(t, res[0].SimulateTransactionResults, 0)
require.Equal(t, big.NewInt(0), builder.env.state.GetBalance(testUserAddress))
bundle = &suavextypes.Bundle{
Txs: []*types.Transaction{tx1, tx2},
BlockNumber: big.NewInt(5),
MaxBlock: big.NewInt(6),
}
res, err = builder.AddBundles([]*suavextypes.Bundle{bundle})
require.NoError(t, err)
require.Len(t, res, 1)
require.False(t, res[0].Success)
require.Equal(t, ErrExceedsMaxBlock.Error(), res[0].Error)
require.Len(t, res[0].SimulateTransactionResults, 0)
require.Equal(t, big.NewInt(0), builder.env.state.GetBalance(testUserAddress))
bundle = &suavextypes.Bundle{
Txs: []*types.Transaction{},
}
res, err = builder.AddBundles([]*suavextypes.Bundle{bundle})
require.NoError(t, err)
require.False(t, res[0].Success)
require.Equal(t, ErrEmptyTxs.Error(), res[0].Error)
require.Len(t, res[0].SimulateTransactionResults, 0)
require.Equal(t, big.NewInt(0), builder.env.state.GetBalance(testUserAddress))
} }
func TestBuilder_FillTransactions(t *testing.T) { func TestBuilder_FillTransactions(t *testing.T) {
@ -118,10 +266,8 @@ func TestBuilder_Bid(t *testing.T) {
_, err = builder.BuildBlock() _, err = builder.BuildBlock()
require.NoError(t, err) require.NoError(t, err)
req, err := builder.Bid([48]byte{}) _, err = builder.Bid([48]byte{})
require.NoError(t, err) require.NoError(t, err)
fmt.Println("-- req --", req)
} }
func newMockBuilderConfig(t *testing.T) (*BuilderConfig, *testWorkerBackend) { func newMockBuilderConfig(t *testing.T) (*BuilderConfig, *testWorkerBackend) {
@ -145,6 +291,49 @@ func newMockBuilderConfig(t *testing.T) (*BuilderConfig, *testWorkerBackend) {
return bConfig, backend return bConfig, backend
} }
func (b *testWorkerBackend) newRandomTxWithNonce(nonce uint64) *types.Transaction {
gasPrice := big.NewInt(10 * params.InitialBaseFee)
tx, _ := types.SignTx(types.NewTransaction(nonce, testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey)
return tx
}
func (b *testWorkerBackend) insertRandomBlocks(n int) []*types.Block {
extraVanity := 32
extraSeal := crypto.SignatureLength
diffInTurn := big.NewInt(2)
signer := new(types.HomesteadSigner)
_, blocks, _ := core.GenerateChainWithGenesis(b.genesis, b.chain.Engine(), n, func(i int, block *core.BlockGen) {
block.SetDifficulty(big.NewInt(2)) // diffInTurn
if i != 1 {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), common.Address{0x00}, new(big.Int), params.TxGas, block.BaseFee(), nil), signer, testBankKey)
if err != nil {
panic(err)
}
block.AddTxWithChain(b.chain, tx)
}
})
for i, block := range blocks {
header := block.Header()
if i > 0 {
header.ParentHash = blocks[i-1].Hash()
}
header.Extra = make([]byte, extraVanity+extraSeal)
header.Difficulty = diffInTurn
sig, _ := crypto.Sign(clique.SealHash(header).Bytes(), testBankKey)
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
blocks[i] = block.WithSeal(header)
}
if _, err := b.chain.InsertChain(blocks); err != nil {
panic(fmt.Sprintf("failed to insert initial blocks: %v", err))
}
return blocks
}
func (b *testWorkerBackend) newCall(to common.Address, data []byte) *types.Transaction { func (b *testWorkerBackend) newCall(to common.Address, data []byte) *types.Transaction {
gasPrice := big.NewInt(10 * params.InitialBaseFee) gasPrice := big.NewInt(10 * params.InitialBaseFee)
tx, _ := types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), to, big.NewInt(0), 1000000, gasPrice, data), types.HomesteadSigner{}, testBankKey) tx, _ := types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), to, big.NewInt(0), 1000000, gasPrice, data), types.HomesteadSigner{}, testBankKey)

View file

@ -24,6 +24,14 @@ type Bundle struct {
RefundPercent *int `json:"percent,omitempty"` RefundPercent *int `json:"percent,omitempty"`
} }
func (bundle *Bundle) RevertingHashesMap() map[common.Hash]struct{} {
m := make(map[common.Hash]struct{})
for _, hash := range bundle.RevertingHashes {
m[hash] = struct{}{}
}
return m
}
type BuildBlockArgs struct { type BuildBlockArgs struct {
Slot uint64 `json:"slot"` Slot uint64 `json:"slot"`
ProposerPubkey []byte `json:"proposerPubkey"` ProposerPubkey []byte `json:"proposerPubkey"`
@ -52,6 +60,13 @@ type SimulateTransactionResult struct {
Error string `json:"error"` Error string `json:"error"`
} }
type SimulateBundleResult struct {
Egp uint64 `json:"egp"`
SimulateTransactionResults []*SimulateTransactionResult `json:"simulateTransactionResults"`
Success bool `json:"success"`
Error string `json:"error"`
}
// field type overrides for gencodec // field type overrides for gencodec
type simulateTransactionResultMarshaling struct { type simulateTransactionResultMarshaling struct {
Egp hexutil.Uint64 Egp hexutil.Uint64
@ -77,6 +92,8 @@ type SubmitBlockRequest struct {
type API interface { type API interface {
NewSession(ctx context.Context, args *BuildBlockArgs) (string, error) NewSession(ctx context.Context, args *BuildBlockArgs) (string, error)
AddTransaction(ctx context.Context, sessionId string, tx *types.Transaction) (*SimulateTransactionResult, error) AddTransaction(ctx context.Context, sessionId string, tx *types.Transaction) (*SimulateTransactionResult, error)
AddTransactions(ctx context.Context, sessionId string, txs types.Transactions) ([]*SimulateTransactionResult, error)
AddBundles(ctx context.Context, sessionId string, bundles []*Bundle) ([]*SimulateBundleResult, error)
BuildBlock(ctx context.Context, sessionId string) error BuildBlock(ctx context.Context, sessionId string) error
Bid(ctx context.Context, sessioId string, blsPubKey phase0.BLSPubKey) (*SubmitBlockRequest, error) Bid(ctx context.Context, sessioId string, blsPubKey phase0.BLSPubKey) (*SubmitBlockRequest, error)
} }

View file

@ -42,6 +42,18 @@ func (a *APIClient) AddTransaction(ctx context.Context, sessionId string, tx *ty
return receipt, err return receipt, err
} }
func (a *APIClient) AddTransactions(ctx context.Context, sessionId string, txs types.Transactions) ([]*SimulateTransactionResult, error) {
var receipt []*SimulateTransactionResult
err := a.rpc.CallContext(ctx, &receipt, "suavex_addTransactions", sessionId, txs)
return receipt, err
}
func (a *APIClient) AddBundles(ctx context.Context, sessionId string, bundles []*Bundle) ([]*SimulateBundleResult, error) {
var receipt []*SimulateBundleResult
err := a.rpc.CallContext(ctx, &receipt, "suavex_addBundles", sessionId, bundles)
return receipt, err
}
func (a *APIClient) BuildBlock(ctx context.Context, sessionId string) error { func (a *APIClient) BuildBlock(ctx context.Context, sessionId string) error {
return a.rpc.CallContext(ctx, nil, "suavex_buildBlock", sessionId) return a.rpc.CallContext(ctx, nil, "suavex_buildBlock", sessionId)
} }

View file

@ -13,6 +13,8 @@ var _ API = (*Server)(nil)
type SessionManager interface { type SessionManager interface {
NewSession(context.Context, *BuildBlockArgs) (string, error) NewSession(context.Context, *BuildBlockArgs) (string, error)
AddTransaction(sessionId string, tx *types.Transaction) (*SimulateTransactionResult, error) AddTransaction(sessionId string, tx *types.Transaction) (*SimulateTransactionResult, error)
AddTransactions(sessionId string, txs types.Transactions) ([]*SimulateTransactionResult, error)
AddBundles(sessionId string, bundles []*Bundle) ([]*SimulateBundleResult, error)
BuildBlock(sessionId string) error BuildBlock(sessionId string) error
Bid(sessionId string, blsPubKey phase0.BLSPubKey) (*SubmitBlockRequest, error) Bid(sessionId string, blsPubKey phase0.BLSPubKey) (*SubmitBlockRequest, error)
} }
@ -36,6 +38,14 @@ 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) AddTransactions(ctx context.Context, sessionId string, txs types.Transactions) ([]*SimulateTransactionResult, error) {
return s.sessionMngr.AddTransactions(sessionId, txs)
}
func (s *Server) AddBundles(ctx context.Context, sessionId string, bundles []*Bundle) ([]*SimulateBundleResult, error) {
return s.sessionMngr.AddBundles(sessionId, bundles)
}
func (s *Server) BuildBlock(ctx context.Context, sessionId string) error { func (s *Server) BuildBlock(ctx context.Context, sessionId string) error {
return s.sessionMngr.BuildBlock(sessionId) return s.sessionMngr.BuildBlock(sessionId)
} }

View file

@ -27,6 +27,14 @@ func TestAPI(t *testing.T) {
txn := types.NewTransaction(0, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) txn := types.NewTransaction(0, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})
_, err = c.AddTransaction(context.Background(), "1", txn) _, err = c.AddTransaction(context.Background(), "1", txn)
require.NoError(t, err) require.NoError(t, err)
_, err = c.AddTransactions(context.Background(), "1", []*types.Transaction{txn})
require.NoError(t, err)
bundle := &Bundle{
Txs: []*types.Transaction{txn},
}
_, err = c.AddBundles(context.Background(), "1", []*Bundle{bundle})
require.NoError(t, err)
} }
type nullSessionManager struct{} type nullSessionManager struct{}
@ -39,8 +47,12 @@ func (nullSessionManager) AddTransaction(sessionId string, tx *types.Transaction
return &SimulateTransactionResult{Logs: []*SimulatedLog{}}, nil return &SimulateTransactionResult{Logs: []*SimulatedLog{}}, nil
} }
func (nullSessionManager) AddBundle(sessionId string, bundle Bundle) error { func (nullSessionManager) AddTransactions(sessionId string, txs types.Transactions) ([]*SimulateTransactionResult, error) {
return nil return nil, nil
}
func (nullSessionManager) AddBundles(sessionId string, bundles []*Bundle) ([]*SimulateBundleResult, error) {
return nil, nil
} }
func (nullSessionManager) BuildBlock(sessionId string) error { func (nullSessionManager) BuildBlock(sessionId string) error {

View file

@ -150,6 +150,22 @@ func (s *SessionManager) AddTransaction(sessionId string, tx *types.Transaction)
return builder.AddTransaction(tx) return builder.AddTransaction(tx)
} }
func (s *SessionManager) AddTransactions(sessionId string, txs types.Transactions) ([]*api.SimulateTransactionResult, error) {
builder, err := s.getSession(sessionId)
if err != nil {
return nil, err
}
return builder.AddTransactions(txs)
}
func (s *SessionManager) AddBundles(sessionId string, bundles []*api.Bundle) ([]*api.SimulateBundleResult, error) {
builder, err := s.getSession(sessionId)
if err != nil {
return nil, err
}
return builder.AddBundles(bundles)
}
func (s *SessionManager) BuildBlock(sessionId string) error { func (s *SessionManager) BuildBlock(sessionId string) error {
builder, err := s.getSession(sessionId) builder, err := s.getSession(sessionId)
if err != nil { if err != nil {