Browse Source

new utility: mmnode-txfind

The MMGen Project 4 years ago
parent
commit
4da65900fd
2 changed files with 97 additions and 37 deletions
  1. 3 37
      mmnode-blocks-info
  2. 94 0
      mmnode-txfind

+ 3 - 37
mmnode-blocks-info

@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 #!/usr/bin/env python3
 #
 #
 # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
 # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
-# Copyright (C)2013-2020 The MMGen Project <mmgen@tuta.io>
+# Copyright (C)2013-2021 The MMGen Project <mmgen@tuta.io>
 #
 #
 # This program is free software: you can redistribute it and/or modify it under
 # This program is free software: you can redistribute it and/or modify it under
 # the terms of the GNU General Public License as published by the Free Software
 # the terms of the GNU General Public License as published by the Free Software
@@ -28,7 +28,7 @@ from decimal import Decimal
 opts_data = {
 opts_data = {
 	'sets': [('raw_miner_info',True,'miner_info',True)],
 	'sets': [('raw_miner_info',True,'miner_info',True)],
 	'text': {
 	'text': {
-		'desc':    'Display information about or find a transaction within a range of blocks',
+		'desc':    'Display information about a range of blocks',
 		'usage':   '[opts] +<last n blocks>|<block num>|<block num range>',
 		'usage':   '[opts] +<last n blocks>|<block num>|<block num range>',
 		'options': """
 		'options': """
 -h, --help            Print this help message
 -h, --help            Print this help message
@@ -39,7 +39,6 @@ opts_data = {
 -o, --fields=         Display the specified fields
 -o, --fields=         Display the specified fields
 -s, --summary         Print the summary only
 -s, --summary         Print the summary only
 -S, --no-summary      Don't print the summary
 -S, --no-summary      Don't print the summary
--t, --transaction=t   Search for transaction 't' in specified block range
 
 
 If no block number is specified, the current block is assumed
 If no block number is specified, the current block is assumed
 """
 """
@@ -272,37 +271,6 @@ class BlocksInfoOverview(BlocksInfo):
 					self.sum_fs.format('Avg conf time:', f'{ac//60}:{ac%60:02}')
 					self.sum_fs.format('Avg conf time:', f'{ac//60}:{ac%60:02}')
 				)
 				)
 
 
-class BlocksInfoTxFind(BlocksInfo):
-
-	found_tx = False
-
-	def post_init(self):
-		if len(opt.transaction) != 64 or not is_hex_str(opt.transaction):
-			die(2,f'{opt.transaction}: invalid transaction id')
-
-	async def process_block(self,height,H):
-		if opt.transaction in (await c.call('getblock',H))['tx']:
-			Msg('\rRequested transaction is in block {} ({} confirmations)'.format(height,c.blockcount-height+1))
-			return True
-		msg_r('\rChecking block {} '.format(height))
-
-	async def print_summary(self):
-		if self.found_tx:
-			try:
-				await c.call('getmempoolentry',opt.transaction) # ,on_fail='silent')):
-			except:
-				Msg('\rTransaction not found in block range {}-{} or in mempool'.format(self.first,self.last))
-			else:
-				Msg('\rTransaction is in mempool')
-
-	async def run(self):
-		for height in range(self.first,self.last+1):
-			H = await c.call('getblockhash',height)
-			if await self.process_block(height,H): # returns True when finished
-				break
-		else:
-			self.found_tx = True
-
 class BlocksInfoHashes(BlocksInfo):
 class BlocksInfoHashes(BlocksInfo):
 
 
 	def print_header(self):
 	def print_header(self):
@@ -327,9 +295,7 @@ async def main():
 	global c
 	global c
 	c = await rpc_init(proto)
 	c = await rpc_init(proto)
 
 
-	if opt.transaction:
-		m = BlocksInfoTxFind()
-	elif opt.hashes:
+	if opt.hashes:
 		m = BlocksInfoHashes()
 		m = BlocksInfoHashes()
 	else:
 	else:
 		m = BlocksInfoOverview()
 		m = BlocksInfoOverview()

+ 94 - 0
mmnode-txfind

@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C)2013-2021 The MMGen Project <mmgen@tuta.io>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+mmgen-txfind: Find a transaction in the blockchain or mempool
+"""
+
+from mmgen.common import *
+
+opts_data = {
+	'text': {
+		'desc':    'Find a transaction in the blockchain or mempool',
+		'usage':   '[opts] <transaction ID>',
+		'options': """
+-h, --help      Print this help message
+--, --longhelp  Print help message for long options (common options)
+-q, --quiet     Be quieter
+-v, --verbose   Be more verbose
+""",
+	'notes': """
+If transaction is in blockchain, the block number and number of confirmations
+are displayed.
+
+Requires --txindex for correct operation.
+"""
+	}
+}
+
+msg_data = {
+	'normal': {
+		'none':  'Transaction not found in blockchain or mempool',
+		'block': 'Transaction is in block {b} ({c} confirmations)',
+		'mem':   'Transaction is in mempool',
+	},
+	'quiet': {
+		'none':  'None',
+		'block': '{b} {c}',
+		'mem':   'mempool',
+	}
+}
+
+async def main(txid):
+	if len(txid) != 64 or not is_hex_str(txid):
+		die(2,f'{txid}: invalid transaction ID')
+
+	if opt.verbose:
+		msg(f'TxID: {txid}')
+
+	from mmgen.protocol import init_proto_from_opts
+	proto = init_proto_from_opts()
+
+	from mmgen.rpc import rpc_init
+	c = await rpc_init(proto)
+
+	exitval = 0
+	try:
+		tip1 = await c.call('getblockcount')
+		ret = await c.call('getrawtransaction',txid,True)
+		tip2 = await c.call('getblockcount')
+	except:
+		Msg('\r' + msgs['none'])
+		exitval = 1
+	else:
+		assert tip1 == tip2, 'Blockchain is updating.  Try again later'
+		if 'confirmations' in ret:
+			confs = ret['confirmations']
+			Msg('\r' + msgs['block'].format(b = tip1 - confs + 1, c = confs))
+		else:
+			Msg('\r' + msgs['mem'])
+
+	return exitval
+
+cmd_args = opts.init(opts_data)
+msgs = msg_data['quiet' if opt.quiet else 'normal']
+
+if len(cmd_args) != 1:
+	die(1,'One transaction ID must be specified')
+
+sys.exit(run_session(main(cmd_args[0])))