-
Notifications
You must be signed in to change notification settings - Fork 295
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
primitives: Add initial proof-of-work funcs. #2788
Conversation
8fa898c
to
2debfc9
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.
Commit title typo rimitives: Add check proof of work.
.
2debfc9
to
be158f1
Compare
Corrected. |
8b581ad
to
eeea7b9
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.
Looks good to me. I confirmed that the behavior is the same as the corresponding functions in blockchain/standalone
. I just had a few minor comments inline.
eeea7b9
to
57ad6d4
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.
benchmarks
$ go test -bench .
goos: linux
goarch: amd64
pkg: github.com/decred/dcrd/internal/staging/primitives
cpu: AMD Ryzen 9 3900XT 12-Core Processor
BenchmarkDiffBitsToUint256-24 332246042 3.625 ns/op 0 B/op 0 allocs/op
BenchmarkUint256ToDiffBits-24 220453808 5.322 ns/op 0 B/op 0 allocs/op
BenchmarkCalcWork-24 28234624 41.63 ns/op 0 B/op 0 allocs/op
BenchmarkHashToUint256-24 500613214 2.060 ns/op 0 B/op 0 allocs/op
BenchmarkCheckProofOfWork-24 39382293 29.22 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/decred/dcrd/internal/staging/primitives 8.405s
57ad6d4
to
5e64822
Compare
5e64822
to
5940b5b
Compare
5940b5b
to
53dbfed
Compare
This implements code for converting between difficulty bits and the new uint256 type along with associated tests. The functions are the semantic equivalents of CompactToBig and BigToCompact from blockchain/standalone updated to use the new uint256 type instead of stdlib big integers and renamed to DiffBitsToUint256 and Uint256ToDiffBits, respectively. The primary motivation for renaming the functions to specifically call out difficulty bits instead of the shorter "Compact" is to prevent future ambiguity with Satoshi-style variable length compact integers that will ultimately also be available from the package. Note that for legacy reasons, even though the difficulty bits encoding is only used in Decred to encode unsigned 256-bit integers which represent difficulty targets, the encoding is capable of representing negative numbers as well as numbers much larger than the maximum value of an unsigned 256-bit integer. Therefore, in order to enable proper error detection and stay consistent with legacy code, DiffBitsToUint256 returns additional flags to indicate the aforementioned conditions.
The following is a comparison between the existing implementations in the blockchain/standalone module with big integers (old) and the new implementations (new) averaging 10 runs each: name old time/op new time/op delta ------------------------------------------------------------------------------ DiffBitsToUint256 158ns ± 1% 4ns ± 1% -97.35% (p=0.000 n=10+10) Uint256ToDiffBits 151ns ± 2% 8ns ± 4% -94.82% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ------------------------------------------------------------------------------- DiffBitsToUint256 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Uint256ToDiffBits 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10)
This implements code for calculating a uint256 work value from difficulty bits along with associated tests. The function is the semantic equivalent of CalcWork from blockchain/standalone updated to use and return the new uint256 type instead of stdlib big integers. Note that the original calculation involves a dividend of 2^256 which is not directly representable by a uint256, so this implementation retains the same semantics by transforming the calculation as described in detail by the comments.
The following is a comparison between the existing implementation in the blockchain/standalone module with big integers (old) and the new implementation (new) averaging 10 runs each: name old time/op new time/op delta --------------------------------------------------------------------- CalcWork 638ns ± 1% 59ns ± 1% -90.78% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ---------------------------------------------------------------------- CalcWork 7.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10)
This implements a function to convert a hash to the new uint256 type along with associated tests. The function is the semantic equivalent of HashToBig from blockchain/standalone updated to use and return the new uint256 type instead of stdlib big integers.
The following is a comparison between the existing implementation in the blockchain/standalone module with big integers (old) and the new implementation (new) averaging 10 runs each: name old time/op new time/op delta -------------------------------------------------------------------------- HashToUint256 127ns ± 3% 3ns ± 1% -97.68% (p=0.000 n=10+10) name old allocs/op new allocs/op delta --------------------------------------------------------------------------- HashToUint256 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10)
This implements functions to verify a block hash is less than the target difficulty represented by given difficulty bits and that said difficulty is in min/max range per a proof-of-work limit along with associated tests. It also introduces error infrastructure consistent with the rest of the code. The functions are the semantic equivalent of the functions of the same names from blockchain/standalone updated to use and accept the new uint256 type instead of stdlib big integers.
The following is a comparison between the existing implementation in the blockchain/standalone module with big integers (old) and the new implementation (new) averaging 10 runs each: name old time/op new time/op delta ----------------------------------------------------------------------------- CheckProofOfWork 314ns ± 1% 43ns ± 0% -86.42% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ------------------------------------------------------------------------------ CheckProofOfWork 5.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10)
53dbfed
to
92ccbee
Compare
This requires #2787.This introduces a primitives package that currently only contains functions related to proof of work along with comprehensive tests, benchmarks, full documentation and a skeleton
README.md
.These functions are all the semantic equivalents of their respective functions in
blockchain/standalone
updated to use, accept, and return the new uint256 type instead of stdlib big integers.Specifically, the following functions are updated and added along with their associated tests and benchmarks:
DiffBitsToUint256
(equiv tostandalone.CompactToBig
)Uint256ToDiffBits
(equiv tostandalone.BigToCompact
)CalcWork
(equiv tostandalone.CalcWork
)HashToUint256
(equiv tostandalone.HashToBig
)CheckProofOfWorkRange
(equiv tostandalone.CheckProofOfWorkRange
)CheckProofOfWork
(equiv tostandalone.CheckProofOfWork
)It is split into multiple commits to ease the review process and each commit further describes the relevant changes.
A few key points:
The primary motivation for renaming the functions to specifically call out difficulty bits instead of the shorter "Compact" is to prevent future ambiguity with Satoshi-style variable length compact integers that will ultimately also be available from the package.
For legacy reasons, even though the difficulty bits encoding is only used in Decred to encode unsigned 256-bit integers which represent difficulty targets, the encoding is capable of representing negative numbers as well as numbers much larger than the maximum value of an unsigned 256-bit integer. Therefore, in order to enable proper error detection and stay consistent with legacy code,
DiffBitsToUint256
returns additional flags to indicate the aforementioned conditions.The original calculation that
CalcWork
performed (and therefore is used in consensus and must stay the same) involves a dividend of 2^256 which is not directly representable by a uint256, so this implementation retains the same semantics by transforming the calculation as described in detail by the comments in the code.Benchmarks
The following is a comparison between the existing implementations in the blockchain/standalone module with big integers (old) and the new implementation (new) averaging 10 runs each:
This is work towards #2786.