From 5fe76ed22b3f6fa25070085ca878b8de42aaad3b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 11 Oct 2019 13:31:43 +0200 Subject: [PATCH] Move --- wallet-dict/const.fif | 7 - wallet-dict/gen-pub.fif | 14 -- wallet-dict/proto.php | 163 ------------- wallet-dict/scheme.tlb | 198 ---------------- wallet-dict/wallet-code.fc | 250 -------------------- wallet-dict/wallet-code.fif | 416 ---------------------------------- wallet-dict/wallet-create.fif | 159 ------------- wallet-dict/wallet.fif | 54 ----- 8 files changed, 1261 deletions(-) delete mode 100644 wallet-dict/const.fif delete mode 100644 wallet-dict/gen-pub.fif delete mode 100644 wallet-dict/proto.php delete mode 100644 wallet-dict/scheme.tlb delete mode 100644 wallet-dict/wallet-code.fc delete mode 100644 wallet-dict/wallet-code.fif delete mode 100644 wallet-dict/wallet-create.fif delete mode 100755 wallet-dict/wallet.fif diff --git a/wallet-dict/const.fif b/wallet-dict/const.fif deleted file mode 100644 index 15aa16a..0000000 --- a/wallet-dict/const.fif +++ /dev/null @@ -1,7 +0,0 @@ - -// Minimum signatures to send order -3 : k -// Maximum signatures per order -10 : n - - diff --git a/wallet-dict/gen-pub.fif b/wallet-dict/gen-pub.fif deleted file mode 100644 index ea25385..0000000 --- a/wallet-dict/gen-pub.fif +++ /dev/null @@ -1,14 +0,0 @@ -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." " cr - ."Create public key files from private keys; if doesn't exist, it will be created." cr cr - 1 halt -} : usage -$# 1 < ' usage if - -$1 +".pk" load-generate-keypair drop -$1 +".pubkey" B>file - - -."Wrote private key to " $1 +".pk" type cr -."Wrote public key to " $1 +".pubkey" type cr \ No newline at end of file diff --git a/wallet-dict/proto.php b/wallet-dict/proto.php deleted file mode 100644 index 88afc09..0000000 --- a/wallet-dict/proto.php +++ /dev/null @@ -1,163 +0,0 @@ - 0, - 'minSig' => 3, - 'keys' => [ - 'key1' - ], - 'messages' => [ - 'hash' => [ - 'expires' => 100, - 'signatures' => [ - 0 => 'sig' // Generated from key1 - ], - 'seqno' => 0, - 'body' => 'body' - ] - ] - ]; -} else { - $db = \json_decode(\file_get_contents('db.json'), true); -} - -function storeDb(array $db) -{ - \file_put_contents('db.json', \json_encode($db)); -} - -function garbageCollect(array $db): array -{ - $changed = false; - foreach ($db['messages'] as $hash => $message) { - if ($message['expires'] < \time()) { - unset($db['messages'][$hash]); - $changed = true; - } - } - return [$changed, $db]; -} - -function hasKey(string $key, array $db) -{ - foreach ($db['keys'] as $id => $curKey) { - if ($curKey === $key) { - return $id; - } - } - return false; -} - - -$message = \json_decode(\file_get_contents('php://input')); - -$op = $message['op']; -$body = $message['body']; -if ($op === 11) { - return $db['seqno']; -} - -if ($op === 12) { - return hasKey($body, $db); -} - -if ($op === 0) { - //list($shouldUpdate, $db) = garbageCollect($db); - - $signatures = $body['signatures']; - if (empty($signatures)) { - //if ($shouldUpdate) { - // storeDb($db); - //} - return 'not enough signatures'; - } - - if ($body['expires'] < \time()) { - //if ($shouldUpdate) { - // storeDb($db); - //} - return 'message expired'; - } - $hash = \hash('sha256', \json_encode($body)); - - if ($db['seqno'] === $body['seqno']) { - $db['seqno']++; - $oldSignatures = []; - // Assuming there are no signatures stored - } elseif (!isset($db['messages'][$hash])) { - return 'wrong seqno or no such message'; - } else { - $oldSignatures = $db['messages'][$hash]['signatures']; - } - - foreach ($signatures as $idx => $signature) { - $key = $db['keys'][$idx]; - if (!checkSig($signature, $key)) { - return 'wrong sig'; - } - - $oldSignatures[$idx] = $signature; - } - - $count = 0; - foreach ($oldSignatures as $sig) { - if (++$count >= 3) { - sendMessage($body); - break; - } - } - - if ($count < 3) { - $db['messages'][$hash] = [ - 'expires' => $body['expires'], - 'signatures' => $oldSignatures, - 'body' => $body - ]; - } - - storeDb(garbageCollect($db)); -} - - -$keys = [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, -]; - -$n = count($keys); -$nCells = $n / 3; - -$cells = []; -$cell = []; -for ($x = 0; $x < n; $x++) { - for ($y = 0; $y < 3; $y++) { - $z = $x + $y; - } -} - -foreach ($keys as $k => $key) { - if ($k && !($k % 3)) { - $cells []= $cell; - $cell = []; - } - $cell []= $key; -} -if ($cell) { - $cells []= $cell; -} - -$final = []; -for ($x = $nRev = count($cells) - 1; $x >= 0; $x--) { - if ($nRev > 2 && $x != $nRev && $x > 1) { - - } -} diff --git a/wallet-dict/scheme.tlb b/wallet-dict/scheme.tlb deleted file mode 100644 index 88a6f49..0000000 --- a/wallet-dict/scheme.tlb +++ /dev/null @@ -1,198 +0,0 @@ -// This is just an approximated TL scheme, explaining the message formats used by the multisig wallet. -// Multisig wallet constructors - -// 256 bits -pubKey$_ k:bits256 = PubKey; - -// 512 bits -signature$_ R:bits256 s:bits256 = Signature; - -// Message + send ModeMessage -modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X; - -// Actual multisigned message -wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X; - -// key ID => signature -multiSigWrapper$0 signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) = MultiSigWrapper X; -//multiSigFuture$1 = MultiSigWrapper X; - -// For internal storage, no constructor ID -multiSigWrapperStorage$_ signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) = MultiSigWrapperStorage X; - - -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; - -// Not doing explicit versioning here, since the structure of the storage can only change after an update of the onchain wallet code -// Max 10 keys (not sure about this, the contest instruction file says 10 in one place and 100 in another, so I chose 10 => 16 => 2^(4) ) -// -// Keys will be deserialized to a simple tuple, using the correct PubKeys constructor depending on the number n of keys left -// -// The pubKeys3and constructor is used when 10+ keys have to be stored -// in which case the last pubKeys3 constructor will contain a references to another PubKeys constructor, -// leaving one reference free in the storage cell to store the messages hashmap. -// -storage$_ seqno:uint32 minSigs:(## 4) n:(## 4) keys:[ ^PubKeys ] messages:(HashmapE 256 ^(MultiSigWrapperStorage X)) - { minSigs > 0 } { n >= minSigs } { n <= 10 } { minSigs <= 10 } = Storage X; - -// TON stuff - -unit$_ = Unit; -true$_ = True; -// EMPTY False; -bool_false$0 = Bool; -bool_true$1 = Bool; -bool_false$0 = BoolFalse; -bool_true$1 = BoolTrue; -nothing$0 {X:Type} = Maybe X; -just$1 {X:Type} value:X = Maybe X; -left$0 {X:Type} {Y:Type} value:X = Either X Y; -right$1 {X:Type} {Y:Type} value:Y = Either X Y; -pair$_ {X:Type} {Y:Type} first:X second:Y = Both X Y; - -bit$_ (## 1) = Bit; -/* - * - * FROM hashmap.tlb - * - */ -// ordinary Hashmap / HashmapE, with fixed length keys -// -hm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(HashmapNode m X) = Hashmap n X; - -hmn_leaf#_ {X:Type} value:X = HashmapNode 0 X; -hmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X) - right:^(Hashmap n X) = HashmapNode (n + 1) X; - -hml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m; -hml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m; -hml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m; - -unary_zero$0 = Unary ~0; -unary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1); - -hme_empty$0 {n:#} {X:Type} = HashmapE n X; -hme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X; - -extra_currencies$_ dict:(HashmapE 32 (VarUInteger 32)) - = ExtraCurrencyCollection; -// true#_ = True; -_ {n:#} _:(Hashmap n True) = BitstringSet n; - -// HashmapAug, hashmap with an extra value -// (augmentation) of type Y at every node -// -ahm_edge#_ {n:#} {X:Type} {Y:Type} {l:#} {m:#} - label:(HmLabel ~l n) {n = (~m) + l} - node:(HashmapAugNode m X Y) = HashmapAug n X Y; -ahmn_leaf#_ {X:Type} {Y:Type} extra:Y value:X = HashmapAugNode 0 X Y; -ahmn_fork#_ {n:#} {X:Type} {Y:Type} left:^(HashmapAug n X Y) - right:^(HashmapAug n X Y) extra:Y = HashmapAugNode (n + 1) X Y; - -ahme_empty$0 {n:#} {X:Type} {Y:Type} extra:Y - = HashmapAugE n X Y; -ahme_root$1 {n:#} {X:Type} {Y:Type} root:^(HashmapAug n X Y) - extra:Y = HashmapAugE n X Y; - -// VarHashmap / VarHashmapE, with variable-length keys -// -vhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(VarHashmapNode m X) - = VarHashmap n X; -vhmn_leaf$00 {n:#} {X:Type} value:X = VarHashmapNode n X; -vhmn_fork$01 {n:#} {X:Type} left:^(VarHashmap n X) - right:^(VarHashmap n X) value:(Maybe X) - = VarHashmapNode (n + 1) X; -vhmn_cont$1 {n:#} {X:Type} branch:Bit child:^(VarHashmap n X) - value:X = VarHashmapNode (n + 1) X; - -// nothing$0 {X:Type} = Maybe X; -// just$1 {X:Type} value:X = Maybe X; - -vhme_empty$0 {n:#} {X:Type} = VarHashmapE n X; -vhme_root$1 {n:#} {X:Type} root:^(VarHashmap n X) - = VarHashmapE n X; - -// -// PfxHashmap / PfxHashmapE, with variable-length keys -// constituting a prefix code -// - -phm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(PfxHashmapNode m X) - = PfxHashmap n X; - -phmn_leaf$0 {n:#} {X:Type} value:X = PfxHashmapNode n X; -phmn_fork$1 {n:#} {X:Type} left:^(PfxHashmap n X) - right:^(PfxHashmap n X) = PfxHashmapNode (n + 1) X; - -phme_empty$0 {n:#} {X:Type} = PfxHashmapE n X; -phme_root$1 {n:#} {X:Type} root:^(PfxHashmap n X) - = PfxHashmapE n X; -/* - * - * END hashmap.tlb - * - */ - -// TON messages - - -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; -_ _:MsgAddressInt = MsgAddress; -_ _:MsgAddressExt = MsgAddress; -// -var_uint$_ {n:#} len:(#< n) value:(uint (len * 8)) - = VarUInteger n; -var_int$_ {n:#} len:(#< n) value:(int (len * 8)) - = VarInteger n; -nanograms$_ amount:(VarUInteger 16) = Grams; -// -extra_currencies$_ dict:(HashmapE 32 (VarUInteger 32)) - = ExtraCurrencyCollection; -currencies$_ grams:Grams other:ExtraCurrencyCollection - = CurrencyCollection; -// -int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - src:MsgAddressInt dest:MsgAddressInt - value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams - created_lt:uint64 created_at:uint32 = CommonMsgInfo; -ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt - import_fee:Grams = CommonMsgInfo; -ext_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt - created_lt:uint64 created_at:uint32 = CommonMsgInfo; - - -int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - src:MsgAddress dest:MsgAddressInt - value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams - created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; -ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt - created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; - -tick_tock$_ tick:Bool tock:Bool = TickTock; - -_ split_depth:(Maybe (## 5)) special:(Maybe TickTock) - code:(Maybe ^Cell) data:(Maybe ^Cell) - library:(HashmapE 256 SimpleLib) = StateInit; - -simple_lib$_ public:Bool root:^Cell = SimpleLib; - -// create a message -message$_ {X:Type} info:CommonMsgInfo - init:(Maybe (Either StateInit ^StateInit)) - body:(Either X ^X) = Message X; - diff --git a/wallet-dict/wallet-code.fc b/wallet-dict/wallet-code.fc deleted file mode 100644 index 26c499a..0000000 --- a/wallet-dict/wallet-code.fc +++ /dev/null @@ -1,250 +0,0 @@ -;; Multisig wallet smart contract - -cell preload_refidx(slice s, int index) asm "PLDREFVAR"; - -;; Tuple manipulation primitives for integers -tuple tuple_set(tuple t, int index, int value) asm(t value index) "SETINDEXVARQ"; -(tuple, ()) ~tuple_set(tuple t, int index, int value) asm(t value index) "SETINDEXVARQ"; - -;; Tuple manipulation primitives for cells -tuple tuple_setcell(tuple t, int index, cell value) asm(t value index) "SETINDEXVARQ"; -(tuple, ()) ~tuple_setcell(tuple t, int index, cell value) asm(t value index) "SETINDEXVARQ"; - -int tuple_len(tuple t) asm "TLEN"; - -;; Cleanup expired partial orders -;; messages -(cell, ()) ~collect_garbage(cell messages) { - var hash = -1; - do { - (hash, var cs, var ok) = messages.udict_get_next?(256, hash); - if (ok) { - - ;; modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X; - ;; wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X; - ;; multiSigWrapperStorage$_ signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) = MultiSigWrapperStorage X; - ;; - ;; Skip signatures, check expiry - ;; - ;; expiry <= now - if (cs.skip_dict().preload_uint(32) <= now()) { - messages~udict_delete?(256, hash); - } - } - } until (~ ok); - - return (messages, ()); -} - -;; messages -(slice, (tuple, tuple)) ~load_keys(slice messages) { - int length = messages~load_uint(4); - int index = 0; - var keys = nil; - var keys_cells = nil; - var keys_cell = messages~load_ref(); - keys_cells~tuple_setcell(index / 3, keys_cell); - var keys_slice = keys_cell.begin_parse(); - do { - if ((index % 3 == 0)) { - if ((index < 9) & (index > 0)) { - keys_slice.end_parse(); - var keys_cell = messages~load_ref(); - keys_cells~tuple_setcell(index / 3, keys_cell); - var keys_slice = keys_cell.begin_parse(); - } else { - var newkeys_slice = keys_slice.preload_ref().begin_parse(); - keys_slice.end_parse(); - keys_slice = newkeys_slice; - } - } - int key = keys_slice.preload_uint(256); - - keys~tuple_set(index, key); - index += 1; - } until (index == length); - keys_slice.end_parse(); - - return (messages, (keys, keys_cells)); -} -;; messages -tuple preload_keys(slice messages) { - int length = messages~load_uint(4); - int index = 0; - var keys = nil; - var keys_slice = messages~load_ref().begin_parse(); - do { - if ((index % 3 == 0)) { - if ((index < 9) & (index > 0)) { - var keys_slice = messages~load_ref().begin_parse(); - } else { - var keys_slice = keys_slice.preload_ref().begin_parse(); - } - } - int key = keys_slice~load_uint(256); - keys~tuple_set(index, key); - index += 1; - } until (index == length); - - return keys; -} - -slice skip_keys(slice messages) { - int length = messages~load_uint(4); - length = min(length / 3, 3); - int index = 0; - do { - messages~load_ref(); - } until (index == length); - return messages; -} -builder store_keys(builder b, int length, var keys) { - b~store_uint(4, length); - - length = keys.tuple_len(); - int index = 0; - do { - b.store_ref(keys.cell_at(index)); - index += 1; - } until (index == length); - return b; -} - -() store_db(int seqno, cell keys, cell messages) { - set_data(begin_cell().store_uint(seqno, 32).store_dict(keys).store_dict(messages).end_cell()); -} - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -;; multiSigWrapper$0 keys_signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) = MultiSigWrapper X; -() recv_external(slice in_msg) impure { - ;; Check if multiSigWrapper$0 or future unsupported protocol - throw_unless(32, in_msg~load_uint(1)); - - ;; Check if is hme_empty$0 or hme_root$1 - ;; Throw if empty signature list - throw_unless(33, in_msg.preload_uint(1)); - - var signatures = in_msg~load_dict(); - slice message_data = in_msg; - - ;; wrappedMessage$_ expires_at:uint32 seqno:uint32 body:^(Message X) = WrappedMessage X; - (int expires_at, int msg_seqno) = (message_data~load_uint(32), message_data~load_uint(32)); - ;; Message expired - throw_if(34, expires_at <= now()); - - ;; We will need the hash anyway - int hash = slice_hash(in_msg); - - ;; storage$_ seqno:uint32 minSigs:(## 4) keys:(HashmapE 4 ^PubKey) messages:(HashmapE 256 ^(StoredMessage X)) = Storage X; - slice stored_data = get_data().begin_parse(); - (int stored_seqno, int min_sigs, (var keys, var kcells), var messages) = (stored_data~load_uint(32), stored_data~load_uint(4), stored_data~load_keys(), stored_data~load_dict()); - stored_data.end_parse(); - - ;; This is a new message, so there will be no stored messages - var storedMessageSignatures = new_dict(); - ;; If new message, increase seqno - if (stored_seqno == msg_seqno) { - stored_seqno += 1; - - ;; If old message - } else { - var (storedMessage, ok) = messages.udict_get?(256, hash); - ;; Throw if old message and doesn't exist in db - throw_unless(35, ok); - - ;; multiSigWrapperStorage$_ signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) = MultiSigWrapperStorage X; - ;; - ;; Load signatures - var storedMessageSignatures = storedMessage~load_ref().begin_parse().preload_dict(); - storedMessage.end_parse(); - } - - accept_message(); - message_data~touch(); - - var idx = -1; - do { - (idx, var signature, var ok) = signatures.udict_get_next?(4, idx); - if (ok) { - var public_key = keys.int_at(idx); - ;;throw_unless(at(at(36, kok); - - var signature_cell = signature~load_ref(); - var signature_slice = signature_cell.begin_parse(); - var slice_copy = signature_slice; - - signature_slice.end_parse(); - - throw_unless(37, check_signature(hash, slice_copy, public_key)); - - storedMessageSignatures~udict_set_ref(4, idx, signature_cell); - } - } until (~ ok); - - var (mode, message) = (message_data~load_uint(8), message_data~load_ref()); - message_data.end_parse(); - - var count = 0; - var sent = 0; - var idx = -1; - do { - (idx, var signature, var ok) = storedMessageSignatures.udict_get_next?(4, idx); - if (ok) { - count += 1; - if (count >= min_sigs) { - send_raw_message(message, mode); - messages~udict_delete?(256, hash); - ok = 0; - } - } - } until (~ ok); - - ;; modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X; - ;; wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X; - ;; multiSigWrapperStorage$_ signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) = MultiSigWrapperStorage X; - ;; - if (count < min_sigs) { - messages~udict_set_ref(256, hash, begin_cell().store_dict(storedMessageSignatures).store_uint(expires_at, 32).store_uint(msg_seqno, 32).store_uint(mode, 8).store_ref(message).end_cell()); - } - messages~collect_garbage(); - - ;; storage$_ seqno:uint32 minSigs:(## 4) keys:(HashmapE 4 ^PubKey) messages:(HashmapE 256 ^(Message X)) = Storage X; - set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(min_sigs, 4).store_keys(keys.tuple_len(), kcells).store_dict(messages).end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -(int, int) getKey(int id) method_id { - var res = get_data().begin_parse().skip_bits(36).preload_keys().int_at(id); - if (res.null?()) { - return (0, 0); - } - return (-1, res); -} -(int, int) getId(int key) method_id { - var keys = get_data().begin_parse().skip_bits(36).preload_keys(); - int index = 0; - int length = keys.tuple_len(); - do { - if (keys.int_at(index) == key) { - return (-1, index); - } - } until (index == length); - return (0, 0); -} - -(cell) getPartials() method_id { - return get_data().begin_parse().skip_bits(36).skip_keys().preload_dict(); -} -(cell) getPartialsById(int id) method_id { - cell messages = get_data().begin_parse().skip_bits(36).skip_keys().preload_dict(); - cell messages_found = new_dict(); - return messages_found; -} \ No newline at end of file diff --git a/wallet-dict/wallet-code.fif b/wallet-dict/wallet-code.fif deleted file mode 100644 index a36c8c6..0000000 --- a/wallet-dict/wallet-code.fif +++ /dev/null @@ -1,416 +0,0 @@ -"Asm.fif" include -// automatically generated from `/home/daniil/repos/contest/lib/crypto/smartcont/stdlib.fc` `wallet-code.fc` -PROGRAM{ - DECLPROC ~collect_garbage - DECLPROC ~load_keys - DECLPROC preload_keys - DECLPROC skip_keys - DECLPROC store_keys - DECLPROC store_db - DECLPROC recv_internal - DECLPROC recv_external - 85143 DECLMETHOD seqno - 119659 DECLMETHOD getKey - 66593 DECLMETHOD getId - 124239 DECLMETHOD getPartials - 87848 DECLMETHOD getPartialsById - ~collect_garbage PROC:<{ - -1 PUSHINT - UNTIL:<{ - OVER - 8 PUSHPOW2 - DICTUGETNEXT - NULLSWAPIFNOT - NULLSWAPIFNOT - DUP - IF:<{ - s0 s2 XCHG - SKIPDICT - 32 PLDU - NOW - LEQ - IF:<{ - 8 PUSHPOW2 - s1 s3 s3 PUXC2 - DICTUDEL - DROP - }>ELSE<{ - s0 s2 XCHG - }> - }>ELSE<{ - 2SWAP - DROP - }> - SWAP - NOT - s1 s2 XCHG - }> - DROP - }> - ~load_keys PROC:<{ - 4 LDU - 0 PUSHINT - PUSHNULL - PUSHNULL - s0 s3 XCHG - LDREF - s4 s1 XCPU - 0 PUSHINT - SETINDEXVARQ - SWAP - CTOS - UNTIL:<{ - s3 PUSH - 3 PUSHINT - MOD - 0 EQINT - IF:<{ - s3 PUSH - 9 LESSINT - s4 PUSH - 0 GTINT - AND - IF:<{ - DUP - ENDS - s0 s4 XCHG - LDREF - s4 PUSH - 3 PUSHINT - DIV - s3 s2 s(-1) XCPUXC - SETINDEXVARQ - NIP - }>ELSE<{ - DUP - PLDREF - CTOS - SWAP - ENDS - s4 s4 XCHG2 - }> - }>ELSE<{ - s4 s4 XCHG2 - }> - s4 PUSH - 256 PLDU - s3 s0 s4 XC2PU - SETINDEXVARQ - s0 s3 XCHG - INC - s0 s5 PUSH2 - EQUAL - s5 s4 s0 XCHG3 - s3 s3 s0 XCHG3 - }> - s3 POP - s4 POP - SWAP - ENDS - ROT - }> - preload_keys PROC:<{ - 4 LDU - 0 PUSHINT - PUSHNULL - s0 s2 XCHG - LDREF - DROP - CTOS - UNTIL:<{ - OVER - 3 PUSHINT - MOD - 0 EQINT - IF:<{ - OVER - 9 LESSINT - s2 PUSH - 0 GTINT - AND - IF:<{ - }>ELSE<{ - }> - }> - 256 LDU - s3 s3 s2 XC2PU - SETINDEXVARQ - SWAP - INC - s0 s3 PUSH2 - EQUAL - s1 s3 s0 XCHG3 - }> - s2 s3 XCHG - 3 BLKDROP - }> - skip_keys PROC:<{ - 4 LDU - SWAP - 3 PUSHINT - DIV - 3 PUSHINT - MIN - UNTIL:<{ - SWAP - LDREF - NIP - OVER - 0 EQINT - s1 s2 XCHG - }> - DROP - }> - store_keys PROC:<{ - 4 PUSHINT - 2SWAP - STUX - OVER - TLEN - s2 POP - 0 PUSHINT - UNTIL:<{ - INC - s0 s2 PUSH2 - EQUAL - }> - DROP - NIP - }> - store_db PROC:<{ - NEWC - s1 s3 XCHG - 32 STU - STDICT - STDICT - ENDC - c4 POP - }> - recv_internal PROC:<{ - DROP - }> - recv_external PROC:<{ - 1 LDU - SWAP - 32 THROWIFNOT - DUP - 1 PLDU - 33 THROWIFNOT - LDDICT - DUP - 32 LDU - 32 LDU - s2 PUSH - NOW - LEQ - 34 THROWIF - s0 s3 XCHG - HASHSU - c4 PUSH - CTOS - 32 LDU - 4 LDU - ~load_keys CALLDICT - s0 s2 XCHG - LDDICT - ENDS - NEWDICT - s5 s7 PUSH2 - EQUAL - IF:<{ - s0 s5 XCHG - INC - }>ELSE<{ - s6 s1 PUSH2 - 8 PUSHPOW2 - DICTUGET - NULLSWAPIFNOT - 35 THROWIFNOT - LDREF - NIP - ENDS - s0 s5 XCHG - }> - ACCEPT - s0 s9 XCHG - -1 PUSHINT - UNTIL:<{ - s11 PUSH - 4 PUSHINT - DICTUGETNEXT - NULLSWAPIFNOT - NULLSWAPIFNOT - DUP - IF:<{ - s5 s1 PUSH2 - INDEXVAR - s0 s3 XCHG - LDREF - DROP - DUP - CTOS - DUP - ENDS - s11 s0 s4 PUXC2 - CHKSIGNU - 37 THROWIFNOT - s1 s2 XCHG - 4 PUSHINT - s3 s9 s9 PUXC2 - DICTUSETREF - }>ELSE<{ - s1 s8 s8 XCHG3 - DROP - }> - s0 s7 XCHG - NOT - }> - DROP - s10 POP - s0 s9 XCHG - 8 LDU - LDREF - ENDS - 0 PUSHINT - -1 PUSHINT - UNTIL:<{ - s7 PUSH - 4 PUSHINT - DICTUGETNEXT - NULLSWAPIFNOT - NULLSWAPIFNOT - s2 POP - OVER - IF:<{ - s0 s2 XCHG - INC - s0 s7 PUSH2 - GEQ - IF:<{ - NIP - s2 s3 PUSH2 - SENDRAWMSG - 8 PUSHPOW2 - s9 s13 s13 PUXC2 - DICTUDEL - DROP - 0 PUSHINT - }>ELSE<{ - s13 s13 XCHG2 - }> - }>ELSE<{ - s0 s13 s13 XCHG3 - }> - NOT - s13 s13 s0 XCHG3 - }> - DROP - s5 PUSH - LESS - IF:<{ - NEWC - s1 s6 XCHG - STDICT - s1 s8 XCHG - 32 STU - s1 s6 XCHG - 32 STU - s1 s6 XCHG - 8 STU - s1 s2 XCHG - STREF - ENDC - s0 s0 s6 XCHG3 - 8 PUSHPOW2 - DICTUSETREF - }>ELSE<{ - s4 s10 XCHG - s3 s8 XCHG - s2 s7 XCHG - s4 s6 XCHG - 6 BLKDROP - }> - ~collect_garbage CALLDICT - s0 s3 XCHG - INC - NEWC - 32 STU - s1 s4 XCHG - 4 STU - s0 s3 XCHG - TLEN - s2 s3 XCHG - SWAP - store_keys CALLDICT - STDICT - ENDC - c4 POP - }> - seqno PROC:<{ - c4 PUSH - CTOS - 32 PLDU - }> - getKey PROC:<{ - c4 PUSH - CTOS - 36 PUSHINT - SDSKIPFIRST - preload_keys CALLDICT - SWAP - INDEXVAR - DUP - ISNULL - IFJMP:<{ - DROP - 0 PUSHINT - DUP - }> - -1 PUSHINT - SWAP - }> - getId PROC:<{ - c4 PUSH - CTOS - 36 PUSHINT - SDSKIPFIRST - preload_keys CALLDICT - 0 PUSHINT - OVER - TLEN - UNTIL:<{ - s2 PUSH - 0 INDEX - s4 PUSH - EQUAL - IFJMP:<{ - s1 s3 XCHG - 3 BLKDROP - -1 PUSHINT - SWAP - }> - 2DUP - EQUAL - }> - 4 BLKDROP - 0 PUSHINT - DUP - }> - getPartials PROC:<{ - c4 PUSH - CTOS - 36 PUSHINT - SDSKIPFIRST - skip_keys CALLDICT - PLDDICT - }> - getPartialsById PROC:<{ - DROP - c4 PUSH - CTOS - 36 PUSHINT - SDSKIPFIRST - skip_keys CALLDICT - PLDDICT - }> -}END>c diff --git a/wallet-dict/wallet-create.fif b/wallet-dict/wallet-create.fif deleted file mode 100644 index 6ee15d0..0000000 --- a/wallet-dict/wallet-create.fif +++ /dev/null @@ -1,159 +0,0 @@ -"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 ." [ ...] [ ]" 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 - ."Optionally load a number of pre-generated partially signed orders 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" must be a number!" constant n -$4 (number) 1 <> abort" must be a number!" constant k -$# 4 n + - constant m - -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 - -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 - not and { 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 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; - -// 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 -// - - -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/wallet-dict/wallet.fif b/wallet-dict/wallet.fif deleted file mode 100755 index 4338533..0000000 --- a/wallet-dict/wallet.fif +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env -S fift -s -"TonUtil.fif" include - - -{ - ."usage: " @' $0 type ." command [arguments]" cr - cr - ."Available commands: create-wallet, " cr - @' $0 type ." create-wallet - " [-B ] []" cr - ."Creates a request to advanced wallet created by new-wallet-v2.fif, with private key loaded from file .pk " - ."and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" cr 1 halt -} : usage -def? $6 { @' $5 "-B" $= { @' $6 =: body-boc-file [forget] $6 def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond - @' $# 2- =: $# } if } if -$# dup 4 < swap 5 > or ' usage if - -true constant bounce - -$1 =: file-base -$2 bounce parse-load-address =: bounce 2=: dest_addr -$3 parse-int =: seqno -$4 $>GR =: amount -def? $5 { @' $5 } { "wallet-query" } cond constant savefile -3 constant send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -60 constant timeout // external message expires in 60 seconds - -file-base +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -def? body-boc-file { @' body-boc-file file>B B>boc } { } cond -constant body-cell - -."Transferring " amount .GR ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."seqno=0x" seqno x. ."bounce=" bounce . cr -."Body of transfer message is " body-cell - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."Query expires in " timeout . ."seconds" cr -."(Saved to file " type .")" cr