Chat with us    I'm writing my Qi Quai report for Steph.
     
Econet / AmountOfQuai     Search:

Updating KQuai

Comparing actualAmountOfQuai and realizedAmountOfQuai

core > slice.go

  • func (sl *Slice) Append(
  • Append takes a proposed header and constructs a local block and attempts to hierarchically append it to the block graph.
  • header.KQuaiDiscount() stores the block's kQuaiDiscount value which ranges from 0 to 100,000.
    • What it represents: a rolling average of the recent kQuai rate change (normalized and capped) expressed on a 0..100000 scale (100000 == 100%). The controller updates it with an EMA over 4000 blocks using the per‑block rate‑of‑change term (capped at 100000).
    • How it’s computed (protocol):
      • kQuaiDiscounti = (kQuaiDiscount{i-1}3999 + min(|kQuaii - kQuai{i-4000}| 100000 / kQuai_{i-4000}, 100000)) / 4000.
    • How it’s used: the slice code reads header.KQuaiDiscount and applies it to the pool’s discounted conversion amount as:
      • conversionAmountAfterKQuaiDiscount = discountedConversionAmountInInt * (KQuaiDiscountMultiplier − kQuaiDiscount) / KQuaiDiscountMultiplier.
      • That value is applied only to conversions aligned with the exchange‑rate trend; conversions against the trend don’t get this extra discount.
  • params.StartingKQuaiDiscount = 100
  • Line 1787 calculates: newkQuaiDiscount := sl.hc.ComputeKQuaiDiscount(parent, exchangeRate)
  • Line 402: actualConversionAmountInQuai := big.NewInt(0)
  • Line 403: realizedConversionAmountInQuai := big.NewInt(0)

  • line 405-499: Go through the transactions in newInboundEtxs that are conversions and determine whether they should proceed, whether they satisfy the allowed slippage, which is up to 10%

value, originalValue, originalExtValues are three copies of etx.Value(), which is the amount of the transaction specified as a big integer. The meaning of the amount depends on whether it refers to Qi or Quai.

if the amount refers to Quai, define tempActualConversionAmountInQuai.

ext.To() is the recipient's address, which is an account in Qi or an account in Quai. We can tell by querying etx.To().IsInQuaiLedgerScope() or etx.To().IsInQuaiLedgerScope().

  • This is a conversion, so if the recipient wants it in Quai, the original amount was in Qi. So we set it equal to misc.QiToQuai of the value (in Qi) at the exchange rate given the miner difficulty.
  • If the recipient wants it in Qi, then since this is a conversion, the amount must currently be in Quai, so we keep that.

slip is given by the user or set at a minimum of 0.30% and a maximum of 90%. slip expresses the tolerance of the user as regards changes during the conversion process.

apply cubic discount

  • we're interested in this behavior after we've gone past block ConversionSlipChangeBlock = 285000
  • we apply block.ConversionFlowAmount() to calculate the discount
  • line 441: discountedConversionAmount = misc.ApplyCubicDiscount(tempActualConversionAmountInQuai, block.ConversionFlowAmount())

conversionAmountAfterKQuaiDiscount applies the KQuaiDiscount from the header

  • calculate tenPercentOriginalValue for comparing with slip
  • calculate amountAfterMaxSlip for comparing as regards slip

Lines 465-481: to update the value, apply the kQuaiDiscount (to reduce the amount and discourage conversion) if

  • exchangeRateIncreasing (Qi per Quai is increasing) and converting from Quai to Qi
  • not exchangeRateIncreasing (Qi per Quai is decreasing) and converting from Qi to Quai

limit any discount to 10%

check if the new (discounted) value is within the allowed slippage, and if not, then set the conversion amount to zero so that that conversion does not take place


ComputeConversionAmountInQuai


Line 502: actualConversionAmountInQuai = misc.ComputeConversionAmountInQuai(header, newInboundEtxs)

Leads us to: consensus > misc > rewards.go func ComputeConversionAmountInQuai

This receives the transactions newInboundExts

Consider the conversions.

If the recipient of the amount to be converted maintains the Qi ledger, then the conversion must be from Quai, and so the original amount must already be in Quai. So that amount is simply copied over.

If the recipient of the amount to be converted maintains the Quai ledger, then the conversion must be from Qi. So we calculate the amount of Quai using the function QiToQuai() which makes use of the header's ExchangeRate and MinerDifficulty.


QiToQuai


Go to: consensus > misc > rewards.go func QiToQuai

It applies the amount in Qi, the exchange rate and the difficulty.

It multiplies the amount by CalculateQuaiReward() / CalculateQiReward()

These functions are located on the same page: consensus > misc > rewards.go

CalculateQuaiReward() multiplies exchangeRate times difficulty

  • exchangeRate is k_Quai (see the Conversions page)

CalculateQiReward() multiplies k_Qi times difficulty

  • The amount 1/k_Qi is given by params.OneOverKqi(header.NumberU64()).
  • k_Qi expresses the block difficulty and is adjusted for foreseen improvements in calculation speeds

QiToQuai returns (exchangeRate / k_Qi) times the amount in Qi. This gives us the corresponding amount in Quai.


Calculate discounts


ComputeConversionAmountInQuai adds up all of the conversion amounts in Quai for all of the conversions. It returns this amount. In the Append function it is called: actualConversionAmountInQuai

continuing... and assuming the block number is large enough... apply the cubic discount, noting conversionFlowAmount, to actualConversionAmountInQuai. conversionFlowAmount is an EMA of its previous values. This yields discountedConversionAmount.

conversionAmountAfterKQuaiDiscount applies the KQuaiDiscount, which will be relevant for conversions that go with the trend


Cycle through all nonzero conversions newInboundExts


Lines 518-570

Apply the conversion discount flow to all conversions.

  • Multiply the original value by discountedConversionAmountInInt / actualConversionAmountInQuai

Calculate ten percent of original value, in order to restrict slippage

If converting from Quai to Qi

  • If the exchange rate (Qi per Quai) is increasing, reduce by the kQuaiDiscount
  • If the value is less than 10% of the original value, then set the value at 10% of the original value.
  • The value is in Quai. It is stored in etxValuesBeforeConversion[i] and is: realizedConversionAmountInQuai
  • It is converted from Quai to Qi by misc.QuaiToQi, which depends on the exchange rate and the miner difficulty.

If converting from Qi to Quai

  • If the exchange rate (Qi per Quai) is decreasing, reduce by the kQuaiDiscount
  • If the value is less than 10% of the original value, then set the value at 10% of the original value.
  • The value is in Quai. It is stored in etxValuesBeforeConversion[i] and is: realizedConversionAmountInQuai
  • It is converted from Quai to Qi by misc.QuaiToQi, which depends on the exchange rate and the miner difficulty.

Compare preferences for Qi and Quai


Calculate: updatedTokenChoiceSet with func CalculateTokenChoicesSet, provide: block.ExchangeRate(), newInboundEtxs, actualConversionAmountInQuai, realizedConversionAmountInQuai, minerDifficulty

For each block, a decision is made whether the market is prefering Qi or Quai. This decision is not entirely straightforward. It can be thought of as voting.

  • Each coinbase transaction gets one vote. Note that the winner of a block may express their winning as a single transaction or as multiple transactions. Also, a nonwinning miner (workshare/uncle authors) may express their winning as a single transaction or as multiple transactions. Each transaction gets one vote.
  • Each conversion receives N votes, where N is the whole number of block rewards R in the amount NR + r, and the remainder r<N. Which is to say, if the amount is less than a block reward, then it does not get any votes.

All the votes are added up to see who wins, Qi or Quai, in which case diffErr is added or subtracted, respectively, to tokenchoices.Diff

Lines 120 to 124

  • If tokenChoices.Qi > tokenChoices.Quai, then add diffErr.
  • Otherwise, subtract diffErr.

Calculate the final exchange rate


Calculate the exchange rate using: CalculateBetaFromMiningChoiceAndConversions which inputs block.ExchangeRate(), updatedTokenChoiceSet.

Exchange rate calculated by:

  • exchangeRate := misc.CalculateKQuai