Skip to content

Commit

Permalink
Apply correct Turing gas multiplier
Browse files Browse the repository at this point in the history
  • Loading branch information
InoMurko committed Oct 30, 2023
1 parent ac70a6a commit c125850
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 12 deletions.
29 changes: 20 additions & 9 deletions boba_examples/turing-hello-world/test/local-webserver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { BigNumber, Contract, ContractFactory, providers, Wallet, utils } from 'ethers'
import { ethers } from 'hardhat'
import { Contract, ContractFactory, providers, Wallet, utils } from 'ethers'
import chai, { expect } from 'chai'
import { solidity } from 'ethereum-waffle'
chai.use(solidity)
Expand Down Expand Up @@ -280,14 +279,26 @@ if (hre.network.name === "boba_local") {
}
})

it("should charge extra gas for L1 calldata storage", async() => {
const g1 = (await hello.estimateGas.multArray(urlStr2, 1, 10, gasOverride)).toNumber()
const g2 = (await hello.estimateGas.multArray(urlStr2, 101, 10, gasOverride)).toNumber()
it("should charge extra gas for L1 calldata storage", async() => {
const eg1 = (await hello.estimateGas.multArray(urlStr2, 1, 10, gasOverride)).toNumber()
let tx1 = await hello.multArray(urlStr2, 1, 10, gasOverride)
const res1 = await tx1.wait()
expect(res1).to.be.ok
const ag1 = res1.gasUsed.toNumber()

const eg2 = (await hello.estimateGas.multArray(urlStr2, 101, 10, gasOverride)).toNumber()
let tx2 = await hello.multArray(urlStr2, 101, 10, gasOverride)
const res2 = await tx2.wait()
expect(res2).to.be.ok
const ag2 = res2.gasUsed.toNumber()

// Larger calldata costs more gas inside the contract itself. We need to test for
// additional usage on top of this from the L1 calldata calculation. The exact value
// depends on the L1 gas price so this test doesn't look for a specific number
expect (g2 - g1).to.be.above(110000)
})
// depends on the L1 gas price so this test doesn't look for a specific number.
// Actual tx is a different code path than estimateGas so both are checked.
expect (eg2 - eg1).to.be.above(110000)
expect (ag2 - ag1).to.be.above(110000)
})

it("should support a large response", async() => {
const nElem = 2038
Expand Down Expand Up @@ -353,7 +364,7 @@ if (hre.network.name === "boba_local") {
helper.address
)
// Change expected value if tests are added or skipped above
expect(postBalance).to.equal( utils.parseEther('0.9'))
expect(postBalance).to.equal(utils.parseEther('0.7'))
})
})
} else {
Expand Down
16 changes: 13 additions & 3 deletions integration-tests/test/eth-l2/turing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('Turing 256 Bit Random Number Test', async () => {
).attach(L1StandardBridgeAddress)
/* eslint-disable */
const http = require('http')
const ip = require('ip')
const ip = require('ip')
// start local server
const server = (module.exports = http
.createServer(async function (req, res) {
Expand Down Expand Up @@ -114,7 +114,7 @@ describe('Turing 256 Bit Random Number Test', async () => {
res.end('Expected content-type: application/json')
}
})
.listen(apiPort))
.listen(apiPort))
URL = `http://${ip.address()}:${apiPort}/echo`
/* eslint-enable */
})
Expand Down Expand Up @@ -267,16 +267,26 @@ describe('Turing 256 Bit Random Number Test', async () => {
} catch (e) {
expect(e.error.toString()).to.contain('SERVER_ERROR')
}
try {
await random.MixedInput(URL, 123, 999, { gasLimit: 11_000_000 })
} catch (e) {
expect(e.error.toString()).to.contain('SERVER_ERROR')
}
})

// Should reject a 2nd call from a different EVM depth.
it('should disallow nested Turing calls', async () => {
try {
const tr = await random.NestedRandom(1)
await random.estimateGas.NestedRandom(1)
expect(1).to.equal(0)
} catch (e) {
expect(e.error.toString()).to.contain('SERVER_ERROR')
}
try {
const tr = await random.NestedRandom(1, { gasLimit: 11_000_000 })
} catch (e) {
expect(e.error.toString()).to.contain('SERVER_ERROR')
}
})

