You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chantools/btc/descriptors.go

84 lines
1.8 KiB
Go

package btc
import (
"strings"
)
var (
inputCharset = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ" +
"&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\\\"\\\\ "
checksumCharset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
generator = []uint64{
0xf5dee51989, 0xa9fdca3312, 0x1bab10e32d, 0x3706b1677a,
0x644d626ffd,
}
)
func descriptorSumPolymod(symbols []uint64) uint64 {
chk := uint64(1)
for _, value := range symbols {
top := chk >> 35
chk = (chk&0x7ffffffff)<<5 ^ value
for i := 0; i < 5; i++ {
if (top>>i)&1 != 0 {
chk ^= generator[i]
}
}
}
return chk
}
func descriptorSumExpand(s string) []uint64 {
groups := []uint64{}
symbols := []uint64{}
for _, c := range s {
v := strings.IndexRune(inputCharset, c)
if v < 0 {
return nil
}
symbols = append(symbols, uint64(v&31))
groups = append(groups, uint64(v>>5))
if len(groups) == 3 {
symbols = append(
symbols, groups[0]*9+groups[1]*3+groups[2],
)
groups = []uint64{}
}
}
if len(groups) == 1 {
symbols = append(symbols, groups[0])
} else if len(groups) == 2 {
symbols = append(symbols, groups[0]*3+groups[1])
}
return symbols
}
func DescriptorSumCreate(s string) string {
symbols := append(descriptorSumExpand(s), 0, 0, 0, 0, 0, 0, 0, 0)
checksum := descriptorSumPolymod(symbols) ^ 1
builder := strings.Builder{}
for i := 0; i < 8; i++ {
builder.WriteByte(checksumCharset[(checksum>>(5*(7-i)))&31])
}
return s + "#" + builder.String()
}
func DescriptorSumCheck(s string, require bool) bool {
if !strings.Contains(s, "#") {
return !require
}
if s[len(s)-9] != '#' {
return false
}
for _, c := range s[len(s)-8:] {
if !strings.ContainsRune(checksumCharset, c) {
return false
}
}
symbols := append(
descriptorSumExpand(s[:len(s)-9]),
uint64(strings.Index(checksumCharset, s[len(s)-8:])),
)
return descriptorSumPolymod(symbols) == 1
}