| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | package vm | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-14 11:23:37 +02:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 14:24:40 +02:00
										 |  |  | 	"github.com/holiman/uint256" | 
					
						
							| 
									
										
										
										
											2018-06-14 11:23:37 +02:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-31 17:09:50 +02:00
										 |  |  | // Memory implements a simple memory model for the ethereum virtual machine. | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | type Memory struct { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	store       []byte | 
					
						
							|  |  |  | 	lastGasCost uint64 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-25 18:26:35 +08:00
										 |  |  | // NewMemory returns a new memory model. | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | func NewMemory() *Memory { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return &Memory{} | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Set sets offset + size to value | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | func (m *Memory) Set(offset, size uint64, value []byte) { | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 	// It's possible the offset is greater than 0 and size equals 0. This is because | 
					
						
							|  |  |  | 	// the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP) | 
					
						
							|  |  |  | 	if size > 0 { | 
					
						
							| 
									
										
										
										
											2018-06-14 11:23:37 +02:00
										 |  |  | 		// length of store may never be less than offset + size. | 
					
						
							|  |  |  | 		// The store should be resized PRIOR to setting the memory | 
					
						
							|  |  |  | 		if offset+size > uint64(len(m.store)) { | 
					
						
							|  |  |  | 			panic("invalid memory: store empty") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-05-26 11:13:32 +02:00
										 |  |  | 		copy(m.store[offset:offset+size], value) | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-14 11:23:37 +02:00
										 |  |  | // Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to | 
					
						
							|  |  |  | // 32 bytes. | 
					
						
							| 
									
										
										
										
											2020-06-08 14:24:40 +02:00
										 |  |  | func (m *Memory) Set32(offset uint64, val *uint256.Int) { | 
					
						
							| 
									
										
										
										
											2018-06-14 11:23:37 +02:00
										 |  |  | 	// length of store may never be less than offset + size. | 
					
						
							|  |  |  | 	// The store should be resized PRIOR to setting the memory | 
					
						
							|  |  |  | 	if offset+32 > uint64(len(m.store)) { | 
					
						
							|  |  |  | 		panic("invalid memory: store empty") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Zero the memory area | 
					
						
							|  |  |  | 	copy(m.store[offset:offset+32], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) | 
					
						
							|  |  |  | 	// Fill in relevant bits | 
					
						
							| 
									
										
										
										
											2020-06-08 14:24:40 +02:00
										 |  |  | 	val.WriteToSlice(m.store[offset:]) | 
					
						
							| 
									
										
										
										
											2018-06-14 11:23:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Resize resizes the memory to size | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | func (m *Memory) Resize(size uint64) { | 
					
						
							|  |  |  | 	if uint64(m.Len()) < size { | 
					
						
							|  |  |  | 		m.store = append(m.store, make([]byte, size-uint64(m.Len()))...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Get returns offset + size as a new slice | 
					
						
							| 
									
										
										
										
											2019-11-04 10:31:10 +01:00
										 |  |  | func (m *Memory) GetCopy(offset, size int64) (cpy []byte) { | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 	if size == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 01:27:59 -07:00
										 |  |  | 	if len(m.store) > int(offset) { | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		cpy = make([]byte, size) | 
					
						
							| 
									
										
										
										
											2018-05-02 01:27:59 -07:00
										 |  |  | 		copy(cpy, m.store[offset:offset+size]) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // GetPtr returns the offset + size | 
					
						
							| 
									
										
										
										
											2018-05-02 01:27:59 -07:00
										 |  |  | func (m *Memory) GetPtr(offset, size int64) []byte { | 
					
						
							| 
									
										
										
										
											2015-05-19 17:26:38 +02:00
										 |  |  | 	if size == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 01:27:59 -07:00
										 |  |  | 	if len(m.store) > int(offset) { | 
					
						
							|  |  |  | 		return m.store[offset : offset+size] | 
					
						
							| 
									
										
										
										
											2015-05-19 17:26:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Len returns the length of the backing slice | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | func (m *Memory) Len() int { | 
					
						
							|  |  |  | 	return len(m.store) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Data returns the backing slice | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | func (m *Memory) Data() []byte { | 
					
						
							|  |  |  | 	return m.store | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-26 08:56:25 -04:00
										 |  |  | // Print dumps the content of the memory. | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | func (m *Memory) Print() { | 
					
						
							|  |  |  | 	fmt.Printf("### mem %d bytes ###\n", len(m.store)) | 
					
						
							|  |  |  | 	if len(m.store) > 0 { | 
					
						
							|  |  |  | 		addr := 0 | 
					
						
							|  |  |  | 		for i := 0; i+32 <= len(m.store); i += 32 { | 
					
						
							|  |  |  | 			fmt.Printf("%03d: % x\n", addr, m.store[i:i+32]) | 
					
						
							|  |  |  | 			addr++ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		fmt.Println("-- empty --") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fmt.Println("####################") | 
					
						
							|  |  |  | } |