Rozumienie Bitcoin Script

advanced
Część ścieżki Jak działa Bitcoin, krok 9 z 11

Czym jest Bitcoin Script?

Za każdym razem, gdy wysyłasz Bitcoin, tak naprawdę nie przenosisz monety z jednego miejsca w drugie. Tworzysz wyjście i dołączasz do niego mały program. Ten program definiuje dokładne warunki, na jakich te monety będzie można później wydać. Język używany do pisania tych programów nazywa się Bitcoin Script.

Satoshi Nakamoto opisał to najlepiej, nazywając skrypt rodzajem predykatu: małym równaniem, które rozwiązuje się jako prawda albo fałsz. Jeśli wydający zdoła sprawić, że równanie da prawdę, monety się przesuwają. Jeśli nie, pozostają zablokowane. To całe zadanie Script. To mechanizm blokady, a nie uniwersalny komputer.

Bitcoin Script jest celowo mały i ograniczony. Nie jest kompletny w sensie Turinga, co oznacza, że nie ma pętli, nie ma rekurencji i nie ma sposobu na wykonanie nieskończonego programu. To nie jest brakująca funkcja. To fundamentalna decyzja dotycząca bezpieczeństwa. Język, który nie może działać w nieskończoność, zawsze można szybko i tanio sprawdzić w każdym węźle sieci, a to po części pozwala zwykłym ludziom weryfikować Bitcoin na skromnym sprzęcie.

Stoi to w celowym kontraście do sieci używających kompletnego w sensie Turinga języka kontraktów. Ta większa ekspresyjność wielokrotnie prowadziła do nieoczekiwanych zachowań, zamrożonych środków i exploitów, które wyssały wartość liczoną w setkach milionów Euro lub Dolarów. Na tych platformach tokeny mogą też zostać zamrożone lub przejęte przez emitenta albo kontrolującą je organizację. Bitcoin wybrał mniejszy, przewidywalny język właśnie po to, aby nikt nie trzymał takiego przełącznika nad twoimi monetami.

Jeśli nie czytałeś jeszcze, jak sieć sprawdza transakcję, Jak weryfikowane są transakcje Bitcoin jest dobrym uzupełnieniem tego artykułu.

Stos: jak myśli Script

Bitcoin Script to język oparty na stosie. Stos to zwykła sterta danych, do której możesz tylko dołożyć element na wierzch (operacja "push") albo zdjąć element z wierzchu (operacja "pop"). To, co położysz ostatnie, zdejmiesz jako pierwsze. Komputery obsługują ten rodzaj pamięci bardzo wydajnie, nawet jeśli dla nas wygląda to nieco dziwnie.

Przez stos Script nie zapisuje się tak, jak zwykle zapisujemy działania matematyczne. Zamiast pisać 9 plus 12, najpierw piszesz dwie liczby, a potem operację: 9 12 OP_ADD. Obie liczby trafiają na stos, a następnie OP_ADD zdejmuje je obie, dodaje i odkłada wynik z powrotem.

Polecenia takie jak OP_ADD nazywamy opkodami, od operation code. To czasowniki tego języka. Aktywnych opkodów jest około 80 i obejmują proste działania matematyczne, porównania, haszowanie kryptograficzne oraz sprawdzanie podpisów. Każdy zdejmuje kilka elementów ze stosu, wykonuje swoje zadanie i może odłożyć wynik.

Oto kompletny, choć trochę niepoważny, przykład działającego skryptu:

9 12 OP_ADD 21 OP_EQUAL

Czytając od lewej do prawej: połóż 9, połóż 12, potem OP_ADD zastępuje je liczbą 21. Teraz połóż kolejne 21. Na końcu OP_EQUAL zdejmuje obie wartości, widzi, że są zgodne, i kładzie 1. Na stosie zostaje pojedyncze 1, więc skrypt jest poprawny. Mówiąc prosto, to wyjście jest zablokowane za zagadką "podaj mi dwie liczby, które sumują się do 21", a każdy, kto potrafi liczyć, mógłby je odblokować.

Skrypt blokady i skrypt odblokowania

W Bitcoinie ten pojedynczy skrypt jest w rzeczywistości podzielony na dwie połowy, które znajdują się w różnych miejscach.

