Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-subblocks refactoring #2180

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ import scorex.util.ModifierId
case class ProgressInfo[PM <: BlockSection](branchPoint: Option[ModifierId],
toRemove: Seq[PM],
toApply: Seq[PM],
toDownload: Seq[(NetworkObjectTypeId.Value, ModifierId)])
(implicit encoder: ScorexEncoder) {
toDownload: Seq[(NetworkObjectTypeId.Value, ModifierId)]) {

if (toRemove.nonEmpty)
require(branchPoint.isDefined, s"Branch point should be defined for non-empty `toRemove`")

lazy val chainSwitchingNeeded: Boolean = toRemove.nonEmpty

override def toString: String = {
s"ProgressInfo(BranchPoint: ${branchPoint.map(encoder.encodeId)}, " +
s"ProgressInfo(BranchPoint: ${branchPoint.map(ScorexEncoder.encodeId)}, " +
s" to remove: ${toRemove.map(_.encodedId)}, to apply: ${toApply.map(_.encodedId)})"
}
}

object ProgressInfo {
val empty = ProgressInfo[BlockSection](None, Seq.empty, Seq.empty, Seq.empty)
}
8 changes: 4 additions & 4 deletions ergo-core/src/main/scala/org/ergoplatform/core/core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ package object core {

type VersionTag = VersionTag.Type

def idsToString(ids: Seq[(NetworkObjectTypeId.Value, util.ModifierId)])(implicit enc: ScorexEncoder): String = {
def idsToString(ids: Seq[(NetworkObjectTypeId.Value, util.ModifierId)]): String = {
List(ids.headOption, ids.lastOption)
.flatten
.map { case (typeId, id) => s"($typeId,${enc.encodeId(id)})" }
.map { case (typeId, id) => s"($typeId,${ScorexEncoder.encodeId(id)})" }
.mkString("[", "..", "]")
}

def idsToString(modifierType: NetworkObjectTypeId.Value, ids: Seq[util.ModifierId])(implicit encoder: ScorexEncoder): String = {
def idsToString(modifierType: NetworkObjectTypeId.Value, ids: Seq[util.ModifierId]): String = {
idsToString(ids.map(id => (modifierType, id)))
}

def idsToString(invData: InvData)(implicit encoder: ScorexEncoder): String = idsToString(invData.typeId, invData.ids)
def idsToString(invData: InvData): String = idsToString(invData.typeId, invData.ids)

def bytesToId: Array[Byte] => util.ModifierId = scorex.util.bytesToId

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.ergoplatform.http.api

import cats.syntax.either._
import io.circe._
import cats.syntax.either._ // needed for Scala 2.11
import io.circe._ // needed for Scala 2.11
import io.circe.syntax._
import org.bouncycastle.util.BigIntegers
import org.ergoplatform.ErgoBox.RegisterId
Expand Down
16 changes: 8 additions & 8 deletions ergo-core/src/main/scala/org/ergoplatform/settings/Algos.scala
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package org.ergoplatform.settings

import org.ergoplatform.utils
import org.ergoplatform.utils.ScorexEncoder
import scorex.crypto.authds.LeafData
import scorex.crypto.authds.merkle.MerkleTree
import scorex.crypto.hash.Digest32
import scorex.util._
import scorex.util.encode.BytesEncoder


object Algos extends ErgoAlgos with utils.ScorexEncoding {

// ErgoAlgos in sigmastate extends scorex.util.ScorexEncoding where encoder is BytesEncoder
// but here we use scorex.core.utils.ScorexEncoding where encoder is ScorexEncoder
// After ScorexEncoder is moved (there is even a todo for that) from scorex.core to scorex.util
// we can fix this ugliness.
override implicit val encoder: ScorexEncoder = utils.ScorexEncoder.default
override implicit val encoder: BytesEncoder = utils.ScorexEncoder

lazy val emptyMerkleTreeRoot: Digest32 = Algos.hash(LeafData @@ Array[Byte]())

@inline def encode(id: ModifierId): String = encoder.encode(id)
/**
* This method might be useful and reimplemented, if encoding of ModifierId and VersionTag
* is different form default bytes encoding, e.g. this method should be reimplemented together
* with encode() and decode methods
*/
@inline def encode(id: String): String = id

/**
* A method to build a Merkle tree over binary objects (leafs of the tree)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import scorex.util.encode.{Base16, BytesEncoder}

import scala.util.Try

class ScorexEncoder extends BytesEncoder {
object ScorexEncoder extends BytesEncoder {
@inline
override val Alphabet: String = Base16.Alphabet

Expand All @@ -16,14 +16,6 @@ class ScorexEncoder extends BytesEncoder {
@inline
override def decode(input: String): Try[Array[Byte]] = Base16.decode(input)

/**
* This method might be useful and reimplemented, if encoding of ModifierId and VersionTag
* is different form default bytes encoding, e.g. this method should be reimplemented together
* with encode() and decode methods
*/
@inline
def encode(input: String): String = input

/**
* This method might be useful and reimplemented, if encoding of ModifierId and VersionTag
* is different form default bytes encoding, e.g. this method should be reimplemented together
Expand All @@ -41,7 +33,3 @@ class ScorexEncoder extends BytesEncoder {
def encodeId(input: ModifierId): String = input

}

object ScorexEncoder {
val default: ScorexEncoder = new ScorexEncoder()
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.ergoplatform.utils

import scorex.util.encode.BytesEncoder

/**
* Trait with bytes to string encoder
* TODO extract to ScorexUtils project
*/
trait ScorexEncoding {
implicit val encoder: ScorexEncoder = ScorexEncoder.default
val encoder: BytesEncoder = ScorexEncoder
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import scala.util.{Failure, Success, Try}
*/
object ModifierValidator {

def apply(settings: ValidationSettings)(implicit e: ScorexEncoder): ValidationState[Unit] = {
ValidationState(ModifierValidator.success, settings)(e)
def apply(settings: ValidationSettings): ValidationState[Unit] = {
ValidationState(ModifierValidator.success, settings)
}

/** report recoverable modifier error that could be fixed by later retries */
Expand Down Expand Up @@ -65,7 +65,7 @@ object ModifierValidator {
}

/** This is the place where all the validation DSL lives */
case class ValidationState[T](result: ValidationResult[T], settings: ValidationSettings)(implicit e: ScorexEncoder) {
case class ValidationState[T](result: ValidationResult[T], settings: ValidationSettings) {

/** Create the next validation state as the result of given `operation` */
def pass[R](operation: => ValidationResult[R]): ValidationState[R] = {
Expand Down Expand Up @@ -115,6 +115,7 @@ case class ValidationState[T](result: ValidationResult[T], settings: ValidationS
/** Validate the `id`s are equal. The `error` callback will be provided with detail on argument values
*/
def validateEqualIds(id: Short, `given`: => ModifierId, expected: => ModifierId, modifierTypeId: NetworkObjectTypeId.Value): ValidationState[T] = {
val e = ScorexEncoder
pass {
if (!settings.isActive(id) || given == expected) result
else settings.getError(id, InvalidModifier(s"Given: ${e.encodeId(given)}, expected ${e.encodeId(expected)}", given, modifierTypeId))
Expand Down
11 changes: 4 additions & 7 deletions src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.ergoplatform.http.api.ApiError.BadRequest
import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress}
import scorex.core.api.http.{ApiResponse, ApiRoute}
import org.ergoplatform.utils.ScorexEncoding
import org.ergoplatform.utils.ScorexEncoder
import scorex.crypto.hash.Blake2b256
import scorex.util.encode.Base16
import sigmastate.crypto.DLogProtocol.ProveDlog
Expand All @@ -18,10 +18,7 @@ import java.security.SecureRandom
import scala.util.Failure
import sigmastate.serialization.{ErgoTreeSerializer, GroupElementSerializer, SigmaSerializer}

class ErgoUtilsApiRoute(val ergoSettings: ErgoSettings)(
implicit val context: ActorRefFactory
) extends ApiRoute
with ScorexEncoding {
class ErgoUtilsApiRoute(val ergoSettings: ErgoSettings)(implicit val context: ActorRefFactory) extends ApiRoute {

private val SeedSize = 32
private val treeSerializer: ErgoTreeSerializer = new ErgoTreeSerializer
Expand All @@ -46,7 +43,7 @@ class ErgoUtilsApiRoute(val ergoSettings: ErgoSettings)(
private def seed(length: Int): String = {
val seed = new Array[Byte](length)
new SecureRandom().nextBytes(seed) //seed mutated here!
encoder.encode(seed)
ScorexEncoder.encode(seed)
}

def seedRoute: Route = (get & path("seed")) {
Expand All @@ -60,7 +57,7 @@ class ErgoUtilsApiRoute(val ergoSettings: ErgoSettings)(
def hashBlake2b: Route = {
(post & path("hash" / "blake2b") & entity(as[Json])) { json =>
json.as[String] match {
case Right(message) => ApiResponse(encoder.encode(Blake2b256(message)))
case Right(message) => ApiResponse(ScorexEncoder.encode(Blake2b256(message)))
case Left(ex) => ApiError(StatusCodes.BadRequest, ex.getMessage())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import org.ergoplatform.network.message.{InvSpec, MessageSpec, ModifiersSpec, Re
import scorex.core.network._
import scorex.core.network.{ConnectedPeer, ModifiersStatus, SendToPeer, SendToPeers}
import org.ergoplatform.network.message.{InvData, Message, ModifiersData}
import org.ergoplatform.utils.ScorexEncoding
import org.ergoplatform.utils.ScorexEncoder
import org.ergoplatform.validation.MalformedModifierError
import scorex.util.{ModifierId, ScorexLogging}
import scorex.core.network.DeliveryTracker
Expand Down Expand Up @@ -53,7 +53,7 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef,
settings: ErgoSettings,
syncTracker: ErgoSyncTracker,
deliveryTracker: DeliveryTracker)(implicit ex: ExecutionContext)
extends Actor with Synchronizer with ScorexLogging with ScorexEncoding {
extends Actor with Synchronizer with ScorexLogging {

import org.ergoplatform.network.ErgoNodeViewSynchronizer._

Expand Down Expand Up @@ -777,7 +777,7 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef,
case _ =>
// Penalize peer and do nothing - it will be switched to correct state on CheckDelivery
penalizeMisbehavingPeer(remote)
log.warn(s"Failed to parse transaction with declared id ${encoder.encodeId(id)} from ${remote.toString}")
log.warn(s"Failed to parse transaction with declared id ${ScorexEncoder.encodeId(id)} from ${remote.toString}")
}
}
}
Expand All @@ -801,7 +801,7 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef,
// Forget about block section, so it will be redownloaded if announced again only
deliveryTracker.setUnknown(id, modifierTypeId)
penalizeMisbehavingPeer(remote)
log.warn(s"Failed to parse modifier with declared id ${encoder.encodeId(id)} from ${remote.toString}")
log.warn(s"Failed to parse modifier with declared id ${ScorexEncoder.encodeId(id)} from ${remote.toString}")
None
}
}
Expand Down Expand Up @@ -1230,7 +1230,7 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef,
} else {
// A block section is not delivered on time.
log.info(s"Peer ${peer.toString} has not delivered network object " +
s"$modifierTypeId : ${encoder.encodeId(modifierId)} on time")
s"$modifierTypeId : ${ScorexEncoder.encodeId(modifierId)} on time")

// Number of delivery checks for a block section, utxo set snapshot chunk or manifest
// increased or initialized, except the case where we can have issues with connectivity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.nodeView.ErgoNodeViewHolder.{BlockAppliedTransactions, CurrentView, DownloadRequest}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._
import org.ergoplatform.modifiers.history.{ADProofs, HistoryModifierSerializer}
import org.ergoplatform.utils.ScorexEncoding
import org.ergoplatform.validation.RecoverableModifierError
import scorex.util.{ModifierId, ScorexLogging}
import spire.syntax.all.cfor
Expand All @@ -40,7 +39,7 @@ import scala.util.{Failure, Success, Try}
*
*/
abstract class ErgoNodeViewHolder[State <: ErgoState[State]](settings: ErgoSettings)
extends Actor with ScorexLogging with ScorexEncoding with FileUtils {
extends Actor with ScorexLogging with FileUtils {

private implicit lazy val actorSystem: ActorSystem = context.system

Expand Down Expand Up @@ -240,7 +239,7 @@ abstract class ErgoNodeViewHolder[State <: ErgoState[State]](settings: ErgoSetti
}
case Failure(e) =>
log.warn(s"Invalid modifier! Typeid: ${modToApply.modifierTypeId} id: ${modToApply.id} ", e)
history.reportModifierIsInvalid(modToApply, progressInfo).map { case (newHis, newProgressInfo) =>
history.reportModifierIsInvalid(modToApply).map { case (newHis, newProgressInfo) =>
context.system.eventStream.publish(SemanticallyFailedModification(modToApply.modifierTypeId, modToApply.id, e))
UpdateInformation(newHis, updateInfo.state, Some(modToApply), Some(newProgressInfo), updateInfo.suffix)
}
Expand Down Expand Up @@ -573,7 +572,7 @@ abstract class ErgoNodeViewHolder[State <: ErgoState[State]](settings: ErgoSetti
log.info("State and history are both empty on startup")
Success(stateIn)
case (stateId, Some(block), _) if stateId == block.id =>
log.info(s"State and history have the same version ${encoder.encode(stateId)}, no recovery needed.")
log.info(s"State and history have the same version ${Algos.encode(stateId)}, no recovery needed.")
Success(stateIn)
case (_, None, _) =>
log.info("State and history are inconsistent. History is empty on startup, rollback state to genesis.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@ trait ErgoHistory
* @return ProgressInfo with next modifier to try to apply
*/
@SuppressWarnings(Array("OptionGet", "TraversableHead"))
def reportModifierIsInvalid(modifier: BlockSection,
progressInfo: ProgressInfo[BlockSection]
): Try[(ErgoHistory, ProgressInfo[BlockSection])] = synchronized {
def reportModifierIsInvalid(modifier: BlockSection): Try[(ErgoHistory, ProgressInfo[BlockSection])] = synchronized {
log.warn(s"Modifier ${modifier.encodedId} of type ${modifier.modifierTypeId} is marked as invalid")
correspondingHeader(modifier) match {
case Some(invalidatedHeader) =>
Expand All @@ -136,7 +134,7 @@ trait ErgoHistory
case (false, false) =>
// Modifiers from best header and best full chain are not involved, no rollback and links change required
historyStorage.insert(validityRow, BlockSection.emptyArray).map { _ =>
this -> ProgressInfo[BlockSection](None, Seq.empty, Seq.empty, Seq.empty)
this -> ProgressInfo.empty
}
case _ =>
// Modifiers from best header and best full chain are involved, links change required
Expand All @@ -148,7 +146,7 @@ trait ErgoHistory
newBestHeaderOpt.map(h => BestHeaderKey -> idToBytes(h.id)).toArray,
BlockSection.emptyArray
).map { _ =>
this -> ProgressInfo[BlockSection](None, Seq.empty, Seq.empty, Seq.empty)
this -> ProgressInfo.empty
}
} else {
val invalidatedChain: Seq[ErgoFullBlock] = bestFullBlockOpt.toSeq
Expand Down Expand Up @@ -184,7 +182,7 @@ trait ErgoHistory
//No headers become invalid. Just mark this modifier as invalid
log.warn(s"Modifier ${modifier.encodedId} of type ${modifier.modifierTypeId} is missing corresponding header")
historyStorage.insert(Array(validityKey(modifier.id) -> Array(0.toByte)), BlockSection.emptyArray).map { _ =>
this -> ProgressInfo[BlockSection](None, Seq.empty, Seq.empty, Seq.empty)
this -> ProgressInfo.empty
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import org.ergoplatform.nodeView.history.extra.ExtraIndex
import org.ergoplatform.nodeView.history.storage._
import org.ergoplatform.nodeView.history.storage.modifierprocessors.{BlockSectionProcessor, HeadersProcessor}
import org.ergoplatform.settings.{ErgoSettings, NipopowSettings}
import org.ergoplatform.utils.ScorexEncoding
import org.ergoplatform.validation.MalformedModifierError
import scorex.util.{ModifierId, ScorexLogging}

Expand All @@ -27,8 +26,7 @@ trait ErgoHistoryReader
with ContainsModifiers[BlockSection]
with HeadersProcessor
with BlockSectionProcessor
with ScorexLogging
with ScorexEncoding {
with ScorexLogging {

type ModifierIds = Seq[(NetworkObjectTypeId.Value, ModifierId)]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import org.ergoplatform.modifiers.history.HistoryModifierSerializer
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.nodeView.history.extra.{ExtraIndex, ExtraIndexSerializer, Segment}
import org.ergoplatform.settings.{Algos, CacheSettings, ErgoSettings}
import org.ergoplatform.utils.ScorexEncoding
import scorex.db.{ByteArrayWrapper, LDBFactory, LDBKVStore}
import scorex.util.{ModifierId, ScorexLogging, idToBytes}

Expand All @@ -28,8 +27,7 @@ import scala.jdk.CollectionConverters.asScalaIteratorConverter
*/
class HistoryStorage(indexStore: LDBKVStore, objectsStore: LDBKVStore, extraStore: LDBKVStore, config: CacheSettings)
extends ScorexLogging
with AutoCloseable
with ScorexEncoding {
with AutoCloseable {

private lazy val headersCache =
Caffeine.newBuilder()
Expand Down Expand Up @@ -84,7 +82,7 @@ class HistoryStorage(indexStore: LDBKVStore, objectsStore: LDBKVStore, extraStor
cacheModifier(pm)
Some(pm)
case Failure(_) =>
log.warn(s"Failed to parse modifier ${encoder.encode(id)} from db (bytes are: ${Algos.encode(bytes)})")
log.warn(s"Failed to parse modifier ${Algos.encode(id)} from db (bytes are: ${Algos.encode(bytes)})")
None
}
}
Expand All @@ -99,7 +97,7 @@ class HistoryStorage(indexStore: LDBKVStore, objectsStore: LDBKVStore, extraStor
}
Some(pm)
case Failure(_) =>
log.warn(s"Failed to parse index ${encoder.encode(id)} from db (bytes are: ${Algos.encode(bytes)})")
log.warn(s"Failed to parse index ${Algos.encode(id)} from db (bytes are: ${Algos.encode(bytes)})")
None
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ package org.ergoplatform.nodeView.history.storage.modifierprocessors

import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.modifiers.{BlockSection, NonHeaderBlockSection}
import org.ergoplatform.utils.ScorexEncoding

import scala.util.Try

/**
* Trait that declares interfaces for validation and processing of various
* block sections: BlockTransactions, ADProofs, etc.
*/
trait BlockSectionProcessor extends ScorexEncoding {
trait BlockSectionProcessor {

/**
* Whether state requires to download adProofs before full block application
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import scala.util.{Failure, Success, Try}
trait EmptyBlockSectionProcessor extends BlockSectionProcessor {

override protected def process(m: NonHeaderBlockSection): Try[ProgressInfo[BlockSection]] =
Success(ProgressInfo[BlockSection](None, Seq.empty, Seq.empty, Seq.empty))
Success(ProgressInfo.empty)

override protected def validate(m: NonHeaderBlockSection): Try[Unit] =
Failure(new Error("Regime that does not support block sections processing"))
Expand Down
Loading
Loading