#!/usr/bin/env -S fift -s "TonUtil.fif" include "lib.fif" include { ."usage: " @' $0 type ." []" cr ."Creates a request to lightning wallet created by wallet-create.fif, with private key .pk " ."and state .addr, and saves it into -state.boc" cr ." transfers the specified amount of funds to the other user (can be zero)" cr ." indicates whether we created the wallet or not (1 or 0)" cr ." indicates whether this is a final state (1 or 0)" cr 1 halt } : usage $# 5 < ' usage if $1 =: state-base $2 =: key $3 parse-int =: isA $4 parse-int =: seqno $5 $>GR =: amount def? $6 { @' $6 parse-int } ' 0 cond constant final amount 0 < abort"Amount cannot be smaller than 0!" // seqno 2 mod =: turnB // turnB isA // 1 0 => 1 OK // 1 1 => 0 not OK // 0 0 => 0 not OK // 0 1 => 1 OK seqno 2 mod isA xor 1 <> { ."Not your turn! Ask the other user to generate a new state, first." cr 1 halt } if seqno 1 - =: prevseqno state-base +"-state" prevseqno (.) $+ +".boc" const previous-state state-base +"-state" prevseqno (.) $+ +"c.boc" const previous-statec state-base +"-state" seqno (.) $+ +".boc" const new-state state-base +"-state" seqno (.) $+ +"-ext.boc" const new-state-ext ."Preparing to create new state file: " new-state type ."..." cr ."Previous state file: " previous-state type cr previous-state file-exists? not { ."The previous state file was not created! Ask the other user to generate and send you a new state, first." cr 1 halt } if ."Confirmed previous state file: " previous-statec type cr previous-statec file-exists? not { ."The previous state file was not confirmed! Sign the previous state, first." cr 1 halt } if previous-statec file>B B>boc { ."Not enough signatures in previous state, need 2, have 1" cr 1 halt } if state-base +".addr" load-address 2dup 2constant wallet-addr ."Lightning wallet address = " 2dup .addr ." - " 6 .Addr cr key +".pk" load-keypair nip constant privkey ."Transferring " amount .GR ."to other user..." cr ."Old delta: " delta .GR cr // A can only make δ smaller (not bigger!) // B can only make δ bigger (not smaller!) isA { delta amount - delta! } { delta amount + delta! } cond ."New delta: " delta .GR cr // New state // state$_ signatures:MaybeTwoSignatures seqno:uint32 negative:Bool delta:Grams final:Bool {turnB:(seqno % 2)} = State; ."Signing new state with seqno " seqno . cr // .": " // // oneSignatureA$0 a:^Signature = MaybeTwoSignatures; // oneSignatureB$1 a:^Signature = MaybeTwoSignatures; // state$_ signatures:MaybeTwoSignatures seqno:uint32 delta:Grams final:Bool {turnB:(seqno % 2)} = State; ."Signed new state with seqno " seqno . cr // ."is: " // B dup Bx. cr new-state tuck B>file ."(Saved zerostate to file " type .")" cr // // addr_none$00 = MsgAddressExt; // addr_extern$01 len:(## 9) external_address:(bits len) // = MsgAddressExt; // anycast_info$_ depth:(#<= 30) { depth >= 1 } // rewrite_pfx:(bits depth) = Anycast; // addr_std$10 anycast:(Maybe Anycast) // workchain_id:int8 address:bits256 = MsgAddressInt; // addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) // workchain_id:int32 address:(bits addr_len) = MsgAddressInt; // // ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt // import_fee:Grams = CommonMsgInfo; // // // message$_ {X:Type} info:CommonMsgInfo // init:(Maybe (Either StateInit ^StateInit)) // body:(Either X ^X) = Message X; // ."resulting external message: " cr // B dup Bx. cr new-state-ext tuck B>file ."(Saved to file " type .")" cr cr cr