Skrypt blokujący, technicznie scriptPubKey, jest dołączony do wyjścia. Ustala warunki wydania. W powyższym przykładzie częścią blokującą jest OP_ADD 21 OP_EQUAL, czyli reguła, którą trzeba spełnić.

Skrypt odblokowujący, technicznie scriptSig, dostarcza później ten, kto chce wydać to wyjście. Podaje wartości wejściowe spełniające regułę. W przykładzie częścią odblokowującą jest 9 12, czyli odpowiedź na zagadkę.

Wysłanie komuś Bitcoina oznacza więc tak naprawdę utworzenie wyjścia, którego skrypt blokujący może spełnić tylko ta osoba. Klasyczna wersja blokuje monety na kluczu, więc tylko posiadacz odpowiadającego klucza prywatnego potrafi utworzyć poprawny skrypt odblokowujący.

Jeden szczegół myli prawie wszystkich. Choć skrypt odblokowujący dostarcza wydający już po tym, jak wyjście istnieje, to gdy węzeł wykonuje pełną walidację, umieszcza najpierw skrypt odblokowujący, a potem skrypt blokujący. Skrypt odblokowujący kładzie dane na stosie, a skrypt blokujący następnie je sprawdza.

How Locking and Unlocking Fit Together

1

Unlocking Script

scriptSig

<Signature> <PublicKey>

Provided by the spender.

2

Locking Script

scriptPubKey

OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

Attached to the output.

During validation the unlocking script runs first, then the locking script.

If the combined script leaves a single TRUE on the stack, the output is unlocked.

Jak skrypt jest walidowany

Węzeł waliduje transakcję, łącząc skrypt odblokowujący i blokujący oraz wykonując je od lewej do prawej. Wynik jest binarny.

Skrypt jest poprawny, jeśli po zakończeniu na stosie zostaje dokładnie jeden niezerowy element. W praktyce oznacza to pojedyncze OP_1 lub dowolną wartość liczoną jako "prawda".

Skrypt jest niepoprawny, jeśli na końcu stos jest pusty, jeśli jedyne, co zostało, to zero, jeśli zostaje więcej niż jeden element albo jeśli skrypt przerwie się przedwcześnie. Nie ma "może". Albo warunki są spełnione, albo monety się nie przesuwają.

Ta jednoznaczność typu zdane albo niezdane sprawia, że Bitcoin da się weryfikować. Każdy węzeł wykonuje te same skrypty i dochodzi do tej samej odpowiedzi, bez dwuznaczności i bez zależności od informacji z zewnątrz.

Pay-to-Public-Key: pierwotna blokada

Najwcześniejszy standardowy typ skryptu to Pay-to-Public-Key (P2PK). Skrypt blokujący zawiera po prostu klucz publiczny, po którym następuje opkod OP_CHECKSIG. Aby wydać, właściciel podaje podpis w skrypcie odblokowującym.

Blokada:      <KluczPubliczny> OP_CHECKSIG
Odblokowanie: <Podpis>

OP_CHECKSIG zdejmuje podpis i klucz publiczny, sprawdza, czy podpis został utworzony odpowiadającym kluczem prywatnym, i kładzie 1, jeśli wszystko się zgadza. P2PK pojawia się w wielu z pierwszych bloków, w tym w wyjściach coinbase bloku genezy.

Dziś prawie nikt nie używa P2PK. Problem jest praktyczny: aby komuś zapłacić, potrzebowałbyś jego pełnego klucza publicznego, który jest długi, nieczytelny i łatwy do błędnego przepisania. Satoshi rozwiązał to kolejnym wzorcem.

Pay-to-Public-Key-Hash: koń roboczy

Pay-to-Public-Key-Hash (P2PKH) przechowuje w skrypcie blokującym tylko hash klucza publicznego, a nie sam klucz. Pomyśl o hashu jak o krótkim odcisku palca klucza. Właściwy klucz publiczny ujawnia się dopiero później, w skrypcie odblokowującym, w chwili wydawania monet.

