1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-04-21

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 のログを見ていると

Pre-sealed block for proposal at 

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

検索

substrate/lib.rs at master · bdevux/substrate

core/consensus/aura/src/lib.rs

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

core/consensus/aura/src/lib.rs

    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つ

let maybe_author = slot_author::<P>(slot_num, &authorities);
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

    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

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())
}
AuthoritiesApi::authorities(&*client.runtime_api(), at).ok()

substrate/lib.rs at master · bdevux/substrate

  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

  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

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

まとめ

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

core/consensus/aura/src/lib.rs
substrate/lib.rs at master · bdevux/substrate

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

所感

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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?