def _no_sign_send(self, to_address, amount, data=b''): # gethの署名機構を用いて送金 nonce = self.web3.eth.getTransactionCount(self.config.account_pubkey) gas_price = self.web3.eth.gasPrice transaction = { 'to': to_address, 'value': amount, 'gas': 21000, 'gasPrice': gas_price, 'nonce': nonce, 'chainId': 1, 'data': data } params = (to_address, amount / NUKO_TO_WEI, data) logging.info("Send to=%s, amount=%s, data=%s" % params) signed = self.web3.eth.account.signTransaction( transaction, self.config.account_seckey) raw_tx_hex = bytes2hex(signed.rawTransaction) logging.info(raw_tx_hex) try: tx_hash = bytes2hex(self.web3.eth.sendRawTransaction(raw_tx_hex)) return True, tx_hash except ValueError as e: logging.error(e) return False, e
def start(self): get_genesis = bytes2hex(self.obj.neko.get_block_by_number(0).hash) if get_genesis != self.config.genesis: logging.error("# don't match %s != %s" % (get_genesis, self.config.genesis)) threading.Thread(target=self._run, name="incoming", daemon=True).start() logging.info("# incoming start")
def _sign_send(self, to_address, amount, data=b''): # 自前の署名機構を用いて送金 nonce = self.web3.eth.getTransactionCount(self.config.account_pubkey) gas_price = self.web3.eth.gasPrice # 常時4Gwei? tx = Transaction( nonce=nonce, gasprice=gas_price, startgas=21000, to=to_address, value=amount, data=data, ) params = (to_address, amount / NUKO_TO_WEI, gas_price, nonce) logging.info("Send to=%s,amount=%s,price=%s,nonce=%s" % params) tx.sign(self.config.account_seckey) raw_tx_hex = self.web3.toHex(rlp.encode(tx)) logging.info("raw tx:%s" % raw_tx_hex) try: tx_hash = bytes2hex(self.web3.eth.sendRawTransaction(raw_tx_hex)) return True, tx_hash except ValueError as e: logging.error(e) return False, e
def _run(self): time_span = 0.02 if self.config.node[0] in LOCAL_IP_ADDRESS else 0.1 divide = 1500 error = count = announce = 0 block_data = self.read_block_file() logging.info("# start income loop %ssec %sdiv" % (time_span, divide)) while error < 50: try: time.sleep(time_span) count += 1 if self.config.stop_signal: break previous_height = max(block_data) next_height = previous_height + 1 block = self.obj.neko.get_block_by_number(next_height) if block is None: if time_span != 5: logging.info("# finish sync %s" % next_height) time_span = 5 divide = 800 self.finish = 1 continue next_block_hash = bytes2hex(block.hash) previous_block_hash = bytes2hex(block.parentHash) if block_data[previous_height] == previous_block_hash: # 新規Blockとして追加 block_data[next_height] = next_block_hash self.now_height = next_height if announce: logging.info("new block %d" % next_height) # TXにユーザーバインドアドレスが含まれていないかチェック txs = [ self.obj.neko.get_transaction_by_hash(bytes2hex(tx)) for tx in block.transactions ] self.recode_txs(txs, block, announce) else: # フォークによりBlockを一つ前へ... del block_data[previous_height] with self.connect.cursor() as cursor: sql = "DELETE FROM `incoming` WHERE `height`='%d'" cursor.execute(sql % block.number) self.commit() logging.info("find fork %s" % previous_height) continue if count % divide == 0: error = 0 logging.info("# block write %d" % next_height) threading.Thread(target=self.write_block_file, args=(copy.copy(block_data), ), name="block write", daemon=True).start() except ValueError as e: self.rollback() logging.error(e) error += 1 except Exception as e: self.rollback() logging.error(e) import traceback traceback.print_exc() error += 1 self.write_block_file(block_data) logging.error("# incoming polling stopped") self.config.stop_ok.append("incoming")
def recode_txs(self, txs, block, announce): with self.connect.cursor() as cursor: for tx in txs: try: if tx.to != self.config.account_pubkey: continue address_from = dict(tx)['from'] tx_hash = bytes2hex(tx.hash) # 既に登録されているTXか確認 sql = "SELECT `uuid` FROM `incoming` WHERE `tx_hash`=%s" cursor.execute(sql % tx_hash) if cursor.fetchone() is not None: continue logging.info("# TX:%s" % tx_hash) logging.info("# ADDR:%s" % address_from) # bind_userによるアドレス定義 sql = "SELECT `user_id` FROM `bind_user` WHERE `user_id`= '%d'" cursor.execute(sql % tx.value) user_id = cursor.fetchone() if user_id: params = (address_from, user_id['user_id'], block.timestamp) sql = "INSERT INTO `bind_address` (`address`,`user_id`,`time`) VALUES ('%s','%d','%d')" cursor.execute(sql % params) # ダブればここでエラーになる logging.info("# bind user %s=%s" % (user_id['user_id'], address_from)) sql = "UPDATE `incoming` SET `recipient`='%d' WHERE `address`='%s' AND `recipient`='0'" cursor.execute(sql % (user_id['user_id'], address_from)) continue # bind_addressによる入金 sql = "SELECT `user_id` FROM `bind_address` WHERE `address`='%s'" cursor.execute(sql % address_from) user_id = cursor.fetchone() user_id = 0 if user_id is None else user_id['user_id'] logging.info("# bind address %s=%s" % (user_id, address_from)) params = (tx_hash, address_from, user_id, round(tx.value / MICRO_TO_WEI), tx.blockNumber, block.timestamp) sql = "INSERT INTO `incoming` (`tx_hash`,`address`,`recipient`,`amount`," \ "`height`, `time`) VALUES (%s,'%s','%d','%d','%d','%d')" cursor.execute(sql % params) logging.info("# income %s <= %s" % (user_id, round(tx.value / NUKO_TO_WEI, 6))) except pymysql.err.IntegrityError as e: logging.error(e) continue except Exception as e: import traceback traceback.print_exc() logging.error(e) continue self.commit() return