diff --git a/wallet/proto.php b/wallet/proto.php index bfd0748..88afc09 100644 --- a/wallet/proto.php +++ b/wallet/proto.php @@ -118,3 +118,46 @@ if ($op === 0) { 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/scheme.tlb b/wallet/scheme.tlb index 54a2f56..88a6f49 100644 --- a/wallet/scheme.tlb +++ b/wallet/scheme.tlb @@ -21,13 +21,23 @@ multiSigWrapper$0 signatures:(HashmapE 4 ^Signature) message:(WrappedMessage X) 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) ) -// Min 3 signatures per message -// ^StoredMessage because 256*(40+) > 1023 // -storage$_ seqno:uint32 minSigs:(## 4) keys:(HashmapE 4 ^PubKey) messages:(HashmapE 256 ^(MultiSigWrapperStorage X)) - {k:(## 4)} { k > 0 } { k >= 3 } { n >= k } { n <= 10 } = Storage X; +// 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 diff --git a/wallet/wallet-create.fif b/wallet/wallet-create.fif index 32c7cb0..a310f69 100644 --- a/wallet/wallet-create.fif +++ b/wallet/wallet-create.fif @@ -1,9 +1,14 @@ "TonUtil.fif" include +{ constant } : const -{ dup ."Loading public key from file " type cr +{ 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) public keys." cr @@ -26,18 +31,101 @@ k n <= not abort" must smaller than or equal to " $# 4 n + < abort"Not enough keys were provided in args!" -5 { dup $() swap 1+ } n times drop -n tuple constant keys-files +5 { dup $() +".pubkey" load-pubkey swap 1+ } n times drop +n tuple constant keys -5 n + { dup $() swap 1+ } m times drop +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 +."m=" m . ."..." cr cr -keys-files explode { } swap times +// 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 + +'drop nCeil 3 - times + +/* +dictnew +0 { dup 1+ swap // Create a counter + 0 { dup 1+ swap // Create another counter + 2 pick + // Sum counters + dup keys swap [] // Get n-th value v + } + u@ 256 u, // ~ + + swap // Get x + 3 roll // Get dictionary s + 4 // Get n + + b>idict! + not abort"Failure storing dictionary value!" + + swap +} nCells times drop const keys-dict +*/ + +// 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