-
Notifications
You must be signed in to change notification settings - Fork 1
/
grouphug.py
90 lines (75 loc) · 3.21 KB
/
grouphug.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
from telegram import Update
from telegram.ext import (
Application,
CommandHandler,
MessageHandler,
filters,
ContextTypes,
)
from dotenv import load_dotenv
import asyncio
import os
import bitcoin
load_dotenv()
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Send me a Bitcoin transaction in raw format")
async def handle_transaction(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
tx_raw = update.message.text
is_valid, message = validate_transaction(tx_raw)
if is_valid:
message_to_send = f"add_tx {tx_raw}"
server_response = await send_to_server(message_to_send)
await update.message.reply_text('Transaction processed. Server response: ' + server_response)
else:
await update.message.reply_text('Transaction validation failed: ' + message)
async def send_to_server(message):
host = os.getenv('SERVER_IP')
port = int(os.getenv('SERVER_PORT'))
try:
reader, writer = await asyncio.open_connection(host, port)
writer.write(message.encode())
await writer.drain()
response = await reader.read(100)
return response.decode()
finally:
if writer:
writer.close()
await writer.wait_closed()
def validate_transaction(tx_raw):
# Strip and remove all spaces
#tx_raw = tx_raw.strip().replace(' ', '')
# Check if all characters are valid hexadecimal
if any(c not in "0123456789abcdefABCDEF" for c in tx_raw):
return False, "Transaction data contains non-hexadecimal characters."
# Deserialize the transaction
try:
tx = bitcoin.deserialize(tx_raw)
except Exception as e:
return False, f"Failed to deserialize transaction: {str(e)}"
# Check the number of inputs and outputs
if len(tx['ins']) != len(tx['outs']):
return False, "The number of inputs does not match the number of outputs."
# Check for maximum input limit
if len(tx['ins']) > 5:
return False, "The transaction has more than 5 inputs, which is not allowed."
# Check the locktime of the transaction
if tx['locktime'] != 0:
return False, "The transaction's locktime must be 0. Found locktime: {}".format(tx['locktime'])
# Check each input for the correct witness structure
for index, input in enumerate(tx['ins']):
if 'witness' not in input or len(input['witness']) != 2:
return False, f"Input {index + 1} has an invalid witness structure. Required: 2 items in the witness."
# Assuming the SigHash type is the last byte of the last item in the witness
last_byte = input['witness'][-1][-1]
if last_byte != 0x83:
return False, f"Input {index + 1} does not use the required SigHash type SINGLE | ANYONECANPAY."
# If all checks are passed
return True, "Transaction is valid."
def main() -> None:
token = os.getenv('TELEGRAM_BOT_TOKEN')
application = Application.builder().token(token).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_transaction))
application.run_polling()
if __name__ == '__main__':
main()