diff options
author | Determinant <[email protected]> | 2020-09-15 23:55:34 -0400 |
---|---|---|
committer | Determinant <[email protected]> | 2020-09-15 23:55:34 -0400 |
commit | 78745551c077bf54151202138c2629f288769561 (patch) | |
tree | 2b628e99fd110617089778fa91235ecd2888f4ef /core/vm/contract.go | |
parent | 7d1388c743b4ec8f4a86bea95bfada785dee83f7 (diff) |
WIP: geth-tavum
Diffstat (limited to 'core/vm/contract.go')
-rw-r--r-- | core/vm/contract.go | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/core/vm/contract.go b/core/vm/contract.go index ed17402..915193d 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -19,7 +19,8 @@ package vm import ( "math/big" - "github.com/ava-labs/go-ethereum/common" + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" ) // ContractRef is a reference to the contract's backing object @@ -81,18 +82,43 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uin return c } -func (c *Contract) validJumpdest(dest *big.Int) bool { - udest := dest.Uint64() +func (c *Contract) validJumpdest(dest *uint256.Int) bool { + udest, overflow := dest.Uint64WithOverflow() // PC cannot go beyond len(code) and certainly can't be bigger than 63bits. // Don't bother checking for JUMPDEST in that case. - if dest.BitLen() >= 63 || udest >= uint64(len(c.Code)) { + if overflow || udest >= uint64(len(c.Code)) { return false } // Only JUMPDESTs allowed for destinations if OpCode(c.Code[udest]) != JUMPDEST { return false } + return c.isCode(udest) +} + +func (c *Contract) validJumpSubdest(udest uint64) bool { + // PC cannot go beyond len(code) and certainly can't be bigger than 63 bits. + // Don't bother checking for BEGINSUB in that case. + if int64(udest) < 0 || udest >= uint64(len(c.Code)) { + return false + } + // Only BEGINSUBs allowed for destinations + if OpCode(c.Code[udest]) != BEGINSUB { + return false + } + return c.isCode(udest) +} + +// isCode returns true if the provided PC location is an actual opcode, as +// opposed to a data-segment following a PUSHN operation. +func (c *Contract) isCode(udest uint64) bool { + // Do we already have an analysis laying around? + if c.analysis != nil { + return c.analysis.codeSegment(udest) + } // Do we have a contract hash already? + // If we do have a hash, that means it's a 'regular' contract. For regular + // contracts ( not temporary initcode), we store the analysis in a map if c.CodeHash != (common.Hash{}) { // Does parent context have the analysis? analysis, exist := c.jumpdests[c.CodeHash] @@ -102,6 +128,8 @@ func (c *Contract) validJumpdest(dest *big.Int) bool { analysis = codeBitmap(c.Code) c.jumpdests[c.CodeHash] = analysis } + // Also stash it in current contract for faster access + c.analysis = analysis return analysis.codeSegment(udest) } // We don't have the code hash, most likely a piece of initcode not already |