и тут у тебя ошибка:
for tx in transactions:
sender_address = tx['sender_address']
recipient_address = tx['recipient_address']
amount = tx['amount']
ты же подаешь на вход не те данные что в твоем примере:
transactions1 = ["Ketchup", "French Fries"]
blockchain.add_block(transactions1)
Тогда приведи уже полный пример, чтоб работало все наконец то.
Действительно, у меня ошибка в примере. В транзакции должны быть ключи 'sender_address', 'recipient_address' и 'amount', чтобы функция add_block() сработала правильно.
Вот пример полного кода блокчейн, включая функцию add_block() для работы с транзакциями:
``` python
from datetime import datetime
import hashlib
class Blockchain:
def __init__(self):
self.chain = [{'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'prev_block_hash': ' ', 'transactions': []}]
self.participants = [] # список участников
def add_block(self, transactions):
for tx in transactions:
sender_address = tx['sender_address']
recipient_address = tx['recipient_address']
amount = tx['amount']
# Проверяем, содержит ли отправитель достаточное количество средств
if not self.check_utxo(sender_address, amount):
return False
# Проверяем, есть ли получатель в нашем списке участников
if recipient_address not in self.participants:
self.participants.append(recipient_address)
# Проверяем, является ли транзакция действительной
if not self.verify_transaction(tx):
return False
# Создаем новый блок с указанием всех проведенных транзакций
prev_block_hash = self.chain[-1]['prev_block_hash']
new_block = {'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'transactions': transactions, 'prev_block_hash': prev_block_hash}
self.chain.append(new_block)
return True
def verify_transaction(self, tx):
# Проверяем, не была ли транзакция уже использована
if not self.check_double_spend(tx):
return False
# Проверяем, корректность подписи
if not self.verify_signature(tx):
return False
return True
def check_double_spend(self, tx):
sender_address = tx['sender_address']
sender_utxo = self.find_utxo(sender_address)
# Проверяем, не были ли уже использованы какие-то из UTXO в данной транзакции
for utxo in sender_utxo:
if utxo in tx['inputs']:
return False
return True
def verify_signature(self, tx):
# Должны быть подписи от всех отправителей
signatures = tx['signatures']
sender_addresses = tx['sender_address']
if len(signatures) != len(sender_addresses):
return False
# Проверяем, что данные транзакции не были подделаны
hash_tx = self.hash_transaction(tx)
for i, sig in enumerate(signatures):
if not self.verify_signature_single(hash_tx, sig, sender_addresses
):
return False
return True
def verify_signature_single(self, data, signature, sender_address):
# Проверка подлинности подписи
return sender_address.verify(signature, data.encode())
def find_utxo(self, address):
# Поиск неиспользованных выходов транзакций на данный адрес
utxo = []
for block in self.chain:
for tx in block['transactions']:
for i, out in enumerate(tx['outputs']):
if address == out['recipient_address'] and i not in tx['inputs']:
utxo.append({'transaction_id': tx['transaction_id'], 'output_index': i})
return utxo
def check_utxo(self, address, amount):
# Проверка, может ли отправитель отправить запрашиваемую сумму
utxo = self.find_utxo(address)
total = 0
for out in utxo:
block_idx = self.get_block_index(out['transaction_id'])
if self.chain[block_idx]['transactions'][out['transaction_id']]['outputs'][out['output_index']]['amount'] >= amount:
total += amount
else:
total += self.chain[block_idx]['transactions'][out['transaction_id']]['outputs'][out['output_index']]['amount']
if total >= amount:
return True
return False
def get_balance(self, address):
# Получение текущего баланса адреса
utxo = self.find_utxo(address)
balance = 0
for out in utxo:
block_idx = self.get_block_index(out['transaction_id'])
balance += self.chain[block_idx]['transactions'][out['transaction_id']]['outputs'][out['output_index']]['amount']
return balance
def hash_transaction(self, tx):
# Получение хэша транзакции
message = str(tx).encode()
return hashlib.sha256(message).hexdigest()
def get_block_index(self, transaction_id):
# Получение индекса блока по номеру транзакции
for i, block in enumerate(self.chain):
for tx in block['transactions']:
if tx['transaction_id'] == transaction_id:
return i
return None
```
Для добавления нового блока с транзакциями нужно вызвать метод add_block() со списком транзакций в формате:
```python
blockchain = Blockchain()
transactions1 = [{'sender_address': 'address_1', 'recipient_address': 'address_2', 'amount': 10}]
blockchain.add_block(transactions1)
transactions2 = [{'sender_address': 'address_2', 'recipient_address': 'address_3', 'amount': 5},
{'sender_address': 'address_1', 'recipient_address': 'address_3', 'amount': 3}]
blockchain.add_block(transactions2)
```
Здесь мы создаем экземпляр блокчейн и добавляем два блока с транзакциями: первая транзакция переводит 10 единиц от 'address_1' к 'address_2', а вторая транзакция переводит 5 единиц от 'address_2' к 'address_3' и 3 единицы от 'address_1' к 'address_3'.