mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Improve things
This commit is contained in:
parent
1a5fe3fec1
commit
798d625a6d
4 changed files with 198 additions and 127 deletions
|
|
@ -5,9 +5,12 @@ import (
|
|||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type BuildBlockArgs -field-override buildBlockArgsMarshaling -out gen_buildblockargs_json.go
|
||||
|
||||
type Bundle struct {
|
||||
BlockNumber *big.Int `json:"blockNumber,omitempty"` // if BlockNumber is set it must match DecryptionCondition!
|
||||
MaxBlock *big.Int `json:"maxBlock,omitempty"`
|
||||
|
|
@ -17,16 +20,24 @@ type Bundle struct {
|
|||
}
|
||||
|
||||
type BuildBlockArgs struct {
|
||||
Slot uint64
|
||||
ProposerPubkey []byte
|
||||
Parent common.Hash
|
||||
Timestamp uint64
|
||||
FeeRecipient common.Address
|
||||
GasLimit uint64
|
||||
Random common.Hash
|
||||
Withdrawals []*types.Withdrawal
|
||||
Extra []byte
|
||||
FillPending bool
|
||||
Slot uint64 `json:"slot"`
|
||||
ProposerPubkey []byte `json:"proposerPubkey"`
|
||||
Parent common.Hash `json:"parent"`
|
||||
Timestamp uint64 `json:"timestamp"`
|
||||
FeeRecipient common.Address `json:"feeRecipient"`
|
||||
GasLimit uint64 `json:"gasLimit"`
|
||||
Random common.Hash `json:"random"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
Extra []byte `json:"extra"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
type buildBlockArgsMarshaling struct {
|
||||
Slot hexutil.Uint64
|
||||
ProposerPubkey hexutil.Bytes
|
||||
Timestamp hexutil.Uint64
|
||||
GasLimit hexutil.Uint64
|
||||
Extra hexutil.Bytes
|
||||
}
|
||||
|
||||
type API interface {
|
||||
|
|
|
|||
86
suave/builder/api/gen_buildblockargs_json.go
Normal file
86
suave/builder/api/gen_buildblockargs_json.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
var _ = (*buildBlockArgsMarshaling)(nil)
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (b BuildBlockArgs) MarshalJSON() ([]byte, error) {
|
||||
type BuildBlockArgs struct {
|
||||
Slot hexutil.Uint64 `json:"slot"`
|
||||
ProposerPubkey hexutil.Bytes `json:"proposerPubkey"`
|
||||
Parent common.Hash `json:"parent"`
|
||||
Timestamp hexutil.Uint64 `json:"timestamp"`
|
||||
FeeRecipient common.Address `json:"feeRecipient"`
|
||||
GasLimit hexutil.Uint64 `json:"gasLimit"`
|
||||
Random common.Hash `json:"random"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
Extra hexutil.Bytes `json:"extra"`
|
||||
}
|
||||
var enc BuildBlockArgs
|
||||
enc.Slot = hexutil.Uint64(b.Slot)
|
||||
enc.ProposerPubkey = b.ProposerPubkey
|
||||
enc.Parent = b.Parent
|
||||
enc.Timestamp = hexutil.Uint64(b.Timestamp)
|
||||
enc.FeeRecipient = b.FeeRecipient
|
||||
enc.GasLimit = hexutil.Uint64(b.GasLimit)
|
||||
enc.Random = b.Random
|
||||
enc.Withdrawals = b.Withdrawals
|
||||
enc.Extra = b.Extra
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (b *BuildBlockArgs) UnmarshalJSON(input []byte) error {
|
||||
type BuildBlockArgs struct {
|
||||
Slot *hexutil.Uint64 `json:"slot"`
|
||||
ProposerPubkey *hexutil.Bytes `json:"proposerPubkey"`
|
||||
Parent *common.Hash `json:"parent"`
|
||||
Timestamp *hexutil.Uint64 `json:"timestamp"`
|
||||
FeeRecipient *common.Address `json:"feeRecipient"`
|
||||
GasLimit *hexutil.Uint64 `json:"gasLimit"`
|
||||
Random *common.Hash `json:"random"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
Extra *hexutil.Bytes `json:"extra"`
|
||||
}
|
||||
var dec BuildBlockArgs
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
if dec.Slot != nil {
|
||||
b.Slot = uint64(*dec.Slot)
|
||||
}
|
||||
if dec.ProposerPubkey != nil {
|
||||
b.ProposerPubkey = *dec.ProposerPubkey
|
||||
}
|
||||
if dec.Parent != nil {
|
||||
b.Parent = *dec.Parent
|
||||
}
|
||||
if dec.Timestamp != nil {
|
||||
b.Timestamp = uint64(*dec.Timestamp)
|
||||
}
|
||||
if dec.FeeRecipient != nil {
|
||||
b.FeeRecipient = *dec.FeeRecipient
|
||||
}
|
||||
if dec.GasLimit != nil {
|
||||
b.GasLimit = uint64(*dec.GasLimit)
|
||||
}
|
||||
if dec.Random != nil {
|
||||
b.Random = *dec.Random
|
||||
}
|
||||
if dec.Withdrawals != nil {
|
||||
b.Withdrawals = dec.Withdrawals
|
||||
}
|
||||
if dec.Extra != nil {
|
||||
b.Extra = *dec.Extra
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/txpool"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
|
@ -44,11 +45,12 @@ type SessionManager struct {
|
|||
sessions map[string]*miner.Builder
|
||||
sessionTimers map[string]*time.Timer
|
||||
sessionsLock sync.RWMutex
|
||||
blockchain blockchain
|
||||
blockchain *core.BlockChain
|
||||
pool *txpool.TxPool
|
||||
config *Config
|
||||
}
|
||||
|
||||
func NewSessionManager(blockchain blockchain, config *Config) *SessionManager {
|
||||
func NewSessionManager(blockchain *core.BlockChain, pool *txpool.TxPool, config *Config) *SessionManager {
|
||||
if config.GasCeil == 0 {
|
||||
config.GasCeil = 1000000000000000000
|
||||
}
|
||||
|
|
@ -70,12 +72,24 @@ func NewSessionManager(blockchain blockchain, config *Config) *SessionManager {
|
|||
sessionTimers: make(map[string]*time.Timer),
|
||||
blockchain: blockchain,
|
||||
config: config,
|
||||
pool: pool,
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *SessionManager) BlockChain() *core.BlockChain {
|
||||
return s.blockchain
|
||||
}
|
||||
|
||||
func (s *SessionManager) TxPool() *txpool.TxPool {
|
||||
return s.pool
|
||||
}
|
||||
|
||||
// NewSession creates a new builder session and returns the session id
|
||||
func (s *SessionManager) NewSession(ctx context.Context, args *api.BuildBlockArgs) (string, error) {
|
||||
if args == nil {
|
||||
return "", fmt.Errorf("args cannot be nil")
|
||||
}
|
||||
// Wait for session to become available
|
||||
select {
|
||||
case <-s.sem:
|
||||
|
|
@ -88,11 +102,17 @@ func (s *SessionManager) NewSession(ctx context.Context, args *api.BuildBlockArg
|
|||
builderCfg := &miner.BuilderConfig{
|
||||
ChainConfig: s.blockchain.Config(),
|
||||
Engine: s.blockchain.Engine(),
|
||||
// TODO
|
||||
Chain: s.blockchain,
|
||||
EthBackend: s,
|
||||
GasCeil: s.config.GasCeil,
|
||||
}
|
||||
|
||||
builderArgs := &miner.BuilderArgs{
|
||||
ParentHash: args.Parent,
|
||||
ParentHash: args.Parent,
|
||||
FeeRecipient: args.FeeRecipient,
|
||||
ProposerPubkey: args.ProposerPubkey,
|
||||
Extra: args.Extra,
|
||||
Slot: args.Slot,
|
||||
}
|
||||
|
||||
id := uuid.New().String()[:7]
|
||||
|
|
|
|||
|
|
@ -2,18 +2,22 @@ package builder
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"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/state"
|
||||
"github.com/ethereum/go-ethereum/core/txpool"
|
||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||
"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"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -22,7 +26,9 @@ func TestSessionManager_SessionTimeout(t *testing.T) {
|
|||
SessionIdleTimeout: 500 * time.Millisecond,
|
||||
})
|
||||
|
||||
id, err := mngr.NewSession(context.TODO(), nil)
|
||||
args := &api.BuildBlockArgs{}
|
||||
|
||||
id, err := mngr.NewSession(context.TODO(), args)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
|
@ -35,6 +41,7 @@ func TestSessionManager_MaxConcurrentSessions(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
const d = time.Millisecond * 100
|
||||
args := &api.BuildBlockArgs{}
|
||||
|
||||
mngr, _ := newSessionManager(t, &Config{
|
||||
MaxConcurrentSessions: 1,
|
||||
|
|
@ -42,7 +49,7 @@ func TestSessionManager_MaxConcurrentSessions(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("SessionAvailable", func(t *testing.T) {
|
||||
sess, err := mngr.NewSession(context.TODO(), nil)
|
||||
sess, err := mngr.NewSession(context.TODO(), args)
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, sess)
|
||||
})
|
||||
|
|
@ -53,7 +60,7 @@ func TestSessionManager_MaxConcurrentSessions(t *testing.T) {
|
|||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
sess, err := mngr.NewSession(ctx, nil)
|
||||
sess, err := mngr.NewSession(ctx, args)
|
||||
require.Zero(t, sess)
|
||||
require.ErrorIs(t, err, context.Canceled)
|
||||
})
|
||||
|
|
@ -62,7 +69,7 @@ func TestSessionManager_MaxConcurrentSessions(t *testing.T) {
|
|||
time.Sleep(d) // Wait for the session to expire.
|
||||
|
||||
// We should be able to open a session again.
|
||||
sess, err := mngr.NewSession(context.TODO(), nil)
|
||||
sess, err := mngr.NewSession(context.TODO(), args)
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, sess)
|
||||
})
|
||||
|
|
@ -73,7 +80,8 @@ func TestSessionManager_SessionRefresh(t *testing.T) {
|
|||
SessionIdleTimeout: 500 * time.Millisecond,
|
||||
})
|
||||
|
||||
id, err := mngr.NewSession(context.TODO(), nil)
|
||||
args := &api.BuildBlockArgs{}
|
||||
id, err := mngr.NewSession(context.TODO(), args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// if we query the session under the idle timeout,
|
||||
|
|
@ -98,124 +106,70 @@ func TestSessionManager_StartSession(t *testing.T) {
|
|||
// test that the session starts and it can simulate transactions
|
||||
mngr, bMock := newSessionManager(t, &Config{})
|
||||
|
||||
id, err := mngr.NewSession(context.TODO(), nil)
|
||||
args := &api.BuildBlockArgs{}
|
||||
id, err := mngr.NewSession(context.TODO(), args)
|
||||
require.NoError(t, err)
|
||||
|
||||
txn := bMock.state.newTransfer(t, common.Address{}, big.NewInt(1))
|
||||
txn := bMock.newTransfer(t, common.Address{}, big.NewInt(1))
|
||||
receipt, err := mngr.AddTransaction(id, txn)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
}
|
||||
|
||||
func newSessionManager(t *testing.T, cfg *Config) (*SessionManager, *blockchainMock) {
|
||||
func newSessionManager(t *testing.T, cfg *Config) (*SessionManager, *testBackend) {
|
||||
backend := newTestBackend(t)
|
||||
|
||||
if cfg == nil {
|
||||
cfg = &Config{}
|
||||
}
|
||||
|
||||
state := newMockState(t)
|
||||
|
||||
bMock := &blockchainMock{
|
||||
state: state,
|
||||
}
|
||||
return NewSessionManager(bMock, cfg), bMock
|
||||
return NewSessionManager(backend.chain, backend.pool, cfg), backend
|
||||
}
|
||||
|
||||
type blockchainMock struct {
|
||||
state *mockState
|
||||
var (
|
||||
testBankKey, _ = crypto.GenerateKey()
|
||||
testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
|
||||
)
|
||||
|
||||
type testBackend struct {
|
||||
chain *core.BlockChain
|
||||
pool *txpool.TxPool
|
||||
}
|
||||
|
||||
func (b *blockchainMock) Engine() consensus.Engine {
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
func (b *blockchainMock) GetHeader(common.Hash, uint64) *types.Header {
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
func (b *blockchainMock) Config() *params.ChainConfig {
|
||||
return b.state.chainConfig
|
||||
}
|
||||
|
||||
func (b *blockchainMock) CurrentHeader() *types.Header {
|
||||
return &types.Header{
|
||||
Number: big.NewInt(1),
|
||||
Difficulty: big.NewInt(1),
|
||||
Root: b.state.stateRoot,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *blockchainMock) StateAt(root common.Hash) (*state.StateDB, error) {
|
||||
return b.state.stateAt(root)
|
||||
}
|
||||
|
||||
type mockState struct {
|
||||
stateRoot common.Hash
|
||||
statedb state.Database
|
||||
|
||||
premineKey *ecdsa.PrivateKey
|
||||
premineKeyAdd common.Address
|
||||
|
||||
nextNonce uint64 // figure out a better way
|
||||
signer types.Signer
|
||||
|
||||
chainConfig *params.ChainConfig
|
||||
}
|
||||
|
||||
func newMockState(t *testing.T) *mockState {
|
||||
premineKey, _ := crypto.GenerateKey() // TODO: it would be nice to have it deterministic
|
||||
premineKeyAddr := crypto.PubkeyToAddress(premineKey.PublicKey)
|
||||
|
||||
// create a state reference with at least one premined account
|
||||
// In order to test the statedb in isolation, we are going
|
||||
// to commit this pre-state to a memory database
|
||||
db := state.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
preState, err := state.New(types.EmptyRootHash, db, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
preState.AddBalance(premineKeyAddr, big.NewInt(1000000000000000000))
|
||||
|
||||
root, err := preState.Commit(1, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
// for the sake of this test, we only need all the forks enabled
|
||||
chainConfig := params.TestChainConfig
|
||||
|
||||
// Disable london so that we do not check gasFeeCap (TODO: Fix)
|
||||
chainConfig.LondonBlock = big.NewInt(100)
|
||||
|
||||
return &mockState{
|
||||
statedb: db,
|
||||
stateRoot: root,
|
||||
premineKey: premineKey,
|
||||
premineKeyAdd: premineKeyAddr,
|
||||
signer: types.NewEIP155Signer(chainConfig.ChainID),
|
||||
chainConfig: chainConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockState) stateAt(root common.Hash) (*state.StateDB, error) {
|
||||
return state.New(root, m.statedb, nil)
|
||||
}
|
||||
|
||||
func (m *mockState) getNonce() uint64 {
|
||||
next := m.nextNonce
|
||||
m.nextNonce++
|
||||
return next
|
||||
}
|
||||
|
||||
func (m *mockState) newTransfer(t *testing.T, to common.Address, amount *big.Int) *types.Transaction {
|
||||
tx := types.NewTransaction(m.getNonce(), to, amount, 1000000, big.NewInt(1), nil)
|
||||
return m.newTxn(t, tx)
|
||||
}
|
||||
|
||||
func (m *mockState) newTxn(t *testing.T, tx *types.Transaction) *types.Transaction {
|
||||
// sign the transaction
|
||||
signature, err := crypto.Sign(m.signer.Hash(tx).Bytes(), m.premineKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
// include the signature in the transaction
|
||||
tx, err = tx.WithSignature(m.signer, signature)
|
||||
require.NoError(t, err)
|
||||
|
||||
func (tb *testBackend) newTransfer(t *testing.T, to common.Address, amount *big.Int) *types.Transaction {
|
||||
gasPrice := big.NewInt(10 * params.InitialBaseFee)
|
||||
tx, _ := types.SignTx(types.NewTransaction(tb.pool.Nonce(testBankAddress), to, amount, params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey)
|
||||
return tx
|
||||
}
|
||||
|
||||
func newTestBackend(t *testing.T) *testBackend {
|
||||
// code based on miner 'newTestWorker'
|
||||
testTxPoolConfig := legacypool.DefaultConfig
|
||||
testTxPoolConfig.Journal = ""
|
||||
|
||||
var (
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
config = *params.AllCliqueProtocolChanges
|
||||
)
|
||||
config.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000}
|
||||
engine := clique.New(config.Clique, db)
|
||||
|
||||
var gspec = &core.Genesis{
|
||||
Config: &config,
|
||||
Alloc: core.GenesisAlloc{testBankAddress: {Balance: big.NewInt(1000000000000000000)}},
|
||||
}
|
||||
|
||||
gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength)
|
||||
copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes())
|
||||
engine.Authorize(testBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) {
|
||||
return crypto.Sign(crypto.Keccak256(data), testBankKey)
|
||||
})
|
||||
|
||||
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("core.NewBlockChain failed: %v", err)
|
||||
}
|
||||
pool := legacypool.New(testTxPoolConfig, chain)
|
||||
txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), chain, []txpool.SubPool{pool})
|
||||
|
||||
return &testBackend{chain: chain, pool: txpool}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue