# INTEGRATION
## Запуск Beacon сразу в режиме Altair
подпилить код чтобы бикон сразу стартовал с Альтаира.
тут надо еще разбираться.
Еще хотелось бы как-то упростить запуск всей связки gbv (жват-бикон-валидатор),
в части того, что для каждого запуска нужна генерации генезиса, запуска gbv
до истечения заданного времени в генезисе.
В нашем случае это вообще смысла не имеет.
## Разделить DAG-АПИ на два вызова:
- GetCandidates: возвращает кандидатов финализации
- Finalise:
- должен выполнятся один раз - проверять эпоху-слот,
- финализация заданных блоков
- криэйт блока
- dag_sync выпилить
## Призма - реализация консенсуса
### 1. Реализовать функционал вызова GWAT-API:
в файле beacon-chain/powchain/engine_client.go реализовать вызов:
- dag.GetCandidates
- dag.Finalise
### 2. исправить структуру Eth1Data (Altair) и все юзкейсы (~171):
BlockHash -> BlockHashes
proto/prysm/v1alpha1/beacon_block.pb.go:1001
````go
type Eth1Data struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DepositRoot []byte `protobuf:"bytes,1,opt,name=deposit_root,json=depositRoot,proto3" json:"deposit_root,omitempty" ssz-size:"32"`
DepositCount uint64 `protobuf:"varint,2,opt,name=deposit_count,json=depositCount,proto3" json:"deposit_count,omitempty"`
BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"`
//^^^^^^^^^^^^
}
````
### 3. вызовов gwat-api dag.GetCandidates:
beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go:33
````go
// eth1DataMajorityVote determines the appropriate eth1data for a block proposal using
// an algorithm called Voting with the Majority. The algorithm works as follows:
// - Determine the timestamp for the start slot for the eth1 voting period.
// - Determine the earliest and latest timestamps that a valid block can have.
// - Determine the first block not before the earliest timestamp. This block is the lower bound.
// - Determine the last block not after the latest timestamp. This block is the upper bound.
// - If the last block is too early, use current eth1data from the beacon state.
// - Filter out votes on unknown blocks and blocks which are outside of the range determined by the lower and upper bounds.
// - If no blocks are left after filtering votes, use eth1data from the latest valid block.
// - Otherwise:
// - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie.
// - This vote's block is the eth1 block to use for the block proposal.
func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.BeaconState) (*ethpb.Eth1Data, error) {
...
if lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount {
// TODO запрос АПИ GetCandidates
hash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime.Number)
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if err != nil {
log.WithError(err).Error("Could not get hash of last block by latest valid time")
return vs.randomETH1DataVote(ctx)
}
return ðpb.Eth1Data{
BlockHash: hash.Bytes(),
//^^^^^^^^^^^^^^^^^^^^^^^^
DepositCount: lastBlockDepositCount,
DepositRoot: lastBlockDepositRoot[:],
}, nil
}
return vs.HeadFetcher.HeadETH1Data(), nil
}
````
### 4. вызовов gwat-api dag.Finalise:
beacon-chain/blockchain/receive_attestation.go:111
````go
// This routine processes fork choice attestations from the pool to account for validator votes and fork choice.
func (s *Service) spawnProcessAttestationsRoutine(stateFeed *event.Feed) {
// Wait for state to be initialized.
stateChannel := make(chan *feed.Event, 1)
stateSub := stateFeed.Subscribe(stateChannel)
go func() {
select {
...
case <-stateChannel:
stateSub.Unsubscribe()
break
}
...
st := slots.NewSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
for {
select {
...
case <-st.C():
...
/*
s.updateHead Determined the head from the fork choice service and saves its new data
(head root, head block, and head state) to the local service cache.
*/
newHeadRoot, err := s.updateHead(s.ctx, balances)
if err != nil {
log.WithError(err).Warn("Resolving fork due to new attestation")
}
/* TODO
Похоже здесь надо:
1) провалидировать newHeadRoot ( err == nil или посмотреть s.notifyEngineIfChangedHead(s.ctx, newHeadRoot))
2) добавить вызов нашего Finalise
*/
s.notifyEngineIfChangedHead(s.ctx, newHeadRoot)
}
}
}()
}
````
## Дополнительно
### Продумать поведение призмы в разных режимах
- Первый запуск
- Перезапуск
- Синхронизация
- Рассинхрон, форки, и.п. исключительные ситуации
### Перепроверить актуальность и работоспособность апи
````go
// NodeClient is the client API for Node service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type NodeClient interface {
GetSyncStatus(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SyncStatus, error)
GetGenesis(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Genesis, error)
GetVersion(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Version, error)
ListImplementedServices(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ImplementedServices, error)
GetHost(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*HostData, error)
GetPeer(ctx context.Context, in *PeerRequest, opts ...grpc.CallOption) (*Peer, error)
ListPeers(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Peers, error)
GetETH1ConnectionStatus(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ETH1ConnectionStatus, error)
}
````
и
beacon-chain/powchain/engine_client.go:49
````go
// EngineCaller defines a client that can interact with an Ethereum
// execution node's engine service via JSON-RPC.
type EngineCaller interface {
NewPayload(ctx context.Context, payload *pb.ExecutionPayload) ([]byte, error)
ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
) (*pb.PayloadIDBytes, []byte, error)
GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error)
ExchangeTransitionConfiguration(
ctx context.Context, cfg *pb.TransitionConfiguration,
) error
ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error)
GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error)
}
````