1// Copyright (c) 2013 - 2020 The btcsuite developers 2// Use of this source code is governed by an ISC 3// license that can be found in the LICENSE file. 4 5package btcutil_test 6 7import ( 8 "bytes" 9 "encoding/hex" 10 "testing" 11 12 "github.com/btcsuite/btcd/btcec" 13 "github.com/btcsuite/btcd/chaincfg" 14 . "github.com/btcsuite/btcutil" 15) 16 17func TestEncodeDecodeWIF(t *testing.T) { 18 validEncodeCases := []struct { 19 privateKey []byte // input 20 net *chaincfg.Params // input 21 compress bool // input 22 wif string // output 23 publicKey []byte // output 24 name string // name of subtest 25 }{ 26 { 27 privateKey: []byte{ 28 0x0c, 0x28, 0xfc, 0xa3, 0x86, 0xc7, 0xa2, 0x27, 29 0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11, 30 0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b, 31 0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d}, 32 net: &chaincfg.MainNetParams, 33 compress: false, 34 wif: "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ", 35 publicKey: []byte{ 36 0x04, 0xd0, 0xde, 0x0a, 0xae, 0xae, 0xfa, 0xd0, 37 0x2b, 0x8b, 0xdc, 0x8a, 0x01, 0xa1, 0xb8, 0xb1, 38 0x1c, 0x69, 0x6b, 0xd3, 0xd6, 0x6a, 0x2c, 0x5f, 39 0x10, 0x78, 0x0d, 0x95, 0xb7, 0xdf, 0x42, 0x64, 40 0x5c, 0xd8, 0x52, 0x28, 0xa6, 0xfb, 0x29, 0x94, 41 0x0e, 0x85, 0x8e, 0x7e, 0x55, 0x84, 0x2a, 0xe2, 42 0xbd, 0x11, 0x5d, 0x1e, 0xd7, 0xcc, 0x0e, 0x82, 43 0xd9, 0x34, 0xe9, 0x29, 0xc9, 0x76, 0x48, 0xcb, 44 0x0a}, 45 name: "encodeValidUncompressedMainNetWif", 46 }, 47 { 48 privateKey: []byte{ 49 0xdd, 0xa3, 0x5a, 0x14, 0x88, 0xfb, 0x97, 0xb6, 50 0xeb, 0x3f, 0xe6, 0xe9, 0xef, 0x2a, 0x25, 0x81, 51 0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9, 52 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98}, 53 net: &chaincfg.TestNet3Params, 54 compress: true, 55 wif: "cV1Y7ARUr9Yx7BR55nTdnR7ZXNJphZtCCMBTEZBJe1hXt2kB684q", 56 publicKey: []byte{ 57 0x02, 0xee, 0xc2, 0x54, 0x06, 0x61, 0xb0, 0xc3, 58 0x9d, 0x27, 0x15, 0x70, 0x74, 0x24, 0x13, 0xbd, 59 0x02, 0x93, 0x2d, 0xd0, 0x09, 0x34, 0x93, 0xfd, 60 0x0b, 0xec, 0xed, 0x0b, 0x7f, 0x93, 0xad, 0xde, 61 0xc4}, 62 name: "encodeValidCompressedTestNet3Wif", 63 }, 64 } 65 66 for _, validCase := range validEncodeCases { 67 t.Run(validCase.name, func(t *testing.T) { 68 priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), validCase.privateKey) 69 wif, err := NewWIF(priv, validCase.net, validCase.compress) 70 if err != nil { 71 t.Fatalf("NewWIF failed: expected no error, got '%v'", err) 72 } 73 74 if !wif.IsForNet(validCase.net) { 75 t.Fatal("IsForNet failed: got 'false', want 'true'") 76 } 77 78 if gotPubKey := wif.SerializePubKey(); !bytes.Equal(gotPubKey, validCase.publicKey) { 79 t.Fatalf("SerializePubKey failed: got '%s', want '%s'", 80 hex.EncodeToString(gotPubKey), hex.EncodeToString(validCase.publicKey)) 81 } 82 83 // Test that encoding the WIF structure matches the expected string. 84 got := wif.String() 85 if got != validCase.wif { 86 t.Fatalf("NewWIF failed: want '%s', got '%s'", 87 validCase.wif, got) 88 } 89 90 // Test that decoding the expected string results in the original WIF 91 // structure. 92 decodedWif, err := DecodeWIF(got) 93 if err != nil { 94 t.Fatalf("DecodeWIF failed: expected no error, got '%v'", err) 95 } 96 if decodedWifString := decodedWif.String(); decodedWifString != validCase.wif { 97 t.Fatalf("NewWIF failed: want '%v', got '%v'", validCase.wif, decodedWifString) 98 } 99 }) 100 } 101 102 invalidDecodeCases := []struct { 103 name string 104 wif string 105 err error 106 }{ 107 { 108 name: "decodeInvalidLengthWif", 109 wif: "deadbeef", 110 err: ErrMalformedPrivateKey, 111 }, 112 { 113 name: "decodeInvalidCompressMagicWif", 114 wif: "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sfZr2ym", 115 err: ErrMalformedPrivateKey, 116 }, 117 { 118 name: "decodeInvalidChecksumWif", 119 wif: "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTj", 120 err: ErrChecksumMismatch, 121 }, 122 } 123 124 for _, invalidCase := range invalidDecodeCases { 125 t.Run(invalidCase.name, func(t *testing.T) { 126 decodedWif, err := DecodeWIF(invalidCase.wif) 127 if decodedWif != nil { 128 t.Fatalf("DecodeWIF: unexpectedly succeeded - got '%v', want '%v'", 129 decodedWif, nil) 130 } 131 if err != invalidCase.err { 132 t.Fatalf("DecodeWIF: expected error '%v', got '%v'", 133 invalidCase.err, err) 134 } 135 }) 136 } 137 138 t.Run("encodeInvalidNetworkWif", func(t *testing.T) { 139 privateKey := []byte{ 140 0x0c, 0x28, 0xfc, 0xa3, 0x86, 0xc7, 0xa2, 0x27, 141 0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11, 142 0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b, 143 0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d} 144 priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKey) 145 146 wif, err := NewWIF(priv, nil, true) 147 148 if wif != nil { 149 t.Fatalf("NewWIF: unexpectedly succeeded - got '%v', want '%v'", 150 wif, nil) 151 } 152 if err == nil || err.Error() != "no network" { 153 t.Fatalf("NewWIF: expected error 'no network', got '%v'", err) 154 } 155 }) 156} 157