github.com/MetalBlockchain/subnet-evm@v0.4.9/core/vm/memory.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2015 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package vm 28 29 import ( 30 "github.com/holiman/uint256" 31 ) 32 33 // Memory implements a simple memory model for the ethereum virtual machine. 34 type Memory struct { 35 store []byte 36 lastGasCost uint64 37 } 38 39 // NewMemory returns a new memory model. 40 func NewMemory() *Memory { 41 return &Memory{} 42 } 43 44 // Set sets offset + size to value 45 func (m *Memory) Set(offset, size uint64, value []byte) { 46 // It's possible the offset is greater than 0 and size equals 0. This is because 47 // the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP) 48 if size > 0 { 49 // length of store may never be less than offset + size. 50 // The store should be resized PRIOR to setting the memory 51 if offset+size > uint64(len(m.store)) { 52 panic("invalid memory: store empty") 53 } 54 copy(m.store[offset:offset+size], value) 55 } 56 } 57 58 // Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to 59 // 32 bytes. 60 func (m *Memory) Set32(offset uint64, val *uint256.Int) { 61 // length of store may never be less than offset + size. 62 // The store should be resized PRIOR to setting the memory 63 if offset+32 > uint64(len(m.store)) { 64 panic("invalid memory: store empty") 65 } 66 // Fill in relevant bits 67 b32 := val.Bytes32() 68 copy(m.store[offset:], b32[:]) 69 } 70 71 // Resize resizes the memory to size 72 func (m *Memory) Resize(size uint64) { 73 if uint64(m.Len()) < size { 74 m.store = append(m.store, make([]byte, size-uint64(m.Len()))...) 75 } 76 } 77 78 // GetCopy returns offset + size as a new slice 79 func (m *Memory) GetCopy(offset, size int64) (cpy []byte) { 80 if size == 0 { 81 return nil 82 } 83 84 if len(m.store) > int(offset) { 85 cpy = make([]byte, size) 86 copy(cpy, m.store[offset:offset+size]) 87 88 return 89 } 90 91 return 92 } 93 94 // GetPtr returns the offset + size 95 func (m *Memory) GetPtr(offset, size int64) []byte { 96 if size == 0 { 97 return nil 98 } 99 100 if len(m.store) > int(offset) { 101 return m.store[offset : offset+size] 102 } 103 104 return nil 105 } 106 107 // Len returns the length of the backing slice 108 func (m *Memory) Len() int { 109 return len(m.store) 110 } 111 112 // Data returns the backing slice 113 func (m *Memory) Data() []byte { 114 return m.store 115 }