1
0
mirror of https://github.com/danog/toncontest.git synced 2024-12-03 09:57:57 +01:00
toncontest/wallet/wallet-code.fc

99 lines
2.8 KiB
Plaintext
Raw Normal View History

2019-10-03 21:54:25 +02:00
;; Multisig wallet smart contract
;; Cleanup expired partial orders (& get contract data)
;; needsWrite, seqno, keys, messages
(int, int, cell, cell) collect_garbage() {
var data = get_data().begin_parse();
var (seqno, keys, messages) = (data~load_int(32), data~load_dict(), data~load_dict());
data.end_parse();
var needsWrite = 0;
var hash = -1;
do {
(hash, var cs, var ok) = messages.idict_get_next?(256, hash);
if (ok) {
;; expiry <= now
if (cs~load_uint(32) <= now()) {
messages.idict_delete?(256, hash);
needsWrite = -1;
}
}
} until (~ ok);
return (needsWrite, seqno, keys, messages);
}
() 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_if(32, in_msg~load_uint(1) != 0);
;; Check if is hme_empty$0 or hme_root$1
;; If empty signature list
throw_if(33, in_msg.preload_uint(1) != 1);
var signatures = in_msg~load_dict();
var cs = in_msg;
;; wrappedMessage$_ expires_at:uint32 seqno:uint32 body:(Either (Message X) ^(Message X)) = WrappedMessage X;
var (expires_at, msg_seqno) = (cs~load_uint(32), cs~load_uint(32));
;; Message expired
throw_if(34, expires_at <= now());
var hash = slice_hash(in_msg);
var (needsWrite, stored_seqno, keys, messages) = collect_garbage();
var storedSignatures = new_dict();
;; If new message, increase seqno
if (stored_seqno == msg_seqno) {
stored_seqno += 1;
needsWrite = -1;
;; If old message
} else {
(var storedMessage, var ok) = messages.idict_get?(256, hash);
;; If old message and doesn't exist in db
ifnot (ok) {
;; Store new garbage-collected db
if (needsWrite) {
store_db(stored_seqno, keys, messages);
}
;; Throw
throw_if(35, -1);
}
;; Skip expiry
storedMessage.skip_bits(32);
;; No seqno: we can't regenerate the hash of a stored message.
;; That's a tradeoff to save grams on storage (and storing the seqno would be pointless anyway,
;; since all integrity checks were already made when the message was first stored)
;;
;; Load signatures
var storedSignatures = storedMessage.load_dict();
}
accept_message();
cs~touch();
while (cs.slice_refs()) {
var mode = cs~load_uint(8);
send_raw_message(cs~load_ref(), mode);
}
cs.end_parse();
;;set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell());
}
;; Get methods
int seqno() method_id {
return get_data().begin_parse().preload_uint(32);
}