OSDN Git Service

Merge branch 'dev' into wallet
[bytom/bytom.git] / common / address_test.go
1 package common
2
3 import (
4     "bytes"
5     "fmt"
6     "reflect"
7     "strings"
8     "testing"
9
10     "github.com/bytom/consensus"
11     "github.com/bytom/common/bech32"
12
13 )
14
15 func TestAddresses(t *testing.T) {
16     tests := []struct {
17         name    string
18         addr    string
19         encoded string
20         valid   bool
21         result  Address
22         f       func() (Address, error)
23         net     *consensus.Params
24     }{
25         // Segwit address tests.
26         {
27             name:    "segwit mainnet p2wpkh v0",
28             addr:    "BM1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7K23GYYF",
29             encoded: "bm1qw508d6qejxtdg4y5r3zarvary0c5xw7k23gyyf",
30             valid:   true,
31             result: tstAddressWitnessPubKeyHash(
32                 0,
33                 [20]byte{
34                     0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94,
35                     0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6},
36                 consensus.MainNetParams.Bech32HRPSegwit),
37             f: func() (Address, error) {
38                 pkHash := []byte{
39                     0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94,
40                     0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}
41                 return NewAddressWitnessPubKeyHash(pkHash, &consensus.MainNetParams)
42             },
43             net: &consensus.MainNetParams,
44         },
45         {
46             name:    "segwit mainnet p2wsh v0",
47             addr:    "bm1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qk5egtg",
48             encoded: "bm1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qk5egtg",
49             valid:   true,
50             result: tstAddressWitnessScriptHash(
51                 0,
52                 [32]byte{
53                     0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68,
54                     0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13,
55                     0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1,
56                     0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62},
57                 consensus.MainNetParams.Bech32HRPSegwit),
58             f: func() (Address, error) {
59                 scriptHash := []byte{
60                     0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68,
61                     0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13,
62                     0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1,
63                     0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}
64                 return NewAddressWitnessScriptHash(scriptHash, &consensus.MainNetParams)
65             },
66             net: &consensus.MainNetParams,
67         },
68         {
69             name:    "segwit testnet p2wpkh v0",
70             addr:    "tm1qw508d6qejxtdg4y5r3zarvary0c5xw7kw8fqyc",
71             encoded: "tm1qw508d6qejxtdg4y5r3zarvary0c5xw7kw8fqyc",
72             valid:   true,
73             result: tstAddressWitnessPubKeyHash(
74                 0,
75                 [20]byte{
76                     0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94,
77                     0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6},
78                 consensus.TestNetParams.Bech32HRPSegwit),
79             f: func() (Address, error) {
80                 pkHash := []byte{
81                     0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94,
82                     0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}
83                 return NewAddressWitnessPubKeyHash(pkHash, &consensus.TestNetParams)
84             },
85             net: &consensus.TestNetParams,
86         },
87         {
88             name:    "segwit testnet p2wsh v0",
89             addr:    "tm1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qqq379v",
90             encoded: "tm1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qqq379v",
91             valid:   true,
92             result: tstAddressWitnessScriptHash(
93                 0,
94                 [32]byte{
95                     0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68,
96                     0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13,
97                     0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1,
98                     0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62},
99                 consensus.TestNetParams.Bech32HRPSegwit),
100             f: func() (Address, error) {
101                 scriptHash := []byte{
102                     0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68,
103                     0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13,
104                     0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1,
105                     0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}
106                 return NewAddressWitnessScriptHash(scriptHash, &consensus.TestNetParams)
107             },
108             net: &consensus.TestNetParams,
109         },
110         {
111             name:    "segwit testnet p2wsh witness v0",
112             addr:    "tm1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesvkesyk",
113             encoded: "tm1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesvkesyk",
114             valid:   true,
115             result:  tstAddressWitnessScriptHash(
116                 0,
117                 [32]byte{
118                     0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62,
119                     0x21, 0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66,
120                     0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c, 0x6c, 0xe2,
121                     0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33},
122                 consensus.TestNetParams.Bech32HRPSegwit),
123             f: func() (Address, error) {
124                 scriptHash := []byte{
125                     0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62,
126                     0x21, 0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66,
127                     0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c, 0x6c, 0xe2,
128                     0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}
129                 return NewAddressWitnessScriptHash(scriptHash, &consensus.TestNetParams)
130             },
131             net: &consensus.TestNetParams,
132         },
133         // Unsupported witness versions (version 0 only supported at this point)
134         {
135             name:  "segwit mainnet witness v1",
136             addr:  "bm1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
137             valid: false,
138             net:   &consensus.MainNetParams,
139         },
140         {
141             name:  "segwit mainnet witness v16",
142             addr:  "BM1SW50QA3JX3S",
143             valid: false,
144             net:   &consensus.MainNetParams,
145         },
146         {
147             name:  "segwit mainnet witness v2",
148             addr:  "bm1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
149             valid: false,
150             net:   &consensus.MainNetParams,
151         },
152         // Invalid segwit addresses
153         {
154             name:  "segwit invalid hrp",
155             addr:  "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty",
156             valid: false,
157             net:   &consensus.TestNetParams,
158         },
159         {
160             name:  "segwit invalid checksum",
161             addr:  "bm1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5",
162             valid: false,
163             net:   &consensus.MainNetParams,
164         },
165         {
166             name:  "segwit invalid witness version",
167             addr:  "BM13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2",
168             valid: false,
169             net:   &consensus.MainNetParams,
170         },
171         {
172             name:  "segwit invalid program length",
173             addr:  "bm1rw5uspcuh",
174             valid: false,
175             net:   &consensus.MainNetParams,
176         },
177         {
178             name:  "segwit invalid program length",
179             addr:  "bm10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90",
180             valid: false,
181             net:   &consensus.MainNetParams,
182         },
183         {
184             name:  "segwit invalid program length for witness version 0 (per BIP141)",
185             addr:  "BM1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
186             valid: false,
187             net:   &consensus.MainNetParams,
188         },
189         {
190             name:  "segwit mixed case",
191             addr:  "tm1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7",
192             valid: false,
193             net:   &consensus.TestNetParams,
194         },
195         {
196             name:  "segwit zero padding of more than 4 bits",
197             addr:  "tm1pw508d6qejxtdg4y5r3zarqfsj6c3",
198             valid: false,
199             net:   &consensus.TestNetParams,
200         },
201         {
202             name:  "segwit non-zero padding in 8-to-5 conversion",
203             addr:  "tm1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv",
204             valid: false,
205             net:   &consensus.TestNetParams,
206         },
207     }
208
209     for _, test := range tests {
210         // Decode addr and compare error against valid.        
211         decoded, err := DecodeAddress(test.addr, test.net)
212         if (err == nil) != test.valid {
213             t.Errorf("%v: decoding test failed: %v", test.name, err)
214             return
215         }
216
217         if err == nil {
218             // Ensure the stringer returns the same address as the
219             // original.
220             
221             if decodedStringer, ok := decoded.(fmt.Stringer); ok {
222                 addr := test.addr
223
224                 // For Segwit addresses the string representation
225                 // will always be lower case, so in that case we
226                 // convert the original to lower case first.
227                 if strings.Contains(test.name, "segwit") {
228                     addr = strings.ToLower(addr)
229                 }
230
231                 if addr != decodedStringer.String() {
232                     t.Errorf("%v: String on decoded value does not match expected value: %v != %v",
233                         test.name, test.addr, decodedStringer.String())
234                     return
235                 }
236
237             }
238         
239             // Encode again and compare against the original.
240             encoded := decoded.EncodeAddress()
241             if test.encoded != encoded {
242                 t.Errorf("%v: decoding and encoding produced different addressess: %v != %v",
243                     test.name, test.encoded, encoded)
244                 return
245             }
246
247             // Perform type-specific calculations.
248             var saddr []byte
249             switch decoded.(type) {
250
251             case *AddressWitnessPubKeyHash:
252                 saddr = tstAddressSegwitSAddr(encoded)
253             case *AddressWitnessScriptHash:
254                 saddr = tstAddressSegwitSAddr(encoded)
255             }
256
257             // Check script address, as well as the Hash160 method for P2PKH and
258             // P2SH addresses.
259             if !bytes.Equal(saddr, decoded.ScriptAddress()) {
260                 t.Errorf("%v: script addresses do not match:\n%x != \n%x",
261                     test.name, saddr, decoded.ScriptAddress())
262                 return
263             }
264             switch a := decoded.(type) {
265
266             case *AddressWitnessPubKeyHash:
267                 if hrp := a.Hrp(); test.net.Bech32HRPSegwit != hrp {
268                     t.Errorf("%v: hrps do not match:\n%x != \n%x",
269                         test.name, test.net.Bech32HRPSegwit, hrp)
270                     return
271                 }
272
273                 expVer := test.result.(*AddressWitnessPubKeyHash).WitnessVersion()
274                 if v := a.WitnessVersion(); v != expVer {
275                     t.Errorf("%v: witness versions do not match:\n%x != \n%x",
276                         test.name, expVer, v)
277                     return
278                 }
279
280                 if p := a.WitnessProgram(); !bytes.Equal(saddr, p) {
281                     t.Errorf("%v: witness programs do not match:\n%x != \n%x",
282                         test.name, saddr, p)
283                     return
284                 }
285
286             case *AddressWitnessScriptHash:
287                 if hrp := a.Hrp(); test.net.Bech32HRPSegwit != hrp {
288                     t.Errorf("%v: hrps do not match:\n%x != \n%x",
289                         test.name, test.net.Bech32HRPSegwit, hrp)
290                     return
291                 }
292
293                 expVer := test.result.(*AddressWitnessScriptHash).WitnessVersion()
294                 if v := a.WitnessVersion(); v != expVer {
295                     t.Errorf("%v: witness versions do not match:\n%x != \n%x",
296                         test.name, expVer, v)
297                     return
298                 }
299
300                 if p := a.WitnessProgram(); !bytes.Equal(saddr, p) {
301                     t.Errorf("%v: witness programs do not match:\n%x != \n%x",
302                         test.name, saddr, p)
303                     return
304                 }
305             }
306
307             // Ensure the address is for the expected network.
308             if !decoded.IsForNet(test.net) {
309                 t.Errorf("%v: calculated network does not match expected",
310                     test.name)
311                 return
312             }
313         }
314
315         if !test.valid {
316             // If address is invalid, but a creation function exists,
317             // verify that it returns a nil addr and non-nil error.
318             if test.f != nil {
319                 _, err := test.f()
320                 if err == nil {
321                     t.Errorf("%v: address is invalid but creating new address succeeded",
322                         test.name)
323                     return
324                 }
325             }
326             continue
327         }
328
329         // Valid test, compare address created with f against expected result.
330         addr, err := test.f()
331         if err != nil {
332             t.Errorf("%v: address is valid but creating new address failed with error %v",
333                 test.name, err)
334             return
335         }
336
337         if !reflect.DeepEqual(addr, test.result) {
338             t.Errorf("%v: created address does not match expected result",
339                 test.name)
340             return
341         }
342     }
343 }
344
345
346 // TstAddressWitnessPubKeyHash creates an AddressWitnessPubKeyHash, initiating
347 // the fields as given.
348 func tstAddressWitnessPubKeyHash(version byte, program [20]byte,
349     hrp string) *AddressWitnessPubKeyHash {
350
351     return &AddressWitnessPubKeyHash{
352         hrp:            hrp,
353         witnessVersion: version,
354         witnessProgram: program,
355     }
356 }
357
358 // TstAddressWitnessScriptHash creates an AddressWitnessScriptHash, initiating
359 // the fields as given.
360 func tstAddressWitnessScriptHash(version byte, program [32]byte,
361     hrp string) *AddressWitnessScriptHash {
362
363     return &AddressWitnessScriptHash{
364         hrp:            hrp,
365         witnessVersion: version,
366         witnessProgram: program,
367     }
368 }
369
370 // TstAddressSegwitSAddr returns the expected witness program bytes for
371 // bech32 encoded P2WPKH and P2WSH bitcoin addresses.
372 func tstAddressSegwitSAddr(addr string) []byte {
373     _, data, err := bech32.Decode(addr)
374     if err != nil {
375         return []byte{}
376     }
377
378     // First byte is version, rest is base 32 encoded data.
379     data, err = bech32.ConvertBits(data[1:], 5, 8, false)
380     if err != nil {
381         return []byte{}
382     }
383     return data
384 }