github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/evm/code.go (about) 1 package evm 2 3 import ( 4 "github.com/hyperledger/burrow/acm" 5 "github.com/hyperledger/burrow/execution/evm/asm" 6 "github.com/tmthrgd/go-bitset" 7 ) 8 9 type Code struct { 10 Bytecode acm.Bytecode 11 OpcodeBitset bitset.Bitset 12 } 13 14 // Build a Code object that includes analysis of which symbols are opcodes versus push data 15 func NewCode(code []byte) *Code { 16 return &Code{ 17 Bytecode: code, 18 OpcodeBitset: opcodeBitset(code), 19 } 20 } 21 22 func (code *Code) Length() uint64 { 23 if code == nil { 24 return 0 25 } 26 return uint64(len(code.Bytecode)) 27 } 28 29 func (code *Code) GetBytecode() acm.Bytecode { 30 if code == nil { 31 return nil 32 } 33 return code.Bytecode 34 } 35 36 func (code *Code) IsOpcode(indexOfSymbolInCode uint64) bool { 37 if code == nil || indexOfSymbolInCode >= uint64(code.OpcodeBitset.Len()) { 38 return false 39 } 40 return code.OpcodeBitset.IsSet(uint(indexOfSymbolInCode)) 41 } 42 43 func (code *Code) IsPushData(indexOfSymbolInCode uint64) bool { 44 return !code.IsOpcode(indexOfSymbolInCode) 45 } 46 47 func (code *Code) GetSymbol(n uint64) asm.OpCode { 48 if code.Length() <= n { 49 return asm.STOP 50 } else { 51 return asm.OpCode(code.Bytecode[n]) 52 } 53 } 54 55 // If code[i] is an opcode (rather than PUSH data) then bitset.IsSet(i) will be true 56 func opcodeBitset(code []byte) bitset.Bitset { 57 bs := bitset.New(uint(len(code))) 58 for i := 0; i < len(code); i++ { 59 bs.Set(uint(i)) 60 symbol := asm.OpCode(code[i]) 61 if symbol >= asm.PUSH1 && symbol <= asm.PUSH32 { 62 i += int(symbol - asm.PUSH1 + 1) 63 } 64 } 65 return bs 66 }