github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/p2p/enr/enr.go (about)

     1  // Package enr implements Ethereum Node Records as defined in EIP-778. A node record holds
     2  // arbitrary information about a node on the peer-to-peer network.
     3  // Records contain named keys. To store and retrieve key/values in a record, use the Entry
     4  // interface.
     5  //
     6  // Records must be signed before transmitting them to another node. Decoding a record verifies
     7  // its signature. When creating a record, set the entries you want, then call Sign to add the
     8  // signature. Modifying a record invalidates the signature.
     9  //
    10  // Package enr supports the "secp256k1-keccak" identity scheme.
    11  package enr
    12  
    13  import (
    14  	"bytes"
    15  	"crypto/ecdsa"
    16  	"errors"
    17  	"fmt"
    18  	"io"
    19  	"sort"
    20  
    21  	"github.com/quickchainproject/quickchain/crypto"
    22  	"github.com/quickchainproject/quickchain/crypto/sha3"
    23  	"github.com/quickchainproject/quickchain/rlp"
    24  )
    25  
    26  const SizeLimit = 300 // maximum encoded size of a node record in bytes
    27  
    28  const ID_SECP256k1_KECCAK = ID("secp256k1-keccak") // the default identity scheme
    29  
    30  var (
    31  	errNoID           = errors.New("unknown or unspecified identity scheme")
    32  	errInvalidSig     = errors.New("invalid signature")
    33  	errNotSorted      = errors.New("record key/value pairs are not sorted by key")
    34  	errDuplicateKey   = errors.New("record contains duplicate key")
    35  	errIncompletePair = errors.New("record contains incomplete k/v pair")
    36  	errTooBig         = fmt.Errorf("record bigger than %d bytes", SizeLimit)
    37  	errEncodeUnsigned = errors.New("can't encode unsigned record")
    38  	errNotFound       = errors.New("no such key in record")
    39  )
    40  
    41  // Record represents a node record. The zero value is an empty record.
    42  type Record struct {
    43  	seq       uint64 // sequence number
    44  	signature []byte // the signature
    45  	raw       []byte // RLP encoded record
    46  	pairs     []pair // sorted list of all key/value pairs
    47  }
    48  
    49  // pair is a key/value pair in a record.
    50  type pair struct {
    51  	k string
    52  	v rlp.RawValue
    53  }
    54  
    55  // Signed reports whether the record has a valid signature.
    56  func (r *Record) Signed() bool {
    57  	return r.signature != nil
    58  }
    59  
    60  // Seq returns the sequence number.
    61  func (r *Record) Seq() uint64 {
    62  	return r.seq
    63  }
    64  
    65  // SetSeq updates the record sequence number. This invalidates any signature on the record.
    66  // Calling SetSeq is usually not required because signing the redord increments the
    67  // sequence number.
    68  func (r *Record) SetSeq(s uint64) {
    69  	r.signature = nil
    70  	r.raw = nil
    71  	r.seq = s
    72  }
    73  
    74  // Load retrieves the value of a key/value pair. The given Entry must be a pointer and will
    75  // be set to the value of the entry in the record.
    76  //
    77  // Errors returned by Load are wrapped in KeyError. You can distinguish decoding errors
    78  // from missing keys using the IsNotFound function.
    79  func (r *Record) Load(e Entry) error {
    80  	i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() })
    81  	if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() {
    82  		if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil {
    83  			return &KeyError{Key: e.ENRKey(), Err: err}
    84  		}
    85  		return nil
    86  	}
    87  	return &KeyError{Key: e.ENRKey(), Err: errNotFound}
    88  }
    89  
    90  // Set adds or updates the given entry in the record.
    91  // It panics if the value can't be encoded.
    92  func (r *Record) Set(e Entry) {
    93  	r.signature = nil
    94  	r.raw = nil
    95  	blob, err := rlp.EncodeToBytes(e)
    96  	if err != nil {
    97  		panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err))
    98  	}
    99  
   100  	i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() })
   101  
   102  	if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() {
   103  		// element is present at r.pairs[i]
   104  		r.pairs[i].v = blob
   105  		return
   106  	} else if i < len(r.pairs) {
   107  		// insert pair before i-th elem
   108  		el := pair{e.ENRKey(), blob}
   109  		r.pairs = append(r.pairs, pair{})
   110  		copy(r.pairs[i+1:], r.pairs[i:])
   111  		r.pairs[i] = el
   112  		return
   113  	}
   114  
   115  	// element should be placed at the end of r.pairs
   116  	r.pairs = append(r.pairs, pair{e.ENRKey(), blob})
   117  }
   118  
   119  // EncodeRLP implements rlp.Encoder. Encoding fails if
   120  // the record is unsigned.
   121  func (r Record) EncodeRLP(w io.Writer) error {
   122  	if !r.Signed() {
   123  		return errEncodeUnsigned
   124  	}
   125  	_, err := w.Write(r.raw)
   126  	return err
   127  }
   128  
   129  // DecodeRLP implements rlp.Decoder. Decoding verifies the signature.
   130  func (r *Record) DecodeRLP(s *rlp.Stream) error {
   131  	raw, err := s.Raw()
   132  	if err != nil {
   133  		return err
   134  	}
   135  	if len(raw) > SizeLimit {
   136  		return errTooBig
   137  	}
   138  
   139  	// Decode the RLP container.
   140  	dec := Record{raw: raw}
   141  	s = rlp.NewStream(bytes.NewReader(raw), 0)
   142  	if _, err := s.List(); err != nil {
   143  		return err
   144  	}
   145  	if err = s.Decode(&dec.signature); err != nil {
   146  		return err
   147  	}
   148  	if err = s.Decode(&dec.seq); err != nil {
   149  		return err
   150  	}
   151  	// The rest of the record contains sorted k/v pairs.
   152  	var prevkey string
   153  	for i := 0; ; i++ {
   154  		var kv pair
   155  		if err := s.Decode(&kv.k); err != nil {
   156  			if err == rlp.EOL {
   157  				break
   158  			}
   159  			return err
   160  		}
   161  		if err := s.Decode(&kv.v); err != nil {
   162  			if err == rlp.EOL {
   163  				return errIncompletePair
   164  			}
   165  			return err
   166  		}
   167  		if i > 0 {
   168  			if kv.k == prevkey {
   169  				return errDuplicateKey
   170  			}
   171  			if kv.k < prevkey {
   172  				return errNotSorted
   173  			}
   174  		}
   175  		dec.pairs = append(dec.pairs, kv)
   176  		prevkey = kv.k
   177  	}
   178  	if err := s.ListEnd(); err != nil {
   179  		return err
   180  	}
   181  
   182  	// Verify signature.
   183  	if err = dec.verifySignature(); err != nil {
   184  		return err
   185  	}
   186  	*r = dec
   187  	return nil
   188  }
   189  
   190  type s256raw []byte
   191  
   192  func (s256raw) ENRKey() string { return "secp256k1" }
   193  
   194  // NodeAddr returns the node address. The return value will be nil if the record is
   195  // unsigned.
   196  func (r *Record) NodeAddr() []byte {
   197  	var entry s256raw
   198  	if r.Load(&entry) != nil {
   199  		return nil
   200  	}
   201  	return crypto.Keccak256(entry)
   202  }
   203  
   204  // Sign signs the record with the given private key. It updates the record's identity
   205  // scheme, public key and increments the sequence number. Sign returns an error if the
   206  // encoded record is larger than the size limit.
   207  func (r *Record) Sign(privkey *ecdsa.PrivateKey) error {
   208  	r.seq = r.seq + 1
   209  	r.Set(ID_SECP256k1_KECCAK)
   210  	r.Set(Secp256k1(privkey.PublicKey))
   211  	return r.signAndEncode(privkey)
   212  }
   213  
   214  func (r *Record) appendPairs(list []interface{}) []interface{} {
   215  	list = append(list, r.seq)
   216  	for _, p := range r.pairs {
   217  		list = append(list, p.k, p.v)
   218  	}
   219  	return list
   220  }
   221  
   222  func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error {
   223  	// Put record elements into a flat list. Leave room for the signature.
   224  	list := make([]interface{}, 1, len(r.pairs)*2+2)
   225  	list = r.appendPairs(list)
   226  
   227  	// Sign the tail of the list.
   228  	h := sha3.NewKeccak256()
   229  	rlp.Encode(h, list[1:])
   230  	sig, err := crypto.Sign(h.Sum(nil), privkey)
   231  	if err != nil {
   232  		return err
   233  	}
   234  	sig = sig[:len(sig)-1] // remove v
   235  
   236  	// Put signature in front.
   237  	r.signature, list[0] = sig, sig
   238  	r.raw, err = rlp.EncodeToBytes(list)
   239  	if err != nil {
   240  		return err
   241  	}
   242  	if len(r.raw) > SizeLimit {
   243  		return errTooBig
   244  	}
   245  	return nil
   246  }
   247  
   248  func (r *Record) verifySignature() error {
   249  	// Get identity scheme, public key, signature.
   250  	var id ID
   251  	var entry s256raw
   252  	if err := r.Load(&id); err != nil {
   253  		return err
   254  	} else if id != ID_SECP256k1_KECCAK {
   255  		return errNoID
   256  	}
   257  	if err := r.Load(&entry); err != nil {
   258  		return err
   259  	} else if len(entry) != 33 {
   260  		return fmt.Errorf("invalid public key")
   261  	}
   262  
   263  	// Verify the signature.
   264  	list := make([]interface{}, 0, len(r.pairs)*2+1)
   265  	list = r.appendPairs(list)
   266  	h := sha3.NewKeccak256()
   267  	rlp.Encode(h, list)
   268  	if !crypto.VerifySignature(entry, h.Sum(nil), r.signature) {
   269  		return errInvalidSig
   270  	}
   271  	return nil
   272  }