github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/core/vm/contract.go (about) 1 package vm 2 3 import ( 4 "math/big" 5 6 "github.com/neatlab/neatio/utilities/common" 7 ) 8 9 type ContractRef interface { 10 Address() common.Address 11 } 12 13 type AccountRef common.Address 14 15 func (ar AccountRef) Address() common.Address { return (common.Address)(ar) } 16 17 type Contract struct { 18 CallerAddress common.Address 19 caller ContractRef 20 self ContractRef 21 22 jumpdests map[common.Hash]bitvec 23 analysis bitvec 24 25 Code []byte 26 CodeHash common.Hash 27 CodeAddr *common.Address 28 Input []byte 29 30 Gas uint64 31 value *big.Int 32 } 33 34 func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract { 35 c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object} 36 37 if parent, ok := caller.(*Contract); ok { 38 39 c.jumpdests = parent.jumpdests 40 } else { 41 c.jumpdests = make(map[common.Hash]bitvec) 42 } 43 44 c.Gas = gas 45 46 c.value = value 47 48 return c 49 } 50 51 func (c *Contract) validJumpdest(dest *big.Int) bool { 52 udest := dest.Uint64() 53 54 if dest.BitLen() >= 63 || udest >= uint64(len(c.Code)) { 55 return false 56 } 57 58 if OpCode(c.Code[udest]) != JUMPDEST { 59 return false 60 } 61 62 if c.CodeHash != (common.Hash{}) { 63 64 analysis, exist := c.jumpdests[c.CodeHash] 65 if !exist { 66 67 analysis = codeBitmap(c.Code) 68 c.jumpdests[c.CodeHash] = analysis 69 } 70 return analysis.codeSegment(udest) 71 } 72 73 if c.analysis == nil { 74 c.analysis = codeBitmap(c.Code) 75 } 76 return c.analysis.codeSegment(udest) 77 } 78 79 func (c *Contract) AsDelegate() *Contract { 80 81 parent := c.caller.(*Contract) 82 c.CallerAddress = parent.CallerAddress 83 c.value = parent.value 84 85 return c 86 } 87 88 func (c *Contract) GetOp(n uint64) OpCode { 89 return OpCode(c.GetByte(n)) 90 } 91 92 func (c *Contract) GetByte(n uint64) byte { 93 if n < uint64(len(c.Code)) { 94 return c.Code[n] 95 } 96 97 return 0 98 } 99 100 func (c *Contract) Caller() common.Address { 101 return c.CallerAddress 102 } 103 104 func (c *Contract) UseGas(gas uint64) (ok bool) { 105 if c.Gas < gas { 106 return false 107 } 108 c.Gas -= gas 109 return true 110 } 111 112 func (c *Contract) Address() common.Address { 113 return c.self.Address() 114 } 115 116 func (c *Contract) Value() *big.Int { 117 return c.value 118 } 119 120 func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) { 121 c.Code = code 122 c.CodeHash = hash 123 c.CodeAddr = addr 124 } 125 126 func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) { 127 c.Code = codeAndHash.code 128 c.CodeHash = codeAndHash.hash 129 c.CodeAddr = addr 130 }