github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/enr/enr.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 //</624342658105479168> 11 12 13 //包ENR实现EIP-778中定义的以太坊节点记录。节点记录保留 14 //有关对等网络上节点的任意信息。 15 // 16 //记录包含命名键。要在记录中存储和检索键/值,请使用条目 17 //接口。 18 // 19 //在将记录传输到另一个节点之前,必须对它们进行签名。解码记录验证 20 //它的签名。创建记录时,设置所需条目,然后调用sign添加 21 //签名。修改记录会使签名失效。 22 // 23 //ENR包支持“secp256k1 keccak”身份方案。 24 package enr 25 26 import ( 27 "bytes" 28 "errors" 29 "fmt" 30 "io" 31 "sort" 32 33 "github.com/ethereum/go-ethereum/rlp" 34 ) 35 36 const SizeLimit = 300 //节点记录的最大编码大小(字节) 37 38 var ( 39 errNoID = errors.New("unknown or unspecified identity scheme") 40 errInvalidSig = errors.New("invalid signature") 41 errNotSorted = errors.New("record key/value pairs are not sorted by key") 42 errDuplicateKey = errors.New("record contains duplicate key") 43 errIncompletePair = errors.New("record contains incomplete k/v pair") 44 errTooBig = fmt.Errorf("record bigger than %d bytes", SizeLimit) 45 errEncodeUnsigned = errors.New("can't encode unsigned record") 46 errNotFound = errors.New("no such key in record") 47 ) 48 49 //记录表示节点记录。零值是一个空记录。 50 type Record struct { 51 seq uint64 //序列号 52 signature []byte //签名 53 raw []byte //RLP编码记录 54 pairs []pair //所有键/值对的排序列表 55 } 56 57 //对是记录中的键/值对。 58 type pair struct { 59 k string 60 v rlp.RawValue 61 } 62 63 //签名报告记录是否具有有效签名。 64 func (r *Record) Signed() bool { 65 return r.signature != nil 66 } 67 68 //seq返回序列号。 69 func (r *Record) Seq() uint64 { 70 return r.seq 71 } 72 73 //setseq更新记录序列号。这将使记录上的任何签名失效。 74 //通常不需要调用setseq,因为在签名记录中设置了任何键 75 //增加序列号。 76 func (r *Record) SetSeq(s uint64) { 77 r.signature = nil 78 r.raw = nil 79 r.seq = s 80 } 81 82 //LOAD检索键/值对的值。给定的项必须是指针,并且将 83 //设置为记录中条目的值。 84 // 85 //加载返回的错误被包装在keyError中。您可以区分解码错误 86 //使用isNotFound函数来消除丢失的键。 87 func (r *Record) Load(e Entry) error { 88 i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() }) 89 if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() { 90 if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil { 91 return &KeyError{Key: e.ENRKey(), Err: err} 92 } 93 return nil 94 } 95 return &KeyError{Key: e.ENRKey(), Err: errNotFound} 96 } 97 98 //set添加或更新记录中的给定项。如果值不能 99 //编码的。如果记录已签名,则set将递增序列号并使其失效。 100 //序列号。 101 func (r *Record) Set(e Entry) { 102 blob, err := rlp.EncodeToBytes(e) 103 if err != nil { 104 panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err)) 105 } 106 r.invalidate() 107 108 pairs := make([]pair, len(r.pairs)) 109 copy(pairs, r.pairs) 110 i := sort.Search(len(pairs), func(i int) bool { return pairs[i].k >= e.ENRKey() }) 111 switch { 112 case i < len(pairs) && pairs[i].k == e.ENRKey(): 113 //元素存在于r.pairs[i] 114 pairs[i].v = blob 115 case i < len(r.pairs): 116 //在第i个元素之前插入对 117 el := pair{e.ENRKey(), blob} 118 pairs = append(pairs, pair{}) 119 copy(pairs[i+1:], pairs[i:]) 120 pairs[i] = el 121 default: 122 //元素应放置在r.pairs的末尾 123 pairs = append(pairs, pair{e.ENRKey(), blob}) 124 } 125 r.pairs = pairs 126 } 127 128 func (r *Record) invalidate() { 129 if r.signature == nil { 130 r.seq++ 131 } 132 r.signature = nil 133 r.raw = nil 134 } 135 136 //encoderlp实现rlp.encoder。编码失败,如果 137 //记录未签名。 138 func (r Record) EncodeRLP(w io.Writer) error { 139 if !r.Signed() { 140 return errEncodeUnsigned 141 } 142 _, err := w.Write(r.raw) 143 return err 144 } 145 146 //decoderlp实现rlp.decoder。解码验证签名。 147 func (r *Record) DecodeRLP(s *rlp.Stream) error { 148 raw, err := s.Raw() 149 if err != nil { 150 return err 151 } 152 if len(raw) > SizeLimit { 153 return errTooBig 154 } 155 156 //解码RLP容器。 157 dec := Record{raw: raw} 158 s = rlp.NewStream(bytes.NewReader(raw), 0) 159 if _, err := s.List(); err != nil { 160 return err 161 } 162 if err = s.Decode(&dec.signature); err != nil { 163 return err 164 } 165 if err = s.Decode(&dec.seq); err != nil { 166 return err 167 } 168 //记录的其余部分包含已排序的k/v对。 169 var prevkey string 170 for i := 0; ; i++ { 171 var kv pair 172 if err := s.Decode(&kv.k); err != nil { 173 if err == rlp.EOL { 174 break 175 } 176 return err 177 } 178 if err := s.Decode(&kv.v); err != nil { 179 if err == rlp.EOL { 180 return errIncompletePair 181 } 182 return err 183 } 184 if i > 0 { 185 if kv.k == prevkey { 186 return errDuplicateKey 187 } 188 if kv.k < prevkey { 189 return errNotSorted 190 } 191 } 192 dec.pairs = append(dec.pairs, kv) 193 prevkey = kv.k 194 } 195 if err := s.ListEnd(); err != nil { 196 return err 197 } 198 199 _, scheme := dec.idScheme() 200 if scheme == nil { 201 return errNoID 202 } 203 if err := scheme.Verify(&dec, dec.signature); err != nil { 204 return err 205 } 206 *r = dec 207 return nil 208 } 209 210 //nodeadr返回节点地址。如果记录是 211 //未签名或使用未知的标识方案。 212 func (r *Record) NodeAddr() []byte { 213 _, scheme := r.idScheme() 214 if scheme == nil { 215 return nil 216 } 217 return scheme.NodeAddr(r) 218 } 219 220 //setsig设置记录签名。如果编码的记录较大,则返回错误 221 //大于大小限制或根据传递的方案签名无效。 222 func (r *Record) SetSig(idscheme string, sig []byte) error { 223 //检查“id”是否已设置并与给定方案匹配。这种恐慌是因为 224 //这里的不一致始终是签名函数调用中的实现错误 225 //这种方法。 226 id, s := r.idScheme() 227 if s == nil { 228 panic(errNoID) 229 } 230 if id != idscheme { 231 panic(fmt.Errorf("identity scheme mismatch in Sign: record has %s, want %s", id, idscheme)) 232 } 233 234 //对照方案进行验证。 235 if err := s.Verify(r, sig); err != nil { 236 return err 237 } 238 raw, err := r.encode(sig) 239 if err != nil { 240 return err 241 } 242 r.signature, r.raw = sig, raw 243 return nil 244 } 245 246 //AppendElements将序列号和条目追加到给定切片。 247 func (r *Record) AppendElements(list []interface{}) []interface{} { 248 list = append(list, r.seq) 249 for _, p := range r.pairs { 250 list = append(list, p.k, p.v) 251 } 252 return list 253 } 254 255 func (r *Record) encode(sig []byte) (raw []byte, err error) { 256 list := make([]interface{}, 1, 2*len(r.pairs)+1) 257 list[0] = sig 258 list = r.AppendElements(list) 259 if raw, err = rlp.EncodeToBytes(list); err != nil { 260 return nil, err 261 } 262 if len(raw) > SizeLimit { 263 return nil, errTooBig 264 } 265 return raw, nil 266 } 267 268 func (r *Record) idScheme() (string, IdentityScheme) { 269 var id ID 270 if err := r.Load(&id); err != nil { 271 return "", nil 272 } 273 return string(id), FindIdentityScheme(string(id)) 274 } 275