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