[DEV-17] Move Bech32Prefix-related code from btcd/chaincfg/params.go to btcdutil (#62)

* [DEV-17] Moved Bech32 stuff from params.go to address.go.

* [DEV-17] Removed dagconfig dependency from address_test.go.

* [DEV-17] Removed dagconfig dependency from builder_test.go.

* [DEV-17] Removed dagconfig dependency from internal_test.go.

* [DEV-17] Removed dagconfig dependency from wif.go.

* [DEV-17] Removed dagconfig dependency from externdedkey.go.

* [DEV-17] Fixed compilation errors outside of hdkeychain.

* [DEV-17] Resolved circular dependencies.

* [DEV-17] Fixed failing tests.

* [DEV-17] Renamed DagXxx to Bech32PrefixDAGXxx

* [DEV-17] Fixed register_test.go.

* [DEV-17] Renamed HDKeyIDPairXxxNet to XxxNetHDKeyPair.

* [DEV-17] Renamed IsForNet to IsForPrefix.
This commit is contained in:
stasatdaglabs 2018-09-23 15:49:50 +03:00 committed by Svarog
parent 9b5aa66e5b
commit 6dd3b815c1
25 changed files with 606 additions and 593 deletions

View File

@ -6,6 +6,7 @@ package fullblocktests
import ( import (
"encoding/hex" "encoding/hex"
"github.com/daglabs/btcd/util/hdkeychain"
"math" "math"
"math/big" "math/big"
"time" "time"
@ -123,8 +124,7 @@ var regressionNetParams = &dagconfig.Params{
PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed)
// BIP32 hierarchical deterministic extended key magics // BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv HDKeyIDPair: hdkeychain.HDKeyPairRegressionNet,
HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub
// BIP44 coin type used in the hierarchical deterministic path for // BIP44 coin type used in the hierarchical deterministic path for
// address generation. // address generation.

View File

@ -731,7 +731,7 @@ func loadConfig() (*Config, []string, error) {
// Check mining addresses are valid and saved parsed versions. // Check mining addresses are valid and saved parsed versions.
cfg.MiningAddrs = make([]util.Address, 0, len(cfg.configFlags.MiningAddrs)) cfg.MiningAddrs = make([]util.Address, 0, len(cfg.configFlags.MiningAddrs))
for _, strAddr := range cfg.configFlags.MiningAddrs { for _, strAddr := range cfg.configFlags.MiningAddrs {
addr, err := util.DecodeAddress(strAddr, activeNetParams) addr, err := util.DecodeAddress(strAddr, activeNetParams.Prefix)
if err != nil { if err != nil {
str := "%s: mining address '%s' failed to decode: %v" str := "%s: mining address '%s' failed to decode: %v"
err := fmt.Errorf(str, funcName, strAddr, err) err := fmt.Errorf(str, funcName, strAddr, err)
@ -739,7 +739,7 @@ func loadConfig() (*Config, []string, error) {
fmt.Fprintln(os.Stderr, usageMessage) fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err return nil, nil, err
} }
if !addr.IsForNet(activeNetParams) { if !addr.IsForPrefix(activeNetParams.Prefix) {
str := "%s: mining address '%s' is on the wrong network" str := "%s: mining address '%s' is on the wrong network"
err := fmt.Errorf(str, funcName, strAddr) err := fmt.Errorf(str, funcName, strAddr)
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View File

@ -6,12 +6,12 @@ package dagconfig
import ( import (
"errors" "errors"
"github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/util/hdkeychain"
"math" "math"
"math/big" "math/big"
"time" "time"
"fmt"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/wire" "github.com/daglabs/btcd/wire"
) )
@ -96,57 +96,6 @@ const (
DefinedDeployments DefinedDeployments
) )
// Bech32Prefix is the human-readable prefix for a Bech32 address.
type Bech32Prefix int
// Constants that define Bech32 address prefixes. Every network is assigned
// a unique prefix.
const (
// Unknown/Erroneous prefix
Unknown Bech32Prefix = iota
// Prefix for the main network.
DagCoin
// Prefix for the regression test network.
DagReg
// Prefix for the test network.
DagTest
// Prefix for the simulation network.
DagSim
)
// Map from strings to Bech32 address prefix constants for parsing purposes.
var stringsToBech32Prefixes = map[string]Bech32Prefix{
"dagcoin": DagCoin,
"dagreg": DagReg,
"dagtest": DagTest,
"dagsim": DagSim,
}
// ParsePrefix attempts to parse a Bech32 address prefix.
func ParsePrefix(prefixString string) (Bech32Prefix, error) {
prefix, ok := stringsToBech32Prefixes[prefixString]
if !ok {
return Unknown, fmt.Errorf("could not parse prefix %v", prefixString)
}
return prefix, nil
}
// Converts from Bech32 address prefixes to their string values
func (prefix Bech32Prefix) String() string {
for key, value := range stringsToBech32Prefixes {
if prefix == value {
return key
}
}
return ""
}
// Params defines a Bitcoin network by its parameters. These parameters may be // Params defines a Bitcoin network by its parameters. These parameters may be
// used by Bitcoin applications to differentiate networks as well as addresses // used by Bitcoin applications to differentiate networks as well as addresses
// and keys for one network from those intended for use on another network. // and keys for one network from those intended for use on another network.
@ -245,14 +194,13 @@ type Params struct {
RelayNonStdTxs bool RelayNonStdTxs bool
// Human-readable prefix for Bech32 encoded addresses // Human-readable prefix for Bech32 encoded addresses
Prefix Bech32Prefix Prefix util.Bech32Prefix
// Address encoding magics // Address encoding magics
PrivateKeyID byte // First byte of a WIF private key PrivateKeyID byte // First byte of a WIF private key
// BIP32 hierarchical deterministic extended key magics // BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID [4]byte HDKeyIDPair hdkeychain.HDKeyIDPair
HDPublicKeyID [4]byte
// BIP44 coin type used in the hierarchical deterministic path for // BIP44 coin type used in the hierarchical deterministic path for
// address generation. // address generation.
@ -329,14 +277,13 @@ var MainNetParams = Params{
RelayNonStdTxs: false, RelayNonStdTxs: false,
// Human-readable part for Bech32 encoded addresses // Human-readable part for Bech32 encoded addresses
Prefix: DagCoin, Prefix: util.Bech32PrefixDAGCoin,
// Address encoding magics // Address encoding magics
PrivateKeyID: 0x80, // starts with 5 (uncompressed) or K (compressed) PrivateKeyID: 0x80, // starts with 5 (uncompressed) or K (compressed)
// BIP32 hierarchical deterministic extended key magics // BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID: [4]byte{0x04, 0x88, 0xad, 0xe4}, // starts with xprv HDKeyIDPair: hdkeychain.HDKeyPairMainNet,
HDPublicKeyID: [4]byte{0x04, 0x88, 0xb2, 0x1e}, // starts with xpub
// BIP44 coin type used in the hierarchical deterministic path for // BIP44 coin type used in the hierarchical deterministic path for
// address generation. // address generation.
@ -389,14 +336,13 @@ var RegressionNetParams = Params{
RelayNonStdTxs: true, RelayNonStdTxs: true,
// Human-readable part for Bech32 encoded addresses // Human-readable part for Bech32 encoded addresses
Prefix: DagReg, Prefix: util.Bech32PrefixDAGReg,
// Address encoding magics // Address encoding magics
PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed)
// BIP32 hierarchical deterministic extended key magics // BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv HDKeyIDPair: hdkeychain.HDKeyPairRegressionNet,
HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub
// BIP44 coin type used in the hierarchical deterministic path for // BIP44 coin type used in the hierarchical deterministic path for
// address generation. // address generation.
@ -466,14 +412,13 @@ var TestNet3Params = Params{
RelayNonStdTxs: true, RelayNonStdTxs: true,
// Human-readable part for Bech32 encoded addresses // Human-readable part for Bech32 encoded addresses
Prefix: DagTest, Prefix: util.Bech32PrefixDAGTest,
// Address encoding magics // Address encoding magics
PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed)
// BIP32 hierarchical deterministic extended key magics // BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv HDKeyIDPair: hdkeychain.HDKeyPairTestNet,
HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub
// BIP44 coin type used in the hierarchical deterministic path for // BIP44 coin type used in the hierarchical deterministic path for
// address generation. // address generation.
@ -531,11 +476,10 @@ var SimNetParams = Params{
PrivateKeyID: 0x64, // starts with 4 (uncompressed) or F (compressed) PrivateKeyID: 0x64, // starts with 4 (uncompressed) or F (compressed)
// Human-readable part for Bech32 encoded addresses // Human-readable part for Bech32 encoded addresses
Prefix: DagSim, Prefix: util.Bech32PrefixDAGSim,
// BIP32 hierarchical deterministic extended key magics // BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID: [4]byte{0x04, 0x20, 0xb9, 0x00}, // starts with sprv HDKeyIDPair: hdkeychain.HDKeyPairSimNet,
HDPublicKeyID: [4]byte{0x04, 0x20, 0xbd, 0x3a}, // starts with spub
// BIP44 coin type used in the hierarchical deterministic path for // BIP44 coin type used in the hierarchical deterministic path for
// address generation. // address generation.
@ -547,16 +491,10 @@ var (
// network could not be set due to the network already being a standard // network could not be set due to the network already being a standard
// network or previously-registered into this package. // network or previously-registered into this package.
ErrDuplicateNet = errors.New("duplicate Bitcoin network") ErrDuplicateNet = errors.New("duplicate Bitcoin network")
// ErrUnknownHDKeyID describes an error where the provided id which
// is intended to identify the network for a hierarchical deterministic
// private extended key is not registered.
ErrUnknownHDKeyID = errors.New("unknown hd private extended key bytes")
) )
var ( var (
registeredNets = make(map[wire.BitcoinNet]struct{}) registeredNets = make(map[wire.BitcoinNet]struct{})
hdPrivToPubKeyIDs = make(map[[4]byte][]byte)
) )
// String returns the hostname of the DNS seed in human-readable form. // String returns the hostname of the DNS seed in human-readable form.
@ -578,7 +516,6 @@ func Register(params *Params) error {
return ErrDuplicateNet return ErrDuplicateNet
} }
registeredNets[params.Net] = struct{}{} registeredNets[params.Net] = struct{}{}
hdPrivToPubKeyIDs[params.HDPrivateKeyID] = params.HDPublicKeyID[:]
return nil return nil
} }
@ -591,24 +528,6 @@ func mustRegister(params *Params) {
} }
} }
// 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.
func HDPrivateKeyToPublicKeyID(id []byte) ([]byte, error) {
if len(id) != 4 {
return nil, ErrUnknownHDKeyID
}
var key [4]byte
copy(key[:], id)
pubBytes, ok := hdPrivToPubKeyIDs[key]
if !ok {
return nil, ErrUnknownHDKeyID
}
return pubBytes, nil
}
// newHashFromStr converts the passed big-endian hex string into a // newHashFromStr converts the passed big-endian hex string into a
// daghash.Hash. It only differs from the one available in daghash in that // daghash.Hash. It only differs from the one available in daghash in that
// it panics on an error since it will only (and must only) be called with // it panics on an error since it will only (and must only) be called with

View File

@ -34,57 +34,6 @@ func TestMustRegisterPanic(t *testing.T) {
mustRegister(&MainNetParams) mustRegister(&MainNetParams)
} }
func TestParsePrefix(t *testing.T) {
tests := []struct {
prefixStr string
expectedPrefix Bech32Prefix
expectedError bool
}{
{"dagcoin", DagCoin, false},
{"dagreg", DagReg, false},
{"dagtest", DagTest, false},
{"dagsim", DagSim, false},
{"blabla", Unknown, true},
{"unknown", Unknown, true},
{"", Unknown, true},
}
for _, test := range tests {
result, err := ParsePrefix(test.prefixStr)
if (err != nil) != test.expectedError {
t.Errorf("TestParsePrefix: %s: expected error status: %t, but got %t",
test.prefixStr, test.expectedError, (err != nil))
}
if result != test.expectedPrefix {
t.Errorf("TestParsePrefix: %s: expected prefix: %d, but got %d",
test.prefixStr, test.expectedPrefix, result)
}
}
}
func TestPrefixToString(t *testing.T) {
tests := []struct {
prefix Bech32Prefix
expectedPrefixStr string
}{
{DagCoin, "dagcoin"},
{DagReg, "dagreg"},
{DagTest, "dagtest"},
{DagSim, "dagsim"},
{Unknown, ""},
}
for _, test := range tests {
result := test.prefix.String()
if result != test.expectedPrefixStr {
t.Errorf("TestPrefixToString: %s: expected string: %s, but got %s",
test.prefix, test.expectedPrefixStr, result)
}
}
}
func TestDNSSeedToString(t *testing.T) { func TestDNSSeedToString(t *testing.T) {
host := "test.dns.seed.com" host := "test.dns.seed.com"
seed := DNSSeed{HasFiltering: false, Host: host} seed := DNSSeed{HasFiltering: false, Host: host}

View File

@ -2,6 +2,7 @@ package dagconfig_test
import ( import (
"bytes" "bytes"
"github.com/daglabs/btcd/util/hdkeychain"
"reflect" "reflect"
"testing" "testing"
@ -12,10 +13,12 @@ import (
// network. This is necessary to test the registration of and // network. This is necessary to test the registration of and
// lookup of encoding magics from the network. // lookup of encoding magics from the network.
var mockNetParams = Params{ var mockNetParams = Params{
Name: "mocknet", Name: "mocknet",
Net: 1<<32 - 1, Net: 1<<32 - 1,
HDPrivateKeyID: [4]byte{0x01, 0x02, 0x03, 0x04}, HDKeyIDPair: hdkeychain.HDKeyIDPair{
HDPublicKeyID: [4]byte{0x05, 0x06, 0x07, 0x08}, PrivateKeyID: [4]byte{0x01, 0x02, 0x03, 0x04},
PublicKeyID: [4]byte{0x05, 0x06, 0x07, 0x08},
},
} }
func TestRegister(t *testing.T) { func TestRegister(t *testing.T) {
@ -24,10 +27,6 @@ func TestRegister(t *testing.T) {
params *Params params *Params
err error err error
} }
type prefixTest struct {
prefix string
valid bool
}
type hdTest struct { type hdTest struct {
priv []byte priv []byte
want []byte want []byte
@ -65,36 +64,36 @@ func TestRegister(t *testing.T) {
}, },
hdMagics: []hdTest{ hdMagics: []hdTest{
{ {
priv: MainNetParams.HDPrivateKeyID[:], priv: MainNetParams.HDKeyIDPair.PrivateKeyID[:],
want: MainNetParams.HDPublicKeyID[:], want: MainNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: TestNet3Params.HDPrivateKeyID[:], priv: TestNet3Params.HDKeyIDPair.PrivateKeyID[:],
want: TestNet3Params.HDPublicKeyID[:], want: TestNet3Params.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: RegressionNetParams.HDPrivateKeyID[:], priv: RegressionNetParams.HDKeyIDPair.PrivateKeyID[:],
want: RegressionNetParams.HDPublicKeyID[:], want: RegressionNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: SimNetParams.HDPrivateKeyID[:], priv: SimNetParams.HDKeyIDPair.PrivateKeyID[:],
want: SimNetParams.HDPublicKeyID[:], want: SimNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: mockNetParams.HDPrivateKeyID[:], priv: mockNetParams.HDKeyIDPair.PrivateKeyID[:],
err: ErrUnknownHDKeyID, err: hdkeychain.ErrUnknownHDKeyID,
}, },
{ {
priv: []byte{0xff, 0xff, 0xff, 0xff}, priv: []byte{0xff, 0xff, 0xff, 0xff},
err: ErrUnknownHDKeyID, err: hdkeychain.ErrUnknownHDKeyID,
}, },
{ {
priv: []byte{0xff}, priv: []byte{0xff},
err: ErrUnknownHDKeyID, err: hdkeychain.ErrUnknownHDKeyID,
}, },
}, },
}, },
@ -109,8 +108,8 @@ func TestRegister(t *testing.T) {
}, },
hdMagics: []hdTest{ hdMagics: []hdTest{
{ {
priv: mockNetParams.HDPrivateKeyID[:], priv: mockNetParams.HDKeyIDPair.PrivateKeyID[:],
want: mockNetParams.HDPublicKeyID[:], want: mockNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
}, },
@ -146,37 +145,37 @@ func TestRegister(t *testing.T) {
}, },
hdMagics: []hdTest{ hdMagics: []hdTest{
{ {
priv: MainNetParams.HDPrivateKeyID[:], priv: MainNetParams.HDKeyIDPair.PrivateKeyID[:],
want: MainNetParams.HDPublicKeyID[:], want: MainNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: TestNet3Params.HDPrivateKeyID[:], priv: TestNet3Params.HDKeyIDPair.PrivateKeyID[:],
want: TestNet3Params.HDPublicKeyID[:], want: TestNet3Params.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: RegressionNetParams.HDPrivateKeyID[:], priv: RegressionNetParams.HDKeyIDPair.PrivateKeyID[:],
want: RegressionNetParams.HDPublicKeyID[:], want: RegressionNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: SimNetParams.HDPrivateKeyID[:], priv: SimNetParams.HDKeyIDPair.PrivateKeyID[:],
want: SimNetParams.HDPublicKeyID[:], want: SimNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: mockNetParams.HDPrivateKeyID[:], priv: mockNetParams.HDKeyIDPair.PrivateKeyID[:],
want: mockNetParams.HDPublicKeyID[:], want: mockNetParams.HDKeyIDPair.PublicKeyID[:],
err: nil, err: nil,
}, },
{ {
priv: []byte{0xff, 0xff, 0xff, 0xff}, priv: []byte{0xff, 0xff, 0xff, 0xff},
err: ErrUnknownHDKeyID, err: hdkeychain.ErrUnknownHDKeyID,
}, },
{ {
priv: []byte{0xff}, priv: []byte{0xff},
err: ErrUnknownHDKeyID, err: hdkeychain.ErrUnknownHDKeyID,
}, },
}, },
}, },
@ -185,13 +184,17 @@ func TestRegister(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, regTest := range test.register { for _, regTest := range test.register {
err := Register(regTest.params) err := Register(regTest.params)
// HDKeyIDPairs must be registered separately
hdkeychain.RegisterHDKeyIDPair(regTest.params.HDKeyIDPair)
if err != regTest.err { if err != regTest.err {
t.Errorf("%s:%s: Registered network with unexpected error: got %v expected %v", t.Errorf("%s:%s: Registered network with unexpected error: got %v expected %v",
test.name, regTest.name, err, regTest.err) test.name, regTest.name, err, regTest.err)
} }
} }
for i, magTest := range test.hdMagics { for i, magTest := range test.hdMagics {
pubKey, err := HDPrivateKeyToPublicKeyID(magTest.priv[:]) pubKey, err := hdkeychain.HDPrivateKeyToPublicKeyID(magTest.priv[:])
if !reflect.DeepEqual(err, magTest.err) { if !reflect.DeepEqual(err, magTest.err) {
t.Errorf("%s: HD magic %d mismatched error: got %v expected %v ", t.Errorf("%s: HD magic %d mismatched error: got %v expected %v ",
test.name, i, err, magTest.err) test.name, i, err, magTest.err)

View File

@ -118,7 +118,7 @@ func newMemWallet(net *dagconfig.Params, harnessID uint32) (*memWallet, error) {
copy(harnessHDSeed[:], hdSeed[:]) copy(harnessHDSeed[:], hdSeed[:])
binary.BigEndian.PutUint32(harnessHDSeed[:daghash.HashSize], harnessID) binary.BigEndian.PutUint32(harnessHDSeed[:daghash.HashSize], harnessID)
hdRoot, err := hdkeychain.NewMaster(harnessHDSeed[:], net) hdRoot, err := hdkeychain.NewMaster(harnessHDSeed[:], net.HDKeyIDPair.PrivateKeyID)
if err != nil { if err != nil {
return nil, nil return nil, nil
} }
@ -562,7 +562,7 @@ func (m *memWallet) ConfirmedBalance() util.Amount {
// keyToAddr maps the passed private to corresponding p2pkh address. // keyToAddr maps the passed private to corresponding p2pkh address.
func keyToAddr(key *btcec.PrivateKey, net *dagconfig.Params) (util.Address, error) { func keyToAddr(key *btcec.PrivateKey, net *dagconfig.Params) (util.Address, error) {
serializedKey := key.PubKey().SerializeCompressed() serializedKey := key.PubKey().SerializeCompressed()
pubKeyAddr, err := util.NewAddressPubKey(serializedKey, net) pubKeyAddr, err := util.NewAddressPubKey(serializedKey, net.Prefix)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -257,7 +257,7 @@ func newPoolHarness(dagParams *dagconfig.Params, dbName string) (*poolHarness, [
// Generate associated pay-to-script-hash address and resulting payment // Generate associated pay-to-script-hash address and resulting payment
// script. // script.
pubKeyBytes := signPub.SerializeCompressed() pubKeyBytes := signPub.SerializeCompressed()
payPubKeyAddr, err := util.NewAddressPubKey(pubKeyBytes, dagParams) payPubKeyAddr, err := util.NewAddressPubKey(pubKeyBytes, dagParams.Prefix)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -10,11 +10,10 @@ import (
"time" "time"
"github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
) )
// TestCalcMinRequiredTxRelayFee tests the calcMinRequiredTxRelayFee API. // TestCalcMinRequiredTxRelayFee tests the calcMinRequiredTxRelayFee API.
@ -292,8 +291,7 @@ func TestCheckTransactionStandard(t *testing.T) {
Sequence: wire.MaxTxInSequenceNum, Sequence: wire.MaxTxInSequenceNum,
} }
addrHash := [20]byte{0x01} addrHash := [20]byte{0x01}
addr, err := util.NewAddressPubKeyHash(addrHash[:], addr, err := util.NewAddressPubKeyHash(addrHash[:], util.Bech32PrefixDAGTest)
&dagconfig.TestNet3Params)
if err != nil { if err != nil {
t.Fatalf("NewAddressPubKeyHash: unexpected error: %v", err) t.Fatalf("NewAddressPubKeyHash: unexpected error: %v", err)
} }

View File

@ -183,5 +183,4 @@ var privKeyBytes, _ = hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
var privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) var privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
var pubKeyHash = util.Hash160(pubKey.SerializeCompressed()) var pubKeyHash = util.Hash160(pubKey.SerializeCompressed())
var addr, err = util.NewAddressPubKeyHash(pubKeyHash, var addr, _ = util.NewAddressPubKeyHash(pubKeyHash, util.Bech32PrefixDAGCoin)
&dagconfig.MainNetParams)

View File

@ -9,10 +9,9 @@ import (
"strconv" "strconv"
"github.com/daglabs/btcd/btcjson" "github.com/daglabs/btcd/btcjson"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
) )
// ***************************** // *****************************
@ -771,7 +770,7 @@ func (r FutureAddMultisigAddressResult) Receive() (util.Address, error) {
return nil, err return nil, err
} }
return util.DecodeAddress(addr, &dagconfig.MainNetParams) return util.DecodeAddress(addr, util.Bech32PrefixDAGCoin)
} }
// AddMultisigAddressAsync returns an instance of a type that can be used to get // AddMultisigAddressAsync returns an instance of a type that can be used to get
@ -885,7 +884,7 @@ func (r FutureGetNewAddressResult) Receive() (util.Address, error) {
return nil, err return nil, err
} }
return util.DecodeAddress(addr, &dagconfig.MainNetParams) return util.DecodeAddress(addr, util.Bech32PrefixDAGCoin)
} }
// GetNewAddressAsync returns an instance of a type that can be used to get the // GetNewAddressAsync returns an instance of a type that can be used to get the
@ -923,7 +922,7 @@ func (r FutureGetRawChangeAddressResult) Receive() (util.Address, error) {
return nil, err return nil, err
} }
return util.DecodeAddress(addr, &dagconfig.MainNetParams) return util.DecodeAddress(addr, util.Bech32PrefixDAGCoin)
} }
// GetRawChangeAddressAsync returns an instance of a type that can be used to // GetRawChangeAddressAsync returns an instance of a type that can be used to
@ -962,7 +961,7 @@ func (r FutureGetAccountAddressResult) Receive() (util.Address, error) {
return nil, err return nil, err
} }
return util.DecodeAddress(addr, &dagconfig.MainNetParams) return util.DecodeAddress(addr, util.Bech32PrefixDAGCoin)
} }
// GetAccountAddressAsync returns an instance of a type that can be used to get // GetAccountAddressAsync returns an instance of a type that can be used to get
@ -1068,7 +1067,7 @@ func (r FutureGetAddressesByAccountResult) Receive() ([]util.Address, error) {
addrs := make([]util.Address, 0, len(addrStrings)) addrs := make([]util.Address, 0, len(addrStrings))
for _, addrStr := range addrStrings { for _, addrStr := range addrStrings {
addr, err := util.DecodeAddress(addrStr, addr, err := util.DecodeAddress(addrStr,
&dagconfig.MainNetParams) util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -557,7 +557,7 @@ func handleCreateRawTransaction(s *Server, cmd interface{}, closeChan <-chan str
} }
// Decode the provided address. // Decode the provided address.
addr, err := util.DecodeAddress(encodedAddr, params) addr, err := util.DecodeAddress(encodedAddr, params.Prefix)
if err != nil { if err != nil {
return nil, &btcjson.RPCError{ return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidAddressOrKey, Code: btcjson.ErrRPCInvalidAddressOrKey,
@ -577,7 +577,7 @@ func handleCreateRawTransaction(s *Server, cmd interface{}, closeChan <-chan str
Message: "Invalid address or key", Message: "Invalid address or key",
} }
} }
if !addr.IsForNet(params) { if !addr.IsForPrefix(params.Prefix) {
return nil, &btcjson.RPCError{ return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidAddressOrKey, Code: btcjson.ErrRPCInvalidAddressOrKey,
Message: "Invalid address: " + encodedAddr + Message: "Invalid address: " + encodedAddr +
@ -818,7 +818,7 @@ func handleDecodeScript(s *Server, cmd interface{}, closeChan <-chan struct{}) (
} }
// Convert the script itself to a pay-to-script-hash address. // Convert the script itself to a pay-to-script-hash address.
p2sh, err := util.NewAddressScriptHash(script, s.cfg.ChainParams) p2sh, err := util.NewAddressScriptHash(script, s.cfg.ChainParams.Prefix)
if err != nil { if err != nil {
context := "Failed to convert script to pay-to-script-hash" context := "Failed to convert script to pay-to-script-hash"
return nil, internalRPCError(err.Error(), context) return nil, internalRPCError(err.Error(), context)
@ -2913,7 +2913,7 @@ func handleSearchRawTransactions(s *Server, cmd interface{}, closeChan <-chan st
// Attempt to decode the supplied address. // Attempt to decode the supplied address.
params := s.cfg.ChainParams params := s.cfg.ChainParams
addr, err := util.DecodeAddress(c.Address, params) addr, err := util.DecodeAddress(c.Address, params.Prefix)
if err != nil { if err != nil {
return nil, &btcjson.RPCError{ return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidAddressOrKey, Code: btcjson.ErrRPCInvalidAddressOrKey,
@ -3313,7 +3313,7 @@ func handleValidateAddress(s *Server, cmd interface{}, closeChan <-chan struct{}
c := cmd.(*btcjson.ValidateAddressCmd) c := cmd.(*btcjson.ValidateAddressCmd)
result := btcjson.ValidateAddressResult{} result := btcjson.ValidateAddressResult{}
addr, err := util.DecodeAddress(c.Address, s.cfg.ChainParams) addr, err := util.DecodeAddress(c.Address, s.cfg.ChainParams.Prefix)
if err != nil { if err != nil {
// Return the default value (false) for IsValid. // Return the default value (false) for IsValid.
return result, nil return result, nil
@ -3385,7 +3385,7 @@ func handleVerifyMessage(s *Server, cmd interface{}, closeChan <-chan struct{})
// Decode the provided address. // Decode the provided address.
params := s.cfg.ChainParams params := s.cfg.ChainParams
addr, err := util.DecodeAddress(c.Address, params) addr, err := util.DecodeAddress(c.Address, params.Prefix)
if err != nil { if err != nil {
return nil, &btcjson.RPCError{ return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidAddressOrKey, Code: btcjson.ErrRPCInvalidAddressOrKey,
@ -3431,7 +3431,7 @@ func handleVerifyMessage(s *Server, cmd interface{}, closeChan <-chan struct{})
} else { } else {
serializedPK = pk.SerializeUncompressed() serializedPK = pk.SerializeUncompressed()
} }
address, err := util.NewAddressPubKey(serializedPK, params) address, err := util.NewAddressPubKey(serializedPK, params.Prefix)
if err != nil { if err != nil {
// Again mirror Bitcoin Core behavior, which treats error in public key // Again mirror Bitcoin Core behavior, which treats error in public key
// reconstruction as invalid signature. // reconstruction as invalid signature.

View File

@ -28,8 +28,8 @@ import (
"github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
) )
const ( const (
@ -330,7 +330,7 @@ func (f *wsClientFilter) addAddressStr(s string, params *dagconfig.Params) {
// If address can't be decoded, no point in saving it since it should also // If address can't be decoded, no point in saving it since it should also
// impossible to create the address from an inspected transaction output // impossible to create the address from an inspected transaction output
// script. // script.
a, err := util.DecodeAddress(s, params) a, err := util.DecodeAddress(s, params.Prefix)
if err != nil { if err != nil {
return return
} }
@ -411,7 +411,7 @@ func (f *wsClientFilter) removeAddress(a util.Address) {
// //
// NOTE: This extension was ported from github.com/decred/dcrd // NOTE: This extension was ported from github.com/decred/dcrd
func (f *wsClientFilter) removeAddressStr(s string, params *dagconfig.Params) { func (f *wsClientFilter) removeAddressStr(s string, params *dagconfig.Params) {
a, err := util.DecodeAddress(s, params) a, err := util.DecodeAddress(s, params.Prefix)
if err == nil { if err == nil {
f.removeAddress(a) f.removeAddress(a)
} else { } else {
@ -1539,8 +1539,8 @@ out:
} }
waiting = true waiting = true
// This channel is notified when a notification has been sent // This channel is notified when a notification has been sent
// across the network socket. // across the network socket.
case <-ntfnSentChan: case <-ntfnSentChan:
// No longer waiting if there are no more messages in // No longer waiting if there are no more messages in
// the pending messages queue. // the pending messages queue.
@ -1948,7 +1948,7 @@ func handleStopNotifyReceived(wsc *wsClient, icmd interface{}) (interface{}, err
// properly, the function returns an error. Otherwise, nil is returned. // properly, the function returns an error. Otherwise, nil is returned.
func checkAddressValidity(addrs []string, params *dagconfig.Params) error { func checkAddressValidity(addrs []string, params *dagconfig.Params) error {
for _, addr := range addrs { for _, addr := range addrs {
_, err := util.DecodeAddress(addr, params) _, err := util.DecodeAddress(addr, params.Prefix)
if err != nil { if err != nil {
return &btcjson.RPCError{ return &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidAddressOrKey, Code: btcjson.ErrRPCInvalidAddressOrKey,

View File

@ -12,8 +12,8 @@ import (
"github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
) )
// This example demonstrates creating a script which pays to a bitcoin address. // This example demonstrates creating a script which pays to a bitcoin address.
@ -25,7 +25,7 @@ func ExamplePayToAddrScript() {
// the address type. It is also required for the upcoming call to // the address type. It is also required for the upcoming call to
// PayToAddrScript. // PayToAddrScript.
addressStr := "dagcoin:qqfgqp8l9l90zwetj84k2jcac2m8falvvy9uastr55" addressStr := "dagcoin:qqfgqp8l9l90zwetj84k2jcac2m8falvvy9uastr55"
address, err := util.DecodeAddress(addressStr, &dagconfig.MainNetParams) address, err := util.DecodeAddress(addressStr, util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
@ -91,8 +91,7 @@ func ExampleSignTxOutput() {
} }
privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
pubKeyHash := util.Hash160(pubKey.SerializeCompressed()) pubKeyHash := util.Hash160(pubKey.SerializeCompressed())
addr, err := util.NewAddressPubKeyHash(pubKeyHash, addr, err := util.NewAddressPubKeyHash(pubKeyHash, util.Bech32PrefixDAGCoin)
&dagconfig.MainNetParams)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return

View File

@ -12,8 +12,8 @@ import (
"github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
) )
type addressToKey struct { type addressToKey struct {
@ -152,7 +152,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -189,7 +189,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -250,7 +250,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -288,7 +288,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -348,7 +348,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -385,7 +385,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -445,7 +445,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -482,7 +482,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -543,7 +543,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -558,7 +558,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -599,7 +599,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -614,7 +614,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -681,7 +681,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -695,7 +695,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -737,7 +737,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKeyHash( address, err := util.NewAddressPubKeyHash(
util.Hash160(pk), &dagconfig.TestNet3Params) util.Hash160(pk), util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -751,7 +751,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -817,7 +817,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -831,7 +831,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -872,7 +872,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed() SerializeUncompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -886,7 +886,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -951,7 +951,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -965,7 +965,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -1005,7 +1005,7 @@ func TestSignTxOutput(t *testing.T) {
pk := (*btcec.PublicKey)(&key.PublicKey). pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeCompressed() SerializeCompressed()
address, err := util.NewAddressPubKey(pk, &dagconfig.TestNet3Params) address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -1019,7 +1019,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -1084,7 +1084,7 @@ func TestSignTxOutput(t *testing.T) {
pk1 := (*btcec.PublicKey)(&key1.PublicKey). pk1 := (*btcec.PublicKey)(&key1.PublicKey).
SerializeCompressed() SerializeCompressed()
address1, err := util.NewAddressPubKey(pk1, &dagconfig.TestNet3Params) address1, err := util.NewAddressPubKey(pk1, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -1100,7 +1100,7 @@ func TestSignTxOutput(t *testing.T) {
pk2 := (*btcec.PublicKey)(&key2.PublicKey). pk2 := (*btcec.PublicKey)(&key2.PublicKey).
SerializeCompressed() SerializeCompressed()
address2, err := util.NewAddressPubKey(pk2, &dagconfig.TestNet3Params) address2, err := util.NewAddressPubKey(pk2, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address 2 for %s: %v", t.Errorf("failed to make address 2 for %s: %v",
msg, err) msg, err)
@ -1116,7 +1116,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -1157,7 +1157,7 @@ func TestSignTxOutput(t *testing.T) {
pk1 := (*btcec.PublicKey)(&key1.PublicKey). pk1 := (*btcec.PublicKey)(&key1.PublicKey).
SerializeCompressed() SerializeCompressed()
address1, err := util.NewAddressPubKey(pk1, &dagconfig.TestNet3Params) address1, err := util.NewAddressPubKey(pk1, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -1173,7 +1173,7 @@ func TestSignTxOutput(t *testing.T) {
pk2 := (*btcec.PublicKey)(&key2.PublicKey). pk2 := (*btcec.PublicKey)(&key2.PublicKey).
SerializeCompressed() SerializeCompressed()
address2, err := util.NewAddressPubKey(pk2, &dagconfig.TestNet3Params) address2, err := util.NewAddressPubKey(pk2, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address 2 for %s: %v", t.Errorf("failed to make address 2 for %s: %v",
msg, err) msg, err)
@ -1189,7 +1189,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)
@ -1259,7 +1259,7 @@ func TestSignTxOutput(t *testing.T) {
pk1 := (*btcec.PublicKey)(&key1.PublicKey). pk1 := (*btcec.PublicKey)(&key1.PublicKey).
SerializeCompressed() SerializeCompressed()
address1, err := util.NewAddressPubKey(pk1, &dagconfig.TestNet3Params) address1, err := util.NewAddressPubKey(pk1, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address for %s: %v", t.Errorf("failed to make address for %s: %v",
msg, err) msg, err)
@ -1275,7 +1275,7 @@ func TestSignTxOutput(t *testing.T) {
pk2 := (*btcec.PublicKey)(&key2.PublicKey). pk2 := (*btcec.PublicKey)(&key2.PublicKey).
SerializeCompressed() SerializeCompressed()
address2, err := util.NewAddressPubKey(pk2, &dagconfig.TestNet3Params) address2, err := util.NewAddressPubKey(pk2, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make address 2 for %s: %v", t.Errorf("failed to make address 2 for %s: %v",
msg, err) msg, err)
@ -1291,7 +1291,7 @@ func TestSignTxOutput(t *testing.T) {
} }
scriptAddr, err := util.NewAddressScriptHash( scriptAddr, err := util.NewAddressScriptHash(
pkScript, &dagconfig.TestNet3Params) pkScript, util.Bech32PrefixDAGTest)
if err != nil { if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v", t.Errorf("failed to make p2sh addr for %s: %v",
msg, err) msg, err)

View File

@ -430,7 +430,7 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (Scrip
// Skip the pubkey hash if it's invalid for some reason. // Skip the pubkey hash if it's invalid for some reason.
requiredSigs = 1 requiredSigs = 1
addr, err := util.NewAddressPubKeyHash(pops[2].data, addr, err := util.NewAddressPubKeyHash(pops[2].data,
chainParams) chainParams.Prefix)
if err == nil { if err == nil {
addrs = append(addrs, addr) addrs = append(addrs, addr)
} }
@ -441,7 +441,7 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (Scrip
// Therefore the pubkey is the first item on the stack. // Therefore the pubkey is the first item on the stack.
// Skip the pubkey if it's invalid for some reason. // Skip the pubkey if it's invalid for some reason.
requiredSigs = 1 requiredSigs = 1
addr, err := util.NewAddressPubKey(pops[0].data, chainParams) addr, err := util.NewAddressPubKey(pops[0].data, chainParams.Prefix)
if err == nil { if err == nil {
addrs = append(addrs, addr) addrs = append(addrs, addr)
} }
@ -453,7 +453,7 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (Scrip
// Skip the script hash if it's invalid for some reason. // Skip the script hash if it's invalid for some reason.
requiredSigs = 1 requiredSigs = 1
addr, err := util.NewAddressScriptHashFromHash(pops[1].data, addr, err := util.NewAddressScriptHashFromHash(pops[1].data,
chainParams) chainParams.Prefix)
if err == nil { if err == nil {
addrs = append(addrs, addr) addrs = append(addrs, addr)
} }
@ -470,7 +470,7 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (Scrip
// Extract the public keys while skipping any that are invalid. // Extract the public keys while skipping any that are invalid.
addrs = make([]util.Address, 0, numPubKeys) addrs = make([]util.Address, 0, numPubKeys)
for i := 0; i < numPubKeys; i++ { for i := 0; i < numPubKeys; i++ {
addr, err := util.NewAddressPubKey(pops[i+1].data, chainParams) addr, err := util.NewAddressPubKey(pops[i+1].data, chainParams.Prefix)
if err == nil { if err == nil {
addrs = append(addrs, addr) addrs = append(addrs, addr)
} }

View File

@ -32,7 +32,7 @@ func mustParseShortForm(script string) []byte {
// the tests as a helper since the only way it can fail is if there is an error // the tests as a helper since the only way it can fail is if there is an error
// in the test source code. // in the test source code.
func newAddressPubKey(serializedPubKey []byte) util.Address { func newAddressPubKey(serializedPubKey []byte) util.Address {
addr, err := util.NewAddressPubKey(serializedPubKey, &dagconfig.MainNetParams) addr, err := util.NewAddressPubKey(serializedPubKey, util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
panic("invalid public key in test source") panic("invalid public key in test source")
} }
@ -45,7 +45,7 @@ func newAddressPubKey(serializedPubKey []byte) util.Address {
// as a helper since the only way it can fail is if there is an error in the // as a helper since the only way it can fail is if there is an error in the
// test source code. // test source code.
func newAddressPubKeyHash(pkHash []byte) util.Address { func newAddressPubKeyHash(pkHash []byte) util.Address {
addr, err := util.NewAddressPubKeyHash(pkHash, &dagconfig.MainNetParams) addr, err := util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
panic("invalid public key hash in test source") panic("invalid public key hash in test source")
} }
@ -59,7 +59,7 @@ func newAddressPubKeyHash(pkHash []byte) util.Address {
// test source code. // test source code.
func newAddressScriptHash(scriptHash []byte) util.Address { func newAddressScriptHash(scriptHash []byte) util.Address {
addr, err := util.NewAddressScriptHashFromHash(scriptHash, addr, err := util.NewAddressScriptHashFromHash(scriptHash,
&dagconfig.MainNetParams) util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
panic("invalid script hash in test source") panic("invalid script hash in test source")
} }
@ -497,8 +497,8 @@ func (b *bogusAddress) ScriptAddress() []byte {
return nil return nil
} }
// IsForNet lies blatantly to satisfy the util.Address interface. // IsForPrefix lies blatantly to satisfy the util.Address interface.
func (b *bogusAddress) IsForNet(chainParams *dagconfig.Params) bool { func (b *bogusAddress) IsForPrefix(prefix util.Bech32Prefix) bool {
return true // why not? return true // why not?
} }
@ -515,7 +515,7 @@ func TestPayToAddrScript(t *testing.T) {
// 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX
p2pkhMain, err := util.NewAddressPubKeyHash(hexToBytes("e34cce70c86"+ p2pkhMain, err := util.NewAddressPubKeyHash(hexToBytes("e34cce70c86"+
"373273efcc54ce7d2a491bb4a0e84"), &dagconfig.MainNetParams) "373273efcc54ce7d2a491bb4a0e84"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create public key hash address: %v", err) t.Fatalf("Unable to create public key hash address: %v", err)
} }
@ -523,20 +523,20 @@ func TestPayToAddrScript(t *testing.T) {
// Taken from transaction: // Taken from transaction:
// b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d // b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d
p2shMain, _ := util.NewAddressScriptHashFromHash(hexToBytes("e8c300"+ p2shMain, _ := util.NewAddressScriptHashFromHash(hexToBytes("e8c300"+
"c87986efa84c37c0519929019ef86eb5b4"), &dagconfig.MainNetParams) "c87986efa84c37c0519929019ef86eb5b4"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create script hash address: %v", err) t.Fatalf("Unable to create script hash address: %v", err)
} }
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
p2pkCompressedMain, err := util.NewAddressPubKey(hexToBytes("02192d"+ p2pkCompressedMain, err := util.NewAddressPubKey(hexToBytes("02192d"+
"74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), &dagconfig.MainNetParams) "74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create pubkey address (compressed): %v", t.Fatalf("Unable to create pubkey address (compressed): %v",
err) err)
} }
p2pkCompressed2Main, err := util.NewAddressPubKey(hexToBytes("03b0b"+ p2pkCompressed2Main, err := util.NewAddressPubKey(hexToBytes("03b0b"+
"d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), &dagconfig.MainNetParams) "d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create pubkey address (compressed 2): %v", t.Fatalf("Unable to create pubkey address (compressed 2): %v",
err) err)
@ -545,7 +545,7 @@ func TestPayToAddrScript(t *testing.T) {
p2pkUncompressedMain, err := util.NewAddressPubKey(hexToBytes("0411"+ p2pkUncompressedMain, err := util.NewAddressPubKey(hexToBytes("0411"+
"db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+ "db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+
"cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+ "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+
"12a3"), &dagconfig.MainNetParams) "12a3"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create pubkey address (uncompressed): %v", t.Fatalf("Unable to create pubkey address (uncompressed): %v",
err) err)
@ -632,13 +632,13 @@ func TestMultiSigScript(t *testing.T) {
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
p2pkCompressedMain, err := util.NewAddressPubKey(hexToBytes("02192d"+ p2pkCompressedMain, err := util.NewAddressPubKey(hexToBytes("02192d"+
"74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), &dagconfig.MainNetParams) "74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create pubkey address (compressed): %v", t.Fatalf("Unable to create pubkey address (compressed): %v",
err) err)
} }
p2pkCompressed2Main, err := util.NewAddressPubKey(hexToBytes("03b0b"+ p2pkCompressed2Main, err := util.NewAddressPubKey(hexToBytes("03b0b"+
"d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), &dagconfig.MainNetParams) "d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create pubkey address (compressed 2): %v", t.Fatalf("Unable to create pubkey address (compressed 2): %v",
err) err)
@ -647,7 +647,7 @@ func TestMultiSigScript(t *testing.T) {
p2pkUncompressedMain, err := util.NewAddressPubKey(hexToBytes("0411"+ p2pkUncompressedMain, err := util.NewAddressPubKey(hexToBytes("0411"+
"db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+ "db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+
"cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+ "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+
"12a3"), &dagconfig.MainNetParams) "12a3"), util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Unable to create pubkey address (uncompressed): %v", t.Fatalf("Unable to create pubkey address (uncompressed): %v",
err) err)

View File

@ -8,9 +8,7 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/util/bech32" "github.com/daglabs/btcd/util/bech32"
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
@ -35,11 +33,62 @@ const (
scriptHashAddrID = 0x08 scriptHashAddrID = 0x08
) )
// Bech32Prefix is the human-readable prefix for a Bech32 address.
type Bech32Prefix int
// Constants that define Bech32 address prefixes. Every network is assigned
// a unique prefix.
const (
// Unknown/Erroneous prefix
Bech32PrefixUnknown Bech32Prefix = iota
// Prefix for the main network.
Bech32PrefixDAGCoin
// Prefix for the regression test network.
Bech32PrefixDAGReg
// Prefix for the test network.
Bech32PrefixDAGTest
// Prefix for the simulation network.
Bech32PrefixDAGSim
)
// Map from strings to Bech32 address prefix constants for parsing purposes.
var stringsToBech32Prefixes = map[string]Bech32Prefix{
"dagcoin": Bech32PrefixDAGCoin,
"dagreg": Bech32PrefixDAGReg,
"dagtest": Bech32PrefixDAGTest,
"dagsim": Bech32PrefixDAGSim,
}
// ParsePrefix attempts to parse a Bech32 address prefix.
func ParsePrefix(prefixString string) (Bech32Prefix, error) {
prefix, ok := stringsToBech32Prefixes[prefixString]
if !ok {
return Bech32PrefixUnknown, fmt.Errorf("could not parse prefix %v", prefixString)
}
return prefix, nil
}
// Converts from Bech32 address prefixes to their string values
func (prefix Bech32Prefix) String() string {
for key, value := range stringsToBech32Prefixes {
if prefix == value {
return key
}
}
return ""
}
// encodeAddress returns a human-readable payment address given a network prefix // encodeAddress returns a human-readable payment address given a network prefix
// and a ripemd160 hash which encodes the bitcoin network and address type. It is used // and a ripemd160 hash which encodes the bitcoin network and address type. It is used
// in both pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address // in both pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address
// encoding. // encoding.
func encodeAddress(prefix dagconfig.Bech32Prefix, hash160 []byte, version byte) string { func encodeAddress(prefix Bech32Prefix, hash160 []byte, version byte) string {
return bech32.Encode(prefix.String(), hash160[:ripemd160.Size], version) return bech32.Encode(prefix.String(), hash160[:ripemd160.Size], version)
} }
@ -68,9 +117,9 @@ type Address interface {
// when inserting the address into a txout's script. // when inserting the address into a txout's script.
ScriptAddress() []byte ScriptAddress() []byte
// IsForNet returns whether or not the address is associated with the // IsForPrefix returns whether or not the address is associated with the
// passed bitcoin network. // passed bitcoin network.
IsForNet(*dagconfig.Params) bool IsForPrefix(prefix Bech32Prefix) bool
} }
// DecodeAddress decodes the string encoding of an address and returns // DecodeAddress decodes the string encoding of an address and returns
@ -79,17 +128,17 @@ type Address interface {
// The bitcoin network address is associated with is extracted if possible. // The bitcoin network address is associated with is extracted if possible.
// When the address does not encode the network, such as in the case of a raw // When the address does not encode the network, such as in the case of a raw
// public key, the address will be associated with the passed defaultNet. // public key, the address will be associated with the passed defaultNet.
func DecodeAddress(addr string, defaultNet *dagconfig.Params) (Address, error) { func DecodeAddress(addr string, defaultPrefix Bech32Prefix) (Address, error) {
prefixString, decoded, version, err := bech32.Decode(addr) prefixString, decoded, version, err := bech32.Decode(addr)
if err != nil { if err != nil {
return nil, fmt.Errorf("decoded address is of unknown format: %v", err) return nil, fmt.Errorf("decoded address is of unknown format: %v", err)
} }
prefix, err := dagconfig.ParsePrefix(prefixString) prefix, err := ParsePrefix(prefixString)
if err != nil { if err != nil {
return nil, fmt.Errorf("decoded address's prefix could not be parsed: %v", err) return nil, fmt.Errorf("decoded address's prefix could not be parsed: %v", err)
} }
if defaultNet.Prefix != prefix { if defaultPrefix != prefix {
return nil, fmt.Errorf("decoded address is of wrong network: %v", err) return nil, fmt.Errorf("decoded address is of wrong network: %v", err)
} }
@ -98,9 +147,9 @@ func DecodeAddress(addr string, defaultNet *dagconfig.Params) (Address, error) {
case ripemd160.Size: // P2PKH or P2SH case ripemd160.Size: // P2PKH or P2SH
switch version { switch version {
case pubKeyHashAddrID: case pubKeyHashAddrID:
return newAddressPubKeyHash(defaultNet.Prefix, decoded) return newAddressPubKeyHash(defaultPrefix, decoded)
case scriptHashAddrID: case scriptHashAddrID:
return newAddressScriptHashFromHash(defaultNet.Prefix, decoded) return newAddressScriptHashFromHash(defaultPrefix, decoded)
default: default:
return nil, ErrUnknownAddressType return nil, ErrUnknownAddressType
} }
@ -112,14 +161,14 @@ func DecodeAddress(addr string, defaultNet *dagconfig.Params) (Address, error) {
// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH) // AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// transaction. // transaction.
type AddressPubKeyHash struct { type AddressPubKeyHash struct {
prefix dagconfig.Bech32Prefix prefix Bech32Prefix
hash [ripemd160.Size]byte hash [ripemd160.Size]byte
} }
// NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash mustbe 20 // NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash mustbe 20
// bytes. // bytes.
func NewAddressPubKeyHash(pkHash []byte, net *dagconfig.Params) (*AddressPubKeyHash, error) { func NewAddressPubKeyHash(pkHash []byte, prefix Bech32Prefix) (*AddressPubKeyHash, error) {
return newAddressPubKeyHash(net.Prefix, pkHash) return newAddressPubKeyHash(prefix, pkHash)
} }
// newAddressPubKeyHash is the internal API to create a pubkey hash address // newAddressPubKeyHash is the internal API to create a pubkey hash address
@ -127,7 +176,7 @@ func NewAddressPubKeyHash(pkHash []byte, net *dagconfig.Params) (*AddressPubKeyH
// it up through its parameters. This is useful when creating a new address // it up through its parameters. This is useful when creating a new address
// structure from a string encoding where the identifer byte is already // structure from a string encoding where the identifer byte is already
// known. // known.
func newAddressPubKeyHash(prefix dagconfig.Bech32Prefix, pkHash []byte) (*AddressPubKeyHash, error) { func newAddressPubKeyHash(prefix Bech32Prefix, pkHash []byte) (*AddressPubKeyHash, error) {
// Check for a valid pubkey hash length. // Check for a valid pubkey hash length.
if len(pkHash) != ripemd160.Size { if len(pkHash) != ripemd160.Size {
return nil, errors.New("pkHash must be 20 bytes") return nil, errors.New("pkHash must be 20 bytes")
@ -150,10 +199,10 @@ func (a *AddressPubKeyHash) ScriptAddress() []byte {
return a.hash[:] return a.hash[:]
} }
// IsForNet returns whether or not the pay-to-pubkey-hash address is associated // IsForPrefix returns whether or not the pay-to-pubkey-hash address is associated
// with the passed bitcoin network. // with the passed bitcoin network.
func (a *AddressPubKeyHash) IsForNet(net *dagconfig.Params) bool { func (a *AddressPubKeyHash) IsForPrefix(prefix Bech32Prefix) bool {
return a.prefix == net.Prefix return a.prefix == prefix
} }
// String returns a human-readable string for the pay-to-pubkey-hash address. // String returns a human-readable string for the pay-to-pubkey-hash address.
@ -173,20 +222,20 @@ func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
// AddressScriptHash is an Address for a pay-to-script-hash (P2SH) // AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// transaction. // transaction.
type AddressScriptHash struct { type AddressScriptHash struct {
prefix dagconfig.Bech32Prefix prefix Bech32Prefix
hash [ripemd160.Size]byte hash [ripemd160.Size]byte
} }
// NewAddressScriptHash returns a new AddressScriptHash. // NewAddressScriptHash returns a new AddressScriptHash.
func NewAddressScriptHash(serializedScript []byte, net *dagconfig.Params) (*AddressScriptHash, error) { func NewAddressScriptHash(serializedScript []byte, prefix Bech32Prefix) (*AddressScriptHash, error) {
scriptHash := Hash160(serializedScript) scriptHash := Hash160(serializedScript)
return newAddressScriptHashFromHash(net.Prefix, scriptHash) return newAddressScriptHashFromHash(prefix, scriptHash)
} }
// NewAddressScriptHashFromHash returns a new AddressScriptHash. scriptHash // NewAddressScriptHashFromHash returns a new AddressScriptHash. scriptHash
// must be 20 bytes. // must be 20 bytes.
func NewAddressScriptHashFromHash(scriptHash []byte, net *dagconfig.Params) (*AddressScriptHash, error) { func NewAddressScriptHashFromHash(scriptHash []byte, prefix Bech32Prefix) (*AddressScriptHash, error) {
return newAddressScriptHashFromHash(net.Prefix, scriptHash) return newAddressScriptHashFromHash(prefix, scriptHash)
} }
// newAddressScriptHashFromHash is the internal API to create a script hash // newAddressScriptHashFromHash is the internal API to create a script hash
@ -194,7 +243,7 @@ func NewAddressScriptHashFromHash(scriptHash []byte, net *dagconfig.Params) (*Ad
// looking it up through its parameters. This is useful when creating a new // looking it up through its parameters. This is useful when creating a new
// address structure from a string encoding where the identifer byte is already // address structure from a string encoding where the identifer byte is already
// known. // known.
func newAddressScriptHashFromHash(prefix dagconfig.Bech32Prefix, scriptHash []byte) (*AddressScriptHash, error) { func newAddressScriptHashFromHash(prefix Bech32Prefix, scriptHash []byte) (*AddressScriptHash, error) {
// Check for a valid script hash length. // Check for a valid script hash length.
if len(scriptHash) != ripemd160.Size { if len(scriptHash) != ripemd160.Size {
return nil, errors.New("scriptHash must be 20 bytes") return nil, errors.New("scriptHash must be 20 bytes")
@ -217,10 +266,10 @@ func (a *AddressScriptHash) ScriptAddress() []byte {
return a.hash[:] return a.hash[:]
} }
// IsForNet returns whether or not the pay-to-script-hash address is associated // IsForPrefix returns whether or not the pay-to-script-hash address is associated
// with the passed bitcoin network. // with the passed bitcoin network.
func (a *AddressScriptHash) IsForNet(net *dagconfig.Params) bool { func (a *AddressScriptHash) IsForPrefix(prefix Bech32Prefix) bool {
return a.prefix == net.Prefix return a.prefix == prefix
} }
// String returns a human-readable string for the pay-to-script-hash address. // String returns a human-readable string for the pay-to-script-hash address.
@ -256,7 +305,7 @@ const (
// AddressPubKey is an Address for a pay-to-pubkey transaction. // AddressPubKey is an Address for a pay-to-pubkey transaction.
type AddressPubKey struct { type AddressPubKey struct {
prefix dagconfig.Bech32Prefix prefix Bech32Prefix
pubKeyFormat PubKeyFormat pubKeyFormat PubKeyFormat
pubKey *btcec.PublicKey pubKey *btcec.PublicKey
pubKeyHashID byte pubKeyHashID byte
@ -265,7 +314,7 @@ type AddressPubKey struct {
// NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey // NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey
// address. The serializedPubKey parameter must be a valid pubkey and can be // address. The serializedPubKey parameter must be a valid pubkey and can be
// uncompressed, compressed, or hybrid. // uncompressed, compressed, or hybrid.
func NewAddressPubKey(serializedPubKey []byte, net *dagconfig.Params) (*AddressPubKey, error) { func NewAddressPubKey(serializedPubKey []byte, prefix Bech32Prefix) (*AddressPubKey, error) {
pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256())
if err != nil { if err != nil {
return nil, err return nil, err
@ -287,7 +336,7 @@ func NewAddressPubKey(serializedPubKey []byte, net *dagconfig.Params) (*AddressP
pubKeyFormat: pkFormat, pubKeyFormat: pkFormat,
pubKey: pubKey, pubKey: pubKey,
pubKeyHashID: pubKeyHashAddrID, pubKeyHashID: pubKeyHashAddrID,
prefix: net.Prefix, prefix: prefix,
}, nil }, nil
} }
@ -327,10 +376,10 @@ func (a *AddressPubKey) ScriptAddress() []byte {
return a.serialize() return a.serialize()
} }
// IsForNet returns whether or not the pay-to-pubkey address is associated // IsForPrefix returns whether or not the pay-to-pubkey address is associated
// with the passed bitcoin network. // with the passed bitcoin network.
func (a *AddressPubKey) IsForNet(net *dagconfig.Params) bool { func (a *AddressPubKey) IsForPrefix(prefix Bech32Prefix) bool {
return a.prefix == net.Prefix return a.prefix == prefix
} }
// String returns the hex-encoded human-readable string for the pay-to-pubkey // String returns the hex-encoded human-readable string for the pay-to-pubkey

View File

@ -12,7 +12,6 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
@ -25,7 +24,7 @@ func TestAddresses(t *testing.T) {
valid bool valid bool
result util.Address result util.Address
f func() (util.Address, error) f func() (util.Address, error)
net *dagconfig.Params prefix util.Bech32Prefix
}{ }{
// Positive P2PKH tests. // Positive P2PKH tests.
{ {
@ -34,7 +33,7 @@ func TestAddresses(t *testing.T) {
encoded: "dagcoin:qr35ennsep3hxfe7lnz5ee7j5jgmkjswss74as46gy", encoded: "dagcoin:qr35ennsep3hxfe7lnz5ee7j5jgmkjswss74as46gy",
valid: true, valid: true,
result: util.TstAddressPubKeyHash( result: util.TstAddressPubKeyHash(
dagconfig.DagCoin, util.Bech32PrefixDAGCoin,
[ripemd160.Size]byte{ [ripemd160.Size]byte{
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84}), 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84}),
@ -42,9 +41,9 @@ func TestAddresses(t *testing.T) {
pkHash := []byte{ pkHash := []byte{
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84} 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84}
return util.NewAddressPubKeyHash(pkHash, &dagconfig.MainNetParams) return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixDAGCoin)
}, },
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
{ {
name: "mainnet p2pkh 2", name: "mainnet p2pkh 2",
@ -52,7 +51,7 @@ func TestAddresses(t *testing.T) {
encoded: "dagcoin:qq80qvqs0lfxuzmt7sz3909ze6camq9d4gwzqeljga", encoded: "dagcoin:qq80qvqs0lfxuzmt7sz3909ze6camq9d4gwzqeljga",
valid: true, valid: true,
result: util.TstAddressPubKeyHash( result: util.TstAddressPubKeyHash(
dagconfig.DagCoin, util.Bech32PrefixDAGCoin,
[ripemd160.Size]byte{ [ripemd160.Size]byte{
0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4,
0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa}), 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa}),
@ -60,9 +59,9 @@ func TestAddresses(t *testing.T) {
pkHash := []byte{ pkHash := []byte{
0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4,
0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa} 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa}
return util.NewAddressPubKeyHash(pkHash, &dagconfig.MainNetParams) return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixDAGCoin)
}, },
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
{ {
name: "testnet p2pkh", name: "testnet p2pkh",
@ -70,7 +69,7 @@ func TestAddresses(t *testing.T) {
encoded: "dagtest:qputx94qseratdmjs0j395mq8u03er0x3ucluj5qam", encoded: "dagtest:qputx94qseratdmjs0j395mq8u03er0x3ucluj5qam",
valid: true, valid: true,
result: util.TstAddressPubKeyHash( result: util.TstAddressPubKeyHash(
dagconfig.DagTest, util.Bech32PrefixDAGTest,
[ripemd160.Size]byte{ [ripemd160.Size]byte{
0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83,
0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f}), 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f}),
@ -78,9 +77,9 @@ func TestAddresses(t *testing.T) {
pkHash := []byte{ pkHash := []byte{
0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83,
0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f} 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f}
return util.NewAddressPubKeyHash(pkHash, &dagconfig.TestNet3Params) return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixDAGTest)
}, },
net: &dagconfig.TestNet3Params, prefix: util.Bech32PrefixDAGTest,
}, },
// Negative P2PKH tests. // Negative P2PKH tests.
@ -93,15 +92,15 @@ func TestAddresses(t *testing.T) {
0x00, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0x00, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b,
0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad,
0xaa} 0xaa}
return util.NewAddressPubKeyHash(pkHash, &dagconfig.MainNetParams) return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixDAGCoin)
}, },
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
{ {
name: "p2pkh bad checksum", name: "p2pkh bad checksum",
addr: "dagcoin:qr35ennsep3hxfe7lnz5ee7j5jgmkjswss74as46gx", addr: "dagcoin:qr35ennsep3hxfe7lnz5ee7j5jgmkjswss74as46gx",
valid: false, valid: false,
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
// Positive P2SH tests. // Positive P2SH tests.
@ -114,7 +113,7 @@ func TestAddresses(t *testing.T) {
encoded: "dagcoin:pruptvpkmxamee0f72sq40gm70wfr624zq8mc2ujcn", encoded: "dagcoin:pruptvpkmxamee0f72sq40gm70wfr624zq8mc2ujcn",
valid: true, valid: true,
result: util.TstAddressScriptHash( result: util.TstAddressScriptHash(
dagconfig.DagCoin, util.Bech32PrefixDAGCoin,
[ripemd160.Size]byte{ [ripemd160.Size]byte{
0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2, 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2,
0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10}), 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10}),
@ -141,9 +140,9 @@ func TestAddresses(t *testing.T) {
0xdb, 0xfb, 0x1e, 0x75, 0x4e, 0x35, 0xfa, 0x1c, 0x78, 0x44, 0xdb, 0xfb, 0x1e, 0x75, 0x4e, 0x35, 0xfa, 0x1c, 0x78, 0x44,
0xc4, 0x1f, 0x32, 0x2a, 0x18, 0x63, 0xd4, 0x62, 0x13, 0x53, 0xc4, 0x1f, 0x32, 0x2a, 0x18, 0x63, 0xd4, 0x62, 0x13, 0x53,
0xae} 0xae}
return util.NewAddressScriptHash(script, &dagconfig.MainNetParams) return util.NewAddressScriptHash(script, util.Bech32PrefixDAGCoin)
}, },
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
{ {
// Taken from transactions: // Taken from transactions:
@ -154,7 +153,7 @@ func TestAddresses(t *testing.T) {
encoded: "dagcoin:pr5vxqxg0xrwl2zvxlq9rxffqx00sm44ksj47shjr6", encoded: "dagcoin:pr5vxqxg0xrwl2zvxlq9rxffqx00sm44ksj47shjr6",
valid: true, valid: true,
result: util.TstAddressScriptHash( result: util.TstAddressScriptHash(
dagconfig.DagCoin, util.Bech32PrefixDAGCoin,
[ripemd160.Size]byte{ [ripemd160.Size]byte{
0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37,
0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4}), 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4}),
@ -162,9 +161,9 @@ func TestAddresses(t *testing.T) {
hash := []byte{ hash := []byte{
0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37,
0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4} 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4}
return util.NewAddressScriptHashFromHash(hash, &dagconfig.MainNetParams) return util.NewAddressScriptHashFromHash(hash, util.Bech32PrefixDAGCoin)
}, },
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
{ {
// Taken from bitcoind base58_keys_valid. // Taken from bitcoind base58_keys_valid.
@ -173,7 +172,7 @@ func TestAddresses(t *testing.T) {
encoded: "dagtest:przhjdpv93xfygpqtckdc2zkzuzqeyj2pg6ghunlhx", encoded: "dagtest:przhjdpv93xfygpqtckdc2zkzuzqeyj2pg6ghunlhx",
valid: true, valid: true,
result: util.TstAddressScriptHash( result: util.TstAddressScriptHash(
dagconfig.DagTest, util.Bech32PrefixDAGTest,
[ripemd160.Size]byte{ [ripemd160.Size]byte{
0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e,
0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a}), 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a}),
@ -181,9 +180,9 @@ func TestAddresses(t *testing.T) {
hash := []byte{ hash := []byte{
0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e,
0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a} 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a}
return util.NewAddressScriptHashFromHash(hash, &dagconfig.TestNet3Params) return util.NewAddressScriptHashFromHash(hash, util.Bech32PrefixDAGTest)
}, },
net: &dagconfig.TestNet3Params, prefix: util.Bech32PrefixDAGTest,
}, },
// Negative P2SH tests. // Negative P2SH tests.
@ -196,15 +195,15 @@ func TestAddresses(t *testing.T) {
0x00, 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0x00, 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9,
0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55,
0x10} 0x10}
return util.NewAddressScriptHashFromHash(hash, &dagconfig.MainNetParams) return util.NewAddressScriptHashFromHash(hash, util.Bech32PrefixDAGCoin)
}, },
net: &dagconfig.MainNetParams, prefix: util.Bech32PrefixDAGCoin,
}, },
} }
for _, test := range tests { for _, test := range tests {
// Decode addr and compare error against valid. // Decode addr and compare error against valid.
decoded, err := util.DecodeAddress(test.addr, test.net) decoded, err := util.DecodeAddress(test.addr, test.prefix)
if (err == nil) != test.valid { if (err == nil) != test.valid {
t.Errorf("%v: decoding test failed: %v", test.name, err) t.Errorf("%v: decoding test failed: %v", test.name, err)
return return
@ -270,7 +269,7 @@ func TestAddresses(t *testing.T) {
} }
// Ensure the address is for the expected network. // Ensure the address is for the expected network.
if !decoded.IsForNet(test.net) { if !decoded.IsForPrefix(test.prefix) {
t.Errorf("%v: calculated network does not match expected", t.Errorf("%v: calculated network does not match expected",
test.name) test.name)
return return
@ -310,33 +309,33 @@ func TestAddresses(t *testing.T) {
func TestDecodeAddressErrorConditions(t *testing.T) { func TestDecodeAddressErrorConditions(t *testing.T) {
tests := []struct { tests := []struct {
address string address string
prefix dagconfig.Bech32Prefix prefix util.Bech32Prefix
errorMessage string errorMessage string
}{ }{
{ {
"bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn", "bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn",
dagconfig.Unknown, util.Bech32PrefixUnknown,
"decoded address's prefix could not be parsed", "decoded address's prefix could not be parsed",
}, },
{ {
"dagreg:qpm2qsznhks23z7629mms6s4cwef74vcwvtmvqeszh", "dagreg:qpm2qsznhks23z7629mms6s4cwef74vcwvtmvqeszh",
dagconfig.DagTest, util.Bech32PrefixDAGTest,
"decoded address is of wrong network", "decoded address is of wrong network",
}, },
{ {
"dagreg:raskzctpv9skzctpv9skzctpv9skzctpvyd070wnqg", "dagreg:raskzctpv9skzctpv9skzctpv9skzctpvyd070wnqg",
dagconfig.DagReg, util.Bech32PrefixDAGReg,
"unknown address type", "unknown address type",
}, },
{ {
"dagreg:raskzcg5egs6nnj", "dagreg:raskzcg5egs6nnj",
dagconfig.DagReg, util.Bech32PrefixDAGReg,
"decoded address is of unknown size", "decoded address is of unknown size",
}, },
} }
for _, test := range tests { for _, test := range tests {
_, err := util.DecodeAddress(test.address, &dagconfig.Params{Prefix: test.prefix}) _, err := util.DecodeAddress(test.address, test.prefix)
if err == nil { if err == nil {
t.Errorf("decodeAddress unexpectedly succeeded") t.Errorf("decodeAddress unexpectedly succeeded")
} else if !strings.Contains(err.Error(), test.errorMessage) { } else if !strings.Contains(err.Error(), test.errorMessage) {
@ -345,3 +344,54 @@ func TestDecodeAddressErrorConditions(t *testing.T) {
} }
} }
} }
func TestParsePrefix(t *testing.T) {
tests := []struct {
prefixStr string
expectedPrefix util.Bech32Prefix
expectedError bool
}{
{"dagcoin", util.Bech32PrefixDAGCoin, false},
{"dagreg", util.Bech32PrefixDAGReg, false},
{"dagtest", util.Bech32PrefixDAGTest, false},
{"dagsim", util.Bech32PrefixDAGSim, false},
{"blabla", util.Bech32PrefixUnknown, true},
{"unknown", util.Bech32PrefixUnknown, true},
{"", util.Bech32PrefixUnknown, true},
}
for _, test := range tests {
result, err := util.ParsePrefix(test.prefixStr)
if (err != nil) != test.expectedError {
t.Errorf("TestParsePrefix: %s: expected error status: %t, but got %t",
test.prefixStr, test.expectedError, err != nil)
}
if result != test.expectedPrefix {
t.Errorf("TestParsePrefix: %s: expected prefix: %d, but got %d",
test.prefixStr, test.expectedPrefix, result)
}
}
}
func TestPrefixToString(t *testing.T) {
tests := []struct {
prefix util.Bech32Prefix
expectedPrefixStr string
}{
{util.Bech32PrefixDAGCoin, "dagcoin"},
{util.Bech32PrefixDAGReg, "dagreg"},
{util.Bech32PrefixDAGTest, "dagtest"},
{util.Bech32PrefixDAGSim, "dagsim"},
{util.Bech32PrefixUnknown, ""},
}
for _, test := range tests {
result := test.prefix.String()
if result != test.expectedPrefixStr {
t.Errorf("TestPrefixToString: %s: expected string: %s, but got %s",
test.prefix, test.expectedPrefixStr, result)
}
}
}

View File

@ -9,19 +9,15 @@ import (
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/util/gcs/builder" "github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/util/gcs" "github.com/daglabs/btcd/util/gcs"
"github.com/daglabs/btcd/util/gcs/builder"
"github.com/daglabs/btcd/wire"
) )
var ( var (
// No need to allocate an err variable in every test
err error
// List of values for building a filter // List of values for building a filter
contents = [][]byte{ contents = [][]byte{
[]byte("Alex"), []byte("Alex"),
@ -66,7 +62,7 @@ func TestUseBlockHash(t *testing.T) {
} }
// util.Address // util.Address
addr, err := util.DecodeAddress(testAddr, &dagconfig.MainNetParams) addr, err := util.DecodeAddress(testAddr, util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Fatalf("Address decode failed: %s", err.Error()) t.Fatalf("Address decode failed: %s", err.Error())
} }

View File

@ -6,8 +6,8 @@ package hdkeychain_test
import ( import (
"fmt" "fmt"
"github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/util/hdkeychain" "github.com/daglabs/btcd/util/hdkeychain"
) )
@ -22,7 +22,7 @@ func ExampleNewMaster() {
} }
// Generate a new master node using the seed. // Generate a new master node using the seed.
key, err := hdkeychain.NewMaster(seed, &dagconfig.MainNetParams) key, err := hdkeychain.NewMaster(seed, hdkeychain.HDKeyPairMainNet.PrivateKeyID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
@ -118,12 +118,12 @@ func Example_defaultWalletLayout() {
// Get and show the address associated with the extended keys for the // Get and show the address associated with the extended keys for the
// main bitcoin network. // main bitcoin network.
acct0ExtAddr, err := acct0Ext10.Address(&dagconfig.MainNetParams) acct0ExtAddr, err := acct0Ext10.Address(util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
acct0IntAddr, err := acct0Int0.Address(&dagconfig.MainNetParams) acct0IntAddr, err := acct0Int0.Address(util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return

View File

@ -19,10 +19,9 @@ import (
"math/big" "math/big"
"github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/util/base58" "github.com/daglabs/btcd/util/base58"
"github.com/daglabs/btcd/dagconfig/daghash"
) )
const ( const (
@ -96,12 +95,19 @@ var (
// key is not the expected length. // key is not the expected length.
ErrInvalidKeyLen = errors.New("the provided serialized extended key " + ErrInvalidKeyLen = errors.New("the provided serialized extended key " +
"length is invalid") "length is invalid")
// ErrUnknownHDKeyID describes an error where the provided id which
// is intended to identify the network for a hierarchical deterministic
// private extended key is not registered.
ErrUnknownHDKeyID = errors.New("unknown hd private extended key bytes")
) )
// masterKey is the master key used along with a random seed used to generate // masterKey is the master key used along with a random seed used to generate
// the master node in the hierarchical tree. // the master node in the hierarchical tree.
var masterKey = []byte("Bitcoin seed") var masterKey = []byte("Bitcoin seed")
var hdPrivToPubKeyIDs = make(map[[4]byte][]byte)
// ExtendedKey houses all the information needed to support a hierarchical // ExtendedKey houses all the information needed to support a hierarchical
// deterministic extended key. See the package overview documentation for // deterministic extended key. See the package overview documentation for
// more details on how to use extended keys. // more details on how to use extended keys.
@ -344,7 +350,7 @@ func (k *ExtendedKey) Neuter() (*ExtendedKey, error) {
} }
// Get the associated public extended key version bytes. // Get the associated public extended key version bytes.
version, err := dagconfig.HDPrivateKeyToPublicKeyID(k.version) version, err := HDPrivateKeyToPublicKeyID(k.version)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -357,6 +363,52 @@ func (k *ExtendedKey) Neuter() (*ExtendedKey, error) {
k.depth, k.childNum, false), nil k.depth, k.childNum, false), nil
} }
type HDKeyIDPair struct {
PrivateKeyID [4]byte
PublicKeyID [4]byte
}
var (
HDKeyPairMainNet = HDKeyIDPair{
PrivateKeyID: [4]byte{0x04, 0x88, 0xad, 0xe4}, // starts with xprv
PublicKeyID: [4]byte{0x04, 0x88, 0xb2, 0x1e}, // starts with xpub
}
HDKeyPairTestNet = HDKeyIDPair{
PrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv
PublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub
}
HDKeyPairRegressionNet = HDKeyIDPair{
PrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv
PublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub
}
HDKeyPairSimNet = HDKeyIDPair{
PrivateKeyID: [4]byte{0x04, 0x20, 0xb9, 0x00}, // starts with sprv
PublicKeyID: [4]byte{0x04, 0x20, 0xbd, 0x3a}, // starts with spub
}
)
func RegisterHDKeyIDPair(hdKeyIDPair HDKeyIDPair) {
hdPrivToPubKeyIDs[hdKeyIDPair.PrivateKeyID] = hdKeyIDPair.PublicKeyID[:]
}
// 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.
func HDPrivateKeyToPublicKeyID(id []byte) ([]byte, error) {
if len(id) != 4 {
return nil, ErrUnknownHDKeyID
}
var key [4]byte
copy(key[:], id)
pubBytes, ok := hdPrivToPubKeyIDs[key]
if !ok {
return nil, ErrUnknownHDKeyID
}
return pubBytes, nil
}
// ECPubKey converts the extended key to a btcec public key and returns it. // ECPubKey converts the extended key to a btcec public key and returns it.
func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error) { func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error) {
return btcec.ParsePubKey(k.pubKeyBytes(), btcec.S256()) return btcec.ParsePubKey(k.pubKeyBytes(), btcec.S256())
@ -377,9 +429,9 @@ func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error) {
// Address converts the extended key to a standard bitcoin pay-to-pubkey-hash // Address converts the extended key to a standard bitcoin pay-to-pubkey-hash
// address for the passed network. // address for the passed network.
func (k *ExtendedKey) Address(net *dagconfig.Params) (*util.AddressPubKeyHash, error) { func (k *ExtendedKey) Address(prefix util.Bech32Prefix) (*util.AddressPubKeyHash, error) {
pkHash := util.Hash160(k.pubKeyBytes()) pkHash := util.Hash160(k.pubKeyBytes())
return util.NewAddressPubKeyHash(pkHash, net) return util.NewAddressPubKeyHash(pkHash, prefix)
} }
// paddedAppend appends the src byte slice to dst, returning the new slice. // paddedAppend appends the src byte slice to dst, returning the new slice.
@ -423,19 +475,19 @@ func (k *ExtendedKey) String() string {
} }
// IsForNet returns whether or not the extended key is associated with the // IsForNet returns whether or not the extended key is associated with the
// passed bitcoin network. // passed network keyIDs.
func (k *ExtendedKey) IsForNet(net *dagconfig.Params) bool { func (k *ExtendedKey) IsForNet(hdKeyIDPair HDKeyIDPair) bool {
return bytes.Equal(k.version, net.HDPrivateKeyID[:]) || return bytes.Equal(k.version, hdKeyIDPair.PrivateKeyID[:]) ||
bytes.Equal(k.version, net.HDPublicKeyID[:]) bytes.Equal(k.version, hdKeyIDPair.PublicKeyID[:])
} }
// SetNet associates the extended key, and any child keys yet to be derived from // SetNet associates the extended key, and any child keys yet to be derived from
// it, with the passed network. // it, with the passed key IDs.
func (k *ExtendedKey) SetNet(net *dagconfig.Params) { func (k *ExtendedKey) SetNet(hdKeyIDPair HDKeyIDPair) {
if k.isPrivate { if k.isPrivate {
k.version = net.HDPrivateKeyID[:] k.version = hdKeyIDPair.PrivateKeyID[:]
} else { } else {
k.version = net.HDPublicKeyID[:] k.version = hdKeyIDPair.PublicKeyID[:]
} }
} }
@ -472,7 +524,7 @@ func (k *ExtendedKey) Zero() {
// will derive to an unusable secret key. The ErrUnusable error will be // will derive to an unusable secret key. The ErrUnusable error will be
// returned if this should occur, so the caller must check for it and generate a // returned if this should occur, so the caller must check for it and generate a
// new seed accordingly. // new seed accordingly.
func NewMaster(seed []byte, net *dagconfig.Params) (*ExtendedKey, error) { func NewMaster(seed []byte, hdPrivateKeyID [4]byte) (*ExtendedKey, error) {
// Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes].
if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes { if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes {
return nil, ErrInvalidSeedLen return nil, ErrInvalidSeedLen
@ -497,7 +549,7 @@ func NewMaster(seed []byte, net *dagconfig.Params) (*ExtendedKey, error) {
} }
parentFP := []byte{0x00, 0x00, 0x00, 0x00} parentFP := []byte{0x00, 0x00, 0x00, 0x00}
return NewExtendedKey(net.HDPrivateKeyID[:], secretKey, chainCode, return NewExtendedKey(hdPrivateKeyID[:], secretKey, chainCode,
parentFP, 0, 0, true), nil parentFP, 0, 0, true), nil
} }
@ -575,3 +627,11 @@ func GenerateSeed(length uint8) ([]byte, error) {
return buf, nil return buf, nil
} }
func init() {
// Register all default keyPairIDs when the package is initialized.
RegisterHDKeyIDPair(HDKeyPairMainNet)
RegisterHDKeyIDPair(HDKeyPairTestNet)
RegisterHDKeyIDPair(HDKeyPairRegressionNet)
RegisterHDKeyIDPair(HDKeyPairSimNet)
}

View File

@ -12,11 +12,10 @@ import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"errors" "errors"
"github.com/daglabs/btcd/util"
"math" "math"
"reflect" "reflect"
"testing" "testing"
"github.com/daglabs/btcd/dagconfig"
) )
// TestBIP0032Vectors tests the vectors provided by [BIP32] to ensure the // TestBIP0032Vectors tests the vectors provided by [BIP32] to ensure the
@ -29,179 +28,179 @@ func TestBIP0032Vectors(t *testing.T) {
hkStart := uint32(0x80000000) hkStart := uint32(0x80000000)
tests := []struct { tests := []struct {
name string name string
master string master string
path []uint32 path []uint32
wantPub string wantPub string
wantPriv string wantPriv string
net *dagconfig.Params hdKeyIDPair HDKeyIDPair
}{ }{
// Test vector 1 // Test vector 1
{ {
name: "test vector 1 chain m", name: "test vector 1 chain m",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{}, path: []uint32{},
wantPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", wantPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
wantPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", wantPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 1 chain m/0H", name: "test vector 1 chain m/0H",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart}, path: []uint32{hkStart},
wantPub: "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw", wantPub: "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
wantPriv: "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", wantPriv: "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 1 chain m/0H/1", name: "test vector 1 chain m/0H/1",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1}, path: []uint32{hkStart, 1},
wantPub: "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ", wantPub: "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
wantPriv: "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", wantPriv: "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 1 chain m/0H/1/2H", name: "test vector 1 chain m/0H/1/2H",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1, hkStart + 2}, path: []uint32{hkStart, 1, hkStart + 2},
wantPub: "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", wantPub: "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
wantPriv: "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", wantPriv: "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 1 chain m/0H/1/2H/2", name: "test vector 1 chain m/0H/1/2H/2",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1, hkStart + 2, 2}, path: []uint32{hkStart, 1, hkStart + 2, 2},
wantPub: "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV", wantPub: "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
wantPriv: "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", wantPriv: "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 1 chain m/0H/1/2H/2/1000000000", name: "test vector 1 chain m/0H/1/2H/2/1000000000",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000}, path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000},
wantPub: "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy", wantPub: "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
wantPriv: "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", wantPriv: "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
// Test vector 2 // Test vector 2
{ {
name: "test vector 2 chain m", name: "test vector 2 chain m",
master: testVec2MasterHex, master: testVec2MasterHex,
path: []uint32{}, path: []uint32{},
wantPub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", wantPub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
wantPriv: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", wantPriv: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 2 chain m/0", name: "test vector 2 chain m/0",
master: testVec2MasterHex, master: testVec2MasterHex,
path: []uint32{0}, path: []uint32{0},
wantPub: "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", wantPub: "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
wantPriv: "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", wantPriv: "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 2 chain m/0/2147483647H", name: "test vector 2 chain m/0/2147483647H",
master: testVec2MasterHex, master: testVec2MasterHex,
path: []uint32{0, hkStart + 2147483647}, path: []uint32{0, hkStart + 2147483647},
wantPub: "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a", wantPub: "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
wantPriv: "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", wantPriv: "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 2 chain m/0/2147483647H/1", name: "test vector 2 chain m/0/2147483647H/1",
master: testVec2MasterHex, master: testVec2MasterHex,
path: []uint32{0, hkStart + 2147483647, 1}, path: []uint32{0, hkStart + 2147483647, 1},
wantPub: "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon", wantPub: "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
wantPriv: "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", wantPriv: "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 2 chain m/0/2147483647H/1/2147483646H", name: "test vector 2 chain m/0/2147483647H/1/2147483646H",
master: testVec2MasterHex, master: testVec2MasterHex,
path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646}, path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646},
wantPub: "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL", wantPub: "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
wantPriv: "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", wantPriv: "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 2 chain m/0/2147483647H/1/2147483646H/2", name: "test vector 2 chain m/0/2147483647H/1/2147483646H/2",
master: testVec2MasterHex, master: testVec2MasterHex,
path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646, 2}, path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646, 2},
wantPub: "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt", wantPub: "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
wantPriv: "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", wantPriv: "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
// Test vector 3 // Test vector 3
{ {
name: "test vector 3 chain m", name: "test vector 3 chain m",
master: testVec3MasterHex, master: testVec3MasterHex,
path: []uint32{}, path: []uint32{},
wantPub: "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13", wantPub: "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13",
wantPriv: "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", wantPriv: "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
{ {
name: "test vector 3 chain m/0H", name: "test vector 3 chain m/0H",
master: testVec3MasterHex, master: testVec3MasterHex,
path: []uint32{hkStart}, path: []uint32{hkStart},
wantPub: "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y", wantPub: "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y",
wantPriv: "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", wantPriv: "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
// Test vector 1 - Testnet // Test vector 1 - Testnet
{ {
name: "test vector 1 chain m - testnet", name: "test vector 1 chain m - testnet",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{}, path: []uint32{},
wantPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", wantPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp",
wantPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", wantPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m",
net: &dagconfig.TestNet3Params, hdKeyIDPair: HDKeyPairTestNet,
}, },
{ {
name: "test vector 1 chain m/0H - testnet", name: "test vector 1 chain m/0H - testnet",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart}, path: []uint32{hkStart},
wantPub: "tpubD8eQVK4Kdxg3gHrF62jGP7dKVCoYiEB8dFSpuTawkL5YxTus5j5pf83vaKnii4bc6v2NVEy81P2gYrJczYne3QNNwMTS53p5uzDyHvnw2jm", wantPub: "tpubD8eQVK4Kdxg3gHrF62jGP7dKVCoYiEB8dFSpuTawkL5YxTus5j5pf83vaKnii4bc6v2NVEy81P2gYrJczYne3QNNwMTS53p5uzDyHvnw2jm",
wantPriv: "tprv8bxNLu25VazNnppTCP4fyhyCvBHcYtzE3wr3cwYeL4HA7yf6TLGEUdS4QC1vLT63TkjRssqJe4CvGNEC8DzW5AoPUw56D1Ayg6HY4oy8QZ9", wantPriv: "tprv8bxNLu25VazNnppTCP4fyhyCvBHcYtzE3wr3cwYeL4HA7yf6TLGEUdS4QC1vLT63TkjRssqJe4CvGNEC8DzW5AoPUw56D1Ayg6HY4oy8QZ9",
net: &dagconfig.TestNet3Params, hdKeyIDPair: HDKeyPairTestNet,
}, },
{ {
name: "test vector 1 chain m/0H/1 - testnet", name: "test vector 1 chain m/0H/1 - testnet",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1}, path: []uint32{hkStart, 1},
wantPub: "tpubDApXh6cD2fZ7WjtgpHd8yrWyYaneiFuRZa7fVjMkgxsmC1QzoXW8cgx9zQFJ81Jx4deRGfRE7yXA9A3STsxXj4CKEZJHYgpMYikkas9DBTP", wantPub: "tpubDApXh6cD2fZ7WjtgpHd8yrWyYaneiFuRZa7fVjMkgxsmC1QzoXW8cgx9zQFJ81Jx4deRGfRE7yXA9A3STsxXj4CKEZJHYgpMYikkas9DBTP",
wantPriv: "tprv8e8VYgZxtHsSdGrtvdxYaSrryZGiYviWzGWtDDKTGh5NMXAEB8gYSCLHpFCywNs5uqV7ghRjimALQJkRFZnUrLHpzi2pGkwqLtbubgWuQ8q", wantPriv: "tprv8e8VYgZxtHsSdGrtvdxYaSrryZGiYviWzGWtDDKTGh5NMXAEB8gYSCLHpFCywNs5uqV7ghRjimALQJkRFZnUrLHpzi2pGkwqLtbubgWuQ8q",
net: &dagconfig.TestNet3Params, hdKeyIDPair: HDKeyPairTestNet,
}, },
{ {
name: "test vector 1 chain m/0H/1/2H - testnet", name: "test vector 1 chain m/0H/1/2H - testnet",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1, hkStart + 2}, path: []uint32{hkStart, 1, hkStart + 2},
wantPub: "tpubDDRojdS4jYQXNugn4t2WLrZ7mjfAyoVQu7MLk4eurqFCbrc7cHLZX8W5YRS8ZskGR9k9t3PqVv68bVBjAyW4nWM9pTGRddt3GQftg6MVQsm", wantPub: "tpubDDRojdS4jYQXNugn4t2WLrZ7mjfAyoVQu7MLk4eurqFCbrc7cHLZX8W5YRS8ZskGR9k9t3PqVv68bVBjAyW4nWM9pTGRddt3GQftg6MVQsm",
wantPriv: "tprv8gjmbDPpbAirVSezBEMuwSu1Ci9EpUJWKokZTYccSZSomNMLytWyLdtDNHRbucNaRJWWHANf9AzEdWVAqahfyRjVMKbNRhBmxAM8EJr7R15", wantPriv: "tprv8gjmbDPpbAirVSezBEMuwSu1Ci9EpUJWKokZTYccSZSomNMLytWyLdtDNHRbucNaRJWWHANf9AzEdWVAqahfyRjVMKbNRhBmxAM8EJr7R15",
net: &dagconfig.TestNet3Params, hdKeyIDPair: HDKeyPairTestNet,
}, },
{ {
name: "test vector 1 chain m/0H/1/2H/2 - testnet", name: "test vector 1 chain m/0H/1/2H/2 - testnet",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1, hkStart + 2, 2}, path: []uint32{hkStart, 1, hkStart + 2, 2},
wantPub: "tpubDFfCa4Z1v25WTPAVm9EbEMiRrYwucPocLbEe12BPBGooxxEUg42vihy1DkRWyftztTsL23snYezF9uXjGGwGW6pQjEpcTpmsH6ajpf4CVPn", wantPub: "tpubDFfCa4Z1v25WTPAVm9EbEMiRrYwucPocLbEe12BPBGooxxEUg42vihy1DkRWyftztTsL23snYezF9uXjGGwGW6pQjEpcTpmsH6ajpf4CVPn",
wantPriv: "tprv8iyAReWmmePqZv8hsVZzpx4KHXRyT4chmHdriW95m11R8Tyi3fDLYDM93bq4NGn1V6eCu5cE3zSQ6hPd31F2ApKXkZgTyn1V78pHjkq1V2v", wantPriv: "tprv8iyAReWmmePqZv8hsVZzpx4KHXRyT4chmHdriW95m11R8Tyi3fDLYDM93bq4NGn1V6eCu5cE3zSQ6hPd31F2ApKXkZgTyn1V78pHjkq1V2v",
net: &dagconfig.TestNet3Params, hdKeyIDPair: HDKeyPairTestNet,
}, },
{ {
name: "test vector 1 chain m/0H/1/2H/2/1000000000 - testnet", name: "test vector 1 chain m/0H/1/2H/2/1000000000 - testnet",
master: testVec1MasterHex, master: testVec1MasterHex,
path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000}, path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000},
wantPub: "tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF", wantPub: "tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF",
wantPriv: "tprv8kgvuL81tmn36Fv9z38j8f4K5m1HGZRjZY2QxnXDy5PuqbP6a5TzoKWCgTcGHBu66W3TgSbAu2yX6sPza5FkHmy564Sh6gmCPUNeUt4yj2x", wantPriv: "tprv8kgvuL81tmn36Fv9z38j8f4K5m1HGZRjZY2QxnXDy5PuqbP6a5TzoKWCgTcGHBu66W3TgSbAu2yX6sPza5FkHmy564Sh6gmCPUNeUt4yj2x",
net: &dagconfig.TestNet3Params, hdKeyIDPair: HDKeyPairTestNet,
}, },
} }
@ -214,7 +213,7 @@ tests:
continue continue
} }
extKey, err := NewMaster(masterSeed, test.net) extKey, err := NewMaster(masterSeed, test.hdKeyIDPair.PrivateKeyID)
if err != nil { if err != nil {
t.Errorf("NewMaster #%d (%s): unexpected error when "+ t.Errorf("NewMaster #%d (%s): unexpected error when "+
"creating new master key: %v", i, test.name, "creating new master key: %v", i, test.name,
@ -648,7 +647,7 @@ func TestExtendedKeyAPI(t *testing.T) {
continue continue
} }
addr, err := key.Address(&dagconfig.MainNetParams) addr, err := key.Address(util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Errorf("Address #%d (%s): unexpected error: %v", i, t.Errorf("Address #%d (%s): unexpected error: %v", i,
test.name, err) test.name, err)
@ -666,84 +665,84 @@ func TestExtendedKeyAPI(t *testing.T) {
// TestNet ensures the network related APIs work as intended. // TestNet ensures the network related APIs work as intended.
func TestNet(t *testing.T) { func TestNet(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
key string key string
origNet *dagconfig.Params origHDKeyIDPair HDKeyIDPair
newNet *dagconfig.Params newHDKeyIDPair HDKeyIDPair
newPriv string newPriv string
newPub string newPub string
isPrivate bool isPrivate bool
}{ }{
// Private extended keys. // Private extended keys.
{ {
name: "mainnet -> simnet", name: "mainnet -> simnet",
key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
origNet: &dagconfig.MainNetParams, origHDKeyIDPair: HDKeyPairMainNet,
newNet: &dagconfig.SimNetParams, newHDKeyIDPair: HDKeyPairSimNet,
newPriv: "sprv8Erh3X3hFeKunvVdAGQQtambRPapECWiTDtvsTGdyrhzhbYgnSZajRRWbihzvq4AM4ivm6uso31VfKaukwJJUs3GYihXP8ebhMb3F2AHu3P", newPriv: "sprv8Erh3X3hFeKunvVdAGQQtambRPapECWiTDtvsTGdyrhzhbYgnSZajRRWbihzvq4AM4ivm6uso31VfKaukwJJUs3GYihXP8ebhMb3F2AHu3P",
newPub: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk", newPub: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk",
isPrivate: true, isPrivate: true,
}, },
{ {
name: "simnet -> mainnet", name: "simnet -> mainnet",
key: "sprv8Erh3X3hFeKunvVdAGQQtambRPapECWiTDtvsTGdyrhzhbYgnSZajRRWbihzvq4AM4ivm6uso31VfKaukwJJUs3GYihXP8ebhMb3F2AHu3P", key: "sprv8Erh3X3hFeKunvVdAGQQtambRPapECWiTDtvsTGdyrhzhbYgnSZajRRWbihzvq4AM4ivm6uso31VfKaukwJJUs3GYihXP8ebhMb3F2AHu3P",
origNet: &dagconfig.SimNetParams, origHDKeyIDPair: HDKeyPairSimNet,
newNet: &dagconfig.MainNetParams, newHDKeyIDPair: HDKeyPairMainNet,
newPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", newPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
isPrivate: true, isPrivate: true,
}, },
{ {
name: "mainnet -> regtest", name: "mainnet -> regtest",
key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
origNet: &dagconfig.MainNetParams, origHDKeyIDPair: HDKeyPairMainNet,
newNet: &dagconfig.RegressionNetParams, newHDKeyIDPair: HDKeyPairRegressionNet,
newPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", newPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m",
newPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", newPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp",
isPrivate: true, isPrivate: true,
}, },
{ {
name: "regtest -> mainnet", name: "regtest -> mainnet",
key: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", key: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m",
origNet: &dagconfig.RegressionNetParams, origHDKeyIDPair: HDKeyPairRegressionNet,
newNet: &dagconfig.MainNetParams, newHDKeyIDPair: HDKeyPairMainNet,
newPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", newPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
isPrivate: true, isPrivate: true,
}, },
// Public extended keys. // Public extended keys.
{ {
name: "mainnet -> simnet", name: "mainnet -> simnet",
key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
origNet: &dagconfig.MainNetParams, origHDKeyIDPair: HDKeyPairMainNet,
newNet: &dagconfig.SimNetParams, newHDKeyIDPair: HDKeyPairSimNet,
newPub: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk", newPub: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk",
isPrivate: false, isPrivate: false,
}, },
{ {
name: "simnet -> mainnet", name: "simnet -> mainnet",
key: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk", key: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk",
origNet: &dagconfig.SimNetParams, origHDKeyIDPair: HDKeyPairSimNet,
newNet: &dagconfig.MainNetParams, newHDKeyIDPair: HDKeyPairMainNet,
newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
isPrivate: false, isPrivate: false,
}, },
{ {
name: "mainnet -> regtest", name: "mainnet -> regtest",
key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
origNet: &dagconfig.MainNetParams, origHDKeyIDPair: HDKeyPairMainNet,
newNet: &dagconfig.RegressionNetParams, newHDKeyIDPair: HDKeyPairRegressionNet,
newPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", newPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp",
isPrivate: false, isPrivate: false,
}, },
{ {
name: "regtest -> mainnet", name: "regtest -> mainnet",
key: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", key: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp",
origNet: &dagconfig.RegressionNetParams, origHDKeyIDPair: HDKeyPairRegressionNet,
newNet: &dagconfig.MainNetParams, newHDKeyIDPair: HDKeyPairMainNet,
newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
isPrivate: false, isPrivate: false,
}, },
} }
@ -756,17 +755,17 @@ func TestNet(t *testing.T) {
continue continue
} }
if !extKey.IsForNet(test.origNet) { if !extKey.IsForNet(test.origHDKeyIDPair) {
t.Errorf("IsForNet #%d (%s): key is not for expected "+ t.Errorf("IsForNet #%d (%s): key is not for expected "+
"network %v", i, test.name, test.origNet.Name) "network %v", i, test.name, test.origHDKeyIDPair)
continue continue
} }
extKey.SetNet(test.newNet) extKey.SetNet(test.newHDKeyIDPair)
if !extKey.IsForNet(test.newNet) { if !extKey.IsForNet(test.newHDKeyIDPair) {
t.Errorf("SetNet/IsForNet #%d (%s): key is not for "+ t.Errorf("SetNet/IsForNet #%d (%s): key is not for "+
"expected network %v", i, test.name, "expected network %v", i, test.name,
test.newNet.Name) test.newHDKeyIDPair)
continue continue
} }
@ -801,15 +800,15 @@ func TestNet(t *testing.T) {
// the errors are handled properly. // the errors are handled properly.
func TestErrors(t *testing.T) { func TestErrors(t *testing.T) {
// Should get an error when seed has too few bytes. // Should get an error when seed has too few bytes.
net := &dagconfig.MainNetParams hdKeyIDPair := HDKeyPairMainNet
_, err := NewMaster(bytes.Repeat([]byte{0x00}, 15), net) _, err := NewMaster(bytes.Repeat([]byte{0x00}, 15), hdKeyIDPair.PrivateKeyID)
if err != ErrInvalidSeedLen { if err != ErrInvalidSeedLen {
t.Fatalf("NewMaster: mismatched error -- got: %v, want: %v", t.Fatalf("NewMaster: mismatched error -- got: %v, want: %v",
err, ErrInvalidSeedLen) err, ErrInvalidSeedLen)
} }
// Should get an error when seed has too many bytes. // Should get an error when seed has too many bytes.
_, err = NewMaster(bytes.Repeat([]byte{0x00}, 65), net) _, err = NewMaster(bytes.Repeat([]byte{0x00}, 65), hdKeyIDPair.PrivateKeyID)
if err != ErrInvalidSeedLen { if err != ErrInvalidSeedLen {
t.Fatalf("NewMaster: mismatched error -- got: %v, want: %v", t.Fatalf("NewMaster: mismatched error -- got: %v, want: %v",
err, ErrInvalidSeedLen) err, ErrInvalidSeedLen)
@ -820,7 +819,7 @@ func TestErrors(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("GenerateSeed: unexpected error: %v", err) t.Fatalf("GenerateSeed: unexpected error: %v", err)
} }
extKey, err := NewMaster(seed, net) extKey, err := NewMaster(seed, hdKeyIDPair.PrivateKeyID)
if err != nil { if err != nil {
t.Fatalf("NewMaster: unexpected error: %v", err) t.Fatalf("NewMaster: unexpected error: %v", err)
} }
@ -864,7 +863,7 @@ func TestErrors(t *testing.T) {
key: "xbad4LfUL9eKmA66w2GJdVMqhvDmYGJpTGjWRAtjHqoUY17sGaymoMV9Cm3ocn9Ud6Hh2vLFVC7KSKCRVVrqc6dsEdsTjRV1WUmkK85YEUujAPX", key: "xbad4LfUL9eKmA66w2GJdVMqhvDmYGJpTGjWRAtjHqoUY17sGaymoMV9Cm3ocn9Ud6Hh2vLFVC7KSKCRVVrqc6dsEdsTjRV1WUmkK85YEUujAPX",
err: nil, err: nil,
neuter: true, neuter: true,
neuterErr: dagconfig.ErrUnknownHDKeyID, neuterErr: ErrUnknownHDKeyID,
}, },
} }
@ -892,25 +891,25 @@ func TestErrors(t *testing.T) {
// TestZero ensures that zeroing an extended key works as intended. // TestZero ensures that zeroing an extended key works as intended.
func TestZero(t *testing.T) { func TestZero(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
master string master string
extKey string extKey string
net *dagconfig.Params hdKeyIDPair HDKeyIDPair
}{ }{
// Test vector 1 // Test vector 1
{ {
name: "test vector 1 chain m", name: "test vector 1 chain m",
master: "000102030405060708090a0b0c0d0e0f", master: "000102030405060708090a0b0c0d0e0f",
extKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", extKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
// Test vector 2 // Test vector 2
{ {
name: "test vector 2 chain m", name: "test vector 2 chain m",
master: "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542", master: "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
extKey: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", extKey: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
net: &dagconfig.MainNetParams, hdKeyIDPair: HDKeyPairMainNet,
}, },
} }
@ -960,7 +959,7 @@ func TestZero(t *testing.T) {
} }
wantAddr := "dagcoin:qz689gnx6z7cnsfhq6jpxtx0k9hhcwulevtzqltud6" wantAddr := "dagcoin:qz689gnx6z7cnsfhq6jpxtx0k9hhcwulevtzqltud6"
addr, err := key.Address(&dagconfig.MainNetParams) addr, err := key.Address(util.Bech32PrefixDAGCoin)
if err != nil { if err != nil {
t.Errorf("Addres s #%d (%s): unexpected error: %v", i, t.Errorf("Addres s #%d (%s): unexpected error: %v", i,
testName, err) testName, err)
@ -984,7 +983,7 @@ func TestZero(t *testing.T) {
i, test.name, err) i, test.name, err)
continue continue
} }
key, err := NewMaster(masterSeed, test.net) key, err := NewMaster(masterSeed, test.hdKeyIDPair.PrivateKeyID)
if err != nil { if err != nil {
t.Errorf("NewMaster #%d (%s): unexpected error when "+ t.Errorf("NewMaster #%d (%s): unexpected error when "+
"creating new master key: %v", i, test.name, "creating new master key: %v", i, test.name,
@ -1041,8 +1040,7 @@ func TestZero(t *testing.T) {
// uint8 to encode the depth. This implicitly bounds the depth of the tree to // uint8 to encode the depth. This implicitly bounds the depth of the tree to
// 255 derivations. Here we test that an error is returned after 'max uint8'. // 255 derivations. Here we test that an error is returned after 'max uint8'.
func TestMaximumDepth(t *testing.T) { func TestMaximumDepth(t *testing.T) {
net := &dagconfig.MainNetParams extKey, err := NewMaster([]byte(`abcd1234abcd1234abcd1234abcd1234`), HDKeyPairMainNet.PrivateKeyID)
extKey, err := NewMaster([]byte(`abcd1234abcd1234abcd1234abcd1234`), net)
if err != nil { if err != nil {
t.Fatalf("NewMaster: unexpected error: %v", err) t.Fatalf("NewMaster: unexpected error: %v", err)
} }

View File

@ -13,7 +13,6 @@ package util
import ( import (
"github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/util/bech32" "github.com/daglabs/btcd/util/bech32"
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
@ -31,7 +30,7 @@ func TstAppDataDir(goos, appName string, roaming bool) string {
return appDataDir(goos, appName, roaming) return appDataDir(goos, appName, roaming)
} }
func TstAddressPubKeyHash(prefix dagconfig.Bech32Prefix, hash [ripemd160.Size]byte) *AddressPubKeyHash { func TstAddressPubKeyHash(prefix Bech32Prefix, hash [ripemd160.Size]byte) *AddressPubKeyHash {
return &AddressPubKeyHash{ return &AddressPubKeyHash{
prefix: prefix, prefix: prefix,
hash: hash, hash: hash,
@ -40,7 +39,7 @@ func TstAddressPubKeyHash(prefix dagconfig.Bech32Prefix, hash [ripemd160.Size]by
// TstAddressScriptHash makes an AddressScriptHash, setting the // TstAddressScriptHash makes an AddressScriptHash, setting the
// unexported fields with the parameters hash and netID. // unexported fields with the parameters hash and netID.
func TstAddressScriptHash(prefix dagconfig.Bech32Prefix, hash [ripemd160.Size]byte) *AddressScriptHash { func TstAddressScriptHash(prefix Bech32Prefix, hash [ripemd160.Size]byte) *AddressScriptHash {
return &AddressScriptHash{ return &AddressScriptHash{
prefix: prefix, prefix: prefix,

View File

@ -7,9 +7,7 @@ package util
import ( import (
"bytes" "bytes"
"errors" "errors"
"github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/util/base58" "github.com/daglabs/btcd/util/base58"
) )
@ -49,17 +47,14 @@ type WIF struct {
// as a string encoded in the Wallet Import Format. The compress argument // as a string encoded in the Wallet Import Format. The compress argument
// specifies whether the address intended to be imported or exported was created // specifies whether the address intended to be imported or exported was created
// by serializing the public key compressed rather than uncompressed. // by serializing the public key compressed rather than uncompressed.
func NewWIF(privKey *btcec.PrivateKey, net *dagconfig.Params, compress bool) (*WIF, error) { func NewWIF(privKey *btcec.PrivateKey, privateKeyID byte, compress bool) (*WIF, error) {
if net == nil { return &WIF{privKey, compress, privateKeyID}, nil
return nil, errors.New("no network")
}
return &WIF{privKey, compress, net.PrivateKeyID}, nil
} }
// IsForNet returns whether or not the decoded WIF structure is associated // IsForNet returns whether or not the decoded WIF structure is associated
// with the passed bitcoin network. // with the passed bitcoin network.
func (w *WIF) IsForNet(net *dagconfig.Params) bool { func (w *WIF) IsForNet(privateKeyID byte) bool {
return w.netID == net.PrivateKeyID return w.netID == privateKeyID
} }
// DecodeWIF creates a new WIF structure by decoding the string encoding of // DecodeWIF creates a new WIF structure by decoding the string encoding of

View File

@ -25,11 +25,11 @@ func TestEncodeDecodeWIF(t *testing.T) {
0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9, 0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9,
0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98}) 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98})
wif1, err := NewWIF(priv1, &dagconfig.MainNetParams, false) wif1, err := NewWIF(priv1, dagconfig.MainNetParams.PrivateKeyID, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
wif2, err := NewWIF(priv2, &dagconfig.TestNet3Params, true) wif2, err := NewWIF(priv2, dagconfig.TestNet3Params.PrivateKeyID, true)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }