github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/enr/idscheme.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  //版权所有2018 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  package enr
    26  
    27  import (
    28  	"crypto/ecdsa"
    29  	"fmt"
    30  	"sync"
    31  
    32  	"github.com/ethereum/go-ethereum/common/math"
    33  	"github.com/ethereum/go-ethereum/crypto"
    34  	"github.com/ethereum/go-ethereum/crypto/sha3"
    35  	"github.com/ethereum/go-ethereum/rlp"
    36  )
    37  
    38  //已知身份方案的注册表。
    39  var schemes sync.Map
    40  
    41  //标识方案能够验证记录签名和
    42  //派生节点地址。
    43  type IdentityScheme interface {
    44  	Verify(r *Record, sig []byte) error
    45  	NodeAddr(r *Record) []byte
    46  }
    47  
    48  //RegisterIdentityScheme向全局注册表添加标识方案。
    49  func RegisterIdentityScheme(name string, scheme IdentityScheme) {
    50  	if _, loaded := schemes.LoadOrStore(name, scheme); loaded {
    51  		panic("identity scheme " + name + " already registered")
    52  	}
    53  }
    54  
    55  //findidentityScheme将名称解析为全局注册表中的标识方案。
    56  func FindIdentityScheme(name string) IdentityScheme {
    57  	s, ok := schemes.Load(name)
    58  	if !ok {
    59  		return nil
    60  	}
    61  	return s.(IdentityScheme)
    62  }
    63  
    64  //v4id是“v4”标识方案。
    65  type v4ID struct{}
    66  
    67  func init() {
    68  	RegisterIdentityScheme("v4", v4ID{})
    69  }
    70  
    71  //signv4使用v4方案对记录进行签名。
    72  func SignV4(r *Record, privkey *ecdsa.PrivateKey) error {
    73  //复制r以避免在签名失败时修改它。
    74  	cpy := *r
    75  	cpy.Set(ID("v4"))
    76  	cpy.Set(Secp256k1(privkey.PublicKey))
    77  
    78  	h := sha3.NewKeccak256()
    79  	rlp.Encode(h, cpy.AppendElements(nil))
    80  	sig, err := crypto.Sign(h.Sum(nil), privkey)
    81  	if err != nil {
    82  		return err
    83  	}
    84  sig = sig[:len(sig)-1] //移除V
    85  	if err = cpy.SetSig("v4", sig); err == nil {
    86  		*r = cpy
    87  	}
    88  	return err
    89  }
    90  
    91  //s256raw是一个未分析的secp256k1公钥条目。
    92  type s256raw []byte
    93  
    94  func (s256raw) ENRKey() string { return "secp256k1" }
    95  
    96  func (v4ID) Verify(r *Record, sig []byte) error {
    97  	var entry s256raw
    98  	if err := r.Load(&entry); err != nil {
    99  		return err
   100  	} else if len(entry) != 33 {
   101  		return fmt.Errorf("invalid public key")
   102  	}
   103  
   104  	h := sha3.NewKeccak256()
   105  	rlp.Encode(h, r.AppendElements(nil))
   106  	if !crypto.VerifySignature(entry, h.Sum(nil), sig) {
   107  		return errInvalidSig
   108  	}
   109  	return nil
   110  }
   111  
   112  func (v4ID) NodeAddr(r *Record) []byte {
   113  	var pubkey Secp256k1
   114  	err := r.Load(&pubkey)
   115  	if err != nil {
   116  		return nil
   117  	}
   118  	buf := make([]byte, 64)
   119  	math.ReadBits(pubkey.X, buf[:32])
   120  	math.ReadBits(pubkey.Y, buf[32:])
   121  	return crypto.Keccak256(buf)
   122  }