"TonUtil.fif" include "lib.fif" include { ."usage: " @' $0 type ." [ ...]" cr cr ."Creates a new multisignature wallet in specified workchain composed of (1-10) keys." cr ."The first of the keys must be a private key (pre-existing or not), used to generate the wallet; the rest MUST be public keys." cr ."Create or generate public key files from private keys using gen-pub.fif privkey" cr cr ."Min (1-10) signatures required to send an order; load pre-existing public keys from files ." cr 1 halt } : usage $# 5 < ' usage if $1 parse-workchain-id =: wc // set workchain id from command line argument $2 constant file-base $3 (number) 1 <> abort" must be a number!" constant n $4 (number) 1 <> abort" must be a number!" constant k n 1 < n 10 > or abort" must be between 1 and 10" k 1 < k 10 > or abort" must be between 1 and 10" k n <= not abort" must smaller than or equal to " $# 4 n + < abort"Not enough keys were provided in args!" $5 +".pk" load-generate-keypair const privkey 256 B>u@ 6 { dup $() +".pubkey" load-pubkey swap 1+ } n 1- times drop n tuple constant keys cr ."Creating new multisignature wallet in workchain " wc . ."with n=" n . ."k=" k . ."..." cr cr // idict! (v x s n – s0 −1 or s 0), adds a new value v (represented // by a Slice) with key given by signed big-endian n-bit integer x into // dictionary s with n-bit keys, and returns the new dictionary s0 and −1 // on success. Otherwise the unchanged dictionary s and 0 are returned. // Create dictionaries with keys and messages // Extract keys keys explode dup 1- // Create counter dictnew swap // ...and dict (swap the two) rot // Put length on top for times { dup 1- swap // Decrement counter (val dict ncount curcount) 3 roll // Get n-th value v (dict ncount curcount val) udict! // Store (ncount dict') not abort"Failure storing dictionary value!" swap // Swap dict (dict' ncount) } swap times drop const keys-dict .s // code "wallet-code.fif" include // data // storage$_ seqno:uint32 minSigs:(## 4) keys:(HashmapE 4 PubKey) messages:(HashmapE 256 (MultiSigWrapperStorage X)) // { minSigs > 0 } { n >= minSigs } { n <= 10 } { minSigs <= 10 } = Storage X; // create StateInit // _ split_depth:(Maybe (## 5)) special:(Maybe TickTock) // code:(Maybe ^Cell) data:(Maybe ^Cell) // library:(HashmapE 256 SimpleLib) = StateInit; // split_depth 0 special 0 code 1 data 1 library hme_empty 0 // dup ."StateInit: " // dup ."signing message: " dup ."External message for initialization is " B dup Bx. cr file-base +"-create.boc" tuck B>file ."(Saved wallet creating query to file " type .")" cr