-
Notifications
You must be signed in to change notification settings - Fork 75
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
[ETCM-75] Support for checkpoint blocks in Blockchain #716
Conversation
6ed0963
to
c40bc7b
Compare
else | ||
bestBlockNum | ||
} | ||
|
||
override def getLatestCheckpointBlockNumber(): BigInt = { | ||
val latestCheckpointNumberInStorage = appStateStorage.getLatestCheckpointBlockNumber() | ||
if (bestKnownBlockAndLatestCheckpoint.get().latestCheckpointNumber > latestCheckpointNumberInStorage) |
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.
Could you explain in what situation these numbers can be different?
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.
I'm not sure every border case here, but as far as I understand the best block number is firstly saved in memory and then persisted to the storage only when it's time to persist cache. I want to save the best block number and latest checkpoint transactionally so getLatestCheckpointBlockNumber
behaves the same. We can have the latest checkpoint number in memory bigger than the number in storage because the cache wasn't persisted yet.
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.
Ok, maybe add a comment about it?
c40bc7b
to
1529908
Compare
@@ -11,6 +12,9 @@ import org.scalatest.matchers.should.Matchers | |||
|
|||
class BlockchainSpec extends AnyFlatSpec with Matchers { | |||
|
|||
val checkpoint = ObjectGenerators.fakeCheckpointGen(2, 5).sample.get | |||
//val keys = Seq(generateKeyPair(secureRandom)) |
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.
Minor: remove
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.
Apart from minor issues LGTM!
prev.map { num => | ||
// side effect | ||
saveLatestCheckpointNumber(num) | ||
appStateStorage.putLatestCheckpointBlockNumber(num) |
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.
I am not sure about this bit.
Lets say we have saved X
blocks with all the mpt nodes i.e best checkpoint and best known block is X
. (for simplicity checkpoint and bestblock are the same)
Now we are on X + 20
(without updating bestblock and checkpoint in db) , last checkpoint was on X + 10
. We start to rollback and and we find this checkpint an we save into db. Now node dies.
After restart, best checkpoint in db will be X + 10
but best block will be X
as this was last time we sved all data.
Imo if we must to update best checkpoint in db, we should also update best block.
67348f8
to
a9c3dea
Compare
.commit() | ||
|
||
// not transactional part | ||
saveBestKnownBlocks(newBestBlockNumber, prevCheckpointNumber) |
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.
Should we also add this to our save function as well?
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.
in save
is different logic which controls what blocks data will be saved, so it's better to use low-level methods there
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.
And much more error prone... I think we'll suffer from this eventually 😕
val checkpointNumber = oldBranch | ||
.filter(_.block.hasCheckpoint) | ||
.sortBy(_.block.number) | ||
.lastOption |
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.
Minor: instead of sortBy and lastOption, should we maybe use max or maxBy?
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.
that was my first option, but maxBy/max are always returning value - in this case, we could have an empty list.
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.
Yeah, that's a pain of usage, but maybe we could have done Try(oldBranch.collect { case b if b.block.hasCheckpoint => b.block.number }).max).toOption
?
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.
IMHO your proposition is less readable, but it's probably doing one less iteration (filter, sortBy, lastOption vs collect, max). WDYT about .filter(_.block.hasCheckpoint).sortBy(-_.block.number).headOption
?
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.
a9c3dea
to
643d0c9
Compare
643d0c9
to
a2edd59
Compare
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.
LGTM!
.\\ //.
. \ \ / /.
.\ ,\ /` /,.-
-. \ /'/ / .
` - `-' \ -
'. /.\`
- .-
:`//.'
.`.'
.' BP
9af95a2
to
913a042
Compare
913a042
to
28fa411
Compare
Description
added saving last checkpoint number during block save and rollback
Important Changes Introduced
Testing
unit tests