Hash powstaje przez wykonanie SHA-256, a potem RIPEMD-160, czyli kombinacji, którą Bitcoin zamyka w jednym opkodzie o nazwie OP_HASH160. Wynik ma tylko 160 bitów, znacznie mniej niż klucz publiczny. Z tego hasha, po pewnym zakodowaniu i dodaniu sumy kontrolnej, portfel buduje znany adres Bitcoin. Warto zatrzymać się przy jednym szczególe: adresy tak naprawdę nie istnieją wewnątrz blockchaina. Są wygodą tworzoną przez portfele na podstawie tych hashy. To, co widzi protokół, to hash.

Kompromis polega na tym, że klucz publiczny nie jest już widoczny w wyjściu, a OP_CHECKSIG potrzebuje go do sprawdzenia podpisu. Wydający musi więc podać zarówno klucz publiczny, jak i podpis, a skrypt najpierw sprawdza, czy podany klucz rzeczywiście daje hash zapisany w blokadzie.

Blokada:      OP_DUP OP_HASH160 <HashKluczaPublicznego> OP_EQUALVERIFY OP_CHECKSIG
Odblokowanie: <Podpis> <KluczPubliczny>

Więcej o samym etapie haszowania znajdziesz w Czym jest hash?.

Krok po kroku przez skrypt P2PKH

Oto pełny skrypt P2PKH wykonywany krok po kroku. Skrypt odblokowujący idzie pierwszy.

  1. Podpis i klucz publiczny trafiają na stos.
  2. OP_DUP powiela element z wierzchu, czyli klucz publiczny, bo skrypt potrzebuje jednej kopii do zhaszowania i jednej do późniejszego sprawdzenia podpisu.
  3. OP_HASH160 bierze wierzchnią kopię klucza publicznego i ją haszuje, zostawiając na stosie świeży hash klucza publicznego.
  4. Oczekiwany hash ze skryptu blokującego trafia na stos, a OP_EQUALVERIFY porównuje oba hashe. Jeśli się różnią, skrypt od razu zawodzi. Jeśli są zgodne, oba są usuwane i wykonanie trwa dalej.
  5. To, co zostaje, jest teraz w praktyce skryptem P2PK: podpis i klucz publiczny. OP_CHECKSIG sprawdza podpis względem klucza i kładzie 1.

Na stosie zostaje pojedyncze 1, więc wyjście jest odblokowane. Mechanika jest identyczna niezależnie od tego, czy monety zablokowano starszym P2PKH, czy jego nowoczesnym odpowiednikiem SegWit, P2WPKH. Zmienia się tylko miejsce przechowywania danych podpisu.

P2PKH Script Execution

Step through how a node unlocks a Pay-to-Public-Key-Hash output.

Unlocking / scriptSig
<SIG><PK>
Locking / scriptPubKey
OP_DUPOP_HASH160<PKH>OP_EQUALVERIFYOP_CHECKSIG

Stack (top to bottom)

empty

Operation

Initial State

The script is ready. The unlocking script runs first, then the locking script.

Navigate step by step or press Play to advance automatically.
Step 0 / 8

Skrypty wielopodpisowe

Jedną z najbardziej przydatnych sztuczek Script jest wymóg więcej niż jednego podpisu do wydania. Standardowy skrypt multisig, typu P2MS, koduje regułę "m z n": spośród n wymienionych kluczy publicznych dowolne m poprawnych podpisów odblokowuje środki.

Multisig 2 z 3 wymaga na przykład 2 podpisów z zestawu 3 kluczy. To podstawa współdzielonej kontroli, gdzie żaden pojedynczy klucz nie może sam przesunąć pieniędzy. Stanowi fundament konfiguracji wielopodpisowych omawianych w naszych artykułach o bezpieczeństwie.

Blokada:      OP_2 <KluczPub1> <KluczPub2> <KluczPub3> OP_3 OP_CHECKMULTISIG
Odblokowanie: <Podpis1> <Podpis2>

OP_CHECKMULTISIG sprawdza zarówno to, czy obecna jest wymagana liczba poprawnych podpisów, jak i to, czy każdy należy do jednego z wymienionych kluczy. Zapisany wprost w ten sposób multisig ma jednak tę samą niewygodę co P2PK. Wysyłający musi znać każdy klucz publiczny i dokładny skrypt, wyjście staje się duże i drogie, a twoja konfiguracja bezpieczeństwa jest wystawiona on-chain na widok wszystkich. Kolejny wzorzec rozwiązuje to wszystko za jednym razem.

Pay-to-Script-Hash: ukrywanie złożoności

