This commit is contained in:
Kevaundray Wedderburn 2025-07-10 23:14:07 +01:00
parent adf6119e88
commit 66425aa070

View file

@ -380,7 +380,7 @@ var (
u256_16 = uint256.NewInt(16) u256_16 = uint256.NewInt(16)
u256_480 = uint256.NewInt(480) u256_480 = uint256.NewInt(480)
u256_199680 = uint256.NewInt(199680) u256_199680 = uint256.NewInt(199680)
// divisors as uint256 // divisors as uint256
u256_byzantiumDivisor = uint256.NewInt(byzantiumDivisor) u256_byzantiumDivisor = uint256.NewInt(byzantiumDivisor)
u256_berlinDivisor = uint256.NewInt(berlinDivisor) u256_berlinDivisor = uint256.NewInt(berlinDivisor)
@ -407,19 +407,19 @@ func byzantiumMultComplexity(x uint64) *uint256.Int {
// For large x, use uint256 arithmetic to avoid overflow // For large x, use uint256 arithmetic to avoid overflow
// x^2 / 16 + 480*x - 199680 // x^2 / 16 + 480*x - 199680
xUint := new(uint256.Int).SetUint64(x) xUint := new(uint256.Int).SetUint64(x)
// Calculate x^2 // Calculate x^2
xSquared := new(uint256.Int).Mul(xUint, xUint) xSquared := new(uint256.Int).Mul(xUint, xUint)
// Calculate x^2 / 16 (right shift by 4 bits) // Calculate x^2 / 16 (right shift by 4 bits)
xSquaredDiv16 := new(uint256.Int).Rsh(xSquared, 4) xSquaredDiv16 := new(uint256.Int).Rsh(xSquared, 4)
// Calculate 480 * x // Calculate 480 * x
x480 := new(uint256.Int).Mul(xUint, u256_480) x480 := new(uint256.Int).Mul(xUint, u256_480)
// Calculate 480 * x - 199680 // Calculate 480 * x - 199680
x480Minus199680 := new(uint256.Int).Sub(x480, u256_199680) x480Minus199680 := new(uint256.Int).Sub(x480, u256_199680)
// Add the two parts together // Add the two parts together
return new(uint256.Int).Add(xSquaredDiv16, x480Minus199680) return new(uint256.Int).Add(xSquaredDiv16, x480Minus199680)
} }
@ -435,13 +435,14 @@ func byzantiumMultComplexity(x uint64) *uint256.Int {
func berlinMultComplexity(x uint64) *uint256.Int { func berlinMultComplexity(x uint64) *uint256.Int {
// TODO: The preceding line is too smart. // TODO: The preceding line is too smart.
// TODO: The issue is that (x+7) / 8 can overflow // TODO: The issue is that (x+7) / 8 can overflow
// TODO: if x > 2^64 - 7 // TODO: if x > 2^64 - 7
ceilDiv8 := (x >> 3) + ((x&7 + 7) >> 3) // safe ceil(x / 8) ceilDiv8 := (x >> 3) + ((x&7 + 7) >> 3) // safe ceil(x / 8)
z := new(uint256.Int).SetUint64(ceilDiv8) z := new(uint256.Int).SetUint64(ceilDiv8)
return new(uint256.Int).Mul(z, z) // square without overflow return new(uint256.Int).Mul(z, z) // square without overflow
} }
// Slow Bigint way (benchmark this) // Slow Bigint way (benchmark this)
// func berlinMultComplexity(xInt uint64) *big.Int { // func berlinMultComplexity(xInt uint64) *big.Int {
// x := new(big.Int).SetUint64(xInt) // x := new(big.Int).SetUint64(xInt)
// x = new(big.Int).Add(x, big.NewInt(7)) // x + 7 // x = new(big.Int).Add(x, big.NewInt(7)) // x + 7
// x = new(big.Int).Rsh(x, 3) // (x + 7) / 8 // x = new(big.Int).Rsh(x, 3) // (x + 7) / 8
@ -465,17 +466,17 @@ func osakaMultComplexity(x uint64) *uint256.Int {
// This is the adjusted exponent length used in gas calculation. // This is the adjusted exponent length used in gas calculation.
func calculateIterationCount(expLen uint64, expHead *uint256.Int, multiplier uint64) uint64 { func calculateIterationCount(expLen uint64, expHead *uint256.Int, multiplier uint64) uint64 {
var iterationCount uint64 var iterationCount uint64
// For large exponents (expLen > 32), add (expLen - 32) * multiplier // For large exponents (expLen > 32), add (expLen - 32) * multiplier
if expLen > 32 { if expLen > 32 {
iterationCount = (expLen - 32) * multiplier iterationCount = (expLen - 32) * multiplier
} }
// Add the MSB position - 1 if expHead is non-zero // Add the MSB position - 1 if expHead is non-zero
if bitLen := expHead.BitLen(); bitLen > 0 { if bitLen := expHead.BitLen(); bitLen > 0 {
iterationCount += uint64(bitLen - 1) iterationCount += uint64(bitLen - 1)
} }
// Return at least 1 // Return at least 1
return max(iterationCount, 1) return max(iterationCount, 1)
} }
@ -484,18 +485,18 @@ func calculateIterationCount(expLen uint64, expHead *uint256.Int, multiplier uin
func byzantiumGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64 { func byzantiumGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64 {
// Calculate max(baseLen, modLen) // Calculate max(baseLen, modLen)
maxLen := max(baseLen, modLen) maxLen := max(baseLen, modLen)
// Calculate multiplication complexity // Calculate multiplication complexity
multComplexity := byzantiumMultComplexity(maxLen) multComplexity := byzantiumMultComplexity(maxLen)
// Calculate iteration count // Calculate iteration count
iterationCount := calculateIterationCount(expLen, expHead, byzantiumMultiplier) iterationCount := calculateIterationCount(expLen, expHead, byzantiumMultiplier)
// Calculate gas: (multComplexity * iterationCount) / byzantiumDivisor // Calculate gas: (multComplexity * iterationCount) / byzantiumDivisor
iterCount := new(uint256.Int).SetUint64(iterationCount) iterCount := new(uint256.Int).SetUint64(iterationCount)
gas := new(uint256.Int).Mul(multComplexity, iterCount) gas := new(uint256.Int).Mul(multComplexity, iterCount)
gas.Div(gas, u256_byzantiumDivisor) gas.Div(gas, u256_byzantiumDivisor)
if !gas.IsUint64() { if !gas.IsUint64() {
return math.MaxUint64 return math.MaxUint64
} }
@ -506,22 +507,22 @@ func byzantiumGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint
func berlinGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64 { func berlinGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64 {
// Calculate max(baseLen, modLen) // Calculate max(baseLen, modLen)
maxLen := max(baseLen, modLen) maxLen := max(baseLen, modLen)
// Calculate multiplication complexity // Calculate multiplication complexity
multComplexity := berlinMultComplexity(maxLen) multComplexity := berlinMultComplexity(maxLen)
// Calculate iteration count // Calculate iteration count
iterationCount := calculateIterationCount(expLen, expHead, berlinMultiplier) iterationCount := calculateIterationCount(expLen, expHead, berlinMultiplier)
// Calculate gas: (multComplexity * iterationCount) / berlinDivisor // Calculate gas: (multComplexity * iterationCount) / berlinDivisor
iterCount := new(uint256.Int).SetUint64(iterationCount) iterCount := new(uint256.Int).SetUint64(iterationCount)
gas := new(uint256.Int).Mul(multComplexity, iterCount) gas := new(uint256.Int).Mul(multComplexity, iterCount)
gas.Div(gas, u256_berlinDivisor) gas.Div(gas, u256_berlinDivisor)
if !gas.IsUint64() { if !gas.IsUint64() {
return math.MaxUint64 return math.MaxUint64
} }
// Return at least berlinMinGas // Return at least berlinMinGas
return max(gas.Uint64(), berlinMinGas) return max(gas.Uint64(), berlinMinGas)
} }
@ -530,22 +531,22 @@ func berlinGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64
func osakaGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64 { func osakaGasCalc(baseLen, expLen, modLen uint64, expHead *uint256.Int) uint64 {
// Calculate max(baseLen, modLen) // Calculate max(baseLen, modLen)
maxLen := max(baseLen, modLen) maxLen := max(baseLen, modLen)
// Calculate multiplication complexity // Calculate multiplication complexity
multComplexity := osakaMultComplexity(maxLen) multComplexity := osakaMultComplexity(maxLen)
// Calculate iteration count // Calculate iteration count
iterationCount := calculateIterationCount(expLen, expHead, osakaMultiplier) iterationCount := calculateIterationCount(expLen, expHead, osakaMultiplier)
// Calculate gas: (multComplexity * iterationCount) / osakaDivisor // Calculate gas: (multComplexity * iterationCount) / osakaDivisor
iterCount := new(uint256.Int).SetUint64(iterationCount) iterCount := new(uint256.Int).SetUint64(iterationCount)
gas := new(uint256.Int).Mul(multComplexity, iterCount) gas := new(uint256.Int).Mul(multComplexity, iterCount)
gas.Div(gas, u256_osakaDivisor) gas.Div(gas, u256_osakaDivisor)
if !gas.IsUint64() { if !gas.IsUint64() {
return math.MaxUint64 return math.MaxUint64
} }
// Return at least osakaMinGas // Return at least osakaMinGas
return max(gas.Uint64(), osakaMinGas) return max(gas.Uint64(), osakaMinGas)
} }
@ -556,7 +557,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
baseLenBig := new(uint256.Int).SetBytes(getData(input, 0, 32)) baseLenBig := new(uint256.Int).SetBytes(getData(input, 0, 32))
expLenBig := new(uint256.Int).SetBytes(getData(input, 32, 32)) expLenBig := new(uint256.Int).SetBytes(getData(input, 32, 32))
modLenBig := new(uint256.Int).SetBytes(getData(input, 64, 32)) modLenBig := new(uint256.Int).SetBytes(getData(input, 64, 32))
// Convert to uint64, capping at max value // Convert to uint64, capping at max value
baseLen := baseLenBig.Uint64() baseLen := baseLenBig.Uint64()
if !baseLenBig.IsUint64() { if !baseLenBig.IsUint64() {
@ -570,14 +571,14 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
if !modLenBig.IsUint64() { if !modLenBig.IsUint64() {
modLen = math.MaxUint64 modLen = math.MaxUint64
} }
// Skip the header // Skip the header
if len(input) > 96 { if len(input) > 96 {
input = input[96:] input = input[96:]
} else { } else {
input = input[:0] input = input[:0]
} }
// Retrieve the head 32 bytes of exp for the adjusted exponent length // Retrieve the head 32 bytes of exp for the adjusted exponent length
var expHead *uint256.Int var expHead *uint256.Int
if uint64(len(input)) <= baseLen { if uint64(len(input)) <= baseLen {
@ -590,7 +591,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
expHead = new(uint256.Int).SetBytes(getData(input, baseLen, expLen)) expHead = new(uint256.Int).SetBytes(getData(input, baseLen, expLen))
} }
} }
// Choose the appropriate gas calculation based on the EIP flags // Choose the appropriate gas calculation based on the EIP flags
if c.eip7883 { if c.eip7883 {
return osakaGasCalc(baseLen, expLen, modLen, expHead) return osakaGasCalc(baseLen, expLen, modLen, expHead)