mirror of
https://github.com/danog/toncontest.git
synced 2024-11-30 04:29:14 +01:00
update
This commit is contained in:
parent
5fe76ed22b
commit
c7a6366724
6
wallet/README.md
Normal file
6
wallet/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Multisignature wallet
|
||||
|
||||
Upgradable multisignature wallet.
|
||||
Included signature verification scripts to avoid problems with eventual preloaded orders with invalid signatures.
|
||||
|
||||
Code can be upgraded via a special multisignature message.
|
@ -39,9 +39,9 @@ dest_addr 2dup bounce 7 + .Addr ." = " .addr
|
||||
body-cell <s 2dup s-fits? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
|
||||
b>
|
||||
// create wrapper message
|
||||
// modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
// modeMessage$0 mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
// wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X;
|
||||
<b now timeout + 32 u, seqno 32 u, send-mode 8 u, swap ref, b>
|
||||
<b now timeout + 32 u, seqno 32 u, 0 1 u, send-mode 8 u, swap ref, b>
|
||||
|
||||
dup ."signing message: " <s csr. cr
|
||||
dup hashu
|
||||
@ -54,7 +54,14 @@ wallet_pk ed25519_sign_uint
|
||||
|
||||
// key ID => signature
|
||||
// multiSigWrapper$0 signatures:(HashmapE 4 Signature) message:(WrappedMessage X) = MultiSigWrapper X;
|
||||
<b swap <s key-id dictnew 4 udict! not abort"Failure inserting signature!" dict, swap <s s, b>
|
||||
<b
|
||||
0 1 u, // $0
|
||||
swap <s key-id dictnew 4 udict! // Create and populate dictionary
|
||||
not abort"Failure inserting signature!"
|
||||
|
||||
dict, // signatures
|
||||
swap <s s, // message
|
||||
b>
|
||||
|
||||
//
|
||||
// addr_none$00 = MsgAddressExt;
|
||||
|
@ -21,16 +21,27 @@
|
||||
// D n -- uint
|
||||
{
|
||||
0 -rot
|
||||
{ drop swap 1+ swap -1 } dictmap
|
||||
{ drop swap 1+ swap -1 } dictmap drop
|
||||
} : dictlen
|
||||
|
||||
// u D n -- s ? or ?
|
||||
{
|
||||
{ swap 2 pick = { nip 0 } { drop -1 } cond } dictforeach
|
||||
dup ' nip if
|
||||
not
|
||||
} : dict[]
|
||||
|
||||
{ hole dup 1 ' @ does create 1 ' ! does create } : variable-set
|
||||
{ hole hole 2dup 2 { @ swap @ swap } does create 2 { rot swap ! ! } does create } : 2variable-set
|
||||
2variable-set wallet-addr wallet-addr!
|
||||
variable-set message-hash message-hash!
|
||||
variable-set message-contents message-contents!
|
||||
variable-set sig-count sig-count!
|
||||
|
||||
// udata BSig ukey – ?
|
||||
{
|
||||
256 u>B rot 256 u>B -rot ed25519_chksign
|
||||
} : ed25519_chksignuu
|
||||
|
||||
// Inspects contents of cell provided on top of the stack
|
||||
// c --
|
||||
@ -99,6 +110,7 @@ variable-set message-contents message-contents!
|
||||
|
||||
dict@+ swap
|
||||
dup null? abort"Empty signature list!"
|
||||
dup 4 dictlen sig-count!
|
||||
|
||||
."Signed by the following keys: "
|
||||
4 { drop . ."- " -1 } dictforeach cr drop
|
||||
@ -106,7 +118,7 @@ variable-set message-contents message-contents!
|
||||
."Hash: " dup s>c hashu dup x. cr
|
||||
message-hash!
|
||||
|
||||
// modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
// modeMessage$0 mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
// wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X;
|
||||
|
||||
32 u@+ swap
|
||||
@ -116,6 +128,9 @@ variable-set message-contents message-contents!
|
||||
32 u@+ swap
|
||||
."Seqno: " . cr
|
||||
|
||||
1 u@+ swap
|
||||
{ ."Is code message!" cr ref@ <s quit } if
|
||||
|
||||
8 u@+ swap
|
||||
."Mode: " . cr
|
||||
|
||||
|
@ -8,7 +8,9 @@ pubKey$_ k:bits256 = PubKey;
|
||||
signature$_ R:bits256 s:bits256 = Signature;
|
||||
|
||||
// Message + send ModeMessage
|
||||
modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
modeMessage$0 mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
// Special code upgrade message
|
||||
codeMessage$1 code:^Cell = ModeMessage X;
|
||||
|
||||
// Actual multisigned message
|
||||
wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X;
|
||||
|
@ -32,7 +32,7 @@ dup hash wallet_pk ed25519_sign_uint
|
||||
256 B>u@+ swap 256 B>u@ swap
|
||||
<b swap 256 u, swap 256 u, b> <s
|
||||
|
||||
roll
|
||||
.s rot
|
||||
// Now we have (message) value dict
|
||||
|
||||
// udict! => value key dict bits
|
||||
|
41
wallet/verify.fif
Normal file
41
wallet/verify.fif
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env -S fift -s
|
||||
"TonUtil.fif" include
|
||||
"lib.fif" include
|
||||
|
||||
{
|
||||
."usage: " @' $0 type ." <input> <key1> <key1-id> [<key2> <key2-id> ...]" cr
|
||||
."Verify multisig <input>.boc file with public key <keyN-id> loaded from file <keyN>.pubkey" cr 1 halt
|
||||
} : usage
|
||||
$# 3 < ' usage if
|
||||
$# 3 - 2 mod ' usage if
|
||||
|
||||
$1 +".boc" load-boc constant order
|
||||
order inspect cr
|
||||
|
||||
// multiSigWrapper$0 signatures:(HashmapE 4 Signature) message:(WrappedMessage X) = MultiSigWrapper X;
|
||||
message-contents
|
||||
1 u@+ nip // $0 was already verified
|
||||
|
||||
// multiSigWrapper$0 signatures:(HashmapE 4 Signature) message:(WrappedMessage X) = MultiSigWrapper X;
|
||||
dict@ const signatures
|
||||
|
||||
variable-set key key!
|
||||
variable-set key-id key-id!
|
||||
|
||||
2 { dup 1+ swap // Counter
|
||||
$() +".pubkey" load-pubkey key!
|
||||
dup 1+ swap // Increment counter
|
||||
$() parse-int key-id!
|
||||
|
||||
."Checking signature of key ID " key-id . ."... "
|
||||
key-id signatures 4 dict[] // Find signature
|
||||
not abort"Could not find signature with specified key ID!"
|
||||
|
||||
64 B@
|
||||
// udata BSig ukey – ?
|
||||
message-hash swap key
|
||||
|
||||
ed25519_chksignuu
|
||||
not abort"Invalid signature!"
|
||||
."OK!" cr
|
||||
} $# 1- 2 /c times
|
@ -21,7 +21,7 @@ int udict_has?(cell dict, int key_len, int index) asm(index dict key_len) "DICTU
|
||||
do {
|
||||
(hash, var cs, int ok) = messages.udict_get_next?(256, hash);
|
||||
if (ok) {
|
||||
;; modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
;; modeMessage$0 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;
|
||||
;;
|
||||
@ -110,14 +110,19 @@ int udict_has?(cell dict, int key_len, int index) asm(index dict key_len) "DICTU
|
||||
}
|
||||
} until (~ ok);
|
||||
|
||||
var (mode, message) = (message_data~load_uint(8), message_data~load_ref());
|
||||
message_data.end_parse();
|
||||
|
||||
if (storedSignatureCount >= min_sigs) {
|
||||
send_raw_message(message, mode);
|
||||
if (message_data~load_uint(1)) {
|
||||
;; Code upgrade
|
||||
set_code(message_data~load_ref());
|
||||
} else {
|
||||
;; Simple message
|
||||
var (mode, message) = (message_data~load_uint(8), message_data~load_ref());
|
||||
send_raw_message(message, mode);
|
||||
}
|
||||
message_data.end_parse();
|
||||
messages~udict_delete?(256, hash);
|
||||
} else {
|
||||
;; modeMessage$_ mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
;; modeMessage$0 mode:uint8 body:^(Message X) = ModeMessage X;
|
||||
;; wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(ModeMessage X) = WrappedMessage X;
|
||||
;; multiSigWrapperStorage$_ count:(## 4) signatures:(HashmapE 4 Signature) message:(WrappedMessage X) = MultiSigWrapperStorage X;
|
||||
;;
|
||||
|
@ -152,24 +152,32 @@ PROGRAM{
|
||||
}>
|
||||
DROP
|
||||
s9 POP
|
||||
s0 s6 XCHG
|
||||
8 LDU
|
||||
LDREF
|
||||
ENDS
|
||||
s4 s3 PUSH2
|
||||
2OVER
|
||||
GEQ
|
||||
IF:<{
|
||||
s3 POP
|
||||
s4 POP
|
||||
s5 POP
|
||||
s6 POP
|
||||
s0 s3 XCHG
|
||||
SENDRAWMSG
|
||||
1 LDU
|
||||
SWAP
|
||||
IF:<{
|
||||
LDREF
|
||||
SWAP
|
||||
SETCODE
|
||||
}>ELSE<{
|
||||
8 LDU
|
||||
LDREF
|
||||
s0 s2 XCHG
|
||||
SENDRAWMSG
|
||||
}>
|
||||
ENDS
|
||||
ROT
|
||||
8 PUSHPOW2
|
||||
DICTUDEL
|
||||
DROP
|
||||
}>ELSE<{
|
||||
2DROP
|
||||
s6 POP
|
||||
4 PUSHINT
|
||||
NEWC
|
||||
s1 s0 s4 XCHG3
|
||||
@ -181,12 +189,14 @@ PROGRAM{
|
||||
s0 s1 s3 XCHG3
|
||||
8 PUSHPOW2
|
||||
DICTUSETB
|
||||
s1 s2 XCHG
|
||||
}>
|
||||
~collect_garbage CALLDICT
|
||||
s0 s3 XCHG
|
||||
INC
|
||||
NEWC
|
||||
32 STU
|
||||
s1 s2 XCHG
|
||||
4 STU
|
||||
STDICT
|
||||
STDICT
|
||||
|
@ -1,7 +1,7 @@
|
||||
"TonUtil.fif" include
|
||||
"lib.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <workchain-id> <wallet-name> <n> <k> <privkey1> [<pubkey2> ...] [<boc1> <boc2>]" cr cr
|
||||
{ ."usage: " @' $0 type ." <workchain-id> <wallet-name> <n> <k> <privkey1> [<pubkey2> ...]" 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
|
||||
@ -15,7 +15,6 @@ $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"
|
||||
@ -28,14 +27,11 @@ $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
|
||||
."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
|
||||
@ -60,28 +56,6 @@ rot // Put length on top for times
|
||||
swap
|
||||
} swap times drop const keys-dict
|
||||
|
||||
// Extract internal messages
|
||||
messages explode
|
||||
|
||||
dictnew swap
|
||||
{
|
||||
swap // Get n-th value
|
||||
inspect
|
||||
message-contents // Get v
|
||||
1 u@+ nip // Remove $0
|
||||
dict@+ swap // ...get signatures
|
||||
dup dictlen // ...and signature count
|
||||
<b swap 4 u, swap dict, swap s, // Finally rebuild cell
|
||||
|
||||
message-hash // Get x
|
||||
rot // Get dictionary s
|
||||
256 // Get n
|
||||
b>udict!
|
||||
not abort"Failure storing dictionary value!"
|
||||
|
||||
swap
|
||||
} swap times const messages-dict
|
||||
|
||||
// code
|
||||
"wallet-code.fif" include
|
||||
// data
|
||||
@ -90,7 +64,7 @@ dictnew swap
|
||||
<b 0 32 u,
|
||||
k 4 u,
|
||||
keys-dict dict,
|
||||
messages-dict dict,
|
||||
dictnew dict,
|
||||
b>
|
||||
// no libraries
|
||||
null
|
||||
|
Loading…
Reference in New Issue
Block a user