Skip to content

Conversation

@ceyonur
Copy link
Contributor

@ceyonur ceyonur commented Sep 17, 2025

Why this should be merged

Refactors common parts from acp-176 and acp-226 into common package.

How this works

Uses TargetExcessParam structure to define common functions, so that different implementations/parameters can use the same functions

How this was tested

existing tests

Need to be documented in RELEASES.md?

no

@ceyonur ceyonur mentioned this pull request Sep 17, 2025
@ceyonur ceyonur changed the title Ceyonur/acp 176 226 refactor acp-176/226 refactor to common package Sep 17, 2025
Base automatically changed from ceyonur/acp-176-math-package to master September 18, 2025 13:32
@ceyonur ceyonur changed the base branch from master to ceyonur/acp-226-math-package September 18, 2025 16:25
Base automatically changed from ceyonur/acp-226-math-package to master September 18, 2025 19:35
@ceyonur ceyonur force-pushed the ceyonur/acp-176-226-refactor branch from a9463c2 to 4b1dd83 Compare September 18, 2025 21:00
@ceyonur ceyonur marked this pull request as ready for review September 18, 2025 21:35
Copilot AI review requested due to automatic review settings September 18, 2025 21:35
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Refactors common functionality from ACP-176 and ACP-226 implementations into a shared common package to reduce code duplication and improve maintainability.

  • Introduces TargetExcessParams structure to encapsulate parameters and functions for target excess calculations
  • Moves exponential calculation logic from gas package to a new math utility function
  • Updates both ACP implementations to use the shared common package functions

Reviewed Changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
vms/evm/upgrades/common/target_excess.go New common package with shared target excess calculation functions and parameters structure
vms/evm/upgrades/acp226/acp226.go Refactored to use common package functions, removing duplicate implementation
vms/evm/upgrades/acp176/acp176.go Refactored to use common package functions, removing duplicate implementation
vms/components/gas/gas.go Simplified to use new math utility function for exponential calculations
utils/math/exponential.go New utility function extracted from gas package for exponential calculations

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@@ -154,7 +157,7 @@ func (s *State) UpdateTargetExcess(desiredTargetExcess gas.Gas) {
)

// Ensure the gas capacity does not exceed the maximum capacity.
newMaxCapacity := mulWithUpperBound(newTargetPerSecond, TargetToMaxCapacity) // C
newMaxCapacity := gas.Gas(common.MulWithUpperBound(uint64(newTargetPerSecond), TargetToMaxCapacity)) // C
s.Gas.Capacity = min(s.Gas.Capacity, newMaxCapacity)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this now uses golang builtin min, would it be a problem? cc @StephenButtolph

Copy link
Contributor

@michaelkaplan13 michaelkaplan13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nit, and think we should update/remove the "target" terminology from target_excess.go since it's not just applying to the gas target anymore, but otherwise LGTM.

@joshua-kim joshua-kim moved this to In Progress 🏗️ in avalanchego Sep 29, 2025
@StephenButtolph StephenButtolph moved this from In Progress 🏗️ to In Review 🔎 in avalanchego Sep 30, 2025

maxOutput uint256.Int
)
num.SetUint64(numerator) // range is [0, MaxUint64]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: All of these range comments seem overly verbose since it's already known that the range of a unit64 is the range of a uint64. Should we get rid of them?

Comment on lines 23 to 38
// def fake_exponential(factor: int, numerator: int, denominator: int) -> int:
// i = 1
// output = 0
// numerator_accum = factor * denominator
// while numerator_accum > 0:
// output += numerator_accum
// numerator_accum = (numerator_accum * numerator) // (denominator * i)
// i += 1
// return output // denominator
//
// This implementation is optimized with the knowledge that any value greater
// than MaxUint64 gets returned as MaxUint64. This means that every intermediate
// value is guaranteed to be at most MaxUint193. So, we can safely use
// uint256.Int.
//
// This function does not perform any memory allocations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems overly verbose to me that we document this - isn't this just a translation of the below source code? Wonder if we should just get rid of this too.

// This function does not perform any memory allocations.
//
//nolint:dupword // The python is copied from the EIP-4844 specification
func CalculateExponential(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we call this ApproximateExponential so the caller doesn't have to read the godoc to know this is not an exact result?

// See the file LICENSE for licensing terms.

// Package common provides shared utility functions for ACP implementations.
package common
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really dislike common packages... I feel like it's unclear what the boundary is for what they own and they tend to turn into dumpsters for things that don't fit elsewhere. Would it be reasonable for us to define an excess package instead?


// AdjustExcess calculates the optimal new excess given the current and desired excess values,
// ensuring the change does not exceed the maximum excess difference.
func (p ExcessParams) AdjustExcess(excess, desired uint64) uint64 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typically receivers start with the first letter of the type (e) unless there's a commonly known abbreviation for the type (like db or vm).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have changed the package name, I think we should rename ExcessParams > Params

Comment on lines 16 to 18
MinValue uint64 // Minimum value (P or M)
ConversionRate uint64 // Conversion factor for exponential calculations (D)
MaxExcessDiff uint64 // Maximum change in excess per update (Q)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these letters coming from? Is there some formula we should doc at the top of this type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved those letters to relevant acps

)

// ExcessParams contains the parameters needed for excess calculations.
type ExcessParams struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know much about this type so I'm not the person to ask for naming, but should we call this Excess? It seems like a math-y type so I assumed everything inside it was a parameter for its calculations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's still contains parameters for calculations. It's not the real excess, but it's a set of parameters to be used in excess calculations.


// MulWithUpperBound multiplies two numbers and returns the result. If the
// result overflows, it returns [math.MaxUint64].
func MulWithUpperBound(a, b uint64) uint64 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be in this package? Seems like this is only used for acp176 implementation - wondering if we could move and unexport there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can move this to acp176 package as an unexported function

@joshua-kim joshua-kim moved this from In Review 🔎 to In Progress 🏗️ in avalanchego Oct 1, 2025
@ceyonur ceyonur marked this pull request as draft October 7, 2025 08:19
@ceyonur ceyonur marked this pull request as ready for review October 7, 2025 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress 🏗️

Development

Successfully merging this pull request may close these issues.

5 participants