def apply_block(state, block): # Pre-processing and verification snapshot = state.snapshot() cs = get_consensus_strategy(state.config) try: # Start a new block context cs.initialize(state, block) # Basic validation assert validate_header(state, block.header) assert cs.check_seal(state, block.header) assert cs.validate_uncles(state, block) assert validate_transaction_tree(state, block) # Process transactions for tx in block.transactions: apply_transaction(state, tx) # Finalize (incl paying block rewards) cs.finalize(state, block) # Verify state root, tx list root, receipt root assert verify_execution_results(state, block) # Post-finalize (ie. add the block header to the state for now) post_finalize(state, block) except (ValueError, AssertionError) as e: state.revert(snapshot) raise e return state
def test_transaction(db): k, v, k2, v2 = accounts() chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1) blk = mine_next_block(chain) tx = get_transaction() assert tx not in blk.transactions messages.apply_transaction(chain.state, tx) assert chain.state.get_balance(v) == utils.denoms.finney * 990 assert chain.state.get_balance(v2) == utils.denoms.finney * 10
def get_receipts(self, block): # Receipts are no longer stored in the database, so need to generate # them on the fly here. temp_state = self.chain.mk_poststate_of_blockhash( block.header.prevhash) initialize(temp_state, block) for tx in block.transactions: apply_transaction(temp_state, tx) return temp_state.receipts
def inject_tx(txhex): tx = rlp.decode(ethereum_utils.decode_hex(txhex[2:]), transactions.Transaction) chain.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) chain.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) messages.apply_transaction(chain.head_state, tx) chain.block.transactions.append(tx) contract_address = ethereum_utils.sha3(rlp.encode([tx.sender, 0]))[12:] assert chain.head_state.get_code(contract_address) chain.mine(1) return contract_address
def direct_tx(self, transaction): self.last_tx, self.last_sender = transaction, None success, output = apply_transaction(self.head_state, transaction) self.block.transactions.append(transaction) if not success: raise TransactionFailed() return output
def compute_state_test_unit(state, txdata, konfig): state.env.config = konfig s = state.snapshot() try: # Create the transaction tx = transactions.Transaction( nonce=parse_int_or_hex(txdata['nonce'] or b"0"), gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"), startgas=parse_int_or_hex(txdata['gasLimit'] or b"0"), to=decode_hex(remove_0x_head(txdata['to'])), value=parse_int_or_hex(txdata['value'] or b"0"), data=decode_hex(remove_0x_head(txdata['data']))) if 'secretKey' in txdata: tx.sign(decode_hex(remove_0x_head(txdata['secretKey']))) else: tx.v = parse_int_or_hex(txdata['v']) # Run it prev = state.to_dict() print("calling apply_transaction") success, output = apply_transaction(state, tx) print("Applied tx") except InvalidTransaction as e: print("Exception: %r" % e) success, output = False, b'' state.commit() post = state.to_dict() output_decl = { "hash": '0x' + encode_hex(state.trie.root_hash), #"indexes": indices, #"diff": mk_state_diff(prev, post) } state.revert(s) return output_decl
def make_casper_genesis(alloc, epoch_length, withdrawal_delay, base_interest_factor, base_penalty_factor): # The Casper-specific config declaration casper_config = copy.deepcopy(config.default_config) casper_config['HOMESTEAD_FORK_BLKNUM'] = 0 casper_config['ANTI_DOS_FORK_BLKNUM'] = 0 casper_config['CLEARING_FORK_BLKNUM'] = 0 casper_config['CONSENSUS_STRATEGY'] = 'hybrid_casper' casper_config['NULL_SENDER'] = utils.sha3('NULL_SENDER') casper_config['EPOCH_LENGTH'] = epoch_length casper_config['WITHDRAWAL_DELAY'] = withdrawal_delay casper_config['OWNER'] = a0 casper_config['BASE_INTEREST_FACTOR'] = base_interest_factor casper_config['BASE_PENALTY_FACTOR'] = base_penalty_factor # Get initialization txs init_txs, casper_address = mk_initializers(casper_config, casper_config['NULL_SENDER']) casper_config['CASPER_ADDRESS'] = casper_address # Create state and apply required state_transitions for initializing Casper state = genesis_helpers.mk_basic_state( alloc, None, env=config.Env(config=casper_config)) state.gas_limit = 10**8 for tx in init_txs: state.set_balance(utils.privtoaddr(casper_config['NULL_SENDER']), 15**18) success, output = apply_transaction(state, tx) assert success state.gas_used = 0 state.set_balance(utils.privtoaddr(casper_config['NULL_SENDER']), 0) consensus.initialize(state) state.commit() return state
def compute_state_test_unit(state, txdata, indices, konfig): state.env.config = konfig s = state.snapshot() try: # Create the transaction tx = transactions.Transaction( nonce=parse_int_or_hex(txdata['nonce'] or b"0"), gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"), startgas=parse_int_or_hex( txdata['gasLimit'][indices["gas"]] or b"0"), to=decode_hex(remove_0x_head(txdata['to'])), value=parse_int_or_hex(txdata['value'][indices["value"]] or b"0"), data=decode_hex(remove_0x_head(txdata['data'][indices["data"]]))) if 'secretKey' in txdata: tx.sign(decode_hex(remove_0x_head(txdata['secretKey']))) else: tx.v = parse_int_or_hex(txdata['v']) # Run it prev = state.to_dict() success, output = apply_transaction(state, tx) print("Applied tx") except InvalidTransaction as e: print("Exception: %r" % e) success, output = False, b'' # state.set_code('0x3e180b1862f9d158abb5e519a6d8605540c23682', b'') state.commit() post = state.to_dict() # print('pozt', post) output_decl = { "hash": '0x' + encode_hex(state.trie.root_hash), "indexes": indices, "diff": mk_state_diff(prev, post) } state.revert(s) return output_decl
def tx(self, sender=k0, to=b'\x00' * 20, value=0, data=b'', startgas=STARTGAS, gasprice=GASPRICE): sender_addr = privtoaddr(sender) transaction = Transaction(self.state.get_nonce(sender_addr), gasprice, startgas, to, value, data).sign(sender) success, output = apply_transaction(self.state, transaction) if not success: raise TransactionFailed() return output
def add_transactions(state, block, txqueue, min_gasprice=0): if not txqueue: return pre_txs = len(block.transactions) log.info('Adding transactions, %d in txqueue, %d dunkles' % (len(txqueue.txs), pre_txs)) while True: tx = txqueue.pop_transaction(max_gas=state.gas_limit - state.gas_used, min_gasprice=min_gasprice) if tx is None: break try: apply_transaction(state, tx) block.transactions.append(tx) except (InsufficientBalance, BlockGasLimitReached, InsufficientStartGas, InvalidNonce, UnsignedTransaction) as e: pass log.info('Added %d transactions' % (len(block.transactions) - pre_txs))
def direct_tx(self, transaction): self.last_tx = transaction if self.last_sender is not None and privtoaddr( self.last_sender) != transaction.sender: self.last_sender = None success, output = apply_transaction(self.head_state, transaction) self.block.transactions.append(transaction) if not success: raise TransactionFailed() return output
def call(this, to, value=0, data='', sender=None, startgas=25000, gasprice=60 * denoms.shannon): sender = normalize_address(sender or this.coinbase) to = normalize_address(to, allow_blank=True) block = this.head_candidate state_root_before = block.state_root assert block.prevhash == this.chain.head_hash # rebuild block state before finalization test_state = this.chain.mk_poststate_of_blockhash( block.prevhash) initialize(test_state, block) for tx in block.transactions: success, _ = apply_transaction(test_state, tx) assert success # Need this because otherwise the Transaction.network_id # @property returns 0, which causes the tx to fail validation. class MockedTx(Transaction): network_id = None # apply transaction nonce = test_state.get_nonce(sender) tx = MockedTx(nonce, gasprice, startgas, to, value, data) tx.sender = sender try: success, output = apply_transaction(test_state, tx) except InvalidTransaction as e: log.debug("error applying tx in Eth.call", exc=e) success = False assert block.state_root == state_root_before if success: return output else: return False
def apply_shard_transaction(mainchain_state, shard_state, shard_id, tx): """Apply shard transactions, including both receipt-consuming and normal transactions. """ if ((mainchain_state is not None) and (shard_id is not None) and is_valid_receipt_consuming_tx( mainchain_state, shard_state, shard_id, tx)): success, output = send_msg_transfer_value(mainchain_state, shard_state, shard_id, tx) else: success, output = apply_transaction(shard_state, tx) return success, output
def broadcast_deposit(self): if not self.valcode_tx or not self.deposit_tx: # Generate transactions valcode_tx = self.mk_validation_code_tx() valcode_addr = utils.mk_contract_address(self.coinbase, self.nonce - 1) deposit_tx = self.mk_deposit_tx(3 * 10**18, valcode_addr) # Verify the transactions pass temp_state = self.chain.state.ephemeral_clone() valcode_success, o1 = apply_transaction(temp_state, valcode_tx) deposit_success, o2 = apply_transaction(temp_state, deposit_tx) if not (valcode_success and deposit_success): self.nonce = self.chain.state.get_nonce(self.coinbase) raise Exception('Valcode tx or deposit tx failed') self.valcode_tx = valcode_tx log.info('Valcode Tx generated: {}'.format(str(valcode_tx))) self.valcode_addr = valcode_addr self.deposit_tx = deposit_tx log.info('Deposit Tx generated: {}'.format(str(deposit_tx))) self.broadcast_transaction(self.valcode_tx) self.broadcast_transaction(self.deposit_tx)
def broadcast_logout(self, login_logout_flag): epoch = self.chain.state.block_number // self.epoch_length # Generage the message logout_msg = casper_utils.mk_logout( self.get_validator_index(self.chain.state), epoch, self.key) # Generate transactions logout_tx = self.mk_logout(logout_msg) # Verify the transactions pass temp_state = self.chain.state.ephemeral_clone() logout_success, o1 = apply_transaction(temp_state, logout_tx) if not logout_success: self.nonce = self.chain.state.get_nonce(self.coinbase) raise Exception('Valcode tx or deposit tx failed') log.info('Login/logout Tx generated: {}'.format(str(logout_tx))) self.broadcast_transaction(logout_tx)
def direct_tx(self, transaction, shard_id=None): if shard_id is None: self.last_tx, self.last_sender = transaction, None success, output = apply_transaction(self.head_state, transaction) self.block.transactions.append(transaction) else: self.shard_last_tx[shard_id], self.shard_last_sender[ shard_id] = transaction, None assert self.chain.has_shard(shard_id) success, output = apply_shard_transaction( self.head_state, self.shard_head_state[shard_id], shard_id, transaction) self.collation[shard_id].transactions.append(transaction) if not success: raise TransactionFailed() return output
def initialize(state, block=None): config = state.config state.txindex = 0 state.gas_used = 0 state.bloom = 0 state.receipts = [] if block is not None: update_block_env_variables(state, block) # Initalize the next epoch in the Casper contract if state.block_number % state.config[ 'EPOCH_LENGTH'] == 0 and state.block_number != 0: key, account = state.config['NULL_SENDER'], privtoaddr( state.config['NULL_SENDER']) data = casper_utils.casper_translator.encode( 'initialize_epoch', [state.block_number // state.config['EPOCH_LENGTH']]) transaction = transactions.Transaction(state.get_nonce(account), 0, 3141592, state.config['CASPER_ADDRESS'], 0, data).sign(key) success, output = apply_transaction(state, transaction) assert success if state.is_DAO(at_fork_height=True): for acct in state.config['CHILD_DAO_LIST']: state.transfer_value(acct, state.config['DAO_WITHDRAWER'], state.get_balance(acct)) if state.is_METROPOLIS(at_fork_height=True): state.set_code( utils.normalize_address(config["METROPOLIS_STATEROOT_STORE"]), config["METROPOLIS_GETTER_CODE"]) state.set_code( utils.normalize_address(config["METROPOLIS_BLOCKHASH_STORE"]), config["METROPOLIS_GETTER_CODE"])
def conBench(state, exek, curr_row, _nonce, index): ################################### Start contracts' benchmarking ################################### Ugas = 0 exTime = [] gasUsed = [] minTime = 0 maxTime = 0 avgTime = 0 medTime = 0 stdevTime = 0 CITime = 0 type = "Execution" #### prepare creation & execution bytecodes for benchmarking #### if worksheet.cell_value(curr_row, 5) != "": creation_bytecode = worksheet.cell_value( curr_row, 4) + worksheet.cell_value(curr_row, 5) else: creation_bytecode = worksheet.cell_value(curr_row, 4) if worksheet.cell_value(curr_row, 7) != "": execution_bytecode = worksheet.cell_value( curr_row, 6) + worksheet.cell_value(curr_row, 7) else: execution_bytecode = worksheet.cell_value(curr_row, 6) ##### if transaction is to invoke a contract, we first need to deploy the contract ##### if creation_bytecode != "Contract Creation": try: tx1 = transactions.Transaction(nonce=_nonce, gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to="", value=0, data=codecs.decode( creation_bytecode[2:], 'hex'), r=1, s=2, v=27) tx1._sender = exek['origin'] _nonce = _nonce + 1 success, address, t, g = pb.apply_transaction(state, tx1) if g > blockLimit: success = 0 address = "" except Exception: success = 0 address = "" pass elif creation_bytecode == "Contract Creation": # if transaction is to create a contract, make address empty and pass for next test type = "Creation" address = "" success = 1 #################### test transaction execution ######################## ################ test if execution works or not, before conducting the benchmark ####################### if success == 1: # if contract was crteated successfully try: tx2 = transactions.Transaction(nonce=_nonce, gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to=address, value=0, data=codecs.decode( execution_bytecode[2:], 'hex'), r=1, s=2, v=27) tx2._sender = exek['origin'] success1, output1, t, g = pb.apply_transaction(state, tx2) if g > blockLimit: success1 = 0 except Exception: success1 = 0 pass _nonce = _nonce + 1 #################### transactions' benchmarking ######################## if success1 == 1: # if contract was created successfully or if transaction is to create a new contract if type == "creation": address = "" attempts = 0 while attempts < 10: # attempt the benchmark up to 10 times if confidence interval is more than 2% of the average value exTime = [] gasUsed = [] for i in range(num_runs): try: txInvoke = transactions.Transaction( nonce=_nonce, gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to=address, value=0, data=codecs.decode(execution_bytecode[2:], 'hex'), r=1, s=2, v=27) txInvoke._sender = exek['origin'] success2, output2, time, gas = pb.apply_transaction( state, txInvoke) if gas > blockLimit: gas = 0 time = 0 except Exception: time = 0 gas = 0 pass _nonce = _nonce + 1 exTime.append(time) gasUsed.append(gas) minTime = round(min(exTime), 0) maxTime = round(max(exTime), 0) avgTime = round(np.mean(exTime), 0) medTime = round(statistics.median(exTime), 0) stdevTime = round(statistics.stdev(exTime), 0) if min(gasUsed) == max(gasUsed): Ugas = max(gasUsed) else: Ugas = 0 CITime = mean_confidence_interval(exTime) if Ugas != 0 and (CITime / avgTime * 100) > 2.0: attempts += 1 else: break result[index][0] = worksheet.cell_value(curr_row, 1) result[index][1] = type result[index][2] = Ugas result[index][3] = minTime result[index][4] = maxTime result[index][5] = avgTime result[index][6] = medTime result[index][7] = stdevTime result[index][8] = CITime