1
0
mirror of https://github.com/danog/toncontest.git synced 2024-11-30 04:29:14 +01:00
toncontest/wallet/wallet-create.fif
2019-10-06 20:41:54 +02:00

160 lines
5.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"TonUtil.fif" include
' constant : const
{ dup ."Loading public key from file " type ."..." cr
file>B dup Blen 32 <> abort"Public key must be exactly 32 bytes long"
256 B>u@
} : load-pubkey
{ dup ."Loading order from file " type ."..." cr
file>B B>boc
} : load-boc
{ ."usage: " @' $0 type ." <workchain-id> <wallet-name> <n> <k> <privkey1> [<pubkey2> ...] [<boc1> <boc2>]" cr cr
."Creates a new multisignature wallet in specified workchain composed of <n> (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 <k> (1-10) signatures required to send an order; load <n> pre-existing public keys from files <key1...n>." cr
."Optionally load a number of pre-generated partially signed orders <boc1...m> to preload into the contract." cr 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"<n> must be a number!" constant n
$4 (number) 1 <> abort"<k> must be a number!" constant k
$# 4 n + - constant m
n 1 < n 10 > or abort"<n> must be between 1 and 10"
k 1 < k 10 > or abort"<k> must be between 1 and 10"
k n <= not abort"<k> must smaller than or equal to <n>"
$# 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
5 n + { dup $() +".boc" load-boc swap 1+ } m times drop
m tuple constant messages
cr
."Creating new advanced wallet in workchain " wc .
."with n=" n .
."k=" k .
."m=" m . ."..." 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
// Keys will be deserialized to a simple tuple, using the correct PubKeys constructor depending on the number n of keys left
//
// pubKeys1$_ key1:PubKey = PubKeys;
// pubKeys2$_ key1:PubKey key2:PubKey = PubKeys;
// pubKeys3$_ key1:PubKey key2:PubKey key3:PubKey = PubKeys;
// pubKeys3and$_ key1:PubKey key2:PubKey key3:PubKey _:^PubKeys = PubKeys;
//
// keys:[ ^PubKeys ]
// First create builders with groups of (at most) 3 keys each
<b
0 { dup 1+ swap // Create a counter
// Get builder b (or create a new one)
// if ($k && !($k % 3)) {
dup dup 3 mod 0<> not and { <b } { 2 roll } cond
keys rot [] // Get n-th value x
256 // y
u, // Write uint
swap
} n times drop
// Then convert builders into cells, appropriately inserting references for nested pubkeys
n 3 /c const nCeil // Number of builders
nCeil 1- const nRev // Steps for reverse counter
nCeil 3 > const shouldRef // Whether there are more than 3 builders and references must be created
nCeil 1+ const nRoll // Steps for roll
nRev { dup 1- swap // Create a reverse counter
rot // Get current builder
swap
// if ($x != $nRev && $x > 1 && $nCeil > 3)
dup nRev <> swap 1 > shouldRef and and { nCeil pick ref, } if
b> // Close builder, create cell
nCeil -roll // Put cell at the back of the stack
} nCeil times drop
// Number of cells to store / Number of already referenced cells to delete
nCeil 3 > { 3 nCeil 3 - } { nCeil 0 } cond const nRem const nCells
// Drop all cells we already referenced
' drop nRem times
// Reverse order of cells
nCells 0 reverse
// Create tuple with cells
nCells tuple const keyCells
// messages:(HashmapE 256 ^(MultiSigWrapperStorage X))
dictnew
0 { dup 1+ swap // Create a counter
messages swap [] // Get n-th value v
dup <b swap ref, // ~
swap hashu // Get x
3 roll // Get dictionary s
256 // Get n
b>idict!
not abort"Failure storing dictionary value!"
swap
} m times drop const messages-dict
// code
"wallet-code.fif" include
// data
// storage$_ seqno:uint32 minSigs:(## 4) n:(## 4) keys:[ ^PubKeys ] messages:(HashmapE 256 ^(MultiSigWrapperStorage X))
// { minSigs > 0 } { n >= minSigs } { n <= 10 } { minSigs <= 10 } = Storage X;
<b 0 32 u,
k 4 u,
nCells 4 u,
keyCells explode roll { swap ref, } nCells times
messages-dict dict,
b>
// no libraries
null
// 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
//
<b b{0011} s, 3 roll ref, rot ref, swap dict, b>
dup ."StateInit: " <s csr. cr
dup hash wc swap 2dup 2constant wallet_addr
."new wallet address = " 2dup .addr cr
2dup file-base +".addr" save-address-verbose
."Non-bounceable address (for init): " 2dup 7 .Addr cr
."Bounceable address (for later access): " 6 .Addr cr
.s
<b 0 32 u, -1 32 i, b>
dup ."signing message: " <s csr. cr
dup hash privkey ed25519_sign_uint rot
<b b{1000100} s, wallet_addr addr, b{000010} s, swap <s s, b{0} s, swap B, swap <s s, b>
dup ."External message for initialization is " <s csr. cr
2 boc+>B dup Bx. cr
file-base +"-query.boc" tuck B>file
."(Saved wallet creating query to file " type .")" cr