Substrate 自Node がブロック生成する判定はどこにあるんだろう

# Substrate Validator Node

ノード起動時のフラグに --validator フラグをつけるだけではブロック生成は行われない。
Chain state >> session.validators に --key で設定したアドレスが含まれていなければならない

## 知りたいこと

コードのどこで ブロック生成するかしないかの判定をしているのか
どういうロジックで判定されているのか

## validator になる方法は2つ

session.validators にアドレスが含まれていればブロックの生成を行います。（後述）

session.validators にアドレスが含まれるようにする方法は2つ

1. chain spec(json, chain_spec.rs) で定義する
2. staking.validate() で立候補する

1 はネットワーク、ノードを一番最初に起動するときに使用される初期値です。ブロックが生成されたあとから chain spec を変更することはできません。

2 は既存のネットワークに参加する際に validator になるための正常な手段です。

## ブロックを生成する判定をしているコード

### 探すためのヒント

validator node のログを見ていると

```bash
Pre-sealed block for proposal at 
```

これが出力されている。ブロック生成者をみると、Node のアドレスになっていることから、このログを出力しているところがブロックを生成している場所だと思われる。

## 検索

[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/eb7f7747c45e14a754a967f9bb0f0e791ee60b0a/core/consensus/aura/src/lib.rs#L438)

core/consensus/aura/src/lib.rs

```rust
info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.",
              header_num,
              import_block.post_header().hash(),
              pre_hash
          );
```

## 判定している場所

[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/eb7f7747c45e14a754a967f9bb0f0e791ee60b0a/core/consensus/aura/src/lib.rs#L362)

core/consensus/aura/src/lib.rs

```rust
    let maybe_author = slot_author::<P>(slot_num, &authorities);
    let proposal_work = match maybe_author {
      None => return Box::new(future::ok(())),
      Some(author) => if author == &public_key {
```

判定している場所はここでしょう。maybe_author と node の アドレス(public_key) が一致したらブロック生成
maybe_author がわかれば、判定のロジックがわかることになる

## maybe_author は authorities から抽出された1つ

```rust
let maybe_author = slot_author::<P>(slot_num, &authorities);
```

```rust
fn slot_author<P: Pair>(slot_num: u64, authorities: &[AuthorityId<P>]) -> Option<&AuthorityId<P>> {
  if authorities.is_empty() { return None }

  let idx = slot_num % (authorities.len() as u64);
  assert!(idx <= usize::max_value() as u64,
    "It is impossible to have a vector with length beyond the address space; qed");

  let current_author = authorities.get(idx as usize)
    .expect("authorities not empty; index constrained to list length;\
        this is a valid index; qed");

  Some(current_author)
}
```

authorities 配列から1つ抽出してます。


[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/eb7f7747c45e14a754a967f9bb0f0e791ee60b0a/core/consensus/aura/src/lib.rs#L334)

```rust
    let (timestamp, slot_num, slot_duration) =
      (slot_info.timestamp, slot_info.number, slot_info.duration);

    let authorities = match authorities(client.as_ref(), &BlockId::Hash(chain_head.hash())) {
      Ok(authorities) => authorities,
```

[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/eb7f7747c45e14a754a967f9bb0f0e791ee60b0a/core/consensus/aura/src/lib.rs#L717)

```rust
fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, ConsensusError> where
  B: Block,
  C: ProvideRuntimeApi + ProvideCache<B>,
  C::Api: AuthoritiesApi<B>,
{
  client
    .cache()
    .and_then(|cache| cache.get_at(&well_known_cache_keys::AUTHORITIES, at)
      .and_then(|v| Decode::decode(&mut &v[..])))
    .or_else(|| {
      if client.runtime_api().has_api::<AuthoritiesApi<B>>(at).unwrap_or(false) {
        AuthoritiesApi::authorities(&*client.runtime_api(), at).ok()
      } else {
        CoreApi::authorities(&*client.runtime_api(), at).ok()
      }
    }).ok_or_else(|| consensus_common::ErrorKind::InvalidAuthoritiesSet.into())
}
```

```rust
AuthoritiesApi::authorities(&*client.runtime_api(), at).ok()
```
[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/master/node/runtime/src/lib.rs#L341)

```rust
  impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
    fn authorities() -> Vec<AuthorityIdFor<Block>> {
      Consensus::authorities()
    }
  }
```
Cargo.toml をみると、Consensus は srml-consensus ある


[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/master/srml/consensus/src/lib.rs#L348)

```rust
  pub fn authorities() -> Vec<T::SessionKey> {
    AuthorityStorageVec::<T::SessionKey>::items()
  }
```

（おいかけていくうちに、何をさがしてたのか忘れそうになります）
この authorities 配列 の中に自分のノードのアドレスがあればブロックを生成する
authorities ってどうやってセットされてるの？ だっけ？

### maybe_author は staking で validator に選出された session アドレス

記憶がただしければ、validator 選出のロジックから set_validators() が呼び出されていた

[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/master/srml/staking/src/lib.rs#L927)

```rust
fn select_validators() -> BalanceOf<T> {
  .
  .
  .
        <session::Module<T>>::set_validators(
          &elected_stashes.into_iter().map(|s| Self::bonded(s).unwrap_or_default()).collect::<Vec<_>>()
        );
  .
  .
  .
}
```

参考（コードに触れていませんが。。。）
[Substrate Validator に立候補、、、がうまくいかない - Qiita](https://qiita.com/MTDK1/items/6b8eab1f9aa880f7754c)


## まとめ

ブロックを生成している場所

core/consensus/aura/src/lib.rs
[substrate/lib.rs at master · bdevux/substrate](https://github.com/bdevux/substrate/blob/eb7f7747c45e14a754a967f9bb0f0e791ee60b0a/core/consensus/aura/src/lib.rs#L362)

staking で選出された validators に自node が含まれていて、自分の順番になったときにブロックを生成する


## 所感

そりゃそうだよねという結果
わざわざソースコードをおいかけているのは rust に慣れるためだったりもします。