github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/addrbook.go (about)

     1  package dht
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"fmt"
     8  	"os"
     9  	"sync"
    10  
    11  	"github.com/turingchain2020/turingchain/common/db"
    12  	p2pty "github.com/turingchain2020/turingchain/system/p2p/dht/types"
    13  	"github.com/turingchain2020/turingchain/types"
    14  	"github.com/turingchain2020/turingchain/wallet/bipwallet"
    15  	"github.com/libp2p/go-libp2p-core/crypto"
    16  	"github.com/libp2p/go-libp2p-core/peer"
    17  )
    18  
    19  const (
    20  	addrkeyTag              = "mutiaddrs"
    21  	privKeyTag              = "privkey"
    22  	privKeyCompressBytesLen = 32
    23  )
    24  
    25  // AddrBook peer address manager
    26  type AddrBook struct {
    27  	mtx     sync.Mutex
    28  	cfg     *types.P2P
    29  	privkey string
    30  	pubkey  string
    31  	bookDb  db.DB
    32  }
    33  
    34  // NewAddrBook new addr book
    35  func NewAddrBook(cfg *types.P2P) *AddrBook {
    36  	a := &AddrBook{
    37  		cfg: cfg,
    38  	}
    39  	dbPath := cfg.DbPath + "/" + p2pty.DHTTypeName
    40  	a.bookDb = db.NewDB("addrBook", a.cfg.Driver, dbPath, a.cfg.DbCache)
    41  	a.loadDb()
    42  	return a
    43  
    44  }
    45  
    46  // AddrsInfo get addr infos
    47  func (a *AddrBook) AddrsInfo() []peer.AddrInfo {
    48  	var addrsInfo []peer.AddrInfo
    49  	if a.bookDb == nil {
    50  		return addrsInfo
    51  	}
    52  
    53  	addrsInfoBs, err := a.bookDb.Get([]byte(addrkeyTag))
    54  	if err != nil {
    55  		log.Error("LoadAddrsInfo", " Get addrkeyTag", err.Error())
    56  		return addrsInfo
    57  	}
    58  
    59  	err = json.Unmarshal(addrsInfoBs, &addrsInfo)
    60  	if err != nil {
    61  		log.Error("LoadAddrsInfo", "Unmarshal err", err.Error())
    62  		return nil
    63  	}
    64  
    65  	return addrsInfo
    66  }
    67  
    68  func (a *AddrBook) loadDb() bool {
    69  
    70  	privkey, err := a.bookDb.Get([]byte(privKeyTag))
    71  	if len(privkey) != 0 && err == nil {
    72  		pubkey, err := GenPubkey(string(privkey))
    73  		if err != nil {
    74  			log.Error("genPubkey", "err", err.Error())
    75  			panic(err)
    76  		}
    77  		a.setKey(string(privkey), pubkey)
    78  		return true
    79  	}
    80  
    81  	return false
    82  
    83  }
    84  
    85  //Randkey Rand keypair
    86  func (a *AddrBook) Randkey() crypto.PrivKey {
    87  	a.initKey()
    88  	return a.GetPrivkey()
    89  }
    90  func (a *AddrBook) initKey() {
    91  
    92  	priv, pub, err := GenPrivPubkey()
    93  	if err != nil {
    94  		var maxRetry = 10
    95  		for i := 0; i < maxRetry; i++ {
    96  			priv, pub, err = GenPrivPubkey()
    97  			if err == nil {
    98  				break
    99  			}
   100  			if i == maxRetry-1 && err != nil {
   101  				panic(err.Error())
   102  			}
   103  		}
   104  
   105  	}
   106  
   107  	a.saveKey(hex.EncodeToString(priv), hex.EncodeToString(pub))
   108  }
   109  
   110  func (a *AddrBook) saveKey(priv, pub string) {
   111  	a.setKey(priv, pub)
   112  	err := a.bookDb.Set([]byte(privKeyTag), []byte(priv))
   113  	if err != nil {
   114  		panic(err)
   115  	}
   116  }
   117  
   118  // GetPrivkey get private key
   119  func (a *AddrBook) GetPrivkey() crypto.PrivKey {
   120  	a.mtx.Lock()
   121  	defer a.mtx.Unlock()
   122  	if a.privkey == "" {
   123  		return nil
   124  	}
   125  	keybytes, err := hex.DecodeString(a.privkey)
   126  	if err != nil {
   127  		log.Error("GetPrivkey", "DecodeString Error", err.Error())
   128  		return nil
   129  	}
   130  	log.Debug("GetPrivkey", "privsize", len(keybytes))
   131  
   132  	privkey, err := crypto.UnmarshalSecp256k1PrivateKey(keybytes)
   133  	if err != nil {
   134  		privkey, err = crypto.UnmarshalPrivateKey(keybytes)
   135  		if err != nil {
   136  			log.Error("GetPrivkey", "UnmarshalPrivateKey", err.Error())
   137  			return nil
   138  		}
   139  
   140  	}
   141  
   142  	return privkey
   143  }
   144  
   145  // GetPrivPubKey return privkey and pubkey
   146  func (a *AddrBook) GetPrivPubKey() (string, string) {
   147  	a.mtx.Lock()
   148  	defer a.mtx.Unlock()
   149  	return a.privkey, a.pubkey
   150  }
   151  
   152  func (a *AddrBook) setKey(privkey, pubkey string) {
   153  	a.mtx.Lock()
   154  	defer a.mtx.Unlock()
   155  	a.privkey = privkey
   156  	a.pubkey = pubkey
   157  
   158  }
   159  
   160  // SaveAddr save addr
   161  func (a *AddrBook) SaveAddr(addrinfos []peer.AddrInfo) error {
   162  
   163  	jsonBytes, err := json.Marshal(addrinfos)
   164  	if err != nil {
   165  		log.Error("Failed to save AddrBook to file", "err", err)
   166  		return err
   167  	}
   168  	log.Debug("saveToDb", "addrs", string(jsonBytes))
   169  	return a.bookDb.Set([]byte(addrkeyTag), jsonBytes)
   170  
   171  }
   172  
   173  // StoreHostID store host id into file
   174  func (a *AddrBook) StoreHostID(id peer.ID, path string) {
   175  	dbPath := path + "/" + p2pty.DHTTypeName
   176  	if os.MkdirAll(dbPath, 0755) != nil {
   177  		return
   178  	}
   179  
   180  	pf, err := os.Create(fmt.Sprintf("%v/%v", dbPath, id.Pretty()))
   181  	if err != nil {
   182  		log.Error("StoreHostId", "Create file", err.Error())
   183  		return
   184  	}
   185  
   186  	defer pf.Close()
   187  	var peerInfo = make(map[string]interface{})
   188  	var info = make(map[string]interface{})
   189  	pubkey, err := PeerIDToPubkey(id.Pretty())
   190  	if err == nil {
   191  		info["pubkey"] = pubkey
   192  		pbytes, _ := hex.DecodeString(pubkey)
   193  		addr, _ := bipwallet.PubToAddress(pbytes)
   194  		info["address"] = addr
   195  	}
   196  
   197  	peerInfo[id.Pretty()] = info
   198  	bs, err := json.MarshalIndent(peerInfo, "", "\t")
   199  	if err != nil {
   200  		log.Error("StoreHostId", "MarshalIndent", err.Error())
   201  		return
   202  	}
   203  	_, err = pf.Write(bs)
   204  	if err != nil {
   205  		return
   206  	}
   207  
   208  }
   209  
   210  // GenPrivPubkey return key and pubkey in bytes
   211  func GenPrivPubkey() ([]byte, []byte, error) {
   212  	priv, pub, err := crypto.GenerateSecp256k1Key(rand.Reader)
   213  	//priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.Secp256k1, 2048, rand.Reader)
   214  	if err != nil {
   215  		return nil, nil, err
   216  	}
   217  
   218  	privkey, err := priv.Raw()
   219  	if err != nil {
   220  		return nil, nil, err
   221  
   222  	}
   223  	pubkey, err := pub.Raw()
   224  	if err != nil {
   225  		return nil, nil, err
   226  
   227  	}
   228  	return privkey, pubkey, nil
   229  
   230  }
   231  
   232  // GenPubkey generate public key
   233  func GenPubkey(key string) (string, error) {
   234  	keybytes, err := hex.DecodeString(key)
   235  	if err != nil {
   236  		log.Error("DecodeString Error", "Error", err.Error())
   237  		return "", err
   238  	}
   239  
   240  	log.Info("GenPubkey", "key size", len(keybytes))
   241  	privkey, err := crypto.UnmarshalSecp256k1PrivateKey(keybytes)
   242  	if err != nil {
   243  
   244  		privkey, err = crypto.UnmarshalPrivateKey(keybytes)
   245  		if err != nil {
   246  			//切换
   247  			log.Error("genPubkey", "UnmarshalPrivateKey", err.Error())
   248  			return "", err
   249  		}
   250  	}
   251  
   252  	pubkey, err := privkey.GetPublic().Raw()
   253  	if err != nil {
   254  		log.Error("genPubkey", "GetPubkey", err.Error())
   255  		return "", err
   256  	}
   257  	return hex.EncodeToString(pubkey), nil
   258  
   259  }
   260  
   261  //PeerIDToPubkey 提供节点ID转换为pubkey,进而通过pubkey创建turingchain 地址的功能
   262  func PeerIDToPubkey(id string) (string, error) {
   263  	//encodeIdStr := "16Uiu2HAm7vDB7XDuEv8XNPcoPqumVngsjWoogGXENNDXVYMiCJHM"
   264  	//hexpubStr:="02b99bc73bfb522110634d5644d476b21b3171eefab517da0646ef2aba39dbf4a0"
   265  	//turingchain address:13ohj5JH6NE15ENfuQRneqGdg29nT27K3k
   266  	pID, err := peer.Decode(id)
   267  	if err != nil {
   268  		return "", err
   269  	}
   270  
   271  	pub, err := pID.ExtractPublicKey()
   272  	if err != nil {
   273  		return "", err
   274  	}
   275  
   276  	pbs, err := pub.Raw()
   277  	if err != nil {
   278  		return "", err
   279  	}
   280  	return hex.EncodeToString(pbs), nil
   281  
   282  }