github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/enr/entries.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 //</624342658264862720> 11 12 13 package enr 14 15 import ( 16 "crypto/ecdsa" 17 "fmt" 18 "io" 19 "net" 20 21 "github.com/ethereum/go-ethereum/crypto" 22 "github.com/ethereum/go-ethereum/rlp" 23 ) 24 25 //条目由已知的节点记录条目类型实现。 26 // 27 //要定义要包含在节点记录中的新条目, 28 //创建满足此接口的Go类型。类型应该 29 //如果需要对值进行额外检查,还可以实现rlp.decoder。 30 type Entry interface { 31 ENRKey() string 32 } 33 34 type generic struct { 35 key string 36 value interface{} 37 } 38 39 func (g generic) ENRKey() string { return g.key } 40 41 func (g generic) EncodeRLP(w io.Writer) error { 42 return rlp.Encode(w, g.value) 43 } 44 45 func (g *generic) DecodeRLP(s *rlp.Stream) error { 46 return s.Decode(g.value) 47 } 48 49 //WithEntry用键名包装任何值。它可用于设置和加载任意值 50 //在记录中。值v必须由rlp支持。要在加载时使用WithEntry,值 51 //必须是指针。 52 func WithEntry(k string, v interface{}) Entry { 53 return &generic{key: k, value: v} 54 } 55 56 //tcp是“tcp”密钥,它保存节点的tcp端口。 57 type TCP uint16 58 59 func (v TCP) ENRKey() string { return "tcp" } 60 61 //udp是“udp”密钥,它保存节点的udp端口。 62 type UDP uint16 63 64 func (v UDP) ENRKey() string { return "udp" } 65 66 //ID是“ID”键,它保存标识方案的名称。 67 type ID string 68 69 const IDv4 = ID("v4") //默认标识方案 70 71 func (v ID) ENRKey() string { return "id" } 72 73 //IP是“IP”密钥,它保存节点的IP地址。 74 type IP net.IP 75 76 func (v IP) ENRKey() string { return "ip" } 77 78 //encoderlp实现rlp.encoder。 79 func (v IP) EncodeRLP(w io.Writer) error { 80 if ip4 := net.IP(v).To4(); ip4 != nil { 81 return rlp.Encode(w, ip4) 82 } 83 return rlp.Encode(w, net.IP(v)) 84 } 85 86 //decoderlp实现rlp.decoder。 87 func (v *IP) DecodeRLP(s *rlp.Stream) error { 88 if err := s.Decode((*net.IP)(v)); err != nil { 89 return err 90 } 91 if len(*v) != 4 && len(*v) != 16 { 92 return fmt.Errorf("invalid IP address, want 4 or 16 bytes: %v", *v) 93 } 94 return nil 95 } 96 97 //secp256k1是保存公钥的“secp256k1”密钥。 98 type Secp256k1 ecdsa.PublicKey 99 100 func (v Secp256k1) ENRKey() string { return "secp256k1" } 101 102 //encoderlp实现rlp.encoder。 103 func (v Secp256k1) EncodeRLP(w io.Writer) error { 104 return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v))) 105 } 106 107 //decoderlp实现rlp.decoder。 108 func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { 109 buf, err := s.Bytes() 110 if err != nil { 111 return err 112 } 113 pk, err := crypto.DecompressPubkey(buf) 114 if err != nil { 115 return err 116 } 117 *v = (Secp256k1)(*pk) 118 return nil 119 } 120 121 //keyError是一个与键相关的错误。 122 type KeyError struct { 123 Key string 124 Err error 125 } 126 127 //错误实现错误。 128 func (err *KeyError) Error() string { 129 if err.Err == errNotFound { 130 return fmt.Sprintf("missing ENR key %q", err.Key) 131 } 132 return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err) 133 } 134 135 //IsNotFound报告给定的错误是否意味着键/值对 136 //记录中缺少。 137 func IsNotFound(err error) bool { 138 kerr, ok := err.(*KeyError) 139 return ok && kerr.Err == errNotFound 140 } 141