github.com/turingchain2020/turingchain@v1.1.21/common/address/address.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package address 计算地址相关的函数
     6  package address
     7  
     8  import (
     9  	"bytes"
    10  	"crypto/sha256"
    11  	"encoding/hex"
    12  	"errors"
    13  	"unsafe"
    14  
    15  	"github.com/turingchain2020/turingchain/common"
    16  	"github.com/decred/base58"
    17  	lru "github.com/hashicorp/golang-lru"
    18  )
    19  
    20  var addrSeed = []byte("address seed bytes for public key")
    21  var addressCache *lru.Cache
    22  var pubkey2AddrCache *lru.Cache
    23  var checkAddressCache *lru.Cache
    24  var multisignCache *lru.Cache
    25  var multiCheckAddressCache *lru.Cache
    26  var execPubKeyCache *lru.Cache
    27  
    28  // ErrCheckVersion :
    29  var ErrCheckVersion = errors.New("check version error")
    30  
    31  //ErrCheckChecksum :
    32  var ErrCheckChecksum = errors.New("Address Checksum error")
    33  
    34  //ErrAddressChecksum :
    35  var ErrAddressChecksum = errors.New("address checksum error")
    36  
    37  //MaxExecNameLength 执行器名最大长度
    38  const MaxExecNameLength = 100
    39  
    40  //NormalVer 普通地址的版本号
    41  var NormalVer byte
    42  
    43  //MultiSignVer 多重签名地址的版本号
    44  var MultiSignVer byte = 5
    45  
    46  func init() {
    47  	var err error
    48  	multisignCache, err = lru.New(10240)
    49  	if err != nil {
    50  		panic(err)
    51  	}
    52  	pubkey2AddrCache, err = lru.New(10240)
    53  	if err != nil {
    54  		panic(err)
    55  	}
    56  	addressCache, err = lru.New(10240)
    57  	if err != nil {
    58  		panic(err)
    59  	}
    60  	checkAddressCache, err = lru.New(10240)
    61  	if err != nil {
    62  		panic(err)
    63  	}
    64  	multiCheckAddressCache, err = lru.New(10240)
    65  	if err != nil {
    66  		panic(err)
    67  	}
    68  	execPubKeyCache, err = lru.New(10240)
    69  	if err != nil {
    70  		panic(err)
    71  	}
    72  }
    73  
    74  //ExecAddress 计算量有点大,做一次cache
    75  func ExecAddress(name string) string {
    76  	if value, ok := addressCache.Get(name); ok {
    77  		return value.(string)
    78  	}
    79  	addr := GetExecAddress(name)
    80  	addrstr := addr.String()
    81  	addressCache.Add(name, addrstr)
    82  	return addrstr
    83  }
    84  
    85  //MultiSignAddress create a multi sign address
    86  func MultiSignAddress(pubkey []byte) string {
    87  	skey := *(*string)(unsafe.Pointer(&pubkey))
    88  	if value, ok := multisignCache.Get(skey); ok {
    89  		return value.(string)
    90  	}
    91  	addr := HashToAddress(MultiSignVer, pubkey)
    92  	addrstr := addr.String()
    93  	multisignCache.Add(string(pubkey), addrstr)
    94  	return addrstr
    95  }
    96  
    97  //ExecPubKey 计算公钥
    98  func ExecPubKey(name string) []byte {
    99  	if len(name) > MaxExecNameLength {
   100  		panic("name too long")
   101  	}
   102  	if value, ok := execPubKeyCache.Get(name); ok {
   103  		return value.([]byte)
   104  	}
   105  	var bname [200]byte
   106  	buf := append(bname[:0], addrSeed...)
   107  	buf = append(buf, []byte(name)...)
   108  	hash := common.Sha2Sum(buf)
   109  	execPubKeyCache.Add(name, hash)
   110  	return hash[:]
   111  }
   112  
   113  //GetExecAddress 获取地址
   114  func GetExecAddress(name string) *Address {
   115  	hash := ExecPubKey(name)
   116  	addr := PubKeyToAddress(hash[:])
   117  	return addr
   118  }
   119  
   120  //PubKeyToAddress 公钥转为地址
   121  func PubKeyToAddress(in []byte) *Address {
   122  	return HashToAddress(NormalVer, in)
   123  }
   124  
   125  //PubKeyToAddr 公钥转为地址
   126  func PubKeyToAddr(in []byte) string {
   127  	instr := *(*string)(unsafe.Pointer(&in))
   128  	if value, ok := pubkey2AddrCache.Get(instr); ok {
   129  		return value.(string)
   130  	}
   131  	addr := HashToAddress(NormalVer, in).String()
   132  	pubkey2AddrCache.Add(string(in), addr)
   133  	return addr
   134  }
   135  
   136  //HashToAddress hash32 to address
   137  func HashToAddress(version byte, in []byte) *Address {
   138  	a := new(Address)
   139  	a.Pubkey = make([]byte, len(in))
   140  	copy(a.Pubkey[:], in[:])
   141  	a.Version = version
   142  	a.SetBytes(common.Rimp160(in))
   143  	return a
   144  }
   145  
   146  func checksum(input []byte) (cksum [4]byte) {
   147  	h := sha256.Sum256(input)
   148  	h2 := sha256.Sum256(h[:])
   149  	copy(cksum[:], h2[:4])
   150  	return
   151  }
   152  
   153  func checkAddress(ver byte, addr string) (e error) {
   154  
   155  	dec := base58.Decode(addr)
   156  	if dec == nil {
   157  		e = errors.New("Cannot decode b58 string '" + addr + "'")
   158  		checkAddressCache.Add(addr, e)
   159  		return
   160  	}
   161  	if len(dec) < 25 {
   162  		e = errors.New("Address too short " + hex.EncodeToString(dec))
   163  		checkAddressCache.Add(addr, e)
   164  		return
   165  	}
   166  	//version 的错误优先
   167  	if dec[0] != ver {
   168  		e = ErrCheckVersion
   169  		return
   170  	}
   171  	//需要兼容以前的错误(以前的错误,是一种特殊的情况)
   172  	if len(dec) == 25 {
   173  		sh := common.Sha2Sum(dec[0:21])
   174  		if !bytes.Equal(sh[:4], dec[21:25]) {
   175  			e = ErrCheckChecksum
   176  			return
   177  		}
   178  	}
   179  	var cksum [4]byte
   180  	copy(cksum[:], dec[len(dec)-4:])
   181  	//新的错误: 这个错误用一种新的错误标记
   182  	if checksum(dec[:len(dec)-4]) != cksum {
   183  		e = ErrAddressChecksum
   184  	}
   185  	return e
   186  }
   187  
   188  //CheckMultiSignAddress 检查多重签名地址的有效性
   189  func CheckMultiSignAddress(addr string) (e error) {
   190  	if value, ok := multiCheckAddressCache.Get(addr); ok {
   191  		if value == nil {
   192  			return nil
   193  		}
   194  		return value.(error)
   195  	}
   196  	e = checkAddress(MultiSignVer, addr)
   197  	multiCheckAddressCache.Add(addr, e)
   198  	return
   199  }
   200  
   201  //CheckAddress 检查地址
   202  func CheckAddress(addr string) (e error) {
   203  	if value, ok := checkAddressCache.Get(addr); ok {
   204  		if value == nil {
   205  			return nil
   206  		}
   207  		return value.(error)
   208  	}
   209  	e = checkAddress(NormalVer, addr)
   210  	checkAddressCache.Add(addr, e)
   211  	return
   212  }
   213  
   214  //NewAddrFromString new 地址
   215  func NewAddrFromString(hs string) (a *Address, e error) {
   216  	dec := base58.Decode(hs)
   217  	if dec == nil {
   218  		e = errors.New("Cannot decode b58 string '" + hs + "'")
   219  		return
   220  	}
   221  	if len(dec) < 25 {
   222  		e = errors.New("Address too short " + hex.EncodeToString(dec))
   223  		return
   224  	}
   225  	if len(dec) == 25 {
   226  		sh := common.Sha2Sum(dec[0:21])
   227  		if !bytes.Equal(sh[:4], dec[21:25]) {
   228  			e = ErrCheckChecksum
   229  		} else {
   230  			a = new(Address)
   231  			a.Version = dec[0]
   232  			copy(a.Hash160[:], dec[1:21])
   233  			a.Checksum = make([]byte, 4)
   234  			copy(a.Checksum, dec[21:25])
   235  			a.Enc58str = hs
   236  		}
   237  	}
   238  	return
   239  }
   240  
   241  //Address 地址
   242  type Address struct {
   243  	Version  byte
   244  	Hash160  [20]byte // For a stealth address: it's HASH160
   245  	Checksum []byte   // Unused for a stealth address
   246  	Pubkey   []byte   // Unused for a stealth address
   247  	Enc58str string
   248  }
   249  
   250  //SetBytes 设置地址的bytes
   251  func (a *Address) SetBytes(b []byte) {
   252  	copy(a.Hash160[:], b)
   253  }
   254  
   255  func (a *Address) String() string {
   256  	if a.Enc58str == "" {
   257  		var ad [25]byte
   258  		ad[0] = a.Version
   259  		copy(ad[1:21], a.Hash160[:])
   260  		if a.Checksum == nil {
   261  			sh := common.Sha2Sum(ad[0:21])
   262  			a.Checksum = make([]byte, 4)
   263  			copy(a.Checksum, sh[:4])
   264  		}
   265  		copy(ad[21:25], a.Checksum[:])
   266  		a.Enc58str = base58.Encode(ad[:])
   267  	}
   268  	return a.Enc58str
   269  }
   270  
   271  //SetNormalAddrVer 根据配置设置生成普通地址的version版本号,默认是0
   272  func SetNormalAddrVer(ver byte) {
   273  	if MultiSignVer == ver {
   274  		panic("the version of the normal address conflicts with the version of the multi-signature address!")
   275  
   276  	}
   277  	NormalVer = ver
   278  }