def _make_transaction(self, src_priv_key, dst_address, value, data, use_increased_gas_price): src_address = b2h(utils.privtoaddr(src_priv_key)) nonce_rs = self._get_num_transactions(src_address) nonce = int(nonce_rs, base=16) log.debug(f"Using nonce {nonce}.") gas_price_rs = self._get_gas_price_in_wei() gas_price = int(gas_price_rs, base=16) if use_increased_gas_price: log.debug(f"Using increased gas price.") gas_price = int(gas_price * INCREASED_GAS_PRICE_FACTOR) log.debug(f"gas price is {gas_price}") start_gas_rs = self._eval_startgas(src=src_address, dst=dst_address, value=value, data=b2h(data), gas_price=gas_price_rs) start_gas = int(start_gas_rs, base=16) + ADDITIONAL_START_GAS_TO_BE_ON_THE_SAFE_SIDE log.debug(f"Estimated start gas is {start_gas}") tx = transactions.Transaction(nonce, gas_price, start_gas, dst_address, value, data).sign(src_priv_key) tx_hex = b2h(rlp.encode(tx)) tx_hash = b2h(tx.hash) params = ["0x" + tx_hex] return_value = self._json_call("eth_sendRawTransaction", params) if return_value == "0x0000000000000000000000000000000000000000000000000000000000000000": print("Transaction failed") return return_value return return_value
def trace(code, calldata=""): log_handlers = [ "eth.vm.op", "eth.vm.op.stack", "eth.vm.op.memory", "eth.vm.op.storage", ] output = StringIO() stream_handler = StreamHandler(output) for handler in log_handlers: log_vm_op = get_logger(handler) log_vm_op.setLevel("TRACE") log_vm_op.addHandler(stream_handler) addr = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF01234567") state = State() ext = messages.VMExt(state, transactions.Transaction(0, 0, 21000, addr, 0, addr)) message = vm.Message(addr, addr, 0, 21000, calldata) vm.vm_execute(ext, message, util.safe_decode(code)) stream_handler.flush() ret = output.getvalue() lines = ret.split("\n") state_trace = [] for line in lines: m = re.search(r"pc=b\'(\d+)\'.*op=([A-Z0-9]+)", line) if m: pc = m.group(1) op = m.group(2) m = re.match(r".*stack=(\[.*?\])", line) if m: stackitems = re.findall(r"b\'(\d+)\'", m.group(1)) stack = "[" if len(stackitems): for i in range(0, len(stackitems) - 1): stack += hex(int(stackitems[i])) + ", " stack += hex(int(stackitems[-1])) stack += "]" else: stack = "[]" if re.match(r"^PUSH.*", op): val = re.search(r"pushvalue=(\d+)", line).group(1) pushvalue = hex(int(val)) state_trace.append({ "pc": pc, "op": op, "stack": stack, "pushvalue": pushvalue }) else: state_trace.append({"pc": pc, "op": op, "stack": stack}) return state_trace
def make_trustless_multisend(payouts, remainder, gasprice=20 * 10**9): """ Creates a transaction that trustlessly sends money to multiple recipients, and any left over (unsendable) funds to the address specified in remainder. Arguments: payouts: A list of (address, value tuples) remainder: An address in hex form to send any unsendable balance to gasprice: The gas price, in wei Returns: A transaction object that accomplishes the multisend. """ ct = abi.ContractTranslator(multisend_abi) addresses = [utils.normalize_address(addr) for addr, value in payouts] values = [value for addr, value in payouts] cdata = ct.encode_constructor_arguments([addresses, values, utils.normalize_address(remainder)]) tx = transactions.Transaction( 0, gasprice, 50000 + len(addresses) * 35000, '', sum(values), multisend_contract + cdata) tx.v = 27 tx.r = 0x0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0 tx.s = 0x0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0DA0 while True: try: tx.sender return tx except Exception, e: # Failed to generate public key tx.r += 1
def make_transaction(src_priv_key, dst_address, value, data): src_address = b2h(utils.privtoaddr(src_priv_key)) nonce = get_num_transactions(src_address) gas_price = get_gas_price_in_wei() data_as_string = b2h(data) start_gas = eval_startgas(src_address, dst_address, value, data_as_string, gas_price) nonce = int(nonce, 16) gas_price = int(gas_price, 16) start_gas = int(start_gas, 16) + 100000 tx = transactions.Transaction(nonce, gas_price, start_gas, dst_address, value, data).sign(src_priv_key) tx_hex = b2h(rlp.encode(tx)) tx_hash = b2h(tx.hash) if use_ether_scan: params = [{"hex": "0x" + tx_hex}] else: params = ["0x" + tx_hex] return_value = json_call("eth_sendRawTransaction", params) if return_value == "0x0000000000000000000000000000000000000000000000000000000000000000": print "Transaction failed" return False wait_for_confirmation(tx_hash) return return_value
def send_transactions(self, seed, outs_percent, n_array) -> List[str]: if isinstance(outs_percent, dict): outs_percent = [(key, value) for (key, value) in outs_percent.items()] input_wallets = self._get_input_wallets(seed, n_array) tx_intents = self._transaction_distribution.get_transaction_intents(input_wallets, outs_percent) # print(f"send_transactions\n: {tx_intents}") gas_price = self.etherscan.gas_price estimated_gas = 21000 txs = [] nonce_dict = self._get_nonce_dict(input_wallets) for intent in tx_intents: intent: TransactionIntent = intent in_wallet = intent.in_wallet nonce = nonce_dict[in_wallet.address] print(f"nonce: {nonce}") fee = gas_price * estimated_gas in_amount = intent.amount - fee if in_amount <= 0: print(f"Insufficient funds: required: {fee}, found: {intent.amount}") continue tx = transactions.Transaction(nonce=nonce, to=intent.out_address[2:], value=intent.amount - fee, gasprice=gas_price, startgas=estimated_gas, data=b"") signed = tx.sign(in_wallet.priv, self.etherscan.chain_id) unencoded_tx = rlp.encode(signed) signed_tx = "0x" + unencoded_tx.hex() tx_hash = self.etherscan.send_transaction(signed_tx) txs.append(tx_hash) nonce_dict[in_wallet.address] += 1 return txs
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 trace(code, address = "", calldata = ""): logHandlers = ['eth.vm.op', 'eth.vm.op.stack', 'eth.vm.op.memory', 'eth.vm.op.storage'] output = StringIO() streamHandler = StreamHandler(output) for handler in logHandlers: log_vm_op = get_logger(handler) log_vm_op.setLevel("TRACE") log_vm_op.addHandler(streamHandler) addr_from = codecs.decode('0123456789ABCDEF0123456789ABCDEF01234567', 'hex_codec') addr_to = safe_decode(address) state = State() ext = messages.VMExt(state, transactions.Transaction(0, 0, 21000, addr_from, 0, addr_to)) message = vm.Message(addr_from, addr_to, 0, 21000, calldata, code_address=addr_to) res, gas, dat = vm.vm_execute(ext, message, code) streamHandler.flush() # print(output.getvalue()) ret = output.getvalue() return ret
def post(self): req = request.get_json() source = req['source'] dest = req.get('dest', '') value = req.get('value', 0) data = binascii.unhexlify(req.get('data', '')) network = req.get('network', '') gasprice = req.get('gas_price', 0) print('signer network', network, flush=True) if network in ['ETHEREUM_MAINNET', 'ETHEREUM_ROPSTEN' ] and gasprice == 0: print('eth', flush=True) gasprice = 20 * 10**9 if network in ['RSK_MAINNET', 'RSK_TESTNET']: print('rsk', flush=True) gasprice = 1 * 10**9 if network == '': gasprice = 1 * 10**9 gaslimit = req.get('gaslimit', 10**6) # 10 ** 6 is suitable for deploy account = db.session.query(Account).filter( Account.addr == source).limit(1).with_for_update().one() priv = binascii.unhexlify(account.priv) nonce = req['nonce'] reset_curve_to_eth() tx = transactions.Transaction(nonce, gasprice, gaslimit, dest, value, data).sign(priv) raw_tx = binascii.hexlify(rlp.encode(tx)) return {'result': raw_tx.decode()}
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 test_dishonest_party(self): ADDR_A = rec_hex(t.a1) PKEY_A = t.k1 ADDR_B = rec_hex(t.a2) PKEY_B = t.k2 DAPP_ADDRESS = "0xDEADbEeF000000000000000000000000DeaDbeEf" fake_tx_commit_object = transactions.Transaction( 0, OURGASPRICE, OURGASLIMIT, ADDR_B, (UNLOCK_AMOUNT + extraTransactionFees), b'').sign(PKEY_A) self.chain.direct_tx(fake_tx_commit_object) self.chain.mine(1) witness = "0x03" fakecommitBlockNumber, fakecommitBlockIndex = self.chain.chain.get_tx_position( fake_tx_commit_object) print("tx block number {} and tx block index {}".format( fakecommitBlockNumber, fakecommitBlockIndex)) def _listener(log): print('LOG:', ) print('LOG:', log) print(rec_hex(log['data'])) self.chain.head_state.log_listeners.append(_listener) self.verifier_contract.reveal(fakecommitBlockNumber, fakecommitBlockIndex, DAPP_ADDRESS, UNLOCK_AMOUNT, b'', rec_bin(witness), OURGASPRICE, OURGASLIMIT, sender=PKEY_A, to=self.verifier_contract.address, value=1009, gasprice=OURGASPRICE, startgas=OURGASLIMIT) self.chain.mine(1) #revealBlockNumber, revealBlockIndex = self.chain.chain.get_tx_position() #print("reveal block number {} and reveal block index {}".format(revealBlockNumber, revealBlockIndex)) def aux(x): return x.to_bytes(32, byteorder='big') computedfakecommit = (rec_bin(ADDR_A) + self.verifier_contract.address + aux(UNLOCK_AMOUNT) + b'' + rec_bin(witness) + aux(OURGASPRICE) + aux(OURGASLIMIT)) sessionID = sha3_256(computedfakecommit) print(rec_hex(sessionID)) revealTestSession = self.verifier_contract.getSession( rec_bin( "000000000000000000000000000000000000000000000000128dfa6a90b28000" )) print(revealTestSession)
def apply_message(state, msg=None, **kwargs): if msg is None: msg = vm.Message(**kwargs) else: assert not kwargs ext = VMExt(state, transactions.Transaction(0, 0, 21000, b'', 0, b'')) result, gas_remained, data = apply_msg(ext, msg) return bytearray_to_bytestr(data) if result else None
def get_transaction(gasprice=0, nonce=0): k, v, k2, v2 = accounts() tx = transactions.Transaction(nonce, gasprice, startgas=100000, to=v2, value=utils.denoms.finney * 10, data=b'').sign(k) return tx
def mk_transaction(self, to=b'\x00' * 20, value=0, data=b'', gasprice=tester.GASPRICE, startgas=tester.STARTGAS): tx = transactions.Transaction(self.nonce, gasprice, startgas, to, value, data).sign(self.key) self.nonce += 1 return tx
def sign_transaction(nonce, abi, priv_key, gas, to): # TODO send gas price from bygone?! gasprice = 18000000000 # [nonce, gasprice, startgas, to, value, data, v, r, s] tx = transactions.Transaction(nonce, gasprice, gas, to, 5, abi) signed_tx = tx.sign(priv_key) ret = rlp.encode(signed_tx).hex() return ret
def getIntrinsicGas(test_tx): tx = transactions.Transaction( nonce=parse_int_or_hex(test_tx['nonce'] or b"0"), gasprice=parse_int_or_hex(test_tx['gasPrice'] or b"0"), startgas=parse_int_or_hex(test_tx['gasLimit'] or b"0"), to=decode_hex(remove_0x_head(test_tx['to'])), value=parse_int_or_hex(test_tx['value'] or b"0"), data=decode_hex(remove_0x_head(test_tx['data']))) return tx.intrinsic_gas_used
def getIntrinsicGas(data): import ethereum.transactions as transactions tx = transactions.Transaction(nonce=0, gasprice=0, startgas=0, to=b"", value=0, data=decode_hex(remove_0x_head(data))) return tx.intrinsic_gas_used
def generateInvalidUnlockTx(self, userAddress, contractAddress, maliciousAddress): commit, witness, R, S = generate_submarine_commit._generateRS( normalize_address(rec_hex(userAddress)), normalize_address(rec_hex(contractAddress)), UNLOCK_AMOUNT, b'', OURGASPRICE, OURGASLIMIT) unlockFunctionSelector = b"\xec\x9b\x5b\x3a" submarineData = unlockFunctionSelector + commit # need the unsigned TX hash for ECRecover unlock_tx_unsigned_object = transactions.UnsignedTransaction( 0, # nonce; OURGASPRICE, # gasprice OURGASLIMIT, # startgas normalize_address(maliciousAddress), # to addr UNLOCK_AMOUNT, # value submarineData, # data ) unlock_tx_unsigned_hash = sha3( rlp.encode(unlock_tx_unsigned_object, transactions.UnsignedTransaction)) unlock_tx_object = transactions.Transaction( 0, # nonce; OURGASPRICE, # gasprice OURGASLIMIT, # startgas normalize_address(maliciousAddress), # to addr UNLOCK_AMOUNT, # value submarineData, # data 27, # v R, # r S # s ) try: pub = ecrecover_to_pub(unlock_tx_unsigned_hash, 27, R, S) if pub == b"\x00" * 64: log.info("Address no good, retrying") return self.generateInvalidUnlockTx(userAddress, contractAddress, maliciousAddress) else: commit_addr = sha3(pub)[-20:] log.info("Fake Unlock TX Dict: {}".format( unlock_tx_unsigned_object.as_dict())) log.info("Fake Unlock TX Commit B: {}".format(commit_addr)) return unlock_tx_object, unlock_tx_unsigned_object, commit_addr, commit, witness except (ValueError, InvalidTransaction) as e: if isinstance(e, ValueError) and "VRS" not in str(e): raise log.info("Address no good (%s), retrying" % e) return self.generateInvalidUnlockTx(userAddress, contractAddress, maliciousAddress)
def getTxSender(test_tx): tx = transactions.Transaction( nonce=parse_int_or_hex(test_tx['nonce'] or b"0"), gasprice=parse_int_or_hex(test_tx['gasPrice'] or b"0"), startgas=parse_int_or_hex(test_tx['gasLimit'] or b"0"), to=decode_hex(remove_0x_head(test_tx['to'])), value=parse_int_or_hex(test_tx['value'] or b"0"), data=decode_hex(remove_0x_head(test_tx['data']))) if 'secretKey' in test_tx: tx.sign(decode_hex(remove_0x_head(test_tx['secretKey']))) return encode_hex(tx.sender)
def ethereum(): form = EthForm() if form.submit2.data and form.validate(): api = Savoir(current_app.config['CHAIN_RPC_USER'], current_app.config['CHAIN_RPC_PASSWORD'], current_app.config['CHAIN_RPC_HOST'], current_app.config['CHAIN_RPC_PORT'], current_app.config['CHAIN_NAME']) url = form.url.data if not url: url = current_app.config['GETH_URL'] w3 = Web3(HTTPProvider(url)) if current_app.config['GETH_MODE'] == 'dev': w3.middleware_stack.inject(geth_poa_middleware, layer=0) gasPrice = 2000000000 else: gasPrice = w3.eth.gasPrice # gasPrice = w3.eth.generateGasPrice() privkey = current_app.config['ETH_KEY'] account = w3.toChecksumAddress(utils.privtoaddr(privkey)) block_hash = api.getblockchaininfo().get('bestblockhash') nonce = w3.eth.getTransactionCount(account) startgas = round(w3.eth.estimateGas({'data': block_hash})) to = account value = 0 balance = w3.eth.getBalance(account) cost = startgas * gasPrice if cost > balance: flash('Your account has insufficient funds!') return redirect(url_for('main.ethereum')) tx = transactions.Transaction(nonce, gasPrice, startgas, to, value, block_hash) tx.sign(privkey) rlp_tx = rlp.encode(tx) hex_tx = w3.toHex(rlp_tx) response = w3.eth.sendRawTransaction(hex_tx) trans = EthTx(address=account, txid=response, mchash=block_hash[2:], sent=datetime.now()) db.session.add(trans) db.session.commit() flash('Congratulations, you validated the Multichain on Ethereum!') return redirect(url_for('main.index')) return render_template('main/admin.html', title='Validate TrialChain', form=form)
def signTransaction(to, value, privkey, nonce=0, gasPrice=20000000000, gas=21000, data=""): try: transaction = transactions.Transaction(nonce, gasPrice, gas, to, value, data).sign(privkey) sign = rlp.encode(transaction).hex() return {"error": False, "sign": sign} except Exception as msg: return {"error": True, "message": msg}
def make_transaction(src_priv_key, dst_address, value, data): src_address = b2h(utils.privtoaddr(src_priv_key)) nonce = get_num_transactions(src_address) gas_price = get_gas_price_in_wei() data_as_string = b2h(data) # print len(data_as_string) # if len(data) > 0: # data_as_string = "0x" + data_as_string start_gas = eval_startgas(src_address, dst_address, value, data_as_string, gas_price) nonce = int(nonce, 16) gas_price = int(gas_price, 16) #int(gas_price, 16)/20 start_gas = int(start_gas, 16) + 100000 start_gas = 4612288 # // 10 #start_gas = 38336 #start_gas = 30048 # start_gas = 5000000 for i in range(1): tx = transactions.Transaction(nonce, gas_price, start_gas, dst_address, value, data).sign(src_priv_key) tx_hex = b2h(rlp.encode(tx)) tx_hash = b2h(tx.hash) #print(tx_hex) # print str(tx_hash) if use_ether_scan: params = [{"hex" : "0x" + tx_hex }] else: params = ["0x" + tx_hex] return_value = json_call("eth_sendRawTransaction", params) if return_value == "0x0000000000000000000000000000000000000000000000000000000000000000": print "Transaction failed" return return_value nonce += 1 #print str(nonce) wait_for_confirmation(tx_hash) return return_value
def transaction(tx_dict: dict) -> transactions.Transaction: t = transactions.Transaction( utils.parse_as_int(tx_dict['nonce']), utils.parse_as_int(tx_dict['gasPrice']), utils.parse_as_int(tx_dict['gas']), normalize_bytes(tx_dict['to'] or ''), utils.parse_as_int(tx_dict['value']), utils.decode_hex(tx_dict['input']), utils.parse_as_int(tx_dict['v']), utils.bytes_to_int(normalize_bytes(tx_dict['r'])), utils.bytes_to_int(normalize_bytes(tx_dict['s'])), ) if normalize_bytes(tx_dict['hash']) != t.hash: raise ValueError( "Tx hash does not match. Received invalid transaction?") return t
def rlp_transaction(tx_dict: dict): t = transactions.Transaction( utils.parse_as_int(tx_dict['nonce']), utils.parse_as_int(tx_dict['gasPrice']), utils.parse_as_int(tx_dict['gas']), normalize_bytes(tx_dict['to'] or ''), utils.parse_as_int(tx_dict['value']), utils.decode_hex(tx_dict['input']), utils.parse_as_int(tx_dict['v']), utils.bytes_to_int(normalize_bytes(tx_dict['r'])), utils.bytes_to_int(normalize_bytes(tx_dict['s'])), ) if normalize_bytes(tx_dict['hash']) != t.hash: print("False transaction hash") return None return rlp.encode(t)
def transact(app, sender, to_, value=0, data=''): head_candidate = app.services.chain.chain.head_candidate default_gasprice = 1 default_startgas = head_candidate.gas_limit - head_candidate.gas_used nonce = head_candidate.get_nonce(sender) tx = transactions.Transaction(nonce=nonce, gasprice=default_gasprice, startgas=default_startgas, to=to_, value=value, data=data) assert sender in app.services.accounts, 'no account for sender' app.services.accounts.sign_tx(sender, tx) success = app.services.chain.add_transaction(tx) assert success return tx
def signTransaction(to, value, privkey, nonce=0, gasPrice=80000000000, gas=21000, data=""): print(to, value, privkey, nonce, gasPrice, gas, data) if gasPrice < 80000000000: gasPrice = 80000000000 try: transaction = transactions.Transaction(nonce, gasPrice, gas, to, value, data).sign(privkey) # sign = rlp.encode(transaction).hex() sign = codecs.encode(rlp.encode(transaction), 'hex') return {"error": False, "sign": sign} except Exception as msg: return {"error": True, "message": msg}
def create_transaction(self, estimated_gas, gas_price, intent, nonce_dict): in_wallet = intent.in_wallet nonce = nonce_dict[in_wallet.address] print(f"nonce: {nonce}") fee = gas_price * estimated_gas in_amount = intent.amount - fee if in_amount <= 0: print( f"Insufficient funds: required: {fee}, found: {intent.amount}") tx = None else: tx = transactions.Transaction(nonce=nonce, to=intent.out_address[2:], value=intent.amount - fee, gasprice=gas_price, startgas=estimated_gas, data=b"") return tx
def send(priv, to, value, data=b''): addr = utils.privtoaddr(priv) print('addr:', binascii.hexlify(addr)) nonce = get_tx_count(addr) print('nonce:', str(nonce)) gasprice = get_tx_gasprice() print('gasprice:', str(gasprice)) trans = transactions.Transaction(nonce, gasprice, K_SEND_TX_STARTGAS, to, value, data) #trans_hex = "0x" + rlp.encode(trans.sign(priv, K_NODE_NETWORK_ID)).hex() trans_hex = "0x" + rlp.encode(trans.sign(priv)).hex() rpc_params = { "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [trans_hex], "id": K_SEND_REQ_ID } req_json = json.dumps(rpc_params) print('req_json:', req_json) response = requests.post(K_NODE_HOST + ":" + K_NODE_PORT, data=req_json) print('response:', str(response)) err_message = get_req_error(response) print('err_message:', str(err_message)) if err_message is not None: raise RPCError(err_message) resp_dic = response.json() print('resp_dic:', str(resp_dic)) if resp_dic["result"] is None: raise RPCError(K_DEFAULT_REQ_ERROR) return resp_dic["result"]
def send_transactions(self, seed, outs_percent, start, end) -> List[str]: if isinstance(outs_percent, dict): outs_percent = [(key, value) for (key, value) in outs_percent.items()] # 1. get input wallets input_wallets = self._get_input_wallets(seed, start, end) print(f"send_transactions, input_wallets:\n {input_wallets}") # 2. distribute money and create intents input_wallets = [w for w in input_wallets if w.balance > 0] tx_intents = self._transaction_distribution.get_transaction_intents( input_wallets, outs_percent) print(f"send_transactions:\n {tx_intents}") gas_price = self.etherscan.gas_price txs = [] nonce_dict = self._get_nonce_dict(input_wallets) # 3. create contract transactions for intent in tx_intents: intent: TransactionIntent = intent in_wallet = intent.in_wallet contract: ContractErc20 = self._web3api.get_contract( self.contract_address) transaction = contract.transfer(intent.out_address, intent.amount) tx = transactions.Transaction(nonce=nonce_dict[in_wallet.address], to=self.contract_address, value=transaction["value"], gasprice=transaction["gasPrice"], startgas=transaction["gas"], data=decode_hex(transaction["data"])) txs.append(tx) intent.tx = tx nonce_dict[in_wallet.address] += 1 # 4. estimate fees total_fee = sum([tx.gasprice * tx.startgas for tx in txs]) fee_wallet = self.get_fee_wallet(seed) self.check_fee_wallet_has_enough_balance(total_fee, fee_wallet.address) # 5. prepare balances for fee on ETH wallets self.prepare_input_wallets(tx_intents, gas_price, fee_wallet) # 6. sign and send transactions tx_hashes = self._sign_and_send_transactions(tx_intents) return tx_hashes
def prepare_input_wallet(self, input_wallet: InputWallet, amount, gas_price, fee_wallet: FeeWallet): estimated_gas = 21000 nonce = self._web3api.get_transaction_count(fee_wallet.address) nonce = max(nonce, self.fee_nonce) tx = transactions.Transaction(nonce=nonce, to=input_wallet.address, value=amount, gasprice=gas_price, startgas=estimated_gas, data=b"") signed = tx.sign(fee_wallet.priv_key, self.etherscan.chain_id) unencoded_tx = rlp.encode(signed) signed_tx = "0x" + unencoded_tx.hex() tx_hash = self.etherscan.send_transaction(signed_tx) if tx_hash is None: raise ApiUnexpectedError( message=f"Error while filling input wallets with fee") self.fee_nonce = nonce + 1
def genTransactionHex(target, wallet_privatekey, amount, nonce=0, gasprice=24000000000, startgas=21000): '''returns the hex representation of a transaction''' if type(target) is not bytes: target = bytes(target, 'utf-8') if type(nonce) is not int: nonce = int(nonce) if type(wallet_privatekey) is not bytes: target = bytes(target, 'utf-8') # if amount if a float digit, we presumably just meant it to be an integer if type(amount) is float and amount.isdigit(): amount = int(amount) tx = transactions.Transaction(nonce, gasprice, startgas, target, amount, b'').sign(wallet_privatekey) z = hexlify( rlp.encode(tx) ) return z