Pay-to-Script-Hash (P2SH) pozwala zablokować monety na hashu skryptu zamiast na samym skrypcie. Twój pełny, własny skrypt, zwany redeem script, pozostaje ukryty aż do chwili wydania.

Przy wysyłce na wyjście P2SH skrypt blokujący zawiera tylko hash. Wysyłający nie musi znać twojej struktury multisig ani twoich własnych warunków. Po prostu płaci na krótki adres zaczynający się od cyfry 3. Twój redeem script wraz z danymi, które go spełniają, dostarczasz dopiero później w skrypcie odblokowującym.

Blokada:      OP_HASH160 <HashSkryptu> OP_EQUAL
Odblokowanie: <Podpis1> <Podpis2> <RedeemScript>

Walidacja przebiega w dwóch etapach. Najpierw zewnętrzny skrypt potwierdza, że dostarczony redeem script daje hash zapisany w blokadzie. Następnie redeem script jest rozpakowywany i wykonywany jako osobny skrypt, względem dostarczonych podpisów. Monety przesuwają się tylko wtedy, gdy oba etapy przejdą pomyślnie. P2SH daje trzy korzyści naraz: mniejsze i tańsze wyjścia, czysty, ustandaryzowany adres oraz twoje warunki utrzymane w tajemnicy aż do chwili wydania.

Standardowe skrypty Bitcoina

Choć możesz zbudować niemal dowolny skrypt blokujący, większość węzłów przekazuje tylko niewielki zestaw standardowych wzorców. Poniższa tabela przedstawia typy skryptów, które ukształtowały Bitcoin, od ery legacy aż po SegWit i Taproot, wraz z ich prefiksami adresów i miejscem, w którym każdy przechowuje dane odblokowujące.

Podział na legacy i SegWit ma znaczenie. Skrypty legacy (P2PK, P2PKH, P2MS, P2SH) umieszczają dane odblokowujące w scriptSig. Skrypty SegWit (P2WPKH, P2WSH, P2TR) umieszczają je natomiast w osobnym polu zwanym witness, i właśnie to naprawiło podatność transakcji na zniekształcenia oraz obniżyło opłaty.

Standard Script Types

P2PK

Pay to Public Key

Legacy

Pattern

<PubKey> OP_CHECKSIG

Address

none

Unlocking

scriptSig

P2PKH

Pay to Public Key Hash

Legacy

Pattern

OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

Address

1...

Unlocking

scriptSig

P2MS

Bare Multisig

Legacy

Pattern

OP_m <PubKey> ... <PubKey> OP_n OP_CHECKMULTISIG

Address

none

Unlocking

scriptSig

P2SH

Pay to Script Hash

Legacy

Pattern

OP_HASH160 <ScriptHash> OP_EQUAL

Address

3...

Unlocking

scriptSig

P2WPKH

Pay to Witness Public Key Hash

SegWit

Pattern

OP_0 <PubKeyHash>

Address

bc1q...

Unlocking

witness

P2WSH

Pay to Witness Script Hash

SegWit

Pattern

OP_0 <ScriptHash>

Address

bc1q...

Unlocking

witness

P2TR

Pay to Taproot

Taproot

Pattern

OP_1 <TaprootOutputKey>

Address

bc1p...

Unlocking

witness

P2PK and bare P2MS have no standard address format. Multisig is almost always wrapped in P2SH or P2WSH today.

SegWit i Taproot: poza klasycznym Script

Aktualizacja SegWit z 2017 roku przeniosła dane podpisów poza główne ciało transakcji, do pola witness. Rozwiązało to długotrwały problem zwany malleability transakcji, w którym widoczny podpis można było zmienić tak, aby zmienić identyfikator transakcji bez zmiany jej znaczenia, a także obniżyło koszt dołączania danych podpisu. P2WPKH i P2WSH to po prostu wersje SegWit dla P2PKH i P2SH, które tworzą adresy zaczynające się od bc1q.

Co ciekawe, te nowsze typy skryptów ledwie korzystają z pełnego języka Script. Każdy z nich podąża za stałym wewnętrznym wzorcem, który węzły wykonują w ustalony sposób, czyli dokładnie tym uproszczeniem "wystarczy sprawdzić klucz i podpis", które klasyczny Script umożliwiał, ale nie wymuszał. Pełny język nadal żyje wewnątrz P2WSH, gdzie możesz opakować dowolny potrzebny ci skrypt.

