Bitcoin SV w Pythonie
W poprzednich wpisach (1, 2) wygenerowaliśmy klucz prywatny, poznaliśmy adres
testnet, mainnet, sprawdziliśmy saldo i
pobraliśmy niewydane transakcje. Teraz nauczymy
się, jak przy pomocy oficjalnego bsv-sdk dla Pythona zbudować prostą
transakcję, którą wyślemy na swój własny adres testnetowy. Jak to w ogóle możliwe, że możesz wysłać Bitcoina… samemu sobie?
W Bitcoinie nikt nie wie, kim jesteś - sieć tylko sprawdza, czy umiesz wydać monety zgodnie z zasadami a skoro umiesz, to możesz je wysłać.. nawet z powrotem do siebie i sieci jest to kompletnie obojętne :)

UTXO: Bitcoin SV
W tradycyjnym banku masz konto i tutaj wszystko ląduje do jednego wora:

- ma konkretną kwotę,
- ma "kłódkę" - skrypt, który mówi: kto i na jakich warunkach może je wydać.
Twoje "saldo" to tak naprawdę zbiór wszystkich wierszy, a każdy z tych wierszy potrafisz otworzyć swoim kluczem prywatnym.

I teraz chcesz wydać 50zł w sklepie. Musisz wydać/zużyć jeden z wierszy (wydajemy 100zł), a Twoja reszta (50zł) wracając, utworzy nowy wiersz.

Proste? :) No to przechodzimy do kodu.
Tworzenie i Rozgłaszanie Transakcji BSV
Krok 0: Ile będziemy wysyłać :)
do_wyslania = 222
Krok 1: Zadeklaruj funkcję asynchroniczną
async def create_and_broadcast_transaction():Na początek zadeklaruj asynchroniczną funkcję o nazwie create_and_broadcast_transaction. Słowo kluczowe async jest ważne - dzięki niemu będziesz mógł czekać na odpowiedzi z sieci bez zawieszania całego programu.
Krok 2: Załaduj poprzednią transakcję
Poprzedni wpis, zakończyliśmy wypisaniem niewydanej transakcji w hex (tx_hex); musisz ją teraz przekazać:Krok 3: Przygotuj input - określ źródło pieniędzy
- Stwórz nowy obiekt TransactionInput.
- Przypisz poprzednią transakcję (source_tx) jako źródło. Ten parametr mówi: "pieniądze biorę z tej transakcji"
- Wyciągnij i przypisz ID źródłowej transakcji. source_tx.txid() to metoda, która generuje unikalny identyfikator tej transakcji. ID jednoznacznie identyfikuje transakcję na blockchainie - bez niego sieć nie wiedziałaby, którą transakcję masz na myśli.
- Określ, który output ze źródłowej transakcji chcesz wydać. 0 oznacza pierwszy output (liczymy od zera). Transakcja może mieć wiele wyjść, ale Ty bierzesz tylko jedno - pierwsze.
- Przygotuj szablon skryptu odblokowania. .unlock(klucz_prywatny) - generuje skrypt, który będzie podpisany Twoim kluczem prywatnym Ten skrypt będzie dowodem, że jesteś właścicielem tych pieniędzy i masz prawo je wydać.
source_txid=source_tx.txid(), # (3)
unlocking_script_template=P2PKH().unlock(klucz_prywatny),) # (5)
Zamknij konfigurację input-u.
Krok 4: Przygotuj output - określ cel pieniędzy
- Stwórz nowy obiekt TransactionOutput - to będzie wyjście Twojej transakcji :)
- Stwórz skrypt blokujący pieniądze - to blokuje satoshi na Twoim adresie testnet. Ten fragment .lock(address_testnet) wpisujemy zmienną naszego adresu lub możesz wpisać swój adres jako string .lock("xxxxxxxxxxx")
- Określ ilość satoshi w tym outputcie."satoshis" to zmienna przechowująca konkretną liczbę (np. 222 - u nas to zmienna do_wyslania)
- Oznacz ten output jako zmianę (resztę). Jeśli ustawisz change=True - biblioteka automatycznie wyśle resztę pieniędzy (różnicę między inputem a outputem) z powrotem na Twój adres. Jeśli ustawisz change=False - reszta pieniędzy zostanie zmarnowana.
tx_output = TransactionOutput( # (1)
locking_script=P2PKH().lock(address_testnet), # (2)
satoshis=do_wyslania, # (3)
change=True) # (4)
Zamknij konfigurację output-u. Teraz output jest gotowy.
Krok 5: Połącz input i output w transakcję
tx = Transaction([tx_input], [tx_output], version=1)
- [tx_input] - lista inputów (tutaj jeden, w nawiasach kwadratowych)
- [tx_output] - lista outputów (tutaj jeden)
- version=1 - określa wersję transakcji (1 to oryginalna wersja)
Krok 6: Wyświetl informacje
Wydrukuj na ekran informacyjny komunikat.print(f"{address_testnet} wysyła {do_wyslania} satoshi")
Krok 7: Oblicz opłatę i podpisz transakcję
Oblicz i ustaw automatyczną opłatę. Metoda fee() analizuje rozmiar transakcji (w bajtach) i wylicza odpowiednią opłatę sieciową. Opłata automatycznie zostanie odliczona z outputu. Podpisz całą transakcję Twoim kluczem prywatnym.
Krok 9: Przygotuj klucz API
api_key = 'testnet_73657152612......'Zadeklaruj swój klucz API w zmiennej. Ten klucz identyfikuje Cię wobec usługi Taal ARC i pozwala na rozgłaszanie transakcji.
Krok 10: Rozgłoś transakcję do sieci
Wyślij podpisaną transakcję do sieci Bitcoin SV
- tx.broadcast() - wysyła transakcję
- ARC(...) - tworzy klienta ARC z endpointem serwera i Twoim kluczem API
- await - czeka na odpowiedź z serwera
- response - przechowuje odpowiedź - informacje o tym, czy rozgłoszenie się powiodło
Krok 11: Wyświetl status rozgłoszenia
Wydrukuj status odpowiedzi serwera.
Krok 12: Wyświetl ID transakcji
Wydrukuj unikalny identyfikator Twojej nowej transakcji, którą będziesz mógł zobaczyć w blockchain --> https://test.whatsonchain.com/Krok 13: Uruchom funkcję
if __name__ == "__main__":asyncio.run(create_and_broadcast_transaction())
Kosmetyka:
Wypisz numer indeksu:
Zmodyfikuj zmienną source_output:
source_output_index=tx_pos,
Pełny kod:
nest_asyncio.apply()
import asyncio
from bsv import PrivateKey, P2PKH, ARC, Transaction, TransactionInput, TransactionOutput
import requests
import json
moj_klucz = "KwVs88aLx6ZuZmphr........................."
klucz_prywatny = PrivateKey(moj_klucz)
address_testnet = klucz_prywatny.address(network = "testnet")
url = f"https://api.whatsonchain.com/v1/bsv/test/address/{address_testnet}/confirmed/balance"
response = requests.get(url)
data = response.json()
saldo = data['confirmed']
print(f"Adres testnet : {address_testnet}")
print(f"Saldo : {saldo} satoshi / {saldo / 100000000} BSV")
url = f"https://api.whatsonchain.com/v1/bsv/test/address/{address_testnet}/unspent/all"
response = requests.get(url)
data = response.json()
txid = data['result'][0]['tx_hash']
tx_pos = data['result'][0]['tx_pos']
print(f"\nTransakcja z niewydanym UTXO: {txid}")
print(f"Indeks transakcji: {tx_pos}\n")
url = f"https://api.whatsonchain.com/v1/bsv/test/tx/{txid}/hex"
response = requests.get(url)
tx_hex = response.text
print(f"HEX : {tx_hex}\n")
do_wyslania = 333
input("Naciśnij Enter by kontynuować..")
async def create_and_broadcast_transaction():
source_tx = Transaction.from_hex(tx_hex)
tx_input = TransactionInput(
source_transaction=source_tx,
source_txid=source_tx.txid(),
source_output_index=tx_pos,
unlocking_script_template=P2PKH().unlock(klucz_prywatny),
)
tx_output = TransactionOutput(
locking_script=P2PKH().lock(address_testnet),
satoshis=do_wyslania,
change=True
)
tx = Transaction([tx_input], [tx_output], version=1)
print(f"{address_testnet} wysyła {do_wyslania} satoshi")
tx.fee()
tx.sign()
api_key = 'testnet_2d8a5a0745..........'
response = await tx.broadcast(ARC('https://api.taal.com/arc', api_key))
print(f"Status rozgłoszenia: {response.status}")
print(f"ID transakcji: {tx.txid()}")
if __name__ == "__main__":
asyncio.run(create_and_broadcast_transaction())
input("Koniec")
- wygenerowany klucz prywatny,
- uzupełnione saldo za pomocą kranu testnet,
- sprawdzone saldo z poziomu kodu (a nie poprzez explorer bloków na stronie www),
- ustalone niewydane UTXO
- pobrany hex z powyższego UTXO
- ustalony indeks z UTXO
- zbudowaną funkcję do zbudowania wejść i wyjść
- rozgłoszenie transakcji
- pobranie hasha transakcji
Wysłaliśmy sami sobie Bitcoin'a :)
Co dalej?
W kolejnym wpisie, dalej będziemy pracować na dotychczasowym kodzie. Zbudujemy transakcję w której wyślemy środki na jakiś inny adres a reszta będzie wracała na nasz adres. Pokażę też, dwie metody na zbudowanie takiej transakcji :) Jeśli masz jakieś pytania, nie zawahaj się ich zadać w komentarzach.
Cześć!
**Gwarantuję Ci niezmienność moich treści**
Hash artykułu:
ID transakcji: sprawdź OP_RETURN i porównaj jego hash
hmm w realnej app jak bezpiecznie podstawić priv key ? ;)
OdpowiedzUsuńW realnej APP musiałbyś mieć zaszyfrowany klucz prywatny i odszyfrować go "na chwilę" w pamięci RAM.
UsuńHmm fakt w secure ram ten zwykły przeczesują często wajrusy, thx!
UsuńTo prawda. No chyba że chcemy mieć Uber Turbo Secure App, wtedy trzeba myśleć tak jakby "wajrus" był na naszym komputerze. Czyli (tak podejrzewam) tutaj nic nie może wykonać się na naszym PC. Moja odpowiedź jest do "real app" - z czego korzysta 90% popularnych portfeli. Ty masz na myśli portfel "premium" a ja nie posiadam takiej wiedzy jak to najbezpieczniej wykonać ale jeśli będzie trzeba to poszukam informacji o tym i możemy gdzieś to przedyskutować. Pozdrawiam!
Usuń