github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/enr/enr_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:44</date> 10 //</624342658193559552> 11 12 13 package enr 14 15 import ( 16 "bytes" 17 "encoding/hex" 18 "fmt" 19 "math/rand" 20 "testing" 21 "time" 22 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/rlp" 25 "github.com/stretchr/testify/assert" 26 "github.com/stretchr/testify/require" 27 ) 28 29 var ( 30 privkey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 31 pubkey = &privkey.PublicKey 32 ) 33 34 var rnd = rand.New(rand.NewSource(time.Now().UnixNano())) 35 36 func randomString(strlen int) string { 37 b := make([]byte, strlen) 38 rnd.Read(b) 39 return string(b) 40 } 41 42 //testgetsetid测试ID键的编码/解码和设置/获取。 43 func TestGetSetID(t *testing.T) { 44 id := ID("someid") 45 var r Record 46 r.Set(id) 47 48 var id2 ID 49 require.NoError(t, r.Load(&id2)) 50 assert.Equal(t, id, id2) 51 } 52 53 //testgetsetip4测试IP密钥的编码/解码和设置/获取。 54 func TestGetSetIP4(t *testing.T) { 55 ip := IP{192, 168, 0, 3} 56 var r Record 57 r.Set(ip) 58 59 var ip2 IP 60 require.NoError(t, r.Load(&ip2)) 61 assert.Equal(t, ip, ip2) 62 } 63 64 //testgetsetip6测试IP密钥的编码/解码和设置/获取。 65 func TestGetSetIP6(t *testing.T) { 66 ip := IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68} 67 var r Record 68 r.Set(ip) 69 70 var ip2 IP 71 require.NoError(t, r.Load(&ip2)) 72 assert.Equal(t, ip, ip2) 73 } 74 75 //testgetsetdiscport测试discport密钥的编码/解码和设置/获取。 76 func TestGetSetUDP(t *testing.T) { 77 port := UDP(30309) 78 var r Record 79 r.Set(port) 80 81 var port2 UDP 82 require.NoError(t, r.Load(&port2)) 83 assert.Equal(t, port, port2) 84 } 85 86 //testgetsetsecp256k1测试secp256k1密钥的编码/解码和设置/获取。 87 func TestGetSetSecp256k1(t *testing.T) { 88 var r Record 89 if err := SignV4(&r, privkey); err != nil { 90 t.Fatal(err) 91 } 92 93 var pk Secp256k1 94 require.NoError(t, r.Load(&pk)) 95 assert.EqualValues(t, pubkey, &pk) 96 } 97 98 func TestLoadErrors(t *testing.T) { 99 var r Record 100 ip4 := IP{127, 0, 0, 1} 101 r.Set(ip4) 102 103 //检查是否有钥匙丢失的错误。 104 var udp UDP 105 err := r.Load(&udp) 106 if !IsNotFound(err) { 107 t.Error("IsNotFound should return true for missing key") 108 } 109 assert.Equal(t, &KeyError{Key: udp.ENRKey(), Err: errNotFound}, err) 110 111 //检查无效密钥的错误。 112 var list []uint 113 err = r.Load(WithEntry(ip4.ENRKey(), &list)) 114 kerr, ok := err.(*KeyError) 115 if !ok { 116 t.Fatalf("expected KeyError, got %T", err) 117 } 118 assert.Equal(t, kerr.Key, ip4.ENRKey()) 119 assert.Error(t, kerr.Err) 120 if IsNotFound(err) { 121 t.Error("IsNotFound should return false for decoding errors") 122 } 123 } 124 125 //testsortedgetandset生成排序对切片的测试。 126 func TestSortedGetAndSet(t *testing.T) { 127 type pair struct { 128 k string 129 v uint32 130 } 131 132 for _, tt := range []struct { 133 input []pair 134 want []pair 135 }{ 136 { 137 input: []pair{{"a", 1}, {"c", 2}, {"b", 3}}, 138 want: []pair{{"a", 1}, {"b", 3}, {"c", 2}}, 139 }, 140 { 141 input: []pair{{"a", 1}, {"c", 2}, {"b", 3}, {"d", 4}, {"a", 5}, {"bb", 6}}, 142 want: []pair{{"a", 5}, {"b", 3}, {"bb", 6}, {"c", 2}, {"d", 4}}, 143 }, 144 { 145 input: []pair{{"c", 2}, {"b", 3}, {"d", 4}, {"a", 5}, {"bb", 6}}, 146 want: []pair{{"a", 5}, {"b", 3}, {"bb", 6}, {"c", 2}, {"d", 4}}, 147 }, 148 } { 149 var r Record 150 for _, i := range tt.input { 151 r.Set(WithEntry(i.k, &i.v)) 152 } 153 for i, w := range tt.want { 154 //设置r.pair[i]中的got's键,以便保留对的顺序 155 got := pair{k: r.pairs[i].k} 156 assert.NoError(t, r.Load(WithEntry(w.k, &got.v))) 157 assert.Equal(t, w, got) 158 } 159 } 160 } 161 162 //testDirty测试在记录中设置新的键/值对时记录签名删除。 163 func TestDirty(t *testing.T) { 164 var r Record 165 166 if r.Signed() { 167 t.Error("Signed returned true for zero record") 168 } 169 if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned { 170 t.Errorf("expected errEncodeUnsigned, got %#v", err) 171 } 172 173 require.NoError(t, SignV4(&r, privkey)) 174 if !r.Signed() { 175 t.Error("Signed return false for signed record") 176 } 177 _, err := rlp.EncodeToBytes(r) 178 assert.NoError(t, err) 179 180 r.SetSeq(3) 181 if r.Signed() { 182 t.Error("Signed returned true for modified record") 183 } 184 if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned { 185 t.Errorf("expected errEncodeUnsigned, got %#v", err) 186 } 187 } 188 189 //使用记录中的现有键设置新值时,testgetsetoverwrite测试值overwrite。 190 func TestGetSetOverwrite(t *testing.T) { 191 var r Record 192 193 ip := IP{192, 168, 0, 3} 194 r.Set(ip) 195 196 ip2 := IP{192, 168, 0, 4} 197 r.Set(ip2) 198 199 var ip3 IP 200 require.NoError(t, r.Load(&ip3)) 201 assert.Equal(t, ip2, ip3) 202 } 203 204 //testsignencodeanddecode测试记录的签名、rlp编码和rlp解码。 205 func TestSignEncodeAndDecode(t *testing.T) { 206 var r Record 207 r.Set(UDP(30303)) 208 r.Set(IP{127, 0, 0, 1}) 209 require.NoError(t, SignV4(&r, privkey)) 210 211 blob, err := rlp.EncodeToBytes(r) 212 require.NoError(t, err) 213 214 var r2 Record 215 require.NoError(t, rlp.DecodeBytes(blob, &r2)) 216 assert.Equal(t, r, r2) 217 218 blob2, err := rlp.EncodeToBytes(r2) 219 require.NoError(t, err) 220 assert.Equal(t, blob, blob2) 221 } 222 223 func TestNodeAddr(t *testing.T) { 224 var r Record 225 if addr := r.NodeAddr(); addr != nil { 226 t.Errorf("wrong address on empty record: got %v, want %v", addr, nil) 227 } 228 229 require.NoError(t, SignV4(&r, privkey)) 230 expected := "a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7" 231 assert.Equal(t, expected, hex.EncodeToString(r.NodeAddr())) 232 } 233 234 var pyRecord, _ = hex.DecodeString("f884b8407098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c01826964827634826970847f00000189736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31388375647082765f") 235 236 //testpythorintrop检查是否可以解码和验证由python生成的记录 237 //实施。 238 func TestPythonInterop(t *testing.T) { 239 var r Record 240 if err := rlp.DecodeBytes(pyRecord, &r); err != nil { 241 t.Fatalf("can't decode: %v", err) 242 } 243 244 var ( 245 wantAddr, _ = hex.DecodeString("a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7") 246 wantSeq = uint64(1) 247 wantIP = IP{127, 0, 0, 1} 248 wantUDP = UDP(30303) 249 ) 250 if r.Seq() != wantSeq { 251 t.Errorf("wrong seq: got %d, want %d", r.Seq(), wantSeq) 252 } 253 if addr := r.NodeAddr(); !bytes.Equal(addr, wantAddr) { 254 t.Errorf("wrong addr: got %x, want %x", addr, wantAddr) 255 } 256 want := map[Entry]interface{}{new(IP): &wantIP, new(UDP): &wantUDP} 257 for k, v := range want { 258 desc := fmt.Sprintf("loading key %q", k.ENRKey()) 259 if assert.NoError(t, r.Load(k), desc) { 260 assert.Equal(t, k, v, desc) 261 } 262 } 263 } 264 265 //无法对记录大于sizelimit字节的TestRecordToObig测试进行签名。 266 func TestRecordTooBig(t *testing.T) { 267 var r Record 268 key := randomString(10) 269 270 //为随机键设置大值,预计错误 271 r.Set(WithEntry(key, randomString(SizeLimit))) 272 if err := SignV4(&r, privkey); err != errTooBig { 273 t.Fatalf("expected to get errTooBig, got %#v", err) 274 } 275 276 //为随机键设置一个可接受的值,不期望出现错误 277 r.Set(WithEntry(key, randomString(100))) 278 require.NoError(t, SignV4(&r, privkey)) 279 } 280 281 //testsignencodeanddecoderandom测试包含随机键/值对的记录的编码/解码。 282 func TestSignEncodeAndDecodeRandom(t *testing.T) { 283 var r Record 284 285 //用于测试的随机键/值对 286 pairs := map[string]uint32{} 287 for i := 0; i < 10; i++ { 288 key := randomString(7) 289 value := rnd.Uint32() 290 pairs[key] = value 291 r.Set(WithEntry(key, &value)) 292 } 293 294 require.NoError(t, SignV4(&r, privkey)) 295 _, err := rlp.EncodeToBytes(r) 296 require.NoError(t, err) 297 298 for k, v := range pairs { 299 desc := fmt.Sprintf("key %q", k) 300 var got uint32 301 buf := WithEntry(k, &got) 302 require.NoError(t, r.Load(buf), desc) 303 require.Equal(t, v, got, desc) 304 } 305 } 306 307 func BenchmarkDecode(b *testing.B) { 308 var r Record 309 for i := 0; i < b.N; i++ { 310 rlp.DecodeBytes(pyRecord, &r) 311 } 312 b.StopTimer() 313 r.NodeAddr() 314 } 315