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

Fix for block sections hashcode #2088

Merged
merged 4 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 0 additions & 55 deletions ergo-core/src/main/scala/org/ergoplatform/NodeViewModifier.scala

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.ergoplatform.consensus

import org.ergoplatform.PersistentNodeViewModifier
import org.ergoplatform.modifiers.NetworkObjectTypeId
import org.ergoplatform.modifiers.{BlockSection, NetworkObjectTypeId}
import org.ergoplatform.utils.ScorexEncoder
import scorex.util.ModifierId

Expand All @@ -14,11 +13,11 @@ import scorex.util.ModifierId
* @param toDownload - modifiers to download from other nodes
* @tparam PM - type of used modifier
*/
case class ProgressInfo[PM <: PersistentNodeViewModifier](branchPoint: Option[ModifierId],
toRemove: Seq[PM],
toApply: Seq[PM],
toDownload: Seq[(NetworkObjectTypeId.Value, ModifierId)])
(implicit encoder: ScorexEncoder) {
case class ProgressInfo[PM <: BlockSection](branchPoint: Option[ModifierId],
toRemove: Seq[PM],
toApply: Seq[PM],
toDownload: Seq[(NetworkObjectTypeId.Value, ModifierId)])
(implicit encoder: ScorexEncoder) {

if (toRemove.nonEmpty)
require(branchPoint.isDefined, s"Branch point should be defined for non-empty `toRemove`")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package org.ergoplatform.modifiers

import io.circe.Encoder
import org.ergoplatform.PersistentNodeViewModifier
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}


/**
* Block section, so a header, or block transactions, or extension, or ADProofs.
*/
trait BlockSection extends PersistentNodeViewModifier with ErgoNodeViewModifier
trait BlockSection extends ErgoNodeViewModifier {
/**
* Id of another block section of the same type, which should be applied to the node view before this modifier
*/
def parentId: scorex.util.ModifierId

}

object BlockSection {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.ergoplatform.modifiers

import io.circe.syntax._
import io.circe.{Decoder, Encoder, HCursor, Json}
import org.ergoplatform.TransactionsCarryingPersistentNodeViewModifier
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
Expand All @@ -15,8 +14,7 @@ case class ErgoFullBlock(header: Header,
blockTransactions: BlockTransactions,
extension: Extension,
adProofs: Option[ADProofs])
extends BlockSection
with TransactionsCarryingPersistentNodeViewModifier {
extends TransactionsCarryingBlockSection {

override type M = ErgoFullBlock

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,61 @@
package org.ergoplatform.modifiers

import org.ergoplatform.core.BytesSerializable
import org.ergoplatform.utils.ScorexEncoding
import scorex.util.{ModifierId, bytesToId}
import scorex.utils.Ints

trait ErgoNodeViewModifier { self: BytesSerializable =>
/**
* Basic trait for entities which are modifying internal blockchain view of the node, such as
* unconfirmed transactions, block sections
*/
trait ErgoNodeViewModifier extends BytesSerializable with ScorexEncoding {

/**
* @return cryptographically strong unique identifier of an object
*/
def serializedId: Array[Byte]

/**
* identifier which can is friendly to data structures such as maps etc
*/
lazy val id: ModifierId = bytesToId(serializedId)

/**
* Type of node view modifier (transaction, header etc)
*/
val modifierTypeId: NetworkObjectTypeId.Value

/**
* Size of binary representation provided during object construction (to avoid serialization just to get the value)
*/
val sizeOpt: Option[Int]

/**
* Cached size of binary representation
*/
lazy val size: Int = sizeOpt.getOrElse(bytes.length)

def serializedId: Array[Byte]
/**
* @return readable representation of `id`, as `id` is a hex-encoded string now, just identity functions is used
*/
def encodedId: String = id

override def equals(obj: scala.Any): Boolean = obj match {
case that: ErgoNodeViewModifier => (that.id == id) && (that.modifierTypeId == modifierTypeId)
case _ => false
}

override def hashCode(): Int = {
Ints.fromByteArray(serializedId)
}

}

object ErgoNodeViewModifier {
/**
* It is assumed that all the modifiers (offchain transactions, blocks, blockheaders etc)
* have identifiers of the some length fixed with the ModifierIdSize constant
*/
val ModifierIdSize: Int = 32 // in bytes
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.ergoplatform.modifiers

import org.ergoplatform.modifiers.mempool.ErgoTransaction

/**
* Block section which contains transactions
*/
trait TransactionsCarryingBlockSection extends BlockSection {

def transactions: Seq[ErgoTransaction]

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ package org.ergoplatform.modifiers.history

import io.circe.syntax._
import io.circe.{Decoder, Encoder, HCursor}
import org.ergoplatform.TransactionsCarryingPersistentNodeViewModifier
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.{BlockTransactionsTypeId, NetworkObjectTypeId, NonHeaderBlockSection}
import org.ergoplatform.modifiers.{BlockTransactionsTypeId, NetworkObjectTypeId, NonHeaderBlockSection, TransactionsCarryingBlockSection}
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, ErgoTransactionSerializer}
import org.ergoplatform.nodeView.mempool.TransactionMembershipProof
Expand Down Expand Up @@ -33,7 +32,7 @@ case class BlockTransactions(headerId: ModifierId,
blockVersion: Version,
txs: Seq[ErgoTransaction],
override val sizeOpt: Option[Int] = None)
extends NonHeaderBlockSection with TransactionsCarryingPersistentNodeViewModifier {
extends NonHeaderBlockSection with TransactionsCarryingBlockSection {

assert(txs.nonEmpty, "Block should always contain at least 1 coinbase-like transaction")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scorex.util.Extensions.LongOps
import scorex.util.ScorexLogging

/**
* A structure representing NiPoPow proof as a persistent modifier.
Expand All @@ -28,7 +29,7 @@ case class NipopowProof(popowAlgos: NipopowAlgos,
prefix: Seq[PoPowHeader],
suffixHead: PoPowHeader,
suffixTail: Seq[Header],
continuous: Boolean) {
continuous: Boolean) extends ScorexLogging {

lazy val serializer: ErgoSerializer[NipopowProof] = new NipopowProofSerializer(popowAlgos)

Expand All @@ -47,13 +48,20 @@ case class NipopowProof(popowAlgos: NipopowAlgos,
* @return whether this PoPoW proof is better than "that"
*/
def isBetterThan(that: NipopowProof): Boolean = {
if (this.isValid && that.isValid) {
popowAlgos.lowestCommonAncestor(headersChain, that.headersChain)
.map(h => headersChain.filter(_.height > h.height) -> that.headersChain.filter(_.height > h.height))
.exists({ case (thisDivergingChain, thatDivergingChain) =>
popowAlgos.bestArg(thisDivergingChain)(m) > popowAlgos.bestArg(thatDivergingChain)(m) })
} else {
this.isValid
try {
if (this.isValid && that.isValid) {
popowAlgos.lowestCommonAncestor(headersChain, that.headersChain)
.map(h => headersChain.filter(_.height > h.height) -> that.headersChain.filter(_.height > h.height))
.exists({ case (thisDivergingChain, thatDivergingChain) =>
popowAlgos.bestArg(thisDivergingChain)(m) > popowAlgos.bestArg(thatDivergingChain)(m)
})
} else {
this.isValid
}
} catch {
case t: Throwable =>
log.error(s"Nipopow proofs comparison (isBetter) failed due to ${t.getMessage}: ", t)
false
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package org.ergoplatform.modifiers.mempool

import io.circe.syntax._
import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, ErgoLikeTransaction, ErgoLikeTransactionSerializer, Input}
import org.ergoplatform.ErgoBox.BoxId
import org.ergoplatform.SigmaConstants.{MaxBoxSize, MaxPropositionBytes}
import org.ergoplatform.{EphemerealNodeViewModifier, _}
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.mining.emission.EmissionRules
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction.unresolvedIndices
import org.ergoplatform.modifiers.transaction.Transaction
import org.ergoplatform.modifiers.transaction.Signable
import org.ergoplatform.modifiers.{ErgoNodeViewModifier, NetworkObjectTypeId, TransactionTypeId}
import org.ergoplatform.nodeView.ErgoContext
import org.ergoplatform.nodeView.state.ErgoStateContext
Expand Down Expand Up @@ -57,11 +57,12 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
override val outputCandidates: IndexedSeq[ErgoBoxCandidate],
override val sizeOpt: Option[Int] = None)
extends ErgoLikeTransaction(inputs, dataInputs, outputCandidates)
with Transaction
with EphemerealNodeViewModifier
with Signable
with ErgoNodeViewModifier
with ScorexLogging {

override val modifierTypeId: NetworkObjectTypeId.Value = TransactionTypeId.value

override val serializedId: Array[Byte] = Algos.hash(messageToSign)

override lazy val id: ModifierId = bytesToId(serializedId)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.ergoplatform.modifiers.transaction


/**
* A basic trait for entities which can be signed
*/
trait Signable {

/**
* Bytes to be signed
*/
val messageToSign: Array[Byte]

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.ergoplatform.nodeView.history

import org.ergoplatform.NodeViewModifier
import org.ergoplatform.consensus.SyncInfo
import org.ergoplatform.modifiers.ErgoNodeViewModifier
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.network.message.SyncInfoMessageSpec
import org.ergoplatform.serialization.ErgoSerializer
Expand Down Expand Up @@ -100,7 +100,7 @@ object ErgoSyncInfoSerializer extends ErgoSerializer[ErgoSyncInfo] with ScorexLo
}
} else { // parse v1 sync message
require(length <= ErgoSyncInfo.MaxBlockIds + 1, "Too many block ids in sync info")
val ids = (1 to length).map(_ => bytesToId(r.getBytes(NodeViewModifier.ModifierIdSize)))
val ids = (1 to length).map(_ => bytesToId(r.getBytes(ErgoNodeViewModifier.ModifierIdSize)))
ErgoSyncInfoV1(ids)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class Parameters(val height: Height,
case _ => false
}

override def hashCode(): Height = height.hashCode() + parametersTable.hashCode()
override def hashCode(): Int = height.hashCode() + parametersTable.hashCode()
}

object Parameters {
Expand Down