Pay-to-Taproot (P2TR), aktywowany w listopadzie 2021 roku, to najnowszy standard tworzący adresy zaczynające się od bc1p. Łączy podpisy Schnorra ze strukturą zwaną MAST (Merkelized Abstract Syntax Trees), która pozwala zakodować w drzewie wiele alternatywnych warunków wydania. Co kluczowe, przy wydawaniu ujawniana jest tylko ta gałąź, której faktycznie używasz. Portfel z rozbudowanymi warunkami kopii zapasowej i odzyskiwania może więc wydawać w sposób identyczny ze zwykłą płatnością jednym kluczem, co poprawia zarówno prywatność, jak i efektywność.

Poza podpisami: blokady czasowe i zagadki

Script potrafi wyrazić znacznie więcej niż "udowodnij, że posiadasz ten klucz". Dwa opkody dodają wymiar czasu. OP_CHECKLOCKTIMEVERIFY (wprowadzony przez BIP 65) sprawia, że wyjścia nie da się wydać aż do wybranej daty lub wysokości bloku. OP_CHECKSEQUENCEVERIFY (BIP 112) wymusza opóźnienie względne, liczone od chwili otrzymania monet. Razem sprawiają, że warunki w rodzaju "te środki nie mogą się ruszyć przez sześć miesięcy" są egzekwowane przez sam protokół.

Te blokady czasowe są cegiełkami bardziej zaawansowanych konstrukcji. Hash Time Locked Contract (HTLC) na przykład łączy zagadkę hashową z blokadą czasową, tak aby płatność albo dochodziła do skutku po ujawnieniu sekretu, albo była zwracana po upływie terminu. To właśnie ten wzorzec umożliwia Lightning Network.

Script dopuszcza też czyste zagadki. Zagadka hashowa blokuje monety za warunkiem "dostarcz dane, które dają ten hash". Istnieje nawet zagadka kolizji hashy, która wypłaca każdemu, kto zdoła podać dwa różne dane wejściowe dające ten sam hash, co w praktyce jest publiczną nagrodą za złamaną funkcję skrótu. A specjalny opkod OP_RETURN pozwala dołączyć do wyjścia niewielką porcję danych, oznaczając je jako trwale niewydawalne, co jest czystym sposobem na zakotwiczenie informacji w łańcuchu bez rozdymania zbioru monet do wydania.

Ograniczenia, które utrzymują Bitcoin w bezpieczeństwie

Script ma ścisłe ograniczenia rozmiaru i istnieją one z tego samego powodu, dla którego język unika pętli: aby weryfikacja była szybka i aby nikt nie mógł obrócić go w broń przeciw sieci.

Twarde ograniczenia poprawności są jasne. Pełny skrypt nie może przekroczyć 10 000 bajtów. Może wykonać najwyżej 201 opkodów, nie licząc operacji, które tylko kładą dane na stosie. Żaden pojedynczy element położony na stosie nie może przekroczyć 520 bajtów, a sam stos nie może w danej chwili przechowywać więcej niż 1 000 elementów. Złam którekolwiek z nich, a skrypt jest niepoprawny, kropka.

Jest też warstwa łagodniejsza. Skrypt może być całkowicie poprawny, a mimo to niestandardowy, co oznacza, że węzły odmówią przekazywania go po sieci, nawet jeśli górnik mógłby wciąż umieścić go w bloku. To środek bezpieczeństwa: tylko dobrze przetestowane standardowe wzorce krążą swobodnie, dzięki czemu atakujący nie może zalać sieci dziwnymi skryptami, które wolno się weryfikuje. W praktyce transakcję niestandardową trzeba przekazać wprost górnikowi albo wykopać samodzielnie.

Dlaczego to ma znaczenie

Kuszące jest, by widzieć ograniczenia Script jako Bitcoin pozostający w tyle za bardziej "programowalnymi" łańcuchami. Prawda jest odwrotna. Każde ograniczenie jest tu świadomą wymianą ekspresyjności na przewidywalność, weryfikowalność i bezpieczeństwo.

