Skip to content

proof of work based on bitcoin. - #99

Merged
sinitcin merged 6 commits into
bamfrom
feat/PoW
Mar 29, 2022
Merged

proof of work based on bitcoin.#99
sinitcin merged 6 commits into
bamfrom
feat/PoW

Conversation

@b-yap

@b-yap b-yap commented Feb 10, 2022

Copy link
Copy Markdown
Contributor

continue from: #62

address comments:
#62 (comment)

I don't think the UpgradeVersion is necessary here.

#62 (comment)

Whenever you take a link from github, make sure you use a permalink, which contains the commit hash. You can do this by clicking on the ... on the left of the line number. Why? Because the master branch can always change.

#62 (comment)

This whole file should probably go into ChainConfig.
TARGET_TIMESPAN_SECS should be in ChainConfig, and should be returned as rust Duration.
Uint256 version should be derived from that, and not hardcoded.
TARGET_SPACING should certainly be in ChainConfig.
DIFFICULTY_ADJUSTMENT_INTERVAL should be a function.
TIMESPAN_ADJUSTMENT_FACTOR: This should be called MAX_DIFFICULTY_ADJUSTMENT_PER_INTERVAL, which is basically the max increase/decrease in work that can happen. This protects from having huge swings in difficulty. Also should go into ChainConfig
Finally, the upper and lower things also should be functions.
Preferably, find a way to group them all under PoW in ChainConfig instead of having them scattered. Maybe just prefix? Maybe substruct? I don't know. Please propose something.

#62 (comment)

The block index contains the height

#62 (comment)

call it "interval" instead of 2016 blocks

#62 (comment)

So why do we have a separate function for testnet if we do this check which is true anyway for testnet? Please combine both functions into one function and make them depend on ChainConfig.

Another TODO: To be created in another PR.
#62 (comment)

Sam: This isn't an operation I'm particularly happy about and I think we should discuss the reason why this is necessary. Since we're starting from scratch, let's try to make both H256 and Uint256 use the same order. No need to reverse things every time. This can get very confusing and error-prone very quickly.

Ben: As we briefly discussed earlier I think forking fixed_hash is the best way to approach this, my 30s peak makes it look like we should be dandy dependency wise so it's just a case of fixing the macros and tests and we should be good to go.

Comment thread consensus/src/pow/work.rs Outdated
Comment thread consensus/src/pow/work.rs Outdated
Comment thread consensus/src/pow/work.rs Outdated
Comment thread consensus/src/pow/work.rs Outdated
Comment thread consensus/src/pow/work.rs Outdated
let adjustment_interval = self.difficulty_adjustment_interval();

if is_for_retarget(adjustment_interval, current_height) {
let retarget_block_time = retarget_block_time(adjustment_interval, prev_block_index);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This doesn't seem to be correct. The block that you use to recalculate the new nBits is the first block in the 2016-block interval. Then, if that is longer than two weeks, the difficulty goes down. If it's less than two weeks, the difficulty goes up.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will rename the function to get_starting_block_time.

The function is using the prev_block_index to call the get_ancestor method, based on the adjustment interval.

Comment thread consensus/src/pow/work.rs
b-yap added a commit that referenced this pull request Feb 11, 2022
Comment thread consensus/src/pow/work.rs Outdated
Comment thread consensus/src/pow/work.rs Outdated
@b-yap
b-yap marked this pull request as ready for review February 18, 2022 08:01
@b-yap
b-yap requested a review from erubboli as a code owner February 18, 2022 08:01
@b-yap
b-yap marked this pull request as draft February 18, 2022 08:08
Comment thread common/src/chain/block/block_v1.rs Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I know this would deviate from Bitcoin but the difficulty is determined by the time difference of the last two blocks that are at a height that is a multiple of 2016, so this field is not needed. Even if the field is included, we need to check it has the correct value if it's relied upon for the difficulty check. Have you thought about getting rid of it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The bits field is being used in the ff. ways:

  1. When no_retargeting field in the config is set to true. That only happens for Regtest.
    ChainType::Regtest => true,
  2. if it's not due for retargeting yet, and allow_min_dfficulty_blocks is set to false, which is the Mainnet and Signet:
    ChainType::Mainnet | ChainType::Signet => false,

Let's say the current block height is 8067, and it's not due for retarget (since retarget has happened at 8064).
I am assuming that the difficulty is retrieved from the previous block, at height 8066. No calculation needed.
If we remove the bits field, we'll have to keep calculating the time diff of the blocks of height 8064 and 6048.

As for checking whether its value is correct, Did you mean the check_proof_of_work()? Or do you mean checking whether the previous block's bits field is a correct value?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As for checking whether its value is correct, Did you mean the check_proof_of_work()? Or do you mean checking whether the previous block's bits field is a correct value?

What I mean is that the value of the bits field cannot be trusted to contain the difficulty anyway. I see the get_work_required method here but I can't see it being used anywhere. I.e. at any point, the following must pass:

assert_eq!(calculate_difficulty_from_the_scratch(...).try_into(), Just(this_block.bits))

Blocks that do not satisfy that condition must be rejected, since the check_proof_of_work function relies on the bits field to contain accurate difficulty.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The get_work_required()(previously check_for_work_required()) will be used in the block production.
This was the earliest implementation : ed8db7d#diff-9a00856cffad13af6904b1cb9d4b5a4fd9e0591f10a35a67ddd805141890eeb6R91

But I removed it in this PR, because it's meant for the block production PR (which is currently closed, until Anton's or this is pushed).

Did you mean because the bits is a u32 representation, while the difficulty is 256, that's why the bits field can't be trusted? Or because the previous block can't be trusted, since the bits field can easily be just any number and not from a calculated value during the generation of the 2016th multiple block?

I haven't checked in bitcoin where that is, but we can actually add that kind of validation.

I somehow do agree with you; removing the bits field is not so bad, since we can always calculate for the difficulty. Your get_block_id_by_height function will be useful (Though I think I have to access it through the BlockIndex).

For now I've been following how Bitcoin does it. But also I don't have problems diverging from Bitcoin.
Although I don't know what Sam @TheQuantumPhysicist thinks, we can wait for his opinion.

@b-yap
b-yap changed the base branch from master to bam March 29, 2022 08:55
@b-yap
b-yap marked this pull request as ready for review March 29, 2022 09:07
@sinitcin
sinitcin merged commit bad4413 into bam Mar 29, 2022
@sinitcin
sinitcin deleted the feat/PoW branch March 29, 2022 09:37
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