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