---
# System prepended metadata

title: INTEGRATION

---

# 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 &ethpb.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)
}
````
