初期化#
Flashbots Builder は geth を基に開発されているため、全体の構造は geth と一致しています。Builder のコア構造はbuilder/builder.go
ファイルに定義されており、Builder は外部に BuilderService としてカプセル化され、HTTP サービスを提供します。外部から内部へ、まず BuilderService を分析し、その後 Builder とその内部構成を見ていきます。
BuilderService
- IBuilder インターフェースと httpServer をカプセル化
NewService
パラメータ:リスニングアドレス、localRelay 設定、builder インスタンスを渡す- localRelay が空でない場合、ルーティングを初期化
- GET:/
- GET:
/eth/v1/builder/status
- POST:
/eth/v1/builder/validators
- GET:
/eth/v1/builder/header/{slot:[0-9]+}/{parent_hash:0x[a-fA-F0-9]+}/{pubkey:0x[a-fA-F0-9]+}
- POST:
/eth/v1/builder/blinded_blocks
- localRelay が空でない場合、ルーティングを初期化
- Start:HTTP サービスを起動し、builder を起動
- Stop:HTTP サービスを停止し、builder を停止
Builder
まずNewBuilder
のパラメータBuilderArgs
を見てみましょう。対応するフィールドのコメントはすでに追加されています。
type BuilderArgs struct {
sk *bls.SecretKey // builderの実行に使用する秘密鍵
ds flashbotsextra.IDatabaseService // ローカルのデータベースサービス
relay IRelay // relayインターフェース
builderSigningDomain phase0.Domain // ブロックを提出する際に署名するドメイン名
builderBlockResubmitInterval time.Duration // 一定時間ごとにブロックを再提出
discardRevertibleTxOnErr bool // 無用
eth IEthereumService // ethインスタンス、ブロック構築に使用
dryRun bool // relayにブロックを提出する必要があるか
ignoreLatePayloadAttributes bool // イベントをリッスンする際にフィルタリングするため
validator *blockvalidation.BlockValidationAPI // dryRun時に提出検証に使用
beaconClient IBeaconClient // 信標チェーンクライアント、イベントをリッスンしてペイロードを構築
submissionOffsetFromEndOfSlot time.Duration // ブロック提出の待機時間
limiter *rate.Limiter // レート制限に使用
}
builder のコア構成には ds、relay、eth、beaconClient が含まれており、他のパラメータは後で適用される際にさらに説明されます。
Relay#
まず Relay は二箇所(BuilderService と Builder)に現れ、二種類のタイプ(localRelay と remoteRelay)があります。
- BuilderService には localRelay がすでに存在し、localRelay が空でない場合、BuilderService の HTTP サービスに対応するルーティングが登録されます。
- Builder には Relay があり、remoteReplayEndpoint が設定されていない場合は localRelay を使用し、そうでなければ remoteRelay を使用します。
このことから、各 builder は必ずしも自分自身で relay サービスを実行する必要はありませんが、必ず対応する relay サービスに接続します。
Relay のインターフェース定義は以下の通りです。
type IRelay interface {
SubmitBlock(msg *bellatrixapi.SubmitBlockRequest, vd ValidatorData) error
SubmitBlockCapella(msg *capellaapi.SubmitBlockRequest, vd ValidatorData) error
GetValidatorForSlot(nextSlot uint64) (ValidatorData, error)
Config() RelayConfig
Start() error
Stop()
}
DatabaseService#
前のDatabaseService の初期化に戻ると、初期化時に postgres 接続が設定されているかどうかが判断され、設定されていない場合はデフォルトの dbService が初期化され、そうでなければ db 接続が確立されます。
var ds flashbotsextra.IDatabaseService
dbDSN := os.Getenv("FLASHBOTS_POSTGRES_DSN")
if dbDSN != "" {
ds, err = flashbotsextra.NewDatabaseService(dbDSN)
if err != nil {
log.Error("DBに接続できませんでした", "err", err)
ds = flashbotsextra.NilDbService{}
}
} else {
log.Info("db dsnが提供されていないため、nil db svcを開始します")
ds = flashbotsextra.NilDbService{}
}
IDatabaseServiceのインターフェース定義は以下の通りです。デフォルトの NilDbService はすべて空を返します。
type IDatabaseService interface {
ConsumeBuiltBlock(block *types.Block, blockValue *big.Int, OrdersClosedAt time.Time, sealedAt time.Time,
commitedBundles []types.SimulatedBundle, allBundles []types.SimulatedBundle,
usedSbundles []types.UsedSBundle,
bidTrace *apiv1.BidTrace)
GetPriorityBundles(ctx context.Context, blockNum int64, isHighPrio bool) ([]DbBundle, error)
GetLatestUuidBundles(ctx context.Context, blockNum int64) ([]types.LatestUuidBundle, error)
}
具体的な実装では、主に blocks bundles テーブルなどの情報を記録し、ローカル builder の構築したブロックと bundle 情報を記録し、後でのクエリや置換に使用されます。
Eth#
ここで定義されている構造はEthereumService
で、eth インスタンスをカプセル化したもので、eth インスタンスはおなじみの geth の eth インスタンスで、前に初期化されており、ここではIEthereumService インターフェースとして抽象化され、以下の四つのメソッドを提供します。
type IEthereumService interface {
BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn) error
GetBlockByHash(hash common.Hash) *types.Block
Config() *params.ChainConfig
Synced() bool
}
BeaconClient#
beaconClient は信標チェーンノードとの通信に使用され、初期化部分では、設定された BeaconEndpoints に基づいてNewBeaconClient
またはNewMultiBeaconClient
を選択します。
var beaconClient IBeaconClient
if len(cfg.BeaconEndpoints) == 0 {
beaconClient = &NilBeaconClient{}
} else if len(cfg.BeaconEndpoints) == 1 {
beaconClient = NewBeaconClient(cfg.BeaconEndpoints[0], cfg.SlotsInEpoch, cfg.SecondsInSlot)
} else {
beaconClient = NewMultiBeaconClient(cfg.BeaconEndpoints, cfg.SlotsInEpoch, cfg.SecondsInSlot)
}
BeaconClient
には三つのコアフィールドがあります。
endpoint
:beaconClient の接続を確立slotsInEpoch
:デフォルトは 32secondsInSlot
: デフォルトは 12
slot は eth2.0 の設定で、固定の時間間隔で通常は 12 秒です。すべてのアクティブなバリデーターは一定のルールに従って異なる slot の proposer を交代で担当し、各 slot は一つのブロックをパッケージ化します。
epoch はより大きな時間周期で、複数の連続した slot で構成され、通常は 32 の slot です。
外部に以下のメソッドを提供します。
type IBeaconClient interface {
isValidator(pubkey PubkeyHex) bool
getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error)
SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes)
Start() error
Stop()
}
重要なメソッドは SubscribeToPayloadAttributesEvents
で、定期的なリクエストを取得するために使用されます。