github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/account_level/level_math.go (about)

     1  package account_level
     2  
     3  import (
     4  	"math/big"
     5  	"sync"
     6  )
     7  
     8  var (
     9  	minM    = big.NewRat(570e8, 1)
    10  	ratU    = big.NewRat(1e8, 1)
    11  	ratC    = big.NewRat(1, 8640)
    12  	ratX    = big.NewRat(1, 1)
    13  	ratN    = big.NewRat(-1, 1)
    14  	dratMax = big.NewRat(16, 100)
    15  	dratL2  = big.NewRat(1, 10)
    16  	dratL1  = big.NewRat(8, 100)
    17  	dratS   = big.NewRat(1, 100)
    18  	ratTen  = big.NewRat(10, 1)
    19  
    20  	rat0    = big.NewRat(0, 1)
    21  	rat1    = big.NewRat(1, 10)
    22  	rat2    = big.NewRat(2, 10)
    23  	rat3    = big.NewRat(3, 10)
    24  	rat4    = big.NewRat(4, 10)
    25  	rat5    = big.NewRat(5, 10)
    26  	rat6    = big.NewRat(6, 10)
    27  	rat7    = big.NewRat(7, 10)
    28  	rat8    = big.NewRat(8, 10)
    29  	ratline = big.NewRat(9, 10)
    30  )
    31  
    32  type lvlMath struct {
    33  	mu       sync.Mutex
    34  	manure   []*big.Int //store the used energy in one period
    35  	cycleLen int
    36  	lapWidth uint64
    37  	ydayAmt  *big.Int
    38  	tdayAmt  *big.Int
    39  	newest   *big.Int //the gas wait to exec
    40  	height   uint64
    41  }
    42  
    43  func newLvlMath(cycleLen int, lapWidth uint64) *lvlMath {
    44  	return &lvlMath{
    45  		manure:   make([]*big.Int, 0, cycleLen*2+1),
    46  		ydayAmt:  big.NewInt(0),
    47  		tdayAmt:  big.NewInt(0),
    48  		newest:   big.NewInt(0),
    49  		cycleLen: cycleLen,
    50  		lapWidth: lapWidth,
    51  		height:   0,
    52  	}
    53  }
    54  
    55  func (this *lvlMath) pull(height uint64, usedGas *big.Int) bool {
    56  	this.mu.Lock()
    57  	defer this.mu.Unlock()
    58  	freshManure := big.NewInt(0).Set(usedGas)
    59  	this.newest.Add(this.newest, freshManure)
    60  	this.height = height
    61  	//fmt.Println("💊 💊 💊 ", height, this.lapWidth)
    62  	if height%this.lapWidth == 0 {
    63  		lapGas := new(big.Int).Set(this.newest)
    64  		this.newest.SetInt64(0)
    65  		this.manure = append(this.manure, lapGas)
    66  		l := len(this.manure)
    67  		if l <= this.cycleLen {
    68  			this.ydayAmt.Add(this.ydayAmt, lapGas)
    69  		} else if l <= this.cycleLen*2 {
    70  			this.tdayAmt.Add(this.tdayAmt, lapGas)
    71  		} else {
    72  			this.pop()
    73  			return true
    74  		}
    75  	}
    76  	return false
    77  }
    78  
    79  func (this *lvlMath) pop() {
    80  	if len(this.manure) == this.cycleLen*2+1 {
    81  		yRmoved := this.manure[0]
    82  		tRemoved := this.manure[this.cycleLen]
    83  		newest := this.manure[this.cycleLen*2]
    84  		this.manure = this.manure[1:]
    85  		this.ydayAmt.Sub(this.ydayAmt, yRmoved).Add(this.ydayAmt, tRemoved)
    86  		this.tdayAmt.Sub(this.tdayAmt, tRemoved).Add(this.tdayAmt, newest)
    87  	}
    88  }
    89  
    90  func (this *lvlMath) r() *big.Rat {
    91  	bt := new(big.Rat).SetInt(this.tdayAmt)
    92  	by := new(big.Rat).SetInt(this.ydayAmt)
    93  	rat := new(big.Rat)
    94  	rat.Sub(bt, by)
    95  	byInv := new(big.Rat).Set(by)
    96  	if byInv.Cmp(rat0) != 0 {
    97  		byInv.Inv(byInv)
    98  	}
    99  	rat.Mul(rat, byInv)
   100  
   101  	sign := true
   102  	if rat.Sign() == -1 {
   103  		sign = false
   104  	}
   105  	rat.Abs(rat)
   106  	if rat.Cmp(rat1) == -1 {
   107  		rat.Set(rat0)
   108  
   109  	} else if rat.Cmp(rat2) == -1 {
   110  		rat.Set(rat1)
   111  	} else if rat.Cmp(rat3) == -1 {
   112  		rat.Set(rat2)
   113  	} else if rat.Cmp(rat4) == -1 {
   114  		rat.Set(rat3)
   115  	} else if rat.Cmp(rat5) == -1 {
   116  		rat.Set(rat4)
   117  	} else if rat.Cmp(rat6) == -1 {
   118  		rat.Set(rat5)
   119  	} else if rat.Cmp(rat7) == -1 {
   120  		rat.Set(rat6)
   121  	} else if rat.Cmp(rat8) == -1 {
   122  		rat.Set(rat7)
   123  	} else if rat.Cmp(ratline) == -1 {
   124  		rat.Set(rat8)
   125  	} else {
   126  		rat.Set(ratline)
   127  	}
   128  	if !sign {
   129  		rat.Mul(rat, ratN)
   130  	}
   131  	return rat
   132  }
   133  
   134  func (this *lvlMath) m(rat *big.Rat) *big.Rat {
   135  	by := new(big.Rat).SetInt(this.ydayAmt)
   136  	m := new(big.Rat)
   137  	m.Add(ratX, rat)
   138  	m.Mul(m, by)
   139  	m.Mul(m, ratC)
   140  	if m.Cmp(minM) == -1 {
   141  		m.Set(minM)
   142  	}
   143  	return m
   144  }
   145  
   146  func (this *lvlMath) d(rat *big.Rat) []*big.Rat {
   147  	sign := rat.Sign()
   148  	d1 := new(big.Rat).Set(ratX)
   149  	factor := new(big.Rat)
   150  	if rat.Cmp(rat8) == 1 {
   151  		if sign == 1 {
   152  			factor.Set(dratMax)
   153  		}
   154  	} else {
   155  		d1.Set(ratX)
   156  		factor.Mul(dratL2, rat)
   157  		factor.Sub(dratL1, factor)
   158  	}
   159  
   160  	step := this.ratStep(rat)
   161  	ds := make([]*big.Rat, 0, step)
   162  	ds = append(ds, d1)
   163  	offset := 1
   164  	for i := lv2; i <= lv9; i++ {
   165  		if offset >= step {
   166  			break
   167  		}
   168  		dn := new(big.Rat).Add(ds[i-2], factor)
   169  		factor.Sub(factor, dratS)
   170  		ds = append(ds, dn)
   171  		offset++
   172  	}
   173  	return ds
   174  }
   175  
   176  func (this *lvlMath) v(rat, m *big.Rat, dsReal []*big.Rat, distribution []*big.Int) []uint64 {
   177  	l := len(dsReal)
   178  	/*fmt.Println("dsreal", dsReal)
   179  	fmt.Println("distribution", distribution)*/
   180  	lvAoumt := make([]*big.Rat, 0, l)
   181  	for i := 0; i < l; i++ {
   182  		//fmt.Println("lvamount", distribution[i])
   183  		lvAoumt = append(lvAoumt, new(big.Rat).SetInt(distribution[i]))
   184  	}
   185  	deno := new(big.Rat)
   186  	for k, v := range dsReal {
   187  		part := new(big.Rat)
   188  		part.Mul(v, lvAoumt[k])
   189  		//fmt.Println("deno add ", part, v, lvAoumt[k])
   190  		deno.Add(deno, part)
   191  	}
   192  	//fmt.Println("deno", deno)
   193  	if deno.Cmp(rat0) != 0 {
   194  		deno.Inv(deno)
   195  	}
   196  
   197  	per := make([]uint64, 0, l)
   198  	for _, v := range dsReal {
   199  		part := new(big.Rat)
   200  		part.Mul(v, m)
   201  		part.Mul(part, deno)
   202  		part.Mul(part, ratU)
   203  		rfTmp := big.NewFloat(0).SetRat(part)
   204  		integer, _ := rfTmp.Uint64()
   205  		per = append(per, integer)
   206  	}
   207  	//fmt.Println("️ ", per)
   208  	return per
   209  }
   210  
   211  func (this *lvlMath) ratStep(rat *big.Rat) int {
   212  	sign := rat.Sign()
   213  	step := 9
   214  	if sign == 1 {
   215  		mid := new(big.Rat).Set(rat)
   216  		mid.Mul(ratTen, mid)
   217  		num, _ := mid.Float64()
   218  		step = step - int(num)
   219  		if step == 0 {
   220  			step = 1
   221  		}
   222  		return step
   223  	} else {
   224  		return step
   225  	}
   226  }
   227  
   228  func (this *lvlMath) reward(height uint64, energyUsed *big.Int, distribution []*big.Int) []uint64 {
   229  	bl := this.pull(height, energyUsed)
   230  	if bl {
   231  		r := this.r()
   232  		m := this.m(r)
   233  		//fmt.Println("💊 💊 💊 💊", m)
   234  		d := this.d(r)
   235  		return this.v(r, m, d, distribution)
   236  	}
   237  	//fmt.Println("📈 bl ", bl)
   238  	return make([]uint64, 0)
   239  }