github.com/annchain/OG@v0.0.9/p2p/enr/enr.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package enr implements Ethereum Node Records as defined in EIP-778. A node record holds
    18  // arbitrary information about a node on the peer-to-peer network. Node information is
    19  // stored in key/value Pairs. To store and retrieve key/values in a record, use the Entry
    20  // interface.
    21  //
    22  // Signature Handling
    23  //
    24  // Records must be signed before transmitting them to another node.
    25  //
    26  // Decoding a record doesn't check its Signature. Code working with records from an
    27  // untrusted source must always verify two things: that the record uses an identity scheme
    28  // deemed secure, and that the Signature is valid according to the declared scheme.
    29  //
    30  // When creating a record, set the entries you want and use a signing function provided by
    31  // the identity scheme to add the Signature. Modifying a record invalidates the Signature.
    32  //
    33  // Package enr supports the "secp256k1-keccak" identity scheme.
    34  package enr
    35  
    36  import (
    37  	"bytes"
    38  	"errors"
    39  	"fmt"
    40  	"github.com/annchain/OG/types/msg"
    41  	"sort"
    42  )
    43  
    44  //go:generate msgp
    45  const SizeLimit = 300 // maximum encoded size of a node record in bytes
    46  
    47  var (
    48  	ErrInvalidSig     = errors.New("invalid Signature on node record")
    49  	errNotSorted      = errors.New("record key/value Pairs are not sorted by key")
    50  	errDuplicateKey   = errors.New("record contains duplicate key")
    51  	errIncompletePair = errors.New("record contains incomplete k/v Pair")
    52  	errTooBig         = fmt.Errorf("record bigger than %d bytes", SizeLimit)
    53  	errEncodeUnsigned = errors.New("can't encode unsigned record")
    54  	errNotFound       = errors.New("no such key in record")
    55  )
    56  
    57  // Pair is a key/value Pair in a record.
    58  //msgp:tuple Pair
    59  type Pair struct {
    60  	K string
    61  	//v rlp.RawValue
    62  	V []byte
    63  }
    64  
    65  // Record represents a node record. The zero value is an empty record.
    66  //msgp:tuple Record
    67  type Record struct {
    68  	Seq       uint64 // sequence number
    69  	Signature []byte // the Signature
    70  	Pairs     []Pair // sorted list of all key/value Pairs
    71  	raw       []byte // msgp encoded record
    72  }
    73  
    74  // Seq returns the sequence number.
    75  func (r *Record) GetSeq() uint64 {
    76  	return r.Seq
    77  }
    78  
    79  // SetSeq updates the record sequence number. This invalidates any Signature on the record.
    80  // Calling SetSeq is usually not required because setting any key in a signed record
    81  // increments the sequence number.
    82  func (r *Record) SetSeq(s uint64) {
    83  	r.Signature = nil
    84  	r.raw = nil
    85  	r.Seq = s
    86  }
    87  
    88  // Load retrieves the value of a key/value Pair. The given Entry must be a pointer and will
    89  // be set to the value of the entry in the record.
    90  //
    91  // Errors returned by Load are wrapped in KeyError. You can distinguish decoding errors
    92  // from missing keys using the IsNotFound function.
    93  func (r *Record) Load(e Entry) error {
    94  	i := sort.Search(len(r.Pairs), func(i int) bool { return r.Pairs[i].K >= e.ENRKey() })
    95  	if i < len(r.Pairs) && r.Pairs[i].K == e.ENRKey() {
    96  		if _, err := e.UnmarshalMsg(r.Pairs[i].V); err != nil {
    97  			//if err := rlp.DecodeBytes(r.Pairs[i].V, e); err != nil {
    98  			return &KeyError{Key: e.ENRKey(), Err: err}
    99  		}
   100  		return nil
   101  	}
   102  	return &KeyError{Key: e.ENRKey(), Err: errNotFound}
   103  }
   104  
   105  // Set adds or updates the given entry in the record. It panics if the value can't be
   106  // encoded. If the record is signed, Set increments the sequence number and invalidates
   107  // the sequence number.
   108  func (r *Record) Set(e Entry) {
   109  	blob, err := e.MarshalMsg(nil)
   110  	if err != nil {
   111  		panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err))
   112  	}
   113  	r.invalidate()
   114  
   115  	Pairs := make([]Pair, len(r.Pairs))
   116  	copy(Pairs, r.Pairs)
   117  	i := sort.Search(len(Pairs), func(i int) bool { return Pairs[i].K >= e.ENRKey() })
   118  	switch {
   119  	case i < len(Pairs) && Pairs[i].K == e.ENRKey():
   120  		// element is present at r.Pairs[i]
   121  		Pairs[i].V = blob
   122  	case i < len(r.Pairs):
   123  		// insert Pair before i-th elem
   124  		el := Pair{e.ENRKey(), blob}
   125  		Pairs = append(Pairs, Pair{})
   126  		copy(Pairs[i+1:], Pairs[i:])
   127  		Pairs[i] = el
   128  	default:
   129  		// element should be placed at the end of r.Pairs
   130  		Pairs = append(Pairs, Pair{e.ENRKey(), blob})
   131  	}
   132  	r.Pairs = Pairs
   133  }
   134  
   135  func (r *Record) invalidate() {
   136  	if r.Signature != nil {
   137  		r.Seq++
   138  	}
   139  	r.Signature = nil
   140  	r.raw = nil
   141  }
   142  
   143  // EncodeRLP implements rlp.Encoder. Encoding fails if
   144  // the record is unsigned.
   145  func (r Record) Encode(b []byte) ([]byte, error) {
   146  	if r.Signature == nil {
   147  		return nil, errEncodeUnsigned
   148  	}
   149  	return r.raw, nil
   150  }
   151  
   152  // DecodeRLP implements rlp.Decoder. Decoding verifies the Signature.
   153  func (r *Record) Decode(b []byte) ([]byte, error) {
   154  	dec, err := decodeRecord(b)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	*r = dec
   159  	r.raw = b
   160  	return nil, nil
   161  }
   162  
   163  func decodeRecord(b []byte) (dec Record, err error) {
   164  	if len(b) > SizeLimit {
   165  		return dec, errTooBig
   166  	}
   167  	if _, err = dec.UnmarshalMsg(b); err != nil {
   168  		return dec, err
   169  	}
   170  	// The rest of the record contains sorted k/v Pairs.
   171  	var prevkey string
   172  	for i := 0; i < len(dec.Pairs); i++ {
   173  		kv := dec.Pairs[i]
   174  		if i > 0 {
   175  			if kv.K == prevkey {
   176  				return dec, errDuplicateKey
   177  			}
   178  			if kv.K < prevkey {
   179  				return dec, errNotSorted
   180  			}
   181  		}
   182  		prevkey = kv.K
   183  	}
   184  	return dec, err
   185  }
   186  
   187  // IdentityScheme returns the name of the identity scheme in the record.
   188  func (r *Record) IdentityScheme() string {
   189  	var id ID
   190  	r.Load(&id)
   191  	return string(id)
   192  }
   193  
   194  // VerifySignature checks whether the record is signed using the given identity scheme.
   195  func (r *Record) VerifySignature(s IdentityScheme) error {
   196  	return s.Verify(r, r.Signature)
   197  }
   198  
   199  // SetSig sets the record Signature. It returns an error if the encoded record is larger
   200  // than the size limit or if the Signature is invalid according to the passed scheme.
   201  //
   202  // You can also use SetSig to remove the Signature explicitly by passing a nil scheme
   203  // and Signature.
   204  //
   205  // SetSig panics when either the scheme or the Signature (but not both) are nil.
   206  func (r *Record) SetSig(s IdentityScheme, sig []byte) error {
   207  	switch {
   208  	// Prevent storing invalid data.
   209  	case s == nil && sig != nil:
   210  		panic("enr: invalid call to SetSig with non-nil Signature but nil scheme")
   211  	case s != nil && sig == nil:
   212  		panic("enr: invalid call to SetSig with nil Signature but non-nil scheme")
   213  	// Verify if we have a scheme.
   214  	case s != nil:
   215  		if err := s.Verify(r, sig); err != nil {
   216  			return err
   217  		}
   218  		r.Signature = sig
   219  		raw, err := r.MarshalMsg(nil)
   220  		if err == nil {
   221  			if len(raw) > SizeLimit {
   222  				err = errTooBig
   223  			}
   224  		}
   225  		if err != nil {
   226  			r.Signature = nil
   227  			return err
   228  		}
   229  		r.Signature, r.raw = sig, raw
   230  	// Reset otherwise.
   231  	default:
   232  		r.Signature, r.raw = nil, nil
   233  	}
   234  	return nil
   235  }
   236  
   237  // AppendElements appends the sequence number and entries to the given slice.
   238  func (r *Record) AppendElements(list []msg.MsgpMember) []msg.MsgpMember {
   239  	seq := msg.Uint64(r.Seq)
   240  	list = append(list, &seq)
   241  	for _, p := range r.Pairs {
   242  		k := msg.String(p.K)
   243  		v := msg.Bytes(p.V)
   244  		list = append(list, &k, &v)
   245  	}
   246  	return list
   247  }
   248  
   249  /*
   250  func (r *Record) encode(sig []byte) (raw []byte, err error) {
   251  	list := make([]msg.MsgpMember, 1, 2*len(r.Pairs)+1)
   252  	bs := msg.KeyBytes(sig)
   253  	list[0] = &bs
   254  	msg := msg.Messages(r.AppendElements(list))
   255  	if raw,err = msg.MarshalMsg(nil);err!=nil{
   256  	//if raw, err = rlp.EncodeToBytes(list); err != nil {
   257  		return nil, err
   258  	}
   259  	if len(raw) > SizeLimit {
   260  		return nil, errTooBig
   261  	}
   262  	return raw, nil
   263  }
   264  
   265  */
   266  
   267  func (r Record) Equal(r1 Record) (ok bool, reason error) {
   268  	if r.Seq != r1.Seq {
   269  		return false, fmt.Errorf("seq not equal")
   270  	}
   271  	if len(r.Pairs) != len(r1.Pairs) {
   272  		return false, fmt.Errorf("pairs len not equal")
   273  	}
   274  	for i, p := range r.Pairs {
   275  		if p.K != r1.Pairs[i].K {
   276  			return false, fmt.Errorf("pair key is diff")
   277  		}
   278  		if !bytes.Equal(p.V, r.Pairs[i].V) {
   279  			return false, fmt.Errorf("pair val is diff")
   280  		}
   281  	}
   282  
   283  	if !bytes.Equal(r.Signature, r1.Signature) {
   284  		return false, fmt.Errorf("signatrue not equal")
   285  	}
   286  	if !bytes.Equal(r.raw, r1.raw) {
   287  		return false, fmt.Errorf("raw not equal")
   288  	}
   289  	return true, nil
   290  }