mirror of https://github.com/guggero/chantools
multi: add bitcoin-descriptors to genimportscript
parent
f35a469949
commit
9fadec97a7
@ -0,0 +1,83 @@
|
||||
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
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package btc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testCases = []struct {
|
||||
descriptor string
|
||||
expectedSum string
|
||||
}{{
|
||||
descriptor: "addr(mkmZxiEcEd8ZqjQWVZuC6so5dFMKEFpN2j)",
|
||||
expectedSum: "#02wpgw69",
|
||||
}, {
|
||||
descriptor: "tr(cRhCT5vC5NdnSrQ2Jrah6NPCcth41uT8DWFmA6uD8R4x2ufucnYX)",
|
||||
expectedSum: "#gwfmkgga",
|
||||
}}
|
||||
|
||||
func TestDescriptorSum(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
sum := DescriptorSumCreate(tc.descriptor)
|
||||
require.Equal(t, tc.descriptor+tc.expectedSum, sum)
|
||||
|
||||
DescriptorSumCheck(sum, true)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue