github.com/annchain/OG@v0.0.9/p2p/discv5/node_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package discv5 18 19 import ( 20 "fmt" 21 "github.com/annchain/OG/arefactor/og/types" 22 ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto" 23 "math/big" 24 "math/rand" 25 "net" 26 "reflect" 27 "strings" 28 "testing" 29 "testing/quick" 30 "time" 31 ) 32 33 func ExampleNewNode() { 34 id := MustHexID("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439") 35 36 // Complete nodes contain UDP and TCP endpoints: 37 n1 := NewNode(id, net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 52150, 30303) 38 fmt.Println("n1:", n1) 39 fmt.Println("n1.Incomplete() ->", n1.Incomplete()) 40 41 // An incomplete node can be created by passing zero values 42 // for all parameters except id. 43 n2 := NewNode(id, nil, 0, 0) 44 fmt.Println("n2:", n2) 45 fmt.Println("n2.Incomplete() ->", n2.Incomplete()) 46 47 // Output: 48 // n1: onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:30303?discport=52150 49 // n1.Incomplete() -> false 50 // n2: onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439 51 // n2.Incomplete() -> true 52 } 53 54 var parseNodeTests = []struct { 55 rawurl string 56 wantError string 57 wantResult *Node 58 }{ 59 { 60 rawurl: "http://foobar", 61 wantError: `invalid URL scheme, want "onode"`, 62 }, 63 { 64 rawurl: "onode://01010101@123.124.125.126:3", 65 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 66 }, 67 // Complete nodes with IP address. 68 { 69 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 70 wantError: `invalid IP address`, 71 }, 72 { 73 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 74 wantError: `invalid port`, 75 }, 76 { 77 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 78 wantError: `invalid discport in query`, 79 }, 80 { 81 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 82 wantResult: NewNode( 83 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 84 net.IP{0x7f, 0x0, 0x0, 0x1}, 85 52150, 86 52150, 87 ), 88 }, 89 { 90 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 91 wantResult: NewNode( 92 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 93 net.ParseIP("::"), 94 52150, 95 52150, 96 ), 97 }, 98 { 99 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 100 wantResult: NewNode( 101 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 102 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 103 52150, 104 52150, 105 ), 106 }, 107 { 108 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 109 wantResult: NewNode( 110 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 111 net.IP{0x7f, 0x0, 0x0, 0x1}, 112 22334, 113 52150, 114 ), 115 }, 116 // Incomplete nodes with no address. 117 { 118 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 119 wantResult: NewNode( 120 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 121 nil, 0, 0, 122 ), 123 }, 124 { 125 rawurl: "onode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 126 wantResult: NewNode( 127 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 128 nil, 0, 0, 129 ), 130 }, 131 // Invalid URLs 132 { 133 rawurl: "01010101", 134 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 135 }, 136 { 137 rawurl: "onode://01010101", 138 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 139 }, 140 { 141 // This test checks that errors from url.Parse are handled. 142 rawurl: "://foo", 143 wantError: `parse ://foo: missing protocol scheme`, 144 }, 145 } 146 147 func TestParseNode(t *testing.T) { 148 for _, test := range parseNodeTests { 149 n, err := ParseNode(test.rawurl) 150 if test.wantError != "" { 151 if err == nil { 152 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 153 continue 154 } else if err.Error() != test.wantError { 155 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 156 continue 157 } 158 } else { 159 if err != nil { 160 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 161 continue 162 } 163 if !reflect.DeepEqual(n, test.wantResult) { 164 t.Errorf("test %q:\n result mismatch:\ngot: %#v, want: %#v", test.rawurl, n, test.wantResult) 165 } 166 } 167 } 168 } 169 170 func TestNodeString(t *testing.T) { 171 for i, test := range parseNodeTests { 172 if test.wantError == "" && strings.HasPrefix(test.rawurl, "onode://") { 173 str := test.wantResult.String() 174 if str != test.rawurl { 175 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 176 } 177 } 178 } 179 } 180 181 func TestHexID(t *testing.T) { 182 ref := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 106, 217, 182, 31, 165, 174, 1, 67, 7, 235, 220, 150, 66, 83, 173, 205, 159, 44, 10, 57, 42, 161, 26, 188} 183 id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 184 id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 185 186 if id1 != ref { 187 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 188 } 189 if id2 != ref { 190 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 191 } 192 } 193 194 func TestNodeID_recover(t *testing.T) { 195 prv := newkey() 196 hash := make([]byte, 32) 197 sig, err := ogcrypto2.Sign(hash, prv) 198 if err != nil { 199 t.Fatalf("signing error: %v", err) 200 } 201 202 pub := PubkeyID(&prv.PublicKey) 203 recpub, err := recoverNodeID(hash, sig) 204 if err != nil { 205 t.Fatalf("recovery error: %v", err) 206 } 207 if pub != recpub { 208 t.Errorf("recovered wrong pubkey:\ngot: %v\nwant: %v", recpub, pub) 209 } 210 211 ecdsa, err := pub.Pubkey() 212 if err != nil { 213 t.Errorf("Pubkey error: %v", err) 214 } 215 if !reflect.DeepEqual(ecdsa, &prv.PublicKey) { 216 t.Errorf("Pubkey mismatch:\n got: %#v\n want: %#v", ecdsa, &prv.PublicKey) 217 } 218 } 219 220 func TestNodeID_pubkeyBad(t *testing.T) { 221 ecdsa, err := NodeID{}.Pubkey() 222 if err == nil { 223 t.Error("expected error for zero ID") 224 } 225 if ecdsa != nil { 226 t.Error("expected nil result") 227 } 228 } 229 230 func TestNodeID_distcmp(t *testing.T) { 231 distcmpBig := func(target, a, b types.Hash) int { 232 tbig := new(big.Int).SetBytes(target.Bytes[:]) 233 abig := new(big.Int).SetBytes(a.Bytes[:]) 234 bbig := new(big.Int).SetBytes(b.Bytes[:]) 235 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 236 } 237 if err := quick.CheckEqual(distcmp, distcmpBig, quickcfg()); err != nil { 238 t.Error(err) 239 } 240 } 241 242 // the random tests is likely to miss the case where they're equal. 243 func TestNodeID_distcmpEqual(t *testing.T) { 244 base := types.Hash{} 245 x := types.Hash{} 246 base.Bytes = types.HashBytes{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 247 x.Bytes = types.HashBytes{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 248 if distcmp(base, x, x) != 0 { 249 t.Errorf("distcmp(base, x, x) != 0") 250 } 251 } 252 253 func TestNodeID_logdist(t *testing.T) { 254 logdistBig := func(a, b types.Hash) int { 255 abig, bbig := new(big.Int).SetBytes(a.Bytes[:]), new(big.Int).SetBytes(b.Bytes[:]) 256 return new(big.Int).Xor(abig, bbig).BitLen() 257 } 258 if err := quick.CheckEqual(logdist, logdistBig, quickcfg()); err != nil { 259 t.Error(err) 260 } 261 } 262 263 // the random tests is likely to miss the case where they're equal. 264 func TestNodeID_logdistEqual(t *testing.T) { 265 x := types.Hash{} 266 h := types.HashBytes{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 267 x.Bytes = h 268 if logdist(x, x) != 0 { 269 t.Errorf("logdist(x, x) != 0") 270 } 271 } 272 273 func TestNodeID_hashAtDistance(t *testing.T) { 274 // we don't use quick.Check here because its output isn't 275 // very helpful when the test fails. 276 cfg := quickcfg() 277 for i := 0; i < cfg.MaxCount; i++ { 278 a := gen(types.Hash{}, cfg.Rand).(types.Hash) 279 dist := cfg.Rand.Intn(len(types.Hash{}.Bytes) * 8) 280 result := hashAtDistance(a, dist) 281 actualdist := logdist(result, a) 282 283 if dist != actualdist { 284 t.Log("a: ", a) 285 t.Log("result:", result) 286 t.Fatalf("#%d: distance of result is %d, want %d", i, actualdist, dist) 287 } 288 } 289 } 290 291 func quickcfg() *quick.Config { 292 return &quick.Config{ 293 MaxCount: 5000, 294 Rand: rand.New(rand.NewSource(time.Now().Unix())), 295 } 296 } 297 298 // TODO: The Generate method can be dropped when we require Go >= 1.5 299 // because testing/quick learned to generate arrays in 1.5. 300 301 func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value { 302 var id NodeID 303 m := rand.Intn(len(id)) 304 for i := len(id) - 1; i > m; i-- { 305 id[i] = byte(rand.Uint32()) 306 } 307 return reflect.ValueOf(id) 308 }