Skip to content

Commit d5cf7a2

Browse files
committed
Save code section bounds in Contract instead of EOF header
1 parent 4913c1d commit d5cf7a2

File tree

5 files changed

+27
-41
lines changed

5 files changed

+27
-41
lines changed

core/vm/analysis.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,16 @@ func codeBitmap(c *Contract) bitvec {
6565
// The bitmap is 4 bytes longer than necessary, in case the code
6666
// ends with a PUSH32, the algorithm will push zeroes onto the
6767
// bitvector outside the bounds of the actual code.
68-
bits := make(bitvec, c.CodeSize()/8+1+4)
68+
bits := make(bitvec, c.CodeSize/8+1+4)
6969
return codeBitmapInternal(c, bits)
7070
}
7171

7272
// codeBitmapInternal is the internal implementation of codeBitmap.
7373
// It exists for the purpose of being able to run benchmark tests
7474
// without dynamic allocations affecting the results.
7575
func codeBitmapInternal(c *Contract, bits bitvec) bitvec {
76-
codeBegin := c.CodeBeginOffset()
77-
for pc := uint64(0); pc < c.CodeSize(); {
76+
codeBegin := c.CodeBeginOffset
77+
for pc := uint64(0); pc < c.CodeSize; {
7878
op := OpCode(c.Code[codeBegin+pc])
7979
pc++
8080
if int8(op) < int8(PUSH1) { // If not PUSH (the int8(op) > int(PUSH32) is always false).

core/vm/contract.go

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ type Contract struct {
5050
caller ContractRef
5151
self ContractRef
5252

53-
header EOF1Header
53+
CodeBeginOffset uint64 // starting offset of the code section if EOF or 0 if legacy
54+
CodeSize uint64 // size of the code section if EOF or bytecode size if legacy
5455

5556
jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
5657
analysis bitvec // Locally cached result of JUMPDEST analysis
@@ -90,7 +91,7 @@ func (c *Contract) validJumpdest(dest *uint256.Int) bool {
9091
udest, overflow := dest.Uint64WithOverflow()
9192
// PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
9293
// Don't bother checking for JUMPDEST in that case.
93-
if overflow || udest >= c.CodeSize() {
94+
if overflow || udest >= c.CodeSize {
9495
return false
9596
}
9697
// Only JUMPDESTs allowed for destinations
@@ -148,8 +149,8 @@ func (c *Contract) AsDelegate() *Contract {
148149
// GetOp returns the n'th element in the contract's byte array
149150
// n is offset inside code section in case of EOF contract
150151
func (c *Contract) GetOp(n uint64) OpCode {
151-
if n < c.CodeSize() {
152-
return OpCode(c.Code[c.CodeBeginOffset()+n])
152+
if n < c.CodeSize {
153+
return OpCode(c.Code[c.CodeBeginOffset+n])
153154
}
154155

155156
return STOP
@@ -182,34 +183,19 @@ func (c *Contract) Value() *big.Int {
182183
return c.value
183184
}
184185

185-
// IsLegacy returns true if contract is not EOF
186-
func (c *Contract) IsLegacy() bool {
186+
// getCodeBounds returns beginning offset and size of the code section if EOF
187+
// or 0 and bytecode length if legacy
188+
func getCodeBounds(container []byte, header *EOF1Header) (begin uint64, size uint64) {
187189
// EOF1 doesn't allow contracts without code section
188-
return c.header.codeSize == 0
189-
}
190-
191-
// CodeBeginOffset returns starting offset of the code section
192-
func (c *Contract) CodeBeginOffset() uint64 {
193-
if c.IsLegacy() {
194-
return 0
195-
}
196-
return c.header.CodeBeginOffset()
197-
}
198-
199-
// CodeEndOffset returns offset of the code section end
200-
func (c *Contract) CodeEndOffset() uint64 {
201-
if c.IsLegacy() {
202-
return uint64(len(c.Code))
203-
}
204-
return c.header.CodeEndOffset()
205-
}
206-
207-
// CodeSize returns the size of the code (if legacy) or code section (if EOF)
208-
func (c *Contract) CodeSize() uint64 {
209-
if c.IsLegacy() {
210-
return uint64(len(c.Code))
190+
isLegacy := (header.codeSize == 0)
191+
if isLegacy {
192+
begin = 0
193+
size = uint64(len(container))
194+
} else {
195+
begin = header.CodeBeginOffset()
196+
size = uint64(header.codeSize)
211197
}
212-
return uint64(c.header.codeSize)
198+
return
213199
}
214200

215201
// SetCallCode sets the code of the contract and address of the backing data
@@ -219,8 +205,7 @@ func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []by
219205
c.CodeHash = hash
220206
c.CodeAddr = addr
221207

222-
c.header.codeSize = header.codeSize
223-
c.header.dataSize = header.dataSize
208+
c.CodeBeginOffset, c.CodeSize = getCodeBounds(code, header)
224209
}
225210

226211
// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash.
@@ -230,6 +215,5 @@ func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAn
230215
c.CodeHash = codeAndHash.hash
231216
c.CodeAddr = addr
232217

233-
c.header.codeSize = header.codeSize
234-
c.header.dataSize = header.dataSize
218+
c.CodeBeginOffset, c.CodeSize = getCodeBounds(codeAndHash.code, header)
235219
}

core/vm/instructions.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -867,11 +867,11 @@ func makeLog(size int) executionFunc {
867867
// opPush1 is a specialized version of pushN
868868
func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
869869
var (
870-
codeEnd = scope.Contract.CodeEndOffset()
870+
codeEnd = scope.Contract.CodeBeginOffset + scope.Contract.CodeSize
871871
integer = new(uint256.Int)
872872
)
873873
*pc += 1
874-
dataPos := scope.Contract.CodeBeginOffset() + *pc
874+
dataPos := scope.Contract.CodeBeginOffset + *pc
875875
if dataPos < codeEnd {
876876
scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[dataPos])))
877877
} else {
@@ -883,10 +883,10 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
883883
// make push instruction function
884884
func makePush(size uint64, pushByteSize int) executionFunc {
885885
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
886-
codeEnd := int(scope.Contract.CodeEndOffset())
886+
codeEnd := int(scope.Contract.CodeBeginOffset + scope.Contract.CodeSize)
887887

888888
startMin := codeEnd
889-
pcAbsolute := scope.Contract.CodeBeginOffset() + *pc
889+
pcAbsolute := scope.Contract.CodeBeginOffset + *pc
890890
if int(pcAbsolute+1) < startMin {
891891
startMin = int(pcAbsolute + 1)
892892
}

eth/tracers/js/tracer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
7272
if contractCode != nil {
7373
contract.Code = contractCode
7474
}
75+
contract.CodeSize = uint64(len(contract.Code))
7576

7677
tracer.CaptureTxStart(gasLimit)
7778
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)

eth/tracers/logger/logger_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func TestStoreCapture(t *testing.T) {
5959
contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000)
6060
)
6161
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
62+
contract.CodeSize = uint64(len(contract.Code))
6263
var index common.Hash
6364
logger.CaptureStart(env, common.Address{}, contract.Address(), false, nil, 0, nil)
6465
_, err := env.Interpreter().Run(contract, []byte{}, false)

0 commit comments

Comments
 (0)