-
Notifications
You must be signed in to change notification settings - Fork 78
[ETCM-1042] Switch to a case class implementation for blockchain branch #1073
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
Changes from all commits
a5bcb8a
6aabfe3
7b52b62
ea6936e
148d6a3
7b21a36
b1f28b9
f632017
6130c05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ import io.iohk.ethereum.db.storage.ReceiptStorage | |
| import io.iohk.ethereum.db.storage.StateStorage | ||
| import io.iohk.ethereum.domain.branch.BestBranch | ||
| import io.iohk.ethereum.domain.branch.Branch | ||
| import io.iohk.ethereum.domain.branch.EmptyBranch$ | ||
| import io.iohk.ethereum.domain.branch.EmptyBranch | ||
| import io.iohk.ethereum.mpt.MptNode | ||
| import io.iohk.ethereum.utils.Logger | ||
|
|
||
|
|
@@ -71,16 +71,14 @@ class BlockchainReader( | |
| def getReceiptsByHash(blockhash: ByteString): Option[Seq[Receipt]] = receiptStorage.get(blockhash) | ||
|
|
||
| /** get the current best stored branch */ | ||
| def getBestBranch(): Branch = | ||
| getBestBlock() | ||
| .map { block => | ||
| new BestBranch( | ||
| block.header, | ||
| blockNumberMappingStorage, | ||
| this | ||
| ) | ||
| } | ||
| .getOrElse(EmptyBranch$) | ||
| def getBestBranch(): Branch = { | ||
| val number = getBestBlockNumber() | ||
| blockNumberMappingStorage | ||
| .get(number) | ||
| .orElse(blockNumberMappingStorage.get(appStateStorage.getBestBlockNumber())) | ||
| .map(hash => BestBranch(hash, number)) | ||
| .getOrElse(EmptyBranch) | ||
AurelienRichez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| def getBestBlockNumber(): BigInt = { | ||
| val bestSavedBlockNumber = appStateStorage.getBestBlockNumber() | ||
|
|
@@ -113,6 +111,36 @@ class BlockchainReader( | |
| def genesisBlock: Block = | ||
| getBlockByNumber(0).get | ||
|
|
||
| /** Returns a block inside this branch based on its number */ | ||
| def getBlockByNumber(branch: Branch, number: BigInt): Option[Block] = branch match { | ||
| case BestBranch(_, tipBlockNumber) if tipBlockNumber >= number && number >= 0 => | ||
| for { | ||
| hash <- getHashByBlockNumber(number) | ||
| block <- getBlockByHash(hash) | ||
| } yield block | ||
| case EmptyBranch | BestBranch(_, _) => None | ||
| } | ||
|
|
||
| /** Returns a block hash for the block at the given height if any */ | ||
| def getHashByBlockNumber(branch: Branch, number: BigInt): Option[ByteString] = branch match { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what do you think of using a type alias for ByteString when we are talking about a hash?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer a value class or a tagged type, because the type alias would just be "cosmetic". But it would probably be out of scope to introduce the new type in this PR. |
||
| case BestBranch(_, tipBlockNumber) => | ||
| if (tipBlockNumber >= number && number >= 0) { | ||
| blockNumberMappingStorage.get(number) | ||
| } else None | ||
|
|
||
| case EmptyBranch => None | ||
| } | ||
|
|
||
| /** Checks if given block hash is in this chain. (i.e. is an ancestor of the tip block) */ | ||
| def isInChain(branch: Branch, hash: ByteString): Boolean = branch match { | ||
| case BestBranch(_, tipBlockNumber) => | ||
| (for { | ||
| header <- getBlockHeaderByHash(hash) if header.number <= tipBlockNumber | ||
| hashFromBestChain <- getHashByBlockNumber(branch, header.number) | ||
| } yield header.hash == hashFromBestChain).getOrElse(false) | ||
| case EmptyBranch => false | ||
| } | ||
|
|
||
| /** Allows to query for a block based on it's number | ||
| * | ||
| * @param number Block number | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,17 +2,8 @@ package io.iohk.ethereum.domain.branch | |
|
|
||
| import akka.util.ByteString | ||
|
|
||
| import io.iohk.ethereum.domain.Block | ||
| sealed trait Branch | ||
|
|
||
| /** An interface to manipulate blockchain branches */ | ||
| trait Branch { | ||
| case class BestBranch(tipBlockHash: ByteString, tipBlockNumber: BigInt) extends Branch | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can imagine this case class being used for all the branches, not only the best one
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does not contain data specific to the best branch, yes. Right now it is more a marker type to tell the code that we can use the block number -> hash index. |
||
|
|
||
| /** Returns a block inside this branch based on its number */ | ||
| def getBlockByNumber(number: BigInt): Option[Block] | ||
|
|
||
| /** Returns a block hash for the block at the given height if any */ | ||
| def getHashByBlockNumber(number: BigInt): Option[ByteString] | ||
|
|
||
| /** Checks if given block hash is in this chain. (i.e. is an ancestor of the tip block) */ | ||
| def isInChain(hash: ByteString): Boolean | ||
| } | ||
| case object EmptyBranch extends Branch | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we'll have multiple types of branch later on, right? For the purposes of the code you're changing now (branch as produced by
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we will have several types yes (well, best branch and "other" branch). I don't really know what to do with the |
||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this for? This is a work-around not related to this change, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it is not related to this change.
It's related to anastasiia's comment. It allows to be consistent with
getBestBlockwhich fallbacks to what is in the storage if the block from memory does not exists.