chaincfg: Add IsBech32SegwitPrefix utility method.
The IsBech32SegwitPrefix method takes a string prefix and determines if it is a valid prefix for a Bech32 encoded segwit address for any of the default or registered networks.
This commit is contained in:
parent
9822ffad68
commit
47885ab870
2 changed files with 154 additions and 11 deletions
|
@ -8,6 +8,7 @@ import (
|
|||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
|
@ -195,8 +196,8 @@ type Params struct {
|
|||
// Mempool parameters
|
||||
RelayNonStdTxs bool
|
||||
|
||||
// Human-readable part for Bech32 encoded segwit addresses, as defined in
|
||||
// BIP 173.
|
||||
// Human-readable part for Bech32 encoded segwit addresses, as defined
|
||||
// in BIP 173.
|
||||
Bech32HRPSegwit string
|
||||
|
||||
// Address encoding magics
|
||||
|
@ -547,10 +548,11 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
registeredNets = make(map[wire.BitcoinNet]struct{})
|
||||
pubKeyHashAddrIDs = make(map[byte]struct{})
|
||||
scriptHashAddrIDs = make(map[byte]struct{})
|
||||
hdPrivToPubKeyIDs = make(map[[4]byte][]byte)
|
||||
registeredNets = make(map[wire.BitcoinNet]struct{})
|
||||
pubKeyHashAddrIDs = make(map[byte]struct{})
|
||||
scriptHashAddrIDs = make(map[byte]struct{})
|
||||
bech32SegwitPrefixes = make(map[string]struct{})
|
||||
hdPrivToPubKeyIDs = make(map[[4]byte][]byte)
|
||||
)
|
||||
|
||||
// String returns the hostname of the DNS seed in human-readable form.
|
||||
|
@ -575,6 +577,10 @@ func Register(params *Params) error {
|
|||
pubKeyHashAddrIDs[params.PubKeyHashAddrID] = struct{}{}
|
||||
scriptHashAddrIDs[params.ScriptHashAddrID] = struct{}{}
|
||||
hdPrivToPubKeyIDs[params.HDPrivateKeyID] = params.HDPublicKeyID[:]
|
||||
|
||||
// A valid Bech32 encoded segwit address always has as prefix the
|
||||
// human-readable part for the given net followed by '1'.
|
||||
bech32SegwitPrefixes[params.Bech32HRPSegwit+"1"] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -608,6 +614,15 @@ func IsScriptHashAddrID(id byte) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
// IsBech32SegwitPrefix returns whether the prefix is a known prefix for segwit
|
||||
// addresses on any default or registered network. This is used when decoding
|
||||
// an address string into a specific address type.
|
||||
func IsBech32SegwitPrefix(prefix string) bool {
|
||||
prefix = strings.ToLower(prefix)
|
||||
_, ok := bech32SegwitPrefixes[prefix]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HDPrivateKeyToPublicKeyID accepts a private hierarchical deterministic
|
||||
// extended key id and returns the associated public key id. When the provided
|
||||
// id is not registered, the ErrUnknownHDKeyID error will be returned.
|
||||
|
|
|
@ -3,6 +3,7 @@ package chaincfg_test
|
|||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/btcsuite/btcd/chaincfg"
|
||||
|
@ -16,6 +17,7 @@ var mockNetParams = Params{
|
|||
Net: 1<<32 - 1,
|
||||
PubKeyHashAddrID: 0x9f,
|
||||
ScriptHashAddrID: 0xf9,
|
||||
Bech32HRPSegwit: "tc",
|
||||
HDPrivateKeyID: [4]byte{0x01, 0x02, 0x03, 0x04},
|
||||
HDPublicKeyID: [4]byte{0x05, 0x06, 0x07, 0x08},
|
||||
}
|
||||
|
@ -30,6 +32,10 @@ func TestRegister(t *testing.T) {
|
|||
magic byte
|
||||
valid bool
|
||||
}
|
||||
type prefixTest struct {
|
||||
prefix string
|
||||
valid bool
|
||||
}
|
||||
type hdTest struct {
|
||||
priv []byte
|
||||
want []byte
|
||||
|
@ -37,11 +43,12 @@ func TestRegister(t *testing.T) {
|
|||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
register []registerTest
|
||||
p2pkhMagics []magicTest
|
||||
p2shMagics []magicTest
|
||||
hdMagics []hdTest
|
||||
name string
|
||||
register []registerTest
|
||||
p2pkhMagics []magicTest
|
||||
p2shMagics []magicTest
|
||||
segwitPrefixes []prefixTest
|
||||
hdMagics []hdTest
|
||||
}{
|
||||
{
|
||||
name: "default networks",
|
||||
|
@ -119,6 +126,44 @@ func TestRegister(t *testing.T) {
|
|||
valid: false,
|
||||
},
|
||||
},
|
||||
segwitPrefixes: []prefixTest{
|
||||
{
|
||||
prefix: MainNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: TestNet3Params.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: RegressionNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: SimNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: strings.ToUpper(MainNetParams.Bech32HRPSegwit + "1"),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: mockNetParams.Bech32HRPSegwit + "1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: "abc1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: "1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: MainNetParams.Bech32HRPSegwit,
|
||||
valid: false,
|
||||
},
|
||||
},
|
||||
hdMagics: []hdTest{
|
||||
{
|
||||
priv: MainNetParams.HDPrivateKeyID[:],
|
||||
|
@ -215,6 +260,44 @@ func TestRegister(t *testing.T) {
|
|||
valid: false,
|
||||
},
|
||||
},
|
||||
segwitPrefixes: []prefixTest{
|
||||
{
|
||||
prefix: MainNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: TestNet3Params.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: RegressionNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: SimNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: strings.ToUpper(MainNetParams.Bech32HRPSegwit + "1"),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: mockNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: "abc1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: "1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: MainNetParams.Bech32HRPSegwit,
|
||||
valid: false,
|
||||
},
|
||||
},
|
||||
hdMagics: []hdTest{
|
||||
{
|
||||
priv: mockNetParams.HDPrivateKeyID[:],
|
||||
|
@ -304,6 +387,44 @@ func TestRegister(t *testing.T) {
|
|||
valid: false,
|
||||
},
|
||||
},
|
||||
segwitPrefixes: []prefixTest{
|
||||
{
|
||||
prefix: MainNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: TestNet3Params.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: RegressionNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: SimNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: strings.ToUpper(MainNetParams.Bech32HRPSegwit + "1"),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: mockNetParams.Bech32HRPSegwit + "1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
prefix: "abc1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: "1",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
prefix: MainNetParams.Bech32HRPSegwit,
|
||||
valid: false,
|
||||
},
|
||||
},
|
||||
hdMagics: []hdTest{
|
||||
{
|
||||
priv: MainNetParams.HDPrivateKeyID[:],
|
||||
|
@ -364,6 +485,13 @@ func TestRegister(t *testing.T) {
|
|||
test.name, i, valid, magTest.valid)
|
||||
}
|
||||
}
|
||||
for i, prxTest := range test.segwitPrefixes {
|
||||
valid := IsBech32SegwitPrefix(prxTest.prefix)
|
||||
if valid != prxTest.valid {
|
||||
t.Errorf("%s: segwit prefix %s (%d) valid mismatch: got %v expected %v",
|
||||
test.name, prxTest.prefix, i, valid, prxTest.valid)
|
||||
}
|
||||
}
|
||||
for i, magTest := range test.hdMagics {
|
||||
pubKey, err := HDPrivateKeyToPublicKeyID(magTest.priv[:])
|
||||
if !reflect.DeepEqual(err, magTest.err) {
|
||||
|
|
Loading…
Reference in a new issue