2016-12-14 01:59:48 +03:00
|
|
|
package shachain
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
2017-02-23 06:13:56 +03:00
|
|
|
|
2018-06-05 04:34:16 +03:00
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
2016-12-14 01:59:48 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// getBit return bit on index at position.
|
|
|
|
func getBit(index index, position uint8) uint8 {
|
|
|
|
return uint8((uint64(index) >> position) & 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getPrefix(index index, position uint8) uint64 {
|
|
|
|
// + -------------------------- +
|
|
|
|
// | № | value | mask | return |
|
|
|
|
// + -- + ----- + ---- + ------ +
|
|
|
|
// | 63 | 1 | 0 | 0 |
|
|
|
|
// | 62 | 0 | 0 | 0 |
|
|
|
|
// | 61 | 1 | 0 | 0 |
|
|
|
|
// ....
|
|
|
|
// | 4 | 1 | 0 | 0 |
|
|
|
|
// | 3 | 1 | 0 | 0 |
|
|
|
|
// | 2 | 1 | 1 | 1 | <--- position
|
|
|
|
// | 1 | 0 | 1 | 0 |
|
|
|
|
// | 0 | 1 | 1 | 1 |
|
|
|
|
// + -- + ----- + ---- + ------ +
|
|
|
|
|
2017-02-23 22:56:47 +03:00
|
|
|
var zero uint64
|
2016-12-14 01:59:48 +03:00
|
|
|
mask := (zero - 1) - uint64((1<<position)-1)
|
|
|
|
return (uint64(index) & mask)
|
|
|
|
}
|
|
|
|
|
2018-04-18 05:03:27 +03:00
|
|
|
// countTrailingZeros counts number of trailing zero bits, this function is
|
2016-12-14 01:59:48 +03:00
|
|
|
// used to determine the number of element bucket.
|
|
|
|
func countTrailingZeros(index index) uint8 {
|
2017-02-23 22:56:47 +03:00
|
|
|
var zeros uint8
|
2016-12-14 01:59:48 +03:00
|
|
|
for ; zeros < maxHeight; zeros++ {
|
|
|
|
|
|
|
|
if getBit(index, zeros) != 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return zeros
|
|
|
|
}
|
|
|
|
|
2018-02-07 06:11:11 +03:00
|
|
|
// hashFromString takes a hex-encoded string as input and creates an instance of
|
2017-02-23 06:13:56 +03:00
|
|
|
// chainhash.Hash. The chainhash.NewHashFromStr function not suitable because
|
|
|
|
// it reverse the given hash.
|
2016-12-14 01:59:48 +03:00
|
|
|
func hashFromString(s string) (*chainhash.Hash, error) {
|
2017-02-23 06:13:56 +03:00
|
|
|
// Return an error if hash string is too long.
|
2016-12-14 01:59:48 +03:00
|
|
|
if len(s) > chainhash.MaxHashStringSize {
|
|
|
|
return nil, chainhash.ErrHashStrSize
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hex decoder expects the hash to be a multiple of two.
|
|
|
|
if len(s)%2 != 0 {
|
|
|
|
s = "0" + s
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert string hash to bytes.
|
|
|
|
buf, err := hex.DecodeString(s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
hash, err := chainhash.NewHash(buf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return hash, nil
|
|
|
|
}
|