Class: Ethereum::ExternalCall
- Extended by:
- Forwardable
- Defined in:
- lib/ethereum/external_call.rb
Overview
External calls that can be made from inside the VM. To use the EVM with a different blockchain system, database, set parameters for testing, just swap out the functions here.
Instance Method Summary collapse
- #add_suicide(x) ⇒ Object
- #apply_msg(msg, code = nil) ⇒ Object
- #block_coinbase ⇒ Object
- #block_difficulty ⇒ Object
- #block_gas_limit ⇒ Object
- #block_hash(x) ⇒ Object
- #block_number ⇒ Object
- #block_timestamp ⇒ Object
- #create(msg) ⇒ Object
-
#initialize(block, tx) ⇒ ExternalCall
constructor
A new instance of ExternalCall.
- #log(addr, topics, data) ⇒ Object
- #log_storage(x) ⇒ Object
- #post_anti_dos_hardfork ⇒ Object
- #post_homestead_hardfork ⇒ Object
- #post_metropolis_hardfork ⇒ Object
- #tx_gasprice ⇒ Object
- #tx_origin ⇒ Object
Constructor Details
#initialize(block, tx) ⇒ ExternalCall
Returns a new instance of ExternalCall.
20 21 22 23 |
# File 'lib/ethereum/external_call.rb', line 20 def initialize(block, tx) @block = block @tx = tx end |
Instance Method Details
#add_suicide(x) ⇒ Object
29 30 31 |
# File 'lib/ethereum/external_call.rb', line 29 def add_suicide(x) @block.suicides.push x end |
#apply_msg(msg, code = nil) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/ethereum/external_call.rb', line 151 def apply_msg(msg, code=nil) code ||= get_code msg.code_address if log_msg.trace? log_msg.debug "MSG APPLY", sender: Utils.encode_hex(msg.sender), to: Utils.encode_hex(msg.to), gas: msg.gas, value: msg.value, data: Utils.encode_hex(msg.data.extract_all) if log_state.trace? log_state.trace "MSG PRE STATE SENDER", account: Utils.encode_hex(msg.sender), balance: get_balance(msg.sender), state: log_storage(msg.sender) log_state.trace "MSG PRE STATE RECIPIENT", account: Utils.encode_hex(msg.to), balance: get_balance(msg.to), state: log_storage(msg.to) end end # snapshot before execution snapshot = self.snapshot # transfer value if msg.transfers_value unless transfer_value(msg.sender, msg.to, msg.value) log_msg.debug "MSG TRANSFER FAILED", have: get_balance(msg.to), want: msg.value return [1, msg.gas, []] end end # main loop if SpecialContract[msg.code_address] res, gas, dat = SpecialContract[msg.code_address].call(self, msg) else res, gas, dat = VM.execute self, msg, code end if log_msg.trace? log_msg.trace "MSG APPLIED", gas_remained: gas, sender: msg.sender, to: msg.to, data: dat if log_state.trace? log_state.trace "MSG POST STATE SENDER", account: Utils.encode_hex(msg.sender), balance: get_balance(msg.sender), state: log_storage(msg.sender) log_state.trace "MSG POST STATE RECIPIENT", account: Utils.encode_hex(msg.to), balance: get_balance(msg.to), state: log_storage(msg.to) end end if res == 0 log_msg.debug 'REVERTING' revert snapshot end return res, gas, dat end |
#block_coinbase ⇒ Object
47 48 49 |
# File 'lib/ethereum/external_call.rb', line 47 def block_coinbase @block.coinbase end |
#block_difficulty ⇒ Object
59 60 61 |
# File 'lib/ethereum/external_call.rb', line 59 def block_difficulty @block.difficulty end |
#block_gas_limit ⇒ Object
63 64 65 |
# File 'lib/ethereum/external_call.rb', line 63 def block_gas_limit @block.gas_limit end |
#block_hash(x) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/ethereum/external_call.rb', line 33 def block_hash(x) if post_metropolis_hardfork get_storage_data @block.config[:metropolis_blockhash_store], x else d = @block.number - x hash = if d > 0 && d <= 256 @block.get_ancestor_hash d else Constant::BYTE_EMPTY end Utils.big_endian_to_int hash end end |
#block_number ⇒ Object
55 56 57 |
# File 'lib/ethereum/external_call.rb', line 55 def block_number @block.number end |
#block_timestamp ⇒ Object
51 52 53 |
# File 'lib/ethereum/external_call.rb', line 51 def @block. end |
#create(msg) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/ethereum/external_call.rb', line 91 def create(msg) log_msg.debug 'CONTRACT CREATION' sender = Utils.normalize_address(msg.sender, allow_blank: true) code = msg.data.extract_all if post_metropolis_hardfork msg.to = Utils.mk_metropolis_contract_address msg.sender, code if get_code(msg.to) n1 = get_nonce msg.to n2 = n1 >= Constant::TT40 ? (n + 1) : (Utils.big_endian_to_int(msg.to) + 2) set_nonce msg.to, (n2 % Constant::TT160) msg.to = Utils.normalize_address((get_nonce(msg.to) - 1) % Constant::TT160) end else increment_nonce msg.sender if tx_origin != msg.sender nonce = Utils.encode_int(get_nonce(msg.sender) - 1) msg.to = Utils.mk_contract_address sender, nonce end balance = get_balance(msg.to) if balance > 0 set_balance msg.to, balance set_nonce msg.to, 0 set_code msg.to, Constant::BYTE_EMPTY reset_storage msg.to end msg.is_create = true msg.data = VM::CallData.new [], 0, 0 snapshot = self.snapshot res, gas, dat = apply_msg msg, code if res.true? return 1, gas, msg.to if dat.empty? gcost = dat.size * Opcodes::GCONTRACTBYTE if gas >= gcost gas -= gcost else dat = [] log_msg.debug "CONTRACT CREATION OOG", have: gas, want: gcost, block_number: @block.number if post_homestead_hardfork revert snapshot return 0, 0, Constant::BYTE_EMPTY end end set_code msg.to, Utils.int_array_to_bytes(dat) return 1, gas, msg.to else return 0, gas, Constant::BYTE_EMPTY end end |
#log(addr, topics, data) ⇒ Object
67 68 69 |
# File 'lib/ethereum/external_call.rb', line 67 def log(addr, topics, data) @block.add_log Log.new(addr, topics, data) end |
#log_storage(x) ⇒ Object
25 26 27 |
# File 'lib/ethereum/external_call.rb', line 25 def log_storage(x) @block.account_to_dict(x)[:storage] end |
#post_anti_dos_hardfork ⇒ Object
83 84 85 |
# File 'lib/ethereum/external_call.rb', line 83 def post_anti_dos_hardfork @block.number >= @block.config[:anti_dos_fork_blknum] end |
#post_homestead_hardfork ⇒ Object
79 80 81 |
# File 'lib/ethereum/external_call.rb', line 79 def post_homestead_hardfork @block.number >= @block.config[:homestead_fork_blknum] end |
#post_metropolis_hardfork ⇒ Object
87 88 89 |
# File 'lib/ethereum/external_call.rb', line 87 def post_metropolis_hardfork @block.number >= @block.config[:metropolis_fork_blknum] end |
#tx_gasprice ⇒ Object
75 76 77 |
# File 'lib/ethereum/external_call.rb', line 75 def tx_gasprice @tx.gasprice end |
#tx_origin ⇒ Object
71 72 73 |
# File 'lib/ethereum/external_call.rb', line 71 def tx_origin @tx.sender end |