github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/p2p/enr/enr_test.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package enr 13 14 import ( 15 "bytes" 16 "encoding/hex" 17 "fmt" 18 "math/rand" 19 "testing" 20 "time" 21 22 "github.com/Sberex/go-sberex/crypto" 23 "github.com/Sberex/go-sberex/rlp" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 ) 27 28 var ( 29 privkey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 30 pubkey = &privkey.PublicKey 31 ) 32 33 var rnd = rand.New(rand.NewSource(time.Now().UnixNano())) 34 35 func randomString(strlen int) string { 36 b := make([]byte, strlen) 37 rnd.Read(b) 38 return string(b) 39 } 40 41 // TestGetSetID tests encoding/decoding and setting/getting of the ID key. 42 func TestGetSetID(t *testing.T) { 43 id := ID("someid") 44 var r Record 45 r.Set(id) 46 47 var id2 ID 48 require.NoError(t, r.Load(&id2)) 49 assert.Equal(t, id, id2) 50 } 51 52 // TestGetSetIP4 tests encoding/decoding and setting/getting of the IP4 key. 53 func TestGetSetIP4(t *testing.T) { 54 ip := IP4{192, 168, 0, 3} 55 var r Record 56 r.Set(ip) 57 58 var ip2 IP4 59 require.NoError(t, r.Load(&ip2)) 60 assert.Equal(t, ip, ip2) 61 } 62 63 // TestGetSetIP6 tests encoding/decoding and setting/getting of the IP6 key. 64 func TestGetSetIP6(t *testing.T) { 65 ip := IP6{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68} 66 var r Record 67 r.Set(ip) 68 69 var ip2 IP6 70 require.NoError(t, r.Load(&ip2)) 71 assert.Equal(t, ip, ip2) 72 } 73 74 // TestGetSetDiscPort tests encoding/decoding and setting/getting of the DiscPort key. 75 func TestGetSetDiscPort(t *testing.T) { 76 port := DiscPort(30309) 77 var r Record 78 r.Set(port) 79 80 var port2 DiscPort 81 require.NoError(t, r.Load(&port2)) 82 assert.Equal(t, port, port2) 83 } 84 85 // TestGetSetSecp256k1 tests encoding/decoding and setting/getting of the Secp256k1 key. 86 func TestGetSetSecp256k1(t *testing.T) { 87 var r Record 88 if err := r.Sign(privkey); err != nil { 89 t.Fatal(err) 90 } 91 92 var pk Secp256k1 93 require.NoError(t, r.Load(&pk)) 94 assert.EqualValues(t, pubkey, &pk) 95 } 96 97 func TestLoadErrors(t *testing.T) { 98 var r Record 99 ip4 := IP4{127, 0, 0, 1} 100 r.Set(ip4) 101 102 // Check error for missing keys. 103 var ip6 IP6 104 err := r.Load(&ip6) 105 if !IsNotFound(err) { 106 t.Error("IsNotFound should return true for missing key") 107 } 108 assert.Equal(t, &KeyError{Key: ip6.ENRKey(), Err: errNotFound}, err) 109 110 // Check error for invalid keys. 111 var list []uint 112 err = r.Load(WithEntry(ip4.ENRKey(), &list)) 113 kerr, ok := err.(*KeyError) 114 if !ok { 115 t.Fatalf("expected KeyError, got %T", err) 116 } 117 assert.Equal(t, kerr.Key, ip4.ENRKey()) 118 assert.Error(t, kerr.Err) 119 if IsNotFound(err) { 120 t.Error("IsNotFound should return false for decoding errors") 121 } 122 } 123 124 // TestSortedGetAndSet tests that Set produced a sorted pairs slice. 125 func TestSortedGetAndSet(t *testing.T) { 126 type pair struct { 127 k string 128 v uint32 129 } 130 131 for _, tt := range []struct { 132 input []pair 133 want []pair 134 }{ 135 { 136 input: []pair{{"a", 1}, {"c", 2}, {"b", 3}}, 137 want: []pair{{"a", 1}, {"b", 3}, {"c", 2}}, 138 }, 139 { 140 input: []pair{{"a", 1}, {"c", 2}, {"b", 3}, {"d", 4}, {"a", 5}, {"bb", 6}}, 141 want: []pair{{"a", 5}, {"b", 3}, {"bb", 6}, {"c", 2}, {"d", 4}}, 142 }, 143 { 144 input: []pair{{"c", 2}, {"b", 3}, {"d", 4}, {"a", 5}, {"bb", 6}}, 145 want: []pair{{"a", 5}, {"b", 3}, {"bb", 6}, {"c", 2}, {"d", 4}}, 146 }, 147 } { 148 var r Record 149 for _, i := range tt.input { 150 r.Set(WithEntry(i.k, &i.v)) 151 } 152 for i, w := range tt.want { 153 // set got's key from r.pair[i], so that we preserve order of pairs 154 got := pair{k: r.pairs[i].k} 155 assert.NoError(t, r.Load(WithEntry(w.k, &got.v))) 156 assert.Equal(t, w, got) 157 } 158 } 159 } 160 161 // TestDirty tests record signature removal on setting of new key/value pair in record. 162 func TestDirty(t *testing.T) { 163 var r Record 164 165 if r.Signed() { 166 t.Error("Signed returned true for zero record") 167 } 168 if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned { 169 t.Errorf("expected errEncodeUnsigned, got %#v", err) 170 } 171 172 require.NoError(t, r.Sign(privkey)) 173 if !r.Signed() { 174 t.Error("Signed return false for signed record") 175 } 176 _, err := rlp.EncodeToBytes(r) 177 assert.NoError(t, err) 178 179 r.SetSeq(3) 180 if r.Signed() { 181 t.Error("Signed returned true for modified record") 182 } 183 if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned { 184 t.Errorf("expected errEncodeUnsigned, got %#v", err) 185 } 186 } 187 188 // TestGetSetOverwrite tests value overwrite when setting a new value with an existing key in record. 189 func TestGetSetOverwrite(t *testing.T) { 190 var r Record 191 192 ip := IP4{192, 168, 0, 3} 193 r.Set(ip) 194 195 ip2 := IP4{192, 168, 0, 4} 196 r.Set(ip2) 197 198 var ip3 IP4 199 require.NoError(t, r.Load(&ip3)) 200 assert.Equal(t, ip2, ip3) 201 } 202 203 // TestSignEncodeAndDecode tests signing, RLP encoding and RLP decoding of a record. 204 func TestSignEncodeAndDecode(t *testing.T) { 205 var r Record 206 r.Set(DiscPort(30303)) 207 r.Set(IP4{127, 0, 0, 1}) 208 require.NoError(t, r.Sign(privkey)) 209 210 blob, err := rlp.EncodeToBytes(r) 211 require.NoError(t, err) 212 213 var r2 Record 214 require.NoError(t, rlp.DecodeBytes(blob, &r2)) 215 assert.Equal(t, r, r2) 216 217 blob2, err := rlp.EncodeToBytes(r2) 218 require.NoError(t, err) 219 assert.Equal(t, blob, blob2) 220 } 221 222 func TestNodeAddr(t *testing.T) { 223 var r Record 224 if addr := r.NodeAddr(); addr != nil { 225 t.Errorf("wrong address on empty record: got %v, want %v", addr, nil) 226 } 227 228 require.NoError(t, r.Sign(privkey)) 229 expected := "caaa1485d83b18b32ed9ad666026151bf0cae8a0a88c857ae2d4c5be2daa6726" 230 assert.Equal(t, expected, hex.EncodeToString(r.NodeAddr())) 231 } 232 233 var pyRecord, _ = hex.DecodeString("f896b840954dc36583c1f4b69ab59b1375f362f06ee99f3723cd77e64b6de6d211c27d7870642a79d4516997f94091325d2a7ca6215376971455fb221d34f35b277149a1018664697363763582765f82696490736563703235366b312d6b656363616b83697034847f00000189736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") 234 235 // TestPythonInterop checks that we can decode and verify a record produced by the Python 236 // implementation. 237 func TestPythonInterop(t *testing.T) { 238 var r Record 239 if err := rlp.DecodeBytes(pyRecord, &r); err != nil { 240 t.Fatalf("can't decode: %v", err) 241 } 242 243 var ( 244 wantAddr, _ = hex.DecodeString("caaa1485d83b18b32ed9ad666026151bf0cae8a0a88c857ae2d4c5be2daa6726") 245 wantSeq = uint64(1) 246 wantIP = IP4{127, 0, 0, 1} 247 wantDiscport = DiscPort(30303) 248 ) 249 if r.Seq() != wantSeq { 250 t.Errorf("wrong seq: got %d, want %d", r.Seq(), wantSeq) 251 } 252 if addr := r.NodeAddr(); !bytes.Equal(addr, wantAddr) { 253 t.Errorf("wrong addr: got %x, want %x", addr, wantAddr) 254 } 255 want := map[Entry]interface{}{new(IP4): &wantIP, new(DiscPort): &wantDiscport} 256 for k, v := range want { 257 desc := fmt.Sprintf("loading key %q", k.ENRKey()) 258 if assert.NoError(t, r.Load(k), desc) { 259 assert.Equal(t, k, v, desc) 260 } 261 } 262 } 263 264 // TestRecordTooBig tests that records bigger than SizeLimit bytes cannot be signed. 265 func TestRecordTooBig(t *testing.T) { 266 var r Record 267 key := randomString(10) 268 269 // set a big value for random key, expect error 270 r.Set(WithEntry(key, randomString(300))) 271 if err := r.Sign(privkey); err != errTooBig { 272 t.Fatalf("expected to get errTooBig, got %#v", err) 273 } 274 275 // set an acceptable value for random key, expect no error 276 r.Set(WithEntry(key, randomString(100))) 277 require.NoError(t, r.Sign(privkey)) 278 } 279 280 // TestSignEncodeAndDecodeRandom tests encoding/decoding of records containing random key/value pairs. 281 func TestSignEncodeAndDecodeRandom(t *testing.T) { 282 var r Record 283 284 // random key/value pairs for testing 285 pairs := map[string]uint32{} 286 for i := 0; i < 10; i++ { 287 key := randomString(7) 288 value := rnd.Uint32() 289 pairs[key] = value 290 r.Set(WithEntry(key, &value)) 291 } 292 293 require.NoError(t, r.Sign(privkey)) 294 _, err := rlp.EncodeToBytes(r) 295 require.NoError(t, err) 296 297 for k, v := range pairs { 298 desc := fmt.Sprintf("key %q", k) 299 var got uint32 300 buf := WithEntry(k, &got) 301 require.NoError(t, r.Load(buf), desc) 302 require.Equal(t, v, got, desc) 303 } 304 } 305 306 func BenchmarkDecode(b *testing.B) { 307 var r Record 308 for i := 0; i < b.N; i++ { 309 rlp.DecodeBytes(pyRecord, &r) 310 } 311 b.StopTimer() 312 r.NodeAddr() 313 }