mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
core/vm: fix opEOFCreate, correct initcode stuff
This commit is contained in:
parent
abe9f28845
commit
e9ad878b90
5 changed files with 45 additions and 24 deletions
|
|
@ -72,6 +72,7 @@ type RefTests struct {
|
|||
}
|
||||
|
||||
type EOFTest struct {
|
||||
IsInitCode bool `json:"isInitCode"`
|
||||
Code string `json:"code"`
|
||||
Results map[string]etResult `json:"results"`
|
||||
}
|
||||
|
|
@ -84,7 +85,7 @@ type etResult struct {
|
|||
func eofParser(ctx *cli.Context) error {
|
||||
// If `--hex` is set, parse and validate the hex string argument.
|
||||
if ctx.IsSet(HexFlag.Name) {
|
||||
if _, err := parseAndValidate(ctx.String(HexFlag.Name)); err != nil {
|
||||
if _, err := parseAndValidate(ctx.String(HexFlag.Name), false); err != nil {
|
||||
if err2 := errors.Unwrap(err); err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
|
|
@ -143,7 +144,7 @@ func eofParser(ctx *cli.Context) error {
|
|||
if len(t) == 0 || t[0] == '#' {
|
||||
continue
|
||||
}
|
||||
if _, err := parseAndValidate(t); err != nil {
|
||||
if _, err := parseAndValidate(t, false); err != nil {
|
||||
if err2 := errors.Unwrap(err); err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
|
|
@ -166,7 +167,7 @@ func ExecuteTest(src []byte) (int, int, error) {
|
|||
total++
|
||||
// TODO(matt): all tests currently run against
|
||||
// shanghai EOF, add support for custom forks.
|
||||
_, err := parseAndValidate(tt.Code)
|
||||
_, err := parseAndValidate(tt.Code, tt.IsInitCode)
|
||||
if err2 := errors.Unwrap(err); err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
|
|
@ -193,7 +194,7 @@ func ExecuteTest(src []byte) (int, int, error) {
|
|||
return passed, total, nil
|
||||
}
|
||||
|
||||
func parseAndValidate(s string) (*vm.Container, error) {
|
||||
func parseAndValidate(s string, isInitCode bool) (*vm.Container, error) {
|
||||
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
||||
s = s[2:]
|
||||
}
|
||||
|
|
@ -202,7 +203,7 @@ func parseAndValidate(s string) (*vm.Container, error) {
|
|||
return nil, fmt.Errorf("unable to decode data: %w", err)
|
||||
}
|
||||
var c vm.Container
|
||||
if err := c.UnmarshalBinary(b); err != nil {
|
||||
if err := c.UnmarshalBinary(b, isInitCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.ValidateCode(&jt); err != nil {
|
||||
|
|
@ -223,7 +224,7 @@ func eofDump(ctx *cli.Context) error {
|
|||
return fmt.Errorf("unable to decode data: %w", err)
|
||||
}
|
||||
var c vm.Container
|
||||
if err := c.UnmarshalBinary(b); err != nil {
|
||||
if err := c.UnmarshalBinary(b, false); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Print(c.String())
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ func applyEOFChecks(prestate *Prestate, chainConfig *params.ChainConfig) error {
|
|||
c vm.Container
|
||||
err error
|
||||
)
|
||||
err = c.UnmarshalBinary(acc.Code)
|
||||
err = c.UnmarshalBinary(acc.Code, false)
|
||||
if err == nil {
|
||||
jt := vm.NewPragueEOFInstructionSetForTesting()
|
||||
err = c.ValidateCode(&jt)
|
||||
|
|
|
|||
|
|
@ -882,7 +882,6 @@ func opEOFCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
|||
salt = scope.Stack.pop()
|
||||
offset, size = scope.Stack.pop(), scope.Stack.pop()
|
||||
input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
|
||||
gas = scope.Contract.Gas
|
||||
)
|
||||
if int(idx) >= len(scope.Contract.Container.ContainerSections) {
|
||||
return nil, fmt.Errorf("invalid subcontainer")
|
||||
|
|
@ -895,6 +894,12 @@ func opEOFCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
|||
if ok := scope.Contract.UseGas(hashingCharge, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified); !ok {
|
||||
return nil, ErrGasUintOverflow
|
||||
}
|
||||
if interpreter.evm.Config.Tracer != nil {
|
||||
if interpreter.evm.Config.Tracer != nil {
|
||||
interpreter.evm.Config.Tracer.OnOpcode(*pc, byte(EOFCREATE), 0, hashingCharge, scope, interpreter.returnData, interpreter.evm.depth, nil)
|
||||
}
|
||||
}
|
||||
gas := scope.Contract.Gas
|
||||
// Reuse last popped value from stack
|
||||
stackvalue := size
|
||||
// Apply EIP150
|
||||
|
|
@ -996,6 +1001,18 @@ func opReturnContract(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
|||
if len(deployedCode) == 0 {
|
||||
return nil, errors.New("nonexistant subcontainer")
|
||||
}
|
||||
// Validate the subcontainer
|
||||
var c Container
|
||||
if err := c.UnmarshalBinary(deployedCode, true); err != nil {
|
||||
panic(fmt.Sprintf("%x", deployedCode))
|
||||
}
|
||||
if err := c.ValidateCode(interpreter.tableEOF); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(c.Data) < c.DataSize {
|
||||
return nil, errors.New("invalid subcontainer")
|
||||
}
|
||||
c.DataSize = len(c.Data)
|
||||
// Restore context
|
||||
var (
|
||||
last = len(scope.ReturnStack) - 1
|
||||
|
|
@ -1004,7 +1021,9 @@ func opReturnContract(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
|||
scope.ReturnStack = scope.ReturnStack[:last]
|
||||
scope.CodeSection = retCtx.Section
|
||||
*pc = retCtx.Pc - 1
|
||||
return deployedCode, errStopToken
|
||||
fmt.Printf("%v", c.MarshalBinary())
|
||||
fmt.Printf("%v", deployedCode)
|
||||
return c.MarshalBinary(), errStopToken
|
||||
}
|
||||
|
||||
func opDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ func (c *Container) MarshalBinary() []byte {
|
|||
}
|
||||
|
||||
// UnmarshalBinary decodes an EOF container.
|
||||
func (c *Container) UnmarshalBinary(b []byte) error {
|
||||
func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error {
|
||||
if !hasEOFMagic(b) {
|
||||
return fmt.Errorf("%w: want %x", ErrInvalidMagic, eofMagic)
|
||||
}
|
||||
|
|
@ -224,7 +224,11 @@ func (c *Container) UnmarshalBinary(b []byte) error {
|
|||
if len(containerSizes) != 0 {
|
||||
expectedSize += sum(containerSizes)
|
||||
}
|
||||
if len(b) < expectedSize-dataSize || len(b) > expectedSize {
|
||||
if len(b) < expectedSize-dataSize {
|
||||
return fmt.Errorf("%w: have %d, want %d", ErrInvalidContainerSize, len(b), expectedSize)
|
||||
}
|
||||
// Only check that the expected size is not exceed on non-initcode
|
||||
if !isInitcode && len(b) > expectedSize {
|
||||
return fmt.Errorf("%w: have %d, want %d", ErrInvalidContainerSize, len(b), expectedSize)
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +282,7 @@ func (c *Container) UnmarshalBinary(b []byte) error {
|
|||
}
|
||||
c := new(Container)
|
||||
end := min(idx+size, len(b))
|
||||
if err := c.UnmarshalBinary(b[idx:end]); err != nil {
|
||||
if err := c.UnmarshalBinary(b[idx:end], isInitcode); err != nil {
|
||||
return fmt.Errorf("%w for section %d", err, i)
|
||||
}
|
||||
container = append(container, c)
|
||||
|
|
@ -291,7 +295,10 @@ func (c *Container) UnmarshalBinary(b []byte) error {
|
|||
}
|
||||
|
||||
// Parse data section.
|
||||
end := min(idx+dataSize, len(b))
|
||||
end := len(b)
|
||||
if !isInitcode {
|
||||
end = min(idx+dataSize, len(b))
|
||||
}
|
||||
c.Data = b[idx:end]
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
if isInitcodeEOF {
|
||||
// If the initcode is EOF, verify it is well-formed.
|
||||
var c Container
|
||||
if err := c.UnmarshalBinary(codeAndHash.code); err != nil {
|
||||
if err := c.UnmarshalBinary(codeAndHash.code, isInitcodeEOF); err != nil {
|
||||
return nil, common.Address{}, gas, fmt.Errorf("%w: %v", ErrInvalidEOFInitcode, err)
|
||||
}
|
||||
if err := c.ValidateCode(evm.interpreter.tableEOF); err != nil {
|
||||
|
|
@ -568,13 +568,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||
// Reject code starting with 0xEF if EIP-3541 is enabled.
|
||||
if err == nil && len(ret) >= 1 && HasEOFByte(ret) {
|
||||
if evm.chainRules.IsShanghai {
|
||||
var c Container
|
||||
if err = c.UnmarshalBinary(ret); err == nil {
|
||||
err = c.ValidateCode(evm.interpreter.tableEOF)
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%w: %v", ErrInvalidEOF, err)
|
||||
}
|
||||
// Don't reject EOF contracts after Shanghai
|
||||
} else if evm.chainRules.IsLondon {
|
||||
err = ErrInvalidCode
|
||||
}
|
||||
|
|
@ -691,7 +685,7 @@ func (evm *EVM) GetVMContext() *tracing.VMContext {
|
|||
func (evm *EVM) parseContainer(b []byte) *Container {
|
||||
if evm.chainRules.IsPrague {
|
||||
var c Container
|
||||
if err := c.UnmarshalBinary(b); err != nil && strings.HasPrefix(err.Error(), "invalid magic") {
|
||||
if err := c.UnmarshalBinary(b, false); err != nil && strings.HasPrefix(err.Error(), "invalid magic") {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
// Code was already validated, so no other errors should be possible.
|
||||
|
|
|
|||
Loading…
Reference in a new issue