github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/manager.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  //版权所有2017 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 accounts
    26  
    27  import (
    28  	"reflect"
    29  	"sort"
    30  	"sync"
    31  
    32  	"github.com/ethereum/go-ethereum/event"
    33  )
    34  
    35  //经理是一个主要的客户经理,可以与
    36  //用于签署事务的后端。
    37  type Manager struct {
    38  backends map[reflect.Type][]Backend //当前注册的后端索引
    39  updaters []event.Subscription       //所有后端的钱包更新订阅
    40  updates  chan WalletEvent           //后端钱包更改的订阅接收器
    41  wallets  []Wallet                   //缓存所有注册后端的所有钱包
    42  
    43  feed event.Feed //钱包信息提示到达/离开
    44  
    45  	quit chan chan error
    46  	lock sync.RWMutex
    47  }
    48  
    49  //NewManager创建一个通用的客户经理,通过
    50  //支撑的后端。
    51  func NewManager(backends ...Backend) *Manager {
    52  //从后端检索钱包的初始列表并按URL排序
    53  	var wallets []Wallet
    54  	for _, backend := range backends {
    55  		wallets = merge(wallets, backend.Wallets()...)
    56  	}
    57  //从所有后端订阅钱包通知
    58  	updates := make(chan WalletEvent, 4*len(backends))
    59  
    60  	subs := make([]event.Subscription, len(backends))
    61  	for i, backend := range backends {
    62  		subs[i] = backend.Subscribe(updates)
    63  	}
    64  //召集客户经理并返回
    65  	am := &Manager{
    66  		backends: make(map[reflect.Type][]Backend),
    67  		updaters: subs,
    68  		updates:  updates,
    69  		wallets:  wallets,
    70  		quit:     make(chan chan error),
    71  	}
    72  	for _, backend := range backends {
    73  		kind := reflect.TypeOf(backend)
    74  		am.backends[kind] = append(am.backends[kind], backend)
    75  	}
    76  	go am.update()
    77  
    78  	return am
    79  }
    80  
    81  //关闭将终止客户经理的内部通知进程。
    82  func (am *Manager) Close() error {
    83  	errc := make(chan error)
    84  	am.quit <- errc
    85  	return <-errc
    86  }
    87  
    88  //更新是钱包事件循环,监听来自后端的通知
    89  //更新钱包的缓存。
    90  func (am *Manager) update() {
    91  //管理器终止时关闭所有订阅
    92  	defer func() {
    93  		am.lock.Lock()
    94  		for _, sub := range am.updaters {
    95  			sub.Unsubscribe()
    96  		}
    97  		am.updaters = nil
    98  		am.lock.Unlock()
    99  	}()
   100  
   101  //循环直至终止
   102  	for {
   103  		select {
   104  		case event := <-am.updates:
   105  //钱包事件已到达,更新本地缓存
   106  			am.lock.Lock()
   107  			switch event.Kind {
   108  			case WalletArrived:
   109  				am.wallets = merge(am.wallets, event.Wallet)
   110  			case WalletDropped:
   111  				am.wallets = drop(am.wallets, event.Wallet)
   112  			}
   113  			am.lock.Unlock()
   114  
   115  //通知事件的任何侦听器
   116  			am.feed.Send(event)
   117  
   118  		case errc := <-am.quit:
   119  //经理终止,返回
   120  			errc <- nil
   121  			return
   122  		}
   123  	}
   124  }
   125  
   126  //后端从帐户管理器中检索具有给定类型的后端。
   127  func (am *Manager) Backends(kind reflect.Type) []Backend {
   128  	return am.backends[kind]
   129  }
   130  
   131  //钱包将返回在此帐户管理器下注册的所有签名者帐户。
   132  func (am *Manager) Wallets() []Wallet {
   133  	am.lock.RLock()
   134  	defer am.lock.RUnlock()
   135  
   136  	cpy := make([]Wallet, len(am.wallets))
   137  	copy(cpy, am.wallets)
   138  	return cpy
   139  }
   140  
   141  //Wallet检索与特定URL关联的钱包。
   142  func (am *Manager) Wallet(url string) (Wallet, error) {
   143  	am.lock.RLock()
   144  	defer am.lock.RUnlock()
   145  
   146  	parsed, err := parseURL(url)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	for _, wallet := range am.Wallets() {
   151  		if wallet.URL() == parsed {
   152  			return wallet, nil
   153  		}
   154  	}
   155  	return nil, ErrUnknownWallet
   156  }
   157  
   158  //查找与特定帐户对应的钱包。自从
   159  //帐户可以动态地添加到钱包中或从钱包中删除,此方法具有
   160  //钱包数量的线性运行时间。
   161  func (am *Manager) Find(account Account) (Wallet, error) {
   162  	am.lock.RLock()
   163  	defer am.lock.RUnlock()
   164  
   165  	for _, wallet := range am.wallets {
   166  		if wallet.Contains(account) {
   167  			return wallet, nil
   168  		}
   169  	}
   170  	return nil, ErrUnknownAccount
   171  }
   172  
   173  //订阅创建异步订阅以在
   174  //经理检测到钱包从其任何后端到达或离开。
   175  func (am *Manager) Subscribe(sink chan<- WalletEvent) event.Subscription {
   176  	return am.feed.Subscribe(sink)
   177  }
   178  
   179  //merge是一种类似于append的钱包排序方式,其中
   180  //通过在正确位置插入新钱包,可以保留原始列表。
   181  //
   182  //假定原始切片已按URL排序。
   183  func merge(slice []Wallet, wallets ...Wallet) []Wallet {
   184  	for _, wallet := range wallets {
   185  		n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 })
   186  		if n == len(slice) {
   187  			slice = append(slice, wallet)
   188  			continue
   189  		}
   190  		slice = append(slice[:n], append([]Wallet{wallet}, slice[n:]...)...)
   191  	}
   192  	return slice
   193  }
   194  
   195  //drop是merge的coutterpart,它从排序后的
   196  //缓存并删除指定的。
   197  func drop(slice []Wallet, wallets ...Wallet) []Wallet {
   198  	for _, wallet := range wallets {
   199  		n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 })
   200  		if n == len(slice) {
   201  //未找到钱包,可能在启动过程中发生
   202  			continue
   203  		}
   204  		slice = append(slice[:n], slice[n+1:]...)
   205  	}
   206  	return slice
   207  }