Ponieważ żaden skrypt nie może działać w nieskończoność, każdy węzeł może potwierdzić cały łańcuch bez zaufania do kogokolwiek. Ponieważ język jest mały, mała jest powierzchnia ataku. Ponieważ nie istnieje globalny współdzielony stan, do którego kontrakty mogłyby sięgać, nie ma jednego punktu, w którym ktoś mógłby sięgnąć i zamrozić twoje monety. Ta sama elastyczność, która pozwala innym sieciom obiecywać więcej, jest też tym, co naraziło je na katastrofalne exploity i co pozwala kontrolującym je stronom przejmować lub zamrażać salda do woli.

Bitcoin postawił inaczej. Skromny, przewidywalny język, sprawdzany tak samo przez wszystkich, chroniący stały i neutralny zbiór reguł. To właśnie pozwala kajakowi płynąć po otwartej wodzie bez proszenia o pozwolenie, i o to dokładnie chodzi. Szerszy obraz tego, jak te reguły są egzekwowane w całej sieci, znajdziesz w Mechanizm konsensusu Bitcoina: dogłębna analiza, a strukturę, którą skrypty ostatecznie chronią, w Czym jest blockchain?.

Kluczowe Fakty

Bitcoin Script z założenia nie jest kompletny w sensie Turinga. Nie ma pętli ani rekurencji, więc każdy skrypt kończy się w ograniczonej, przewidywalnej liczbie kroków.

Każde wyjście niesie skrypt blokujący (scriptPubKey). Aby je wydać, transakcja musi dostarczyć pasujący skrypt odblokowujący (scriptSig albo pole witness w SegWit).

Skrypt jest poprawny, gdy po wykonaniu na stosie pozostaje jedna niezerowa wartość. Wszystko inne kończy się niepowodzeniem.

Pojedynczy skrypt Bitcoina jest ograniczony do 10 000 bajtów i najwyżej 201 wykonanych opkodów, przy czym żaden element danych nie może przekraczać 520 bajtów.

P2WPKH (natywny SegWit, 2017) oraz P2TR (Taproot, 2021) to nowoczesne standardowe typy skryptów, odblokowywane przez pole witness, a nie przez scriptSig.

Często zadawane pytania

Nie, i jest to zamierzone. Bitcoin Script nie jest kompletny w sensie Turinga, co oznacza, że nie potrafi wykonywać pętli ani dowolnych programów. Ta decyzja projektowa usuwa całe kategorie błędów i sprawia, że każdą transakcję da się szybko i tanio zweryfikować, nawet na skromnym sprzęcie.

scriptPubKey to skrypt blokujący dołączony do wyjścia. Określa warunki, które trzeba spełnić, aby wydać te monety. scriptSig to skrypt odblokowujący dostarczany przez osobę wydającą. Dostarcza dane, zwykle podpis i klucz publiczny, które spełniają te warunki.

Tak. Bitcoin Script obsługuje zagadki, blokady czasowe i warunki wielopodpisowe daleko wykraczające poza zwykłe sprawdzenie podpisu. Własne skrypty są poprawne i można je wykopać, ale większość węzłów przekazuje tylko niewielki zestaw standardowych wzorców, więc skrypt niestandardowy trudniej potwierdzić, chyba że jest opakowany w P2SH lub P2WSH.

Taproot wprowadził Pay-to-Taproot (P2TR), który łączy podpisy Schnorra z drzewem możliwych warunków wydania zwanym MAST. On-chain ujawniana jest tylko ta gałąź, której faktycznie używasz, więc złożony kontrakt wygląda tak samo jak prosta płatność, co poprawia zarówno prywatność, jak i efektywność miejsca w blokach.

Źródła

  1. 1.Greg Walker: Bitcoin Script (learnmeabitcoin.com)
  2. 2.Antonopoulos: Mastering Bitcoin, Chapter 7, Authorization and Authentication
  3. 3.Bitcoin Wiki: Script and Opcode List
  4. 4.BIP 16: Pay to Script Hash
  5. 5.BIP 141: Segregated Witness
  6. 6.BIP 341 and BIP 342: Taproot and Tapscript

To nie jest porada finansowa. CanoeBit publikuje wyłącznie treści edukacyjne. Nic tutaj nie stanowi rekomendacji kupna, sprzedaży ani trzymania jakiegokolwiek aktywa.