github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/enr/enr.go (about)

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