„Vajúdnak a hegyek: nevetséges kisegér születik”
Horatius
Bástya elvtárs: Mi ez?
Pelikán: Narancs.
Bástya elvtárs: Narancs?!
Pelikán: Az új magyar narancs.
Kicsit sárgább, kicsit savanyúbb, de a mienk.
Bacsó Péter: A tanú
ASC1: Algorand Smart Contract on Layer 1
TEAL: Transaction Execution Approval Language
Egy mindent engedélyező szerződés
Téma és variációk: szerződés, egy bemenettel
Téma és variációk: szerződés hash preimage használatával
Téma és variációk: fogadás hash preimage használatával
A TEAL alacsony szintű, assembler-szerű nyelv, melyben leírható, hogy egy fizetési művelet végrehajtása előtt milyen további logikai feltételek vizsgálatára kerüljön sor. A TEAL program végeredménye 0 vagy 1 a stack-en, amely tiltja vagy engedélyezi a tranzakció végrehajtását. A TEAL lefordításával előálló file kétféleképpen építhető be a fizetési műveletekbe:
Fontos tudnunk, hogy a TEAL kód a tranzakció részeként tárolódik a blokkláncon.
A TEAL-t végrehajtó gép jellemzői:
Adattípusok:
Adatkonverziók:
Megjegyzés: az sha256 bemenete []byte, kimenete [32]byte. A hash-en végezhető művelet az egyenlőség vizsgálata (==) vagy a nem egyenlőség viszgálata (!=). A btoi függvényt a hash eredményére alkalmazva a fg. hibával elszáll, ugyanis a [32]byte hash tömb hosszabb 8-nál. Emiatt a TEAL-ben a Bitcoin-hoz hasonló „bányászati” logika nem írható le.
Műveletek:
Függvények:
uint megadása a TEAL-ben:
[]byte megadása a TEAL-ben:
Megjegyzés:
[]byte => hexadecimális konverzió:
$ python
"ABC".encode('hex')
'414243'
[]byte => base64 konverzió:
$ printf "ABC" | base64
QUJD
base64 => []byte konverzió:
$ printf "QUJD" | base64 -d
ABC
uint64 => base64 konverzió, ill. base64 => uint64 konverzió:
$ python
Python 2.7.15+ (default, Oct 7 2019, 17:39:04)
>>> import hashlib
>>> import base64
>>> import struct
>>> i=1234
>>> struct.pack(">H", i)
'\x04\xd2'
>>> base64.b64encode(struct.pack(">H", i))
'BNI='
>>> base64.b64decode('BNI=')
'\x04\xd2'
>>>
$ python3
Python 3.6.9 (default, Nov 7 2019, 10:44:02)
>>> import base64
>>> import math
>>> i=1234
>>> base64.b64encode(i.to_bytes(math.ceil(i.bit_length()/8),'big'))
b'BNI='
>>> base64.b64decode('BNI=')
b'\x04\xd2'
>>>
A legegyszerűbb szerződés TEAL nyelven mindent engedélyez azzal, hogy 1-et tesz föl a stack-re:
$ nano p1.teal
// mindent engedélyez
int 1
A szerződés a következőképpen fordítható le:
$ ./goal clerk compile p1.teal
p1.teal: 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY
A lefordított kód a .tok file-ba kerül. A .tok file tartalma:
$ hexdump -C p1.teal.tok
00000000 01 20 01 01 22 |. .."|
00000005
A kód disassemblálható (visszafordítható) a -D kapcsolóval:
$ ./goal clerk compile -D p1.teal.tok
// version 1
intcblock 1
intc_0
A kód mint szerződés egy fizetési műveletbe úgy iktatható be, hogy a küldő címe helyett (-f (addr)) a --from-program (teal-program) parancsrészt adjuk meg, továbbá megadjuk a számla zárási címet ("close" address) is a -c-vel:
$ ./goal account list -w w1 -d data
Please enter the password for wallet 'w1':
[offline] Unnamed-2 GCDEMV3UUGUAVCWPU3PSG4ONB2AGJNNFYD32VYPOOYQYJAYNGV55EAW2EQ 898000 microAlgos
0 units (creator , ID 1081)
[offline] Unnamed-0 I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM 97458533 microAlgos *Default
[offline] Unnamed-1 QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E 1998258 microAlgos
$ ./goal clerk send -a 12 -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM --from-program p1.teal -d data -o p1.txn
$ ./goal clerk inspect p1.txn
p1.txn[0]
{
"lsig": {
"l": "// version 1\nintcblock 1\nintc_0\n"
},
"txn": {
"amt": 12,
"close": "I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM",
"fee": 1000,
"fv": 755692,
"gen": "betanet-v1.0",
"gh": "mFgazF+2uRS1tMiL9dsj01hJGySEmPN28B/TjjvpVW0=",
"lv": 756692,
"note": "vT7z5d+SHrs=",
"rcv": "QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E",
"snd": "6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY",
"type": "pay"
}
}
Látható, hogy így az "snd" mezőbe a szerződés címe kerül. Megjelenik továbbá a tranzakcióban a "lsig" JSON mező, amelyen belül a "l" mezőben a TEAL-lel leírt logika található. Az "l" utáni tartalom nem más, mint a TEAL bytekód vissza-assemblált listája.
A szerződés logikájának a működését a "dryrun" paranccsal lehet tesztelni:
$ ./goal clerk dryrun -t p1.txn -d data
tx[0] cost=2 trace:
1 intcblock => <empty stack>
4 intc_0 => 1 0x1
- pass -
$
A "pass" azt mutatja, hogy a szerződés engedélyezi a fizetési műveletet, ami nem más, mint 12 /uAlgo küldése a 6Z3C... címről a QNEO... címre. A tranzakció a rawsend paranccsal küldhető el az Algorand hálózatnak:
$ ./goal clerk rawsend -f p1.txn -d data
Raw transaction ID MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA issued
Transaction MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA still pending as of round 755809
Transaction MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA committed in round 755811
Ha az Algoexplorer-rel megnézzük, hogy a szerződés címén milyen tranzakciók voltak, azt látjuk, hogy 3 hónapja már valaki feltöltötte ezt a szereződést 100 Algóval, most pedig kiürítettük:
TRANSACTION DETAILS
TxID MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA
Block 755811
Age 7 minutes ago
From 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY
To QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E
Close: I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM
Value 0.000012 Algos
100.945588 Algos
Fee 0.001 Algos
TxID D3CX2LW4RIKCLQY66P7VMXFOLXC5KPSQC7JTXAI7ZS75DQHWFPUQ
Block 123979
Age 3 months ago
From E6JSNTY4PVCY3IRZ6XEDHEO6VIHCQ5KGXCIQKFQCMB2N6HXRY4IB43VSHI
To 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY
Close:
Value 100 Algos
0 Algos
Fee 0.01 Algos
Nézzük meg, mi történik, ha még egyszer elküldjük a tranzakciót:
$ ./goal clerk rawsend -f p1.txn -d data
Warning: Couldn't broadcast tx with algod: HTTP 400 Bad Request: TransactionPool.Remember: transaction already in ledger: MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA
Encountered errors in sending 1 transactions:
MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA: HTTP 400 Bad Request: TransactionPool.Remember: transaction already in ledger: MIH2IB3L4QNI7IZXE24JTNA4PGLTPZMVIOVOM72Y4VRLJIQHCYOA
Rejected transactions written to p1.txn.rej
Hibát kapunk, mert ez a tranzació már bekerült a blokkláncba. Ugyanazt a tranzakció kétszer nem kerülhet be a blokkláncba, mert a tranzakció ugyanazzal a hash-sel rendelkezik, és emiatt ugyanaz lenne a tranzakció azonosítója.
Ha újra létrehozzuk a tranzakciót, és ezt az új tranzakciót elküldjük a hálózatnak, akkor "overspend" hibát kapunk, hiszen a szerződéshez tartozó címen már nem található semmilyen forrás, lenulláztuk az előző tranzakció során:
$ ./goal clerk send -a 12 -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM --from-program p1.teal -d data -o p1.txn
$ ./goal clerk rawsend -f p1.txn -d data
Warning: Couldn't broadcast tx with algod: HTTP 400 Bad Request: TransactionPool.Remember: transaction 5IYNA47EIREPARMXLAQVYBDWAM4MR2746NIJVLXMFEG6YKCQYTKQ: overspend (account 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY, data {_struct:{} Status:Offline MicroAlgos:{Raw:0} RewardsBase:0 RewardedMicroAlgos:{Raw:0} VoteID:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] SelectionID:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] VoteFirstValid:0 VoteLastValid:0 VoteKeyDilution:0 AssetParams:map[] Assets:map[]}, tried to spend {1000})
Töltsük fel a szerződéshez tartozó címet 1 Algóval, majd küldjük el ismét a tranzakciót:
$ ./goal clerk send -a 1000000 -f I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM -t 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY -d data
Please enter the password for wallet 'w1':
Sent 1000000 MicroAlgos from account I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM to address 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY, transaction ID: LPSSKQ7S6AZJF3T6JBFLCUXVSSRXOGNBUOE6OWWKJSPBFLBUOPTA. Fee set to 1000
Transaction LPSSKQ7S6AZJF3T6JBFLCUXVSSRXOGNBUOE6OWWKJSPBFLBUOPTA still pending as of round 756180
Transaction LPSSKQ7S6AZJF3T6JBFLCUXVSSRXOGNBUOE6OWWKJSPBFLBUOPTA committed in round 756182
$ ./goal clerk send -a 12 -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM --from-program p1.teal -d data -o p1.txn
$ ./goal clerk rawsend -f p1.txn -d data
Raw transaction ID XA6WNAIBL7SJ6RRHFVROQ3KYCX7A3EM6TUAU3FXIZHBAZVJ2TIQA issued
Transaction XA6WNAIBL7SJ6RRHFVROQ3KYCX7A3EM6TUAU3FXIZHBAZVJ2TIQA still pending as of round 756187
Transaction XA6WNAIBL7SJ6RRHFVROQ3KYCX7A3EM6TUAU3FXIZHBAZVJ2TIQA committed in round 756189
$
Ha az Algoexplorer-rel megnézzük, hogy a legutolsó tranzakció során mi történt, a következőket látjuk:
TxID: XA6WNAIBL7SJ6RRHFVROQ3KYCX7A3EM6TUAU3FXIZHBAZVJ2TIQA
Status: Completed
Block: 756189
Sender: 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY
Receiver: QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E
Amount: 0.000012 Algos
Fee: 0.001 Algos
Sender balance:0 Algos
First round: 756185
Last round: 757185
Close address: I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM
Close amount: 0.998988 Algos
Type: pay
Created at: Tue Dec 03 2019 16:52:35 GMT+0100 (közép-európai téli idő)
A TEAL-ben megírt logikának a "send" során argumentumok, azaz bemeneti paraméterek is megadhatók. Írjunk most egy olyan szerződést, amely a megfelelő argumentum megadásával teszi lehetővé a költést. A lenti TEAL program az arg_0 bemeneti paramétert uint64 típussá alakítja át, majd összehasonlítja a 42-vel. A stack-en akkor lesz 1, ha az uint64(par_0) és a 42 egyenlő.
$ nano ex1.teal
arg_0
btoi
int 42
==
A paramétereket a "goal clerk send"-ben base64 alakban kell megadni. Az uint64 tipusú 42 átkódolása base64 alakra:
>>> i=42
>>> base64.b64encode(i.to_bytes(math.ceil(i.bit_length()/8),'big'))
b'Kg=='
>>>
A tranzakció ugyanúgy állítható össze, mint az előző példában. Új elem a parancssorban az "--argb64 Kg==". A tranzakció vizsgálatakor (goal clerk inspect) az "lsig" JSON objektumban az "arg" a bemenő paramétereket tartalmazza, az "l" pedig a TEAL program disassemblált listája.
$ ./goal clerk send -a 1234 -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E --from-program ex1.teal -d data -o ex1.txn --argb64 Kg==
$
$ ./goal clerk inspect ex1.txn
ex1.txn[0]
{
"lsig": {
"arg": [
"Kg=="
],
"l": "// version 1\nintcblock 42\narg_0\nbtoi\nintc_0\n==\n"
},
"txn": {
"amt": 1234,
"close": "QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E",
"fee": 1000,
"fv": 736944,
"gen": "betanet-v1.0",
"gh": "mFgazF+2uRS1tMiL9dsj01hJGySEmPN28B/TjjvpVW0=",
"lv": 737944,
"note": "py5LutuV0/c=",
"rcv": "QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E",
"snd": "72BTTM2ZWYFGYQ75BDCW45GKLRZHDGLMSFXVXWGOZYV26MKLGGQSDNR7MU",
"type": "pay"
}
}
$ ./goal clerk dryrun -t ex1.txn -d data
tx[0] cost=5 trace:
1 intcblock => <empty stack>
4 arg_0 => 2a
5 btoi => 42 0x2a
6 intc_0 => 42 0x2a
7 == => 1 0x1
- pass -
$
$ ./goal clerk send -a 1001234 -f I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM -t 72BTTM2ZWYFGYQ75BDCW45GKLRZHDGLMSFXVXWGOZYV26MKLGGQSDNR7MU -d data
Please enter the password for wallet 'w1':
Sent 1001234 MicroAlgos from account I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM to address 72BTTM2ZWYFGYQ75BDCW45GKLRZHDGLMSFXVXWGOZYV26MKLGGQSDNR7MU, transaction ID: 45MHTV37Y55ZIBTKYUEIYO4KKFTCHGJSYIZNHOXTUDJIGJNHBYWA. Fee set to 1000
Transaction 45MHTV37Y55ZIBTKYUEIYO4KKFTCHGJSYIZNHOXTUDJIGJNHBYWA still pending as of round 737013
Transaction 45MHTV37Y55ZIBTKYUEIYO4KKFTCHGJSYIZNHOXTUDJIGJNHBYWA still pending as of round 737015
Transaction 45MHTV37Y55ZIBTKYUEIYO4KKFTCHGJSYIZNHOXTUDJIGJNHBYWA committed in round 737016
$
$ ./goal clerk rawsend -f ex1.txn -d data
Raw transaction ID 3RXEU4VXQAJ2SDFDOTRFAU5S2BJAV3VOWMCWGHZJB5JCRJCTFELQ issued
Transaction 3RXEU4VXQAJ2SDFDOTRFAU5S2BJAV3VOWMCWGHZJB5JCRJCTFELQ still pending as of round 737023
Transaction 3RXEU4VXQAJ2SDFDOTRFAU5S2BJAV3VOWMCWGHZJB5JCRJCTFELQ committed in round 737025
$
Megjegyzés: Megírhattuk volna a szerződést úgy is, hogy két []byte tömb között történjen az összehasonlítás. Ekkor:
$ nano ex1a.teal
arg_0
byte 0x3432 // "42"
==
$
$ printf 42 | base64
NDI=
$ ./goal clerk send -a 12 -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM --from-program ex1a.teal -d data -o ex1a.txn --argb64 NDI=
$ ./goal clerk dryrun -t ex1a.txn -d data
tx[0] cost=4 trace:
1 bytecblock => <empty stack>
6 arg_0 => 3432
7 bytec_0 => 3432
8 == => 1 0x1
- pass -
$
Legyen az sha256 preimage egyetlen szóköz karakter.
Az sha256(" ") base64 alakjának kiszámítása Python2-ben:
$ python
>>> import hashlib
>>> import base64
>>> base64.b64encode(hashlib.sha256(" ").digest(), )
'Nqnn8clbgv+5l0PgxcTOldg8mkMKrFn4TvPL+rYUUGg='
>>>
A TEAL kód, és lefordítása:
$ nano ex2.teal
//# preimage in arg_0 is " "
arg_0
sha256
byte base64 Nqnn8clbgv+5l0PgxcTOldg8mkMKrFn4TvPL+rYUUGg=
==
$
$ ./goal clerk compile ex2.teal
ex2.teal: EOWMS2Z5YWXALIJBQ5V7LOG36K2IRCCLQCDNXCQRMR7VOREE7AZX6KOW6U
$ ls ex2.*
ex2.teal ex2.teal.tok
$ ./goal clerk compile -D ex2.teal.tok
// version 1
bytecblock 0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a430aac59f84ef3cbfab6145068
arg_0
sha256
bytec_0
==
A " " hash preimage base64-es alakja:
$ printf " " | base64
IA==
$
A tranzakció, amely a szerződésből próbál költeni:
$ ./goal clerk send -a 12 -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM --from-program ex2.teal -d data -o ex2.txn --argb64 IA==
$ ./goal clerk dryrun -t ex2.txn -d data
tx[0] cost=11 trace:
1 bytecblock => <empty stack>
36 arg_0 => 20
37 sha256 => 36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a430aac59f84ef3cbfab6145068
38 bytec_0 => 36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a430aac59f84ef3cbfab6145068
39 == => 1 0x1
- pass -
$
Mint az előző példában, most is fel kell tölteni a szerződést a goal clerk send paranccsal. Ezt követően a goal clerk rawsend paranccsal küldhető el a tranzakció az Algorand hálózatnak.
$ ./goal clerk send -a 100000 -f I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM -t EOWMS2Z5YWXALIJBQ5V7LOG36K2IRCCLQCDNXCQRMR7VOREE7AZX6KOW6U -d data
Please enter the password for wallet 'w1':
Sent 100000 MicroAlgos from account I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM to address EOWMS2Z5YWXALIJBQ5V7LOG36K2IRCCLQCDNXCQRMR7VOREE7AZX6KOW6U, transaction ID: S5ECADUE3K3Q7G5VD34FGYHHU4BEC4N4U6HCRQLPCLSOTJD5DLBQ. Fee set to 1000
Transaction S5ECADUE3K3Q7G5VD34FGYHHU4BEC4N4U6HCRQLPCLSOTJD5DLBQ still pending as of round 751240
Transaction S5ECADUE3K3Q7G5VD34FGYHHU4BEC4N4U6HCRQLPCLSOTJD5DLBQ committed in round 751242
$ ./goal clerk rawsend -f ex2.txn -d data
Raw transaction ID G7GY6RLD6SNUDC3IIGS5I35BBNE3OJGBBDVAGIQPXFH7KLCY63MA issued
Transaction G7GY6RLD6SNUDC3IIGS5I35BBNE3OJGBBDVAGIQPXFH7KLCY63MA still pending as of round 751261
Transaction G7GY6RLD6SNUDC3IIGS5I35BBNE3OJGBBDVAGIQPXFH7KLCY63MA committed in round 751263
Megjegyzés: Ha preimage-nek a "" üres stringet választottuk volna, akkor azt nem tudtuk volna megadni --argb64 paraméterként.
Képzeljük el, hogy szeretnénk az Algorand blokkláncon fogadást kötni arra vonatkozóan, hogy vajon az FTC vagy a Vasas győz-e a következő rangadón. A fogadóiroda előre létre tud hozni nekünk egy szerződést arra a csapatra vonatkozóan, amelyre fogadni szeretnénk. A fogadóiroda el tudja helyezni a szerződésben az következő adatok hash-ét:
sha256("XXX győzött"+"dátum"+"a mi nyilvános kulcsunk"+"titok"), ahol a titok 32 kvázi-véletlen byte,
majd elküldi nekünk a szerződés címét. Ezt követően a szerződésre el tudjuk küldeni a fogadás díját, és a fogadóiroda is el tudja küldeni a szerződésnek a nyeremény összegét.
Ha nyertünk, akkor a fogadóiroda elküldi nekünk a hash preimage-et, vagyis a "XXX győzött"+"dátum"+"a mi nyilvános kulcsunk"+"titok" üzenetet. Ennek birtokában fel tudjuk venni a szerdődésre átutalt nyereményt. Persze, más is képes lenne erre, ha megtudja a hash preimage-et! (Kérdés: lehet-e olyan szerződést írni, amelyből csak a nyertes képes felvenni a nyereményt?)
A hash preimage és a hash kialakítása Python-ban:
$ python
>>> import hashlib
>>> import base64
>>>
>>> import os
>>> a=os.urandom(32)
>>> a.encode('base64')
'WxsT3Syh2yGp3pKkynTf1vc8YufC0raLMKQm5o8/Pn4=\n'
>>>
>>> b="FTC won"
>>> b
'FTC won'
>>>
>>> import time
>>> ts=time.time()
>>> ts
1575364156.828548
>>>
>>> import datetime
>>> c=datetime.datetime.fromtimestamp(ts)
>>> c
datetime.datetime(2019, 12, 3, 10, 9, 16, 828548)
>>> c.isoformat()
'2019-12-03T10:09:16.828548'
>>> d=c.isoformat()
>>> a
'[\x1b\x13\xdd,\xa1\xdb!\xa9\xde\x92\xa4\xcat\xdf\xd6\xf7<b\xe7\xc2\xd2\xb6\x8b0\xa4&\xe6\x8f?>~'
>>> b
'FTC won'
>>> d
'2019-12-03T10:09:16.828548'
>>> e=b+" "+d+" "+a
>>> e
'FTC won 2019-12-03T10:09:16.828548 [\x1b\x13\xdd,\xa1\xdb!\xa9\xde\x92\xa4\xcat\xdf\xd6\xf7<b\xe7\xc2\xd2\xb6\x8b0\xa4&\xe6\x8f?>~'
>>> base64.b64encode(e)
'RlRDIHdvbiAyMDE5LTEyLTAzVDEwOjA5OjE2LjgyODU0OCBbGxPdLKHbIanekqTKdN/W9zxi58LStoswpCbmjz8+fg=='
>>>
>>>
>>> hashlib.sha256(e).digest().encode('base64')
'c6cDNFNf6zN4fAkUt2fH/qCywJN4HLFTPvmJj7IDA/Y=\n'
>>> hashlib.sha256(e).hexdigest()
'73a70334535feb33787c0914b767c7fea0b2c093781cb1533ef9898fb20303f6'
>>>
A TEAL-ben megírt szerződés:
$ nano ex4.teal
// preimage in arg_0 is 'FTC won 2019-12-03T10:09:16.828548 [\x1b\x13\xdd,\xa1\xdb!\xa9\xde\x92\xa4\xcat\xdf\xd6\xf7<b\xe7\xc2\xd2\xb6\x8b0\xa4&\xe6\x8f?>~'
// preimage in base64 is RlRDIHdvbiAyMDE5LTEyLTAzVDEwOjA5OjE2LjgyODU0OCBbGxPdLKHbIanekqTKdN/W9zxi58LS\ntoswpCbmjz8+fg==
arg_0
sha256
byte 0x73a70334535feb33787c0914b767c7fea0b2c093781cb1533ef9898fb20303f6
==
$
A szerződés lefordítása és a tranzakció kialakítása:
$ ./goal clerk compile ex4.teal
ex4.teal: C7E4FFVJP3WDMEN3QXYBTTO6K6ZDCWYTTCDLELJDYKUPJJPD7MMMEH7L7Q
$
$ $ ./goal clerk send -a 12 -t QNEOAAHOHK5CUVZVJEA4HBLIXIXFVDC6R7JXSK5Y6HHLQW3VOJWAR2AT5E -c I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM --from-program ex4.teal -d data -o ex4.txn --argb64 RlRDIHdvbiAyMDE5LTEyLTAzVDEwOjA5OjE2LjgyODU0OCBbGxPdLKHbIanekqTKdN/W9zxi58LStoswpCbmjz8+fg==
$
A szerződés tesztelése:
$ ./goal clerk dryrun -t ex4.txn -d data
tx[0] cost=11 trace:
1 bytecblock => <empty stack>
36 arg_0 => 46544320776f6e20323031392d31322d30335431303a30393a31362e383238353438205b1b13dd2ca1db21a9de92a4ca74dfd6f73c62e7c2d2b68b30a426e68f3f3e7e
37 sha256 => 73a70334535feb33787c0914b767c7fea0b2c093781cb1533ef9898fb20303f6
38 bytec_0 => 73a70334535feb33787c0914b767c7fea0b2c093781cb1533ef9898fb20303f6
39 == => 1 0x1
- pass -
$
A tranzakció tényleges próbája előtt a szerződés címére pénzt kell küldeni:
$ ./goal clerk send -t C7E4FFVJP3WDMEN3QXYBTTO6K6ZDCWYTTCDLELJDYKUPJJPD7MMMEH7L7Q -f I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM -a 1000000 -d data
Please enter the password for wallet 'w1':
Sent 1000000 MicroAlgos from account I7TXJS23FOZZIDFTSQUMRVLFXNG7HCY6ZRGCQULOCMRM47M6I6PEGESSFM to address C7E4FFVJP3WDMEN3QXYBTTO6K6ZDCWYTTCDLELJDYKUPJJPD7MMMEH7L7Q, transaction ID: MHFG2GBERNRLHCMI4HJF53E7IGV6WUSVP4SC7B6AB26GLEPF556Q. Fee set to 1000
Transaction MHFG2GBERNRLHCMI4HJF53E7IGV6WUSVP4SC7B6AB26GLEPF556Q still pending as of round 752735
Transaction MHFG2GBERNRLHCMI4HJF53E7IGV6WUSVP4SC7B6AB26GLEPF556Q still pending as of round 752737
Transaction MHFG2GBERNRLHCMI4HJF53E7IGV6WUSVP4SC7B6AB26GLEPF556Q committed in round 752738
Ezután a tranzakció a "goal clerk rawsend" paranccsal elküldhető az Algroand hálózatnak:
$ ./goal clerk rawsend -f ex4.txn -d data
Raw transaction ID QARL4277KR2M2DFZMYCZCVGSHDRKYAMQDXDWES4ANT3NZ4IF5BCQ issued
Transaction QARL4277KR2M2DFZMYCZCVGSHDRKYAMQDXDWES4ANT3NZ4IF5BCQ still pending as of round 752748
Transaction QARL4277KR2M2DFZMYCZCVGSHDRKYAMQDXDWES4ANT3NZ4IF5BCQ committed in round 752750
$
Megtörténik a szerződés címén lévő pénz átutalása a "-t" és "-c" után megadott címekre. ("To", ill. "Close" address)
A TEAL másik használati módja az, hogy aláírjuk a lefordított TEAL programot valamelyik címhez tartozó titkos kulccsal. Ezek utan az adott címről történő műveletek esetén a TEAL-ben leírt logika is lefuttatásra kerül. A folyamat hasonló a szerződésnél látotthoz, csak itt az lsig JSON objektumot alkotó elemek:
Lássunk egy egyszerű példát! Küldjünk 1 /uAlgót a JW6L... címről a OSWE... címre:
$ ./goal clerk send -a 1 -f JW6L2ZCQT3UIQH5AFM3CVW3C7M3QFYHXA3EU4WHREOATRWMXP6MBFNKILM -t OSWEIKXSTSVH7KV65N24USUNANXRKGACZEG3ZF2U6UCPCSAY4WRBWAKYYU -o tx1.txn -d data_testnet
Please enter the password for wallet 'w1':
$
Legyen a plusz logikai feltétel megvalósító TEAL program az alábbi:
$ cat p0.teal
// version 1
int 1
int 2
==
$
Fordítsuk le a TEAL logikát, és írjuk alá a TEAL logikai feltételt a küldő címhez tartozó privát kuccsal:
$ ./goal clerk compile p0.teal -s -o p0.lsig -w w2 -a JW6L2ZCQT3UIQH5AFM3CVW3C7M3QFYHXA3EU4WHREOATRWMXP6MBFNKILM -d data_testnet
Please enter the password for wallet 'w2':
$ ./goal clerk inspect p0.lsig
Cannot decode transactions from p0.lsig: msgpack decode error [pos 3]: no matching struct field found when decoding stream map with key l
$ hexdump -C p0.lsig
00000000 82 a1 6c c4 08 01 20 02 01 02 22 23 12 a3 73 69 |..l... ..."#..si|
00000010 67 c4 40 22 54 01 61 92 8e d7 69 84 09 20 09 87 |g.@"T.a...i.. ..|
00000020 99 dd ee 14 2c 07 07 31 72 bb 1d e1 ca 64 ae 32 |....,..1r....d.2|
00000030 19 93 85 bf 4f c2 61 28 06 57 fb 11 23 2e ba c9 |....O.a(.W..#...|
00000040 81 2d 3c 46 bd 44 c2 65 17 ca c9 ef fc 3a 4a f7 |.-<F.D.e.....:J.|
00000050 42 ec 0d |B..|
00000053
$
Írjuk alá a küldési tranzakciót a logikai feltétellel, és vizsgáljuk meg az így létrejött tranzakciót:
$ ./goal clerk sign -L p0.lsig -i tx1.txn -o stx1.txn -d data_testnet
$ ./goal clerk inspect stx1.txn
stx1.txn[0]
{
"lsig": {
"l": "// version 1\nintcblock 1 2\nintc_0\nintc_1\n==\n",
"sig": "IlQBYZKO12mECSAJh5nd7hQsBwcxcrsd4cpkrjIZk4W/T8JhKAZX+xEjLrrJgS08Rr1EwmUXysnv/DpK90LsDQ=="
},
"txn": {
"amt": 1,
"fee": 1000,
"fv": 3487330,
"gen": "testnet-v1.0",
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 3488330,
"note": "P0EZtPxSHiI=",
"rcv": "OSWEIKXSTSVH7KV65N24USUNANXRKGACZEG3ZF2U6UCPCSAY4WRBWAKYYU",
"snd": "JW6L2ZCQT3UIQH5AFM3CVW3C7M3QFYHXA3EU4WHREOATRWMXP6MBFNKILM",
"type": "pay"
}
}
$
Látható, hogy a "lsig" JSON struktúrában az "l" és a "sig" elemek vannak jelen, ahol az "l" a TEAL bytekód disassemblált alakja, a "sig" pedig egy aláírás, amely a JW6L... címhez tartozó privát kulccsal írja alá a TEAL byte kódot.
Nézzük meg szimuláció szintjén, mi történne, ha elküldenénk ezt a tranzakciót az Algorand hálózatnak:
$ ./goal clerk dryrun -t stx1.txn -d data_testnet
tx[0] cost=4 trace:
1 intcblock => <empty stack>
5 intc_0 => 1 0x1
6 intc_1 => 2 0x2
7 == => 0 0x0
REJECT
$
A logika természetesen elutasítja a tranzakció végrehajtását, mert az 1 és a 2 nem egyenlő egymással.
Ugyanez a tranzakció a logikai feltétel nélkül a következőképpen nézne ki:
$ ./goal clerk sign -i tx1.txn -o stx1m.txn -w w2 -d data_testnet
Please enter the password for wallet 'w2':
lipi@lipi-VirtualBox:~/node$ ./goal clerk inspect stx1m.txn
stx1m.txn[0]
{
"sig": "C1oisZrc/L93JL1We6MKcTy5xPUc51MKyhELaDnWqfHm3M0bPhG1rfTqYHODgfeOnc26pKFKYYRj/fmRr6O2Aw==",
"txn": {
"amt": 1,
"fee": 1000,
"fv": 3487330,
"gen": "testnet-v1.0",
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 3488330,
"note": "P0EZtPxSHiI=",
"rcv": "OSWEIKXSTSVH7KV65N24USUNANXRKGACZEG3ZF2U6UCPCSAY4WRBWAKYYU",
"snd": "JW6L2ZCQT3UIQH5AFM3CVW3C7M3QFYHXA3EU4WHREOATRWMXP6MBFNKILM",
"type": "pay"
}
}
$ ./goal clerk dryrun -t stx1m.txn -d data_testnet
$