github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/protocols/accounting.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:41</date>
    10  //</624450105759502336>
    11  
    12  
    13  package protocols
    14  
    15  import (
    16  	"time"
    17  
    18  	"github.com/ethereum/go-ethereum/metrics"
    19  )
    20  
    21  //定义一些指标
    22  var (
    23  //所有指标都是累积的
    24  
    25  //单位贷记总额
    26  	mBalanceCredit metrics.Counter
    27  //借记单位总额
    28  	mBalanceDebit metrics.Counter
    29  //贷记字节总数
    30  	mBytesCredit metrics.Counter
    31  //借记字节总数
    32  	mBytesDebit metrics.Counter
    33  //贷记邮件总数
    34  	mMsgCredit metrics.Counter
    35  //借记邮件总数
    36  	mMsgDebit metrics.Counter
    37  //本地节点必须删除远程对等节点的次数
    38  	mPeerDrops metrics.Counter
    39  //本地节点透支和丢弃的次数
    40  	mSelfDrops metrics.Counter
    41  
    42  	MetricsRegistry metrics.Registry
    43  )
    44  
    45  //价格定义如何将价格传递给会计实例
    46  type Prices interface {
    47  //返回消息的价格
    48  	Price(interface{}) *Price
    49  }
    50  
    51  type Payer bool
    52  
    53  const (
    54  	Sender   = Payer(true)
    55  	Receiver = Payer(false)
    56  )
    57  
    58  //价格表示消息的成本
    59  type Price struct {
    60  	Value   uint64
    61  PerByte bool //如果价格为每字节或单位,则为真
    62  	Payer   Payer
    63  }
    64  
    65  //因为给了信息的价格
    66  //协议以绝对值提供消息价格
    67  //然后,此方法返回正确的有符号金额,
    68  //根据“付款人”论点确定的付款人:
    69  //“send”将传递“sender”付款人,“receive”将传递“receiver”参数。
    70  //因此:如果发送人和发送人支付,金额为正,否则为负。
    71  //如果收货方付款,金额为正,否则为负。
    72  func (p *Price) For(payer Payer, size uint32) int64 {
    73  	price := p.Value
    74  	if p.PerByte {
    75  		price *= uint64(size)
    76  	}
    77  	if p.Payer == payer {
    78  		return 0 - int64(price)
    79  	}
    80  	return int64(price)
    81  }
    82  
    83  //余额是实际的会计实例
    84  //余额定义了会计所需的操作
    85  //实现在内部维护每个对等点的平衡
    86  type Balance interface {
    87  //使用远程节点“peer”将金额添加到本地余额中;
    88  //正数=贷方本地节点
    89  //负金额=借方本地节点
    90  	Add(amount int64, peer *Peer) error
    91  }
    92  
    93  //会计实现钩子接口
    94  //它通过余额接口与余额接口连接,
    95  //通过价格接口与协议及其价格进行接口时
    96  type Accounting struct {
    97  Balance //会计逻辑接口
    98  Prices  //价格逻辑接口
    99  }
   100  
   101  func NewAccounting(balance Balance, po Prices) *Accounting {
   102  	ah := &Accounting{
   103  		Prices:  po,
   104  		Balance: balance,
   105  	}
   106  	return ah
   107  }
   108  
   109  //SetupAccountingMetrics为P2P会计指标创建单独的注册表;
   110  //这个注册表应该独立于任何其他指标,因为它在不同的端点上持续存在。
   111  //它还实例化给定的度量并启动持续执行例程,该例程
   112  //在经过的时间间隔内,将度量值写入级别数据库
   113  func SetupAccountingMetrics(reportInterval time.Duration, path string) *AccountingMetrics {
   114  //创建空注册表
   115  	MetricsRegistry = metrics.NewRegistry()
   116  //实例化度量
   117  	mBalanceCredit = metrics.NewRegisteredCounterForced("account.balance.credit", MetricsRegistry)
   118  	mBalanceDebit = metrics.NewRegisteredCounterForced("account.balance.debit", MetricsRegistry)
   119  	mBytesCredit = metrics.NewRegisteredCounterForced("account.bytes.credit", MetricsRegistry)
   120  	mBytesDebit = metrics.NewRegisteredCounterForced("account.bytes.debit", MetricsRegistry)
   121  	mMsgCredit = metrics.NewRegisteredCounterForced("account.msg.credit", MetricsRegistry)
   122  	mMsgDebit = metrics.NewRegisteredCounterForced("account.msg.debit", MetricsRegistry)
   123  	mPeerDrops = metrics.NewRegisteredCounterForced("account.peerdrops", MetricsRegistry)
   124  	mSelfDrops = metrics.NewRegisteredCounterForced("account.selfdrops", MetricsRegistry)
   125  //创建数据库并开始持久化
   126  	return NewAccountingMetrics(MetricsRegistry, reportInterval, path)
   127  }
   128  
   129  //发送需要一个对等点、一个大小和一个消息以及
   130  //-使用价格接口计算本地节点向对等端发送大小消息的成本
   131  //-使用余额界面的贷记/借记本地节点
   132  func (ah *Accounting) Send(peer *Peer, size uint32, msg interface{}) error {
   133  //获取消息的价格(通过协议规范)
   134  	price := ah.Price(msg)
   135  //此邮件不需要记帐
   136  	if price == nil {
   137  		return nil
   138  	}
   139  //评估发送消息的价格
   140  	costToLocalNode := price.For(Sender, size)
   141  //做会计工作
   142  	err := ah.Add(costToLocalNode, peer)
   143  //记录度量:只增加面向用户的度量的计数器
   144  	ah.doMetrics(costToLocalNode, size, err)
   145  	return err
   146  }
   147  
   148  //接收需要一个对等点、一个大小和一个消息以及
   149  //-使用价格接口计算从对等端接收大小消息的本地节点的成本
   150  //-使用余额界面的贷记/借记本地节点
   151  func (ah *Accounting) Receive(peer *Peer, size uint32, msg interface{}) error {
   152  //获取消息的价格(通过协议规范)
   153  	price := ah.Price(msg)
   154  //此邮件不需要记帐
   155  	if price == nil {
   156  		return nil
   157  	}
   158  //评估接收消息的价格
   159  	costToLocalNode := price.For(Receiver, size)
   160  //做会计工作
   161  	err := ah.Add(costToLocalNode, peer)
   162  //记录度量:只增加面向用户的度量的计数器
   163  	ah.doMetrics(costToLocalNode, size, err)
   164  	return err
   165  }
   166  
   167  //记录一些指标
   168  //这不是错误处理。'err'由'send'和'receive'返回
   169  //如果违反了限制(透支),则“err”将不为零,在这种情况下,对等方已被取消。
   170  //如果违反了限制,“err”不等于零:
   171  //*如果价格为正数,则本地节点已记入贷方;因此“err”隐式地表示远程节点已被删除。
   172  //*如果价格为负,则本地节点已被借记,因此“err”隐式地表示本地节点“透支”
   173  func (ah *Accounting) doMetrics(price int64, size uint32, err error) {
   174  	if price > 0 {
   175  		mBalanceCredit.Inc(price)
   176  		mBytesCredit.Inc(int64(size))
   177  		mMsgCredit.Inc(1)
   178  		if err != nil {
   179  //增加由于“透支”而丢弃远程节点的次数
   180  			mPeerDrops.Inc(1)
   181  		}
   182  	} else {
   183  		mBalanceDebit.Inc(price)
   184  		mBytesDebit.Inc(int64(size))
   185  		mMsgDebit.Inc(1)
   186  		if err != nil {
   187  //增加本地节点对其他节点进行“透支”的次数
   188  			mSelfDrops.Inc(1)
   189  		}
   190  	}
   191  }
   192