github.com/ethereum/go-ethereum@v1.16.1/eth/tracers/internal/util.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package internal
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  
    23  	"github.com/holiman/uint256"
    24  )
    25  
    26  const (
    27  	memoryPadLimit = 1024 * 1024
    28  )
    29  
    30  // GetMemoryCopyPadded returns offset + size as a new slice.
    31  // It zero-pads the slice if it extends beyond memory bounds.
    32  func GetMemoryCopyPadded(m []byte, offset, size int64) ([]byte, error) {
    33  	if offset < 0 || size < 0 {
    34  		return nil, errors.New("offset or size must not be negative")
    35  	}
    36  	length := int64(len(m))
    37  	if offset+size < length { // slice fully inside memory
    38  		return memoryCopy(m, offset, size), nil
    39  	}
    40  	paddingNeeded := offset + size - length
    41  	if paddingNeeded > memoryPadLimit {
    42  		return nil, fmt.Errorf("reached limit for padding memory slice: %d", paddingNeeded)
    43  	}
    44  	cpy := make([]byte, size)
    45  	if overlap := length - offset; overlap > 0 {
    46  		copy(cpy, MemoryPtr(m, offset, overlap))
    47  	}
    48  	return cpy, nil
    49  }
    50  
    51  func memoryCopy(m []byte, offset, size int64) (cpy []byte) {
    52  	if size == 0 {
    53  		return nil
    54  	}
    55  
    56  	if len(m) > int(offset) {
    57  		cpy = make([]byte, size)
    58  		copy(cpy, m[offset:offset+size])
    59  
    60  		return
    61  	}
    62  
    63  	return
    64  }
    65  
    66  // MemoryPtr returns a pointer to a slice of memory.
    67  func MemoryPtr(m []byte, offset, size int64) []byte {
    68  	if size == 0 {
    69  		return nil
    70  	}
    71  
    72  	if len(m) > int(offset) {
    73  		return m[offset : offset+size]
    74  	}
    75  
    76  	return nil
    77  }
    78  
    79  // StackBack returns the n'th item in stack
    80  func StackBack(st []uint256.Int, n int) *uint256.Int {
    81  	return &st[len(st)-n-1]
    82  }