All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.alephium.protocol.model.ChainIndex.scala Maven / Gradle / Ivy

There is a newer version: 3.8.8
Show newest version
// Copyright 2018 The Alephium Authors
// This file is part of the alephium project.
//
// The library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the library. If not, see .

package org.alephium.protocol.model

import scala.util.Random

import org.alephium.protocol.config.GroupConfig
import org.alephium.protocol.model.BlockHash
import org.alephium.util.Bytes

class ChainIndex(val from: GroupIndex, val to: GroupIndex) {
  def flattenIndex(implicit groupConfig: GroupConfig): Int = {
    from.value * groupConfig.groups + to.value
  }

  def relateTo(brokerInfo: BrokerGroupInfo): Boolean = {
    brokerInfo.contains(from) || brokerInfo.contains(to)
  }

  def relateTo(groupIndex: GroupIndex): Boolean = {
    from == groupIndex || to == groupIndex
  }

  def isIntraGroup: Boolean = from == to

  override def equals(obj: Any): Boolean =
    obj match {
      case that: ChainIndex => from == that.from && to == that.to
      case _                => false
    }

  override def hashCode(): Int = {
    from.value ^ to.value
  }

  override def toString: String = s"ChainIndex(${from.value}, ${to.value})"

  def prettyString: String = s"chain: ${from.value}->${to.value}"
}

object ChainIndex {
  def from(from: Int, to: Int)(implicit config: GroupConfig): Option[ChainIndex] = {
    if (validate(from, to)) {
      Some(new ChainIndex(GroupIndex.unsafe(from), GroupIndex.unsafe(to)))
    } else {
      None
    }
  }

  def unsafe(index: Int)(implicit config: GroupConfig): ChainIndex = {
    assume(index >= 0 && index < config.chainNum)
    new ChainIndex(
      GroupIndex.unsafe(index / config.groups),
      GroupIndex.unsafe(index % config.groups)
    )
  }

  def unsafe(from: Int, to: Int)(implicit config: GroupConfig): ChainIndex = {
    assume(validate(from, to))
    new ChainIndex(GroupIndex.unsafe(from), GroupIndex.unsafe(to))
  }

  def apply(from: GroupIndex, to: GroupIndex): ChainIndex = {
    new ChainIndex(from, to)
  }

  @inline
  def validate(from: Int, to: Int)(implicit config: GroupConfig): Boolean = {
    0 <= from && from < config.groups && 0 <= to && to < config.groups
  }

  def from(hash: BlockHash)(implicit config: GroupConfig): ChainIndex = {
    from(hash, config.groups)
  }

  @SuppressWarnings(Array("org.wartremover.warts.IterableOps"))
  def from(hash: BlockHash, groups: Int): ChainIndex = {
    val bytes = hash.bytes
    assume(bytes.length >= 2)

    val beforeLast = Bytes.toPosInt(bytes(bytes.length - 2))
    val last       = Bytes.toPosInt(bytes.last)
    val bigIndex   = beforeLast << 8 | last
    assume(bigIndex >= 0)

    val chainNum = groups * groups
    val index    = bigIndex % chainNum
    new ChainIndex(new GroupIndex(index / groups), new GroupIndex(index % groups))
  }

  def random(implicit groupConfig: GroupConfig): ChainIndex = {
    ChainIndex.unsafe(Random.nextInt(groupConfig.chainNum))
  }

  def randomIntraGroup(implicit groupConfig: GroupConfig): ChainIndex = {
    val groupIndex = GroupIndex.random
    ChainIndex(groupIndex, groupIndex)
  }

  def checkFromGroup(index: Int, targetGroup: GroupIndex)(implicit
      groupConfig: GroupConfig
  ): Boolean = {
    (index / groupConfig.groups) == targetGroup.value
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy