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