Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

creation-time CODECOPY adds no code to the witness #86

4 changes: 2 additions & 2 deletions core/vm/gas_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func gasCodeCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
uint64Length = 0xffffffffffffffff
}
_, offset, nonPaddedSize := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, uint64Length)
statelessGas = touchEachChunksOnReadAndChargeGas(offset, nonPaddedSize, contract.Address().Bytes()[:], nil, nil, evm.Accesses)
statelessGas = touchEachChunksOnReadAndChargeGas(offset, nonPaddedSize, contract.Address().Bytes()[:], nil, nil, evm.Accesses, contract.IsDeployment)
}
usedGas, err := gasCodeCopyStateful(evm, contract, stack, mem, memorySize)
return usedGas + statelessGas, err
Expand Down Expand Up @@ -150,7 +150,7 @@ func gasExtCodeCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
// behavior from CODECOPY which only charges witness access costs for the part of the range
// which overlaps in the account code. TODO: clarify this is desired behavior and amend the
// spec.
statelessGas = touchEachChunksOnReadAndChargeGas(uint64CodeOffset, uint64Length, targetAddr[:], nil, nil, evm.Accesses)
statelessGas = touchEachChunksOnReadAndChargeGas(uint64CodeOffset, uint64Length, targetAddr[:], nil, nil, evm.Accesses, contract.IsDeployment)
}
usedGas, err := gasExtCodeCopyStateful(evm, contract, stack, mem, memorySize)
return usedGas + statelessGas, err
Expand Down
14 changes: 9 additions & 5 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,14 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([

paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(scope.Contract.Code, uint64CodeOffset, length.Uint64())
if interpreter.evm.chainConfig.IsCancun(interpreter.evm.Context.BlockNumber) {
touchEachChunksOnReadAndChargeGas(copyOffset, nonPaddedCopyLength, scope.Contract.Address().Bytes()[:], scope.Contract.Code, scope.Contract, interpreter.evm.Accesses)
touchEachChunksOnReadAndChargeGas(copyOffset, nonPaddedCopyLength, scope.Contract.Address().Bytes()[:], scope.Contract.Code, scope.Contract, interpreter.evm.Accesses, scope.Contract.IsDeployment)
}
scope.Memory.Set(memOffset.Uint64(), uint64(len(paddedCodeCopy)), paddedCodeCopy)
return nil, nil
}

// touchEachChunksAndChargeGas is a helper function to touch every chunk in a code range and charge witness gas costs
func touchEachChunksOnReadAndChargeGas(offset, size uint64, address []byte, code []byte, contract AnalyzedContract, accesses *types.AccessWitness) uint64 {
func touchEachChunksOnReadAndChargeGas(offset, size uint64, address []byte, code []byte, contract AnalyzedContract, accesses *types.AccessWitness, deployment bool) uint64 {
// note that in the case where the copied code is outside the range of the
// contract code but touches the last leaf with contract code in it,
// we don't include the last leaf of code in the AccessWitness. The
Expand Down Expand Up @@ -434,7 +434,11 @@ func touchEachChunksOnReadAndChargeGas(offset, size uint64, address []byte, code
padding := make([]byte, 31-valueSize, 31-valueSize)
copy(value[valueSize+1:], padding)
}
accesses.SetLeafValue(index[:], value)
if deployment {
accesses.SetLeafValue(index[:], nil)
} else {
accesses.SetLeafValue(index[:], value)
}
}
}

Expand All @@ -458,7 +462,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
code := interpreter.evm.StateDB.GetCode(addr)
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
cb := codeBitmap(code)
touchEachChunksOnReadAndChargeGas(copyOffset, nonPaddedCopyLength, addr[:], code, &cb, interpreter.evm.Accesses)
touchEachChunksOnReadAndChargeGas(copyOffset, nonPaddedCopyLength, addr[:], code, &cb, interpreter.evm.Accesses, false)
gballet marked this conversation as resolved.
Show resolved Hide resolved
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), paddedCodeCopy)
} else {
codeCopy := getData(interpreter.evm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64())
Expand Down Expand Up @@ -980,7 +984,7 @@ func makePush(size uint64, pushByteSize int) executionFunc {
}

if interpreter.evm.chainConfig.IsCancun(interpreter.evm.Context.BlockNumber) {
statelessGas := touchEachChunksOnReadAndChargeGas(uint64(startMin), uint64(pushByteSize), scope.Contract.Address().Bytes()[:], scope.Contract.Code, scope.Contract, interpreter.evm.Accesses)
statelessGas := touchEachChunksOnReadAndChargeGas(uint64(startMin), uint64(pushByteSize), scope.Contract.Address().Bytes()[:], scope.Contract.Code, scope.Contract, interpreter.evm.Accesses, scope.Contract.IsDeployment)
scope.Contract.UseGas(statelessGas)
}

Expand Down
2 changes: 1 addition & 1 deletion core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
if in.evm.ChainConfig().IsCancun(in.evm.Context.BlockNumber) && !contract.IsDeployment {
// if the PC ends up in a new "page" of verkleized code, charge the
// associated witness costs.
contract.Gas -= touchEachChunksOnReadAndChargeGas(pc, 1, contract.Address().Bytes()[:], contract.Code, contract, in.evm.TxContext.Accesses)
contract.Gas -= touchEachChunksOnReadAndChargeGas(pc, 1, contract.Address().Bytes()[:], contract.Code, contract, in.evm.TxContext.Accesses, contract.IsDeployment)
}

// TODO how can we tell if we are in stateless mode here and need to get the op from the witness
Expand Down