it('should allow repeated Random calls (legacy support)', async () => {
Expand Down
5 changes: 5 additions & 0 deletions l2geth/core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
}
}

p2 := msg.GasPrice()
if vmenv.ChainConfig().IsTuringCharge2Fork(vmenv.BlockNumber) && p2.BitLen() > 0 {
vmenv.Context.TuringGasMul = float64(l1GasPrice.Uint64()) / float64(p2.Uint64())
}

// Determine the L2 Boba fee if users chose BOBA as the fee token
feeTokenSelection := statedb.GetFeeTokenSelection(msg.From())

Expand Down
17 changes: 17 additions & 0 deletions l2geth/core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,23 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
log.Debug("TURING ERROR: evm.Context.Turing already set")
return nil, gas, ErrTuringDepth
}

// For compatibility, only apply a charge beyond the legacy size limit
if isTuring2 {
if len(evm.Context.Turing) > 160 {
feePerByte := evm.Context.TuringGasMul * 500.0 / 32.0
turingGas = uint64(float64(len(evm.Context.Turing)) * feePerByte)
}

if contract.Gas <= turingGas {
log.Debug("TURING ERROR: Insufficient gas for calldata", "have", contract.Gas, "need", turingGas)
return nil, 0, ErrTuringTooLong
} else {
log.Debug("TURING Deducting calldata gas", "had", contract.Gas, "len", len(evm.Context.Turing), "Mul", evm.Context.TuringGasMul, "deducting", turingGas)
contract.UseGas(turingGas)
}
}

ret, err = run(evm, contract, evm.Context.Turing, false)
log.Trace("TURING REPLAY", "evm.Context.Turing", evm.Context.Turing)
}
Expand Down
67 changes: 67 additions & 0 deletions l2geth/params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,36 @@ var (

// Enable the conditional logic to prevent Turing balances from reaching zero
BobaOperaTestnetTuringChargeForkNum = big.NewInt(3000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaMainnetTuringCharge2ForkNum = big.NewInt(1064000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaGoerliTuringCharge2ForkNum = big.NewInt(114000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaMoonbeamTuringCharge2ForkNum = big.NewInt(1580000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaMoonbaseTuringCharge2ForkNum = big.NewInt(350000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaAvaxTuringCharge2ForkNum = big.NewInt(101200)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaFujiTuringCharge2ForkNum = big.NewInt(4000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaBnbTuringCharge2ForkNum = big.NewInt(25740000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaBnbTestnetTuringCharge2ForkNum = big.NewInt(428000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaOperaTuringCharge2ForkNum = big.NewInt(80000)

// Enable the conditional logic to fix bug in charging for L1 Turing calldata
BobaOperaTestnetTuringCharge2ForkNum = big.NewInt(3000)
)

// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
Expand Down Expand Up @@ -567,6 +597,43 @@ func (c *ChainConfig) IsTuringChargeFork(num *big.Int) bool {
return true
}

func (c *ChainConfig) IsTuringCharge2Fork(num *big.Int) bool {
if c.ChainID == nil {
return true
}
if c.ChainID.Cmp(OpMainnetChainID) == 0 {
return isForked(BobaMainnetTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpGoerliChainID) == 0 {
return isForked(BobaGoerliTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpMoonbeamChainID) == 0 {
return isForked(BobaMoonbeamTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpMoonbaseChainID) == 0 {
return isForked(BobaMoonbaseTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpBnbChainID) == 0 {
return isForked(BobaBnbTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpBnbTestnetChainID) == 0 {
return isForked(BobaBnbTestnetTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpAvaxChainID) == 0 {
return isForked(BobaAvaxTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpFujiChainID) == 0 {
return isForked(BobaFujiTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpOperaChainID) == 0 {
return isForked(BobaOperaTuringCharge2ForkNum, num)
}
if c.ChainID.Cmp(OpOperaTestnetChainID) == 0 {
return isForked(BobaOperaTestnetTuringCharge2ForkNum, num)
}
return true
}

func (c *ChainConfig) IsEthereumL2() bool {
if os.Getenv("IS_ETHEREUM_L2") == "true" {
return true
Expand Down

0 comments on commit c125850

Please sign in to comment.