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

[ETCM-75] Support for checkpoint blocks in Blockchain #716

Merged
merged 1 commit into from
Oct 13, 2020

Conversation

pslaski
Copy link
Contributor

@pslaski pslaski commented Oct 1, 2020

Description

added saving last checkpoint number during block save and rollback

Important Changes Introduced

  • saving last checkpoint number to the memory and persisting it with best block number after cache persist during block save
  • persisting last checkpoint number and best block number immediately during block remove

Testing

unit tests

@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch from 6ed0963 to c40bc7b Compare October 1, 2020 14:21
else
bestBlockNum
}

override def getLatestCheckpointBlockNumber(): BigInt = {
val latestCheckpointNumberInStorage = appStateStorage.getLatestCheckpointBlockNumber()
if (bestKnownBlockAndLatestCheckpoint.get().latestCheckpointNumber > latestCheckpointNumberInStorage)
Copy link
Contributor

@rtkaczyk rtkaczyk Oct 1, 2020

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch from c40bc7b to 1529908 Compare October 2, 2020 11:36
@@ -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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: remove

Copy link
Contributor

@rtkaczyk rtkaczyk left a 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)
Copy link
Contributor

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.

@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch 3 times, most recently from 67348f8 to a9c3dea Compare October 8, 2020 16:44
src/main/scala/io/iohk/ethereum/domain/Blockchain.scala Outdated Show resolved Hide resolved
.commit()

// not transactional part
saveBestKnownBlocks(newBestBlockNumber, prevCheckpointNumber)
Copy link

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?

Copy link
Contributor Author

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

Copy link

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
Copy link

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?

Copy link
Contributor Author

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.

Copy link

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?

Copy link
Contributor Author

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 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch from a9c3dea to 643d0c9 Compare October 9, 2020 12:56
@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch from 643d0c9 to a2edd59 Compare October 9, 2020 14:18
Copy link

@ntallar ntallar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

 .\\            //.
. \ \          / /.
.\  ,\     /` /,.-
 -.   \  /'/ /  .
 ` -   `-'  \  -
   '.       /.\`
      -    .-
      :`//.'
      .`.'
      .' BP 

@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch 2 times, most recently from 9af95a2 to 913a042 Compare October 13, 2020 11:10
@pslaski pslaski force-pushed the etcm-75-blockchain-support-checkpoint branch from 913a042 to 28fa411 Compare October 13, 2020 11:14
@pslaski pslaski merged commit dd6d8e0 into develop Oct 13, 2020
@pslaski pslaski deleted the etcm-75-blockchain-support-checkpoint branch October 13, 2020 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants