Skip to content

Commit

Permalink
Merge branch 'master' into qdm12/libevm-master-merge
Browse files Browse the repository at this point in the history
Commit 2663434
  • Loading branch information
qdm12 committed Feb 24, 2025
2 parents 20c5470 + 2663434 commit 1b3f283
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 41 deletions.
47 changes: 23 additions & 24 deletions plugin/evm/upgrade/acp176/acp176.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (

TimeToFillCapacity = 10 // in seconds
TargetToMax = 2 // multiplier to convert from target per second to max per second
TargetToPriceUpdateConversion = 43 // 43s ~= 30s * ln(2) which makes the price double at most every ~30 seconds
TargetToPriceUpdateConversion = 87 // 87s ~= 60s * ln(2) which makes the price double at most every ~60 seconds
MaxTargetChangeRate = 1024 // Controls the rate that the target can change per block.

targetToMaxCapacity = TargetToMax * TimeToFillCapacity
Expand All @@ -52,38 +52,24 @@ func (s *State) Target() gas.Gas {
// MaxCapacity returns the maximum possible accrued gas capacity, `C`.
func (s *State) MaxCapacity() gas.Gas {
targetPerSecond := s.Target()
maxCapacity, err := safemath.Mul(targetToMaxCapacity, targetPerSecond)
if err != nil {
maxCapacity = math.MaxUint64
}
return maxCapacity
return mulWithUpperBound(targetPerSecond, targetToMaxCapacity)
}

// GasPrice returns the current required fee per gas.
//
// GasPrice = MinGasPrice * e^(Excess / (Target() * TargetToPriceUpdateConversion))
func (s *State) GasPrice() gas.Price {
target := s.Target()
priceUpdateConversion, err := safemath.Mul(TargetToPriceUpdateConversion, target) // K
if err != nil {
priceUpdateConversion = math.MaxUint64
}

targetPerSecond := s.Target()
priceUpdateConversion := mulWithUpperBound(targetPerSecond, TargetToPriceUpdateConversion) // K
return gas.CalculatePrice(MinGasPrice, s.Gas.Excess, priceUpdateConversion)
}

// AdvanceTime increases the gas capacity and decreases the gas excess based on
// the elapsed seconds.
func (s *State) AdvanceTime(seconds uint64) {
targetPerSecond := s.Target()
maxPerSecond, err := safemath.Mul(TargetToMax, targetPerSecond) // R
if err != nil {
maxPerSecond = math.MaxUint64
}
maxCapacity, err := safemath.Mul(TimeToFillCapacity, maxPerSecond) // C
if err != nil {
maxCapacity = math.MaxUint64
}
maxPerSecond := mulWithUpperBound(targetPerSecond, TargetToMax) // R
maxCapacity := mulWithUpperBound(maxPerSecond, TimeToFillCapacity) // C
s.Gas = s.Gas.AdvanceTime(
maxCapacity,
maxPerSecond,
Expand Down Expand Up @@ -134,15 +120,18 @@ func (s *State) UpdateTargetExcess(desiredTargetExcess gas.Gas) {
newTargetPerSecond,
previousTargetPerSecond,
)

// Ensure the gas capacity does not exceed the maximum capacity.
newMaxCapacity := mulWithUpperBound(newTargetPerSecond, targetToMaxCapacity) // C
s.Gas.Capacity = min(s.Gas.Capacity, newMaxCapacity)
}

// DesiredTargetExcess calculates the optimal desiredTargetExcess given the
// desired target.
//
// This could be solved directly by calculating D * ln(desiredTarget / P) using
// floating point math. However, it introduces inaccuracies. So, we use a binary
// search to find the closest integer solution.
func DesiredTargetExcess(desiredTarget gas.Gas) gas.Gas {
// This could be solved directly by calculating D * ln(desiredTarget / P)
// using floating point math. However, it introduces inaccuracies. So, we
// use a binary search to find the closest integer solution.
return gas.Gas(sort.Search(maxTargetExcess, func(targetExcessGuess int) bool {
state := State{
TargetExcess: gas.Gas(targetExcessGuess),
Expand Down Expand Up @@ -180,3 +169,13 @@ func scaleExcess(
bigExcess.Div(&bigExcess, &bigTarget)
return gas.Gas(bigExcess.Uint64())
}

// mulWithUpperBound multiplies two numbers and returns the result. If the
// result overflows, it returns [math.MaxUint64].
func mulWithUpperBound(a, b gas.Gas) gas.Gas {
product, err := safemath.Mul(a, b)
if err != nil {
return math.MaxUint64
}
return product
}
70 changes: 53 additions & 17 deletions plugin/evm/upgrade/acp176/acp176_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var (
name: "almost_excess_change",
state: State{
Gas: gas.State{
Excess: 29_805_331, // MinTargetPerSecond * ln(2) * TargetToPriceUpdateConversion
Excess: 60_303_808, // MinTargetPerSecond * ln(2) * TargetToPriceUpdateConversion
},
TargetExcess: 33, // Largest excess that doesn't increase the target
},
Expand All @@ -53,7 +53,7 @@ var (
name: "small_excess_change",
state: State{
Gas: gas.State{
Excess: 29_805_362, // (MinTargetPerSecond + 1) * ln(2) * TargetToPriceUpdateConversion
Excess: 60_303_868, // (MinTargetPerSecond + 1) * ln(2) * TargetToPriceUpdateConversion
},
TargetExcess: 34, // Smallest excess that increases the target
},
Expand All @@ -65,7 +65,7 @@ var (
name: "max_initial_excess_change",
state: State{
Gas: gas.State{
Excess: 47_286_485, // (MinTargetPerSecond + 977) * ln(3) * TargetToPriceUpdateConversion
Excess: 95_672_652, // (MinTargetPerSecond + 977) * ln(3) * TargetToPriceUpdateConversion
},
TargetExcess: MaxTargetExcessDiff,
},
Expand All @@ -78,85 +78,85 @@ var (
name: "current_target",
state: State{
Gas: gas.State{
Excess: 1_336_650_647, // 1_500_000 * ln(nAVAX) * TargetToPriceUpdateConversion
Excess: 2_704_386_192, // 1_500_000 * ln(nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 13_605_152, // 2^25 * ln(1.5)
},
target: 1_500_000,
maxCapacity: targetToMaxCapacity * 1_500_000,
gasPrice: (nAVAX + 7) * MinGasPrice, // +7 due to approximation
gasPrice: nAVAX*MinGasPrice + 2, // +2 due to approximation
},
{
name: "3m_target",
state: State{
Gas: gas.State{
Excess: 3_267_368_247, // 3_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
Excess: 6_610_721_802, // 3_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 36_863_312, // 2^25 * ln(3)
},
target: 3_000_000,
maxCapacity: targetToMaxCapacity * 3_000_000,
gasPrice: (100*nAVAX + 31) * MinGasPrice, // +31 due to approximation
gasPrice: 100*nAVAX*MinGasPrice + 4, // +4 due to approximation
},
{
name: "6m_target",
state: State{
Gas: gas.State{
Excess: 6_534_736_494, // 6_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
Excess: 13_221_443_604, // 6_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 60_121_472, // 2^25 * ln(6)
},
target: 6_000_000,
maxCapacity: targetToMaxCapacity * 6_000_000,
gasPrice: (100*nAVAX + 31) * MinGasPrice, // +31 due to approximation
gasPrice: 100*nAVAX*MinGasPrice + 4, // +4 due to approximation
},
{
name: "10m_target",
state: State{
Gas: gas.State{
Excess: 10_891_227_490, // 10_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
Excess: 22_035_739_340, // 10_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 77_261_935, // 2^25 * ln(10)
},
target: 10_000_000,
maxCapacity: targetToMaxCapacity * 10_000_000,
gasPrice: (100*nAVAX + 31) * MinGasPrice, // +31 due to approximation
gasPrice: 100*nAVAX*MinGasPrice + 5, // +5 due to approximation
},
{
name: "100m_target",
state: State{
Gas: gas.State{
Excess: 108_912_274_899, // 100_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
Excess: 220_357_393_400, // 100_000_000 * ln(100*nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 154_523_870, // 2^25 * ln(100)
},
target: 100_000_000,
maxCapacity: targetToMaxCapacity * 100_000_000,
gasPrice: (100*nAVAX + 8) * MinGasPrice, // +8 due to approximation
gasPrice: 100*nAVAX*MinGasPrice + 5, // +5 due to approximation
},
{
name: "low_1b_target",
state: State{
Gas: gas.State{
Excess: 1_089_122_722_848, // (1_000_000_000 - 24) * ln(100*nAVAX) * TargetToPriceUpdateConversion
Excess: 2_203_573_881_110, // (1_000_000_000 - 24) * ln(100*nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 231_785_804, // 2^25 * ln(1000)
},
target: 1_000_000_000 - 24,
maxCapacity: targetToMaxCapacity * (1_000_000_000 - 24),
gasPrice: (100*nAVAX + 1) * MinGasPrice, // +1 due to approximation
gasPrice: 100 * nAVAX * MinGasPrice,
},
{
name: "high_1b_target",
state: State{
Gas: gas.State{
Excess: 1_089_122_755_521, // (1_000_000_000 + 6) * ln(100*nAVAX) * TargetToPriceUpdateConversion
Excess: 2_203_573_947_217, // (1_000_000_000 + 6) * ln(100*nAVAX) * TargetToPriceUpdateConversion
},
TargetExcess: 231_785_805, // 2^25 * ln(1000) + 1
},
target: 1_000_000_000 + 6,
maxCapacity: targetToMaxCapacity * (1_000_000_000 + 6),
gasPrice: (100 * nAVAX) * MinGasPrice,
gasPrice: 100 * nAVAX * MinGasPrice,
},
{
name: "largest_max_capacity",
Expand Down Expand Up @@ -558,6 +558,42 @@ var (
TargetExcess: 2 * MaxTargetExcessDiff,
},
},
{
name: "reduce_capacity",
initial: State{
Gas: gas.State{
Capacity: 20_039_100, // MinTargetPerSecond * e^(2*MaxTargetExcessDiff / TargetConversion)
Excess: 2_000_000_000,
},
TargetExcess: 2 * MaxTargetExcessDiff,
},
desiredTargetExcess: 0,
expected: State{
Gas: gas.State{
Capacity: 20_019_540, // MinTargetPerSecond * e^(MaxTargetExcessDiff / TargetConversion)
Excess: 1_998_047_816, // 2M * NewTarget / OldTarget
},
TargetExcess: MaxTargetExcessDiff,
},
},
{
name: "overflow_max_capacity",
initial: State{
Gas: gas.State{
Capacity: math.MaxUint64,
Excess: 2_000_000_000,
},
TargetExcess: maxTargetExcess,
},
desiredTargetExcess: 0,
expected: State{
Gas: gas.State{
Capacity: math.MaxUint64,
Excess: 1_998_047_867, // 2M * NewTarget / OldTarget
},
TargetExcess: maxTargetExcess - MaxTargetExcessDiff,
},
},
}
)

Expand Down

0 comments on commit 1b3f283

Please sign in to comment.